View Javadoc
1   /*
2    * $Id$
3    */
4   
5   /*
6    * Copyright (C) 2008 Ed Huott This program is free software; you can
7    * redistribute it and/or modify it under the terms of the GNU General Public
8    * License as published by the Free Software Foundation; either version 2 of the
9    * License, or (at your option) any later version. This program is distributed
10   * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
11   * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12   * See the GNU General Public License for more details. You should have received
13   * a copy of the GNU General Public License along with this program; if not,
14   * write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
15   * Boston, MA 02110-1301, USA.
16   */
17  
18  package wjhk.jupload2.context;
19  
20  import wjhk.jupload2.gui.JUploadPanel;
21  import wjhk.jupload2.policies.UploadPolicy;
22  
23  /**
24   * Separate thread spawned by the (signed) applet at initialization time so it
25   * will run in a context with the same privileges. Does nothing but wait to be
26   * notified of the presence of a command to be executed in the jsCommand String
27   * variable.
28   */
29  public class JavascriptHandler extends Thread {
30  
31      /**
32       * Command code, for upload.
33       */
34      public final static String COMMAND_START_UPLOAD = "startUpload";
35  
36      /**
37       * One return code for doCommand: indicates that the thread is busy, and can
38       * execute this command.
39       */
40      public final static String RETURN_BUSY = "busy";
41  
42      /**
43       * One return code for doCommand: indicates that the thread is busy, and can
44       * execute this command.
45       */
46      public final static String RETURN_STARTED = "started";
47  
48      /**
49       * Reference to the current upload policy.
50       */
51      private UploadPolicy uploadPolicy = null;
52  
53      /**
54       * Reference to the main panel of the applet.
55       */
56      private JUploadPanel jUploadPanel = null;
57  
58      /**
59       * The current command, or null if the thread is not currently running
60       * command.
61       */
62      private String jsCommand = null;
63  
64      /**
65       * Constructor for JavascriptHandler
66       * 
67       * @param uploadPolicy The current upload policy. Used for debug output.
68       * @param theJUploadPanel Whose methods will will be invoked in order to
69       *            execute the received commands
70       */
71      public JavascriptHandler(UploadPolicy uploadPolicy,
72              JUploadPanel theJUploadPanel) {
73          this.uploadPolicy = uploadPolicy;
74          this.jUploadPanel = theJUploadPanel;
75  
76          setName(this.getClass().getName());
77  
78          // This thread will close as soon as the applet is closed:
79          setDaemon(true);
80      }
81  
82      /**
83       * Method for passing a command (String) to be executed (asynchronously) by
84       * the run() method of this object's thread. Commands are accepted only if
85       * there is no previous command still executing. (Commands are not queued.)
86       * Return value indicates if command was successfully submitted.
87       * 
88       * @param command
89       * @return the command string argument on success, empty string on failure.
90       */
91      public synchronized String doCommand(String command) {
92          if (this.jsCommand != null) {
93              // The previous command not yet finished, we do nothing, and
94              // indicate it.
95              return RETURN_BUSY;
96          }
97  
98          this.jsCommand = command;
99          this.uploadPolicy.displayDebug(
100                 "JavascriptHandler - doCommand(): jsCommand is: ["
101                         + this.jsCommand + "]", 30);
102 
103         // send notify() to waiting thread so that command gets executed.
104         this.notify();
105 
106         // The job will go on.
107         return RETURN_STARTED;
108     }
109 
110     /**
111      * Synchronized method allows for safely accessing jsCommand string. The
112      * command is cleared before returning. This avoid conflicts, and let any
113      * other thread to set the next command, while managing this one.
114      * 
115      * @return Returns the current command.
116      */
117     synchronized String getAndClearCommand() {
118         this.uploadPolicy.displayDebug("getCommand(): jsCommand is: ["
119                 + this.jsCommand + "]", 30);
120         String curCommand = this.jsCommand;
121         clearCommand();
122         return curCommand;
123     }
124 
125     /**
126      * Synchronized method allows for safely clearing jsCommand string
127      */
128     public synchronized void clearCommand() {
129         this.jsCommand = null;
130         this.uploadPolicy.displayDebug("clearCommand(): jsCommand is: ["
131                 + this.jsCommand + "]", 30);
132     }
133 
134     /**
135      * Synchronized method to enable call to wait()
136      * 
137      * @throws InterruptedException
138      */
139     public synchronized void doWait() throws InterruptedException {
140         wait();
141     }
142 
143     /**
144      * Method to run when thread is started.
145      */
146     @Override
147     public void run() {
148         // Run in continuous loop waiting for commands to execute
149         while (true) {
150             try {
151                 // simply wait to be notified that a command is ready to run
152                 doWait();
153                 this.uploadPolicy.displayDebug("run(): Exited doWait()...", 50);
154 
155                 // handle new command
156                 String curCommand = getAndClearCommand();
157                 if (curCommand != null) {
158                     if (curCommand.equals(COMMAND_START_UPLOAD)) {
159                         // start the upload
160                         this.uploadPolicy.displayDebug(
161                                 "run(): Calling doStartUpload()", 50);
162                         this.jUploadPanel.doStartUpload();
163                     } else {
164                         this.uploadPolicy
165                                 .displayWarn("run(): unknown command in jsHandler ("
166                                         + curCommand + ")");
167                     }
168                 }
169             } catch (Exception e) {
170                 // We log everything that happens here.
171                 this.uploadPolicy.displayWarn("Exception: [" + e.getMessage()
172                         + "]");
173                 // But interruption is a valid exception: let's quit.
174                 if (e instanceof InterruptedException) {
175                     break;
176                 }
177             }
178         }
179     } // run()
180 
181 } // class JavascriptHandler