--- /dev/null 2018-10-22 10:24:05.000000000 -0400 +++ new/src/demo/share/jpackager/JNLPConverter/src/jnlp/converter/parser/ResourcesDesc.java 2018-10-22 10:24:03.104600000 -0400 @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jnlp.converter.parser; + +import java.net.URL; +import java.util.Properties; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import jnlp.converter.HTTPHelper; + +/** + * This class contains information about the codebase and properties, i.e., how + * to locate the classes and optional-packages + */ +public class ResourcesDesc implements ResourceType { + + private final List _list; + private volatile JNLPDesc _parent = null; + + /** + * Create empty resource list + */ + public ResourcesDesc() { + _list = new CopyOnWriteArrayList<>(); + } + + public JNLPDesc getParent() { + return _parent; + } + + void setParent(JNLPDesc parent) { + _parent = parent; + for (int i = 0; i < _list.size(); i++) { + Object o = _list.get(i); + if (o instanceof JREDesc) { + JREDesc jredesc = (JREDesc) o; + if (jredesc.getNestedResources() != null) { + jredesc.getNestedResources().setParent(parent); + } + } + } + } + + public void addResource(ResourceType rd) { + if (rd != null) { + _list.add(rd); + } + } + + boolean isEmpty() { + return _list.isEmpty(); + } + + public JARDesc[] getLocalJarDescs() { + ArrayList jds = new ArrayList<>(_list.size()); + for (ResourceType rt : _list) { + if (rt instanceof JARDesc) { + jds.add((JARDesc) rt); + } + } + return jds.toArray(new JARDesc[jds.size()]); + } + + public JREDesc getJreDesc() { + for (ResourceType rt : _list) { + if (rt instanceof JREDesc) { + return (JREDesc)rt; + } + } + + return null; + } + + public ExtensionDesc[] getExtensionDescs() throws Exception { + final ArrayList extList = new ArrayList<>(); + visit(new ResourceVisitor() { + @Override + public void visitExtensionDesc(ExtensionDesc ed) throws Exception { + // add all extensiondesc recursively + addExtToList(extList); + } + }); + return extList.toArray(new ExtensionDesc[extList.size()]); + } + + public JARDesc[] getAllJarDescs() throws Exception { + List jarList = new ArrayList<>(); + addJarsToList(jarList); + return jarList.toArray(new JARDesc[jarList.size()]); + } + + /** + * Add to a list of all the ExtensionDesc. This method goes recusivly through + * all ExtensionDesc + */ + private void addExtToList(final List list) throws Exception { + // Iterate through list an add ext jnlp to the list. + visit(new ResourceVisitor() { + @Override + public void visitExtensionDesc(ExtensionDesc ed) throws Exception { + if (ed.getExtensionDesc() != null) { + ed.getExtensionDesc().getMainJar(); + ResourcesDesc rd = ed.getExtensionDesc().getResourcesDesc(); + if (rd != null) { + rd.addExtToList(list); + } + } + list.add(ed); + } + }); + } + + private void addJarsToList(final List list) throws Exception { + + // Iterate through list an add resources to the list. + // The ordering of resources are preserved + visit(new ResourceVisitor() { + @Override + public void visitJARDesc(JARDesc jd) { + list.add(jd); + } + + @Override + public void visitExtensionDesc(ExtensionDesc ed) throws Exception { + if (ed.getExtensionDesc() != null) { + ResourcesDesc rd = ed.getExtensionDesc().getResourcesDesc(); + if (rd != null) { + rd.addJarsToList(list); + } + } + } + }); + } + + /** + * Get all the resources needed when a specific resource is requested. + * Returns null if no resource was found + */ + public JARDesc[] getResource(final URL location) throws Exception { + final JARDesc[] resources = new JARDesc[1]; + // Find the given resource + visit(new ResourceVisitor() { + @Override + public void visitJARDesc(JARDesc jd) { + if (GeneralUtil.sameURLs(jd.getLocation(), location)) { + resources[0] = jd; + } + } + }); + + // Found no resource? + if (resources[0] == null) { + return null; + } + + // No part, so just one resource + return resources; + } + + /* Returns the Expected Main Jar + * first jar with attribute main="true" + * else first jar if none has that attribute + * will look in extensions, and nested resource blocks if matching + */ + protected JARDesc getMainJar() throws Exception { + // Normal trick to get around final arguments to inner classes + final JARDesc[] results = new JARDesc[2]; + + visit(new ResourceVisitor() { + @Override + public void visitJARDesc(JARDesc jd) { + if (jd.isJavaFile()) { + // Keep track of first Java File + if (results[0] == null || results[0].isNativeLib()) { + results[0] = jd; + } + // Keep tack of Java File marked main + if (jd.isMainJarFile()) { + results[1] = jd; + } + } else if (jd.isNativeLib()) { + // if jnlp extension has only native lib + if (results[0] == null) { + results[0] = jd; + } + } + } + + @Override + public void visitExtensionDesc(ExtensionDesc ed) throws Exception { + // only check if no main yet and it is not an installer + if (results[1] == null && !ed.isInstaller()) { + JNLPDesc extLd = ed.getExtensionDesc(); + if (extLd != null && extLd.isLibrary()) { + ResourcesDesc rd = extLd.getResourcesDesc(); + if (rd != null) { + // look for main jar in extension resource + rd.visit(this); + } + } + } + } + }); + + // Default is the first, if none is specified as main. This might + // return NULL if there is no JAR resources. + JARDesc first = results[0]; + JARDesc main = results[1]; + + // if main is null then return first; + // libraries have no such thing as a main jar, so return first; + // otherwise return main + // only returns null if there are no jars. + return (main == null) ? first : main; + } + + /* + * Get the properties defined for this object + */ + public Properties getResourceProperties() throws Exception { + final Properties props = new Properties(); + visit(new ResourceVisitor() { + @Override + public void visitPropertyDesc(PropertyDesc pd) { + props.setProperty(pd.getKey(), pd.getValue()); + } + + @Override + public void visitExtensionDesc(ExtensionDesc ed) throws Exception { + JNLPDesc jnlpd = ed.getExtensionDesc(); + ResourcesDesc rd = jnlpd.getResourcesDesc(); + if (rd != null) { + Properties extProps = rd.getResourceProperties(); + Enumeration e = extProps.propertyNames(); + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + String value = extProps.getProperty(key); + props.setProperty(key, value); + } + } + } + }); + return props; + } + + /* + * Get the properties defined for this object, in the right order. + */ + public List getResourcePropertyList() throws Exception { + final LinkedList propList = new LinkedList<>(); + visit(new ResourceVisitor() { + @Override + public void visitPropertyDesc(PropertyDesc pd) { + propList.add(new Property(pd.getKey(), pd.getValue())); + } + }); + return propList; + } + + /** + * visitor dispatch + */ + @Override + public void visit(ResourceVisitor rv) throws Exception { + for (int i = 0; i < _list.size(); i++) { + ResourceType rt = _list.get(i); + rt.visit(rv); + } + } + + public void addNested(ResourcesDesc nested) throws Exception { + if (nested != null) { + nested.visit(new ResourceVisitor() { + @Override + public void visitJARDesc(JARDesc jd) { + _list.add(jd); + } + + @Override + public void visitPropertyDesc(PropertyDesc pd) { + _list.add(pd); + } + + @Override + public void visitExtensionDesc(ExtensionDesc ed) { + _list.add(ed); + } + }); + } + + } + + public static class JARDesc implements ResourceType { + + private URL _location; + private String _locationString; + private String _version; + private boolean _isNativeLib; + private boolean _isMainFile; // Only used for Java JAR files (a main JAR file is implicitly eager) + private ResourcesDesc _parent; // Back-pointer to the Resources that contains this JAR + + public JARDesc(URL location, String version, boolean isMainFile, boolean isNativeLib, ResourcesDesc parent) { + _location = location; + _locationString = GeneralUtil.toNormalizedString(location); + _version = version; + _isMainFile = isMainFile; + _isNativeLib = isNativeLib; + _parent = parent; + } + + /** + * Type of JAR resource + */ + public boolean isNativeLib() { + return _isNativeLib; + } + + public boolean isJavaFile() { + return !_isNativeLib; + } + + /** + * Returns URL/version for JAR file + */ + public URL getVersionLocation() throws Exception { + if (getVersion() == null) { + return _location; + } else { + return GeneralUtil.getEmbeddedVersionURL(getLocation(), getVersion()); + } + } + + public URL getLocation() { + return _location; + } + + public String getVersion() { + return _version; + } + + public String getName() { + // File can be separated by '/' or '\\' + int index; + int index1 = _locationString.lastIndexOf('/'); + int index2 = _locationString.lastIndexOf('\\'); + + if (index1 >= index2) { + index = index1; + } else { + index = index2; + } + + if (index != -1) { + return _locationString.substring(index + 1, _locationString.length()); + } + + return null; + } + + /** + * Returns if this is the main JAR file + */ + public boolean isMainJarFile() { + return _isMainFile; + } + + /** + * Get parent LaunchDesc + */ + public ResourcesDesc getParent() { + return _parent; + } + + /** + * Visitor dispatch + */ + public void visit(ResourceVisitor rv) { + rv.visitJARDesc(this); + } + } + + public static class PropertyDesc implements ResourceType { + + private String _key; + private String _value; + + public PropertyDesc(String key, String value) { + _key = key; + _value = value; + } + + // Accessors + public String getKey() { + return _key; + } + + public String getValue() { + return _value; + } + + /** + * Visitor dispatch + */ + public void visit(ResourceVisitor rv) { + rv.visitPropertyDesc(this); + } + + } + + public static class JREDesc implements ResourceType { + + private String _version; + private long _maxHeap; + private long _minHeap; + private String _vmargs; + private ResourcesDesc _resourceDesc; + private JNLPDesc _extensioDesc; + private String _archList; + + /* + * Constructor to create new instance based on the requirements from JNLP file. + */ + public JREDesc(String version, long minHeap, long maxHeap, String vmargs, + ResourcesDesc resourcesDesc, String archList) { + + _version = version; + _maxHeap = maxHeap; + _minHeap = minHeap; + _vmargs = vmargs; + _resourceDesc = resourcesDesc; + _extensioDesc = null; + _archList = archList; + } + + public String[] getArchList() { + return GeneralUtil.getStringList(_archList); + } + + public String getVersion() { + return _version; + } + + public long getMinHeap() { + return _minHeap; + } + + public long getMaxHeap() { + return _maxHeap; + } + + public String getVmArgs() { + return _vmargs; + } + + public String[] getVmArgsList() { + return GeneralUtil.getStringList(_vmargs); + } + + public ResourcesDesc getNestedResources() { + return _resourceDesc; + } + + public JNLPDesc getExtensionDesc() { + return _extensioDesc; + } + + public void setExtensionDesc(JNLPDesc ld) { + _extensioDesc = ld; + } + + /* visitor dispatch */ + public void visit(ResourceVisitor rv) { + rv.visitJREDesc(this); + } + } + + public static class Property implements Cloneable { + + public static final String JNLP_VERSION_ENABLED = "jnlp.versionEnabled"; + + String key; + String value; + + public Property(String spec) { + spec = spec.trim(); + if (!spec.startsWith("-D") || spec.length() < 3) { + throw new IllegalArgumentException("Property invalid"); + } + + int endKey = spec.indexOf("="); + if (endKey < 0) { + // it's legal to have no assignment + this.key = spec.substring(2); // skip "-D" + this.value = ""; + } else { + this.key = spec.substring(2, endKey); + this.value = spec.substring(endKey + 1); + } + } + + public static Property createProperty(String spec) { + Property prop = null; + try { + prop = new Property(spec); + } catch (IllegalArgumentException iae) { + } + return prop; + } + + public Property(String key, String value) { + this.key = key; + if (value != null) { + this.value = value; + } else { + this.value = ""; + } + } + + public String getKey() { + return key; + } + + public String getValue() { + return value; + } + + // @return String representation, unquoted, unified presentation + public String toString() { + if (value.length() == 0) { + return "-D" + key; + } + return "-D" + key + "=" + value; + } + + public void addTo(Properties props) { + props.setProperty(key, value); + } + + // Hash Object + public boolean equals(Object o) { + if (!(o instanceof Property)) { + return false; + } + Property op = (Property) o; + int hashTheirs = op.hashCode(); + int hashThis = hashCode(); + return hashTheirs == hashThis; + } + + public int hashCode() { + return key.hashCode(); + } + + private static List jnlpProps = Arrays.asList(new Object[]{ + JNLP_VERSION_ENABLED + }); + + public static boolean isJnlpProperty(String spec) { + try { + Property p = new Property(spec); + return isJnlpPropertyKey(p.getKey()); + } catch (Exception e) { + return false; + } + } + + public static boolean isJnlpPropertyKey(String key) { + return key != null && jnlpProps.contains(key); + } + } + + public static class ExtensionDesc implements ResourceType { + // Tag elements + + private final URL _location; + private final String _locationString; + private final String _version; + private final URL _codebase; + + // Link to launchDesc + private JNLPDesc _extensionLd; // Link to launchDesc for extension + + public ExtensionDesc(URL location, String version) { + _location = location; + _locationString = GeneralUtil.toNormalizedString(location); + _version = version; + _codebase = GeneralUtil.asPathURL(GeneralUtil.getBase(location)); + _extensionLd = null; + } + + public boolean isInstaller() throws Exception { + if (getExtensionDesc() != null) { + return _extensionLd.isInstaller(); + } + return false; + } + + public URL getLocation() { + return _location; + } + + public String getVersionLocation() throws Exception { + if (getVersion() == null) { + return _locationString; + } else { + return GeneralUtil.toNormalizedString(GeneralUtil.getEmbeddedVersionURL(getLocation(), getVersion())); + } + } + + public String getVersion() { + return _version; + } + + public URL getCodebase() { + return _codebase; + } + + /* + * Information about the resources + */ + public JNLPDesc getExtensionDesc() throws Exception { + if (_extensionLd == null) { + byte[] bits = HTTPHelper.getJNLPBits(getVersionLocation(), _locationString); + _extensionLd = XMLFormat.parse(bits, getCodebase(), getVersionLocation()); + } + return _extensionLd; + } + + public void setExtensionDesc(JNLPDesc desc) { + _extensionLd = desc; + } + + /** + * Visitor dispatch + */ + public void visit(ResourceVisitor rv) throws Exception { + rv.visitExtensionDesc(this); + } + } +}