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