001: /*
002: * @(#)AppletPanel.java 1.69 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package sun.applet;
029:
030: import java.util.*;
031: import java.io.*;
032: import java.net.URL;
033: import java.net.MalformedURLException;
034: import java.net.SocketPermission;
035: import java.net.UnknownHostException;
036: import java.net.InetAddress;
037: import java.net.JarURLConnection;
038: import java.awt.*;
039: import java.awt.event.*;
040: import java.applet.*;
041: import java.awt.image.MemoryImageSource;
042: import java.awt.image.ColorModel;
043: import java.security.*;
044: import java.util.Collections;
045: import java.util.WeakHashMap;
046: import sun.misc.MessageUtils;
047: import sun.misc.Queue;
048:
049: /**
050: * Applet panel class. The panel manages and manipulates the
051: * applet as it is being loaded. It forks a separate thread in a new
052: * thread group to call the applet's init(), start(), stop(), and
053: * destroy() methods.
054: *
055: * @version 1.62, 08/19/02
056: * @author Arthur van Hoff
057: */
058: public abstract class AppletPanel extends Panel implements AppletStub,
059: Runnable {
060: /**
061: * The applet (if loaded).
062: */
063: Applet applet;
064: /**
065: * Applet will allow initialization. Should be
066: * set to false if loading a serialized applet
067: * that was pickled in the init=true state.
068: */
069: protected boolean doInit = true;
070: /**
071: * The classloader for the applet.
072: */
073: AppletClassLoader loader;
074: /* applet event ids */
075: public final static int APPLET_DISPOSE = 0;
076: public final static int APPLET_LOAD = 1;
077: public final static int APPLET_INIT = 2;
078: public final static int APPLET_START = 3;
079: public final static int APPLET_STOP = 4;
080: public final static int APPLET_DESTROY = 5;
081: public final static int APPLET_QUIT = 6;
082: public final static int APPLET_ERROR = 7;
083: /* send to the parent to force relayout */
084: public final static int APPLET_RESIZE = 51234;
085: /* sent to a (distant) parent to indicate that the applet is being
086: * loaded or as completed loading
087: */
088: public final static int APPLET_LOADING = 51235;
089: public final static int APPLET_LOADING_COMPLETED = 51236;
090: /**
091: * The current status. One of:
092: * APPLET_DISPOSE,
093: * APPLET_LOAD,
094: * APPLET_INIT,
095: * APPLET_START,
096: * APPLET_STOP,
097: * APPLET_DESTROY,
098: * APPLET_ERROR.
099: */
100: protected int status;
101: /**
102: * The thread for the applet.
103: */
104: Thread handler;
105: /**
106: * The initial applet size.
107: */
108: Dimension defaultAppletSize = new Dimension(10, 10);
109: /**
110: * The current applet size.
111: */
112: Dimension currentAppletSize = new Dimension(10, 10);
113: MessageUtils mu = new MessageUtils();
114: /**
115: * The thread to use during applet loading
116: */
117:
118: Thread loaderThread = null;
119: /**
120: * Flag to indicate that a loading has been cancelled
121: */
122: boolean loadAbortRequest = false;
123:
124: /* abstract classes */
125: abstract protected String getCode();
126:
127: abstract protected String getJarFiles();
128:
129: abstract protected String getSerializedObject();
130:
131: abstract public int getWidth();
132:
133: abstract public int getHeight();
134:
135: private static int threadGroupNumber = 0;
136:
137: /*
138: * Creates a thread to run the applet. This method is called
139: * the each time an applet is loaded and reloaded.
140: */
141: synchronized void createAppletThread() {
142: // Create a thread group for the applet, and start a new
143: // thread to load the applet.
144: String nm = "applet-" + getCode();
145: loader = getClassLoader(getCodeBase());
146: loader.grab(); // Keep this puppy around!
147: ThreadGroup appletGroup = loader.getThreadGroup();
148: handler = new Thread(appletGroup, this , "thread " + nm);
149: // set the context class loader for this thread
150: AccessController.doPrivileged(new PrivilegedAction() {
151: public Object run() {
152: handler.setContextClassLoader(loader);
153: return null;
154: }
155: });
156: handler.start();
157: }
158:
159: void joinAppletThread() throws InterruptedException {
160: if (handler != null) {
161: handler.join();
162: handler = null;
163: }
164: }
165:
166: void release() {
167: if (loader != null) {
168: loader.release();
169: loader = null;
170: }
171: }
172:
173: /**
174: * Construct an applet viewer and start the applet.
175: */
176: public void init() {
177: try {
178: // Get the width (if any)
179: defaultAppletSize.width = getWidth();
180: currentAppletSize.width = defaultAppletSize.width;
181: // Get the height (if any)
182: defaultAppletSize.height = getHeight();
183: currentAppletSize.height = defaultAppletSize.height;
184: } catch (NumberFormatException e) {
185: // Turn on the error flag and let TagAppletPanel
186: // do the right thing.
187: status = APPLET_ERROR;
188: showAppletStatus("badattribute.exception");
189: showAppletLog("badattribute.exception");
190: showAppletException(e);
191: }
192: setLayout(new BorderLayout());
193: createAppletThread();
194: }
195:
196: /**
197: * Minimum size
198: */
199: public Dimension getMinimumSize() {
200: return new Dimension(defaultAppletSize.width,
201: defaultAppletSize.height);
202: }
203:
204: /**
205: * Preferred size
206: */
207: public Dimension getPreferredSize() {
208: return new Dimension(currentAppletSize.width,
209: currentAppletSize.height);
210: }
211:
212: private AppletListener listeners;
213: /**
214: * AppletEvent Queue
215: */
216: private Queue queue = null;
217:
218: synchronized public void addAppletListener(AppletListener l) {
219: listeners = AppletEventMulticaster.add(listeners, l);
220: }
221:
222: synchronized public void removeAppletListener(AppletListener l) {
223: listeners = AppletEventMulticaster.remove(listeners, l);
224: }
225:
226: /**
227: * Dispatch event to the listeners..
228: */
229: public void dispatchAppletEvent(int id, Object argument) {
230: //System.out.println("SEND= " + id);
231: if (listeners != null) {
232: AppletEvent evt = new AppletEvent(this , id, argument);
233: listeners.appletStateChanged(evt);
234: }
235: }
236:
237: /**
238: * Send an event. Queue it for execution by the handler thread.
239: */
240: public void sendEvent(int id) {
241: synchronized (this ) {
242: if (queue == null) {
243: //System.out.println("SEND0= " + id);
244: queue = new Queue();
245: }
246: Integer eventId = new Integer(id);
247: queue.enqueue(eventId);
248: notifyAll();
249: }
250: if (id == APPLET_QUIT) {
251: try {
252: joinAppletThread(); // Let the applet event handler exit
253: } catch (InterruptedException e) {
254: }
255: // AppletClassLoader.release() must be called by a Thread
256: // not within the applet's ThreadGroup
257: if (loader == null)
258: loader = getClassLoader(getCodeBase());
259: release();
260: }
261: }
262:
263: /**
264: * Get an event from the queue.
265: */
266: synchronized AppletEvent getNextEvent() throws InterruptedException {
267: while (queue == null || queue.isEmpty()) {
268: wait();
269: }
270: Integer eventId = (Integer) queue.dequeue();
271: return new AppletEvent(this , eventId.intValue(), null);
272: }
273:
274: boolean emptyEventQueue() {
275: if ((queue == null) || (queue.isEmpty()))
276: return true;
277: else
278: return false;
279: }
280:
281: /**
282: * Execute applet events.
283: */
284: public void run() {
285: Thread curThread = Thread.currentThread();
286: if (curThread == loaderThread) {
287: // if we are in the loader thread, cause
288: // loading to occur. We may exit this with
289: // status being APPLET_DISPOSE, APPLET_ERROR,
290: // or APPLET_LOAD
291: runLoader();
292: return;
293: }
294: boolean disposed = false;
295: while (!disposed && !curThread.isInterrupted()) {
296: AppletEvent evt;
297: try {
298: evt = getNextEvent();
299: } catch (InterruptedException e) {
300: showAppletStatus("bail");
301: return;
302: }
303: //showAppletStatus("EVENT = " + evt.getID());
304: try {
305: switch (evt.getID()) {
306: case APPLET_LOAD:
307: if (!okToLoad()) {
308: break;
309: }
310: // This complexity allows laoding of applets to be
311: // interruptable. The actual thread loading runs
312: // in a separate thread, so it can be interrupted
313: // without harming the applet thread.
314: // So that we don't have to worry about
315: // concurrency issues, the main applet thread waits
316: // until the loader thread terminates.
317: // (one way or another).
318: if (loaderThread == null) {
319: // NOTE: do we want a name?
320: //System.out.println("------------------- loading applet");
321: setLoaderThread(new Thread(this ));
322: loaderThread.start();
323: // we get to go to sleep while this runs
324: loaderThread.join();
325: setLoaderThread(null);
326: } else {// NOTE: issue an error -- this case should never
327: // occur.
328: }
329: break;
330:
331: case APPLET_INIT:
332: if (status != APPLET_LOAD) {
333: showAppletStatus("notloaded");
334: break;
335: }
336: applet.resize(defaultAppletSize);
337: if (doInit) {
338: applet.init();
339: }
340: doInit = true; // allow restarts
341: validate();
342: status = APPLET_INIT;
343: showAppletStatus("inited");
344: break;
345:
346: case APPLET_START:
347: /* 4721061
348: * check if applet already started
349: */
350: if (status == APPLET_START) {
351: // Do not attempt to start again
352: break;
353: }
354: if (status != APPLET_INIT) {
355: showAppletStatus("notinited");
356: break;
357: }
358: applet.resize(currentAppletSize);
359: applet.setVisible(true);
360: status = APPLET_START;
361: applet.start();
362: validate();
363: /*
364: * Fix for BugTraq ID 4041703.
365: * Set the default focus for an applet.
366: */
367: setDefaultFocus();
368: showAppletStatus("started");
369: break;
370:
371: case APPLET_STOP:
372: if (status != APPLET_START) {
373: showAppletStatus("notstarted");
374: break;
375: }
376: status = APPLET_INIT;
377: applet.setVisible(false);
378: applet.stop();
379: showAppletStatus("stopped");
380: break;
381:
382: case APPLET_DESTROY:
383: if (status != APPLET_INIT) {
384: showAppletStatus("notstopped");
385: break;
386: }
387: status = APPLET_LOAD;
388: applet.destroy();
389: showAppletStatus("destroyed");
390: break;
391:
392: case APPLET_DISPOSE:
393: if (status != APPLET_LOAD) {
394: showAppletStatus("notdestroyed");
395: break;
396: }
397: status = APPLET_DISPOSE;
398: remove(applet);
399: applet = null;
400: showAppletStatus("disposed");
401: disposed = true;
402: break;
403:
404: case APPLET_QUIT:
405: return;
406: }
407: } catch (Exception e) {
408: if (e.getMessage() != null) {
409: showAppletStatus("exception2", e.getClass()
410: .getName(), e.getMessage());
411: } else {
412: showAppletStatus("exception", e.getClass()
413: .getName());
414: }
415: showAppletException(e);
416: } catch (ThreadDeath e) {
417: showAppletStatus("death");
418: return;
419: } catch (Error e) {
420: if (e.getMessage() != null) {
421: showAppletStatus("error2", e.getClass().getName(),
422: e.getMessage());
423: } else {
424: showAppletStatus("error", e.getClass().getName());
425: }
426: showAppletException(e);
427: }
428: clearLoadAbortRequest();
429: }
430: }
431:
432: /*
433: * Fix for BugTraq ID 4041703.
434: * Set the focus to a reasonable default for an Applet.
435: */
436: private void setDefaultFocus() {
437: if (getParent() instanceof Window) {
438: Window window = (Window) getParent();
439: // Don't proceed if the toplevel frame is inactive.
440: if (window.getFocusOwner() != null) {
441: doSetDefaultFocus();
442: }
443: }
444: }
445:
446: private void doSetDefaultFocus() {
447: if (applet == null) {
448: return;
449: }
450: // Find first focus-traversable component.
451: if (activateFocus((Container) applet)) {
452: return;
453: }
454: // No focus-traversable component was found,
455: // so set focus to the first leaf node.
456: Component c = (Component) applet;
457: while (c instanceof Container
458: && ((Container) c).getComponentCount() > 0) {
459: Component child = ((Container) c).getComponent(0);
460: if (child.isVisible() && child.isEnabled()) {
461: c = child;
462: } else {
463: break;
464: }
465: }
466: c.requestFocus();
467: }
468:
469: private boolean activateFocus(Container cont) {
470: int ncomponents = cont.getComponentCount();
471: for (int i = 0; i < ncomponents; i++) {
472: Component c = cont.getComponent(i);
473: if (c.isVisible() && c.isEnabled()
474: && c.isFocusTraversable()) {
475: c.requestFocus();
476: return true;
477: }
478: if (c instanceof Container && c.isVisible()
479: && c.isEnabled()) {
480: if (activateFocus((Container) c)) {
481: return true;
482: }
483: }
484: }
485: return false;
486: }
487:
488: /* End of fix for BugTraq ID 4041703. */
489:
490: /**
491: * Load the applet into memory.
492: * Runs in a seperate (and interruptible) thread from the rest of the
493: * applet event processing so that it can be gracefully interrupted from
494: * things like HotJava.
495: */
496: private void runLoader() {
497: if (status != APPLET_DISPOSE) {
498: showAppletStatus("notdisposed");
499: return;
500: }
501: dispatchAppletEvent(APPLET_LOADING, null);
502: // TODO -- might be cool to visually indicate loading here --
503: // maybe do animation?
504: status = APPLET_LOAD;
505: // Create a class loader
506: loader = getClassLoader(getCodeBase());
507: // Load the archives if present.
508: // NOTE - this probably should be done in a separate thread,
509: // or at least the additional archives (epll).
510:
511: String code = getCode();
512: try {
513: loadJarFiles(loader);
514: applet = createApplet(loader);
515: } catch (ClassNotFoundException e) {
516: status = APPLET_ERROR;
517: showAppletStatus("notfound", code);
518: showAppletLog("notfound", code);
519: showAppletException(e);
520: return;
521: } catch (InstantiationException e) {
522: status = APPLET_ERROR;
523: showAppletStatus("nocreate", code);
524: showAppletLog("nocreate", code);
525: showAppletException(e);
526: return;
527: } catch (IllegalAccessException e) {
528: status = APPLET_ERROR;
529: showAppletStatus("noconstruct", code);
530: showAppletLog("noconstruct", code);
531: showAppletException(e);
532: // sbb -- I added a return here
533: return;
534: } catch (Exception e) {
535: status = APPLET_ERROR;
536: showAppletStatus("exception", e.getMessage());
537: showAppletException(e);
538: return;
539: } catch (ThreadDeath e) {
540: status = APPLET_ERROR;
541: showAppletStatus("death");
542: return;
543: } catch (Error e) {
544: status = APPLET_ERROR;
545: showAppletStatus("error", e.getMessage());
546: showAppletException(e);
547: return;
548: } finally {
549: // notify that loading is no longer going on
550: dispatchAppletEvent(APPLET_LOADING_COMPLETED, null);
551: }
552: // Stick it in the frame
553: applet.setStub(this );
554: applet.setVisible(false);
555: add("Center", applet);
556: showAppletStatus("loaded");
557: validate();
558: }
559:
560: protected Applet createApplet(final AppletClassLoader loader)
561: throws ClassNotFoundException, IllegalAccessException,
562: IOException, InstantiationException, InterruptedException {
563: final String serName = getSerializedObject();
564: String code = getCode();
565: if (code != null && serName != null) {
566: System.err.println(amh.getMessage("runloader.err"));
567: return null;
568: }
569: if (code == null && serName == null) {
570: String msg = "nocode";
571: status = APPLET_ERROR;
572: showAppletStatus(msg);
573: showAppletLog(msg);
574: repaint();
575: }
576: if (code != null) {
577: applet = (Applet) loader.loadCode(code).newInstance();
578: doInit = true;
579: } else {
580: // serName is not null;
581: InputStream is = (InputStream) java.security.AccessController
582: .doPrivileged(new java.security.PrivilegedAction() {
583: public Object run() {
584: return loader.getResourceAsStream(serName);
585: }
586: });
587: ObjectInputStream ois = new AppletObjectInputStream(is,
588: loader);
589: Object serObject = ois.readObject();
590: applet = (Applet) serObject;
591: doInit = false; // skip over the first init
592: }
593: if (Thread.interrupted()) {
594: try {
595: status = APPLET_DISPOSE; // APPLET_ERROR?
596: applet = null;
597: // FIXME: This may not be exactly the right thing: the
598: // status is set by the stop button and not necessarily
599: // here.
600: showAppletStatus("death");
601: } finally {
602: Thread.currentThread().interrupt(); // resignal interrupt
603: }
604: return null;
605: }
606: return applet;
607: }
608:
609: protected void loadJarFiles(AppletClassLoader loader)
610: throws IOException, InterruptedException {
611: // Load the archives if present.
612: // TODO - this probably should be done in a separate thread,
613: // or at least the additional archives (epll).
614: String jarFiles = getJarFiles();
615: if (jarFiles != null) {
616: StringTokenizer st = new StringTokenizer(jarFiles, ",",
617: false);
618: while (st.hasMoreTokens()) {
619: String tok = st.nextToken().trim();
620: try {
621: loader.addJar(tok);
622: } catch (IllegalArgumentException e) {
623: // bad archive name
624: continue;
625: }
626: }
627: }
628: }
629:
630: /**
631: * Request that the loading of the applet be stopped.
632: */
633: protected synchronized void stopLoading() {
634: if (loaderThread != null) {
635: //System.out.println("Interrupting applet loader thread: " + loaderThread);
636: loaderThread.interrupt();
637: } else {
638: setLoadAbortRequest();
639: }
640: }
641:
642: protected synchronized boolean okToLoad() {
643: return !loadAbortRequest;
644: }
645:
646: protected synchronized void clearLoadAbortRequest() {
647: loadAbortRequest = false;
648: }
649:
650: protected synchronized void setLoadAbortRequest() {
651: loadAbortRequest = true;
652: }
653:
654: private synchronized void setLoaderThread(Thread loaderThread) {
655: this .loaderThread = loaderThread;
656: }
657:
658: /**
659: * Return true when the applet has been started.
660: */
661: public boolean isActive() {
662: return status == APPLET_START;
663: }
664:
665: /**
666: * Is called when the applet wants to be resized.
667: */
668: public void appletResize(int width, int height) {
669: currentAppletSize.width = width;
670: currentAppletSize.height = height;
671: Dimension currentSize = new Dimension(currentAppletSize.width,
672: currentAppletSize.height);
673: dispatchAppletEvent(APPLET_RESIZE, currentSize);
674: }
675:
676: public void setBounds(int x, int y, int width, int height) {
677: super .setBounds(x, y, width, height);
678: currentAppletSize.width = width;
679: currentAppletSize.height = height;
680: }
681:
682: public Applet getApplet() {
683: return applet;
684: }
685:
686: /**
687: * Status line. Called by the AppletPanel to provide
688: * feedback on the Applet's state.
689: */
690: protected void showAppletStatus(String status) {
691: getAppletContext().showStatus(amh.getMessage(status));
692: }
693:
694: protected void showAppletStatus(String status, Object arg) {
695: getAppletContext().showStatus(amh.getMessage(status, arg));
696: }
697:
698: protected void showAppletStatus(String status, Object arg1,
699: Object arg2) {
700: getAppletContext().showStatus(
701: amh.getMessage(status, arg1, arg2));
702: }
703:
704: /**
705: * Called by the AppletPanel to print to the log.
706: */
707: protected void showAppletLog(String msg) {
708: System.out.println(amh.getMessage(msg));
709: }
710:
711: protected void showAppletLog(String msg, Object arg) {
712: System.out.println(amh.getMessage(msg, arg));
713: }
714:
715: /**
716: * Called by the AppletPanel to provide
717: * feedback when an exception has happened.
718: */
719: protected void showAppletException(Throwable t) {
720: t.printStackTrace();
721: repaint();
722: }
723:
724: /**
725: * The class loaders
726: */
727: private static Hashtable classloaders = new Hashtable();
728:
729: /**
730: * Flush a class loader.
731: */
732: public static synchronized void flushClassLoader(URL codebase) {
733: classloaders.remove(codebase);
734: }
735:
736: /**
737: * Flush all class loaders.
738: */
739: public static synchronized void flushClassLoaders() {
740: classloaders = new Hashtable();
741: }
742:
743: /**
744: * This method actually creates an AppletClassLoader.
745: *
746: * It can be override by subclasses (such as the Plug-in)
747: * to provide different classloaders.
748: */
749: protected AppletClassLoader createClassLoader(final URL codebase) {
750: return new AppletClassLoader(codebase);
751: }
752:
753: /**
754: * Get a class loader. Create in a restricted context
755: */
756: synchronized AppletClassLoader getClassLoader(final URL codebase) {
757: AppletClassLoader c = (AppletClassLoader) classloaders
758: .get(codebase);
759: if (c == null) {
760: AccessControlContext acc = getAccessControlContext(codebase);
761: c = (AppletClassLoader) AccessController.doPrivileged(
762: new PrivilegedAction() {
763: public Object run() {
764: AppletClassLoader ac = createClassLoader(codebase);
765: /* Should the creation of the classloader be
766: * within the class synchronized block? Since
767: * this class is used by the plugin, take care
768: * to avoid deadlocks, or specialize
769: * AppletPanel within the plugin. It may take
770: * an arbitrary amount of time to create a
771: * class loader (involving getting Jar files
772: * etc.) and may block unrelated applets from
773: * finishing createAppletThread (due to the
774: * class synchronization). If
775: * createAppletThread does not finish quickly,
776: * the applet cannot process other messages,
777: * particularly messages such as destroy
778: * (which timeout when called from the browser).
779: */
780: synchronized (getClass()) {
781: AppletClassLoader res = (AppletClassLoader) classloaders
782: .get(codebase);
783: if (res == null) {
784: classloaders.put(codebase, ac);
785: return ac;
786: } else {
787: return res;
788: }
789: }
790: }
791: }, acc);
792: }
793: return c;
794: }
795:
796: /**
797: * get the context for the AppletClassLoader we are creating.
798: * the context is granted permission to create the class loader,
799: * connnect to the codebase, and whatever else the policy grants
800: * to all codebases.
801: */
802: private AccessControlContext getAccessControlContext(
803: final URL codebase) {
804: PermissionCollection perms = (PermissionCollection) AccessController
805: .doPrivileged(new PrivilegedAction() {
806: public Object run() {
807: Policy p = java.security.Policy.getPolicy();
808: if (p != null) {
809: return p.getPermissions(new CodeSource(
810: null, null));
811: } else {
812: return null;
813: }
814: }
815: });
816: if (perms == null)
817: perms = new Permissions();
818: //NOTE: this is needed to be able to create the classloader itself!
819:
820: perms.add(new RuntimePermission("createClassLoader"));
821: Permission p;
822: java.net.URLConnection urlConnection = null;
823: try {
824: urlConnection = codebase.openConnection();
825: p = urlConnection.getPermission();
826: } catch (java.io.IOException ioe) {
827: p = null;
828: }
829:
830: if (p != null)
831: perms.add(p);
832:
833: if (p instanceof FilePermission) {
834: String path = p.getName();
835: int endIndex = path.lastIndexOf(File.separatorChar);
836:
837: if (endIndex != -1) {
838: path = path.substring(0, endIndex + 1);
839: if (path.endsWith(File.separator)) {
840: path += "-";
841: }
842: perms.add(new FilePermission(path, "read"));
843: }
844: } else {
845: URL locUrl = codebase;
846: if (urlConnection instanceof JarURLConnection) {
847: locUrl = ((JarURLConnection) urlConnection)
848: .getJarFileURL();
849: }
850: String host = locUrl.getHost();
851: if (host != null && (host.length() > 0))
852: perms
853: .add(new SocketPermission(host,
854: "connect, accept"));
855: }
856: ProtectionDomain domain = new ProtectionDomain(new CodeSource(
857: codebase, null), perms);
858: AccessControlContext acc = new AccessControlContext(
859: new ProtectionDomain[] { domain });
860: return acc;
861: }
862:
863: public Thread getAppletHandlerThread() {
864: return handler;
865: }
866:
867: public int getAppletWidth() {
868: return currentAppletSize.width;
869: }
870:
871: public int getAppletHeight() {
872: return currentAppletSize.height;
873: }
874:
875: private static AppletMessageHandler amh = new AppletMessageHandler(
876: "appletpanel");
877: }
|