init
This commit is contained in:
296
java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java
Normal file
296
java/org/apache/tomcat/util/scan/AbstractInputStreamJar.java
Normal file
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.apache.tomcat.Jar;
|
||||
import org.apache.tomcat.util.compat.JreCompat;
|
||||
|
||||
/**
|
||||
* Base implementation of Jar for implementations that use a JarInputStream to
|
||||
* access the JAR file.
|
||||
*/
|
||||
public abstract class AbstractInputStreamJar implements Jar {
|
||||
|
||||
private final URL jarFileURL;
|
||||
|
||||
private NonClosingJarInputStream jarInputStream = null;
|
||||
private JarEntry entry = null;
|
||||
private Boolean multiRelease = null;
|
||||
private Map<String,String> mrMap = null;
|
||||
|
||||
public AbstractInputStreamJar(URL jarFileUrl) {
|
||||
this.jarFileURL = jarFileUrl;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URL getJarFileURL() {
|
||||
return jarFileURL;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void nextEntry() {
|
||||
if (jarInputStream == null) {
|
||||
try {
|
||||
reset();
|
||||
} catch (IOException e) {
|
||||
entry = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
entry = jarInputStream.getNextJarEntry();
|
||||
if (multiRelease.booleanValue()) {
|
||||
// Skip base entries where there is a multi-release entry
|
||||
// Skip multi-release entries that are not being used
|
||||
while (entry != null &&
|
||||
(mrMap.keySet().contains(entry.getName()) ||
|
||||
entry.getName().startsWith("META-INF/versions/") &&
|
||||
!mrMap.values().contains(entry.getName()))) {
|
||||
entry = jarInputStream.getNextJarEntry();
|
||||
}
|
||||
} else {
|
||||
// Skip multi-release entries
|
||||
while (entry != null && entry.getName().startsWith("META-INF/versions/")) {
|
||||
entry = jarInputStream.getNextJarEntry();
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
entry = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEntryName() {
|
||||
// Given how the entry name is used, there is no requirement to convert
|
||||
// the name for a multi-release entry to the corresponding base name.
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
return entry.getName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream getEntryInputStream() throws IOException {
|
||||
return jarInputStream;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean entryExists(String name) throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(String name) throws IOException {
|
||||
gotoEntry(name);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
// Clear the entry so that multiple calls to this method for the
|
||||
// same entry will result in a new InputStream for each call
|
||||
// (BZ 60798)
|
||||
entry = null;
|
||||
return jarInputStream;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getLastModified(String name) throws IOException {
|
||||
gotoEntry(name);
|
||||
if (entry == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return entry.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean exists(String name) throws IOException {
|
||||
gotoEntry(name);
|
||||
return entry != null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getURL(String entry) {
|
||||
StringBuilder result = new StringBuilder("jar:");
|
||||
result.append(getJarFileURL().toExternalForm());
|
||||
result.append("!/");
|
||||
result.append(entry);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
reset();
|
||||
return jarInputStream.getManifest();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
closeStream();
|
||||
entry = null;
|
||||
jarInputStream = createJarInputStream();
|
||||
// Only perform multi-release processing on first access
|
||||
if (multiRelease == null) {
|
||||
if (JreCompat.isJre9Available()) {
|
||||
Manifest manifest = jarInputStream.getManifest();
|
||||
if (manifest == null) {
|
||||
multiRelease = Boolean.FALSE;
|
||||
} else {
|
||||
String mrValue = manifest.getMainAttributes().getValue("Multi-Release");
|
||||
if (mrValue == null) {
|
||||
multiRelease = Boolean.FALSE;
|
||||
} else {
|
||||
multiRelease = Boolean.valueOf(mrValue);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
multiRelease = Boolean.FALSE;
|
||||
}
|
||||
if (multiRelease.booleanValue()) {
|
||||
if (mrMap == null) {
|
||||
populateMrMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void closeStream() {
|
||||
if (jarInputStream != null) {
|
||||
try {
|
||||
jarInputStream.reallyClose();
|
||||
} catch (IOException ioe) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected abstract NonClosingJarInputStream createJarInputStream() throws IOException;
|
||||
|
||||
|
||||
private void gotoEntry(String name) throws IOException {
|
||||
boolean needsReset = true;
|
||||
if (multiRelease == null) {
|
||||
reset();
|
||||
needsReset = false;
|
||||
}
|
||||
|
||||
// Need to convert requested name to multi-release name (if one exists)
|
||||
if (multiRelease.booleanValue()) {
|
||||
String mrName = mrMap.get(name);
|
||||
if (mrName != null) {
|
||||
name = mrName;
|
||||
}
|
||||
} else if (name.startsWith("META-INF/versions/")) {
|
||||
entry = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry != null && name.equals(entry.getName())) {
|
||||
return;
|
||||
}
|
||||
if (needsReset) {
|
||||
reset();
|
||||
}
|
||||
|
||||
JarEntry jarEntry = jarInputStream.getNextJarEntry();
|
||||
while (jarEntry != null) {
|
||||
if (name.equals(jarEntry.getName())) {
|
||||
entry = jarEntry;
|
||||
break;
|
||||
}
|
||||
jarEntry = jarInputStream.getNextJarEntry();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void populateMrMap() throws IOException {
|
||||
int targetVersion = JreCompat.getInstance().jarFileRuntimeMajorVersion();
|
||||
|
||||
Map<String,Integer> mrVersions = new HashMap<>();
|
||||
|
||||
JarEntry jarEntry = jarInputStream.getNextJarEntry();
|
||||
|
||||
// Tracking the base name and the latest valid version found is
|
||||
// sufficient to be able to create the renaming map required
|
||||
while (jarEntry != null) {
|
||||
String name = jarEntry.getName();
|
||||
if (name.startsWith("META-INF/versions/") && name.endsWith(".class")) {
|
||||
|
||||
// Get the base name and version for this versioned entry
|
||||
int i = name.indexOf('/', 18);
|
||||
if (i > 0) {
|
||||
String baseName = name.substring(i + 1);
|
||||
int version = Integer.parseInt(name.substring(18, i));
|
||||
|
||||
// Ignore any entries targeting for a later version than
|
||||
// the target for this runtime
|
||||
if (version <= targetVersion) {
|
||||
Integer mappedVersion = mrVersions.get(baseName);
|
||||
if (mappedVersion == null) {
|
||||
// No version found for this name. Create one.
|
||||
mrVersions.put(baseName, Integer.valueOf(version));
|
||||
} else {
|
||||
// Ignore any entry for which we have already found
|
||||
// a later version
|
||||
if (version > mappedVersion.intValue()) {
|
||||
// Replace the earlier version
|
||||
mrVersions.put(baseName, Integer.valueOf(version));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jarEntry = jarInputStream.getNextJarEntry();
|
||||
}
|
||||
|
||||
mrMap = new HashMap<>();
|
||||
|
||||
for (Entry<String,Integer> mrVersion : mrVersions.entrySet()) {
|
||||
mrMap.put(mrVersion.getKey() , "META-INF/versions/" + mrVersion.getValue().toString() +
|
||||
"/" + mrVersion.getKey());
|
||||
}
|
||||
|
||||
// Reset stream back to the beginning of the JAR
|
||||
closeStream();
|
||||
jarInputStream = createJarInputStream();
|
||||
}
|
||||
}
|
||||
37
java/org/apache/tomcat/util/scan/Constants.java
Normal file
37
java/org/apache/tomcat/util/scan/Constants.java
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
/**
|
||||
* String constants for the scan package.
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
public static final String Package = "org.apache.tomcat.util.scan";
|
||||
|
||||
/* System properties */
|
||||
public static final String SKIP_JARS_PROPERTY =
|
||||
"tomcat.util.scan.StandardJarScanFilter.jarsToSkip";
|
||||
public static final String SCAN_JARS_PROPERTY =
|
||||
"tomcat.util.scan.StandardJarScanFilter.jarsToScan";
|
||||
|
||||
/* Commons strings */
|
||||
public static final String JAR_EXT = ".jar";
|
||||
public static final String WEB_INF_LIB = "/WEB-INF/lib/";
|
||||
public static final String WEB_INF_CLASSES = "/WEB-INF/classes";
|
||||
}
|
||||
71
java/org/apache/tomcat/util/scan/JarFactory.java
Normal file
71
java/org/apache/tomcat/util/scan/JarFactory.java
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
import org.apache.tomcat.Jar;
|
||||
import org.apache.tomcat.util.buf.UriUtil;
|
||||
|
||||
/**
|
||||
* Provide a mechanism to obtain objects that implement {@link Jar}.
|
||||
*/
|
||||
public class JarFactory {
|
||||
|
||||
private JarFactory() {
|
||||
// Factory class. Hide public constructor.
|
||||
}
|
||||
|
||||
|
||||
public static Jar newInstance(URL url) throws IOException {
|
||||
String urlString = url.toString();
|
||||
if (urlString.startsWith("jar:file:")) {
|
||||
if (urlString.endsWith("!/")) {
|
||||
return new JarFileUrlJar(url, true);
|
||||
} else {
|
||||
return new JarFileUrlNestedJar(url);
|
||||
}
|
||||
} else if (urlString.startsWith("war:file:")) {
|
||||
URL jarUrl = UriUtil.warToJar(url);
|
||||
return new JarFileUrlNestedJar(jarUrl);
|
||||
} else if (urlString.startsWith("file:")) {
|
||||
return new JarFileUrlJar(url, false);
|
||||
} else {
|
||||
return new UrlJar(url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static URL getJarEntryURL(URL baseUrl, String entryName)
|
||||
throws MalformedURLException {
|
||||
|
||||
String baseExternal = baseUrl.toExternalForm();
|
||||
|
||||
if (baseExternal.startsWith("jar")) {
|
||||
// Assume this is pointing to a JAR file within a WAR. Java doesn't
|
||||
// support jar:jar:file:... so switch to Tomcat's war:file:...
|
||||
baseExternal = baseExternal.replaceFirst("^jar:", "war:");
|
||||
baseExternal = baseExternal.replaceFirst("!/",
|
||||
Matcher.quoteReplacement(UriUtil.getWarSeparator()));
|
||||
}
|
||||
|
||||
return new URL("jar:" + baseExternal + "!/" + entryName);
|
||||
}
|
||||
}
|
||||
221
java/org/apache/tomcat/util/scan/JarFileUrlJar.java
Normal file
221
java/org/apache/tomcat/util/scan/JarFileUrlJar.java
Normal file
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.zip.ZipEntry;
|
||||
|
||||
import org.apache.tomcat.Jar;
|
||||
import org.apache.tomcat.util.compat.JreCompat;
|
||||
|
||||
/**
|
||||
* Implementation of {@link Jar} that is optimised for file based JAR URLs that
|
||||
* refer directly to a JAR file (e.g URLs of the form jar:file: ... .jar!/ or
|
||||
* file:... .jar).
|
||||
*/
|
||||
public class JarFileUrlJar implements Jar {
|
||||
|
||||
private final JarFile jarFile;
|
||||
private final URL jarFileURL;
|
||||
private final boolean multiRelease;
|
||||
private Enumeration<JarEntry> entries;
|
||||
private Set<String> entryNamesSeen;
|
||||
private JarEntry entry = null;
|
||||
|
||||
public JarFileUrlJar(URL url, boolean startsWithJar) throws IOException {
|
||||
if (startsWithJar) {
|
||||
// jar:file:...
|
||||
JarURLConnection jarConn = (JarURLConnection) url.openConnection();
|
||||
jarConn.setUseCaches(false);
|
||||
jarFile = jarConn.getJarFile();
|
||||
jarFileURL = jarConn.getJarFileURL();
|
||||
} else {
|
||||
// file:...
|
||||
File f;
|
||||
try {
|
||||
f = new File(url.toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
jarFile = JreCompat.getInstance().jarFileNewInstance(f);
|
||||
jarFileURL = url;
|
||||
}
|
||||
multiRelease = JreCompat.getInstance().jarFileIsMultiRelease(jarFile);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URL getJarFileURL() {
|
||||
return jarFileURL;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean entryExists(String name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(String name) throws IOException {
|
||||
// JarFile#getEntry() is multi-release aware
|
||||
ZipEntry entry = jarFile.getEntry(name);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
return jarFile.getInputStream(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastModified(String name) throws IOException {
|
||||
// JarFile#getEntry() is multi-release aware
|
||||
ZipEntry entry = jarFile.getEntry(name);
|
||||
if (entry == null) {
|
||||
return -1;
|
||||
} else {
|
||||
return entry.getTime();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(String name) throws IOException {
|
||||
// JarFile#getEntry() is multi-release aware
|
||||
ZipEntry entry = jarFile.getEntry(name);
|
||||
return entry != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getURL(String entry) {
|
||||
StringBuilder result = new StringBuilder("jar:");
|
||||
result.append(getJarFileURL().toExternalForm());
|
||||
result.append("!/");
|
||||
result.append(entry);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (jarFile != null) {
|
||||
try {
|
||||
jarFile.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextEntry() {
|
||||
// JarFile#entries() is NOT multi-release aware
|
||||
if (entries == null) {
|
||||
entries = jarFile.entries();
|
||||
if (multiRelease) {
|
||||
entryNamesSeen = new HashSet<>();
|
||||
}
|
||||
}
|
||||
|
||||
if (multiRelease) {
|
||||
// Need to ensure that:
|
||||
// - the one, correct entry is returned where multiple versions
|
||||
// are available
|
||||
// - that the order of entries in the JAR doesn't prevent the
|
||||
// correct entries being returned
|
||||
// - the case where an entry appears in the versions location
|
||||
// but not in the the base location is handled correctly
|
||||
|
||||
// Enumerate the entries until one is reached that represents an
|
||||
// entry that has not been seen before.
|
||||
String name = null;
|
||||
while (true) {
|
||||
if (entries.hasMoreElements()) {
|
||||
entry = entries.nextElement();
|
||||
name = entry.getName();
|
||||
// Get 'base' name
|
||||
if (name.startsWith("META-INF/versions/")) {
|
||||
int i = name.indexOf('/', 18);
|
||||
if (i == -1) {
|
||||
continue;
|
||||
}
|
||||
name = name.substring(i + 1);
|
||||
}
|
||||
if (name.length() == 0 || entryNamesSeen.contains(name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
entryNamesSeen.add(name);
|
||||
|
||||
// JarFile.getJarEntry is version aware so use it
|
||||
entry = jarFile.getJarEntry(entry.getName());
|
||||
break;
|
||||
} else {
|
||||
entry = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (entries.hasMoreElements()) {
|
||||
entry = entries.nextElement();
|
||||
} else {
|
||||
entry = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEntryName() {
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
return entry.getName();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getEntryInputStream() throws IOException {
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
return jarFile.getInputStream(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
return jarFile.getManifest();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
entries = null;
|
||||
entryNamesSeen = null;
|
||||
entry = null;
|
||||
}
|
||||
}
|
||||
65
java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java
Normal file
65
java/org/apache/tomcat/util/scan/JarFileUrlNestedJar.java
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.apache.tomcat.Jar} that is optimised for file
|
||||
* based JAR URLs that refer to a JAR file nested inside a WAR
|
||||
* (e.g URLs of the form jar:file: ... .war!/ ... .jar).
|
||||
*/
|
||||
public class JarFileUrlNestedJar extends AbstractInputStreamJar {
|
||||
|
||||
private final JarFile warFile;
|
||||
private final JarEntry jarEntry;
|
||||
|
||||
public JarFileUrlNestedJar(URL url) throws IOException {
|
||||
super(url);
|
||||
JarURLConnection jarConn = (JarURLConnection) url.openConnection();
|
||||
jarConn.setUseCaches(false);
|
||||
warFile = jarConn.getJarFile();
|
||||
|
||||
String urlAsString = url.toString();
|
||||
int pathStart = urlAsString.indexOf("!/") + 2;
|
||||
String jarPath = urlAsString.substring(pathStart);
|
||||
jarEntry = warFile.getJarEntry(jarPath);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closeStream();
|
||||
if (warFile != null) {
|
||||
try {
|
||||
warFile.close();
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected NonClosingJarInputStream createJarInputStream() throws IOException {
|
||||
return new NonClosingJarInputStream(warFile.getInputStream(jarEntry));
|
||||
}
|
||||
}
|
||||
25
java/org/apache/tomcat/util/scan/LocalStrings.properties
Normal file
25
java/org/apache/tomcat/util/scan/LocalStrings.properties
Normal file
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=Failed to scan [{0}] from classloader hierarchy
|
||||
jarScan.classloaderJarNoScan=Not performing JAR scanning on file [{0}] from classpath
|
||||
jarScan.classloaderJarScan=Scanning JAR [{0}] from classpath
|
||||
jarScan.classloaderStart=Scanning for JARs in classloader hierarchy
|
||||
jarScan.jarUrlStart=Scanning JAR at URL [{0}]
|
||||
jarScan.webinfclassesFail=Failed to scan /WEB-INF/classes
|
||||
jarScan.webinflibFail=Failed to scan JAR [{0}] from /WEB-INF/lib
|
||||
jarScan.webinflibJarNoScan=Not performing JAR scanning on file [{0}] from /WEB-INF/lib
|
||||
jarScan.webinflibJarScan=Scanning JAR [{0}] from /WEB-INF/lib
|
||||
jarScan.webinflibStart=Scanning /WEB-INF/lib for JARs
|
||||
16
java/org/apache/tomcat/util/scan/LocalStrings_de.properties
Normal file
16
java/org/apache/tomcat/util/scan/LocalStrings_de.properties
Normal file
@@ -0,0 +1,16 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderJarNoScan=Werde auf Datei [{0}] aus dem Classpath kein JAR Scanning durchführen
|
||||
19
java/org/apache/tomcat/util/scan/LocalStrings_es.properties
Normal file
19
java/org/apache/tomcat/util/scan/LocalStrings_es.properties
Normal file
@@ -0,0 +1,19 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=Fallo al escanear [{0}] desde la herarquia classloader hierarchy
|
||||
jarScan.classloaderJarNoScan=No se ejecutó el escaneo de JAR en el archivo [{0}] de la ruta de clase
|
||||
jarScan.webinflibJarNoScan=No se ejecutó escaneo JAR en el archivo [{0}] de /WEB-INF/lib\n
|
||||
jarScan.webinflibStart=Buscando JARs en /WEB-INF/lib
|
||||
25
java/org/apache/tomcat/util/scan/LocalStrings_fr.properties
Normal file
25
java/org/apache/tomcat/util/scan/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=Echec de recherche dans [{0}] de la hiérarchie de chargeurs de classes
|
||||
jarScan.classloaderJarNoScan=Le JAR [{0}] dans le chemin de classes ne sera pas analysé
|
||||
jarScan.classloaderJarScan=Analyse du JAR [{0}] du chemin de classes
|
||||
jarScan.classloaderStart=Recherche dans les JARs de la hiérarchie de chargeurs de classe
|
||||
jarScan.jarUrlStart=Recherche dans le JAR à l''URL [{0}]
|
||||
jarScan.webinfclassesFail=Impossible de parcourir /WEB-INF/classes
|
||||
jarScan.webinflibFail=Échec de scan du JAR [{0}] de /WEB-INF/lib
|
||||
jarScan.webinflibJarNoScan=Le JAR [{0}] dans /WEB-INF/lib ne sera pas analysé
|
||||
jarScan.webinflibJarScan=Analyse du JAR [{0}] dans /WEB-INF/lib
|
||||
jarScan.webinflibStart=Recherche de JARs dans /WEB-INF/lib
|
||||
25
java/org/apache/tomcat/util/scan/LocalStrings_ja.properties
Normal file
25
java/org/apache/tomcat/util/scan/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=クラスローダー階層から[{0}]をスキャンできませんでした
|
||||
jarScan.classloaderJarNoScan=クラスパス中のファイル [{0}] は JAR スキャンをしませんでした。
|
||||
jarScan.classloaderJarScan=クラスパスの JAR ファイル [{0}] をスキャンします。
|
||||
jarScan.classloaderStart=クラスローダー階層中の JAR ファイルをスキャンします。
|
||||
jarScan.jarUrlStart=URL [{0}] の JAR ファイルをスキャンします。
|
||||
jarScan.webinfclassesFail=/WEB-INF/classesのスキャンに失敗しました
|
||||
jarScan.webinflibFail=/WEB-INF/libからJAR [{0}]をスキャンできませんでした。
|
||||
jarScan.webinflibJarNoScan=/WEB-INF/lib のファイル [{0}] は JAR スキャンをしませんでした。
|
||||
jarScan.webinflibJarScan=/WEB-INF/libからJAR [{0}]のスキャンを行います。
|
||||
jarScan.webinflibStart=/WEB-INF/lib の JAR ファイルを検査しています。
|
||||
25
java/org/apache/tomcat/util/scan/LocalStrings_ko.properties
Normal file
25
java/org/apache/tomcat/util/scan/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,25 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=클래스로더 계층구조로부터 [{0}]을(를) 스캔하지 못했습니다.
|
||||
jarScan.classloaderJarNoScan=클래스패스로부터 파일 [{0}]에 대한 JAR 스캔을 수행하지 않습니다.
|
||||
jarScan.classloaderJarScan=클래스패스로부터 JAR [{0}]을(를) 스캔합니다.
|
||||
jarScan.classloaderStart=클래스로더 계층 구조에서 JAR들을 스캔합니다.
|
||||
jarScan.jarUrlStart=URL [{0}]에 위치한 JAR를 스캔합니다.
|
||||
jarScan.webinfclassesFail=/WEB-INF/classes를 스캔하지 못했습니다.
|
||||
jarScan.webinflibFail=/WEB-INF/lib으로부터 JAR [{0}]을(를) 스캔하지 못했습니다.
|
||||
jarScan.webinflibJarNoScan=/WEB-INF/lib 내의 파일 [{0}]에 대한 JAR 스캔을 수행하지 않습니다.
|
||||
jarScan.webinflibJarScan=/WEB-INF/lib으로부터 JAR [{0}]을(를) 스캔합니다.
|
||||
jarScan.webinflibStart=JAR들을 찾기 위해 /WEB-INF/lib을 스캔합니다.
|
||||
@@ -0,0 +1,23 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
jarScan.classloaderFail=在多级类加载器中扫描[{0}]失败
|
||||
jarScan.classloaderJarNoScan=跳过classpath路径[{0}]下的jar包扫描。
|
||||
jarScan.classloaderJarScan=从classpath扫描JAR[{0}]
|
||||
jarScan.classloaderStart=在类加载器层次结构中扫描JAR
|
||||
jarScan.jarUrlStart=正在扫描URL [{0}] 上的JAR文件
|
||||
jarScan.webinfclassesFail=无法扫描/WEB-INF/classes
|
||||
jarScan.webinflibJarNoScan=没有扫描到/WEB-INF/lib目录下的JAR [{0}]
|
||||
jarScan.webinflibStart=扫描./WEB-INF/lib 中的JARs
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.jar.JarInputStream;
|
||||
|
||||
/**
|
||||
* When using a {@link JarInputStream} with an XML parser, the stream will be
|
||||
* closed by the parser. This causes problems if multiple entries from the JAR
|
||||
* need to be parsed. This implementation makes {{@link #close()} a NO-OP and
|
||||
* adds {@link #reallyClose()} that will close the stream.
|
||||
*/
|
||||
public class NonClosingJarInputStream extends JarInputStream {
|
||||
|
||||
public NonClosingJarInputStream(InputStream in, boolean verify)
|
||||
throws IOException {
|
||||
super(in, verify);
|
||||
}
|
||||
|
||||
public NonClosingJarInputStream(InputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// Make this a NO-OP so that further entries can be read from the stream
|
||||
}
|
||||
|
||||
public void reallyClose() throws IOException {
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
155
java/org/apache/tomcat/util/scan/ReferenceCountedJar.java
Normal file
155
java/org/apache/tomcat/util/scan/ReferenceCountedJar.java
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
import org.apache.tomcat.Jar;
|
||||
|
||||
/**
|
||||
* This class provides a wrapper around {@link Jar} that uses reference counting
|
||||
* to close and re-create the wrapped {@link Jar} instance as required.
|
||||
*/
|
||||
public class ReferenceCountedJar implements Jar {
|
||||
|
||||
private final URL url;
|
||||
private Jar wrappedJar;
|
||||
private int referenceCount = 0;
|
||||
|
||||
public ReferenceCountedJar(URL url) throws IOException {
|
||||
this.url = url;
|
||||
open();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Note: Returns this instance so it can be used with try-with-resources
|
||||
*/
|
||||
private synchronized ReferenceCountedJar open() throws IOException {
|
||||
if (wrappedJar == null) {
|
||||
wrappedJar = JarFactory.newInstance(url);
|
||||
}
|
||||
referenceCount++;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public synchronized void close() {
|
||||
referenceCount--;
|
||||
if (referenceCount == 0) {
|
||||
wrappedJar.close();
|
||||
wrappedJar = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public URL getJarFileURL() {
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream(String name) throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getInputStream(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getLastModified(String name) throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getLastModified(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean exists(String name) throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.exists(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void nextEntry() {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
jar.wrappedJar.nextEntry();
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getEntryName() {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getEntryName();
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public InputStream getEntryInputStream() throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getEntryInputStream();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getURL(String entry) {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getURL(entry);
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Manifest getManifest() throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.getManifest();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
jar.wrappedJar.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean entryExists(String name) throws IOException {
|
||||
try (ReferenceCountedJar jar = open()) {
|
||||
return jar.wrappedJar.entryExists(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
260
java/org/apache/tomcat/util/scan/StandardJarScanFilter.java
Normal file
260
java/org/apache/tomcat/util/scan/StandardJarScanFilter.java
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.apache.tomcat.JarScanFilter;
|
||||
import org.apache.tomcat.JarScanType;
|
||||
import org.apache.tomcat.util.file.Matcher;
|
||||
|
||||
public class StandardJarScanFilter implements JarScanFilter {
|
||||
|
||||
private final ReadWriteLock configurationLock =
|
||||
new ReentrantReadWriteLock();
|
||||
|
||||
private static final String defaultSkip;
|
||||
private static final String defaultScan;
|
||||
private static final Set<String> defaultSkipSet = new HashSet<>();
|
||||
private static final Set<String> defaultScanSet = new HashSet<>();
|
||||
private static final boolean defaultSkipAll;
|
||||
|
||||
static {
|
||||
// Initialize defaults. There are no setter methods for them.
|
||||
defaultSkip = System.getProperty(Constants.SKIP_JARS_PROPERTY);
|
||||
populateSetFromAttribute(defaultSkip, defaultSkipSet);
|
||||
defaultSkipAll = defaultSkipSet.contains("*") || defaultSkipSet.contains("*.jar");
|
||||
defaultScan = System.getProperty(Constants.SCAN_JARS_PROPERTY);
|
||||
populateSetFromAttribute(defaultScan, defaultScanSet);
|
||||
}
|
||||
|
||||
private String tldSkip;
|
||||
private String tldScan;
|
||||
private final Set<String> tldSkipSet;
|
||||
private final Set<String> tldScanSet;
|
||||
private boolean defaultTldScan = true;
|
||||
|
||||
private String pluggabilitySkip;
|
||||
private String pluggabilityScan;
|
||||
private final Set<String> pluggabilitySkipSet;
|
||||
private final Set<String> pluggabilityScanSet;
|
||||
private boolean defaultPluggabilityScan = true;
|
||||
|
||||
/**
|
||||
* This is the standard implementation of {@link JarScanFilter}. By default,
|
||||
* the following filtering rules are used:
|
||||
* <ul>
|
||||
* <li>JARs that match neither the skip nor the scan list will be included
|
||||
* in scan results.</li>
|
||||
* <li>JARs that match the skip list but not the scan list will be excluded
|
||||
* from scan results.</li>
|
||||
* <li>JARs that match the scan list will be included from scan results.
|
||||
* </li>
|
||||
* </ul>
|
||||
* The default skip list and default scan list are obtained from the system
|
||||
* properties {@link Constants#SKIP_JARS_PROPERTY} and
|
||||
* {@link Constants#SCAN_JARS_PROPERTY} respectively. These default values
|
||||
* may be over-ridden for the {@link JarScanType#TLD} and
|
||||
* {@link JarScanType#PLUGGABILITY} scans. The filtering rules may also be
|
||||
* modified for these scan types using {@link #setDefaultTldScan(boolean)}
|
||||
* and {@link #setDefaultPluggabilityScan(boolean)}. If set to
|
||||
* <code>false</code>, the following filtering rules are used for associated
|
||||
* type:
|
||||
* <ul>
|
||||
* <li>JARs that match neither the skip nor the scan list will be excluded
|
||||
* from scan results.</li>
|
||||
* <li>JARs that match the scan list but not the skip list will be included
|
||||
* in scan results.</li>
|
||||
* <li>JARs that match the skip list will be excluded from scan results.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public StandardJarScanFilter() {
|
||||
tldSkip = defaultSkip;
|
||||
tldSkipSet = new HashSet<>(defaultSkipSet);
|
||||
tldScan = defaultScan;
|
||||
tldScanSet = new HashSet<>(defaultScanSet);
|
||||
pluggabilitySkip = defaultSkip;
|
||||
pluggabilitySkipSet = new HashSet<>(defaultSkipSet);
|
||||
pluggabilityScan = defaultScan;
|
||||
pluggabilityScanSet = new HashSet<>(defaultScanSet);
|
||||
}
|
||||
|
||||
|
||||
public String getTldSkip() {
|
||||
return tldSkip;
|
||||
}
|
||||
|
||||
|
||||
public void setTldSkip(String tldSkip) {
|
||||
this.tldSkip = tldSkip;
|
||||
Lock writeLock = configurationLock.writeLock();
|
||||
writeLock.lock();
|
||||
try {
|
||||
populateSetFromAttribute(tldSkip, tldSkipSet);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getTldScan() {
|
||||
return tldScan;
|
||||
}
|
||||
|
||||
|
||||
public void setTldScan(String tldScan) {
|
||||
this.tldScan = tldScan;
|
||||
Lock writeLock = configurationLock.writeLock();
|
||||
writeLock.lock();
|
||||
try {
|
||||
populateSetFromAttribute(tldScan, tldScanSet);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isSkipAll() {
|
||||
return defaultSkipAll;
|
||||
}
|
||||
|
||||
|
||||
public boolean isDefaultTldScan() {
|
||||
return defaultTldScan;
|
||||
}
|
||||
|
||||
|
||||
public void setDefaultTldScan(boolean defaultTldScan) {
|
||||
this.defaultTldScan = defaultTldScan;
|
||||
}
|
||||
|
||||
|
||||
public String getPluggabilitySkip() {
|
||||
return pluggabilitySkip;
|
||||
}
|
||||
|
||||
|
||||
public void setPluggabilitySkip(String pluggabilitySkip) {
|
||||
this.pluggabilitySkip = pluggabilitySkip;
|
||||
Lock writeLock = configurationLock.writeLock();
|
||||
writeLock.lock();
|
||||
try {
|
||||
populateSetFromAttribute(pluggabilitySkip, pluggabilitySkipSet);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getPluggabilityScan() {
|
||||
return pluggabilityScan;
|
||||
}
|
||||
|
||||
|
||||
public void setPluggabilityScan(String pluggabilityScan) {
|
||||
this.pluggabilityScan = pluggabilityScan;
|
||||
Lock writeLock = configurationLock.writeLock();
|
||||
writeLock.lock();
|
||||
try {
|
||||
populateSetFromAttribute(pluggabilityScan, pluggabilityScanSet);
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isDefaultPluggabilityScan() {
|
||||
return defaultPluggabilityScan;
|
||||
}
|
||||
|
||||
|
||||
public void setDefaultPluggabilityScan(boolean defaultPluggabilityScan) {
|
||||
this.defaultPluggabilityScan = defaultPluggabilityScan;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean check(JarScanType jarScanType, String jarName) {
|
||||
Lock readLock = configurationLock.readLock();
|
||||
readLock.lock();
|
||||
try {
|
||||
final boolean defaultScan;
|
||||
final Set<String> toSkip;
|
||||
final Set<String> toScan;
|
||||
switch (jarScanType) {
|
||||
case TLD: {
|
||||
defaultScan = defaultTldScan;
|
||||
toSkip = tldSkipSet;
|
||||
toScan = tldScanSet;
|
||||
break;
|
||||
}
|
||||
case PLUGGABILITY: {
|
||||
defaultScan = defaultPluggabilityScan;
|
||||
toSkip = pluggabilitySkipSet;
|
||||
toScan = pluggabilityScanSet;
|
||||
break;
|
||||
}
|
||||
case OTHER:
|
||||
default: {
|
||||
defaultScan = true;
|
||||
toSkip = defaultSkipSet;
|
||||
toScan = defaultScanSet;
|
||||
}
|
||||
}
|
||||
if (defaultScan) {
|
||||
if (Matcher.matchName(toSkip, jarName)) {
|
||||
if (Matcher.matchName(toScan, jarName)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (Matcher.matchName(toScan, jarName)) {
|
||||
if (Matcher.matchName(toSkip, jarName)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static void populateSetFromAttribute(String attribute, Set<String> set) {
|
||||
set.clear();
|
||||
if (attribute != null) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(attribute, ",");
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
String token = tokenizer.nextToken().trim();
|
||||
if (token.length() > 0) {
|
||||
set.add(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
506
java/org/apache/tomcat/util/scan/StandardJarScanner.java
Normal file
506
java/org/apache/tomcat/util/scan/StandardJarScanner.java
Normal file
File diff suppressed because it is too large
Load Diff
49
java/org/apache/tomcat/util/scan/UrlJar.java
Normal file
49
java/org/apache/tomcat/util/scan/UrlJar.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.scan;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.apache.tomcat.Jar} that is optimised for
|
||||
* non-file based JAR URLs.
|
||||
*/
|
||||
public class UrlJar extends AbstractInputStreamJar {
|
||||
|
||||
public UrlJar(URL jarFileURL) {
|
||||
super(jarFileURL);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closeStream();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected NonClosingJarInputStream createJarInputStream() throws IOException {
|
||||
JarURLConnection jarConn = (JarURLConnection) getJarFileURL().openConnection();
|
||||
URL resourceURL = jarConn.getJarFileURL();
|
||||
URLConnection resourceConn = resourceURL.openConnection();
|
||||
resourceConn.setUseCaches(false);
|
||||
return new NonClosingJarInputStream(resourceConn.getInputStream());
|
||||
}
|
||||
}
|
||||
27
java/org/apache/tomcat/util/scan/package.html
Normal file
27
java/org/apache/tomcat/util/scan/package.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
||||
<html>
|
||||
<head>
|
||||
</head>
|
||||
<body bgcolor="white">
|
||||
<p>
|
||||
This package contains the common classes used to perform configuration scanning
|
||||
for Catalina and Jasper.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user