Skip to content

Commits on Source 4

......@@ -69,10 +69,10 @@ Sub-tree
src/main/java/org/apache/commons/dbcp2
src/main/resources/org/apache/commons/dbcp2
The SHA1 ID for the most recent commit to be merged to Tomcat is:
abc048454398d8c9924a1af9c04501817f44a11d
171528a88cca65f5b192be643c2425458d1edfbb
Pool2
Sub-tree
src/main/java/org/apache/commons/pool2
The SHA1 ID for the most recent commit to be merged to Tomcat is:
3e02523b6907fb22f3582544fe362c785821bcb8
d4e0e88227ad91d8c8ef36ba01d656f71c770f83
......@@ -25,7 +25,7 @@
# ----- Version Control Flags -----
version.major=8
version.minor=5
version.build=34
version.build=35
version.patch=0
version.suffix=
......@@ -140,19 +140,19 @@ jdt.loc.1=http://archive.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj
jdt.loc.2=http://download.eclipse.org/eclipse/downloads/drops4/${jdt.release}/ecj-${jdt.version}.jar
# ----- Tomcat native library -----
tomcat-native.version=1.2.17
tomcat-native.version=1.2.18
tomcat-native.src.checksum.enabled=true
tomcat-native.src.checksum.algorithm=SHA-512
tomcat-native.src.checksum.value=8fa946855fd14525ec0abe7b09975bbd34d6127352e90730a8afb77e16cd91715417e812a40017fee65939a9ce95faf39a9193222f441cda0ad2eb7f690e77b9
tomcat-native.src.checksum.value=66481c1f36dc7ea909bf8d55075a232bf6dea3300b56d36415b13da4aefbee16cb52456f3d44b4a2b09b43cd8c7df628145a0623b9cdfa322bc2432e6c44827f
tomcat-native.win.checksum.enabled=true
tomcat-native.win.checksum.algorithm=SHA-512
tomcat-native.win.checksum.value=2955209b39707949b080f13c09edcad08a13faf5545f7890e2ac493ccbc66d09e152a39b4fa6ac40fe3de6b209b305608db3db8dcf24dda94567b417f55a5f49
tomcat-native.win.checksum.value=979158411b696360fd7efee1df51f4349215fb94df34bae73c7ce98afc45ad3937829c58b7ecf4785d587a90f90d50ec438a96bb166f407a7c831903d953ad55
tomcat-native.home=${base.path}/tomcat-native-${tomcat-native.version}
tomcat-native.tar.gz=${tomcat-native.home}/tomcat-native.tar.gz
tomcat-native.loc.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz
tomcat-native.loc.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/source/tomcat-native-${tomcat-native.version}-src.tar.gz
tomcat-native.win.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-win32-bin.zip
tomcat-native.win.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-win32-bin.zip
tomcat-native.win.1=${base-tomcat.loc.1}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1-win32-bin.zip
tomcat-native.win.2=${base-tomcat.loc.2}/tomcat-connectors/native/${tomcat-native.version}/binaries/tomcat-native-${tomcat-native.version}-openssl-1.1.1-win32-bin.zip
# ----- NSIS, version 3.0 or later -----
nsis.version=3.03
......
......@@ -3066,6 +3066,23 @@ skip.installer property in build.properties" />
Read the Building page on the Apache Tomcat documentation site for details on how to configure your Eclipse workspace.</echo>
</target>
<!-- ============================ IntelliJ IDEA=========================== -->
<target name="ide-intellij"
depends="download-compile, extras-webservices-prepare, download-test-compile"
description="Creates project directory .idea for IntelliJ IDEA">
<copy todir="${tomcat.home}/.idea">
<fileset dir="${tomcat.home}/res/ide-support/idea"/>
</copy>
<echo>IntelliJ IDEA project directory created. Please create PATH VARIABLES for
ANT_HOME = ${ant.home}
TOMCAT_BUILD_LIBS = ${base.path}
</echo>
</target>
<!-- ============================ NetBeans =============================== -->
<target name="ide-netbeans"
......
tomcat8 (8.5.34-2) UNRELEASED; urgency=medium
tomcat8 (8.5.35-1) unstable; urgency=medium
* Team upload.
[ Thomas Opfer ]
* Removed old version requirement for package ant-optional that is not
required any more.
-- Thomas Opfer <ubuntuone@thomasopfer.de> Sun, 23 Sep 2018 22:34:12 +0200
[ Emmanuel Bourg ]
* New upstream release
- Refreshed the patches
-- Emmanuel Bourg <ebourg@apache.org> Thu, 08 Nov 2018 23:40:00 +0100
tomcat8 (8.5.34-1) unstable; urgency=medium
......
......@@ -4,7 +4,7 @@ Author: Emmanuel Bourg <ebourg@apache.org>
Forwarded: not-needed
--- a/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java
+++ b/test/org/apache/tomcat/util/net/openssl/ciphers/TesterOpenSSL.java
@@ -104,6 +104,23 @@
@@ -106,6 +106,23 @@
unimplemented.add(Cipher.SSL2_RC4_128_EXPORT40_WITH_MD5);
unimplemented.add(Cipher.SSL2_IDEA_128_CBC_WITH_MD5);
unimplemented.add(Cipher.SSL2_DES_192_EDE3_CBC_WITH_MD5);
......@@ -26,8 +26,8 @@ Forwarded: not-needed
+ unimplemented.add(Cipher.TLS_RSA_WITH_ARIA_128_GCM_SHA256);
+ unimplemented.add(Cipher.TLS_RSA_WITH_ARIA_256_GCM_SHA384);
// These are TLS v1.3 ciphers that the test suite doesn't yet handle
unimplemented.add(Cipher.TLS_AES_128_CCM_8_SHA256);
// These are TLS v1.3 cipher suites
// Java does not currently support these so they are excluded from the
--- a/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
+++ b/test/org/apache/tomcat/util/net/openssl/ciphers/TestOpenSSLCipherConfigurationParser.java
@@ -575,7 +575,7 @@
......
......@@ -26,6 +26,7 @@ import java.net.PasswordAuthentication;
import java.net.URL;
import java.net.URLConnection;
import org.apache.catalina.util.IOTools;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
......@@ -174,6 +175,8 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
URLConnection conn = null;
InputStreamReader reader = null;
try {
// Set up authorization with our credentials
Authenticator.setDefault(new TaskAuthenticator(username, password));
// Create a connection for this command
conn = (new URL(url + command)).openConnection();
......@@ -184,6 +187,8 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
hconn.setDoInput(true);
hconn.setUseCaches(false);
if (istream != null) {
preAuthenticate();
hconn.setDoOutput(true);
hconn.setRequestMethod("PUT");
if (contentType != null) {
......@@ -200,9 +205,6 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
}
hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");
// Set up authorization with our credentials
Authenticator.setDefault(new TaskAuthenticator(username, password));
// Establish the connection with the server
hconn.connect();
......@@ -292,6 +294,44 @@ public abstract class AbstractCatalinaTask extends BaseRedirectorHelperTask {
}
/*
* This is a hack.
* We need to use streaming to avoid OOME on large uploads.
* We'd like to use Authenticator.setDefault() for authentication as the JRE
* then provides the DIGEST client implementation.
* However, the above two are not compatible. When the request is made, the
* resulting 401 triggers an exception because, when using streams, the
* InputStream is no longer available to send with the repeated request that
* now includes the appropriate Authorization header.
* The hack is to make a simple OPTIONS request- i.e. without a request
* body.
* This triggers authentication and the requirement to authenticate for this
* host is cached and used to provide an appropriate Authorization when the
* next request is made (that includes a request body).
*/
private void preAuthenticate() throws IOException {
URLConnection conn = null;
// Create a connection for this command
conn = (new URL(url)).openConnection();
HttpURLConnection hconn = (HttpURLConnection) conn;
// Set up standard connection characteristics
hconn.setAllowUserInteraction(false);
hconn.setDoInput(true);
hconn.setUseCaches(false);
hconn.setDoOutput(false);
hconn.setRequestMethod("OPTIONS");
hconn.setRequestProperty("User-Agent", "Catalina-Ant-Task/1.0");
// Establish the connection with the server
hconn.connect();
// Swallow response message
IOTools.flow(hconn.getInputStream(), null);
}
private static class TaskAuthenticator extends Authenticator {
private final String user;
......
......@@ -30,7 +30,7 @@ coyoteAdapter.accesslogFail = Excepci\u00F3n al intentar a\u00F1adir una entrada
# CoyoteResponse
coyoteResponse.getOutputStream.ise = getWriter() ya ha sido llamado para esta respuesta
coyoteResponse.getWriter.ise = getOutputStream() ya ha sido llamado para esta respuesta
coyoteResponse.resetBuffer.ise = No puedo limpiar el b\u00FAfer despu\u00E9s de que la repuesta ha sido llevada a cabo
coyoteResponse.resetBuffer.ise = No puedo limpiar el b\u00FAfer despu\u00E9s de que la respuesta ha sido llevada a cabo
coyoteResponse.sendError.ise = No puedo llamar a sendError() tras llevar a cabo la respuesta
coyoteResponse.sendRedirect.ise = No puedo llamar a sendRedirect() tras llevar a cabo la respuesta
coyoteResponse.setBufferSize.ise = No puedo cambiar la medida del b\u00FAfer tras escribir los datos
......
......@@ -68,7 +68,7 @@ public class AprLifecycleListener
protected static final int TCN_REQUIRED_MINOR = 2;
protected static final int TCN_REQUIRED_PATCH = 14;
protected static final int TCN_RECOMMENDED_MINOR = 2;
protected static final int TCN_RECOMMENDED_PV = 14;
protected static final int TCN_RECOMMENDED_PV = 18;
// ---------------------------------------------- Properties
......
......@@ -935,18 +935,21 @@ public abstract class ContainerBase extends LifecycleMBeanBase
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
MultiThrowable multiThrowable = new MultiThrowable();
MultiThrowable multiThrowable = null;
for (Future<Void> result : results) {
try {
result.get();
} catch (Throwable e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
if (multiThrowable == null) {
multiThrowable = new MultiThrowable();
}
multiThrowable.add(e);
}
}
if (multiThrowable.size() > 0) {
if (multiThrowable != null) {
throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
multiThrowable.getThrowable());
}
......
/*
* 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.catalina.core;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* An implementation of LifeCycleListener that loads a native library into the JVM.
* <p>
* Native libraries are associated with the class loader of the class that loaded them,
* and the same library may not be loaded by more than one class loader. Due to that
* restriction, loading a native library from a Webapp's class loader makes it impossible
* for other Webapps to load the native library.
* <p>
* Loading the native library using this listener solves the issue as it is loaded
* by a shared class loader (typically the Common class loader, but may vary in some
* configurations).
*/
public class JniLifecycleListener implements LifecycleListener {
private static final Log log = LogFactory.getLog(JniLifecycleListener.class);
private String libraryName = "";
private String libraryPath = "";
@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) {
if (!libraryName.isEmpty()) {
System.loadLibrary(libraryName);
log.info("Loaded native library " + libraryName);
} else if (!libraryPath.isEmpty()) {
System.load(libraryPath);
log.info("Loaded native library from " + libraryPath);
} else {
throw new IllegalArgumentException("Either libraryName or libraryPath must be set");
}
}
}
public void setLibraryName(String libraryName) {
if (!this.libraryPath.isEmpty()) {
throw new IllegalArgumentException("Either libraryName or libraryPath may be set, not both.");
}
this.libraryName = libraryName;
}
public String getLibraryName() {
return libraryName;
}
public void setLibraryPath(String libraryPath) {
if (!this.libraryName.isEmpty()) {
throw new IllegalArgumentException("Either libraryName or libraryPath may be set, not both.");
}
this.libraryPath = libraryPath;
}
public String getLibraryPath() {
return libraryPath;
}
}
......@@ -51,6 +51,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadPoolExecutor;
......@@ -1045,6 +1046,24 @@ public abstract class WebappClassLoaderBase extends URLClassLoader
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
Enumeration<URL> parentResources = getParent().getResources(name);
Enumeration<URL> localResources = findResources(name);
// Need to combine these enumerations. The order in which the
// Enumerations are combined depends on how delegation is configured
boolean delegateFirst = delegate || filter(name, false);
if (delegateFirst) {
return new CombinedEnumeration(parentResources, localResources);
} else {
return new CombinedEnumeration(localResources, parentResources);
}
}
/**
* Find the resource with the given name, and return an input stream
* that can be used for reading it. The search order is as described
......@@ -2599,4 +2618,43 @@ public abstract class WebappClassLoaderBase extends URLClassLoader
return Boolean.valueOf(findResource("logging.properties") != null);
}
}
private static class CombinedEnumeration implements Enumeration<URL> {
private final Enumeration<URL>[] sources;
private int index = 0;
public CombinedEnumeration(Enumeration<URL> enum1, Enumeration<URL> enum2) {
@SuppressWarnings("unchecked")
Enumeration<URL>[] sources = new Enumeration[] { enum1, enum2 };
this.sources = sources;
}
@Override
public boolean hasMoreElements() {
return inc();
}
@Override
public URL nextElement() {
if (inc()) {
return sources[index].nextElement();
}
throw new NoSuchElementException();
}
private boolean inc() {
while (index < sources.length) {
if (sources[index].hasMoreElements()) {
return true;
}
index++;
}
return false;
}
}
}
......@@ -1200,7 +1200,7 @@ public final class HTMLManagerServlet extends ManagerServlet {
" <small><input type=\"submit\" value=\"{5}\"></small>" +
" </form>\n" +
" <form class=\"inline\" method=\"POST\" action=\"{6}\">" +
" <small><input type=\"submit\" value=\"{7}\"></small>" +
" &nbsp;&nbsp;<small><input type=\"submit\" value=\"{7}\"></small>" +
" </form>\n" +
" </td>\n" +
" </tr><tr>\n" +
......
......@@ -1800,6 +1800,8 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet {
if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler().findSslHostConfigs();
for (SSLHostConfig sslHostConfig : sslHostConfigs) {
if (sslHostConfig.getOpenSslContext().longValue() == 0) {
// Not set. Must be JSSE based.
Set<SSLHostConfigCertificate> sslHostConfigCerts =
sslHostConfig.getCertificates();
for (SSLHostConfigCertificate sslHostConfigCert : sslHostConfigCerts) {
......@@ -1821,6 +1823,12 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet {
}
result.put(name, certList);
}
} else {
List<String> certList = new ArrayList<>();
certList.add(sm.getString("managerServlet.certsNotAvailable"));
String name = connector.toString() + "-" + sslHostConfig.getHostName();
result.put(name, certList);
}
}
} else {
List<String> certList = new ArrayList<>(1);
......@@ -1843,6 +1851,8 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet {
for (SSLHostConfig sslHostConfig : sslHostConfigs) {
String name = connector.toString() + "-" + sslHostConfig.getHostName();
List<String> certList = new ArrayList<>();
if (sslHostConfig.getOpenSslContext().longValue() == 0) {
// Not set. Must be JSSE based.
SSLContext sslContext =
sslHostConfig.getCertificates().iterator().next().getSslContext();
X509Certificate[] certs = sslContext.getAcceptedIssuers();
......@@ -1855,6 +1865,9 @@ public class ManagerServlet extends HttpServlet implements ContainerServlet {
certList.add(cert.toString());
}
}
} else {
certList.add(sm.getString("managerServlet.certsNotAvailable"));
}
result.put(name, certList);
}
} else {
......
......@@ -29,10 +29,12 @@ import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.Pattern;
......@@ -242,6 +244,14 @@ public final class CGIServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Set<String> DEFAULT_SUPER_METHODS = new HashSet<>();
static {
DEFAULT_SUPER_METHODS.add("HEAD");
DEFAULT_SUPER_METHODS.add("OPTIONS");
DEFAULT_SUPER_METHODS.add("TRACE");
}
/**
* The CGI search path will start at
* webAppRootDir + File.separator + cgiPathPrefix
......@@ -260,6 +270,11 @@ public final class CGIServlet extends HttpServlet {
private String parameterEncoding =
System.getProperty("file.encoding", "UTF-8");
/* The HTTP methods this Servlet will pass to the CGI script */
private Set<String> cgiMethods = new HashSet<>();
private boolean cgiMethodsAll = false;
/**
* The time (in milliseconds) to wait for the reading of stderr to complete
* before terminating the CGI process.
......@@ -364,6 +379,23 @@ public final class CGIServlet extends HttpServlet {
enableCmdLineArguments =
Boolean.parseBoolean(config.getInitParameter("enableCmdLineArguments"));
}
if (getServletConfig().getInitParameter("cgiMethods") != null) {
String paramValue = getServletConfig().getInitParameter("cgiMethods");
paramValue.trim();
if ("*".equals(paramValue)) {
cgiMethodsAll = true;
} else {
String[] methods = paramValue.split(",");
for (String method : methods) {
String trimmedMethod = method.trim();
cgiMethods.add(trimmedMethod);
}
}
} else {
cgiMethods.add("GET");
cgiMethods.add("POST");
}
}
......@@ -497,20 +529,21 @@ public final class CGIServlet extends HttpServlet {
}
/**
* Provides CGI Gateway service -- delegates to
* {@link #doGet(HttpServletRequest, HttpServletResponse)}.
*
* @param req HttpServletRequest passed in by servlet container
* @param res HttpServletResponse passed in by servlet container
*
* @exception ServletException if a servlet-specific exception occurs
* @exception IOException if a read/write exception occurs
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
protected void service(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
String method = req.getMethod();
if (cgiMethodsAll || cgiMethods.contains(method)) {
doGet(req, res);
} else if (DEFAULT_SUPER_METHODS.contains(method)){
// If the CGI servlet is explicitly configured to handle one of
// these methods it will be handled in the previous condition
super.service(req, res);
} else {
// Unsupported method
res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
}
......@@ -555,6 +588,29 @@ public final class CGIServlet extends HttpServlet {
}
@Override
protected void doOptions(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// Note: This method will never be called if cgiMethods is "*" so that
// case does nto need to be handled here.
Set<String> allowedMethods = new HashSet<>();
allowedMethods.addAll(cgiMethods);
allowedMethods.addAll(CGIServlet.DEFAULT_SUPER_METHODS);
StringBuilder headerValue = new StringBuilder();
for (String method : allowedMethods) {
headerValue.append(method);
headerValue.append(',');
}
// Remove trailing comma
headerValue.deleteCharAt(headerValue.length() - 1);
res.setHeader("allow", headerValue.toString());
}
/**
* Behaviour depends on the status code.
*
......
......@@ -28,12 +28,14 @@ import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.LogManager;
import org.apache.catalina.Container;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Server;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.security.SecurityConfig;
import org.apache.juli.ClassLoaderLogManager;
import org.apache.juli.logging.Log;
......@@ -278,10 +280,14 @@ public class Catalina {
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
ArrayList<String> attrs = new ArrayList<>();
attrs.add("className");
fakeAttributes.put(Object.class, attrs);
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
List<String> objectAttrs = new ArrayList<>();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs);
// Ignore attribute added by Eclipse for its internal tracking
List<String> contextAttrs = new ArrayList<>();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
......
......@@ -423,10 +423,14 @@ public class ContextConfig implements LifecycleListener {
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
ArrayList<String> attrs = new ArrayList<>();
attrs.add("className");
fakeAttributes.put(Object.class, attrs);
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
List<String> objectAttrs = new ArrayList<>();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs);
// Ignore attribute added by Eclipse for its internal tracking
List<String> contextAttrs = new ArrayList<>();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs);
digester.setFakeAttributes(fakeAttributes);
RuleSet contextRuleSet = new ContextRuleSet("", false);
digester.addRuleSet(contextRuleSet);
......@@ -579,7 +583,7 @@ public class ContextConfig implements LifecycleListener {
File file = new File(docBase);
if (!file.isAbsolute()) {
docBase = (new File(appBase, docBase)).getPath();
docBase = (new File(appBase, docBase)).getCanonicalPath();
} else {
docBase = file.getCanonicalPath();
}
......
/**
* 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.catalina.storeconfig;
import java.beans.PropertyDescriptor;
import org.apache.tomcat.util.IntrospectionUtils;
/**
* Store the Certificate attributes.
*/
public class CertificateStoreAppender extends StoreAppender {
@Override
protected Object checkAttribute(StoreDescription desc,
PropertyDescriptor descriptor, String attributeName, Object bean,
Object bean2) {
if (attributeName.equals("type")) {
return IntrospectionUtils.getProperty(bean, descriptor.getName());
} else {
return super.checkAttribute(desc, descriptor, attributeName, bean, bean2);
}
}
}
\ No newline at end of file
......@@ -41,11 +41,13 @@ public class ConnectorSF extends StoreFactoryBase {
// Store nested <UpgradeProtocol> elements
UpgradeProtocol[] upgradeProtocols = connector.findUpgradeProtocols();
storeElementArray(aWriter, indent, upgradeProtocols);
if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
// Store nested <SSLHostConfig> elements
SSLHostConfig[] hostConfigs = connector.findSslHostConfigs();
storeElementArray(aWriter, indent, hostConfigs);
}
}
}
protected void printOpenTag(PrintWriter aWriter, int indent, Object bean,
StoreDescription aDesc) throws Exception {
......
......@@ -18,9 +18,11 @@
package org.apache.catalina.storeconfig;
import java.io.PrintWriter;
import java.util.ArrayList;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
import org.apache.tomcat.util.net.openssl.OpenSSLConf;
/**
......@@ -39,6 +41,16 @@ public class SSLHostConfigSF extends StoreFactoryBase {
SSLHostConfig sslHostConfig = (SSLHostConfig) aSSLHostConfig;
// Store nested <SSLHostConfigCertificate> elements
SSLHostConfigCertificate[] hostConfigsCertificates = sslHostConfig.getCertificates().toArray(new SSLHostConfigCertificate[0]);
// Remove a possible default UNDEFINED certificate
if (hostConfigsCertificates.length > 1) {
ArrayList<SSLHostConfigCertificate> certificates = new ArrayList<>();
for (SSLHostConfigCertificate certificate : hostConfigsCertificates) {
if (Type.UNDEFINED != certificate.getType()) {
certificates.add(certificate);
}
}
hostConfigsCertificates = certificates.toArray(new SSLHostConfigCertificate[0]);
}
storeElementArray(aWriter, indent, hostConfigsCertificates);
// Store nested <OpenSSLConf> element
OpenSSLConf openSslConf = sslHostConfig.getOpenSslConf();
......
......@@ -230,30 +230,11 @@ public class StoreAppender {
// Create blank instance
Object bean2 = defaultInstance(bean);
for (int i = 0; i < descriptors.length; i++) {
if (descriptors[i] instanceof IndexedPropertyDescriptor) {
continue; // Indexed properties are not persisted
}
if (!isPersistable(descriptors[i].getPropertyType())
|| (descriptors[i].getReadMethod() == null)
|| (descriptors[i].getWriteMethod() == null)) {
continue; // Must be a read-write primitive or String
}
if (desc.isTransientAttribute(descriptors[i].getName())) {
continue; // Skip the specified exceptions
}
Object value = IntrospectionUtils.getProperty(bean, descriptors[i]
.getName());
if (value == null) {
continue; // Null values are not persisted
}
Object value2 = IntrospectionUtils.getProperty(bean2,
descriptors[i].getName());
if (value.equals(value2)) {
// The property has its default value
continue;
}
Object value = checkAttribute(desc, descriptors[i], descriptors[i].getName(), bean, bean2);
if (value != null) {
printAttribute(writer, indent, bean, desc, descriptors[i].getName(), bean2, value);
}
}
if (bean instanceof ResourceBase) {
ResourceBase resource = (ResourceBase) bean;
......@@ -272,6 +253,39 @@ public class StoreAppender {
}
}
/**
* Check if the attribute should be printed.
* @param desc RegistryDescriptor from this bean
* @param descriptor PropertyDescriptor from this bean property
* @param attributeName The attribute name to store
* @param bean The current bean
* @param bean2 A default instance of the bean for comparison
* @return null if the value should be skipped, the value to print otherwise
*/
protected Object checkAttribute(StoreDescription desc, PropertyDescriptor descriptor, String attributeName, Object bean, Object bean2) {
if (descriptor instanceof IndexedPropertyDescriptor) {
return null; // Indexed properties are not persisted
}
if (!isPersistable(descriptor.getPropertyType())
|| (descriptor.getReadMethod() == null)
|| (descriptor.getWriteMethod() == null)) {
return null; // Must be a read-write primitive or String
}
if (desc.isTransientAttribute(descriptor.getName())) {
return null; // Skip the specified exceptions
}
Object value = IntrospectionUtils.getProperty(bean, descriptor.getName());
if (value == null) {
return null; // Null values are not persisted
}
Object value2 = IntrospectionUtils.getProperty(bean2, descriptor.getName());
if (value.equals(value2)) {
// The property has its default value
return null;
}
return value;
}
/**
* Store the specified of the specified JavaBean.
*
......@@ -303,15 +317,7 @@ public class StoreAppender {
*/
public boolean isPrintValue(Object bean, Object bean2, String attrName,
StoreDescription desc) {
boolean printValue = false;
Object value = IntrospectionUtils.getProperty(bean, attrName);
if (value != null) {
Object value2 = IntrospectionUtils.getProperty(bean2, attrName);
printValue = !value.equals(value2);
}
return printValue;
return true;
}
/**
......