diff --git a/appserver/admin/gf_template/src/main/resources/config/domain.xml b/appserver/admin/gf_template/src/main/resources/config/domain.xml index 568b816f4b8..403a0516897 100644 --- a/appserver/admin/gf_template/src/main/resources/config/domain.xml +++ b/appserver/admin/gf_template/src/main/resources/config/domain.xml @@ -265,6 +265,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext @@ -478,6 +480,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext diff --git a/appserver/admin/gf_template_web/src/main/resources/config/domain.xml b/appserver/admin/gf_template_web/src/main/resources/config/domain.xml index 74b78ee70a0..79f9c3e7018 100644 --- a/appserver/admin/gf_template_web/src/main/resources/config/domain.xml +++ b/appserver/admin/gf_template_web/src/main/resources/config/domain.xml @@ -259,6 +259,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext @@ -468,6 +470,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext diff --git a/appserver/admin/production_domain_template/src/main/resources/config/domain.xml b/appserver/admin/production_domain_template/src/main/resources/config/domain.xml index b2044d012e9..062b943a964 100644 --- a/appserver/admin/production_domain_template/src/main/resources/config/domain.xml +++ b/appserver/admin/production_domain_template/src/main/resources/config/domain.xml @@ -212,7 +212,9 @@ [1.8.0u121|1.8.0u160]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.7.jar [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar - [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext @@ -408,7 +410,9 @@ [1.8.0u121|1.8.0u160]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.7.jar [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar - [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext diff --git a/appserver/admin/production_domain_template_web/src/main/resources/config/domain.xml b/appserver/admin/production_domain_template_web/src/main/resources/config/domain.xml index 7300bcf3c94..f21020eb4e7 100644 --- a/appserver/admin/production_domain_template_web/src/main/resources/config/domain.xml +++ b/appserver/admin/production_domain_template_web/src/main/resources/config/domain.xml @@ -235,6 +235,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext @@ -425,6 +427,8 @@ [1.8.0u161|1.8.0u190]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.jar [1.8.0u191|1.8.0u500]-Xbootclasspath/p:${com.sun.aas.installRoot}/lib/grizzly-npn-bootstrap-1.8.1.jar [9|]-Xbootclasspath/a:${com.sun.aas.installRoot}/lib/grizzly-npn-api.jar + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext diff --git a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java index 85db644261a..e6e70ef8a1e 100644 --- a/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java +++ b/appserver/appclient/client/acc/src/main/java/org/glassfish/appclient/client/CLIBootstrap.java @@ -115,6 +115,9 @@ public class CLIBootstrap { private final static String[] ENV_VARS = { "_AS_INSTALL", "APPCPATH", "VMARGS" }; + private final static String EXT_DIRS_INTRODUCER = "-Djava.ext.dirs"; + private final static String ENDORSED_DIRS_INTRODUCER = "-Djava.endorsed.dirs"; + private static final LocalStringManager localStrings = new LocalStringManagerImpl(CLIBootstrap.class); private JavaInfo java; @@ -125,7 +128,7 @@ public class CLIBootstrap { * set up during init with various subtypes of command line elements */ private CommandLineElement - accValuedOptions, accUnvaluedOptions, + extDirs, endorsedDirs, accValuedOptions, accUnvaluedOptions, jvmPropertySettings, jvmValuedOptions, otherJVMOptions, arguments; /** arguments passed to the ACC Java agent */ @@ -236,7 +239,16 @@ private static void envToProps() { * Assign the various command line element matchers. See the * descriptions of each subtype for what each is used for. */ - + extDirs = new OverridableDefaultedPathBasedOption( + EXT_DIRS_INTRODUCER, + userVMArgs.evExtDirs, + java.ext().getAbsolutePath(), + gfInfo.extPaths()); + endorsedDirs = new OverridableDefaultedPathBasedOption( + ENDORSED_DIRS_INTRODUCER, + userVMArgs.evEndorsedDirs, + java.endorsed().getAbsolutePath(), + gfInfo.endorsedPaths()); accValuedOptions = new ACCValuedOption(ACC_VALUED_OPTIONS_PATTERN); accUnvaluedOptions = new ACCUnvaluedOption(ACC_UNVALUED_OPTIONS_PATTERN); jvmPropertySettings = new JVMOption("-D.*", userVMArgs.evJVMPropertySettings); @@ -257,27 +269,44 @@ private void initCommandLineElements() { * patterns are from most specific to most general. */ elementsInScanOrder = new CommandLineElement[] { - accValuedOptions, - accUnvaluedOptions, - jvmValuedOptions, - jvmPropertySettings, - jvmMainSetting, - otherJVMOptions, - arguments }; + extDirs, + endorsedDirs, + accValuedOptions, + accUnvaluedOptions, + jvmValuedOptions, + jvmPropertySettings, + jvmMainSetting, + otherJVMOptions, + arguments}; /* * Add the elements in this order so they appear in the generated java command in the correct positions. */ - //In JDK 9 and later ext and endorsed directory removed . - elementsInOutputOrder = new CommandLineElement[] { - jvmValuedOptions, - jvmPropertySettings, - otherJVMOptions, - accUnvaluedOptions, - accValuedOptions, - jvmMainSetting, - arguments - }; + //In JDK 9 and later ext and endorsed directory removed. + int major = JDK.getMajor(); + if (major >= 9) { + elementsInOutputOrder = new CommandLineElement[]{ + jvmValuedOptions, + jvmPropertySettings, + otherJVMOptions, + accUnvaluedOptions, + accValuedOptions, + jvmMainSetting, + arguments + }; + } else { + elementsInOutputOrder = new CommandLineElement[]{ + jvmValuedOptions, + jvmPropertySettings, + otherJVMOptions, + extDirs, + endorsedDirs, + accUnvaluedOptions, + accValuedOptions, + jvmMainSetting, + arguments + }; + } } @@ -782,7 +811,8 @@ private boolean nextLooksOK(final String[] args, final int slot) { * the user specifies one of these options on the command line then we discard the Java installation values and append * the GlassFish values to the user's values. *

- * If the user does not specify the property then the user would + * This is used for handling java.ext.dirs and java.endorsed.dirs property + * settings. If the user does not specify the property then the user would * expect the Java-provided directories to be used. We need to * specify the GlassFish ones, so that means we need combine the GlassFish * ones and the default JVM ones explicitly. @@ -1047,6 +1077,12 @@ File configxml() { return configXMLFile; } + String[] endorsedPaths() { + return new String[] { + new File(lib, "endorsed").getAbsolutePath(), + new File(modules, "endorsed").getAbsolutePath()}; + } + String extPaths() { return new File(lib, "ext").getAbsolutePath(); } @@ -1108,6 +1144,10 @@ File ext() { return new File(lib(), "ext"); } + File endorsed() { + return new File(lib(), "endorsed"); + } + File lib() { return new File(jreHome, "lib"); } @@ -1128,6 +1168,8 @@ String pathSeparator() { */ class UserVMArgs { + private CommandLineElement evExtDirs; + private CommandLineElement evEndorsedDirs; private CommandLineElement evJVMPropertySettings; private CommandLineElement evJVMValuedOptions; private CommandLineElement evOtherJVMOptions; @@ -1139,6 +1181,18 @@ class UserVMArgs { if (isDebug) { System.err.println("VMARGS = " + (vmargs == null ? "null" : vmargs)); } + + evExtDirs = new OverridableDefaultedPathBasedOption( + EXT_DIRS_INTRODUCER, + null, + java.ext().getAbsolutePath(), + gfInfo.extPaths()); + + evEndorsedDirs = new OverridableDefaultedPathBasedOption( + ENDORSED_DIRS_INTRODUCER, + null, + java.endorsed().getAbsolutePath(), + gfInfo.endorsedPaths()); evJVMPropertySettings = new JVMOption("-D.*", null); evJVMValuedOptions = new JVMValuedOption(JVM_VALUED_OPTIONS_PATTERN, null); @@ -1154,6 +1208,8 @@ class UserVMArgs { } private void initEVCommandLineElements() { + evElements.add(evExtDirs); + evElements.add(evEndorsedDirs); evElements.add(evJVMPropertySettings); evElements.add(evJVMValuedOptions); evElements.add(evOtherJVMOptions); diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/ExtensionFileManager.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/ExtensionFileManager.java new file mode 100644 index 00000000000..52f2b4f96cc --- /dev/null +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/ExtensionFileManager.java @@ -0,0 +1,547 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) 1997-2014 Oracle and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html + * or packager/legal/LICENSE.txt. See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at packager/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * Oracle designates this particular file as subject to the "Classpath" + * exception as provided by Oracle in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +// Portions Copyright [2019] [Payara Foundation and/or its affiliates] + +package org.glassfish.appclient.server.core.jws; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.URI; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.inject.Inject; +import org.glassfish.internal.api.ServerContext; + +import org.jvnet.hk2.annotations.Service; +import org.glassfish.hk2.api.PostConstruct; +import javax.inject.Singleton; +import org.glassfish.logging.annotation.LogMessageInfo; + +/** + * Manages a data structure of all extension jars known to the app server. + *

+ * This class builds a map of extension name to an + * instance of the inner class Extension that records information about that + * extension jar. An Extension is created for every jar file in any of the + * directories specified by java.ext.dirs. + *

+ * Later, a caller can use the findExtensionTransitiveClosure method, passing + * a jar file manifest's main attributes and receiving back a List of Extension objects representing + * all extension jars referenced directly or indirectly from that jar. + * + * @author tjquinn + */ +@Service +@Singleton +public class ExtensionFileManager implements PostConstruct { + + /** the property name that points to extension directories */ + private static final String EXT_DIRS_PROPERTY_NAME = "java.ext.dirs"; + + private Logger _logger = Logger.getLogger(JavaWebStartInfo.APPCLIENT_SERVER_MAIN_LOGGER, + JavaWebStartInfo.APPCLIENT_SERVER_LOGMESSAGE_RESOURCE); + + @LogMessageInfo( + message = "The following extensions or libraries are referenced from the manifest of {0} but were not found where indicated: {1}; ignoring and continuing", + cause = "The server could not open the JAR file(s) or process the extension(s) listed in its manifest.", + action = "Make sure the manifest of the JAR file correctly lists the relative paths of library JARs and the extensions on which the JAR depends.") + public static final String EXT_ERROR = "AS-ACDEPL-00112"; + + /* + *Stores File and version information for all extension jars in all + *extension jar directories. (any directory listed in java.ext.dirs) + */ + private Map extensionFileInfo = null; + + /** Records directories specified in java.ext.dirs */ + private Vector extensionFileDirs = null; + + @Inject + private ServerContext serverContext; + + @Override + public void postConstruct() { + try { + prepareExtensionInfo(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private void prepareExtensionInfo() throws IOException { + extensionFileDirs = buildExtensionFileDirs(); + extensionFileInfo = buildExtensionFileEntries(extensionFileDirs); + } + + /* + *Returns the collection of extension + *file info objects for the extension jars known to the app server. + *@return Map from extension name to + *@throws IOException in case of error accessing a file as a jar file + */ + public Map getExtensionFileEntries() throws IOException { + return extensionFileInfo; + } + + /** + *Constructs the collection of File objects, one for each extension directory. + *@return Vector containing a File for each extension directory + */ + private Vector buildExtensionFileDirs() { + final URI installRootURI = serverContext.getInstallRoot().toURI(); + Vector result = new Vector(); + + String extDirs = System.getProperty(EXT_DIRS_PROPERTY_NAME); + if(extDirs!=null) { + StringTokenizer stkn = new StringTokenizer(extDirs, File.pathSeparator); + + while (stkn.hasMoreTokens()) { + String extensionDirPath = stkn.nextToken(); + final File extDir = new File(extensionDirPath); + /* + * Add the extensions directory only if it falls within the app + * server directory. Otherwise we might add + * Java-provided extensions and serve them to Java Web Start-launched + * clients, which we do not want. + */ + final URI extDirURI = extDir.toURI(); + if (!installRootURI.relativize(extDirURI).equals(extDirURI)) { + result.add(extDir); + } + } + } + return result; + } + + /** + * Constructs the collection of extension files known to the app server. + * @param dirs the directories in which to search for extension jar files + * @return Map mapping the extension name and spec version to the extension jar entry + * @throws IOException in case of errors processing jars in the extension directories + */ + private Map buildExtensionFileEntries(Vector dirs) throws IOException { + + /* + *For each extension directory, collect all jar files + *and add an entry (containing File and spec version string) for each + *file into the data structure. + */ + Map result = new HashMap(); + + for (int i = 0; i < dirs.size(); i++) { + addExtJarsFromDirectory(result, i, dirs.get(i)); + } + return result; + } + + /** + *Create the collection of extension directories. + *@return Vector of File objects, one for each directory. + */ + /** + * Adds entries for the extension files from one directory to the indicated Map. + * @param extensionFilesMap map of each extension name to its Extension + * @param extensionDirNumber the ordinal number of the directory being processed + * @param extDirPath the current directory being processed + * @throws IOException in case of error scanning for jar files + */ + private void addExtJarsFromDirectory(Map map, int extensionDirNumber, File extDir) throws IOException { + File [] extJars = extDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".jar"); + } + }); + if (extJars != null) { + for (File file : extJars) { + Extension entry = buildExtensionForJar(file, extensionDirNumber); + if (entry != null) { + map.put(entry.extensionKey, entry); + } + } + } + } + + /** + * Creates an extension Extension for a jar file if the jar is in fact an extension. + * @param jarFile a File object for the jar to use + * @param extDirectoryNumber the ordinal number of the directory in java.ext.dirs being scanned + * @return Extension for the jar if the jar has an extension name; null otherwise + * @throws IOException in case of errors working with the file + */ + private Extension buildExtensionForJar(File file, int extDirectoryNumber) throws IOException { + Extension result = null; + JarFile jarFile = null; + try { + jarFile = new JarFile(file); + ExtensionKey key = getDefinedExtensionKey(jarFile); + if (key != null) { + result = new Extension(key, file, extDirectoryNumber); + } + return result; + } finally { + if (jarFile != null) { + jarFile.close(); + } + } + } + + /** + * Constructs a List of Extension objects corresponding to jars required to + * satisfy an extension chain. + *

+ * The transitive closure includes any extensions required by the + * initial jar, its Class-Path jars, and any extensions required + * by extensions. + * @param anchorDir the directory relative to which Class-Path manifest entries are evaluated (if relative) + * @param mainAttrs the main attributes from a jar file whose extensions are to be satisfied + * @return List containing an Extension object for each required jar + * @throws IOException in case of errors building the extension jar file data structure + */ + public Set findExtensionTransitiveClosure(final File origAnchorDir, Attributes mainAttrs) throws IOException { + File anchorDir = origAnchorDir; + if ( ! origAnchorDir.isDirectory()) { + anchorDir = origAnchorDir.getParentFile(); + } + final StringBuilder invalidLibPaths = new StringBuilder(); + + Set result = new HashSet(); + + Vector filesToProcess = new Vector(); + + filesToProcess.addAll(getClassPathJars(mainAttrs)); + + Set extensionsUsedByApp = getReferencedExtensions(mainAttrs); + result.addAll(extensionsUsedByApp); + filesToProcess.addAll(extensionsToFiles(extensionsUsedByApp)); + + /** + *Do not use the for/each construct next because the loop may add + *elements to the vector and for/each would throw a concurrent + *modification exception. + */ + for (int i = 0; i < filesToProcess.size(); i++) { + File nextFile = filesToProcess.get(i); + final File absNextFile = nextFile.isAbsolute() ? nextFile : new File(anchorDir, nextFile.getPath()); + /* + *The Class-Path entry might point to a directory. If so, skip it + *because directories do not support extensions. + */ + if (absNextFile.exists() && absNextFile.isDirectory()) { + continue; + } + + try { + JarFile nextJarFile = new JarFile(absNextFile); + try { + Attributes attrs = getMainAttrs(nextJarFile); + Set newExtensions = getReferencedExtensions(attrs); + result.addAll(newExtensions); + filesToProcess.addAll(extensionsToFiles(newExtensions)); + } finally { + nextJarFile.close(); + } + } catch (Exception e) { + invalidLibPaths.append(nextFile.getPath()).append(" "); + } + } + if (invalidLibPaths.length() > 0) { + _logger.log(Level.WARNING, EXT_ERROR, + new Object[] {origAnchorDir, invalidLibPaths.toString()}); + + } + return result; + } + + /** + *Returns a Set of File objects corresponding to the supplied set of Extensions. + *@param extensions set of Extension the files of which are of interest + *@return set of File, one File for each Extension in the input set + */ + private Set extensionsToFiles(Set extensions) { + Set result = new HashSet(); + for (Extension e : extensions) { + result.add(e.file); + } + return result; + } + + /** + *Returns a Set of Extensions that are referenced by the jar file whose + *main attributes are passed. + *@param mainAttrs the main attributes from a jar file's manifest + *@return Set of Extension objects corresponding to the extensions referenced by the attributes + *@throws IOException if an extension jar is required but not found + */ + private Set getReferencedExtensions(Attributes mainAttrs) throws IOException { + Map result = new HashMap(); + Set extensionKeys = getReferencedExtensionKeys(mainAttrs); + + for (ExtensionKey key : extensionKeys) { + if ( ! result.containsKey(key)) { + Extension extension = extensionFileInfo.get(key); + + /* + *Add this extension only if it does not already appear + *in the result collection. In that case, also add the + *file to the collection of files to be processed. + */ + if (extension != null) { + result.put(key, extension); + } else { + throw new IOException("Jar file requires the extension " + key + " but it is not in the known extensions " + extensionFileInfo); + } + } + } + return new HashSet(result.values()); + } + + /** + *Returns the main attributes (if any) object from a jar file. + *@param jarFile the JarFile of interest + *@return Attributes object for the jar file's main attributes. + *@throws IOException in case of error getting the Jar file's manifest + */ + private Attributes getMainAttrs(JarFile jarFile) throws IOException { + Attributes result = null; + + Manifest mf = jarFile.getManifest(); + if (mf != null) { + result = mf.getMainAttributes(); + } + return result; + } + + /** + *Returns the Files corresponding to the Class-Path entries (if any) in a + *Jar file's main attributes. + *@param anchorDir the directory to which relative Class-Path entries are resolved + *@param mainAttrs the jar file's main attributes (which would contain Class-Path entries if there are any) + */ + private List getClassPathJars(Attributes mainAttrs) { + List result = new LinkedList(); + String classPathList = mainAttrs.getValue(Attributes.Name.CLASS_PATH); + if (classPathList != null) { + StringTokenizer stkn = new StringTokenizer(classPathList, " "); + while (stkn.hasMoreTokens()) { + String classPathJarPath = stkn.nextToken(); + File classPathJarFile = new File(classPathJarPath); + result.add(classPathJarFile); + } + } + return result; + } + + /** + *Returns the ExtensionKey for the extension which the specified JarFile provides (if any). + *@param jarFile the JarFile which may be an extension jar + *@returns the ExtensionKey for the extension if this jar is one; null otherwise + *@throws IOException in case of error getting the jar file's main attributes + */ + private ExtensionKey getDefinedExtensionKey(JarFile jarFile) throws IOException { + ExtensionKey result = null; + + Attributes mainAttrs = getMainAttrs(jarFile); + if (mainAttrs != null) { + String extName = mainAttrs.getValue(Attributes.Name.EXTENSION_NAME); + if (extName != null) { + String specVersion = mainAttrs.getValue(Attributes.Name.SPECIFICATION_VERSION); + result = new ExtensionKey(extName, specVersion); + } + } + + return result; + } + + /** + *Returns the ExtensionKeys for the extension jars referenced by the specified main attributes + *@param mainAttrs the main attributes from a jar file that may refer to extension jars + *@return Set of ExtensionKey, one key or each distinct extension jar that is referenced + */ + private Set getReferencedExtensionKeys(Attributes mainAttrs) { + Set result = new HashSet(); + + if (mainAttrs != null) { + String extensionList = mainAttrs.getValue(Attributes.Name.EXTENSION_LIST); + if (extensionList != null) { + StringTokenizer stkn = new StringTokenizer(extensionList, " "); + while (stkn.hasMoreTokens()) { + /* + *For each extension jar in this jar's list, create a new + *ExtensionKey using the name and spec version. + */ + String token = stkn.nextToken().trim(); + String extName = mainAttrs.getValue(token + "-" + Attributes.Name.EXTENSION_NAME); + String specVersion = mainAttrs.getValue(token + "-" + Attributes.Name.SPECIFICATION_VERSION); + ExtensionKey key = new ExtensionKey(extName, specVersion); + result.add(key); + } + } + } + return result; + } + + /** + * The key for identifying extension jar Extension objects in the Map. The key + * needs to include both the extension name and the specification version. + * Note that the spec version defaults to the empty string. + */ + public static class ExtensionKey { + private String extensionName = null; + + private String specificationVersion = null; + + /** + * Creates a new instance of ExtensionKey. + * @param extensionName the extension name of interest (cannot be null) + * @param specificationVersion the spec version of interest + */ + public ExtensionKey(String extensionName, String specificationVersion) { + assert extensionName != null : "extensionName is null"; + this.extensionName = extensionName; + this.specificationVersion = (specificationVersion != null) ? specificationVersion : ""; + } + + @Override + public boolean equals(Object other) { + boolean result = false; + if (other != null) { + if (other == this) { + result = true; + } else { + if (other instanceof ExtensionKey) { + ExtensionKey otherEntryKey = (ExtensionKey) other; + result = extensionName.equals(otherEntryKey.extensionName) && + specificationVersion.equals(otherEntryKey.specificationVersion); + } + } + } + return result; + } + + @Override + public int hashCode() { + int result = 17; + result = 37 * result + extensionName.hashCode(); + result = 37 * result + specificationVersion.hashCode(); + return result; + } + + @Override + public String toString() { + return "Name=" + extensionName + ", spec version = " + specificationVersion; + } + } + + /** + *Records information about an extension jar file known to the app server. + */ + public class Extension { + + private ExtensionKey extensionKey; + + private File file = null; + + /** in case the same extension appears in more than one extension directory */ + private int extDirectoryNumber = -1; + + public Extension(ExtensionKey extensionKey, File file, int extDirectoryNumber) { + assert extensionKey != null : "extensionKey is null"; + assert file != null : "file is null"; + + this.extensionKey = extensionKey; + this.file = file; + this.extDirectoryNumber = extDirectoryNumber; + } + + @Override + public boolean equals(Object other) { + boolean result = false; + if (other != null) { + if (other == this) { + result = true; + } else { + if (other instanceof Extension) { + Extension otherEntry = (Extension) other; + result = extensionKey.equals(otherEntry.extensionKey) && + file.equals(otherEntry.file) && + extDirectoryNumber == otherEntry.extDirectoryNumber; + } + } + } + return result; + } + + @Override + public int hashCode() { + int result = 17; + result = result * 37 + extensionKey.hashCode(); + result = result * 37 + file.hashCode(); + result = result * 37 + extDirectoryNumber; + return result; + } + + public int getExtDirectoryNumber() { + return extDirectoryNumber; + } + + public File getFile() { + return file; + } + + @Override + public String toString() { + return extensionKey.toString() + ", file = " + file.getAbsolutePath() + ", in ext dir " + extDirectoryNumber + "(" + extensionFileDirs.get(extDirectoryNumber).getAbsolutePath(); + } + } +} + diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java index 497f504883d..b1c9a0c95f0 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JWSAdapterManager.java @@ -309,6 +309,16 @@ private synchronized File libDir() { return new File(new File(installRootURI), "lib"); } + static String publicExtensionHref(final ExtensionFileManager.Extension ext) { + return NamingConventions.JWSAPPCLIENT_SYSTEM_PREFIX + "/" + publicExtensionLookupURIText(ext); + } + + static String publicExtensionLookupURIText(final ExtensionFileManager.Extension ext) { + return NamingConventions.JWSAPPCLIENT_EXT_INTRODUCER + "/" + + ext.getExtDirectoryNumber() + "/" + + ext.getFile().getName(); + } + private AutoSignedContent systemJarSignedContent ( final File unsignedFile, final String signingAlias) throws FileNotFoundException { diff --git a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java index 765410e1ae0..f76a5b8be5d 100644 --- a/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java +++ b/appserver/appclient/server/core/src/main/java/org/glassfish/appclient/server/core/jws/JavaWebStartInfo.java @@ -58,6 +58,9 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; @@ -112,6 +115,9 @@ public class JavaWebStartInfo implements ConfigListener { @Inject private DeveloperContentHandler dch; + @Inject + private ExtensionFileManager extensionFileManager; + @Inject private ServerEnvironment serverEnv; @@ -370,6 +376,65 @@ private void startJWSServices() throws EndpointRegistrationException, IOExceptio JWSAdapterManager.userFriendlyContextRoot(acServerApp)}); } + private void processExtensionReferences() throws IOException { + + // TODO: needs to be expanded to handle signed library JARS, perhap signed by different certs + final URI fileURI = URI.create("file:" + helper.appClientServerOriginalAnchor(dc).getRawSchemeSpecificPart()); + Set exts = extensionFileManager.findExtensionTransitiveClosure( + new File(fileURI), + //new File(helper.appClientServerURI(dc)).getParentFile(), + dc.getSource().getManifest().getMainAttributes()); + tHelper.setProperty(APP_LIBRARY_EXTENSION_PROPERTY_NAME, + jarElementsForExtensions(exts)); + for (ExtensionFileManager.Extension e : exts) { + final URI uri = URI.create(JWSAdapterManager.publicExtensionLookupURIText(e)); + final StaticContent newSystemContent = createSignedStaticContent( + e.getFile(), + signedFileForDomainFile(e.getFile()), + uri, + extensionName(e.getFile())); + jwsAdapterManager.addStaticSystemContent( + uri.toString(), + newSystemContent); + } + + } + + private String extensionName(final File f) throws IOException { + JarFile jf = null; + try { + jf = new JarFile(f); + final Manifest mf = jf.getManifest(); + final Attributes mainAttrs = mf.getMainAttributes(); + final String extName = mainAttrs.getValue(Attributes.Name.EXTENSION_NAME); + return (extName == null ? "" : extName); + } finally { + if (jf != null) { + jf.close(); + } + } + } + + private File signedFileForDomainFile(final File unsignedFile) { + + final File rootForSignedFilesInDomain = jwsAdapterManager.rootForSignedFilesInDomain(); + mkdirs(rootForSignedFilesInDomain); + final URI signedFileURI = rootForSignedFilesInDomain.toURI().resolve(relativeURIToDomainFile(unsignedFile)); + return new File(signedFileURI); + } + + private URI relativeURIToDomainFile(final File domainFile) { + return serverEnv.getInstanceRoot().toURI().relativize(domainFile.toURI()); + } + + private String jarElementsForExtensions(final Set exts) { + final StringBuilder sb = new StringBuilder(); + for (ExtensionFileManager.Extension e : exts) { + sb.append(""); + } + return sb.toString(); + } + private void stopJWSServices() throws EndpointRegistrationException { /* * Mark all this client's content as stopped so the Grizzly adapter @@ -487,6 +552,12 @@ private void initClientStaticContent() acServerApp.getDescriptor().getName()); } + /* + * Add static content representing any extension libraries this client + * (or the JARs it depends on) uses. + */ + processExtensionReferences(); + /* * Make sure that there are versions of all GF system JARs * that are signed by the same cert used to sign the facade JAR for diff --git a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/DriverLoader.java b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/DriverLoader.java index b1503e03d20..1728bddcd3b 100644 --- a/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/DriverLoader.java +++ b/appserver/connectors/connectors-runtime/src/main/java/com/sun/enterprise/connectors/util/DriverLoader.java @@ -342,6 +342,27 @@ private Set getImplClassesByIteration(File f, String resType, return implClassNames; } + /** + * Get the library locations corresponding to the ext directories mentioned + * as part of the jvm-options. + */ + private Vector getLibExtDirs() { + String extDirStr = System.getProperty("java.ext.dirs"); + logger.log(Level.FINE, "lib/ext dirs : " + extDirStr); + + Vector extDirs = new Vector(); + StringTokenizer st = new StringTokenizer(extDirStr, File.pathSeparator); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if(logger.isLoggable(Level.FINE)) { + logger.log(Level.FINE,"Ext Dir : " + token); + } + extDirs.addElement(token); + } + + return extDirs; + } + /** * Returns a list of all driver class names that were loaded from the jar file. * @param f @@ -555,6 +576,10 @@ private List getJdbcDriverLocations() { jarFileLocations.add(getLocation(SystemPropertyConstants.DERBY_ROOT_PROPERTY)); jarFileLocations.add(getLocation(SystemPropertyConstants.INSTALL_ROOT_PROPERTY)); jarFileLocations.add(getLocation(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY)); + Vector extLibDirs = getLibExtDirs(); + for (int i = 0; i < extLibDirs.size(); i++) { + jarFileLocations.add(new File((String) extLibDirs.elementAt(i))); + } return jarFileLocations; } diff --git a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/io/DeploymentDescriptorFile.java b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/io/DeploymentDescriptorFile.java index 1ef8a5c8c61..95ec643f73a 100644 --- a/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/io/DeploymentDescriptorFile.java +++ b/appserver/deployment/dol/src/main/java/com/sun/enterprise/deployment/io/DeploymentDescriptorFile.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -//Portions Copyright [2016-2018] [Payara Foundation and/or its affiliates] +//Portions Copyright [2016-2019] [Payara Foundation and/or its affiliates] package com.sun.enterprise.deployment.io; @@ -128,16 +128,16 @@ public SAXParser getSAXParser (boolean validating) { // set the namespace awareness spf.setNamespaceAware(true); - // turn validation on for deployment descriptor XML files + // turn validation on for deployment descriptor XML files spf.setValidating(validating); if(!validating) { spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); } - - //support for older charset names used in java.io and java.lang + + //support for older charset names used in java.io and java.lang spf.setFeature("http://apache.org/xml/features/allow-java-encodings", true); - try { + try { if (!validating) { // if we are not validating, let's not load the DTD if (getDeploymentDescriptorPath().contains(DescriptorConstants.WLS)) { @@ -146,41 +146,41 @@ public SAXParser getSAXParser (boolean validating) { } } - // Validation part 2a: set the schema language if necessary - spf.setFeature("http://apache.org/xml/features/validation/schema",validating); - - SAXParser sp = spf.newSAXParser(); - + // Validation part 2a: set the schema language if necessary + spf.setFeature("http://apache.org/xml/features/validation/schema", validating); + + SAXParser sp = spf.newSAXParser(); + // put the default schema for this deployment file type String path = getDefaultSchemaSource(); - if (path!=null) { - sp.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation",path); + if (path != null) { + sp.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", path); } - // Set Xerces feature to allow dynamic validation. This prevents - // SAX errors from being reported when no schemaLocation attr - // is seen for a DTD based (J2EE1.3) XML descriptor. - sp.getXMLReader().setFeature( - "http://apache.org/xml/features/validation/dynamic", validating); - - return sp; - + // Set Xerces feature to allow dynamic validation. This prevents + // SAX errors from being reported when no schemaLocation attr + // is seen for a DTD based (J2EE1.3) XML descriptor. + sp.getXMLReader().setFeature( + "http://apache.org/xml/features/validation/dynamic", validating); + + return sp; + } catch (SAXNotRecognizedException x) { // This can happen if the parser does not support JAXP 1.2 DOLUtils.getDefaultLogger().log(Level.SEVERE, - "INFO: JAXP SAXParser property not recognized: " - + SaxParserHandler.JAXP_SCHEMA_LANGUAGE); - DOLUtils.getDefaultLogger().log(Level.SEVERE, - "Check to see if parser conforms to JAXP 1.2 spec."); + "INFO: JAXP SAXParser property not recognized: " + + SaxParserHandler.JAXP_SCHEMA_LANGUAGE); + DOLUtils.getDefaultLogger().log(Level.SEVERE, + "Check to see if parser conforms to JAXP 1.2 spec."); - } + } } catch (Exception e) { DOLUtils.getDefaultLogger().log(Level.SEVERE, "enterprise.deployment.backend.saxParserError", - new Object[]{e.getMessage()}); + new Object[]{e.getMessage()}); DOLUtils.getDefaultLogger().log(Level.WARNING, "Error occurred", e); } finally { - Thread.currentThread().setContextClassLoader(currentLoader); + Thread.currentThread().setContextClassLoader(currentLoader); } return null; } diff --git a/appserver/extras/embedded/all/src/main/resources/config/domain.xml b/appserver/extras/embedded/all/src/main/resources/config/domain.xml index edac22ba0cb..a134c5ca11b 100644 --- a/appserver/extras/embedded/all/src/main/resources/config/domain.xml +++ b/appserver/extras/embedded/all/src/main/resources/config/domain.xml @@ -204,14 +204,14 @@ -Djavax.xml.accessExternalSchema=all -Djavax.management.builder.initial=com.sun.enterprise.v3.admin.AppServerMBeanServerBuilder -XX:+UnlockDiagnosticVMOptions - -Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed -Djava.security.policy=${com.sun.aas.instanceRoot}/config/server.policy -Djava.security.auth.login.config=${com.sun.aas.instanceRoot}/config/login.conf -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as -Xmx512m -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks - -Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext -Djdbc.drivers=org.apache.derby.jdbc.ClientDriver -DANTLR_USE_DIRECT_CLASS_LOADING=true -Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory diff --git a/appserver/extras/embedded/web/src/main/resources/config/domain.xml b/appserver/extras/embedded/web/src/main/resources/config/domain.xml index 214df500753..92d4d4d97af 100644 --- a/appserver/extras/embedded/web/src/main/resources/config/domain.xml +++ b/appserver/extras/embedded/web/src/main/resources/config/domain.xml @@ -197,14 +197,14 @@ -Djavax.xml.accessExternalSchema=all -Djavax.management.builder.initial=com.sun.enterprise.v3.admin.AppServerMBeanServerBuilder -XX:+UnlockDiagnosticVMOptions - -Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed -Djava.security.policy=${com.sun.aas.instanceRoot}/config/server.policy -Djava.security.auth.login.config=${com.sun.aas.instanceRoot}/config/login.conf -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as -Xmx512m -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks - -Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext -Djdbc.drivers=org.apache.derby.jdbc.ClientDriver -DANTLR_USE_DIRECT_CLASS_LOADING=true -Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory diff --git a/appserver/security/jacc.provider.file/src/main/java/com/sun/enterprise/security/provider/PolicyParser.java b/appserver/security/jacc.provider.file/src/main/java/com/sun/enterprise/security/provider/PolicyParser.java index a6ae3ba3587..964bd8bf112 100644 --- a/appserver/security/jacc.provider.file/src/main/java/com/sun/enterprise/security/provider/PolicyParser.java +++ b/appserver/security/jacc.provider.file/src/main/java/com/sun/enterprise/security/provider/PolicyParser.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2018] [Payara Foundation and/or its affiliates] +// Portions Copyright [2018-2019] [Payara Foundation and/or its affiliates] package com.sun.enterprise.security.provider; import java.io.*; @@ -97,6 +97,12 @@ public class PolicyParser { // needs to be public for PolicyTool public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME"; + private static final String EXTDIRS_PROPERTY = "java.ext.dirs"; + private static final String OLD_EXTDIRS_EXPANSION = "${" + EXTDIRS_PROPERTY + "}"; + + // package-private: used by PolicyFile for static policy + static final String EXTDIRS_EXPANSION = "${{" + EXTDIRS_PROPERTY + "}}"; + private Vector grantEntries; // Convenience variables for parsing @@ -507,9 +513,33 @@ else if (alias.length() > 0) if (e.signedBy != null) { e.signedBy = expand(e.signedBy); } - + if (e.codeBase != null) { - e.codeBase = expand(e.codeBase, true).replace(File.separatorChar, '/'); + // For backward compatibility with 1.4 + if (e.codeBase.equals(OLD_EXTDIRS_EXPANSION)) { + e.codeBase = EXTDIRS_EXPANSION; + } + int es; + if ((es = e.codeBase.indexOf(EXTDIRS_EXPANSION)) < 0) { + e.codeBase = expand(e.codeBase, true).replace(File.separatorChar, '/'); + } else { + // expand the system property "java.ext.dirs", + // parse it into its path components, + // and then create a grant entry for each component + String[] extDirs = parseExtDirs(e.codeBase, es); + if (extDirs != null && extDirs.length > 0) { + for (int i = 0; i < extDirs.length; i++) { + GrantEntry newGe = (GrantEntry) e.clone(); + newGe.codeBase = extDirs[i]; + add(newGe); + + if (debug != null) { + debug.println("creating policy entry for " + "expanded java.ext.dirs path:\n\t\t" + extDirs[i]); + } + } + } + ignoreEntry = true; + } } } catch (PropertyExpander.ExpandException peee) { if (debug != null) { @@ -555,6 +585,36 @@ private PermissionEntry parsePermissionEntry() throws ParsingException, IOExcept return e; } + // package-private: used by PolicyFile for static policy + static String[] parseExtDirs(String codebase, int start) { + + String s = System.getProperty(EXTDIRS_PROPERTY); + String globalPrefix = (start > 0 ? codebase.substring(0, start) : "file:"); + int end = start + EXTDIRS_EXPANSION.length(); + String globalSuffix = (end < codebase.length() ? codebase.substring(end) : (String) null); + + String[] dirs = null; + String localSuffix; + if (s != null) { + StringTokenizer st = new StringTokenizer(s, File.pathSeparator); + int count = st.countTokens(); + dirs = new String[count]; + for (int i = 0; i < count; i++) { + File file = new File(st.nextToken()); + dirs[i] = sun.net.www.ParseUtil.encodePath(file.getAbsolutePath()); + + if (!dirs[i].startsWith("/")) { + dirs[i] = "/" + dirs[i]; + } + + localSuffix = (globalSuffix == null ? (dirs[i].endsWith("/") ? "*" : "/*") : globalSuffix); + + dirs[i] = globalPrefix + dirs[i] + localSuffix; + } + } + return dirs; + } + private boolean peekAndMatch(String expect) throws ParsingException, IOException { if (peek(expect)) { match(expect); diff --git a/appserver/web/web-core/src/main/java/org/apache/catalina/util/ExtensionValidator.java b/appserver/web/web-core/src/main/java/org/apache/catalina/util/ExtensionValidator.java index 2d7cbad9f14..4277fd5393b 100644 --- a/appserver/web/web-core/src/main/java/org/apache/catalina/util/ExtensionValidator.java +++ b/appserver/web/web-core/src/main/java/org/apache/catalina/util/ExtensionValidator.java @@ -55,7 +55,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// Portions Copyright [2018] Payara Foundation and/or affiliates +// Portions Copyright [2018-2019] Payara Foundation and/or affiliates package org.apache.catalina.util; @@ -143,6 +143,31 @@ public final class ExtensionValidator { } } + // get the files in the extensions directory + String extensionsDir = System.getProperty("java.ext.dirs"); + if (extensionsDir != null) { + StringTokenizer extensionsTok + = new StringTokenizer(extensionsDir, File.pathSeparator); + while (extensionsTok.hasMoreTokens()) { + File targetDir = new File(extensionsTok.nextToken()); + if (!targetDir.exists() || !targetDir.isDirectory()) { + continue; + } + File[] files = targetDir.listFiles(); + for (int i = 0; i < files.length; i++) { + if (files[i].getName().toLowerCase(Locale.ENGLISH).endsWith(".jar")) { + try { + addSystemResource(files[i]); + } catch (IOException e) { + String msg = MessageFormat.format(rb.getString(LogFacade.FAILED_LOAD_MANIFEST_RESOURCES_EXCEPTION), + files[i]); + log.log(Level.SEVERE, msg, e); + } + } + } + } + } + } diff --git a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/V2ToV3ConfigUpgrade.java b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/V2ToV3ConfigUpgrade.java index db7151293e1..b6f5d12e7c9 100644 --- a/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/V2ToV3ConfigUpgrade.java +++ b/nucleus/admin/server-mgmt/src/main/java/com/sun/enterprise/admin/servermgmt/V2ToV3ConfigUpgrade.java @@ -37,7 +37,7 @@ * only if the new code is made subject to such option by the copyright * holder. */ -// Portions Copyright [2018] [Payara Foundation and/or its affiliates] +// Portions Copyright [2018-2019] [Payara Foundation and/or its affiliates] package com.sun.enterprise.admin.servermgmt; @@ -183,6 +183,7 @@ private boolean ok(String s) { "-Dfelix.fileinstall.disableConfigSave=false", "-Dfelix.fileinstall.log.level=2", "-Djavax.management.builder.initial=com.sun.enterprise.v3.admin.AppServerMBeanServerBuilder", + "-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext", "-Dorg.glassfish.web.rfc2109_cookie_names_enforced=false"}; // these are added to DAS only private static final String[] ADD_LIST_DAS = new String[]{ diff --git a/nucleus/admin/template/src/main/resources/config/domain.xml b/nucleus/admin/template/src/main/resources/config/domain.xml index feb594660c6..b4f62e9bd95 100644 --- a/nucleus/admin/template/src/main/resources/config/domain.xml +++ b/nucleus/admin/template/src/main/resources/config/domain.xml @@ -161,14 +161,14 @@ -Djava.awt.headless=true -Djavax.management.builder.initial=com.sun.enterprise.v3.admin.AppServerMBeanServerBuilder -XX:+UnlockDiagnosticVMOptions - -Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed + [|8]-Djava.endorsed.dirs=${com.sun.aas.installRoot}/modules/endorsed${path.separator}${com.sun.aas.installRoot}/lib/endorsed -Djava.security.policy=${com.sun.aas.instanceRoot}/config/server.policy -Djava.security.auth.login.config=${com.sun.aas.instanceRoot}/config/login.conf -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as -Xmx512m -Djavax.net.ssl.keyStore=${com.sun.aas.instanceRoot}/config/keystore.jks -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks - -Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext + [|8]-Djava.ext.dirs=${com.sun.aas.javaRoot}/lib/ext${path.separator}${com.sun.aas.javaRoot}/jre/lib/ext${path.separator}${com.sun.aas.instanceRoot}/lib/ext -DANTLR_USE_DIRECT_CLASS_LOADING=true