Index: java/org/apache/catalina/core/StandardContext.java
===================================================================
--- java/org/apache/catalina/core/StandardContext.java (revision 1744611)
+++ java/org/apache/catalina/core/StandardContext.java (working copy)
@@ -84,6 +84,7 @@
import org.apache.catalina.ContainerListener;
import org.apache.catalina.Context;
import org.apache.catalina.CredentialHandler;
+import org.apache.catalina.Engine;
import org.apache.catalina.Globals;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleException;
@@ -2479,6 +2480,16 @@
this.threadBindingListener = threadBindingListener;
}
+ public ExtensionValidator getExtensionValidator() {
+ try {
+ // Walking back through the Tomcat hierarchy.
+ // Host -> Engine -> Service -> Server.
+ return ((Engine)getParent().getParent()).getService().getServer().getExtensionValidator();
+ } catch (Exception e) {
+ // Return default ExtensionValidator if any cast exception occurred.
+ return ExtensionValidator.DEFAULT;
+ }
+ }
// ------------------------------------------------------ Public Properties
@@ -5019,7 +5030,7 @@
// Validate required extensions
boolean dependencyCheck = true;
try {
- dependencyCheck = ExtensionValidator.validateApplication
+ dependencyCheck = getExtensionValidator().validateApplication
(getResources(), this);
} catch (IOException ioe) {
log.error(sm.getString("standardContext.extensionValidationError"), ioe);
Index: java/org/apache/catalina/core/StandardServer.java
===================================================================
--- java/org/apache/catalina/core/StandardServer.java (revision 1744611)
+++ java/org/apache/catalina/core/StandardServer.java (working copy)
@@ -173,6 +173,10 @@
private final Object namingToken = new Object();
+ /**
+ * Extension validator that is used to ensure that extensions is fulfilled.
+ */
+ private ExtensionValidator extensionValidator = new ExtensionValidator();
// ------------------------------------------------------------- Properties
@@ -352,6 +356,11 @@
this.catalina = catalina;
}
+ @Override
+ public ExtensionValidator getExtensionValidator(){
+ return extensionValidator;
+ }
+
// --------------------------------------------------------- Server Methods
@@ -855,7 +864,7 @@
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
- ExtensionValidator.addSystemResource(f);
+ extensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
Index: java/org/apache/catalina/Server.java
===================================================================
--- java/org/apache/catalina/Server.java (revision 1744611)
+++ java/org/apache/catalina/Server.java (working copy)
@@ -22,6 +22,7 @@
import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.startup.Catalina;
+import org.apache.catalina.util.ExtensionValidator;
/**
* A Server
element represents the entire Catalina
@@ -219,4 +220,6 @@
* context.
*/
public Object getNamingToken();
+
+ public ExtensionValidator getExtensionValidator();
}
Index: java/org/apache/catalina/util/Extension.java
===================================================================
--- java/org/apache/catalina/util/Extension.java (revision 1744611)
+++ java/org/apache/catalina/util/Extension.java (working copy)
@@ -248,11 +248,51 @@
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Extension)) return false;
- // -------------------------------------------------------- Private Methods
+ Extension extension = (Extension) o;
+ if (extensionName != null ? !extensionName.equals(extension.extensionName)
+ : extension.extensionName != null)
+ return false;
+ if (implementationURL != null ? !implementationURL.equals(extension.implementationURL)
+ : extension.implementationURL != null)
+ return false;
+ if (implementationVendor != null ? !implementationVendor.equals(extension.implementationVendor)
+ : extension.implementationVendor != null)
+ return false;
+ if (implementationVendorId != null ? !implementationVendorId.equals(extension.implementationVendorId)
+ : extension.implementationVendorId != null)
+ return false;
+ if (implementationVersion != null ? !implementationVersion.equals(extension.implementationVersion)
+ : extension.implementationVersion != null)
+ return false;
+ if (specificationVendor != null ? !specificationVendor.equals(extension.specificationVendor)
+ : extension.specificationVendor != null)
+ return false;
+ return specificationVersion != null ? specificationVersion.equals(extension.specificationVersion)
+ : extension.specificationVersion == null;
+ }
+ @Override
+ public int hashCode() {
+ int result = extensionName != null ? extensionName.hashCode() : 0;
+ result = 31 * result + (implementationURL != null ? implementationURL.hashCode() : 0);
+ result = 31 * result + (implementationVendor != null ? implementationVendor.hashCode() : 0);
+ result = 31 * result + (implementationVendorId != null ? implementationVendorId.hashCode() : 0);
+ result = 31 * result + (implementationVersion != null ? implementationVersion.hashCode() : 0);
+ result = 31 * result + (specificationVendor != null ? specificationVendor.hashCode() : 0);
+ result = 31 * result + (specificationVersion != null ? specificationVersion.hashCode() : 0);
+ return result;
+ }
+// -------------------------------------------------------- Private Methods
+
+
+
/**
* Return true
if the first version number is greater than
* or equal to the second; otherwise return false
.
Index: java/org/apache/catalina/util/ExtensionValidator.java
===================================================================
--- java/org/apache/catalina/util/ExtensionValidator.java (revision 1744611)
+++ java/org/apache/catalina/util/ExtensionValidator.java (working copy)
@@ -20,9 +20,10 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
@@ -46,10 +47,17 @@
* @author Greg Murray
* @author Justyna Horwat
*/
-public final class ExtensionValidator {
+public class ExtensionValidator {
private static final Log log = LogFactory.getLog(ExtensionValidator.class);
+ public static final ExtensionValidator DEFAULT = new ExtensionValidator(){
+ @Override
+ public void addSystemResource(File jarFile) throws IOException {
+ throw new UnsupportedOperationException("this is a read-only ExtensionValidator");
+ }
+ };
+
/**
* The string resources for this package.
*/
@@ -56,17 +64,17 @@
private static final StringManager sm =
StringManager.getManager("org.apache.catalina.util");
- private static volatile ArrayList containerAvailableExtensions =
+ private volatile Set containerAvailableExtensions =
null;
- private static final ArrayList containerManifestResources =
- new ArrayList<>();
+ private final Set containerManifestResources =
+ new HashSet<>();
- // ----------------------------------------------------- Static Initializer
+ // ----------------------------------------------------- Constructor
/**
- * This static initializer loads the container level extensions that are
+ * This constructor loads the container level extensions that are
* available to all web applications. This method scans all extension
* directories available via the "java.ext.dirs" System property.
*
@@ -73,7 +81,7 @@
* The System Class-Path is also scanned for jar files that may contain
* available extensions.
*/
- static {
+ public ExtensionValidator(){
// check for container level optional packages
String systemClasspath = System.getProperty("java.class.path");
@@ -88,7 +96,7 @@
File item = new File(classpathItem);
if (item.isFile()) {
try {
- addSystemResource(item);
+ doAddSystemResource(item);
} catch (IOException e) {
log.error(sm.getString
("extensionValidator.failload", item), e);
@@ -123,13 +131,13 @@
* @return true if all required extensions satisfied
* @throws IOException Error reading resources needed for validation
*/
- public static synchronized boolean validateApplication(
+ public synchronized boolean validateApplication(
WebResourceRoot resources,
Context context)
throws IOException {
String appName = context.getName();
- ArrayList appManifestResources = new ArrayList<>();
+ Set appManifestResources = new HashSet<>();
// Web application manifest
WebResource resource = resources.getResource("/META-INF/MANIFEST.MF");
@@ -171,15 +179,8 @@
* @param jarFile The system JAR whose manifest to add
* @throws IOException Error reading JAR file
*/
- public static void addSystemResource(File jarFile) throws IOException {
- try (InputStream is = new FileInputStream(jarFile)) {
- Manifest manifest = getManifest(is);
- if (manifest != null) {
- ManifestResource mre = new ManifestResource(jarFile.getAbsolutePath(), manifest,
- ManifestResource.SYSTEM);
- containerManifestResources.add(mre);
- }
- }
+ public void addSystemResource(File jarFile) throws IOException {
+ doAddSystemResource(jarFile);
}
@@ -205,16 +206,16 @@
*
* @return true if manifest resource file requirements are met
*/
- private static boolean validateManifestResources(String appName,
- ArrayList resources) {
+ private boolean validateManifestResources(String appName,
+ Set resources) {
boolean passes = true;
int failureCount = 0;
- ArrayList availableExtensions = null;
+ Set availableExtensions = null;
Iterator it = resources.iterator();
while (it.hasNext()) {
ManifestResource mre = it.next();
- ArrayList requiredList = mre.getRequiredExtensions();
+ Set requiredList = mre.getRequiredExtensions();
if (requiredList == null) {
continue;
}
@@ -299,21 +300,21 @@
*
* @return HashMap Map of available extensions
*/
- private static ArrayList buildAvailableExtensionsList(
- ArrayList resources) {
+ private Set buildAvailableExtensionsList(
+ Set resources) {
- ArrayList availableList = null;
+ Set availableList = null;
Iterator it = resources.iterator();
while (it.hasNext()) {
ManifestResource mre = it.next();
- ArrayList list = mre.getAvailableExtensions();
+ Set list = mre.getAvailableExtensions();
if (list != null) {
Iterator values = list.iterator();
while (values.hasNext()) {
Extension ext = values.next();
if (availableList == null) {
- availableList = new ArrayList<>();
+ availableList = new HashSet<>();
availableList.add(ext);
} else {
availableList.add(ext);
@@ -331,7 +332,7 @@
* @param inStream Input stream to a WAR or JAR file
* @return The WAR's or JAR's manifest
*/
- private static Manifest getManifest(InputStream inStream) throws IOException {
+ private Manifest getManifest(InputStream inStream) throws IOException {
Manifest manifest = null;
try (JarInputStream jin = new JarInputStream(inStream)) {
manifest = jin.getManifest();
@@ -343,7 +344,7 @@
/**
* Add the JARs specified to the extension list.
*/
- private static void addFolderList(String property) {
+ private void addFolderList(String property) {
// get the files in the extensions directory
String extensionsDir = System.getProperty(property);
@@ -363,7 +364,7 @@
if (files[i].getName().toLowerCase(Locale.ENGLISH).endsWith(".jar") &&
files[i].isFile()) {
try {
- addSystemResource(files[i]);
+ doAddSystemResource(files[i]);
} catch (IOException e) {
log.error
(sm.getString
@@ -376,5 +377,19 @@
}
-
+ /**
+ *
+ * @param jarFile
+ * @throws IOException
+ */
+ private void doAddSystemResource(File jarFile) throws IOException {
+ try (InputStream is = new FileInputStream(jarFile)) {
+ Manifest manifest = getManifest(is);
+ if (manifest != null) {
+ ManifestResource mre = new ManifestResource(jarFile.getAbsolutePath(), manifest,
+ ManifestResource.SYSTEM);
+ containerManifestResources.add(mre);
+ }
+ }
+ }
}
Index: java/org/apache/catalina/util/ManifestResource.java
===================================================================
--- java/org/apache/catalina/util/ManifestResource.java (revision 1744611)
+++ java/org/apache/catalina/util/ManifestResource.java (working copy)
@@ -16,8 +16,9 @@
*/
package org.apache.catalina.util;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
@@ -37,8 +38,8 @@
public static final int WAR = 2;
public static final int APPLICATION = 3;
- private ArrayList availableExtensions = null;
- private ArrayList requiredExtensions = null;
+ private Set availableExtensions = null;
+ private Set requiredExtensions = null;
private final String resourceName;
private final int resourceType;
@@ -64,7 +65,7 @@
*
* @return List of available extensions
*/
- public ArrayList getAvailableExtensions() {
+ public Set getAvailableExtensions() {
return availableExtensions;
}
@@ -73,7 +74,7 @@
*
* @return List of required extensions
*/
- public ArrayList getRequiredExtensions() {
+ public Set getRequiredExtensions() {
return requiredExtensions;
}
@@ -136,9 +137,36 @@
return (sb.toString());
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ManifestResource)) return false;
- // -------------------------------------------------------- Private Methods
+ ManifestResource that = (ManifestResource) o;
+ if (resourceType != that.resourceType) return false;
+ if (availableExtensions != null ? !availableExtensions.equals(that.availableExtensions)
+ : that.availableExtensions != null)
+ return false;
+ if (requiredExtensions != null ? !requiredExtensions.equals(that.requiredExtensions)
+ : that.requiredExtensions != null)
+ return false;
+
+ return resourceName != null ? resourceName.equals(that.resourceName)
+ : that.resourceName == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = availableExtensions != null ? availableExtensions.hashCode() : 0;
+ result = 31 * result + (requiredExtensions != null ? requiredExtensions.hashCode() : 0);
+ result = 31 * result + (resourceName != null ? resourceName.hashCode() : 0);
+ result = 31 * result + resourceType;
+ return result;
+ }
+
+// -------------------------------------------------------- Private Methods
+
private void processManifest(Manifest manifest) {
availableExtensions = getAvailableExtensions(manifest);
requiredExtensions = getRequiredExtensions(manifest);
@@ -154,7 +182,7 @@
* @return List of required extensions, or null if the application
* does not require any extensions
*/
- private ArrayList getRequiredExtensions(Manifest manifest) {
+ private Set getRequiredExtensions(Manifest manifest) {
Attributes attributes = manifest.getMainAttributes();
String names = attributes.getValue("Extension-List");
@@ -161,7 +189,7 @@
if (names == null)
return null;
- ArrayList extensionList = new ArrayList<>();
+ Set extensionList = new HashSet<>();
names += " ";
while (true) {
@@ -201,7 +229,7 @@
* @return List of available extensions, or null if the web application
* does not bundle any extensions
*/
- private ArrayList getAvailableExtensions(Manifest manifest) {
+ private Set getAvailableExtensions(Manifest manifest) {
Attributes attributes = manifest.getMainAttributes();
String name = attributes.getValue("Extension-Name");
@@ -208,7 +236,7 @@
if (name == null)
return null;
- ArrayList extensionList = new ArrayList<>();
+ Set extensionList = new HashSet<>();
Extension extension = new Extension();
extension.setExtensionName(name);