Mercurial > hg > release > icedtea-web-1.7
changeset 1474:67fa5af65e7f
autoformatted: netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java and netx/net/sourceforge/jnlp/Parser.java
author | Jiri Vanek <jvanek@redhat.com> |
---|---|
date | Fri, 02 Mar 2018 10:18:08 +0100 |
parents | dbb8dc397d15 |
children | 385bbdb0c185 |
files | ChangeLog netx/net/sourceforge/jnlp/Parser.java netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java |
diffstat | 3 files changed, 775 insertions(+), 629 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Dec 18 13:22:51 2017 +0100 +++ b/ChangeLog Fri Mar 02 10:18:08 2018 +0100 @@ -1,3 +1,10 @@ +2018-02-03 Jiri Vanek <jvanek@redhat.com> + + * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: autoformatted + +2018-02-03 Jiri Vanek <jvanek@redhat.com> + * netx/net/sourceforge/jnlp/Parser.java: auto-formatted + 2017-12-15 Jiri Vanek <jvanek@redhat.com> Post-release changes
--- a/netx/net/sourceforge/jnlp/Parser.java Mon Dec 18 13:22:51 2017 +0100 +++ b/netx/net/sourceforge/jnlp/Parser.java Fri Mar 02 10:18:08 2018 +0100 @@ -14,7 +14,6 @@ // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - package net.sourceforge.jnlp; import static net.sourceforge.jnlp.runtime.Translator.R; @@ -33,26 +32,25 @@ import net.sourceforge.jnlp.util.logging.OutputController; /** - * Contains methods to parse an XML document into a JNLPFile. - * Implements JNLP specification version 1.0. + * Contains methods to parse an XML document into a JNLPFile. Implements JNLP + * specification version 1.0. * - * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author + * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell + * (JAM)</a> - initial author * @version $Revision: 1.13 $ */ public final class Parser { - + private static String CODEBASE = "codebase"; private static String MAINCLASS = "main-class"; private static final Pattern anyWhiteSpace = Pattern.compile("\\s"); // defines netx.jnlp.Node class if using Tiny XML or Nano XML - // Currently uses the Nano XML parse. Search for "SAX" or // "TINY" or "NANO" and uncomment those blocks and comment the // active ones (if any) to switch XML parsers. Also // (un)comment appropriate Node class at end of this file and // do a clean build. - /** * Ensure consistent error handling. */ @@ -69,66 +67,81 @@ OutputController.getLogger().log(OutputController.Level.ERROR_ALL, exception); } }; - */ - + */ // fix: some descriptors need to use the jnlp file at a later // date and having file ref lets us pass it to their // constructors // - /** the file reference */ + /** + * the file reference + */ private final JNLPFile file; // do not use (uninitialized) - /** the root node */ + /** + * the root node + */ private final Node root; - /** the specification version */ + /** + * the specification version + */ private final Version spec; - /** the base URL that all hrefs are relative to */ + /** + * the base URL that all hrefs are relative to + */ private final URL base; - /** the codebase URL */ + /** + * the codebase URL + */ private URL codebase; - /** the file URL */ + /** + * the file URL + */ private final URL fileLocation; - /** whether to throw errors on non-fatal errors. */ + /** + * whether to throw errors on non-fatal errors. + */ private final boolean strict; // if strict==true parses a file with no error then strict==false should also - /** whether to allow extensions to the JNLP specification */ + /** + * whether to allow extensions to the JNLP specification + */ private final boolean allowExtensions; // true if extensions to JNLP spec are ok - + /** - * Create a parser for the JNLP file. If the location - * parameters is not null it is used as the default codebase - * (does not override value of jnlp element's href - * attribute). + * Create a parser for the JNLP file. If the location parameters is not null + * it is used as the default codebase (does not override value of jnlp + * element's href attribute). * <p> - * The root node may be normalized as a side effect of this - * constructor. + * The root node may be normalized as a side effect of this constructor. * </p> + * * @param file the (uninitialized) file reference - * @param base if codebase is not specified, a default base for relative URLs + * @param base if codebase is not specified, a default base for relative + * URLs * @param root the root node * @param settings the parser settings to use when parsing the JNLP file * @throws ParseException if the JNLP file is invalid */ Parser(JNLPFile file, URL base, Node root, ParserSettings settings) throws ParseException { - this(file, base, root, settings, null); + this(file, base, root, settings, null); } /** - * Create a parser for the JNLP file. If the location - * parameters is not null it is used as the default codebase - * (does not override value of jnlp element's href - * attribute). + * Create a parser for the JNLP file. If the location parameters is not null + * it is used as the default codebase (does not override value of jnlp + * element's href attribute). * <p> - * The root node may be normalized as a side effect of this - * constructor. + * The root node may be normalized as a side effect of this constructor. * </p> + * * @param file the (uninitialized) file reference - * @param base if codebase is not specified, a default base for relative URLs + * @param base if codebase is not specified, a default base for relative + * URLs * @param root the root node * @param settings the parser settings to use when parsing the JNLP file * @param codebase codebase to use if we did not parse one from JNLP file. @@ -141,8 +154,9 @@ this.allowExtensions = settings.isExtensionAllowed(); // ensure it's a JNLP node - if (root == null || !root.getNodeName().equals("jnlp")) + if (root == null || !root.getNodeName().equals("jnlp")) { throw new ParseException(R("PInvalidRoot")); + } // JNLP tag information this.spec = getVersion(root, "spec", "1.0+"); @@ -154,7 +168,9 @@ } if (this.codebase == null) // Codebase is overwritten if codebase was not specified in file or if parsing of it failed + { this.codebase = codebase; + } this.base = (this.codebase != null) ? this.codebase : base; // if codebase not specified use default codebase fileLocation = getURL(root, "href", this.base); @@ -165,6 +181,7 @@ /** * Returns the file version. + * * @return version of file */ public Version getFileVersion() { @@ -173,6 +190,7 @@ /** * Returns the file location. + * * @return url of source file */ public URL getFileLocation() { @@ -188,7 +206,7 @@ /** * @return the specification version. - * + * */ public Version getSpecVersion() { return spec; @@ -254,10 +272,9 @@ // // This section loads the resources elements // - /** - * @return all of the ResourcesDesc elements under the specified - * node (jnlp or j2se). + * @return all of the ResourcesDesc elements under the specified node (jnlp + * or j2se). * * @param parent the parent node (either jnlp or j2se) * @param j2se true if the resources are located under a j2se or java node @@ -285,15 +302,15 @@ * @param j2se true if the resources are located under a j2se or java node * @throws ParseException if the JNLP file is invalid */ - private ResourcesDesc getResourcesDesc(Node node, boolean j2se) throws ParseException { + private ResourcesDesc getResourcesDesc(Node node, boolean j2se) throws ParseException { boolean mainFlag = false; // if found a main tag // create resources - ResourcesDesc resources = - new ResourcesDesc(file, - getLocales(node), - splitString(getAttribute(node, "os", null)), - splitString(getAttribute(node, "arch", null))); + ResourcesDesc resources + = new ResourcesDesc(file, + getLocales(node), + splitString(getAttribute(node, "os", null)), + splitString(getAttribute(node, "arch", null))); // step through the elements Node child = node.getFirstChild(); @@ -301,18 +318,23 @@ String name = child.getNodeName(); // check for nativelib but no trusted environment - if ("nativelib".equals(name)) - if (!isTrustedEnvironment()) + if ("nativelib".equals(name)) { + if (!isTrustedEnvironment()) { throw new ParseException(R("PUntrustedNative")); + } + } if ("j2se".equals(name) || "java".equals(name)) { - if (getChildNode(root, "component-desc") != null) - if (strict) + if (getChildNode(root, "component-desc") != null) { + if (strict) { throw new ParseException(R("PExtensionHasJ2SE")); - if (!j2se) + } + } + if (!j2se) { resources.addResource(getJRE(child)); - else + } else { throw new ParseException(R("PInnerJ2SE")); + } } if ("jar".equals(name) || "nativelib".equals(name)) { @@ -331,14 +353,17 @@ resources.addResource(jar); } - if ("extension".equals(name)) + if ("extension".equals(name)) { resources.addResource(getExtension(child)); + } - if ("property".equals(name)) + if ("property".equals(name)) { resources.addResource(getProperty(child)); + } - if ("package".equals(name)) + if ("package".equals(name)) { resources.addResource(getPackage(child)); + } child = child.getNextSibling(); } @@ -385,9 +410,11 @@ boolean main = "true".equals(getAttribute(node, "main", "false")); boolean lazy = "lazy".equals(getAttribute(node, "download", "eager")); - if (nativeJar && main) - if (strict) + if (nativeJar && main) { + if (strict) { throw new ParseException(R("PNativeHasMain")); + } + } return new JARDesc(location, version, part, lazy, main, nativeJar, true); @@ -445,14 +472,15 @@ // // This section loads the information elements // - /** * Make sure a title and vendor are present and nonempty and localized as * best matching as possible for the JVM's current locale. Fallback to a - * generalized title and vendor otherwise. If none is found, throw an exception. + * generalized title and vendor otherwise. If none is found, throw an + * exception. * - * Additionally prints homepage, description, title and vendor to stdout - * if in Debug mode. + * Additionally prints homepage, description, title and vendor to stdout if + * in Debug mode. + * * @throws RequiredElementException */ void checkForInformation() throws RequiredElementException { @@ -462,18 +490,21 @@ String title = file.getTitle(); String vendor = file.getVendor(); - if (title == null || title.trim().isEmpty()) + if (title == null || title.trim().isEmpty()) { throw new MissingTitleException(); - else OutputController.getLogger().log("Acceptable title tag found, contains: " + title); + } else { + OutputController.getLogger().log("Acceptable title tag found, contains: " + title); + } - if (vendor == null || vendor.trim().isEmpty()) + if (vendor == null || vendor.trim().isEmpty()) { throw new MissingVendorException(); - else OutputController.getLogger().log("Acceptable vendor tag found, contains: " + vendor); + } else { + OutputController.getLogger().log("Acceptable vendor tag found, contains: " + vendor); + } } /** - * @return all of the information elements under the specified - * node. + * @return all of the information elements under the specified node. * * @param parent the parent node (jnlp) * @throws ParseException if the JNLP file is invalid @@ -484,8 +515,9 @@ Node info[] = getChildNodes(parent, "information"); // ensure that there are at least one information section present - if (info.length == 0) + if (info.length == 0) { throw new MissingInformationException(); + } // create objects from the info sections for (Node infoNode : info) { @@ -501,7 +533,7 @@ * @param node the information node * @throws ParseException if the JNLP file is invalid */ - InformationDesc getInformationDesc(Node node) throws ParseException { + InformationDesc getInformationDesc(Node node) throws ParseException { List<String> descriptionsUsed = new ArrayList<>(); // locale @@ -515,28 +547,36 @@ while (child != null) { String name = child.getNodeName(); - if ("title".equals(name)) + if ("title".equals(name)) { addInfo(info, child, null, getSpanText(child, false)); - if ("vendor".equals(name)) + } + if ("vendor".equals(name)) { addInfo(info, child, null, getSpanText(child, false)); + } if ("description".equals(name)) { String kind = getAttribute(child, "kind", "default"); - if (descriptionsUsed.contains(kind)) - if (strict) + if (descriptionsUsed.contains(kind)) { + if (strict) { throw new ParseException(R("PTwoDescriptions", kind)); + } + } descriptionsUsed.add(kind); addInfo(info, child, kind, getSpanText(child, false)); } - if ("homepage".equals(name)) + if ("homepage".equals(name)) { addInfo(info, child, null, getRequiredURL(child, "href", base)); - if ("icon".equals(name)) + } + if ("icon".equals(name)) { addInfo(info, child, getAttribute(child, "kind", "default"), getIcon(child)); - if ("offline-allowed".equals(name)) + } + if ("offline-allowed".equals(name)) { addInfo(info, child, null, Boolean.TRUE); + } if ("sharing-allowed".equals(name)) { - if (strict && !allowExtensions) + if (strict && !allowExtensions) { throw new ParseException(R("PSharing")); + } addInfo(info, child, null, Boolean.TRUE); } if ("association".equals(name)) { @@ -566,8 +606,9 @@ protected void addInfo(InformationDesc info, Node node, String mod, Object value) { String modStr = (mod == null) ? "" : "-" + mod; - if (node == null) + if (node == null) { return; + } info.addItem(node.getNodeName() + modStr, value); } @@ -592,11 +633,10 @@ // // This section loads the security descriptor element // - /** - * @return the security descriptor element. If no security - * element was specified in the JNLP file then a SecurityDesc - * with applet permissions is returned. + * @return the security descriptor element. If no security element was + * specified in the JNLP file then a SecurityDesc with applet permissions is + * returned. * * @param parent the parent node * @throws ParseException if the JNLP file is invalid @@ -605,9 +645,11 @@ Node nodes[] = getChildNodes(parent, "security"); // test for too many security elements - if (nodes.length > 1) - if (strict) + if (nodes.length > 1) { + if (strict) { throw new ParseException(R("PTwoSecurity")); + } + } Object type = SecurityDesc.SANDBOX_PERMISSIONS; RequestedPermissionLevel requestedPermissionLevel = RequestedPermissionLevel.NONE; @@ -633,16 +675,17 @@ } /** - * Returns whether the JNLP file requests a trusted execution - * environment. + * Returns whether the JNLP file requests a trusted execution environment. */ private boolean isTrustedEnvironment() { Node security = getChildNode(root, "security"); - if (security != null) + if (security != null) { if (getChildNode(security, "all-permissions") != null - || getChildNode(security, "j2ee-application-client-permissions") != null) + || getChildNode(security, "j2ee-application-client-permissions") != null) { return true; + } + } return false; } @@ -650,7 +693,6 @@ // // This section loads the launch descriptor element // - /** * @return the launch descriptor element, either AppletDesc, * ApplicationDesc, or InstallerDesc. @@ -662,19 +704,23 @@ // check for other than one application type if (1 < getChildNodes(parent, "applet-desc").length + getChildNodes(parent, "application-desc").length - + getChildNodes(parent, "installer-desc").length) + + getChildNodes(parent, "installer-desc").length) { throw new ParseException(R("PTwoDescriptors")); + } Node child = parent.getFirstChild(); while (child != null) { String name = child.getNodeName(); - if ("applet-desc".equals(name)) + if ("applet-desc".equals(name)) { return getApplet(child); - if ("application-desc".equals(name)) + } + if ("application-desc".equals(name)) { return getApplication(child); - if ("installer-desc".equals(name)) + } + if ("installer-desc".equals(name)) { return getInstaller(child); + } child = child.getNextSibling(); } @@ -701,8 +747,9 @@ width = Integer.parseInt(getRequiredAttribute(node, "width", "100")); height = Integer.parseInt(getRequiredAttribute(node, "height", "100")); } catch (NumberFormatException nfe) { - if (width <= 0) + if (width <= 0) { throw new ParseException(R("PBadWidth")); + } throw new ParseException(R("PBadWidth")); } @@ -727,7 +774,6 @@ // if (main == null) // only ok if can be found in main jar file (can't check here but make a note) - // read parameters Node args[] = getChildNodes(node, "argument"); for (Node arg : args) { @@ -756,8 +802,9 @@ while (child != null) { String name = child.getNodeName(); - if ("component-desc".equals(name)) + if ("component-desc".equals(name)) { return new ComponentDesc(); + } child = child.getNextSibling(); } @@ -803,17 +850,21 @@ while (child != null) { String name = child.getNodeName(); - if (null != name) switch (name) { - case "desktop": - if (showOnDesktop && strict) { - throw new ParseException(R("PTwoDesktops")); - } showOnDesktop = true; - break; - case "menu": - if (menu != null && strict) { - throw new ParseException(R("PTwoMenus")); - } menu = getMenu(child); - break; + if (null != name) { + switch (name) { + case "desktop": + if (showOnDesktop && strict) { + throw new ParseException(R("PTwoDesktops")); + } + showOnDesktop = true; + break; + case "menu": + if (menu != null && strict) { + throw new ParseException(R("PTwoMenus")); + } + menu = getMenu(child); + break; + } } child = child.getNextSibling(); @@ -852,22 +903,27 @@ while (child != null) { String name = child.getNodeName(); - if (null != name) switch (name) { - case "title": - if (title != null && strict) { - throw new ParseException(R("PTwoTitles")); - } title = getSpanText(child, false); - break; - case "description": - if (description != null && strict) { - throw new ParseException(R("PTwoDescriptions")); - } description = getSpanText(child, false); - break; - case "icon": - if (icon != null && strict) { - throw new ParseException(R("PTwoIcons")); - } icon = getIcon(child); - break; + if (null != name) { + switch (name) { + case "title": + if (title != null && strict) { + throw new ParseException(R("PTwoTitles")); + } + title = getSpanText(child, false); + break; + case "description": + if (description != null && strict) { + throw new ParseException(R("PTwoDescriptions")); + } + description = getSpanText(child, false); + break; + case "icon": + if (icon != null && strict) { + throw new ParseException(R("PTwoIcons")); + } + icon = getIcon(child); + break; + } } child = child.getNextSibling(); @@ -883,16 +939,16 @@ } // other methods - /** - * @return an array of substrings seperated by spaces (spaces - * escaped with backslash do not separate strings). This method - * splits strings as per the spec except that it does replace - * escaped other characters with their own value. + * @return an array of substrings seperated by spaces (spaces escaped with + * backslash do not separate strings). This method splits strings as per the + * spec except that it does replace escaped other characters with their own + * value. */ private String[] splitString(String source) { - if (source == null) + if (source == null) { return new String[0]; + } List<String> result = new ArrayList<String>(); StringTokenizer st = new StringTokenizer(source, " "); @@ -904,18 +960,20 @@ while (true) { part.append(st.nextToken()); - if (st.hasMoreTokens() && part.charAt(part.length() - 1) == '\\') + if (st.hasMoreTokens() && part.charAt(part.length() - 1) == '\\') { part.setCharAt(part.length() - 1, ' '); // join with the space - else + } else { break; // bizarre while format gets \ at end of string right (no extra space added at end) + } } // delete \ quote chars - for (int i = part.length(); i-- > 0;) - // sweet syntax for reverse loop - if (part.charAt(i) == '\\') + for (int i = part.length(); i-- > 0;) // sweet syntax for reverse loop + { + if (part.charAt(i) == '\\') { part.deleteCharAt(i--); // and skip previous char so \\ becomes \ - + } + } result.add(part.toString()); } @@ -929,13 +987,14 @@ */ private Locale[] getLocales(Node node) { List<Locale> locales = new ArrayList<>(); - String localeParts[] = - splitString(getAttribute(node, "locale", "")); + String localeParts[] + = splitString(getAttribute(node, "locale", "")); for (String localePart : localeParts) { Locale l = getLocale(localePart); - if (l != null) + if (l != null) { locales.add(l); + } } return locales.toArray(new Locale[locales.size()]); @@ -948,8 +1007,9 @@ * @return locale of document */ public Locale getLocale(String localeStr) { - if (localeStr.length() < 2) + if (localeStr.length() < 2) { return null; + } String language = localeStr.substring(0, 2); String country = (localeStr.length() < 5) ? "" : localeStr.substring(3, 5); @@ -965,7 +1025,7 @@ * "<description>text</description>". * * @param node the node with text under it - * @return + * @return * @throws ParseException if the JNLP file is invalid */ private String getSpanText(Node node) throws ParseException { @@ -974,9 +1034,9 @@ /** * Returns the implied text under a node, for example "text" in - * "<description>text</description>". If preserveSpacing is false, - * sequences of whitespace characters are turned into a single - * space character. + * "<description>text</description>". If preserveSpacing is + * false, sequences of whitespace characters are turned into a single space + * character. * * @param node the node with text under it * @param preserveSpacing if true, preserve whitespace @@ -984,19 +1044,18 @@ */ private String getSpanText(Node node, boolean preserveSpacing) throws ParseException { - if (node == null) + if (node == null) { return null; + } // NANO String val = node.getNodeValue(); if (preserveSpacing) { return val; + } else if (val == null) { + return null; } else { - if (val == null) { - return null; - } else { - return val.replaceAll("\\s+", " "); - } + return val.replaceAll("\\s+", " "); } /* TINY @@ -1011,7 +1070,7 @@ } return child.getNodeValue(); - */ + */ } /** @@ -1019,10 +1078,11 @@ */ private static Node getChildNode(Node node, String name) { Node[] result = getChildNodes(node, name); - if (result.length == 0) + if (result.length == 0) { return null; - else + } else { return result[0]; + } } /** @@ -1033,8 +1093,9 @@ Node child = node.getFirstChild(); while (child != null) { - if (child.getNodeName().equals(name)) + if (child.getNodeName().equals(name)) { result.add(child); + } child = child.getNextSibling(); } @@ -1042,12 +1103,13 @@ } /** - * Returns a URL with a trailing / appended to it if there is no - * trailing slash on the specifed URL. + * Returns a URL with a trailing / appended to it if there is no trailing + * slash on the specifed URL. */ private URL addSlash(URL source) { - if (source == null) + if (source == null) { return null; + } if (!source.toString().endsWith("/")) { try { @@ -1060,8 +1122,8 @@ } /** - * @return the same result as getURL except that a - * ParseException is thrown if the attribute is null or empty. + * @return the same result as getURL except that a ParseException is thrown + * if the attribute is null or empty. * * @param node the node * @param name the attribute containing an href @@ -1077,10 +1139,9 @@ } /** - * @return a URL object from a href string relative to the - * code base. If the href denotes a relative URL, it must - * reference a location that is a subdirectory of the - * codebase. + * @return a URL object from a href string relative to the code base. If the + * href denotes a relative URL, it must reference a location that is a + * subdirectory of the codebase. * * @param node the node * @param name the attribute containing an href @@ -1101,15 +1162,15 @@ } return getURL(href, node.getNodeName(), base, strict); } - + public static URL getURL(String href, String nodeName, URL base, boolean strict) throws ParseException { - if (href == null) { + if (href == null) { return null; // so that code can throw an exception if attribute was required } try { - if (base == null) + if (base == null) { return new URL(href); - else { + } else { try { return new URL(href); } catch (MalformedURLException ex) { @@ -1119,7 +1180,7 @@ URL result = new URL(base, href); // check for going above the codebase - if (!result.toString().startsWith(base.toString()) && !base.toString().startsWith(result.toString())){ + if (!result.toString().startsWith(base.toString()) && !base.toString().startsWith(result.toString())) { if (strict) { throw new ParseException(R("PUrlNotInCodebase", nodeName, href, base)); } @@ -1128,16 +1189,16 @@ } } catch (MalformedURLException ex) { - if (base == null) + if (base == null) { throw new ParseException(R("PBadNonrelativeUrl", nodeName, href)); - else + } else { throw new ParseException(R("PBadRelativeUrl", nodeName, href, base)); + } } } /** - * @return a Version from the specified attribute and default - * value. + * @return a Version from the specified attribute and default value. * * @param node the node * @param name the attribute @@ -1146,14 +1207,16 @@ */ private Version getVersion(Node node, String name, String defaultValue) { String version = getAttribute(node, name, defaultValue); - if (version == null) + if (version == null) { return null; - else + } else { return new Version(version); + } } /** * Check that the VM args are valid and safe + * * @param vmArgs a string containing the args * @throws ParseException if the VM arguments are invalid or dangerous */ @@ -1191,76 +1254,75 @@ /** * Returns an array of valid (ie safe and supported) arguments for the JVM * - * Based on http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html + * Based on + * http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html */ private String[] getValidVMArguments() { - return new String[] { - "-d32", /* use a 32-bit data model if available */ - "-client", /* to select the client VM */ - "-server", /* to select the server VM */ - "-verbose", /* enable verbose output */ - "-version", /* print product version and exit */ - "-showversion", /* print product version and continue */ - "-help", /* print this help message */ - "-X", /* print help on non-standard options */ - "-ea", /* enable assertions */ - "-enableassertions", /* enable assertions */ - "-da", /* disable assertions */ - "-disableassertions", /* disable assertions */ - "-esa", /* enable system assertions */ - "-enablesystemassertions", /* enable system assertions */ - "-dsa", /* disable system assertione */ - "-disablesystemassertions", /* disable system assertione */ - "-Xmixed", /* mixed mode execution (default) */ - "-Xint", /* interpreted mode execution only */ - "-Xnoclassgc", /* disable class garbage collection */ - "-Xincgc", /* enable incremental garbage collection */ - "-Xbatch", /* disable background compilation */ - "-Xprof", /* output cpu profiling data */ - "-Xdebug", /* enable remote debugging */ - "-Xfuture", /* enable strictest checks, anticipating future default */ - "-Xrs", /* reduce use of OS signals by Java/VM (see documentation) */ - "-XX:+ForceTimeHighResolution", /* use high resolution timer */ - "-XX:-ForceTimeHighResolution", /* use low resolution (default) */ - }; + return new String[]{ + "-d32", /* use a 32-bit data model if available */ + "-client", /* to select the client VM */ + "-server", /* to select the server VM */ + "-verbose", /* enable verbose output */ + "-version", /* print product version and exit */ + "-showversion", /* print product version and continue */ + "-help", /* print this help message */ + "-X", /* print help on non-standard options */ + "-ea", /* enable assertions */ + "-enableassertions", /* enable assertions */ + "-da", /* disable assertions */ + "-disableassertions", /* disable assertions */ + "-esa", /* enable system assertions */ + "-enablesystemassertions", /* enable system assertions */ + "-dsa", /* disable system assertione */ + "-disablesystemassertions", /* disable system assertione */ + "-Xmixed", /* mixed mode execution (default) */ + "-Xint", /* interpreted mode execution only */ + "-Xnoclassgc", /* disable class garbage collection */ + "-Xincgc", /* enable incremental garbage collection */ + "-Xbatch", /* disable background compilation */ + "-Xprof", /* output cpu profiling data */ + "-Xdebug", /* enable remote debugging */ + "-Xfuture", /* enable strictest checks, anticipating future default */ + "-Xrs", /* reduce use of OS signals by Java/VM (see documentation) */ + "-XX:+ForceTimeHighResolution", /* use high resolution timer */ + "-XX:-ForceTimeHighResolution", /* use low resolution (default) */}; } /** * Returns an array containing the starts of valid (ie safe and supported) * arguments for the JVM * - * Based on http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html + * Based on + * http://java.sun.com/javase/6/docs/technotes/guides/javaws/developersguide/syntax.html */ private String[] getValidStartingVMArguments() { - return new String[] { - "-ea", /* enable assertions for classes */ - "-enableassertions", /* enable assertions for classes */ - "-da", /* disable assertions for classes */ - "-disableassertions", /* disable assertions for classes */ - "-verbose", /* enable verbose output */ - "-Xms", /* set initial Java heap size */ - "-Xmx", /* set maximum Java heap size */ - "-Xss", /* set java thread stack size */ - "-XX:NewRatio", /* set Ratio of new/old gen sizes */ - "-XX:NewSize", /* set initial size of new generation */ - "-XX:MaxNewSize", /* set max size of new generation */ - "-XX:PermSize", /* set initial size of permanent gen */ - "-XX:MaxPermSize", /* set max size of permanent gen */ - "-XX:MaxHeapFreeRatio", /* heap free percentage (default 70) */ - "-XX:MinHeapFreeRatio", /* heap free percentage (default 40) */ - "-XX:UseSerialGC", /* use serial garbage collection */ - "-XX:ThreadStackSize", /* thread stack size (in KB) */ - "-XX:MaxInlineSize", /* set max num of bytecodes to inline */ - "-XX:ReservedCodeCacheSize", /* Reserved code cache size (bytes) */ - "-XX:MaxDirectMemorySize", - - }; + return new String[]{ + "-ea", /* enable assertions for classes */ + "-enableassertions", /* enable assertions for classes */ + "-da", /* disable assertions for classes */ + "-disableassertions", /* disable assertions for classes */ + "-verbose", /* enable verbose output */ + "-Xms", /* set initial Java heap size */ + "-Xmx", /* set maximum Java heap size */ + "-Xss", /* set java thread stack size */ + "-XX:NewRatio", /* set Ratio of new/old gen sizes */ + "-XX:NewSize", /* set initial size of new generation */ + "-XX:MaxNewSize", /* set max size of new generation */ + "-XX:PermSize", /* set initial size of permanent gen */ + "-XX:MaxPermSize", /* set max size of permanent gen */ + "-XX:MaxHeapFreeRatio", /* heap free percentage (default 70) */ + "-XX:MinHeapFreeRatio", /* heap free percentage (default 40) */ + "-XX:UseSerialGC", /* use serial garbage collection */ + "-XX:ThreadStackSize", /* thread stack size (in KB) */ + "-XX:MaxInlineSize", /* set max num of bytecodes to inline */ + "-XX:ReservedCodeCacheSize", /* Reserved code cache size (bytes) */ + "-XX:MaxDirectMemorySize",}; } /** - * @return the same result as getAttribute except that if strict - * mode is enabled or the default value is null a parse - * exception is thrown instead of returning the default value. + * @return the same result as getAttribute except that if strict mode is + * enabled or the default value is null a parse exception is thrown instead + * of returning the default value. * * @param node the node * @param name the attribute @@ -1270,19 +1332,22 @@ private String getRequiredAttribute(Node node, String name, String defaultValue) throws ParseException { String result = getAttribute(node, name, null); - if (result == null || result.length() == 0) - if (strict || defaultValue == null) + if (result == null || result.length() == 0) { + if (strict || defaultValue == null) { throw new ParseException(R("PNeedsAttribute", node.getNodeName(), name)); + } + } - if (result == null) + if (result == null) { return defaultValue; - else + } else { return result; + } } /** - * @return an attribute or the specified defaultValue if there is - * no such attribute. + * @return an attribute or the specified defaultValue if there is no such + * attribute. * * @param node the node * @param name the attribute @@ -1305,12 +1370,12 @@ return result; } - public static final String MALFORMED_PARSER_CLASS = "net.sourceforge.jnlp.MalformedXMLParser"; public static final String NORMAL_PARSER_CLASS = "net.sourceforge.jnlp.XMLParser"; + /** - * @return the root node from the XML document in the specified - * input stream. + * @return the root node from the XML document in the specified input + * stream. * * @throws ParseException if the JNLP file is invalid */ @@ -1321,16 +1386,15 @@ return (Node) m.invoke(parser, input); } catch (InvocationTargetException e) { if (e.getCause() instanceof ParseException) { - throw (ParseException)(e.getCause()); + throw (ParseException) (e.getCause()); } throw new ParseException(R("PBadXML"), e); } catch (Exception e) { throw new ParseException(R("PBadXML"), e); } } - - public static Object getParserInstance(ParserSettings settings) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + public static Object getParserInstance(ParserSettings settings) throws ClassNotFoundException, IllegalAccessException, InstantiationException { String className; if (settings.isMalformedXmlAllowed()) { className = MALFORMED_PARSER_CLASS; @@ -1364,7 +1428,7 @@ return instance; } - private String getOptionalMainClass(Node node) { + private String getOptionalMainClass(Node node) { try { return getMainClass(node, false); } catch (ParseException ex) { @@ -1401,7 +1465,7 @@ OutputController.getLogger().log(OutputController.Level.MESSAGE_DEBUG, "Invlaid char in main-class: '" + main.charAt(0) + "'"); } for (int i = 1; i < main.length(); i++) { - if (main.charAt(i)=='.'){ + if (main.charAt(i) == '.') { //dot connects identifiers continue; }
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Mon Dec 18 13:22:51 2017 +0100 +++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java Fri Mar 02 10:18:08 2018 +0100 @@ -12,7 +12,6 @@ // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - package net.sourceforge.jnlp.runtime; import static net.sourceforge.jnlp.runtime.Translator.R; @@ -92,12 +91,13 @@ import net.sourceforge.jnlp.util.logging.OutputController; /** - * Classloader that takes it's resources from a JNLP file. If the - * JNLP file defines extensions, separate classloaders for these - * will be created automatically. Classes are loaded with the - * security context when the classloader was created. + * Classloader that takes it's resources from a JNLP file. If the JNLP file + * defines extensions, separate classloaders for these will be created + * automatically. Classes are loaded with the security context when the + * classloader was created. * - * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author + * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell + * (JAM)</a> - initial author * @version $Revision: 1.20 $ */ public class JNLPClassLoader extends URLClassLoader { @@ -105,12 +105,15 @@ // todo: initializePermissions should get the permissions from // extension classes too so that main file classes can load // resources in an extension. - - /** Signed JNLP File and Template */ + /** + * Signed JNLP File and Template + */ final public static String TEMPLATE = "JNLP-INF/APPLICATION_TEMPLATE.JNLP"; final public static String APPLICATION = "JNLP-INF/APPLICATION.JNLP"; - /** Actions to specify how cache is to be managed **/ + /** + * Actions to specify how cache is to be managed * + */ public static enum DownloadAction { DOWNLOAD_TO_CACHE, REMOVE_FROM_CACHE, CHECK_CACHE } @@ -119,101 +122,148 @@ FULL, PARTIAL, NONE } - /** True if the application has a signed JNLP File */ + /** + * True if the application has a signed JNLP File + */ private boolean isSignedJNLP = false; - - /** map from JNLPFile unique key to shared classloader */ + + /** + * map from JNLPFile unique key to shared classloader + */ private static Map<String, JNLPClassLoader> uniqueKeyToLoader = new ConcurrentHashMap<>(); - /** map from JNLPFile unique key to lock, the lock is needed to enforce correct - * initialization of applets that share a unique key*/ + /** + * map from JNLPFile unique key to lock, the lock is needed to enforce + * correct initialization of applets that share a unique key + */ private static Map<String, ReentrantLock> uniqueKeyToLock = new HashMap<>(); - /** Provides a search path & temporary storage for native code */ + /** + * Provides a search path & temporary storage for native code + */ private NativeLibraryStorage nativeLibraryStorage; - /** security context */ + /** + * security context + */ private final AccessControlContext acc = AccessController.getContext(); - /** the permissions for the cached jar files */ + /** + * the permissions for the cached jar files + */ private List<Permission> resourcePermissions; - /** the app */ + /** + * the app + */ private ApplicationInstance app = null; // here for faster lookup in security manager - /** list of this, local and global loaders this loader uses */ + /** + * list of this, local and global loaders this loader uses + */ private JNLPClassLoader loaders[] = null; // ..[0]==this - /** whether to strictly adhere to the spec or not */ + /** + * whether to strictly adhere to the spec or not + */ private final boolean strict; - /** loads the resources */ + /** + * loads the resources + */ private final ResourceTracker tracker = new ResourceTracker(true); // prefetch - /** the update policy for resources */ + /** + * the update policy for resources + */ private UpdatePolicy updatePolicy; - /** the JNLP file */ + /** + * the JNLP file + */ private JNLPFile file; - /** the resources section */ + /** + * the resources section + */ private ResourcesDesc resources; - /** the security section */ + /** + * the security section + */ private SecurityDesc security; - /** Permissions granted by the user during runtime. */ + /** + * Permissions granted by the user during runtime. + */ private final ArrayList<Permission> runtimePermissions = new ArrayList<>(); - /** all jars not yet part of classloader or active - * Synchronized since this field may become shared data between multiple classloading threads. - * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). + /** + * all jars not yet part of classloader or active Synchronized since this + * field may become shared data between multiple classloading threads. See + * loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). */ private final List<JARDesc> available = Collections.synchronizedList(new ArrayList<JARDesc>()); - /** the jar cert verifier tool to verify our jars */ + /** + * the jar cert verifier tool to verify our jars + */ private final JarCertVerifier jcv; private SigningState signing = SigningState.NONE; - /** ArrayList containing jar indexes for various jars available to this classloader - * Synchronized since this field may become shared data between multiple classloading threads/ - * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). + /** + * ArrayList containing jar indexes for various jars available to this + * classloader Synchronized since this field may become shared data between + * multiple classloading threads/ See loadClass(String) and + * CodebaseClassLoader.findClassNonRecursive(String). */ private final List<JarIndexAccess> jarIndexes = Collections.synchronizedList(new ArrayList<JarIndexAccess>()); - /** Set of classpath strings declared in the manifest.mf files - * Synchronized since this field may become shared data between multiple classloading threads. - * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). + /** + * Set of classpath strings declared in the manifest.mf files Synchronized + * since this field may become shared data between multiple classloading + * threads. See loadClass(String) and + * CodebaseClassLoader.findClassNonRecursive(String). */ private final Set<String> classpaths = Collections.synchronizedSet(new HashSet<String>()); - /** File entries in the jar files available to this classloader - * Synchronized sinc this field may become shared data between multiple classloading threads. - * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). + /** + * File entries in the jar files available to this classloader Synchronized + * sinc this field may become shared data between multiple classloading + * threads. See loadClass(String) and + * CodebaseClassLoader.findClassNonRecursive(String). */ private final Set<String> jarEntries = Collections.synchronizedSet(new TreeSet<String>()); - /** Map of specific original (remote) CodeSource Urls to securitydesc - * Synchronized since this field may become shared data between multiple classloading threads. - * See loadClass(String) and CodebaseClassLoader.findClassNonRecursive(String). + /** + * Map of specific original (remote) CodeSource Urls to securitydesc + * Synchronized since this field may become shared data between multiple + * classloading threads. See loadClass(String) and + * CodebaseClassLoader.findClassNonRecursive(String). */ - private final Map<URL, SecurityDesc> jarLocationSecurityMap = - Collections.synchronizedMap(new HashMap<URL, SecurityDesc>()); + private final Map<URL, SecurityDesc> jarLocationSecurityMap + = Collections.synchronizedMap(new HashMap<URL, SecurityDesc>()); /*Set to prevent once tried-to-get resources to be tried again*/ private final Set<URL> alreadyTried = Collections.synchronizedSet(new HashSet<URL>()); - - /** Loader for codebase (which is a path, rather than a file) */ + + /** + * Loader for codebase (which is a path, rather than a file) + */ private CodeBaseClassLoader codeBaseLoader; - - /** True if the jar with the main class has been found - * */ - private boolean foundMainJar= false; - - /** Name of the application's main class */ + + /** + * True if the jar with the main class has been found + * + */ + private boolean foundMainJar = false; + + /** + * Name of the application's main class + */ private String mainClass = null; - + /** * Variable to track how many times this loader is in use */ @@ -242,16 +292,18 @@ * @param file the JNLP file * @param policy the UpdatePolicy for this class loader * @param mainName name of the application's main class - * @param enableCodeBase switch whether this classloader can search in codebase or not - * @throws net.sourceforge.jnlp.LaunchException when need to kill an app comes. - * + * @param enableCodeBase switch whether this classloader can search in + * codebase or not + * @throws net.sourceforge.jnlp.LaunchException when need to kill an app + * comes. + * */ protected JNLPClassLoader(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException { super(new URL[0], JNLPClassLoader.class.getClassLoader()); OutputController.getLogger().log("New classloader: " + file.getFileLocation()); - strict = Boolean.valueOf(JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_STRICT_JNLP_CLASSLOADER)); - + strict = Boolean.valueOf(JNLPRuntime.getConfiguration().getProperty(DeploymentConfiguration.KEY_STRICT_JNLP_CLASSLOADER)); + this.file = file; this.updatePolicy = policy; this.resources = file.getResources(); @@ -262,10 +314,9 @@ this.enableCodeBase = enableCodeBase; - AppVerifier verifier; - if (file instanceof PluginBridge && !((PluginBridge)file).useJNLPHref()) { + if (file instanceof PluginBridge && !((PluginBridge) file).useJNLPHref()) { verifier = new PluginAppVerifier(); } else { verifier = new JNLPAppVerifier(); @@ -288,15 +339,12 @@ initializeReadJarPermissions(); installShutdownHooks(); - } public boolean isStrict() { return strict; } - - /** * Install JVM shutdown hooks to clean up resources allocated by this @@ -322,9 +370,9 @@ } /** - * Gets the lock for a given unique key, creating one if it does not yet exist. - * This operation is atomic & thread-safe. - * + * Gets the lock for a given unique key, creating one if it does not yet + * exist. This operation is atomic & thread-safe. + * * @param uniqueKey the file whose unique key should be used * @return the lock */ @@ -342,10 +390,10 @@ } /** - * Creates a fully initialized JNLP classloader for the specified JNLPFile, - * to be used as an applet/application's classloader. - * In contrast, JNLP classloaders can also be constructed simply to merge - * its resources into another classloader. + * Creates a fully initialized JNLP classloader for the specified JNLPFile, + * to be used as an applet/application's classloader. In contrast, JNLP + * classloaders can also be constructed simply to merge its resources into + * another classloader. * * @param file the file to load classes for * @param policy the update policy to use when downloading resources @@ -366,7 +414,7 @@ if (loader.getSigningState() == SigningState.PARTIAL) { loader.securityDelegate.promptUserOnPartialSigning(); } else if (!loader.getSigning() && !loader.securityDelegate.userPromptedForSandbox() && file instanceof PluginBridge) { - UnsignedAppletTrustConfirmation.checkUnsignedWithUserIfRequired((PluginBridge)file); + UnsignedAppletTrustConfirmation.checkUnsignedWithUserIfRequired((PluginBridge) file); } // New loader init may have caused extentions to create a @@ -384,7 +432,7 @@ // loader is now current + ext. But we also need to think of // the baseLoader if (baseLoader != null && baseLoader != loader) { - loader.merge(baseLoader); + loader.merge(baseLoader); } return loader; @@ -392,12 +440,13 @@ /** * Returns a JNLP classloader for the specified JNLP file. - * + * * @param file the file to load classes for * @param policy the update policy to use when downloading resources - * @param enableCodeBase true if codebase can be searched (ok for applets,false for apps) - * @return existing classloader. creates new if none reliable exists - * @throws net.sourceforge.jnlp.LaunchException when launch is doomed + * @param enableCodeBase true if codebase can be searched (ok for + * applets,false for apps) + * @return existing classloader. creates new if none reliable exists + * @throws net.sourceforge.jnlp.LaunchException when launch is doomed */ public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, boolean enableCodeBase) throws LaunchException { return getInstance(file, policy, null, enableCodeBase); @@ -409,22 +458,23 @@ * @param file the file to load classes for * @param policy the update policy to use when downloading resources * @param mainName Overrides the main class name of the application - * @param enableCodeBase ue if codebase can be searched (ok for applets,false for apps) - * @return existing classloader. creates new if none reliable exists - * @throws net.sourceforge.jnlp.LaunchException when launch is doomed + * @param enableCodeBase ue if codebase can be searched (ok for + * applets,false for apps) + * @return existing classloader. creates new if none reliable exists + * @throws net.sourceforge.jnlp.LaunchException when launch is doomed */ public static JNLPClassLoader getInstance(JNLPFile file, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws LaunchException { JNLPClassLoader loader; String uniqueKey = file.getUniqueKey(); - synchronized ( getUniqueKeyLock(uniqueKey) ) { + synchronized (getUniqueKeyLock(uniqueKey)) { JNLPClassLoader baseLoader = uniqueKeyToLoader.get(uniqueKey); // A null baseloader implies that no loader has been created // for this codebase/jnlp yet. Create one. - if (baseLoader == null || - (file.isApplication() && - !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) { + if (baseLoader == null + || (file.isApplication() + && !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) { loader = createInstance(file, policy, mainName, enableCodeBase); } else { @@ -433,15 +483,15 @@ // If this is an applet, we do need to consider its loader loader = new JNLPClassLoader(file, policy, mainName, enableCodeBase); - if (baseLoader != null) + if (baseLoader != null) { baseLoader.merge(loader); + } } loader = baseLoader; } // loaders are mapped to a unique key. Only extensions and parent // share a key, so it is safe to always share based on it - loader.incrementLoaderUseCount(); uniqueKeyToLoader.put(uniqueKey, loader); @@ -451,8 +501,7 @@ } /** - * Returns a JNLP classloader for the JNLP file at the specified - * location. + * Returns a JNLP classloader for the JNLP file at the specified location. * * @param location the file's location * @param uniqueKey key to manage applets/applications in shared vm @@ -463,15 +512,15 @@ * @param enableCodeBase whether to enable codebase search or not * @return classlaoder of this appp * @throws java.io.IOException when IO fails - * @throws net.sourceforge.jnlp.ParseException when parsing fails - * @throws net.sourceforge.jnlp.LaunchException when launch is doomed + * @throws net.sourceforge.jnlp.ParseException when parsing fails + * @throws net.sourceforge.jnlp.LaunchException when launch is doomed */ public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, ParserSettings settings, UpdatePolicy policy, String mainName, boolean enableCodeBase) throws IOException, ParseException, LaunchException { JNLPClassLoader loader; - synchronized ( getUniqueKeyLock(uniqueKey) ) { + synchronized (getUniqueKeyLock(uniqueKey)) { loader = uniqueKeyToLoader.get(uniqueKey); if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) { @@ -542,18 +591,20 @@ /** * Check if a described jar file is invalid + * * @param jar the jar to check * @return true if file exists AND is an invalid jar, false otherwise */ - boolean isInvalidJar(JARDesc jar){ + boolean isInvalidJar(JARDesc jar) { File cacheFile = tracker.getCacheFile(jar.getLocation()); - if (cacheFile == null) + if (cacheFile == null) { return false;//File cannot be retrieved, do not claim it is an invalid jar + } boolean isInvalid = false; try { JarFile jarFile = new JarFile(cacheFile.getAbsolutePath()); jarFile.close(); - } catch (IOException ioe){ + } catch (IOException ioe) { //Catch a ZipException or any other read failure isInvalid = true; } @@ -562,11 +613,12 @@ /** * Determine how invalid jars should be handled + * * @return whether to filter invalid jars, or error later on */ - private boolean shouldFilterInvalidJars(){ - if (file instanceof PluginBridge){ - PluginBridge pluginBridge = (PluginBridge)file; + private boolean shouldFilterInvalidJars() { + if (file instanceof PluginBridge) { + PluginBridge pluginBridge = (PluginBridge) file; /*Ignore on applet, ie !useJNLPHref*/ return !pluginBridge.useJNLPHref(); } @@ -574,14 +626,14 @@ } /** - * Load all of the JARs used in this JNLP file into the - * ResourceTracker for downloading. + * Load all of the JARs used in this JNLP file into the ResourceTracker for + * downloading. */ void initializeResources() throws LaunchException { - if (file instanceof PluginBridge){ - PluginBridge bridge = (PluginBridge)file; - - for (String codeBaseFolder : bridge.getCodeBaseFolders()){ + if (file instanceof PluginBridge) { + PluginBridge bridge = (PluginBridge) file; + + for (String codeBaseFolder : bridge.getCodeBaseFolders()) { try { addToCodeBaseLoader(new URL(file.getCodeBase(), codeBaseFolder)); } catch (MalformedURLException mfe) { @@ -624,16 +676,16 @@ available.add(jar); - if (jar.isEager()) + if (jar.isEager()) { initialJars.add(jar); // regardless of part - + } tracker.addResource(jar.getLocation(), jar.getVersion(), file.getDownloadOptions(), jar.isCacheable() ? JNLPRuntime.getDefaultUpdatePolicy() : UpdatePolicy.FORCE); } //If there are no eager jars, initialize the first jar - if(initialJars.isEmpty()) { + if (initialJars.isEmpty()) { initialJars.add(jars[0]); } @@ -644,10 +696,10 @@ waitForJars(initialJars); //download the jars first. //A ZipException will propagate later on if the jar is invalid and not checked here - if (shouldFilterInvalidJars()){ + if (shouldFilterInvalidJars()) { //We filter any invalid jars Iterator<JARDesc> iterator = initialJars.iterator(); - while (iterator.hasNext()){ + while (iterator.hasNext()) { JARDesc jar = iterator.next(); if (isInvalidJar(jar)) { //Remove this jar as an available jar @@ -668,7 +720,7 @@ //to read the cacerts or trusted.certs files. OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); throw new LaunchException(null, null, R("LSFatal"), - R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo") + ": " +e.getMessage()); + R("LCInit"), R("LFatalVerification"), R("LFatalVerificationInfo") + ": " + e.getMessage()); } //Case when at least one jar has some signing @@ -679,8 +731,9 @@ checkForMain(initialJars); // If jar with main class was not found, check available resources - while (!foundMainJar && available != null && !available.isEmpty()) + while (!foundMainJar && available != null && !available.isEmpty()) { addNextResource(); + } // If the jar with main class was not found, check extension // jnlp's resources @@ -712,16 +765,18 @@ } // If main jar was found, but a signed JNLP file was not located - if (!isSignedJNLP && foundMainJar) + if (!isSignedJNLP && foundMainJar) { file.setSignedJNLPAsMissing(); + } //user does not trust this publisher if (!jcv.isTriviallySigned()) { checkTrustWithUser(); } else { /** - * If the user trusts this publisher (i.e. the publisher's certificate - * is in the user's trusted.certs file), we do not show any dialogs. + * If the user trusts this publisher (i.e. the publisher's + * certificate is in the user's trusted.certs file), we do + * not show any dialogs. */ } } else { @@ -803,12 +858,13 @@ } return codebase; } - - /*** - * Checks for the jar that contains the attribute. - * + + /** + * * + * Checks for the jar that contains the attribute. + * * @param jars Jars that are checked to see if they contain the main class - * @param name attribute to be found + * @param name attribute to be found * @return value of attribute if found */ public String checkForAttributeInJars(List<JARDesc> jars, Attributes.Name name) { @@ -816,7 +872,6 @@ return null; } - // Check main jar JARDesc mainJarDesc = ResourcesDesc.getMainJAR(jars); String result = getManifestAttribute(mainJarDesc.getLocation(), name); @@ -827,33 +882,36 @@ // Check first jar JARDesc firstJarDesc = jars.get(0); - result = getManifestAttribute(firstJarDesc.getLocation(),name); - + result = getManifestAttribute(firstJarDesc.getLocation(), name); + if (result != null) { return result; } // Still not found? Iterate and set if only 1 was found - for (JARDesc jarDesc: jars) { + for (JARDesc jarDesc : jars) { String attributeInThisJar = getManifestAttribute(jarDesc.getLocation(), name); - if (attributeInThisJar != null) { - if (result == null) { // first main class - result = attributeInThisJar; - } else { // There is more than one main class. Set to null and break. - result = null; - break; + if (attributeInThisJar != null) { + if (result == null) { // first main class + result = attributeInThisJar; + } else { // There is more than one main class. Set to null and break. + result = null; + break; } } } return result; } - /*** + + /** + * * * Checks for the jar that contains the main class. If the main class was * found, it checks to see if the jar is signed and whether it contains a * signed JNLP file - * + * * @param jars Jars that are checked to see if they contain the main class - * @throws LaunchException Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match + * @throws LaunchException Thrown if the signed JNLP file, within the main + * jar, fails to be verified or does not match */ void checkForMain(List<JARDesc> jars) throws LaunchException { @@ -866,7 +924,6 @@ } // The main class may be specified in the manifest - if (mainClass == null) { mainClass = checkForAttributeInJars(jars, Attributes.Name.MAIN_CLASS); } @@ -910,31 +967,32 @@ * Gets the name of the main method if specified in the manifest * * @param location The JAR location - * @return the main class name, null if there isn't one of if there was an error + * @return the main class name, null if there isn't one of if there was an + * error */ String getMainClassName(URL location) { return getManifestAttribute(location, Attributes.Name.MAIN_CLASS); } - - + /** * Gets the name of the main method if specified in the manifest * * @param location The JAR location * @param attribute name of the attribute to find - * @return the attribute value, null if there isn't one of if there was an error + * @return the attribute value, null if there isn't one of if there was an + * error */ - public String getManifestAttribute(URL location, Attributes.Name attribute) { + public String getManifestAttribute(URL location, Attributes.Name attribute) { String attributeValue = null; File f = tracker.getCacheFile(location); - if( f != null) { + if (f != null) { JarFile mainJar = null; try { mainJar = new JarFile(f); Manifest manifest = mainJar.getManifest(); - if (manifest == null || manifest.getMainAttributes() == null){ + if (manifest == null || manifest.getMainAttributes() == null) { //yes, jars without manifest exists return null; } @@ -972,10 +1030,11 @@ /** * Is called by checkForMain() to check if the jar file is signed and if it * contains a signed JNLP file. - * + * * @param jarDesc JARDesc of jar * @param jarFile the jar file - * @throws LaunchException thrown if the signed JNLP file, within the main jar, fails to be verified or does not match + * @throws LaunchException thrown if the signed JNLP file, within the main + * jar, fails to be verified or does not match */ private void verifySignedJNLP(JARDesc jarDesc, JarFile jarFile) throws LaunchException { @@ -1014,13 +1073,14 @@ matcher = new JNLPMatcher(inStream, jnlpStream, true, jnlp.getParserSettings()); } // If signed JNLP file does not matches launching JNLP file, throw JNLPMatcherException - if (!matcher.isMatch()) + if (!matcher.isMatch()) { throw new JNLPMatcherException("Signed Application did not match launching JNLP File"); + } this.isSignedJNLP = true; OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Signed Application Verification Successful"); - break; + break; } } } @@ -1030,7 +1090,6 @@ * Throws LaunchException if signed JNLP file fails to be verified * or fails to match the launching JNLP file */ - throw new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LSignedJNLPFileDidNotMatch"), R(e.getMessage())); @@ -1038,9 +1097,8 @@ * Throwing this exception will fail to initialize the application * resulting in the termination of the application */ - } catch (Exception e) { - + OutputController.getLogger().log(e); /* @@ -1049,21 +1107,21 @@ * JarCertVerifier.add) it assumes the jar file is unsigned and * skip the check for a signed JNLP file */ - } OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Ending check for signed JNLP file..."); } /** * Prompt the user for trust on all the signers that require approval. + * * @throws LaunchException if the user does not approve every dialog prompt. */ private void checkTrustWithUser() throws LaunchException { - + if (securityDelegate.getRunInSandbox()) { return; } - + if (getSigningState() == SigningState.FULL && jcv.isFullySigned() && !jcv.getAlreadyTrustPublisher()) { jcv.checkTrustWithUser(securityDelegate, file); } @@ -1086,10 +1144,9 @@ } /** - * Add applet's codebase URL. This allows compatibility with - * applets that load resources from their codebase instead of - * through JARs, but can slow down resource loading. Resources - * loaded from the codebase are not cached. + * Add applet's codebase URL. This allows compatibility with applets that + * load resources from their codebase instead of through JARs, but can slow + * down resource loading. Resources loaded from the codebase are not cached. */ public void enableCodeBase() { addToCodeBaseLoader(file.getCodeBase()); @@ -1097,11 +1154,12 @@ /** * Sets the JNLP app this group is for; can only be called once. + * * @param app application to be ser to this group */ public void setApplication(ApplicationInstance app) { if (this.app != null) { - OutputController.getLogger().log(new IllegalStateException("Application can only be set once")); + OutputController.getLogger().log(new IllegalStateException("Application can only be set once")); return; } @@ -1132,7 +1190,6 @@ // should check for extensions or boot, automatically give all // access w/o security dialog once we actually check certificates. - // copy security permissions from SecurityDesc element if (security != null) { // Security desc. is used only to track security settings for the @@ -1182,9 +1239,10 @@ } // Class from host X should be allowed to connect to host X - if (cs.getLocation() != null && cs.getLocation().getHost().length() > 0) + if (cs.getLocation() != null && cs.getLocation().getHost().length() > 0) { result.add(new SocketPermission(UrlUtils.getHostAndPort(cs.getLocation()), "connect, accept")); + } return result; } catch (RuntimeException ex) { @@ -1198,33 +1256,34 @@ } /** - * Adds to the specified list of JARS any other JARs that need - * to be loaded at the same time as the JARs specified (ie, are - * in the same part). + * Adds to the specified list of JARS any other JARs that need to be loaded + * at the same time as the JARs specified (ie, are in the same part). + * * @param jars jar archives to be added */ protected void fillInPartJars(List<JARDesc> jars) { //can not use iterator, will rise ConcurrentModificationException on jars.add(jar); - for (int x = 0 ; x< jars.size() ; x++) { + for (int x = 0; x < jars.size(); x++) { String part = jars.get(x).getPart(); // "available" field can be affected by two different threads // working in loadClass(String) synchronized (available) { for (JARDesc jar : available) { - if (part != null && part.equals(jar.getPart())) - if (!jars.contains(jar)) + if (part != null && part.equals(jar.getPart())) { + if (!jars.contains(jar)) { jars.add(jar); + } + } } } } } /** - * Ensures that the list of jars have all been transferred, and - * makes them available to the classloader. If a jar contains - * native code, the libraries will be extracted and placed in - * the path. + * Ensures that the list of jars have all been transferred, and makes them + * available to the classloader. If a jar contains native code, the + * libraries will be extracted and placed in the path. * * @param jars the list of jars to load */ @@ -1256,13 +1315,13 @@ // particularly when using The FileManager applet from Webmin. try (JarFile jarFile = new JarFile(localFile)) { for (JarEntry je : Collections.list(jarFile.entries())) { - + // another jar in my jar? it is more likely than you think if (je.getName().endsWith(".jar")) { // We need to extract that jar so that it can be loaded // (inline loading with "jar:..!/..." path will not work // with standard classloader methods) - + String extractedJarLocation = localFile + ".nested/" + je.getName(); File parentDir = new File(extractedJarLocation).getParentFile(); if (!parentDir.isDirectory() && !parentDir.mkdirs()) { @@ -1270,7 +1329,7 @@ } FileOutputStream extractedJar = new FileOutputStream(extractedJarLocation); InputStream is = jarFile.getInputStream(je); - + byte[] bytes = new byte[1024]; int read = is.read(bytes); int fileSize = read; @@ -1279,41 +1338,41 @@ read = is.read(bytes); fileSize += read; } - + is.close(); extractedJar.close(); - + // 0 byte file? skip if (fileSize <= 0) { continue; } - + tracker.addResource(new File(extractedJarLocation).toURL(), null, null, null); - + URL codebase = file.getCodeBase(); if (codebase == null) { //FIXME: codebase should be the codebase of the Main Jar not //the location. Although, it still works in the current state. codebase = file.getResources().getMainJAR().getLocation(); } - + final SecurityDesc jarSecurity = securityDelegate.getJarPermissions(codebase); - + try { URL fileURL = new URL("file://" + extractedJarLocation); // there is no remote URL for this, so lets fake one URL fakeRemote = new URL(jar.getLocation().toString() + "!" + je.getName()); CachedJarFileCallback.getInstance().addMapping(fakeRemote, fileURL); addURL(fakeRemote); - + jarLocationSecurityMap.put(fakeRemote, jarSecurity); - + } catch (MalformedURLException mfue) { OutputController.getLogger().log(OutputController.Level.WARNING_DEBUG, "Unable to add extracted nested jar to classpath"); OutputController.getLogger().log(OutputController.Level.ERROR_ALL, mfue); } } - + jarEntries.add(je.getName()); } } @@ -1328,7 +1387,7 @@ try (JarFile jarFile = new JarFile(localFile.getAbsolutePath())) { Manifest mf = jarFile.getManifest(); - + // Only check classpath if this is the plugin and there is no jnlp_href usage. // Note that this is different from proprietary plugin behaviour. // If jnlp_href is used, the app should be treated similarly to when @@ -1336,19 +1395,19 @@ if (file instanceof PluginBridge && !((PluginBridge) file).useJNLPHref()) { classpaths.addAll(getClassPathsFromManifest(mf, jar.getLocation().getPath())); } - + JarIndexAccess index = JarIndexAccess.getJarIndex(jarFile); - if (index != null) + if (index != null) { jarIndexes.add(index); + } } } else { CachedJarFileCallback.getInstance().addMapping(jar.getLocation(), jar.getLocation()); } OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Activate jar: " + location); - } - catch (Exception ex) { - OutputController.getLogger().log(ex); + } catch (Exception ex) { + OutputController.getLogger().log(ex); } // some programs place a native library in any jar @@ -1374,14 +1433,16 @@ } String result = super.findLibrary(lib); - if (result != null) + if (result != null) { return result; + } return findLibraryExt(lib); } /** * Try to find the library path from another peer classloader. + * * @param lib library to be found * @return location of library */ @@ -1389,19 +1450,21 @@ for (JNLPClassLoader loader : loaders) { String result = null; - if (loader != this) + if (loader != this) { result = loader.findLibrary(lib); - - if (result != null) + } + + if (result != null) { return result; + } } return null; } /** - * Wait for a group of JARs, and send download events if there - * is a download listener or display a progress window otherwise. + * Wait for a group of JARs, and send download events if there is a download + * listener or display a progress window otherwise. * * @param jars the jars */ @@ -1419,6 +1482,7 @@ /** * Find the loaded class in this loader or any of its extension loaders. + * * @param name name of class * @return the class found by name */ @@ -1432,41 +1496,43 @@ result = loader.findLoadedClassAll(name); } - if (result != null) + if (result != null) { return result; + } } - + // Result is still null. Return what the codebaseloader // has (which returns null if it is not loaded there either) - if (codeBaseLoader != null) + if (codeBaseLoader != null) { return codeBaseLoader.findLoadedClassFromParent(name); - else + } else { return null; + } } /** - * Find a JAR in the shared 'extension' classloaders, this - * classloader, or one of the classloaders for the JNLP file's - * extensions. - * This method used to be qualified "synchronized." This was done solely for the - * purpose of ensuring only one thread entered the method at a time. This was not + * Find a JAR in the shared 'extension' classloaders, this classloader, or + * one of the classloaders for the JNLP file's extensions. This method used + * to be qualified "synchronized." This was done solely for the purpose of + * ensuring only one thread entered the method at a time. This was not * strictly necessary - ensuring that all affected fields are thread-safe is - * sufficient. Locking on the JNLPClassLoader instance when this method is called - * can result in deadlock if another thread is dealing with the CodebaseClassLoader - * at the same time. This solution is very heavy-handed as the instance lock is not - * truly required, and taking the lock on the classloader instance when not needed is - * not in general a good idea because it can and will lead to deadlock when multithreaded - * classloading is in effect. The solution is to keep the fields thread safe on their own. - * This is accomplished by wrapping them in Collections.synchronized* to provide - * atomic add/remove operations, and synchronizing on them when iterating or performing - * multiple mutations. - * See bug report RH976833. On some systems this bug will manifest itself as deadlock on - * every webpage with more than one Java applet, potentially also causing the browser - * process to hang. - * More information in the mailing list archives: + * sufficient. Locking on the JNLPClassLoader instance when this method is + * called can result in deadlock if another thread is dealing with the + * CodebaseClassLoader at the same time. This solution is very heavy-handed + * as the instance lock is not truly required, and taking the lock on the + * classloader instance when not needed is not in general a good idea + * because it can and will lead to deadlock when multithreaded classloading + * is in effect. The solution is to keep the fields thread safe on their + * own. This is accomplished by wrapping them in Collections.synchronized* + * to provide atomic add/remove operations, and synchronizing on them when + * iterating or performing multiple mutations. See bug report RH976833. On + * some systems this bug will manifest itself as deadlock on every webpage + * with more than one Java applet, potentially also causing the browser + * process to hang. More information in the mailing list archives: * http://mail.openjdk.java.net/pipermail/distro-pkg-dev/2013-September/024536.html - * - * Affected fields: available, classpaths, jarIndexes, jarEntries, jarLocationSecurityMap + * + * Affected fields: available, classpaths, jarIndexes, jarEntries, + * jarLocationSecurityMap */ @Override public Class<?> loadClass(String name) throws ClassNotFoundException { @@ -1476,8 +1542,9 @@ if (result == null) { try { ClassLoader parent = getParent(); - if (parent == null) + if (parent == null) { parent = ClassLoader.getSystemClassLoader(); + } return parent.loadClass(name); } catch (ClassNotFoundException ex) { @@ -1486,7 +1553,6 @@ // filter out 'bad' package names like java, javax // validPackage(name); - // search this and the extension loaders if (result == null) { try { @@ -1518,7 +1584,6 @@ } // As a last resort, look in any available indexes - // Currently this loads jars directly from the site. We cannot cache it because this // call is initiated from within the applet, which does not have disk read/write permissions // This field synchronized before iterating over it since it may @@ -1563,9 +1628,10 @@ /** * Adds a new JARDesc into this classloader. * <p> - * This will add the JARDesc into the resourceTracker and block until it - * is downloaded. + * This will add the JARDesc into the resourceTracker and block until it is + * downloaded. * </p> + * * @param desc the JARDesc for the new jar */ private void addNewJar(final JARDesc desc) { @@ -1574,6 +1640,7 @@ /** * Adds a new JARDesc into this classloader. + * * @param desc the JARDesc for the new jar * @param updatePolicy the UpdatePolicy for the resource */ @@ -1585,7 +1652,7 @@ desc.getVersion(), null, updatePolicy - ); + ); // Give read permissions to the cached jar file AccessController.doPrivileged(new PrivilegedAction<Void>() { @@ -1604,11 +1671,10 @@ final URL cachedUrl = tracker.getCacheURL(remoteURL); // blocks till download available.remove(desc); // Resource downloaded. Remove from available list. - + try { // Verify if needed - final List<JARDesc> jars = new ArrayList<>(); jars.add(desc); @@ -1617,7 +1683,6 @@ // having AllPermissions as those actions normally happen // during initialization. We therefore need to do those // actions as privileged. - AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() throws Exception { @@ -1656,11 +1721,11 @@ final String fName = name; return AccessController.doPrivileged( new PrivilegedExceptionAction<Class<?>>() { - @Override - public Class<?> run() throws ClassNotFoundException { - return JNLPClassLoader.super.findClass(fName); - } - }, getAccessControlContextForClassLoading()); + @Override + public Class<?> run() throws ClassNotFoundException { + return JNLPClassLoader.super.findClass(fName); + } + }, getAccessControlContextForClassLoading()); } else { return loader.findClass(name); } @@ -1673,17 +1738,17 @@ } // Try codebase loader - if (codeBaseLoader != null) + if (codeBaseLoader != null) { return codeBaseLoader.findClassNonRecursive(name); + } // All else failed. Throw CNFE throw new ClassNotFoundException(name); } /** - * Search for the class by incrementally adding resources to the - * classloader and its extension classloaders until the resource - * is found. + * Search for the class by incrementally adding resources to the classloader + * and its extension classloaders until the resource is found. */ private Class<?> loadClassExt(String name) throws ClassNotFoundException { // make recursive @@ -1698,7 +1763,7 @@ // add resources until found while (true) { JNLPClassLoader addedTo = null; - + try { addedTo = addNextResource(); } catch (LaunchException e) { @@ -1708,12 +1773,12 @@ * [It is handled in initializeResources()]. Therefore, this * exception will never be thrown here and is escaped */ - throw new IllegalStateException(e); } - if (addedTo == null) + if (addedTo == null) { throw new ClassNotFoundException(name); + } try { return addedTo.findClass(name); @@ -1723,11 +1788,10 @@ } /** - * Finds the resource in this, the parent, or the extension - * class loaders. + * Finds the resource in this, the parent, or the extension class loaders. * - * @return a {@link URL} for the resource, or {@code null} - * if the resource could not be found. + * @return a {@link URL} for the resource, or {@code null} if the resource + * could not be found. */ @Override public URL findResource(String name) { @@ -1741,17 +1805,18 @@ } catch (IOException e) { OutputController.getLogger().log(e); } - + // If result is still null, look in the codebase loader - if (result == null && codeBaseLoader != null) + if (result == null && codeBaseLoader != null) { result = codeBaseLoader.findResource(name); + } return result; } /** - * Find the resources in this, the parent, or the extension - * class loaders. Load lazy resources if not found in current resources. + * Find the resources in this, the parent, or the extension class loaders. + * Load lazy resources if not found in current resources. */ @Override public Enumeration<URL> findResources(String name) throws IOException { @@ -1770,8 +1835,7 @@ } /** - * Find the resources in this, the parent, or the extension - * class loaders. + * Find the resources in this, the parent, or the extension class loaders. */ private Enumeration<URL> findResourcesBySearching(String name) throws IOException { List<URL> lresources = new ArrayList<>(); @@ -1787,11 +1851,11 @@ try { e = AccessController.doPrivileged( new PrivilegedExceptionAction<Enumeration<URL>>() { - @Override - public Enumeration<URL> run() throws IOException { - return JNLPClassLoader.super.findResources(fName); - } - }, getAccessControlContextForClassLoading()); + @Override + public Enumeration<URL> run() throws IOException { + return JNLPClassLoader.super.findResources(fName); + } + }, getAccessControlContextForClassLoading()); } catch (PrivilegedActionException pae) { } } else { @@ -1801,16 +1865,16 @@ final Enumeration<URL> fURLEnum = e; try { lresources.addAll(AccessController.doPrivileged( - new PrivilegedExceptionAction<Collection<URL>>() { - @Override - public Collection<URL> run() { - List<URL> resources = new ArrayList<>(); - while (fURLEnum != null && fURLEnum.hasMoreElements()) { - resources.add(fURLEnum.nextElement()); - } - return resources; + new PrivilegedExceptionAction<Collection<URL>>() { + @Override + public Collection<URL> run() { + List<URL> resources = new ArrayList<>(); + while (fURLEnum != null && fURLEnum.hasMoreElements()) { + resources.add(fURLEnum.nextElement()); } - }, getAccessControlContextForClassLoading())); + return resources; + } + }, getAccessControlContextForClassLoading())); } catch (PrivilegedActionException pae) { } } @@ -1819,8 +1883,9 @@ // otherwise the server will get hammered) if (lresources.isEmpty() && codeBaseLoader != null) { e = codeBaseLoader.findResources(name); - while (e.hasMoreElements()) + while (e.hasMoreElements()) { lresources.add(e.nextElement()); + } } return Collections.enumeration(lresources); @@ -1837,8 +1902,7 @@ } /** - * Adds whatever resources have already been downloaded in the - * background. + * Adds whatever resources have already been downloaded in the background. */ protected void addAvailable() { // go through available, check tracker for it and all of its @@ -1850,21 +1914,23 @@ } /** - * Adds the next unused resource to the classloader. That - * resource and all those in the same part will be downloaded - * and added to the classloader before returning. If there are - * no more resources to add, the method returns immediately. + * Adds the next unused resource to the classloader. That resource and all + * those in the same part will be downloaded and added to the classloader + * before returning. If there are no more resources to add, the method + * returns immediately. * * @return the classloader that resources were added to, or null - * @throws LaunchException Thrown if the signed JNLP file, within the main jar, fails to be verified or does not match + * @throws LaunchException Thrown if the signed JNLP file, within the main + * jar, fails to be verified or does not match */ protected JNLPClassLoader addNextResource() throws LaunchException { if (available.isEmpty()) { for (int i = 1; i < loaders.length; i++) { JNLPClassLoader result = loaders[i].addNextResource(); - if (result != null) + if (result != null) { return result; + } } return null; } @@ -1882,25 +1948,28 @@ // this part compatibility with previous classloader /** - * @return title if available. Substitutions if not. + * @return title if available. Substitutions if not. * @deprecated */ @Deprecated public String getExtensionName() { String result = file.getInformation().getTitle(); - if (result == null) + if (result == null) { result = file.getInformation().getDescription(); - if (result == null && file.getFileLocation() != null) + } + if (result == null && file.getFileLocation() != null) { result = file.getFileLocation().toString(); - if (result == null && file.getCodeBase() != null) + } + if (result == null && file.getCodeBase() != null) { result = file.getCodeBase().toString(); + } return result; } /** - * @return location if jnlp + * @return location if jnlp * @deprecated */ @Deprecated @@ -1914,14 +1983,13 @@ /** * Call this when it's suspected that an applet's permission level may have - * just changed from Full Signing to Partial Signing. - * This will display a one-time prompt asking the user to confirm running - * the partially signed applet. - * Partially Signed applets always start off as appearing to be Fully - * Signed, and then during the initialization or loading process, we find - * that we actually need to demote the applet to Partial, either due to - * finding that not all of its JARs are actually signed, or because it - * needs to load something unsigned out of the codebase. + * just changed from Full Signing to Partial Signing. This will display a + * one-time prompt asking the user to confirm running the partially signed + * applet. Partially Signed applets always start off as appearing to be + * Fully Signed, and then during the initialization or loading process, we + * find that we actually need to demote the applet to Partial, either due to + * finding that not all of its JARs are actually signed, or because it needs + * to load something unsigned out of the codebase. */ private void checkPartialSigningWithUser() { if (signing == SigningState.FULL && JNLPRuntime.isVerifying()) { @@ -1949,9 +2017,8 @@ * @param source the origin (remote) url of the code * @return The SecurityDescriptor for that source */ - protected SecurityDesc getCodeSourceSecurity(URL source) { - SecurityDesc sec=jarLocationSecurityMap.get(source); + SecurityDesc sec = jarLocationSecurityMap.get(source); synchronized (alreadyTried) { if (sec == null && !alreadyTried.contains(source)) { alreadyTried.add(source); @@ -1967,8 +2034,8 @@ } } } - if (sec == null){ - OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("LNoSecInstance",source.toString())); + if (sec == null) { + OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, Translator.R("LNoSecInstance", source.toString())); } return sec; } @@ -1988,9 +2055,10 @@ } // jars - for (URL u : extLoader.getURLs()) + for (URL u : extLoader.getURLs()) { addURL(u); - + } + // Codebase addToCodeBaseLoader(extLoader.file.getCodeBase()); @@ -2009,7 +2077,7 @@ /** * Adds the given path to the path loader - * + * * @param u the path to add * @throws IllegalArgumentException If the given url is not a path */ @@ -2026,7 +2094,7 @@ // If there is no loader yet, create one, else add it to the // existing one (happens when called from merge()) if (codeBaseLoader == null) { - codeBaseLoader = new CodeBaseClassLoader(new URL[] { u }, this); + codeBaseLoader = new CodeBaseClassLoader(new URL[]{u}, this); } else { codeBaseLoader.addURL(u); } @@ -2036,11 +2104,12 @@ * Returns a set of paths that indicate the Class-Path entries in the * manifest file. The paths are rooted in the same directory as the * originalJarPath. + * * @param mf the manifest - * @param originalJarPath the remote/original path of the jar containing - * the manifest - * @return a Set of String where each string is a path to the jar on - * the original jar's classpath. + * @param originalJarPath the remote/original path of the jar containing the + * manifest + * @return a Set of String where each string is a path to the jar on the + * original jar's classpath. */ private Set<String> getClassPathsFromManifest(Manifest mf, String originalJarPath) { Set<String> result = new HashSet<>(); @@ -2069,20 +2138,21 @@ } return result; } - + /** * Increments loader use count by 1 - * + * * @throws SecurityException if caller is not trusted */ private void incrementLoaderUseCount() { // For use by trusted code only - if (System.getSecurityManager() != null) + if (System.getSecurityManager() != null) { System.getSecurityManager().checkPermission(new AllPermission()); + } // NB: There will only ever be one class-loader per unique-key - synchronized ( getUniqueKeyLock(file.getUniqueKey()) ){ + synchronized (getUniqueKeyLock(file.getUniqueKey())) { useCount++; } } @@ -2105,8 +2175,8 @@ try { tracker.removeResource(eachJar.getLocation()); } catch (Exception e) { - OutputController.getLogger().log(e); - OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Failed to remove resource from tracker, continuing.."); + OutputController.getLogger().log(e); + OutputController.getLogger().log(OutputController.Level.ERROR_DEBUG, "Failed to remove resource from tracker, continuing.."); } File cachedFile = CacheUtil.getCacheFile(eachJar.getLocation(), null); @@ -2144,9 +2214,11 @@ /** * Manages DownloadService jars which are not mentioned in the JNLP file + * * @param ref Path to the resource. * @param version The version of resource. If null, no version is specified. - * @param action The action to perform with the resource. Either DOWNLOADTOCACHE, REMOVEFROMCACHE, or CHECKCACHE. + * @param action The action to perform with the resource. Either + * DOWNLOADTOCACHE, REMOVEFROMCACHE, or CHECKCACHE. * @return true if CHECKCACHE and the resource is cached. */ boolean manageExternalJars(URL ref, String version, DownloadAction action) { @@ -2154,17 +2226,18 @@ JNLPClassLoader foundLoader = LocateJnlpClassLoader.getLoaderByResourceUrl(this, ref, version); Version resourceVersion = (version == null) ? null : new Version(version); - if (foundLoader != null) + if (foundLoader != null) { + approved = true; + } else if (ref.toString().startsWith(file.getNotNullProbalbeCodeBase().toString())) { approved = true; - - else if (ref.toString().startsWith(file.getNotNullProbalbeCodeBase().toString())) + } else if (SecurityDesc.ALL_PERMISSIONS.equals(security.getSecurityType())) { approved = true; - else if (SecurityDesc.ALL_PERMISSIONS.equals(security.getSecurityType())) - approved = true; + } if (approved) { - if (foundLoader == null) + if (foundLoader == null) { foundLoader = this; + } if (action == DownloadAction.DOWNLOAD_TO_CACHE) { JARDesc jarToCache = new JARDesc(ref, resourceVersion, null, false, true, false, true); @@ -2173,7 +2246,7 @@ foundLoader.addNewJar(jarToCache, UpdatePolicy.FORCE); } else if (action == DownloadAction.REMOVE_FROM_CACHE) { - JARDesc[] jarToRemove = { new JARDesc(ref, resourceVersion, null, false, true, false, true) }; + JARDesc[] jarToRemove = {new JARDesc(ref, resourceVersion, null, false, true, false, true)}; foundLoader.removeJars(jarToRemove); } else if (action == DownloadAction.CHECK_CACHE) { @@ -2185,21 +2258,22 @@ /** * Decrements loader use count by 1 - * + * * If count reaches 0, loader is removed from list of available loaders - * + * * @throws SecurityException if caller is not trusted */ public void decrementLoaderUseCount() { // For use by trusted code only - if (System.getSecurityManager() != null) + if (System.getSecurityManager() != null) { System.getSecurityManager().checkPermission(new AllPermission()); + } String uniqueKey = file.getUniqueKey(); // NB: There will only ever be one class-loader per unique-key - synchronized ( getUniqueKeyLock(uniqueKey) ) { + synchronized (getUniqueKeyLock(uniqueKey)) { useCount--; if (useCount <= 0) { @@ -2209,17 +2283,18 @@ } /** - * Returns an appropriate AccessControlContext for loading classes in - * the running instance. + * Returns an appropriate AccessControlContext for loading classes in the + * running instance. * * The default context during class-loading only allows connection to * codebase. However applets are allowed to load jars from arbitrary - * locations and the codebase only access falls short if a class from - * one location needs a class from another. + * locations and the codebase only access falls short if a class from one + * location needs a class from another. * * Given protected access since CodeBaseClassloader uses this function too. * - * @return The appropriate AccessControlContext for loading classes for this instance + * @return The appropriate AccessControlContext for loading classes for this + * instance */ public AccessControlContext getAccessControlContextForClassLoading() { AccessControlContext context = AccessController.getContext(); @@ -2244,7 +2319,7 @@ // Permissions for all remote hosting urls synchronized (jarLocationSecurityMap) { for (URL u : jarLocationSecurityMap.keySet()) { - permissions.add(new SocketPermission(UrlUtils.getHostAndPort(u), + permissions.add(new SocketPermission(UrlUtils.getHostAndPort(u), "connect, accept")); } } @@ -2259,26 +2334,27 @@ ProtectionDomain pd = new ProtectionDomain(null, permissions); - return new AccessControlContext(new ProtectionDomain[] { pd }); + return new AccessControlContext(new ProtectionDomain[]{pd}); } - + public String getMainClass() { return mainClass; } - - - - /** - * SecurityDelegate, in real usage, relies on having a "parent" JNLPClassLoader instance. - * However, JNLPClassLoaders are very large, heavyweight, difficult-to-mock objects, which - * means that unit testing on anything that uses a SecurityDelegate can become very difficult. - * For example, JarCertVerifier is designed separated from the ClassLoader so it can be tested - * in isolation. However, JCV needs some sort of access back to JNLPClassLoader instances to - * be able to invoke setRunInSandbox(). The SecurityDelegate handles this, allowing JCV to be - * tested without instantiating JNLPClassLoaders, by creating a fake SecurityDelegate that does - * not require one. + + /** + * SecurityDelegate, in real usage, relies on having a "parent" + * JNLPClassLoader instance. However, JNLPClassLoaders are very large, + * heavyweight, difficult-to-mock objects, which means that unit testing on + * anything that uses a SecurityDelegate can become very difficult. For + * example, JarCertVerifier is designed separated from the ClassLoader so it + * can be tested in isolation. However, JCV needs some sort of access back + * to JNLPClassLoader instances to be able to invoke setRunInSandbox(). The + * SecurityDelegate handles this, allowing JCV to be tested without + * instantiating JNLPClassLoaders, by creating a fake SecurityDelegate that + * does not require one. */ public static interface SecurityDelegate { + public boolean isPluginApplet(); public boolean userPromptedForPartialSigning(); @@ -2305,10 +2381,11 @@ } /** - * Handles security decision logic for the JNLPClassLoader, eg which permission level to assign - * to JARs. + * Handles security decision logic for the JNLPClassLoader, eg which + * permission level to assign to JARs. */ public static class SecurityDelegateImpl implements SecurityDelegate { + private final JNLPClassLoader classLoader; private boolean runInSandbox; private boolean promptedForPartialSigning; @@ -2331,27 +2408,25 @@ return new SecurityDesc(classLoader.file, SecurityDesc.SANDBOX_PERMISSIONS, codebaseHost); - } else { - if (isPluginApplet()) { - try { - if (JarCertVerifier.isJarSigned(jarDesc, new PluginAppVerifier(), classLoader.tracker)) { - return new SecurityDesc(classLoader.file, - SecurityDesc.ALL_PERMISSIONS, - codebaseHost); - } else { - return new SecurityDesc(classLoader.file, - SecurityDesc.SANDBOX_PERMISSIONS, - codebaseHost); - } - } catch (final Exception e) { - OutputController.getLogger().log(e); + } else if (isPluginApplet()) { + try { + if (JarCertVerifier.isJarSigned(jarDesc, new PluginAppVerifier(), classLoader.tracker)) { + return new SecurityDesc(classLoader.file, + SecurityDesc.ALL_PERMISSIONS, + codebaseHost); + } else { return new SecurityDesc(classLoader.file, SecurityDesc.SANDBOX_PERMISSIONS, codebaseHost); } - } else { - return classLoader.file.getSecurity(); + } catch (final Exception e) { + OutputController.getLogger().log(e); + return new SecurityDesc(classLoader.file, + SecurityDesc.SANDBOX_PERMISSIONS, + codebaseHost); } + } else { + return classLoader.file.getSecurity(); } } @@ -2367,8 +2442,7 @@ SecurityDesc.SANDBOX_PERMISSIONS, codebaseHost); } - } else { - /* + } else /* * Various combinations of the jars being signed and <security> tags being * present are possible. They are treated as follows * @@ -2379,21 +2453,19 @@ * Unsigned <security> Error * Unsigned no <security> Sandbox * - */ - if (!runInSandbox && !classLoader.getSigning() - && !classLoader.file.getSecurity().getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS)) { - if (classLoader.jcv.allJarsSigned()) { - throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LSignedJNLPAppDifferentCerts"), R("LSignedJNLPAppDifferentCertsInfo")); - } else { - throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LUnsignedJarWithSecurity"), R("LUnsignedJarWithSecurityInfo")); - } - } else if (!runInSandbox && classLoader.getSigning()) { - return classLoader.file.getSecurity(); + */ if (!runInSandbox && !classLoader.getSigning() + && !classLoader.file.getSecurity().getSecurityType().equals(SecurityDesc.SANDBOX_PERMISSIONS)) { + if (classLoader.jcv.allJarsSigned()) { + throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LSignedJNLPAppDifferentCerts"), R("LSignedJNLPAppDifferentCertsInfo")); } else { - return new SecurityDesc(classLoader.file, - SecurityDesc.SANDBOX_PERMISSIONS, - codebaseHost); + throw new LaunchException(classLoader.file, null, R("LSFatal"), R("LCClient"), R("LUnsignedJarWithSecurity"), R("LUnsignedJarWithSecurityInfo")); } + } else if (!runInSandbox && classLoader.getSigning()) { + return classLoader.file.getSecurity(); + } else { + return new SecurityDesc(classLoader.file, + SecurityDesc.SANDBOX_PERMISSIONS, + codebaseHost); } } @@ -2470,7 +2542,7 @@ } } - + /* * Helper class to expose protected URLClassLoader methods. @@ -2487,7 +2559,7 @@ public static class CodeBaseClassLoader extends URLClassLoader { JNLPClassLoader parentJNLPClassLoader; - + /** * Classes that are not found, so that findClass can skip them next time */ @@ -2499,8 +2571,8 @@ } @Override - public void addURL(URL url) { - super.addURL(url); + public void addURL(URL url) { + super.addURL(url); } /* @@ -2508,18 +2580,19 @@ */ Class<?> findClassNonRecursive(final String name) throws ClassNotFoundException { // If we have searched this path before, don't try again - if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) + if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) { throw new ClassNotFoundException(name); + } try { return AccessController.doPrivileged( new PrivilegedExceptionAction<Class<?>>() { - public Class<?> run() throws ClassNotFoundException { - Class<?> c = CodeBaseClassLoader.super.findClass(name); - parentJNLPClassLoader.checkPartialSigningWithUser(); - return c; - } - }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); + public Class<?> run() throws ClassNotFoundException { + Class<?> c = CodeBaseClassLoader.super.findClass(name); + parentJNLPClassLoader.checkPartialSigningWithUser(); + return c; + } + }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); } catch (PrivilegedActionException pae) { notFoundResources.put(name, super.getURLs()); throw new ClassNotFoundException("Could not find class " + name, pae); @@ -2542,11 +2615,12 @@ /** * Returns the output of super.findLoadedClass(). - * + * * The method is renamed because ClassLoader.findLoadedClass() is final - * + * * @param name The name of the class to find - * @return Output of ClassLoader.findLoadedClass() which is the class if found, null otherwise + * @return Output of ClassLoader.findLoadedClass() which is the class if + * found, null otherwise * @see java.lang.ClassLoader#findLoadedClass(String) */ public Class<?> findLoadedClassFromParent(String name) { @@ -2555,7 +2629,7 @@ /** * Returns JNLPClassLoader that encompasses this loader - * + * * @return parent JNLPClassLoader */ public JNLPClassLoader getParentJNLPClassLoader() { @@ -2566,8 +2640,9 @@ public Enumeration<URL> findResources(String name) throws IOException { // If we have searched this path before, don't try again - if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) + if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) { return (new Vector<URL>(0)).elements(); + } if (!name.startsWith("META-INF")) { Enumeration<URL> urls = super.findResources(name); @@ -2586,8 +2661,9 @@ public URL findResource(String name) { // If we have searched this path before, don't try again - if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) + if (Arrays.equals(super.getURLs(), notFoundResources.get(name))) { return null; + } URL url = null; if (!name.startsWith("META-INF")) { @@ -2595,12 +2671,12 @@ final String fName = name; url = AccessController.doPrivileged( new PrivilegedExceptionAction<URL>() { - public URL run() { - return CodeBaseClassLoader.super.findResource(fName); - } - }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); + public URL run() { + return CodeBaseClassLoader.super.findResource(fName); + } + }, parentJNLPClassLoader.getAccessControlContextForClassLoading()); } catch (PrivilegedActionException pae) { - } + } if (url == null) { notFoundResources.put(name, super.getURLs()); @@ -2612,6 +2688,5 @@ return null; } } - - + }