77
78 @Override
79 public void windowClosing(WindowEvent evt) {
80 dispose();
81 }
82 };
83
84 addWindowListener(windowEventListener);
85 }
86 private static AppletMessageHandler amh = new AppletMessageHandler("textframe");
87
88 }
89
90 /**
91 * Lets us construct one using unix-style one shot behaviors.
92 */
93 final class StdAppletViewerFactory implements AppletViewerFactory {
94
95 @Override
96 public AppletViewer createAppletViewer(int x, int y,
97 URL doc, Hashtable atts) {
98 return new AppletViewer(x, y, doc, atts, System.out, this);
99 }
100
101 @Override
102 public MenuBar getBaseMenuBar() {
103 return new MenuBar();
104 }
105
106 @Override
107 public boolean isStandalone() {
108 return true;
109 }
110 }
111
112 /**
113 * The applet viewer makes it possible to run a Java applet without using a browser.
114 * For details on the syntax that <B>appletviewer</B> supports, see
115 * <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.
116 * (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
117 * once the JDK docs have been installed.)
139 */
140
141 PrintStream statusMsgStream;
142
143 /**
144 * For cloning
145 */
146 AppletViewerFactory factory;
147
148
149 private final class UserActionListener implements ActionListener {
150 @Override
151 public void actionPerformed(ActionEvent evt) {
152 processUserAction(evt);
153 }
154 }
155
156 /**
157 * Create the applet viewer.
158 */
159 public AppletViewer(int x, int y, URL doc, Hashtable atts,
160 PrintStream statusMsgStream, AppletViewerFactory factory) {
161 this.factory = factory;
162 this.statusMsgStream = statusMsgStream;
163 setTitle(amh.getMessage("tool.title", atts.get("code")));
164
165 MenuBar mb = factory.getBaseMenuBar();
166
167 Menu m = new Menu(amh.getMessage("menu.applet"));
168
169 addMenuItem(m, "menuitem.restart");
170 addMenuItem(m, "menuitem.reload");
171 addMenuItem(m, "menuitem.stop");
172 addMenuItem(m, "menuitem.save");
173 addMenuItem(m, "menuitem.start");
174 addMenuItem(m, "menuitem.clone");
175 m.add(new MenuItem("-"));
176 addMenuItem(m, "menuitem.tag");
177 addMenuItem(m, "menuitem.info");
178 addMenuItem(m, "menuitem.edit").disable();
179 addMenuItem(m, "menuitem.encoding");
333 while (!panel.emptyEventQueue()) ;
334 appletSystemExit();
335 }
336 }
337
338 /**
339 * Split a string based on the presence of a specified separator. Returns
340 * an array of arbitrary length. The end of each element in the array is
341 * indicated by the separator of the end of the string. If there is a
342 * separator immediately before the end of the string, the final element
343 * will be empty. None of the strings will contain the separator. Useful
344 * when separating strings such as "foo/bar/bas" using separator "/".
345 *
346 * @param sep The separator.
347 * @param s The string to split.
348 * @return An array of strings. Each string in the array is determined
349 * by the location of the provided sep in the original string,
350 * s. Whitespace not stripped.
351 */
352 private String [] splitSeparator(String sep, String s) {
353 Vector v = new Vector();
354 int tokenStart = 0;
355 int tokenEnd = 0;
356
357 while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {
358 v.addElement(s.substring(tokenStart, tokenEnd));
359 tokenStart = tokenEnd+1;
360 }
361 // Add the final element.
362 v.addElement(s.substring(tokenStart));
363
364 String [] retVal = new String[v.size()];
365 v.copyInto(retVal);
366 return retVal;
367 }
368
369 /*
370 * Methods for java.applet.AppletContext
371 */
372
373 private static Map audioClips = new HashMap();
374
375 /**
376 * Get an audio clip.
377 */
378 @Override
379 public AudioClip getAudioClip(URL url) {
380 checkConnect(url);
381 synchronized (audioClips) {
382 AudioClip clip = (AudioClip)audioClips.get(url);
383 if (clip == null) {
384 audioClips.put(url, clip = new AppletAudioClip(url));
385 }
386 return clip;
387 }
388 }
389
390 private static Map imageRefs = new HashMap();
391
392 /**
393 * Get an image.
394 */
395 @Override
396 public Image getImage(URL url) {
397 return getCachedImage(url);
398 }
399
400 /**
401 * Get an image.
402 */
403 static Image getCachedImage(URL url) {
404 // System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
405 synchronized (imageRefs) {
406 AppletImageRef ref = (AppletImageRef)imageRefs.get(url);
407 if (ref == null) {
408 ref = new AppletImageRef(url);
409 imageRefs.put(url, ref);
410 }
411 return ref.get();
412 }
413 }
414
415 /**
416 * Flush the image cache.
417 */
418 static void flushImageCache() {
419 imageRefs.clear();
420 }
421
422 static Vector appletPanels = new Vector();
423
424 /**
425 * Get an applet by name.
426 */
427 @Override
428 public Applet getApplet(String name) {
429 AppletSecurity security = (AppletSecurity)System.getSecurityManager();
430 name = name.toLowerCase();
431 SocketPermission panelSp =
432 new SocketPermission(panel.getCodeBase().getHost(), "connect");
433 for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
434 AppletPanel p = (AppletPanel)e.nextElement();
435 String param = p.getParameter("name");
436 if (param != null) {
437 param = param.toLowerCase();
438 }
439 if (name.equals(param) &&
440 p.getDocumentBase().equals(panel.getDocumentBase())) {
441
442 SocketPermission sp =
443 new SocketPermission(p.getCodeBase().getHost(), "connect");
444
445 if (panelSp.implies(sp)) {
446 return p.applet;
447 }
448 }
449 }
450 return null;
451 }
452
453 /**
454 * Return an enumeration of all the accessible
455 * applets on this page.
456 */
457 @Override
458 public Enumeration getApplets() {
459 AppletSecurity security = (AppletSecurity)System.getSecurityManager();
460 Vector v = new Vector();
461 SocketPermission panelSp =
462 new SocketPermission(panel.getCodeBase().getHost(), "connect");
463
464 for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
465 AppletPanel p = (AppletPanel)e.nextElement();
466 if (p.getDocumentBase().equals(panel.getDocumentBase())) {
467
468 SocketPermission sp =
469 new SocketPermission(p.getCodeBase().getHost(), "connect");
470 if (panelSp.implies(sp)) {
471 v.addElement(p.applet);
472 }
473 }
474 }
475 return v.elements();
476 }
477
478 /**
479 * Ignore.
480 */
481 @Override
482 public void showDocument(URL url) {
483 }
484
485 /**
492 /**
493 * Show status.
494 */
495 @Override
496 public void showStatus(String status) {
497 label.setText(status);
498 }
499
500 @Override
501 public void setStream(String key, InputStream stream)throws IOException{
502 // We do nothing.
503 }
504
505 @Override
506 public InputStream getStream(String key){
507 // We do nothing.
508 return null;
509 }
510
511 @Override
512 public Iterator getStreamKeys(){
513 // We do nothing.
514 return null;
515 }
516
517 /**
518 * System parameters.
519 */
520 static Hashtable systemParam = new Hashtable();
521
522 static {
523 systemParam.put("codebase", "codebase");
524 systemParam.put("code", "code");
525 systemParam.put("alt", "alt");
526 systemParam.put("width", "width");
527 systemParam.put("height", "height");
528 systemParam.put("align", "align");
529 systemParam.put("vspace", "vspace");
530 systemParam.put("hspace", "hspace");
531 }
532
533 /**
534 * Print the HTML tag.
535 */
536 public static void printTag(PrintStream out, Hashtable atts) {
537 out.print("<applet");
538
539 String v = (String)atts.get("codebase");
540 if (v != null) {
541 out.print(" codebase=\"" + v + "\"");
542 }
543
544 v = (String)atts.get("code");
545 if (v == null) {
546 v = "applet.class";
547 }
548 out.print(" code=\"" + v + "\"");
549 v = (String)atts.get("width");
550 if (v == null) {
551 v = "150";
552 }
553 out.print(" width=" + v);
554
555 v = (String)atts.get("height");
556 if (v == null) {
557 v = "100";
558 }
559 out.print(" height=" + v);
560
561 v = (String)atts.get("name");
562 if (v != null) {
563 out.print(" name=\"" + v + "\"");
564 }
565 out.println(">");
566
567 // A very slow sorting algorithm
568 int len = atts.size();
569 String params[] = new String[len];
570 len = 0;
571 for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {
572 String param = (String)e.nextElement();
573 int i = 0;
574 for (; i < len ; i++) {
575 if (params[i].compareTo(param) >= 0) {
576 break;
577 }
578 }
579 System.arraycopy(params, i, params, i + 1, len - i);
580 params[i] = param;
581 len++;
582 }
583
584 for (int i = 0 ; i < len ; i++) {
585 String param = params[i];
586 if (systemParam.get(param) == null) {
587 out.println("<param name=" + param +
588 " value=\"" + atts.get(param) + "\">");
589 }
590 }
591 out.println("</applet>");
592 }
632 * Make sure we don't have two threads running through the event queue
633 * at the same time.
634 */
635 try {
636 panel.joinAppletThread();
637 panel.release();
638 } catch (InterruptedException e) {
639 return; // abort the reload
640 }
641
642 panel.createAppletThread();
643 panel.sendEvent(AppletPanel.APPLET_LOAD);
644 panel.sendEvent(AppletPanel.APPLET_INIT);
645 panel.sendEvent(AppletPanel.APPLET_START);
646 }
647
648 /**
649 * Save the applet to a well known file (for now) as a serialized object
650 */
651 void appletSave() {
652 AccessController.doPrivileged(new PrivilegedAction() {
653
654 @Override
655 public Object run() {
656 // XXX: this privileged block should be made smaller
657 // by initializing a private static variable with "user.dir"
658
659 // Applet needs to be stopped for serialization to succeed.
660 // Since panel.sendEvent only queues the event, there is a
661 // chance that the event will not be processed before
662 // serialization begins. However, by sending the event before
663 // FileDialog is created, enough time is given such that this
664 // situation is unlikely to ever occur.
665
666 panel.sendEvent(AppletPanel.APPLET_STOP);
667 FileDialog fd = new FileDialog(AppletViewer.this,
668 amh.getMessage("appletsave.filedialogtitle"),
669 FileDialog.SAVE);
670 // needed for a bug under Solaris...
671 fd.setDirectory(System.getProperty("user.dir"));
672 fd.setFile(defaultSaveFile);
685 ObjectOutputStream os = new ObjectOutputStream(bos)) {
686
687 showStatus(amh.getMessage("appletsave.err1", panel.applet.toString(), file.toString()));
688 os.writeObject(panel.applet);
689 } catch (IOException ex) {
690 System.err.println(amh.getMessage("appletsave.err2", ex));
691 } finally {
692 panel.sendEvent(AppletPanel.APPLET_START);
693 }
694 return null;
695 }
696 });
697 }
698
699 /**
700 * Clone the viewer and the applet.
701 */
702 void appletClone() {
703 Point p = location();
704 updateAtts();
705 factory.createAppletViewer(p.x + XDELTA, p.y + YDELTA,
706 panel.documentURL, (Hashtable)panel.atts.clone());
707 }
708
709 /**
710 * Show the applet tag.
711 */
712 void appletTag() {
713 ByteArrayOutputStream out = new ByteArrayOutputStream();
714 updateAtts();
715 printTag(new PrintStream(out), panel.atts);
716 showStatus(amh.getMessage("applettag"));
717
718 Point p = location();
719 new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("applettag.textframe"), out.toString());
720 }
721
722 /**
723 * Show the applet info.
724 */
725 void appletInfo() {
726 String str = panel.applet.getAppletInfo();
867 if (factory.isStandalone())
868 System.exit(0);
869 }
870
871 /**
872 * Quit all viewers.
873 * Shutdown all viewers properly then
874 * exit from the program (if not stand alone)
875 */
876 protected void appletQuit()
877 {
878 // The caller thread is event dispatch thread, so
879 // spawn a new thread to avoid blocking the event queue
880 // when calling appletShutdown.
881 //
882 new Thread(new Runnable()
883 {
884 @Override
885 public void run()
886 {
887 for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {
888 AppletPanel p = (AppletPanel)e.nextElement();
889 appletShutdown(p);
890 }
891 appletSystemExit();
892 }
893 }).start();
894 }
895
896 /**
897 * Handle events.
898 */
899 public void processUserAction(ActionEvent evt) {
900
901 String label = ((MenuItem)evt.getSource()).getLabel();
902
903 if (amh.getMessage("menuitem.restart").equals(label)) {
904 appletRestart();
905 return;
906 }
907
908 if (amh.getMessage("menuitem.reload").equals(label)) {
999 /**
1000 * Scan identifier
1001 */
1002 public static String scanIdentifier(Reader in) throws IOException {
1003 StringBuilder sb = new StringBuilder();
1004 while (true) {
1005 if (((c >= 'a') && (c <= 'z')) ||
1006 ((c >= 'A') && (c <= 'Z')) ||
1007 ((c >= '0') && (c <= '9')) || (c == '_')) {
1008 sb.append((char) c);
1009 c = in.read();
1010 } else {
1011 return sb.toString();
1012 }
1013 }
1014 }
1015
1016 /**
1017 * Scan tag
1018 */
1019 public static Hashtable scanTag(Reader in) throws IOException {
1020 Hashtable atts = new Hashtable();
1021 skipSpace(in);
1022 while (c >= 0 && c != '>') {
1023 String att = scanIdentifier(in);
1024 String val = "";
1025 skipSpace(in);
1026 if (c == '=') {
1027 int quote = -1;
1028 c = in.read();
1029 skipSpace(in);
1030 if ((c == '\'') || (c == '\"')) {
1031 quote = c;
1032 c = in.read();
1033 }
1034 StringBuilder sb = new StringBuilder();
1035 while ((c > 0) &&
1036 (((quote < 0) && (c != ' ') && (c != '\t') &&
1037 (c != '\n') && (c != '\r') && (c != '>'))
1038 || ((quote >= 0) && (c != quote)))) {
1039 sb.append((char) c);
1040 c = in.read();
1105 String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
1106 String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
1107 String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
1108 String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
1109 String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
1110 String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
1111 String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
1112 String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
1113 String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
1114 String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
1115 String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
1116
1117 java.net.URLConnection conn = url.openConnection();
1118 Reader in = makeReader(conn.getInputStream());
1119 /* The original URL may have been redirected - this
1120 * sets it to whatever URL/codebase we ended up getting
1121 */
1122 url = conn.getURL();
1123
1124 int ydisp = 1;
1125 Hashtable atts = null;
1126
1127 while(true) {
1128 c = in.read();
1129 if (c == -1)
1130 break;
1131
1132 if (c == '<') {
1133 c = in.read();
1134 if (c == '/') {
1135 c = in.read();
1136 String nm = scanIdentifier(in);
1137 if (nm.equalsIgnoreCase("applet") ||
1138 nm.equalsIgnoreCase("object") ||
1139 nm.equalsIgnoreCase("embed")) {
1140
1141 // We can't test for a code tag until </OBJECT>
1142 // because it is a parameter, not an attribute.
1143 if(isObjectTag) {
1144 if (atts.get("code") == null && atts.get("object") == null) {
1145 statusMsgStream.println(objectRequiresCodeWarning);
1155 factory.createAppletViewer(x, y, url, atts);
1156 x += XDELTA;
1157 y += YDELTA;
1158 // make sure we don't go too far!
1159 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
1160 if ((x > d.width - 300) || (y > d.height - 300)) {
1161 x = 0;
1162 y = 2 * ydisp * YDELTA;
1163 ydisp++;
1164 }
1165 }
1166 atts = null;
1167 isAppletTag = false;
1168 isObjectTag = false;
1169 isEmbedTag = false;
1170 }
1171 }
1172 else {
1173 String nm = scanIdentifier(in);
1174 if (nm.equalsIgnoreCase("param")) {
1175 Hashtable t = scanTag(in);
1176 String att = (String)t.get("name");
1177 if (att == null) {
1178 statusMsgStream.println(requiresNameWarning);
1179 } else {
1180 String val = (String)t.get("value");
1181 if (val == null) {
1182 statusMsgStream.println(requiresNameWarning);
1183 } else if (atts != null) {
1184 atts.put(att.toLowerCase(), val);
1185 } else {
1186 statusMsgStream.println(paramOutsideWarning);
1187 }
1188 }
1189 }
1190 else if (nm.equalsIgnoreCase("applet")) {
1191 isAppletTag = true;
1192 atts = scanTag(in);
1193 if (atts.get("code") == null && atts.get("object") == null) {
1194 statusMsgStream.println(appletRequiresCodeWarning);
1195 atts = null;
1196 } else if (atts.get("width") == null) {
1197 statusMsgStream.println(appletRequiresWidthWarning);
1198 atts = null;
1199 } else if (atts.get("height") == null) {
1200 statusMsgStream.println(appletRequiresHeightWarning);
1218 atts = null;
1219 }
1220 }
1221 else if (nm.equalsIgnoreCase("embed")) {
1222 isEmbedTag = true;
1223 atts = scanTag(in);
1224
1225 if (atts.get("code") == null && atts.get("object") == null) {
1226 statusMsgStream.println(embedRequiresCodeWarning);
1227 atts = null;
1228 } else if (atts.get("width") == null) {
1229 statusMsgStream.println(embedRequiresWidthWarning);
1230 atts = null;
1231 } else if (atts.get("height") == null) {
1232 statusMsgStream.println(embedRequiresHeightWarning);
1233 atts = null;
1234 }
1235 }
1236 else if (nm.equalsIgnoreCase("app")) {
1237 statusMsgStream.println(appNotLongerSupportedWarning);
1238 Hashtable atts2 = scanTag(in);
1239 nm = (String)atts2.get("class");
1240 if (nm != null) {
1241 atts2.remove("class");
1242 atts2.put("code", nm + ".class");
1243 }
1244 nm = (String)atts2.get("src");
1245 if (nm != null) {
1246 atts2.remove("src");
1247 atts2.put("codebase", nm);
1248 }
1249 if (atts2.get("width") == null) {
1250 atts2.put("width", "100");
1251 }
1252 if (atts2.get("height") == null) {
1253 atts2.put("height", "100");
1254 }
1255 printTag(statusMsgStream, atts2);
1256 statusMsgStream.println();
1257 }
1258 }
1259 }
1260 }
1261 in.close();
1262 }
1263
1264 /**
|
77
78 @Override
79 public void windowClosing(WindowEvent evt) {
80 dispose();
81 }
82 };
83
84 addWindowListener(windowEventListener);
85 }
86 private static AppletMessageHandler amh = new AppletMessageHandler("textframe");
87
88 }
89
90 /**
91 * Lets us construct one using unix-style one shot behaviors.
92 */
93 final class StdAppletViewerFactory implements AppletViewerFactory {
94
95 @Override
96 public AppletViewer createAppletViewer(int x, int y,
97 URL doc, Hashtable<String, String> atts) {
98 return new AppletViewer(x, y, doc, atts, System.out, this);
99 }
100
101 @Override
102 public MenuBar getBaseMenuBar() {
103 return new MenuBar();
104 }
105
106 @Override
107 public boolean isStandalone() {
108 return true;
109 }
110 }
111
112 /**
113 * The applet viewer makes it possible to run a Java applet without using a browser.
114 * For details on the syntax that <B>appletviewer</B> supports, see
115 * <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.
116 * (The document named appletviewertags.html in the JDK's docs/tooldocs directory,
117 * once the JDK docs have been installed.)
139 */
140
141 PrintStream statusMsgStream;
142
143 /**
144 * For cloning
145 */
146 AppletViewerFactory factory;
147
148
149 private final class UserActionListener implements ActionListener {
150 @Override
151 public void actionPerformed(ActionEvent evt) {
152 processUserAction(evt);
153 }
154 }
155
156 /**
157 * Create the applet viewer.
158 */
159 public AppletViewer(int x, int y, URL doc, Hashtable<String, String> atts,
160 PrintStream statusMsgStream, AppletViewerFactory factory) {
161 this.factory = factory;
162 this.statusMsgStream = statusMsgStream;
163 setTitle(amh.getMessage("tool.title", atts.get("code")));
164
165 MenuBar mb = factory.getBaseMenuBar();
166
167 Menu m = new Menu(amh.getMessage("menu.applet"));
168
169 addMenuItem(m, "menuitem.restart");
170 addMenuItem(m, "menuitem.reload");
171 addMenuItem(m, "menuitem.stop");
172 addMenuItem(m, "menuitem.save");
173 addMenuItem(m, "menuitem.start");
174 addMenuItem(m, "menuitem.clone");
175 m.add(new MenuItem("-"));
176 addMenuItem(m, "menuitem.tag");
177 addMenuItem(m, "menuitem.info");
178 addMenuItem(m, "menuitem.edit").disable();
179 addMenuItem(m, "menuitem.encoding");
333 while (!panel.emptyEventQueue()) ;
334 appletSystemExit();
335 }
336 }
337
338 /**
339 * Split a string based on the presence of a specified separator. Returns
340 * an array of arbitrary length. The end of each element in the array is
341 * indicated by the separator of the end of the string. If there is a
342 * separator immediately before the end of the string, the final element
343 * will be empty. None of the strings will contain the separator. Useful
344 * when separating strings such as "foo/bar/bas" using separator "/".
345 *
346 * @param sep The separator.
347 * @param s The string to split.
348 * @return An array of strings. Each string in the array is determined
349 * by the location of the provided sep in the original string,
350 * s. Whitespace not stripped.
351 */
352 private String [] splitSeparator(String sep, String s) {
353 Vector<String> v = new Vector<>();
354 int tokenStart = 0;
355 int tokenEnd = 0;
356
357 while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {
358 v.addElement(s.substring(tokenStart, tokenEnd));
359 tokenStart = tokenEnd+1;
360 }
361 // Add the final element.
362 v.addElement(s.substring(tokenStart));
363
364 String [] retVal = new String[v.size()];
365 v.copyInto(retVal);
366 return retVal;
367 }
368
369 /*
370 * Methods for java.applet.AppletContext
371 */
372
373 private static Map<URL, AudioClip> audioClips = new HashMap<>();
374
375 /**
376 * Get an audio clip.
377 */
378 @Override
379 public AudioClip getAudioClip(URL url) {
380 checkConnect(url);
381 synchronized (audioClips) {
382 AudioClip clip = audioClips.get(url);
383 if (clip == null) {
384 audioClips.put(url, clip = new AppletAudioClip(url));
385 }
386 return clip;
387 }
388 }
389
390 private static Map<URL, AppletImageRef> imageRefs = new HashMap<>();
391
392 /**
393 * Get an image.
394 */
395 @Override
396 public Image getImage(URL url) {
397 return getCachedImage(url);
398 }
399
400 /**
401 * Get an image.
402 */
403 static Image getCachedImage(URL url) {
404 // System.getSecurityManager().checkConnection(url.getHost(), url.getPort());
405 synchronized (imageRefs) {
406 AppletImageRef ref = imageRefs.get(url);
407 if (ref == null) {
408 ref = new AppletImageRef(url);
409 imageRefs.put(url, ref);
410 }
411 return ref.get();
412 }
413 }
414
415 /**
416 * Flush the image cache.
417 */
418 static void flushImageCache() {
419 imageRefs.clear();
420 }
421
422 static Vector<AppletPanel> appletPanels = new Vector<>();
423
424 /**
425 * Get an applet by name.
426 */
427 @Override
428 public Applet getApplet(String name) {
429 AppletSecurity security = (AppletSecurity)System.getSecurityManager();
430 name = name.toLowerCase();
431 SocketPermission panelSp =
432 new SocketPermission(panel.getCodeBase().getHost(), "connect");
433 for (Enumeration<AppletPanel> e = appletPanels.elements() ; e.hasMoreElements() ;) {
434 AppletPanel p = e.nextElement();
435 String param = p.getParameter("name");
436 if (param != null) {
437 param = param.toLowerCase();
438 }
439 if (name.equals(param) &&
440 p.getDocumentBase().equals(panel.getDocumentBase())) {
441
442 SocketPermission sp =
443 new SocketPermission(p.getCodeBase().getHost(), "connect");
444
445 if (panelSp.implies(sp)) {
446 return p.applet;
447 }
448 }
449 }
450 return null;
451 }
452
453 /**
454 * Return an enumeration of all the accessible
455 * applets on this page.
456 */
457 @Override
458 public Enumeration<Applet> getApplets() {
459 AppletSecurity security = (AppletSecurity)System.getSecurityManager();
460 Vector<Applet> v = new Vector<>();
461 SocketPermission panelSp =
462 new SocketPermission(panel.getCodeBase().getHost(), "connect");
463
464 for (Enumeration<AppletPanel> e = appletPanels.elements() ; e.hasMoreElements() ;) {
465 AppletPanel p = e.nextElement();
466 if (p.getDocumentBase().equals(panel.getDocumentBase())) {
467
468 SocketPermission sp =
469 new SocketPermission(p.getCodeBase().getHost(), "connect");
470 if (panelSp.implies(sp)) {
471 v.addElement(p.applet);
472 }
473 }
474 }
475 return v.elements();
476 }
477
478 /**
479 * Ignore.
480 */
481 @Override
482 public void showDocument(URL url) {
483 }
484
485 /**
492 /**
493 * Show status.
494 */
495 @Override
496 public void showStatus(String status) {
497 label.setText(status);
498 }
499
500 @Override
501 public void setStream(String key, InputStream stream)throws IOException{
502 // We do nothing.
503 }
504
505 @Override
506 public InputStream getStream(String key){
507 // We do nothing.
508 return null;
509 }
510
511 @Override
512 public Iterator<String> getStreamKeys(){
513 // We do nothing.
514 return null;
515 }
516
517 /**
518 * System parameters.
519 */
520 static Hashtable<String, String> systemParam = new Hashtable<>();
521
522 static {
523 systemParam.put("codebase", "codebase");
524 systemParam.put("code", "code");
525 systemParam.put("alt", "alt");
526 systemParam.put("width", "width");
527 systemParam.put("height", "height");
528 systemParam.put("align", "align");
529 systemParam.put("vspace", "vspace");
530 systemParam.put("hspace", "hspace");
531 }
532
533 /**
534 * Print the HTML tag.
535 */
536 public static void printTag(PrintStream out, Hashtable<String, String> atts) {
537 out.print("<applet");
538
539 String v = atts.get("codebase");
540 if (v != null) {
541 out.print(" codebase=\"" + v + "\"");
542 }
543
544 v = atts.get("code");
545 if (v == null) {
546 v = "applet.class";
547 }
548 out.print(" code=\"" + v + "\"");
549 v = atts.get("width");
550 if (v == null) {
551 v = "150";
552 }
553 out.print(" width=" + v);
554
555 v = atts.get("height");
556 if (v == null) {
557 v = "100";
558 }
559 out.print(" height=" + v);
560
561 v = atts.get("name");
562 if (v != null) {
563 out.print(" name=\"" + v + "\"");
564 }
565 out.println(">");
566
567 // A very slow sorting algorithm
568 int len = atts.size();
569 String params[] = new String[len];
570 len = 0;
571 for (Enumeration<String> e = atts.keys() ; e.hasMoreElements() ;) {
572 String param = e.nextElement();
573 int i = 0;
574 for (; i < len ; i++) {
575 if (params[i].compareTo(param) >= 0) {
576 break;
577 }
578 }
579 System.arraycopy(params, i, params, i + 1, len - i);
580 params[i] = param;
581 len++;
582 }
583
584 for (int i = 0 ; i < len ; i++) {
585 String param = params[i];
586 if (systemParam.get(param) == null) {
587 out.println("<param name=" + param +
588 " value=\"" + atts.get(param) + "\">");
589 }
590 }
591 out.println("</applet>");
592 }
632 * Make sure we don't have two threads running through the event queue
633 * at the same time.
634 */
635 try {
636 panel.joinAppletThread();
637 panel.release();
638 } catch (InterruptedException e) {
639 return; // abort the reload
640 }
641
642 panel.createAppletThread();
643 panel.sendEvent(AppletPanel.APPLET_LOAD);
644 panel.sendEvent(AppletPanel.APPLET_INIT);
645 panel.sendEvent(AppletPanel.APPLET_START);
646 }
647
648 /**
649 * Save the applet to a well known file (for now) as a serialized object
650 */
651 void appletSave() {
652 AccessController.doPrivileged(new PrivilegedAction<Object>() {
653
654 @Override
655 public Object run() {
656 // XXX: this privileged block should be made smaller
657 // by initializing a private static variable with "user.dir"
658
659 // Applet needs to be stopped for serialization to succeed.
660 // Since panel.sendEvent only queues the event, there is a
661 // chance that the event will not be processed before
662 // serialization begins. However, by sending the event before
663 // FileDialog is created, enough time is given such that this
664 // situation is unlikely to ever occur.
665
666 panel.sendEvent(AppletPanel.APPLET_STOP);
667 FileDialog fd = new FileDialog(AppletViewer.this,
668 amh.getMessage("appletsave.filedialogtitle"),
669 FileDialog.SAVE);
670 // needed for a bug under Solaris...
671 fd.setDirectory(System.getProperty("user.dir"));
672 fd.setFile(defaultSaveFile);
685 ObjectOutputStream os = new ObjectOutputStream(bos)) {
686
687 showStatus(amh.getMessage("appletsave.err1", panel.applet.toString(), file.toString()));
688 os.writeObject(panel.applet);
689 } catch (IOException ex) {
690 System.err.println(amh.getMessage("appletsave.err2", ex));
691 } finally {
692 panel.sendEvent(AppletPanel.APPLET_START);
693 }
694 return null;
695 }
696 });
697 }
698
699 /**
700 * Clone the viewer and the applet.
701 */
702 void appletClone() {
703 Point p = location();
704 updateAtts();
705 @SuppressWarnings("unchecked")
706 Hashtable<String, String> tmp = (Hashtable<String, String>) panel.atts.clone();
707 factory.createAppletViewer(p.x + XDELTA, p.y + YDELTA,
708 panel.documentURL, tmp);
709 }
710
711 /**
712 * Show the applet tag.
713 */
714 void appletTag() {
715 ByteArrayOutputStream out = new ByteArrayOutputStream();
716 updateAtts();
717 printTag(new PrintStream(out), panel.atts);
718 showStatus(amh.getMessage("applettag"));
719
720 Point p = location();
721 new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("applettag.textframe"), out.toString());
722 }
723
724 /**
725 * Show the applet info.
726 */
727 void appletInfo() {
728 String str = panel.applet.getAppletInfo();
869 if (factory.isStandalone())
870 System.exit(0);
871 }
872
873 /**
874 * Quit all viewers.
875 * Shutdown all viewers properly then
876 * exit from the program (if not stand alone)
877 */
878 protected void appletQuit()
879 {
880 // The caller thread is event dispatch thread, so
881 // spawn a new thread to avoid blocking the event queue
882 // when calling appletShutdown.
883 //
884 new Thread(new Runnable()
885 {
886 @Override
887 public void run()
888 {
889 for (Enumeration<AppletPanel> e = appletPanels.elements() ; e.hasMoreElements() ;) {
890 AppletPanel p = e.nextElement();
891 appletShutdown(p);
892 }
893 appletSystemExit();
894 }
895 }).start();
896 }
897
898 /**
899 * Handle events.
900 */
901 public void processUserAction(ActionEvent evt) {
902
903 String label = ((MenuItem)evt.getSource()).getLabel();
904
905 if (amh.getMessage("menuitem.restart").equals(label)) {
906 appletRestart();
907 return;
908 }
909
910 if (amh.getMessage("menuitem.reload").equals(label)) {
1001 /**
1002 * Scan identifier
1003 */
1004 public static String scanIdentifier(Reader in) throws IOException {
1005 StringBuilder sb = new StringBuilder();
1006 while (true) {
1007 if (((c >= 'a') && (c <= 'z')) ||
1008 ((c >= 'A') && (c <= 'Z')) ||
1009 ((c >= '0') && (c <= '9')) || (c == '_')) {
1010 sb.append((char) c);
1011 c = in.read();
1012 } else {
1013 return sb.toString();
1014 }
1015 }
1016 }
1017
1018 /**
1019 * Scan tag
1020 */
1021 public static Hashtable<String, String> scanTag(Reader in) throws IOException {
1022 Hashtable<String, String> atts = new Hashtable<>();
1023 skipSpace(in);
1024 while (c >= 0 && c != '>') {
1025 String att = scanIdentifier(in);
1026 String val = "";
1027 skipSpace(in);
1028 if (c == '=') {
1029 int quote = -1;
1030 c = in.read();
1031 skipSpace(in);
1032 if ((c == '\'') || (c == '\"')) {
1033 quote = c;
1034 c = in.read();
1035 }
1036 StringBuilder sb = new StringBuilder();
1037 while ((c > 0) &&
1038 (((quote < 0) && (c != ' ') && (c != '\t') &&
1039 (c != '\n') && (c != '\r') && (c != '>'))
1040 || ((quote >= 0) && (c != quote)))) {
1041 sb.append((char) c);
1042 c = in.read();
1107 String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
1108 String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
1109 String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
1110 String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
1111 String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
1112 String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
1113 String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
1114 String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
1115 String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
1116 String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
1117 String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
1118
1119 java.net.URLConnection conn = url.openConnection();
1120 Reader in = makeReader(conn.getInputStream());
1121 /* The original URL may have been redirected - this
1122 * sets it to whatever URL/codebase we ended up getting
1123 */
1124 url = conn.getURL();
1125
1126 int ydisp = 1;
1127 Hashtable<String, String> atts = null;
1128
1129 while(true) {
1130 c = in.read();
1131 if (c == -1)
1132 break;
1133
1134 if (c == '<') {
1135 c = in.read();
1136 if (c == '/') {
1137 c = in.read();
1138 String nm = scanIdentifier(in);
1139 if (nm.equalsIgnoreCase("applet") ||
1140 nm.equalsIgnoreCase("object") ||
1141 nm.equalsIgnoreCase("embed")) {
1142
1143 // We can't test for a code tag until </OBJECT>
1144 // because it is a parameter, not an attribute.
1145 if(isObjectTag) {
1146 if (atts.get("code") == null && atts.get("object") == null) {
1147 statusMsgStream.println(objectRequiresCodeWarning);
1157 factory.createAppletViewer(x, y, url, atts);
1158 x += XDELTA;
1159 y += YDELTA;
1160 // make sure we don't go too far!
1161 Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
1162 if ((x > d.width - 300) || (y > d.height - 300)) {
1163 x = 0;
1164 y = 2 * ydisp * YDELTA;
1165 ydisp++;
1166 }
1167 }
1168 atts = null;
1169 isAppletTag = false;
1170 isObjectTag = false;
1171 isEmbedTag = false;
1172 }
1173 }
1174 else {
1175 String nm = scanIdentifier(in);
1176 if (nm.equalsIgnoreCase("param")) {
1177 Hashtable<String, String> t = scanTag(in);
1178 String att = t.get("name");
1179 if (att == null) {
1180 statusMsgStream.println(requiresNameWarning);
1181 } else {
1182 String val = t.get("value");
1183 if (val == null) {
1184 statusMsgStream.println(requiresNameWarning);
1185 } else if (atts != null) {
1186 atts.put(att.toLowerCase(), val);
1187 } else {
1188 statusMsgStream.println(paramOutsideWarning);
1189 }
1190 }
1191 }
1192 else if (nm.equalsIgnoreCase("applet")) {
1193 isAppletTag = true;
1194 atts = scanTag(in);
1195 if (atts.get("code") == null && atts.get("object") == null) {
1196 statusMsgStream.println(appletRequiresCodeWarning);
1197 atts = null;
1198 } else if (atts.get("width") == null) {
1199 statusMsgStream.println(appletRequiresWidthWarning);
1200 atts = null;
1201 } else if (atts.get("height") == null) {
1202 statusMsgStream.println(appletRequiresHeightWarning);
1220 atts = null;
1221 }
1222 }
1223 else if (nm.equalsIgnoreCase("embed")) {
1224 isEmbedTag = true;
1225 atts = scanTag(in);
1226
1227 if (atts.get("code") == null && atts.get("object") == null) {
1228 statusMsgStream.println(embedRequiresCodeWarning);
1229 atts = null;
1230 } else if (atts.get("width") == null) {
1231 statusMsgStream.println(embedRequiresWidthWarning);
1232 atts = null;
1233 } else if (atts.get("height") == null) {
1234 statusMsgStream.println(embedRequiresHeightWarning);
1235 atts = null;
1236 }
1237 }
1238 else if (nm.equalsIgnoreCase("app")) {
1239 statusMsgStream.println(appNotLongerSupportedWarning);
1240 Hashtable<String, String> atts2 = scanTag(in);
1241 nm = atts2.get("class");
1242 if (nm != null) {
1243 atts2.remove("class");
1244 atts2.put("code", nm + ".class");
1245 }
1246 nm = atts2.get("src");
1247 if (nm != null) {
1248 atts2.remove("src");
1249 atts2.put("codebase", nm);
1250 }
1251 if (atts2.get("width") == null) {
1252 atts2.put("width", "100");
1253 }
1254 if (atts2.get("height") == null) {
1255 atts2.put("height", "100");
1256 }
1257 printTag(statusMsgStream, atts2);
1258 statusMsgStream.println();
1259 }
1260 }
1261 }
1262 }
1263 in.close();
1264 }
1265
1266 /**
|