Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/applet/AppletViewer.java
38829 views
/*1* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.applet;2627import java.util.*;28import java.io.*;29import java.awt.*;30import java.awt.event.*;31import java.awt.print.*;32import javax.print.attribute.*;33import java.applet.*;34import java.net.URL;35import java.net.SocketPermission;36import sun.misc.Ref;37import java.security.AccessController;38import java.security.PrivilegedAction;39import sun.awt.SunToolkit;40import sun.awt.AppContext;4142/**43* A frame to show the applet tag in.44*/45final class TextFrame extends Frame {4647/**48* Create the tag frame.49*/50TextFrame(int x, int y, String title, String text) {51setTitle(title);52TextArea txt = new TextArea(20, 60);53txt.setText(text);54txt.setEditable(false);5556add("Center", txt);5758Panel p = new Panel();59add("South", p);60Button b = new Button(amh.getMessage("button.dismiss", "Dismiss"));61p.add(b);6263class ActionEventListener implements ActionListener {64@Override65public void actionPerformed(ActionEvent evt) {66dispose();67}68}69b.addActionListener(new ActionEventListener());7071pack();72move(x, y);73setVisible(true);7475WindowListener windowEventListener = new WindowAdapter() {7677@Override78public void windowClosing(WindowEvent evt) {79dispose();80}81};8283addWindowListener(windowEventListener);84}85private static AppletMessageHandler amh = new AppletMessageHandler("textframe");8687}8889/**90* Lets us construct one using unix-style one shot behaviors.91*/92final class StdAppletViewerFactory implements AppletViewerFactory {9394@Override95public AppletViewer createAppletViewer(int x, int y,96URL doc, Hashtable atts) {97return new AppletViewer(x, y, doc, atts, System.out, this);98}99100@Override101public MenuBar getBaseMenuBar() {102return new MenuBar();103}104105@Override106public boolean isStandalone() {107return true;108}109}110111/**112* The applet viewer makes it possible to run a Java applet without using a browser.113* For details on the syntax that <B>appletviewer</B> supports, see114* <a href="../../../docs/tooldocs/appletviewertags.html">AppletViewer Tags</a>.115* (The document named appletviewertags.html in the JDK's docs/tooldocs directory,116* once the JDK docs have been installed.)117*/118public class AppletViewer extends Frame implements AppletContext, Printable {119120/**121* Some constants...122*/123private static String defaultSaveFile = "Applet.ser";124125/**126* The panel in which the applet is being displayed.127*/128AppletViewerPanel panel;129130/**131* The status line.132*/133Label label;134135/**136* output status messages to this stream137*/138139PrintStream statusMsgStream;140141/**142* For cloning143*/144AppletViewerFactory factory;145146147private final class UserActionListener implements ActionListener {148@Override149public void actionPerformed(ActionEvent evt) {150processUserAction(evt);151}152}153154/**155* Create the applet viewer.156*/157public AppletViewer(int x, int y, URL doc, Hashtable atts,158PrintStream statusMsgStream, AppletViewerFactory factory) {159this.factory = factory;160this.statusMsgStream = statusMsgStream;161setTitle(amh.getMessage("tool.title", atts.get("code")));162163MenuBar mb = factory.getBaseMenuBar();164165Menu m = new Menu(amh.getMessage("menu.applet"));166167addMenuItem(m, "menuitem.restart");168addMenuItem(m, "menuitem.reload");169addMenuItem(m, "menuitem.stop");170addMenuItem(m, "menuitem.save");171addMenuItem(m, "menuitem.start");172addMenuItem(m, "menuitem.clone");173m.add(new MenuItem("-"));174addMenuItem(m, "menuitem.tag");175addMenuItem(m, "menuitem.info");176addMenuItem(m, "menuitem.edit").disable();177addMenuItem(m, "menuitem.encoding");178m.add(new MenuItem("-"));179addMenuItem(m, "menuitem.print");180m.add(new MenuItem("-"));181addMenuItem(m, "menuitem.props");182m.add(new MenuItem("-"));183addMenuItem(m, "menuitem.close");184if (factory.isStandalone()) {185addMenuItem(m, "menuitem.quit");186}187188mb.add(m);189190setMenuBar(mb);191192add("Center", panel = new AppletViewerPanel(doc, atts));193add("South", label = new Label(amh.getMessage("label.hello")));194panel.init();195appletPanels.addElement(panel);196197pack();198move(x, y);199setVisible(true);200201WindowListener windowEventListener = new WindowAdapter() {202203@Override204public void windowClosing(WindowEvent evt) {205appletClose();206}207208@Override209public void windowIconified(WindowEvent evt) {210appletStop();211}212213@Override214public void windowDeiconified(WindowEvent evt) {215appletStart();216}217};218219class AppletEventListener implements AppletListener220{221final Frame frame;222223public AppletEventListener(Frame frame)224{225this.frame = frame;226}227228@Override229public void appletStateChanged(AppletEvent evt)230{231AppletPanel src = (AppletPanel)evt.getSource();232233switch (evt.getID()) {234case AppletPanel.APPLET_RESIZE: {235if(src != null) {236resize(preferredSize());237validate();238}239break;240}241case AppletPanel.APPLET_LOADING_COMPLETED: {242Applet a = src.getApplet(); // sun.applet.AppletPanel243244// Fixed #4754451: Applet can have methods running on main245// thread event queue.246//247// The cause of this bug is that the frame of the applet248// is created in main thread group. Thus, when certain249// AWT/Swing events are generated, the events will be250// dispatched through the wrong event dispatch thread.251//252// To fix this, we rearrange the AppContext with the frame,253// so the proper event queue will be looked up.254//255// Swing also maintains a Frame list for the AppContext,256// so we will have to rearrange it as well.257//258if (a != null)259AppletPanel.changeFrameAppContext(frame, SunToolkit.targetToAppContext(a));260else261AppletPanel.changeFrameAppContext(frame, AppContext.getAppContext());262263break;264}265}266}267};268269addWindowListener(windowEventListener);270panel.addAppletListener(new AppletEventListener(this));271272// Start the applet273showStatus(amh.getMessage("status.start"));274initEventQueue();275}276277// XXX 99/9/10 probably should be "private"278public MenuItem addMenuItem(Menu m, String s) {279MenuItem mItem = new MenuItem(amh.getMessage(s));280mItem.addActionListener(new UserActionListener());281return m.add(mItem);282}283284/**285* Send the initial set of events to the appletviewer event queue.286* On start-up the current behaviour is to load the applet and call287* Applet.init() and Applet.start().288*/289private void initEventQueue() {290// appletviewer.send.event is an undocumented and unsupported system291// property which is used exclusively for testing purposes.292String eventList = System.getProperty("appletviewer.send.event");293294if (eventList == null) {295// Add the standard events onto the event queue.296panel.sendEvent(AppletPanel.APPLET_LOAD);297panel.sendEvent(AppletPanel.APPLET_INIT);298panel.sendEvent(AppletPanel.APPLET_START);299} else {300// We're testing AppletViewer. Force the specified set of events301// onto the event queue, wait for the events to be processed, and302// exit.303304// The list of events that will be executed is provided as a305// ","-separated list. No error-checking will be done on the list.306String [] events = splitSeparator(",", eventList);307308for (int i = 0; i < events.length; i++) {309System.out.println("Adding event to queue: " + events[i]);310if (events[i].equals("dispose"))311panel.sendEvent(AppletPanel.APPLET_DISPOSE);312else if (events[i].equals("load"))313panel.sendEvent(AppletPanel.APPLET_LOAD);314else if (events[i].equals("init"))315panel.sendEvent(AppletPanel.APPLET_INIT);316else if (events[i].equals("start"))317panel.sendEvent(AppletPanel.APPLET_START);318else if (events[i].equals("stop"))319panel.sendEvent(AppletPanel.APPLET_STOP);320else if (events[i].equals("destroy"))321panel.sendEvent(AppletPanel.APPLET_DESTROY);322else if (events[i].equals("quit"))323panel.sendEvent(AppletPanel.APPLET_QUIT);324else if (events[i].equals("error"))325panel.sendEvent(AppletPanel.APPLET_ERROR);326else327// non-fatal error if we get an unrecognized event328System.out.println("Unrecognized event name: " + events[i]);329}330331while (!panel.emptyEventQueue()) ;332appletSystemExit();333}334}335336/**337* Split a string based on the presence of a specified separator. Returns338* an array of arbitrary length. The end of each element in the array is339* indicated by the separator of the end of the string. If there is a340* separator immediately before the end of the string, the final element341* will be empty. None of the strings will contain the separator. Useful342* when separating strings such as "foo/bar/bas" using separator "/".343*344* @param sep The separator.345* @param s The string to split.346* @return An array of strings. Each string in the array is determined347* by the location of the provided sep in the original string,348* s. Whitespace not stripped.349*/350private String [] splitSeparator(String sep, String s) {351Vector v = new Vector();352int tokenStart = 0;353int tokenEnd = 0;354355while ((tokenEnd = s.indexOf(sep, tokenStart)) != -1) {356v.addElement(s.substring(tokenStart, tokenEnd));357tokenStart = tokenEnd+1;358}359// Add the final element.360v.addElement(s.substring(tokenStart));361362String [] retVal = new String[v.size()];363v.copyInto(retVal);364return retVal;365}366367/*368* Methods for java.applet.AppletContext369*/370371private static Map audioClips = new HashMap();372373/**374* Get an audio clip.375*/376@Override377public AudioClip getAudioClip(URL url) {378checkConnect(url);379synchronized (audioClips) {380AudioClip clip = (AudioClip)audioClips.get(url);381if (clip == null) {382audioClips.put(url, clip = new AppletAudioClip(url));383}384return clip;385}386}387388private static Map imageRefs = new HashMap();389390/**391* Get an image.392*/393@Override394public Image getImage(URL url) {395return getCachedImage(url);396}397398static Image getCachedImage(URL url) {399// System.getSecurityManager().checkConnection(url.getHost(), url.getPort());400return (Image)getCachedImageRef(url).get();401}402403/**404* Get an image ref.405*/406static Ref getCachedImageRef(URL url) {407synchronized (imageRefs) {408AppletImageRef ref = (AppletImageRef)imageRefs.get(url);409if (ref == null) {410ref = new AppletImageRef(url);411imageRefs.put(url, ref);412}413return ref;414}415}416417/**418* Flush the image cache.419*/420static void flushImageCache() {421imageRefs.clear();422}423424static Vector appletPanels = new Vector();425426/**427* Get an applet by name.428*/429@Override430public Applet getApplet(String name) {431AppletSecurity security = (AppletSecurity)System.getSecurityManager();432name = name.toLowerCase();433SocketPermission panelSp =434new SocketPermission(panel.getCodeBase().getHost(), "connect");435for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {436AppletPanel p = (AppletPanel)e.nextElement();437String param = p.getParameter("name");438if (param != null) {439param = param.toLowerCase();440}441if (name.equals(param) &&442p.getDocumentBase().equals(panel.getDocumentBase())) {443444SocketPermission sp =445new SocketPermission(p.getCodeBase().getHost(), "connect");446447if (panelSp.implies(sp)) {448return p.applet;449}450}451}452return null;453}454455/**456* Return an enumeration of all the accessible457* applets on this page.458*/459@Override460public Enumeration getApplets() {461AppletSecurity security = (AppletSecurity)System.getSecurityManager();462Vector v = new Vector();463SocketPermission panelSp =464new SocketPermission(panel.getCodeBase().getHost(), "connect");465466for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {467AppletPanel p = (AppletPanel)e.nextElement();468if (p.getDocumentBase().equals(panel.getDocumentBase())) {469470SocketPermission sp =471new SocketPermission(p.getCodeBase().getHost(), "connect");472if (panelSp.implies(sp)) {473v.addElement(p.applet);474}475}476}477return v.elements();478}479480/**481* Ignore.482*/483@Override484public void showDocument(URL url) {485}486487/**488* Ignore.489*/490@Override491public void showDocument(URL url, String target) {492}493494/**495* Show status.496*/497@Override498public void showStatus(String status) {499label.setText(status);500}501502@Override503public void setStream(String key, InputStream stream)throws IOException{504// We do nothing.505}506507@Override508public InputStream getStream(String key){509// We do nothing.510return null;511}512513@Override514public Iterator getStreamKeys(){515// We do nothing.516return null;517}518519/**520* System parameters.521*/522static Hashtable systemParam = new Hashtable();523524static {525systemParam.put("codebase", "codebase");526systemParam.put("code", "code");527systemParam.put("alt", "alt");528systemParam.put("width", "width");529systemParam.put("height", "height");530systemParam.put("align", "align");531systemParam.put("vspace", "vspace");532systemParam.put("hspace", "hspace");533}534535/**536* Print the HTML tag.537*/538public static void printTag(PrintStream out, Hashtable atts) {539out.print("<applet");540541String v = (String)atts.get("codebase");542if (v != null) {543out.print(" codebase=\"" + v + "\"");544}545546v = (String)atts.get("code");547if (v == null) {548v = "applet.class";549}550out.print(" code=\"" + v + "\"");551v = (String)atts.get("width");552if (v == null) {553v = "150";554}555out.print(" width=" + v);556557v = (String)atts.get("height");558if (v == null) {559v = "100";560}561out.print(" height=" + v);562563v = (String)atts.get("name");564if (v != null) {565out.print(" name=\"" + v + "\"");566}567out.println(">");568569// A very slow sorting algorithm570int len = atts.size();571String params[] = new String[len];572len = 0;573for (Enumeration e = atts.keys() ; e.hasMoreElements() ;) {574String param = (String)e.nextElement();575int i = 0;576for (; i < len ; i++) {577if (params[i].compareTo(param) >= 0) {578break;579}580}581System.arraycopy(params, i, params, i + 1, len - i);582params[i] = param;583len++;584}585586for (int i = 0 ; i < len ; i++) {587String param = params[i];588if (systemParam.get(param) == null) {589out.println("<param name=" + param +590" value=\"" + atts.get(param) + "\">");591}592}593out.println("</applet>");594}595596/**597* Make sure the atrributes are uptodate.598*/599public void updateAtts() {600Dimension d = panel.size();601Insets in = panel.insets();602panel.atts.put("width",603Integer.toString(d.width - (in.left + in.right)));604panel.atts.put("height",605Integer.toString(d.height - (in.top + in.bottom)));606}607608/**609* Restart the applet.610*/611void appletRestart() {612panel.sendEvent(AppletPanel.APPLET_STOP);613panel.sendEvent(AppletPanel.APPLET_DESTROY);614panel.sendEvent(AppletPanel.APPLET_INIT);615panel.sendEvent(AppletPanel.APPLET_START);616}617618/**619* Reload the applet.620*/621void appletReload() {622panel.sendEvent(AppletPanel.APPLET_STOP);623panel.sendEvent(AppletPanel.APPLET_DESTROY);624panel.sendEvent(AppletPanel.APPLET_DISPOSE);625626/**627* Fixed #4501142: Classloader sharing policy doesn't628* take "archive" into account. This will be overridden629* by Java Plug-in. [stanleyh]630*/631AppletPanel.flushClassLoader(panel.getClassLoaderCacheKey());632633/*634* Make sure we don't have two threads running through the event queue635* at the same time.636*/637try {638panel.joinAppletThread();639panel.release();640} catch (InterruptedException e) {641return; // abort the reload642}643644panel.createAppletThread();645panel.sendEvent(AppletPanel.APPLET_LOAD);646panel.sendEvent(AppletPanel.APPLET_INIT);647panel.sendEvent(AppletPanel.APPLET_START);648}649650/**651* Save the applet to a well known file (for now) as a serialized object652*/653void appletSave() {654AccessController.doPrivileged(new PrivilegedAction() {655656@Override657public Object run() {658// XXX: this privileged block should be made smaller659// by initializing a private static variable with "user.dir"660661// Applet needs to be stopped for serialization to succeed.662// Since panel.sendEvent only queues the event, there is a663// chance that the event will not be processed before664// serialization begins. However, by sending the event before665// FileDialog is created, enough time is given such that this666// situation is unlikely to ever occur.667668panel.sendEvent(AppletPanel.APPLET_STOP);669FileDialog fd = new FileDialog(AppletViewer.this,670amh.getMessage("appletsave.filedialogtitle"),671FileDialog.SAVE);672// needed for a bug under Solaris...673fd.setDirectory(System.getProperty("user.dir"));674fd.setFile(defaultSaveFile);675fd.show();676String fname = fd.getFile();677if (fname == null) {678// Restart applet if Save is cancelled.679panel.sendEvent(AppletPanel.APPLET_START);680return null; // cancelled681}682String dname = fd.getDirectory();683File file = new File(dname, fname);684685try (FileOutputStream fos = new FileOutputStream(file);686BufferedOutputStream bos = new BufferedOutputStream(fos);687ObjectOutputStream os = new ObjectOutputStream(bos)) {688689showStatus(amh.getMessage("appletsave.err1", panel.applet.toString(), file.toString()));690os.writeObject(panel.applet);691} catch (IOException ex) {692System.err.println(amh.getMessage("appletsave.err2", ex));693} finally {694panel.sendEvent(AppletPanel.APPLET_START);695}696return null;697}698});699}700701/**702* Clone the viewer and the applet.703*/704void appletClone() {705Point p = location();706updateAtts();707factory.createAppletViewer(p.x + XDELTA, p.y + YDELTA,708panel.documentURL, (Hashtable)panel.atts.clone());709}710711/**712* Show the applet tag.713*/714void appletTag() {715ByteArrayOutputStream out = new ByteArrayOutputStream();716updateAtts();717printTag(new PrintStream(out), panel.atts);718showStatus(amh.getMessage("applettag"));719720Point p = location();721new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("applettag.textframe"), out.toString());722}723724/**725* Show the applet info.726*/727void appletInfo() {728String str = panel.applet.getAppletInfo();729if (str == null) {730str = amh.getMessage("appletinfo.applet");731}732str += "\n\n";733734String atts[][] = panel.applet.getParameterInfo();735if (atts != null) {736for (int i = 0 ; i < atts.length ; i++) {737str += atts[i][0] + " -- " + atts[i][1] + " -- " + atts[i][2] + "\n";738}739} else {740str += amh.getMessage("appletinfo.param");741}742743Point p = location();744new TextFrame(p.x + XDELTA, p.y + YDELTA, amh.getMessage("appletinfo.textframe"), str);745746}747748/**749* Show character encoding type750*/751void appletCharacterEncoding() {752showStatus(amh.getMessage("appletencoding", encoding));753}754755/**756* Edit the applet.757*/758void appletEdit() {759}760761/**762* Print the applet.763*/764void appletPrint() {765PrinterJob pj = PrinterJob.getPrinterJob();766767if (pj != null) {768PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();769if (pj.printDialog(aset)) {770pj.setPrintable(this);771try {772pj.print(aset);773statusMsgStream.println(amh.getMessage("appletprint.finish"));774} catch (PrinterException e) {775statusMsgStream.println(amh.getMessage("appletprint.fail"));776}777} else {778statusMsgStream.println(amh.getMessage("appletprint.cancel"));779}780} else {781statusMsgStream.println(amh.getMessage("appletprint.fail"));782}783}784785@Override786public int print(Graphics graphics, PageFormat pf, int pageIndex) {787if (pageIndex > 0) {788return Printable.NO_SUCH_PAGE;789} else {790Graphics2D g2d = (Graphics2D)graphics;791g2d.translate(pf.getImageableX(), pf.getImageableY());792panel.applet.printAll(graphics);793return Printable.PAGE_EXISTS;794}795}796797/**798* Properties.799*/800static AppletProps props;801public static synchronized void networkProperties() {802if (props == null) {803props = new AppletProps();804}805props.addNotify();806props.setVisible(true);807}808809/**810* Start the applet.811*/812void appletStart() {813panel.sendEvent(AppletPanel.APPLET_START);814}815816/**817* Stop the applet.818*/819void appletStop() {820panel.sendEvent(AppletPanel.APPLET_STOP);821}822823/**824* Shutdown a viewer.825* Stop, Destroy, Dispose and Quit a viewer826*/827private void appletShutdown(AppletPanel p) {828p.sendEvent(AppletPanel.APPLET_STOP);829p.sendEvent(AppletPanel.APPLET_DESTROY);830p.sendEvent(AppletPanel.APPLET_DISPOSE);831p.sendEvent(AppletPanel.APPLET_QUIT);832}833834/**835* Close this viewer.836* Stop, Destroy, Dispose and Quit an AppletView, then837* reclaim resources and exit the program if this is838* the last applet.839*/840void appletClose() {841842// The caller thread is event dispatch thread, so843// spawn a new thread to avoid blocking the event queue844// when calling appletShutdown.845//846final AppletPanel p = panel;847848new Thread(new Runnable()849{850@Override851public void run()852{853appletShutdown(p);854appletPanels.removeElement(p);855dispose();856857if (countApplets() == 0) {858appletSystemExit();859}860}861}).start();862}863864/**865* Exit the program.866* Exit from the program (if not stand alone) - do no clean-up867*/868private void appletSystemExit() {869if (factory.isStandalone())870System.exit(0);871}872873/**874* Quit all viewers.875* Shutdown all viewers properly then876* exit from the program (if not stand alone)877*/878protected void appletQuit()879{880// The caller thread is event dispatch thread, so881// spawn a new thread to avoid blocking the event queue882// when calling appletShutdown.883//884new Thread(new Runnable()885{886@Override887public void run()888{889for (Enumeration e = appletPanels.elements() ; e.hasMoreElements() ;) {890AppletPanel p = (AppletPanel)e.nextElement();891appletShutdown(p);892}893appletSystemExit();894}895}).start();896}897898/**899* Handle events.900*/901public void processUserAction(ActionEvent evt) {902903String label = ((MenuItem)evt.getSource()).getLabel();904905if (amh.getMessage("menuitem.restart").equals(label)) {906appletRestart();907return;908}909910if (amh.getMessage("menuitem.reload").equals(label)) {911appletReload();912return;913}914915if (amh.getMessage("menuitem.clone").equals(label)) {916appletClone();917return;918}919920if (amh.getMessage("menuitem.stop").equals(label)) {921appletStop();922return;923}924925if (amh.getMessage("menuitem.save").equals(label)) {926appletSave();927return;928}929930if (amh.getMessage("menuitem.start").equals(label)) {931appletStart();932return;933}934935if (amh.getMessage("menuitem.tag").equals(label)) {936appletTag();937return;938}939940if (amh.getMessage("menuitem.info").equals(label)) {941appletInfo();942return;943}944945if (amh.getMessage("menuitem.encoding").equals(label)) {946appletCharacterEncoding();947return;948}949950if (amh.getMessage("menuitem.edit").equals(label)) {951appletEdit();952return;953}954955if (amh.getMessage("menuitem.print").equals(label)) {956appletPrint();957return;958}959960if (amh.getMessage("menuitem.props").equals(label)) {961networkProperties();962return;963}964965if (amh.getMessage("menuitem.close").equals(label)) {966appletClose();967return;968}969970if (factory.isStandalone() && amh.getMessage("menuitem.quit").equals(label)) {971appletQuit();972return;973}974//statusMsgStream.println("evt = " + evt);975}976977/**978* How many applets are running?979*/980981public static int countApplets() {982return appletPanels.size();983}984985986/**987* The current character.988*/989static int c;990991/**992* Scan spaces.993*/994public static void skipSpace(Reader in) throws IOException {995while ((c >= 0) &&996((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) {997c = in.read();998}999}10001001/**1002* Scan identifier1003*/1004public static String scanIdentifier(Reader in) throws IOException {1005StringBuffer buf = new StringBuffer();1006while (true) {1007if (((c >= 'a') && (c <= 'z')) ||1008((c >= 'A') && (c <= 'Z')) ||1009((c >= '0') && (c <= '9')) || (c == '_')) {1010buf.append((char)c);1011c = in.read();1012} else {1013return buf.toString();1014}1015}1016}10171018/**1019* Scan tag1020*/1021public static Hashtable scanTag(Reader in) throws IOException {1022Hashtable atts = new Hashtable();1023skipSpace(in);1024while (c >= 0 && c != '>') {1025String att = scanIdentifier(in);1026String val = "";1027skipSpace(in);1028if (c == '=') {1029int quote = -1;1030c = in.read();1031skipSpace(in);1032if ((c == '\'') || (c == '\"')) {1033quote = c;1034c = in.read();1035}1036StringBuffer buf = new StringBuffer();1037while ((c > 0) &&1038(((quote < 0) && (c != ' ') && (c != '\t') &&1039(c != '\n') && (c != '\r') && (c != '>'))1040|| ((quote >= 0) && (c != quote)))) {1041buf.append((char)c);1042c = in.read();1043}1044if (c == quote) {1045c = in.read();1046}1047skipSpace(in);1048val = buf.toString();1049}1050//statusMsgStream.println("PUT " + att + " = '" + val + "'");1051if (! val.equals("")) {1052atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);1053}1054while (true) {1055if ((c == '>') || (c < 0) ||1056((c >= 'a') && (c <= 'z')) ||1057((c >= 'A') && (c <= 'Z')) ||1058((c >= '0') && (c <= '9')) || (c == '_'))1059break;1060c = in.read();1061}1062//skipSpace(in);1063}1064return atts;1065}10661067/* values used for placement of AppletViewer's frames */1068private static int x = 0;1069private static int y = 0;1070private static final int XDELTA = 30;1071private static final int YDELTA = XDELTA;10721073static String encoding = null;10741075static private Reader makeReader(InputStream is) {1076if (encoding != null) {1077try {1078return new BufferedReader(new InputStreamReader(is, encoding));1079} catch (IOException x) { }1080}1081InputStreamReader r = new InputStreamReader(is);1082encoding = r.getEncoding();1083return new BufferedReader(r);1084}10851086/**1087* Scan an html file for <applet> tags1088*/1089public static void parse(URL url, String enc) throws IOException {1090encoding = enc;1091parse(url, System.out, new StdAppletViewerFactory());1092}10931094public static void parse(URL url) throws IOException {1095parse(url, System.out, new StdAppletViewerFactory());1096}10971098public static void parse(URL url, PrintStream statusMsgStream,1099AppletViewerFactory factory) throws IOException {1100// <OBJECT> <EMBED> tag flags1101boolean isAppletTag = false;1102boolean isObjectTag = false;1103boolean isEmbedTag = false;11041105// warning messages1106String requiresNameWarning = amh.getMessage("parse.warning.requiresname");1107String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");1108String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");1109String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");1110String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");1111String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");1112String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");1113String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");1114String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");1115String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");1116String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");1117String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");11181119java.net.URLConnection conn = url.openConnection();1120Reader in = makeReader(conn.getInputStream());1121/* The original URL may have been redirected - this1122* sets it to whatever URL/codebase we ended up getting1123*/1124url = conn.getURL();11251126int ydisp = 1;1127Hashtable atts = null;11281129while(true) {1130c = in.read();1131if (c == -1)1132break;11331134if (c == '<') {1135c = in.read();1136if (c == '/') {1137c = in.read();1138String nm = scanIdentifier(in);1139if (nm.equalsIgnoreCase("applet") ||1140nm.equalsIgnoreCase("object") ||1141nm.equalsIgnoreCase("embed")) {11421143// We can't test for a code tag until </OBJECT>1144// because it is a parameter, not an attribute.1145if(isObjectTag) {1146if (atts.get("code") == null && atts.get("object") == null) {1147statusMsgStream.println(objectRequiresCodeWarning);1148atts = null;1149}1150}11511152if (atts != null) {1153// XXX 5/18 In general this code just simply1154// shouldn't be part of parsing. It's presence1155// causes things to be a little too much of a1156// hack.1157factory.createAppletViewer(x, y, url, atts);1158x += XDELTA;1159y += YDELTA;1160// make sure we don't go too far!1161Dimension d = Toolkit.getDefaultToolkit().getScreenSize();1162if ((x > d.width - 300) || (y > d.height - 300)) {1163x = 0;1164y = 2 * ydisp * YDELTA;1165ydisp++;1166}1167}1168atts = null;1169isAppletTag = false;1170isObjectTag = false;1171isEmbedTag = false;1172}1173}1174else {1175String nm = scanIdentifier(in);1176if (nm.equalsIgnoreCase("param")) {1177Hashtable t = scanTag(in);1178String att = (String)t.get("name");1179if (att == null) {1180statusMsgStream.println(requiresNameWarning);1181} else {1182String val = (String)t.get("value");1183if (val == null) {1184statusMsgStream.println(requiresNameWarning);1185} else if (atts != null) {1186atts.put(att.toLowerCase(), val);1187} else {1188statusMsgStream.println(paramOutsideWarning);1189}1190}1191}1192else if (nm.equalsIgnoreCase("applet")) {1193isAppletTag = true;1194atts = scanTag(in);1195if (atts.get("code") == null && atts.get("object") == null) {1196statusMsgStream.println(appletRequiresCodeWarning);1197atts = null;1198} else if (atts.get("width") == null) {1199statusMsgStream.println(appletRequiresWidthWarning);1200atts = null;1201} else if (atts.get("height") == null) {1202statusMsgStream.println(appletRequiresHeightWarning);1203atts = null;1204}1205}1206else if (nm.equalsIgnoreCase("object")) {1207isObjectTag = true;1208atts = scanTag(in);1209// The <OBJECT> attribute codebase isn't what1210// we want. If its defined, remove it.1211if(atts.get("codebase") != null) {1212atts.remove("codebase");1213}12141215if (atts.get("width") == null) {1216statusMsgStream.println(objectRequiresWidthWarning);1217atts = null;1218} else if (atts.get("height") == null) {1219statusMsgStream.println(objectRequiresHeightWarning);1220atts = null;1221}1222}1223else if (nm.equalsIgnoreCase("embed")) {1224isEmbedTag = true;1225atts = scanTag(in);12261227if (atts.get("code") == null && atts.get("object") == null) {1228statusMsgStream.println(embedRequiresCodeWarning);1229atts = null;1230} else if (atts.get("width") == null) {1231statusMsgStream.println(embedRequiresWidthWarning);1232atts = null;1233} else if (atts.get("height") == null) {1234statusMsgStream.println(embedRequiresHeightWarning);1235atts = null;1236}1237}1238else if (nm.equalsIgnoreCase("app")) {1239statusMsgStream.println(appNotLongerSupportedWarning);1240Hashtable atts2 = scanTag(in);1241nm = (String)atts2.get("class");1242if (nm != null) {1243atts2.remove("class");1244atts2.put("code", nm + ".class");1245}1246nm = (String)atts2.get("src");1247if (nm != null) {1248atts2.remove("src");1249atts2.put("codebase", nm);1250}1251if (atts2.get("width") == null) {1252atts2.put("width", "100");1253}1254if (atts2.get("height") == null) {1255atts2.put("height", "100");1256}1257printTag(statusMsgStream, atts2);1258statusMsgStream.println();1259}1260}1261}1262}1263in.close();1264}12651266/**1267* Old main entry point.1268*1269* @deprecated1270*/1271@Deprecated1272public static void main(String argv[]) {1273// re-route everything to the new main entry point1274Main.main(argv);1275}12761277private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");12781279private static void checkConnect(URL url)1280{1281SecurityManager security = System.getSecurityManager();1282if (security != null) {1283try {1284java.security.Permission perm =1285url.openConnection().getPermission();1286if (perm != null)1287security.checkPermission(perm);1288else1289security.checkConnect(url.getHost(), url.getPort());1290} catch (java.io.IOException ioe) {1291security.checkConnect(url.getHost(), url.getPort());1292}1293}1294}1295}129612971298