1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
|
// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package net.sourceforge.jnlp.runtime;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import java.lang.reflect.InvocationTargetException;
import java.net.*;
import java.io.*;
import javax.swing.*;
import net.sourceforge.jnlp.*;
import net.sourceforge.jnlp.util.*;
/**
* The applet environment including stub, context, and frame. The
* default environment puts the applet in a non-resiable frame;
* this can be changed by obtaining the frame and setting it
* resizable.
*
* @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
* @version $Revision: 1.12 $
*/
public class AppletEnvironment implements AppletContext, AppletStub {
/** the JNLP file */
private JNLPFile file;
/** the applet instance */
private AppletInstance appletInstance;
/** the applet */
private Applet applet;
/** the parameters */
private Map parameters;
/** the applet container */
private Container cont;
/** weak references to the audio clips */
private WeakList weakClips = new WeakList();
/** whether the applet has been started / displayed */
private boolean appletStarted = false;
/** whether the applet has been destroyed */
private boolean destroyed = false;
/**
* Create a new applet environment for the applet specified by
* the JNLP file.
*/
public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance, Container cont) {
this.file = file;
this.appletInstance = appletInstance;
this.applet = appletInstance.getApplet();
parameters = file.getApplet().getParameters();
this.cont = cont;
}
/**
* Create a new applet environment for the applet specified by
* the JNLP file, in a new frame.
*/
public AppletEnvironment(JNLPFile file, final AppletInstance appletInstance) {
this(file, appletInstance, null);
Frame frame = new Frame(file.getApplet().getName() + " - Applet");
frame.setResizable(false);
appletInstance.addWindow(frame);
// may not need this once security manager can close windows
// that do not have app code on the stack
WindowListener closer = new WindowAdapter() {
public void windowClosing(WindowEvent event) {
appletInstance.destroy();
System.exit(0);
}
};
frame.addWindowListener(closer);
this.cont = frame;
}
/**
* Checks whether the applet has been destroyed, and throws an
* IllegalStateException if the applet has been destroyed of.
*
* @throws IllegalStateException
*/
private void checkDestroyed() {
if (destroyed)
throw new IllegalStateException("Illegal applet stub/context access: applet destroyed.");
}
/**
* Disposes the applet's resources and disables the applet
* environment from further use; after calling this method the
* applet stub and context methods throw IllegalStateExceptions.
*/
public void destroy() {
destroyed = true;
List clips = weakClips.hardList();
for (int i = 0; i < clips.size(); i++) {
((AppletAudioClip)clips.get(i)).dispose();
}
}
/**
* Returns the frame that contains the applet. Disposing this
* frame will destroy the applet.
*/
public Container getAppletFrame() {
// TODO: rename this method to getAppletContainer ?
return cont;
}
/**
* Initialize, start, and show the applet.
*/
public void startApplet() {
checkDestroyed();
if (appletStarted)
return;
appletStarted = true;
try {
AppletDesc appletDesc = file.getApplet();
if (cont instanceof AppletStub)
applet.setStub((AppletStub)cont);
else
applet.setStub(this);
cont.setLayout(new BorderLayout());
cont.add("Center", applet);
cont.validate();
// This is only needed if the applet is in its own frame.
if (cont instanceof Frame) {
Frame frame = (Frame) cont;
frame.pack(); // cause insets to be calculated
Insets insets = frame.getInsets();
frame.setSize(appletDesc.getWidth() + insets.left + insets.right,
appletDesc.getHeight() + insets.top + insets.bottom);
}
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// do first because some applets need to be displayed before
// starting (they use Component.getImage or something)
cont.setVisible(true);
applet.init();
applet.start();
cont.invalidate(); // this should force the applet to
cont.validate(); // the correct size and to repaint
cont.repaint();
}
});
} catch (InterruptedException ie) {
} catch (InvocationTargetException ite) {
}
}
catch (Exception ex) {
if (JNLPRuntime.isDebug())
ex.printStackTrace();
// should also kill the applet?
}
}
// applet context methods
/**
* Returns the applet if the applet's name is specified,
* otherwise return null.
*/
public Applet getApplet(String name) {
checkDestroyed();
if (name != null && name.equals(file.getApplet().getName()))
return applet;
else
return null;
}
/**
* Returns an enumeration that contains only the applet
* from the JNLP file.
*/
public Enumeration getApplets() {
checkDestroyed();
return Collections.enumeration( Arrays.asList(new Applet[] { applet }) );
}
/**
* Returns an audio clip.
*/
public AudioClip getAudioClip(URL location) {
checkDestroyed();
AppletAudioClip clip = new AppletAudioClip(location);
weakClips.add(clip);
weakClips.trimToSize();
return clip;
}
/**
* Return an image loaded from the specified location.
*/
public Image getImage(URL location) {
checkDestroyed();
//return Toolkit.getDefaultToolkit().createImage(location);
Image image = (new ImageIcon(location)).getImage();
return image;
}
/**
* Not implemented yet.
*/
public void showDocument(java.net.URL uRL) {
checkDestroyed();
}
/**
* Not implemented yet.
*/
public void showDocument(java.net.URL uRL, java.lang.String str) {
checkDestroyed();
}
/**
* Not implemented yet.
*/
public void showStatus(java.lang.String str) {
checkDestroyed();
}
/**
* Required for JRE1.4, but not implemented yet.
*/
public void setStream(String key, InputStream stream) {
checkDestroyed();
}
/**
* Required for JRE1.4, but not implemented yet.
*/
public InputStream getStream(String key) {
checkDestroyed();
return null;
}
/**
* Required for JRE1.4, but not implemented yet.
*/
public Iterator getStreamKeys() {
checkDestroyed();
return null;
}
// stub methods
public void appletResize(int width, int height) {
checkDestroyed();
if (cont instanceof Frame) {
Frame frame = (Frame) cont;
Insets insets = frame.getInsets();
frame.setSize(width + insets.left + insets.right,
height + insets.top + insets.bottom);
}
}
public AppletContext getAppletContext() {
checkDestroyed();
return this;
}
public URL getCodeBase() {
checkDestroyed();
return file.getCodeBase();
}
public URL getDocumentBase() {
checkDestroyed();
return file.getApplet().getDocumentBase();
}
// FIXME: Sun's applet code forces all parameters to lower case.
// Does Netx's JNLP code do the same, so we can remove the first lookup?
public String getParameter(String name) {
checkDestroyed();
String s = (String) parameters.get(name);
if (s != null)
return s;
return (String) parameters.get(name.toLowerCase());
}
public boolean isActive() {
checkDestroyed();
// it won't be started or stopped, so if it can call it's running
return true;
}
}
|