/* * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.applet; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import java.net.MalformedURLException; import java.util.Enumeration; import java.util.Properties; import java.util.Vector; import sun.net.www.ParseUtil; /** * The main entry point into AppletViewer. * * @deprecated The Applet API is deprecated. See the * java.applet package * documentation for further information. */ @Deprecated(since = "9") public class Main { /** * The file which contains all of the AppletViewer specific properties. */ static File theUserPropertiesFile; /** * The default key/value pairs for the required user-specific properties. */ static final String [][] avDefaultUserProps = { // There's a bootstrapping problem here. If we don't have a proxyHost, // then we will not be able to connect to a URL outside the firewall; // however, there's no way for us to set the proxyHost without starting // AppletViewer. This problem existed before the re-write. {"http.proxyHost", ""}, {"http.proxyPort", "80"}, {"package.restrict.access.sun", "true"} }; static { File userHome = new File(System.getProperty("user.home")); // make sure we can write to this location userHome.canWrite(); theUserPropertiesFile = new File(userHome, ".appletviewer"); } // i18n private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer"); /** * Member variables set according to options passed in to AppletViewer. */ private boolean helpFlag = false; private String encoding = null; private boolean noSecurityFlag = false; private static boolean cmdLineTestFlag = false; /** * The list of valid URLs passed in to AppletViewer. */ private static Vector urlList = new Vector<>(1); // This is used in init(). Getting rid of this is desirable but depends // on whether the property that uses it is necessary/standard. public static final String theVersion = System.getProperty("java.version"); /** * The main entry point into AppletViewer. */ public static void main(String [] args) { Main m = new Main(); int ret = m.run(args); // Exit immediately if we got some sort of error along the way. // For debugging purposes, if we have passed in "-XcmdLineTest" we // force a premature exit. if ((ret != 0) || (cmdLineTestFlag)) System.exit(ret); } private int run(String [] args) { // DECODE ARGS try { System.err.println(lookup("deprecated")); System.err.flush(); if (args.length == 0) { usage(); return 0; } for (int i = 0; i < args.length; ) { int j = decodeArg(args, i); if (j == 0) { throw new ParseException(lookup("main.err.unrecognizedarg", args[i])); } i += j; } } catch (ParseException e) { System.err.println(e.getMessage()); return 1; } // CHECK ARGUMENTS if (helpFlag) { usage(); return 0; } if (urlList.size() == 0) { System.err.println(lookup("main.err.inputfile")); return 1; } // INSTALL THE SECURITY MANAGER (if necessary) if (!noSecurityFlag && (System.getSecurityManager() == null)) init(); // LAUNCH APPLETVIEWER FOR EACH URL for (int i = 0; i < urlList.size(); i++) { try { // XXX 5/17 this parsing method should be changed/fixed so that // it doesn't do both parsing of the html file and launching of // the AppletPanel AppletViewer.parse(urlList.elementAt(i), encoding); } catch (IOException e) { System.err.println(lookup("main.err.io", e.getMessage())); return 1; } } return 0; } private static void usage() { System.out.println(lookup("usage")); } /** * Decode a single argument in an array and return the number of elements * used. * * @param args The array of arguments. * @param i The argument to decode. * @return The number of array elements used when the argument was * decoded. * @exception ParseException * Thrown when there is a problem with something in the * argument array. */ private int decodeArg(String [] args, int i) throws ParseException { String arg = args[i]; int argc = args.length; if ("-help".equalsIgnoreCase(arg) || "-?".equals(arg)) { helpFlag = true; return 1; } else if ("-encoding".equals(arg) && (i < argc - 1)) { if (encoding != null) throw new ParseException(lookup("main.err.dupoption", arg)); encoding = args[++i]; return 2; } else if ("-Xnosecurity".equals(arg)) { // This is an undocumented (and, in the future, unsupported) // flag which prevents AppletViewer from installing its own // SecurityManager. System.err.println(); System.err.println(lookup("main.warn.nosecmgr")); System.err.println(); noSecurityFlag = true; return 1; } else if ("-XcmdLineTest".equals(arg)) { // This is an internal flag which should be used for command-line // testing. It instructs AppletViewer to force a premature exit // immediately after the applet has been launched. cmdLineTestFlag = true; return 1; } else if (arg.startsWith("-")) { throw new ParseException(lookup("main.err.unsupportedopt", arg)); } else { // we found what we hope is a url URL url = parseURL(arg); if (url != null) { urlList.addElement(url); return 1; } } return 0; } /** * Following the relevant RFC, construct a valid URL based on the passed in * string. * * @param url a string which represents either a relative or absolute URL. * @return a URL when the passed in string can be interpreted according * to the RFC, {@code null} otherwise. * @exception ParseException * Thrown when we are unable to construct a proper URL from the * passed in string. */ private URL parseURL(String url) throws ParseException { URL u = null; // prefix of the urls with 'file' scheme String prefix = "file:"; try { if (url.indexOf(':') <= 1) { // appletviewer accepts only unencoded filesystem paths u = ParseUtil.fileToEncodedURL(new File(url)); } else if (url.startsWith(prefix) && url.length() != prefix.length() && !(new File(url.substring(prefix.length())).isAbsolute())) { // relative file URL, like this "file:index.html" // ensure that this file URL is absolute // ParseUtil.fileToEncodedURL should be done last (see 6329251) String path = ParseUtil.fileToEncodedURL(new File(System.getProperty("user.dir"))).getPath() + url.substring(prefix.length()); u = new URL("file", "", path); } else { // appletviewer accepts only encoded urls u = new URL(url); } } catch (MalformedURLException e) { throw new ParseException(lookup("main.err.badurl", url, e.getMessage())); } return u; } private void init() { // GET APPLETVIEWER USER-SPECIFIC PROPERTIES Properties avProps = getAVProps(); // ADD OTHER RANDOM PROPERTIES // XXX 5/18 need to revisit why these are here, is there some // standard for what is available? // Standard browser properties avProps.put("browser", "sun.applet.AppletViewer"); avProps.put("browser.version", "1.06"); avProps.put("browser.vendor", "Oracle Corporation"); avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion); // Define which packages can be extended by applets // XXX 5/19 probably not needed, not checked in AppletSecurity avProps.put("package.restrict.definition.java", "true"); avProps.put("package.restrict.definition.sun", "true"); // Define which properties can be read by applets. // A property named by "key" can be read only when its twin // property "key.applet" is true. The following ten properties // are open by default. Any other property can be explicitly // opened up by the browser user by calling appletviewer with // -J-Dkey.applet=true avProps.put("java.version.applet", "true"); avProps.put("java.vendor.applet", "true"); avProps.put("java.vendor.url.applet", "true"); avProps.put("java.class.version.applet", "true"); avProps.put("os.name.applet", "true"); avProps.put("os.version.applet", "true"); avProps.put("os.arch.applet", "true"); avProps.put("file.separator.applet", "true"); avProps.put("path.separator.applet", "true"); avProps.put("line.separator.applet", "true"); // Read in the System properties. If something is going to be // over-written, warn about it. Properties sysProps = System.getProperties(); for (Enumeration e = sysProps.propertyNames(); e.hasMoreElements(); ) { String key = (String) e.nextElement(); String val = sysProps.getProperty(key); String oldVal; if ((oldVal = (String) avProps.setProperty(key, val)) != null) System.err.println(lookup("main.warn.prop.overwrite", key, oldVal, val)); } // INSTALL THE PROPERTY LIST System.setProperties(avProps); // Create and install the security manager if (!noSecurityFlag) { System.setSecurityManager(new AppletSecurity()); } else { System.err.println(lookup("main.nosecmgr")); } // REMIND: Create and install a socket factory! } /** * Read the AppletViewer user-specific properties. Typically, these * properties should reside in the file $USER/.appletviewer. If this file * does not exist, one will be created. Information for this file will * be gleaned from $USER/.hotjava/properties. If that file does not exist, * then default values will be used. * * @return A Properties object containing all of the AppletViewer * user-specific properties. */ private Properties getAVProps() { Properties avProps = new Properties(); File dotAV = theUserPropertiesFile; if (dotAV.exists()) { // we must have already done the conversion if (dotAV.canRead()) { // just read the file avProps = getAVProps(dotAV); } else { // send out warning and use defaults System.err.println(lookup("main.warn.cantreadprops", dotAV.toString())); avProps = setDefaultAVProps(); } } else { // create the $USER/.appletviewer file // see if $USER/.hotjava/properties exists File userHome = new File(System.getProperty("user.home")); File dotHJ = new File(userHome, ".hotjava"); dotHJ = new File(dotHJ, "properties"); if (dotHJ.exists()) { // just read the file avProps = getAVProps(dotHJ); } else { // send out warning and use defaults System.err.println(lookup("main.warn.cantreadprops", dotHJ.toString())); avProps = setDefaultAVProps(); } // SAVE THE FILE try (FileOutputStream out = new FileOutputStream(dotAV)) { avProps.store(out, lookup("main.prop.store")); } catch (IOException e) { System.err.println(lookup("main.err.prop.cantsave", dotAV.toString())); } } return avProps; } /** * Set the AppletViewer user-specific properties to be the default values. * * @return A Properties object containing all of the AppletViewer * user-specific properties, set to the default values. */ private Properties setDefaultAVProps() { Properties avProps = new Properties(); for (int i = 0; i < avDefaultUserProps.length; i++) { avProps.setProperty(avDefaultUserProps[i][0], avDefaultUserProps[i][1]); } return avProps; } /** * Given a file, find only the properties that are setable by AppletViewer. * * @param inFile A Properties file from which we select the properties of * interest. * @return A Properties object containing all of the AppletViewer * user-specific properties. */ private Properties getAVProps(File inFile) { Properties avProps = new Properties(); // read the file Properties tmpProps = new Properties(); try (FileInputStream in = new FileInputStream(inFile)) { tmpProps.load(new BufferedInputStream(in)); } catch (IOException e) { System.err.println(lookup("main.err.prop.cantread", inFile.toString())); } // pick off the properties we care about for (int i = 0; i < avDefaultUserProps.length; i++) { String value = tmpProps.getProperty(avDefaultUserProps[i][0]); if (value != null) { // the property exists in the file, so replace the default avProps.setProperty(avDefaultUserProps[i][0], value); } else { // just use the default avProps.setProperty(avDefaultUserProps[i][0], avDefaultUserProps[i][1]); } } return avProps; } /** * Methods for easier i18n handling. */ private static String lookup(String key) { return amh.getMessage(key); } private static String lookup(String key, String arg0) { return amh.getMessage(key, arg0); } private static String lookup(String key, String arg0, String arg1) { return amh.getMessage(key, arg0, arg1); } private static String lookup(String key, String arg0, String arg1, String arg2) { return amh.getMessage(key, arg0, arg1, arg2); } @SuppressWarnings("serial") // JDK implementation class class ParseException extends RuntimeException { public ParseException(String msg) { super(msg); } public ParseException(Throwable t) { super(t.getMessage()); this.t = t; } Throwable t = null; } }