src/demo/share/jpackager/JNLPConverter/src/jnlp/converter/parser/ResourcesDesc.java
branchJDK-8200758-branch
changeset 56963 eaca4369b068
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/demo/share/jpackager/JNLPConverter/src/jnlp/converter/parser/ResourcesDesc.java	Fri Oct 12 19:00:51 2018 -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<ResourceType> _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<JARDesc> 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<ExtensionDesc> 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<JARDesc> 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<ExtensionDesc> 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<JARDesc> 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<Property> getResourcePropertyList() throws Exception {
+        final LinkedList<Property> 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<Object> 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);
+        }
+    }
+}