init
This commit is contained in:
60
java/org/apache/tomcat/ContextBind.java
Normal file
60
java/org/apache/tomcat/ContextBind.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface ContextBind {
|
||||
|
||||
/**
|
||||
* Change the current thread context class loader to the web application
|
||||
* class loader. If no web application class loader is defined, or if the
|
||||
* current thread is already using the web application class loader then no
|
||||
* change will be made. If the class loader is changed and a
|
||||
* {@link org.apache.catalina.ThreadBindingListener} is configured then
|
||||
* {@link org.apache.catalina.ThreadBindingListener#bind()} will be called
|
||||
* after the change has been made.
|
||||
*
|
||||
* @param usePrivilegedAction
|
||||
* Should a {@link java.security.PrivilegedAction} be used when
|
||||
* obtaining the current thread context class loader and setting
|
||||
* the new one?
|
||||
* @param originalClassLoader
|
||||
* The current class loader if known to save this method having to
|
||||
* look it up
|
||||
*
|
||||
* @return If the class loader has been changed by the method it will return
|
||||
* the thread context class loader in use when the method was
|
||||
* called. If no change was made then this method returns null.
|
||||
*/
|
||||
ClassLoader bind(boolean usePrivilegedAction, ClassLoader originalClassLoader);
|
||||
|
||||
/**
|
||||
* Restore the current thread context class loader to the original class
|
||||
* loader in used before {@link #bind(boolean, ClassLoader)} was called. If
|
||||
* no original class loader is passed to this method then no change will be
|
||||
* made. If the class loader is changed and a
|
||||
* {@link org.apache.catalina.ThreadBindingListener} is configured then
|
||||
* {@link org.apache.catalina.ThreadBindingListener#unbind()} will be called
|
||||
* before the change is made.
|
||||
*
|
||||
* @param usePrivilegedAction
|
||||
* Should a {@link java.security.PrivilegedAction} be used when
|
||||
* setting the current thread context class loader?
|
||||
* @param originalClassLoader
|
||||
* The class loader to restore as the thread context class loader
|
||||
*/
|
||||
void unbind(boolean usePrivilegedAction, ClassLoader originalClassLoader);
|
||||
}
|
||||
42
java/org/apache/tomcat/InstanceManager.java
Normal file
42
java/org/apache/tomcat/InstanceManager.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
public interface InstanceManager {
|
||||
|
||||
Object newInstance(Class<?> clazz) throws IllegalAccessException, InvocationTargetException,
|
||||
NamingException, InstantiationException, IllegalArgumentException,
|
||||
NoSuchMethodException, SecurityException;
|
||||
|
||||
Object newInstance(String className) throws IllegalAccessException, InvocationTargetException,
|
||||
NamingException, InstantiationException, ClassNotFoundException,
|
||||
IllegalArgumentException, NoSuchMethodException, SecurityException;
|
||||
|
||||
Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException,
|
||||
InvocationTargetException, NamingException, InstantiationException,
|
||||
ClassNotFoundException, IllegalArgumentException, NoSuchMethodException,
|
||||
SecurityException;
|
||||
|
||||
void newInstance(Object o)
|
||||
throws IllegalAccessException, InvocationTargetException, NamingException;
|
||||
|
||||
void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException;
|
||||
}
|
||||
35
java/org/apache/tomcat/InstanceManagerBindings.java
Normal file
35
java/org/apache/tomcat/InstanceManagerBindings.java
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class InstanceManagerBindings {
|
||||
|
||||
private static final Map<ClassLoader, InstanceManager> bindings = new ConcurrentHashMap<>();
|
||||
|
||||
public static final void bind(ClassLoader classLoader, InstanceManager instanceManager) {
|
||||
bindings.put(classLoader, instanceManager);
|
||||
}
|
||||
public static final void unbind(ClassLoader classLoader) {
|
||||
bindings.remove(classLoader);
|
||||
}
|
||||
public static final InstanceManager get(ClassLoader classLoader) {
|
||||
return bindings.get(classLoader);
|
||||
}
|
||||
}
|
||||
78
java/org/apache/tomcat/InstrumentableClassLoader.java
Normal file
78
java/org/apache/tomcat/InstrumentableClassLoader.java
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
|
||||
/**
|
||||
* Specifies a class loader capable of being decorated with
|
||||
* {@link ClassFileTransformer}s. These transformers can instrument
|
||||
* (or weave) the byte code of classes loaded through this class loader
|
||||
* to alter their behavior. Currently only
|
||||
* {@link org.apache.catalina.loader.WebappClassLoaderBase} implements this
|
||||
* interface. This allows web application frameworks or JPA providers
|
||||
* bundled with a web application to instrument web application classes
|
||||
* as necessary.
|
||||
* <p>
|
||||
* You should always program against the methods of this interface
|
||||
* (whether using reflection or otherwise). The methods in
|
||||
* {@code WebappClassLoaderBase} are protected by the default security
|
||||
* manager if one is in use.
|
||||
*
|
||||
* @since 8.0, 7.0.64
|
||||
*/
|
||||
public interface InstrumentableClassLoader {
|
||||
|
||||
/**
|
||||
* Adds the specified class file transformer to this class loader. The
|
||||
* transformer will then be able to instrument the bytecode of any
|
||||
* classes loaded by this class loader after the invocation of this
|
||||
* method.
|
||||
*
|
||||
* @param transformer The transformer to add to the class loader
|
||||
* @throws IllegalArgumentException if the {@literal transformer} is null.
|
||||
*/
|
||||
void addTransformer(ClassFileTransformer transformer);
|
||||
|
||||
/**
|
||||
* Removes the specified class file transformer from this class loader.
|
||||
* It will no longer be able to instrument the byte code of any classes
|
||||
* loaded by the class loader after the invocation of this method.
|
||||
* However, any classes already instrumented by this transformer before
|
||||
* this method call will remain in their instrumented state.
|
||||
*
|
||||
* @param transformer The transformer to remove
|
||||
*/
|
||||
void removeTransformer(ClassFileTransformer transformer);
|
||||
|
||||
/**
|
||||
* Returns a copy of this class loader without any class file
|
||||
* transformers. This is a tool often used by Java Persistence API
|
||||
* providers to inspect entity classes in the absence of any
|
||||
* instrumentation, something that can't be guaranteed within the
|
||||
* context of a {@link ClassFileTransformer}'s
|
||||
* {@link ClassFileTransformer#transform(ClassLoader, String, Class,
|
||||
* java.security.ProtectionDomain, byte[]) transform} method.
|
||||
* <p>
|
||||
* The returned class loader's resource cache will have been cleared
|
||||
* so that classes already instrumented will not be retained or
|
||||
* returned.
|
||||
*
|
||||
* @return the transformer-free copy of this class loader.
|
||||
*/
|
||||
ClassLoader copyWithoutTransformers();
|
||||
}
|
||||
151
java/org/apache/tomcat/Jar.java
Normal file
151
java/org/apache/tomcat/Jar.java
Normal file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* Provides an abstraction for use by the various classes that need to scan
|
||||
* JARs. The classes provided by the JRE for accessing JARs
|
||||
* ({@link java.util.jar.JarFile} and {@link java.util.jar.JarInputStream}) have
|
||||
* significantly different performance characteristics depending on the form of
|
||||
* the URL used to access the JAR. For file based JAR {@link java.net.URL}s,
|
||||
* {@link java.util.jar.JarFile} is faster but for non-file based
|
||||
* {@link java.net.URL}s, {@link java.util.jar.JarFile} creates a copy of the
|
||||
* JAR in the temporary directory so {@link java.util.jar.JarInputStream} is
|
||||
* faster.
|
||||
*/
|
||||
public interface Jar extends AutoCloseable {
|
||||
|
||||
/**
|
||||
* @return The URL for accessing the JAR file.
|
||||
*/
|
||||
URL getJarFileURL();
|
||||
|
||||
/**
|
||||
* Determines if a specific entry exists within the JAR.
|
||||
*
|
||||
* @param name Entry to look for
|
||||
* @return Implementations will always return {@code false}
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while processing the JAR file
|
||||
* entries
|
||||
*
|
||||
* @deprecated Unused. This will be removed in Tomcat 9 onwards.
|
||||
*/
|
||||
@Deprecated
|
||||
boolean entryExists(String name) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Obtain an {@link InputStream} for a given entry in a JAR. The caller is
|
||||
* responsible for closing the stream.
|
||||
*
|
||||
* @param name Entry to obtain an {@link InputStream} for
|
||||
* @return An {@link InputStream} for the specified entry or null if
|
||||
* the entry does not exist
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while processing the JAR file
|
||||
*/
|
||||
InputStream getInputStream(String name) throws IOException;
|
||||
|
||||
/**
|
||||
* Obtain the last modified time for the given resource in the JAR.
|
||||
*
|
||||
* @param name Entry to obtain the modification time for
|
||||
*
|
||||
* @return The time (in the same format as
|
||||
* {@link System#currentTimeMillis()} that the resource was last
|
||||
* modified. Returns -1 if the entry does not exist
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while processing the JAR file
|
||||
*/
|
||||
long getLastModified(String name) throws IOException;
|
||||
|
||||
/**
|
||||
* Determine if the given resource in present in the JAR.
|
||||
*
|
||||
* @param name Entry to look for
|
||||
*
|
||||
* @return {@code true} if the entry is present in the JAR, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while processing the JAR file
|
||||
*/
|
||||
boolean exists(String name) throws IOException;
|
||||
|
||||
/**
|
||||
* Close any resources associated with this JAR.
|
||||
*/
|
||||
@Override
|
||||
void close();
|
||||
|
||||
/**
|
||||
* Moves the internal pointer to the next entry in the JAR.
|
||||
*/
|
||||
void nextEntry();
|
||||
|
||||
/**
|
||||
* Obtains the name of the current entry.
|
||||
*
|
||||
* @return The entry name
|
||||
*/
|
||||
String getEntryName();
|
||||
|
||||
/**
|
||||
* Obtains the input stream for the current entry.
|
||||
*
|
||||
* @return The input stream
|
||||
* @throws IOException If the stream cannot be obtained
|
||||
*/
|
||||
InputStream getEntryInputStream() throws IOException;
|
||||
|
||||
/**
|
||||
* Obtain, in String form, the URL for an entry in this JAR. Note that for
|
||||
* JARs nested in WAR files, the Tomcat specific war:file:... form will not
|
||||
* be used, rather the jar:jar:file:... form (that the JRE does not
|
||||
* understand will be used). Note that this means that any code using these
|
||||
* URLs will need to understand the jar:jar:file:... form and use the
|
||||
* {@link org.apache.tomcat.util.scan.JarFactory} to ensure resources are
|
||||
* accessed correctly.
|
||||
*
|
||||
* @param entry The entry to generate the URL for
|
||||
*
|
||||
* @return a URL for the specified entry in the JAR
|
||||
*/
|
||||
String getURL(String entry);
|
||||
|
||||
/**
|
||||
* Obtain the manifest for the JAR file.
|
||||
*
|
||||
* @return The manifest for this JAR file.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs trying to obtain the manifest
|
||||
*/
|
||||
Manifest getManifest() throws IOException;
|
||||
|
||||
/**
|
||||
* Resets the internal pointer used to track JAR entries to the beginning of
|
||||
* the JAR.
|
||||
*
|
||||
* @throws IOException If the pointer cannot be reset
|
||||
*/
|
||||
void reset() throws IOException;
|
||||
}
|
||||
31
java/org/apache/tomcat/JarScanFilter.java
Normal file
31
java/org/apache/tomcat/JarScanFilter.java
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
public interface JarScanFilter {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param jarScanType The type of JAR scan currently being performed
|
||||
* @param jarName The name of the JAR file (without any path
|
||||
* information) to be checked to see if it should
|
||||
* be included in the results or not
|
||||
* @return <code>true</code> if the JAR should be returned in the results,
|
||||
* <code>false</code> if it should be excluded
|
||||
*/
|
||||
boolean check(JarScanType jarScanType, String jarName);
|
||||
}
|
||||
23
java/org/apache/tomcat/JarScanType.java
Normal file
23
java/org/apache/tomcat/JarScanType.java
Normal file
@@ -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.
|
||||
*/
|
||||
package org.apache.tomcat;
|
||||
|
||||
public enum JarScanType {
|
||||
TLD,
|
||||
PLUGGABILITY,
|
||||
OTHER
|
||||
}
|
||||
45
java/org/apache/tomcat/JarScanner.java
Normal file
45
java/org/apache/tomcat/JarScanner.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
/**
|
||||
* Scans a web application and classloader hierarchy for JAR files. Uses
|
||||
* include TLD scanning and web-fragment.xml scanning. Uses a call-back
|
||||
* mechanism so the caller can process each JAR found.
|
||||
*/
|
||||
public interface JarScanner {
|
||||
|
||||
/**
|
||||
* Scan the provided ServletContext and classloader for JAR files. Each JAR
|
||||
* file found will be passed to the callback handler to be processed.
|
||||
*
|
||||
* @param scanType The type of JAR scan to perform. This is passed to
|
||||
* the filter which uses it to determine how to
|
||||
* filter the results
|
||||
* @param context The ServletContext - used to locate and access
|
||||
* WEB-INF/lib
|
||||
* @param callback The handler to process any JARs found
|
||||
*/
|
||||
public void scan(JarScanType scanType, ServletContext context,
|
||||
JarScannerCallback callback);
|
||||
|
||||
public JarScanFilter getJarScanFilter();
|
||||
|
||||
public void setJarScanFilter(JarScanFilter jarScanFilter);
|
||||
}
|
||||
67
java/org/apache/tomcat/JarScannerCallback.java
Normal file
67
java/org/apache/tomcat/JarScannerCallback.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This interface is implemented by clients of the {@link JarScanner} to enable
|
||||
* them to receive notification of a discovered JAR.
|
||||
*/
|
||||
public interface JarScannerCallback {
|
||||
|
||||
/**
|
||||
* A JAR was found and may be accessed for further processing via the
|
||||
* provided URL connection. The caller is responsible for closing the JAR.
|
||||
*
|
||||
* @param jar The JAR to process
|
||||
* @param webappPath The path, if any, to the JAR within the web application
|
||||
* @param isWebapp Indicates if the JAR was found within a web
|
||||
* application. If <code>false</code> the JAR should
|
||||
* be treated as being provided by the container
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while scanning the JAR
|
||||
*/
|
||||
public void scan(Jar jar, String webappPath, boolean isWebapp)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* A directory was found that is to be treated as an unpacked JAR. The
|
||||
* directory may be accessed for further processing via the provided file.
|
||||
*
|
||||
* @param file The directory containing the unpacked JAR.
|
||||
* @param webappPath The path, if any, to the file within the web
|
||||
* application
|
||||
* @param isWebapp Indicates if the JAR was found within a web
|
||||
* application. If <code>false</code> the JAR should
|
||||
* be treated as being provided by the container
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while scanning the JAR
|
||||
*/
|
||||
public void scan(File file, String webappPath, boolean isWebapp) throws IOException;
|
||||
|
||||
/**
|
||||
* A directory structure was found within the web application at
|
||||
* /WEB-INF/classes that should be handled as an unpacked JAR. Note that all
|
||||
* resource access must be via the ServletContext to ensure that any
|
||||
* additional resources are visible.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while scanning WEB-INF/classes
|
||||
*/
|
||||
public void scanWebInfClasses() throws IOException;
|
||||
}
|
||||
25
java/org/apache/tomcat/PeriodicEventListener.java
Normal file
25
java/org/apache/tomcat/PeriodicEventListener.java
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.
|
||||
*/
|
||||
|
||||
package org.apache.tomcat;
|
||||
|
||||
public interface PeriodicEventListener {
|
||||
/**
|
||||
* Execute a periodic task, such as reloading, etc.
|
||||
*/
|
||||
public void periodicEvent();
|
||||
}
|
||||
68
java/org/apache/tomcat/SimpleInstanceManager.java
Normal file
68
java/org/apache/tomcat/SimpleInstanceManager.java
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
|
||||
/**
|
||||
* SimpleInstanceManager
|
||||
*
|
||||
* Implement the org.apache.tomcat.InstanceManager interface.
|
||||
*/
|
||||
public class SimpleInstanceManager implements InstanceManager {
|
||||
|
||||
public SimpleInstanceManager() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance(Class<?> clazz) throws IllegalAccessException,
|
||||
InvocationTargetException, NamingException, InstantiationException, NoSuchMethodException {
|
||||
return prepareInstance(clazz.getConstructor().newInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance(String className) throws IllegalAccessException,
|
||||
InvocationTargetException, NamingException, InstantiationException,
|
||||
ClassNotFoundException, NoSuchMethodException {
|
||||
Class<?> clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
|
||||
return prepareInstance(clazz.getConstructor().newInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object newInstance(String fqcn, ClassLoader classLoader) throws IllegalAccessException,
|
||||
InvocationTargetException, NamingException, InstantiationException,
|
||||
ClassNotFoundException, NoSuchMethodException {
|
||||
Class<?> clazz = classLoader.loadClass(fqcn);
|
||||
return prepareInstance(clazz.getConstructor().newInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newInstance(Object o) throws IllegalAccessException, InvocationTargetException,
|
||||
NamingException {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyInstance(Object o) throws IllegalAccessException, InvocationTargetException {
|
||||
}
|
||||
|
||||
private Object prepareInstance(Object o) {
|
||||
return o;
|
||||
}
|
||||
}
|
||||
161
java/org/apache/tomcat/buildutil/CheckEol.java
Normal file
161
java/org/apache/tomcat/buildutil/CheckEol.java
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.buildutil;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
|
||||
/**
|
||||
* Ant task that checks that all the files in the given fileset have end-of-line
|
||||
* delimiters that are appropriate for the current OS.
|
||||
*
|
||||
* <p>
|
||||
* The goal is to check whether we have problems with svn:eol-style property
|
||||
* when files are committed on one OS and then checked on another one.
|
||||
*/
|
||||
public class CheckEol extends Task {
|
||||
|
||||
/** The files to be checked */
|
||||
private final List<FileSet> filesets = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* Sets the files to be checked
|
||||
*
|
||||
* @param fs The fileset to be checked.
|
||||
*/
|
||||
public void addFileset( FileSet fs ) {
|
||||
filesets.add( fs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the check
|
||||
*
|
||||
* @throws BuildException if an error occurs during execution of
|
||||
* this task.
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
|
||||
Mode mode = null;
|
||||
if ("\n".equals(System.lineSeparator())) {
|
||||
mode = Mode.LF;
|
||||
} else if ("\r\n".equals(System.lineSeparator())) {
|
||||
mode = Mode.CRLF;
|
||||
} else {
|
||||
log("Line ends check skipped, because OS line ends setting is neither LF nor CRLF.",
|
||||
Project.MSG_VERBOSE);
|
||||
return;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
|
||||
List<CheckFailure> errors = new ArrayList<>();
|
||||
|
||||
// Step through each file and check.
|
||||
for (FileSet fs : filesets) {
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File basedir = ds.getBasedir();
|
||||
String[] files = ds.getIncludedFiles();
|
||||
if (files.length > 0) {
|
||||
log("Checking line ends in " + files.length + " file(s)");
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = new File(basedir, files[i]);
|
||||
log("Checking file '" + file + "' for correct line ends",
|
||||
Project.MSG_DEBUG);
|
||||
try {
|
||||
check(file, errors, mode);
|
||||
} catch (IOException e) {
|
||||
throw new BuildException("Could not check file '"
|
||||
+ file.getAbsolutePath() + "'", e);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
log("Done line ends check in " + count + " file(s), "
|
||||
+ errors.size() + " error(s) found.");
|
||||
}
|
||||
if (errors.size() > 0) {
|
||||
String message = "The following files have wrong line ends: "
|
||||
+ errors;
|
||||
// We need to explicitly write the message to the log, because
|
||||
// long BuildException messages may be trimmed. E.g. I observed
|
||||
// this problem with Eclipse IDE 3.7.
|
||||
log(message, Project.MSG_ERR);
|
||||
throw new BuildException(message);
|
||||
}
|
||||
}
|
||||
|
||||
private enum Mode {
|
||||
LF, CRLF
|
||||
}
|
||||
|
||||
private static class CheckFailure {
|
||||
private final File file;
|
||||
private final int line;
|
||||
private final String value;
|
||||
|
||||
public CheckFailure(File file, int line, String value) {
|
||||
this.file = file;
|
||||
this.line = line;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return System.lineSeparator() + file + ": uses " + value + " on line " + line;
|
||||
}
|
||||
}
|
||||
|
||||
private void check(File file, List<CheckFailure> errors, Mode mode) throws IOException {
|
||||
try (FileInputStream fis = new FileInputStream(file);
|
||||
BufferedInputStream is = new BufferedInputStream(fis)) {
|
||||
int line = 1;
|
||||
int prev = -1;
|
||||
int ch;
|
||||
while ((ch = is.read()) != -1) {
|
||||
if (ch == '\n') {
|
||||
if (mode == Mode.LF && prev == '\r') {
|
||||
errors.add(new CheckFailure(file, line, "CRLF"));
|
||||
return;
|
||||
} else if (mode == Mode.CRLF && prev != '\r') {
|
||||
errors.add(new CheckFailure(file, line, "LF"));
|
||||
return;
|
||||
}
|
||||
line++;
|
||||
} else if (prev == '\r') {
|
||||
errors.add(new CheckFailure(file, line, "CR"));
|
||||
return;
|
||||
}
|
||||
prev = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
413
java/org/apache/tomcat/buildutil/SignCode.java
Normal file
413
java/org/apache/tomcat/buildutil/SignCode.java
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* 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.buildutil;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.SOAPBody;
|
||||
import javax.xml.soap.SOAPConnection;
|
||||
import javax.xml.soap.SOAPConnectionFactory;
|
||||
import javax.xml.soap.SOAPConstants;
|
||||
import javax.xml.soap.SOAPElement;
|
||||
import javax.xml.soap.SOAPEnvelope;
|
||||
import javax.xml.soap.SOAPException;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
import javax.xml.soap.SOAPPart;
|
||||
|
||||
import org.apache.tomcat.util.buf.StringUtils;
|
||||
import org.apache.tomcat.util.codec.binary.Base64;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Ant task that submits a file to the Digicert (formally Symantec) code-signing
|
||||
* service. The service is defined by the published
|
||||
* <a href="https://api.ws.digicert.com/webtrust/SigningService?wsdl">WSDL</a>.
|
||||
* Note that while the service has migrated to a Digicert domain, the namespace
|
||||
* continues to use a Symantec domain.
|
||||
*/
|
||||
public class SignCode extends Task {
|
||||
|
||||
private static final URL SIGNING_SERVICE_URL;
|
||||
|
||||
private static final String NS = "cod";
|
||||
|
||||
private static final MessageFactory SOAP_MSG_FACTORY;
|
||||
|
||||
static {
|
||||
try {
|
||||
SIGNING_SERVICE_URL = new URL(
|
||||
"https://api-appsec.pki.digicert.com/webtrust/SigningService");
|
||||
} catch (MalformedURLException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
try {
|
||||
SOAP_MSG_FACTORY = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
|
||||
} catch (SOAPException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<FileSet> filesets = new ArrayList<>();
|
||||
private String userName;
|
||||
private String password;
|
||||
private String partnerCode;
|
||||
private String keyStore;
|
||||
private String keyStorePassword;
|
||||
private String applicationName;
|
||||
private String applicationVersion;
|
||||
private String signingService;
|
||||
private boolean debug;
|
||||
|
||||
public void addFileset(FileSet fileset) {
|
||||
filesets.add(fileset);
|
||||
}
|
||||
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
|
||||
public void setPartnerCode(String partnerCode) {
|
||||
this.partnerCode = partnerCode;
|
||||
}
|
||||
|
||||
|
||||
public void setKeyStore(String keyStore) {
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
|
||||
public void setKeyStorePassword(String keyStorePassword) {
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
}
|
||||
|
||||
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
|
||||
public void setApplicationVersion(String applicationVersion) {
|
||||
this.applicationVersion = applicationVersion;
|
||||
}
|
||||
|
||||
|
||||
public void setSigningService(String signingService) {
|
||||
this.signingService = signingService;
|
||||
}
|
||||
|
||||
|
||||
public void setDebug(String debug) {
|
||||
this.debug = Boolean.parseBoolean(debug);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
|
||||
List<File> filesToSign = new ArrayList<>();
|
||||
|
||||
// Process the filesets and populate the list of files that need to be
|
||||
// signed.
|
||||
for (FileSet fileset : filesets) {
|
||||
DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
|
||||
File basedir = ds.getBasedir();
|
||||
String[] files = ds.getIncludedFiles();
|
||||
if (files.length > 0) {
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = new File(basedir, files[i]);
|
||||
filesToSign.add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set up the TLS client
|
||||
System.setProperty("javax.net.ssl.keyStore", keyStore);
|
||||
System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
|
||||
|
||||
try {
|
||||
String signingSetID = makeSigningRequest(filesToSign);
|
||||
downloadSignedFiles(filesToSign, signingSetID);
|
||||
} catch (SOAPException | IOException e) {
|
||||
throw new BuildException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String makeSigningRequest(List<File> filesToSign) throws SOAPException, IOException {
|
||||
log("Constructing the code signing request");
|
||||
|
||||
SOAPMessage message = SOAP_MSG_FACTORY.createMessage();
|
||||
SOAPBody body = populateEnvelope(message, NS);
|
||||
|
||||
SOAPElement requestSigning = body.addChildElement("requestSigning", NS);
|
||||
SOAPElement requestSigningRequest =
|
||||
requestSigning.addChildElement("requestSigningRequest", NS);
|
||||
|
||||
addCredentials(requestSigningRequest, this.userName, this.password, this.partnerCode);
|
||||
|
||||
SOAPElement applicationName =
|
||||
requestSigningRequest.addChildElement("applicationName", NS);
|
||||
applicationName.addTextNode(this.applicationName);
|
||||
|
||||
SOAPElement applicationVersion =
|
||||
requestSigningRequest.addChildElement("applicationVersion", NS);
|
||||
applicationVersion.addTextNode(this.applicationVersion);
|
||||
|
||||
SOAPElement signingServiceName =
|
||||
requestSigningRequest.addChildElement("signingServiceName", NS);
|
||||
signingServiceName.addTextNode(this.signingService);
|
||||
|
||||
List<String> fileNames = getFileNames(filesToSign);
|
||||
|
||||
SOAPElement commaDelimitedFileNames =
|
||||
requestSigningRequest.addChildElement("commaDelimitedFileNames", NS);
|
||||
commaDelimitedFileNames.addTextNode(StringUtils.join(fileNames));
|
||||
|
||||
SOAPElement application =
|
||||
requestSigningRequest.addChildElement("application", NS);
|
||||
application.addTextNode(getApplicationString(fileNames, filesToSign));
|
||||
|
||||
// Send the message
|
||||
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
|
||||
SOAPConnection connection = soapConnectionFactory.createConnection();
|
||||
|
||||
log("Sending signing request to server and waiting for response");
|
||||
SOAPMessage response = connection.call(message, SIGNING_SERVICE_URL);
|
||||
|
||||
if (debug) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(2 * 1024);
|
||||
response.writeTo(baos);
|
||||
log(baos.toString("UTF-8"));
|
||||
}
|
||||
|
||||
log("Processing response");
|
||||
SOAPElement responseBody = response.getSOAPBody();
|
||||
|
||||
// Should come back signed
|
||||
NodeList bodyNodes = responseBody.getChildNodes();
|
||||
NodeList requestSigningResponseNodes = bodyNodes.item(0).getChildNodes();
|
||||
NodeList returnNodes = requestSigningResponseNodes.item(0).getChildNodes();
|
||||
|
||||
String signingSetID = null;
|
||||
String signingSetStatus = null;
|
||||
|
||||
for (int i = 0; i < returnNodes.getLength(); i++) {
|
||||
Node returnNode = returnNodes.item(i);
|
||||
if (returnNode.getLocalName().equals("signingSetID")) {
|
||||
signingSetID = returnNode.getTextContent();
|
||||
} else if (returnNode.getLocalName().equals("signingSetStatus")) {
|
||||
signingSetStatus = returnNode.getTextContent();
|
||||
}
|
||||
}
|
||||
|
||||
if (!signingService.contains("TEST") && !"SIGNED".equals(signingSetStatus) ||
|
||||
signingService.contains("TEST") && !"INITIALIZED".equals(signingSetStatus) ) {
|
||||
throw new BuildException("Signing failed. Status was: " + signingSetStatus);
|
||||
}
|
||||
|
||||
return signingSetID;
|
||||
}
|
||||
|
||||
|
||||
private void downloadSignedFiles(List<File> filesToSign, String id)
|
||||
throws SOAPException, IOException {
|
||||
|
||||
log("Downloading signed files. The signing set ID is: " + id);
|
||||
|
||||
SOAPMessage message = SOAP_MSG_FACTORY.createMessage();
|
||||
SOAPBody body = populateEnvelope(message, NS);
|
||||
|
||||
SOAPElement getSigningSetDetails = body.addChildElement("getSigningSetDetails", NS);
|
||||
SOAPElement getSigningSetDetailsRequest =
|
||||
getSigningSetDetails.addChildElement("getSigningSetDetailsRequest", NS);
|
||||
|
||||
addCredentials(getSigningSetDetailsRequest, this.userName, this.password, this.partnerCode);
|
||||
|
||||
SOAPElement signingSetID =
|
||||
getSigningSetDetailsRequest.addChildElement("signingSetID", NS);
|
||||
signingSetID.addTextNode(id);
|
||||
|
||||
SOAPElement returnApplication =
|
||||
getSigningSetDetailsRequest.addChildElement("returnApplication", NS);
|
||||
returnApplication.addTextNode("true");
|
||||
|
||||
// Send the message
|
||||
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
|
||||
SOAPConnection connection = soapConnectionFactory.createConnection();
|
||||
|
||||
log("Requesting signed files from server and waiting for response");
|
||||
SOAPMessage response = connection.call(message, SIGNING_SERVICE_URL);
|
||||
|
||||
log("Processing response");
|
||||
SOAPElement responseBody = response.getSOAPBody();
|
||||
|
||||
// Check for success
|
||||
|
||||
// Extract the signed file(s) from the ZIP
|
||||
NodeList bodyNodes = responseBody.getChildNodes();
|
||||
NodeList getSigningSetDetailsResponseNodes = bodyNodes.item(0).getChildNodes();
|
||||
NodeList returnNodes = getSigningSetDetailsResponseNodes.item(0).getChildNodes();
|
||||
|
||||
String result = null;
|
||||
String data = null;
|
||||
|
||||
for (int i = 0; i < returnNodes.getLength(); i++) {
|
||||
Node returnNode = returnNodes.item(i);
|
||||
if (returnNode.getLocalName().equals("result")) {
|
||||
result = returnNode.getChildNodes().item(0).getTextContent();
|
||||
} else if (returnNode.getLocalName().equals("signingSet")) {
|
||||
data = returnNode.getChildNodes().item(1).getTextContent();
|
||||
}
|
||||
}
|
||||
|
||||
if (!"0".equals(result)) {
|
||||
throw new BuildException("Download failed. Result code was: " + result);
|
||||
}
|
||||
|
||||
extractFilesFromApplicationString(data, filesToSign);
|
||||
}
|
||||
|
||||
|
||||
private static SOAPBody populateEnvelope(SOAPMessage message, String namespace)
|
||||
throws SOAPException {
|
||||
SOAPPart soapPart = message.getSOAPPart();
|
||||
SOAPEnvelope envelope = soapPart.getEnvelope();
|
||||
envelope.addNamespaceDeclaration(
|
||||
"soapenv","http://schemas.xmlsoap.org/soap/envelope/");
|
||||
envelope.addNamespaceDeclaration(
|
||||
namespace,"http://api.ws.symantec.com/webtrust/codesigningservice");
|
||||
return envelope.getBody();
|
||||
}
|
||||
|
||||
|
||||
private static void addCredentials(SOAPElement requestSigningRequest,
|
||||
String user, String pwd, String code) throws SOAPException {
|
||||
SOAPElement authToken = requestSigningRequest.addChildElement("authToken", NS);
|
||||
SOAPElement userName = authToken.addChildElement("userName", NS);
|
||||
userName.addTextNode(user);
|
||||
SOAPElement password = authToken.addChildElement("password", NS);
|
||||
password.addTextNode(pwd);
|
||||
SOAPElement partnerCode = authToken.addChildElement("partnerCode", NS);
|
||||
partnerCode.addTextNode(code);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signing service requires unique files names. Since files will be returned
|
||||
* in order, use dummy names that we know are unique but retain the file
|
||||
* extension since the signing service appears to use it to figure out what
|
||||
* to sign and how to sign it.
|
||||
*/
|
||||
private static List<String> getFileNames(List<File> filesToSign) {
|
||||
List<String> result = new ArrayList<>(filesToSign.size());
|
||||
|
||||
for (int i = 0; i < filesToSign.size(); i++) {
|
||||
File f = filesToSign.get(i);
|
||||
String fileName = f.getName();
|
||||
int extIndex = fileName.lastIndexOf('.');
|
||||
String newName;
|
||||
if (extIndex < 0) {
|
||||
newName = Integer.toString(i);
|
||||
} else {
|
||||
newName = Integer.toString(i) + fileName.substring(extIndex);
|
||||
}
|
||||
result.add(newName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Zips the files, base 64 encodes the resulting zip and then returns the
|
||||
* string. It would be far more efficient to stream this directly to the
|
||||
* signing server but the files that need to be signed are relatively small
|
||||
* and this simpler to write.
|
||||
*
|
||||
* @param fileNames Modified names of files
|
||||
* @param files Files to be signed
|
||||
*/
|
||||
private static String getApplicationString(List<String> fileNames, List<File> files)
|
||||
throws IOException {
|
||||
// 16 MB should be more than enough for Tomcat
|
||||
// TODO: Refactoring this entire class so it uses streaming rather than
|
||||
// buffering the entire set of files in memory would make it more
|
||||
// widely useful.
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(16 * 1024 * 1024);
|
||||
try (ZipOutputStream zos = new ZipOutputStream(baos)) {
|
||||
byte[] buf = new byte[32 * 1024];
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
try (FileInputStream fis = new FileInputStream(files.get(i))) {
|
||||
ZipEntry zipEntry = new ZipEntry(fileNames.get(i));
|
||||
zos.putNextEntry(zipEntry);
|
||||
int numRead;
|
||||
while ( (numRead = fis.read(buf)) >= 0) {
|
||||
zos.write(buf, 0, numRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Base64.encodeBase64String(baos.toByteArray());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes base64 encoding, unzips the files and writes the new files over
|
||||
* the top of the old ones.
|
||||
*/
|
||||
private static void extractFilesFromApplicationString(String data, List<File> files)
|
||||
throws IOException {
|
||||
ByteArrayInputStream bais = new ByteArrayInputStream(Base64.decodeBase64(data));
|
||||
try (ZipInputStream zis = new ZipInputStream(bais)) {
|
||||
byte[] buf = new byte[32 * 1024];
|
||||
for (int i = 0; i < files.size(); i ++) {
|
||||
try (FileOutputStream fos = new FileOutputStream(files.get(i))) {
|
||||
zis.getNextEntry();
|
||||
int numRead;
|
||||
while ( (numRead = zis.read(buf)) >= 0) {
|
||||
fos.write(buf, 0 , numRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
179
java/org/apache/tomcat/buildutil/Txt2Html.java
Normal file
179
java/org/apache/tomcat/buildutil/Txt2Html.java
Normal file
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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.buildutil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.DirectoryScanner;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.apache.tools.ant.Task;
|
||||
import org.apache.tools.ant.types.FileSet;
|
||||
|
||||
/**
|
||||
* Ant task to convert a given set of files from Text to HTML.
|
||||
* Inserts an HTML header including pre tags and replaces special characters
|
||||
* with their HTML escaped equivalents.
|
||||
*
|
||||
* <p>This task is currently used by the ant script to build our examples</p>
|
||||
*
|
||||
* @author Mark Roth
|
||||
*/
|
||||
public class Txt2Html
|
||||
extends Task
|
||||
{
|
||||
|
||||
/** The directory to contain the resulting files */
|
||||
private File todir;
|
||||
|
||||
/** The file to be converted into HTML */
|
||||
private final List<FileSet> filesets = new LinkedList<>();
|
||||
|
||||
/**
|
||||
* The encoding of the source files (.java and .jsp). Once they use
|
||||
* UTF-8, this will need to be updated.
|
||||
*/
|
||||
private static final String SOURCE_ENCODING = "ISO-8859-1";
|
||||
|
||||
/**
|
||||
* Line terminator to be used for separating lines of the generated
|
||||
* HTML page, to be independent from "line.separator" system property.
|
||||
*/
|
||||
private static final String LINE_SEPARATOR = "\r\n";
|
||||
|
||||
/**
|
||||
* Sets the directory to contain the resulting files
|
||||
*
|
||||
* @param todir The directory
|
||||
*/
|
||||
public void setTodir( File todir ) {
|
||||
this.todir = todir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the files to be converted into HTML
|
||||
*
|
||||
* @param fs The fileset to be converted.
|
||||
*/
|
||||
public void addFileset( FileSet fs ) {
|
||||
filesets.add( fs );
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the conversion
|
||||
*
|
||||
* @throws BuildException if an error occurs during execution of
|
||||
* this task.
|
||||
*/
|
||||
@Override
|
||||
public void execute()
|
||||
throws BuildException
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
// Step through each file and convert.
|
||||
for (FileSet fs : filesets) {
|
||||
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
|
||||
File basedir = ds.getBasedir();
|
||||
String[] files = ds.getIncludedFiles();
|
||||
for( int i = 0; i < files.length; i++ ) {
|
||||
File from = new File( basedir, files[i] );
|
||||
File to = new File( todir, files[i] + ".html" );
|
||||
if( !to.exists() ||
|
||||
(from.lastModified() > to.lastModified()) )
|
||||
{
|
||||
log( "Converting file '" + from.getAbsolutePath() +
|
||||
"' to '" + to.getAbsolutePath(), Project.MSG_VERBOSE );
|
||||
try {
|
||||
convert( from, to );
|
||||
}
|
||||
catch( IOException e ) {
|
||||
throw new BuildException( "Could not convert '" +
|
||||
from.getAbsolutePath() + "' to '" +
|
||||
to.getAbsolutePath() + "'", e );
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if( count > 0 ) {
|
||||
log( "Converted " + count + " file" + (count > 1 ? "s" : "") +
|
||||
" to " + todir.getAbsolutePath() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the actual copy and conversion
|
||||
*
|
||||
* @param from The input file
|
||||
* @param to The output file
|
||||
* @throws IOException Thrown if an error occurs during the conversion
|
||||
*/
|
||||
private void convert( File from, File to )
|
||||
throws IOException
|
||||
{
|
||||
// Open files:
|
||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(from), SOURCE_ENCODING))) {
|
||||
try (PrintWriter out = new PrintWriter(new OutputStreamWriter(
|
||||
new FileOutputStream(to), "UTF-8"))) {
|
||||
|
||||
// Output header:
|
||||
out.print("<!DOCTYPE html><html><head><meta charset=\"UTF-8\" />"
|
||||
+ "<title>Source Code</title></head><body><pre>" );
|
||||
|
||||
// Convert, line-by-line:
|
||||
String line;
|
||||
while( (line = in.readLine()) != null ) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
int len = line.length();
|
||||
for( int i = 0; i < len; i++ ) {
|
||||
char c = line.charAt( i );
|
||||
switch( c ) {
|
||||
case '&':
|
||||
result.append( "&" );
|
||||
break;
|
||||
case '<':
|
||||
result.append( "<" );
|
||||
break;
|
||||
default:
|
||||
result.append( c );
|
||||
}
|
||||
}
|
||||
out.print( result.toString() + LINE_SEPARATOR );
|
||||
}
|
||||
|
||||
// Output footer:
|
||||
out.print( "</pre></body></html>" );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
65
java/org/apache/tomcat/buildutil/translate/BackportBase.java
Normal file
65
java/org/apache/tomcat/buildutil/translate/BackportBase.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.buildutil.translate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Base class providing common implementation for back-port utilities.
|
||||
*/
|
||||
public abstract class BackportBase {
|
||||
|
||||
protected final Map<String,Properties> sourceTranslations = new HashMap<>();
|
||||
protected final Map<String,Properties> targetTranslations = new HashMap<>();
|
||||
protected final File targetRoot;
|
||||
protected final Properties sourceEnglish;
|
||||
protected final Properties targetEnglish;
|
||||
protected final File storageDir;
|
||||
|
||||
protected BackportBase(String... args) throws IOException {
|
||||
if (args.length != 1) {
|
||||
throw new IllegalArgumentException("Missing back-port target");
|
||||
}
|
||||
targetRoot = new File(args[0]);
|
||||
|
||||
if (!targetRoot.isDirectory()) {
|
||||
throw new IllegalArgumentException("Back-port target not a directory");
|
||||
}
|
||||
|
||||
File sourceRoot = new File(".");
|
||||
for (String dir : Constants.SEARCH_DIRS) {
|
||||
File directory = new File(dir);
|
||||
Utils.processDirectory(sourceRoot, directory, sourceTranslations);
|
||||
}
|
||||
|
||||
for (String dir : Constants.SEARCH_DIRS) {
|
||||
File directory = new File(targetRoot, dir);
|
||||
Utils.processDirectory(targetRoot, directory, targetTranslations);
|
||||
}
|
||||
|
||||
sourceEnglish = sourceTranslations.get("");
|
||||
targetEnglish = targetTranslations.get("");
|
||||
|
||||
storageDir = new File(targetRoot, Constants.STORAGE_DIR);
|
||||
}
|
||||
|
||||
protected abstract void execute() throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.buildutil.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Generates a set of English property files to back-port updates to a previous
|
||||
* version. Where a key exists in the source and target versions the value is
|
||||
* copied from the source to the target, overwriting the value in the target.
|
||||
* The expectation is that the changes will be manually reviewed before
|
||||
* committing them.
|
||||
*/
|
||||
public class BackportEnglish extends BackportBase {
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
BackportEnglish backport = new BackportEnglish(args);
|
||||
backport.execute();
|
||||
}
|
||||
|
||||
|
||||
protected BackportEnglish(String[] args) throws IOException {
|
||||
super(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void execute() throws IOException {
|
||||
for (Object key : sourceEnglish.keySet()) {
|
||||
if (targetEnglish.containsKey(key)) {
|
||||
targetEnglish.put(key, sourceEnglish.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
Utils.export("", targetEnglish, storageDir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.buildutil.translate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Generates a set of translated property files to back-port updates to a
|
||||
* previous version. If the source and target use the same value for the English
|
||||
* key then any translated value for that key is copied from the source to the
|
||||
* target.
|
||||
*/
|
||||
public class BackportTranslations extends BackportBase {
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
BackportTranslations backport = new BackportTranslations(args);
|
||||
backport.execute();
|
||||
}
|
||||
|
||||
protected BackportTranslations(String[] args) throws IOException {
|
||||
super(args);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void execute() throws IOException {
|
||||
for (String langauge : targetTranslations.keySet()) {
|
||||
// Skip source
|
||||
if (langauge.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Properties sourceTranslated = sourceTranslations.get(langauge);
|
||||
Properties targetTranslated = targetTranslations.get(langauge);
|
||||
if (targetTranslated == null) {
|
||||
targetTranslated = new Properties();
|
||||
targetTranslations.put(langauge, targetTranslated);
|
||||
}
|
||||
|
||||
for (Object key : targetEnglish.keySet()) {
|
||||
if (sourceTranslated.containsKey(key) &&
|
||||
targetEnglish.get(key).equals(sourceEnglish.get(key))) {
|
||||
|
||||
targetTranslated.put(key, sourceTranslated.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove translated values for keys that have been removed
|
||||
Iterator<Map.Entry<Object,Object>> iter = targetTranslated.entrySet().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Map.Entry<Object,Object> entry = iter.next();
|
||||
if (!targetEnglish.containsKey(entry.getKey())) {
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
Utils.export(langauge, targetTranslated, storageDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
java/org/apache/tomcat/buildutil/translate/Constants.java
Normal file
29
java/org/apache/tomcat/buildutil/translate/Constants.java
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.buildutil.translate;
|
||||
|
||||
public class Constants {
|
||||
|
||||
public static final String L10N_PREFIX = "LocalStrings";
|
||||
public static final String L10N_SUFFIX = ".properties";
|
||||
|
||||
public static final String[] SEARCH_DIRS = new String[] { "java", "webapps" };
|
||||
|
||||
public static final String STORAGE_DIR = ".settings/translations";
|
||||
|
||||
public static final String END_PACKAGE_MARKER = ".zzz.";
|
||||
}
|
||||
133
java/org/apache/tomcat/buildutil/translate/Import.java
Normal file
133
java/org/apache/tomcat/buildutil/translate/Import.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.buildutil.translate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
public class Import {
|
||||
|
||||
public static void main(String... args) throws IOException {
|
||||
File root = new File(Constants.STORAGE_DIR);
|
||||
|
||||
for (File f : root.listFiles()) {
|
||||
// Not robust but good enough
|
||||
if (f.isFile() && f.getName().startsWith(Constants.L10N_PREFIX)) {
|
||||
processFile(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private static void processFile(File f) throws IOException {
|
||||
String language = Utils.getLanguage(f.getName());
|
||||
|
||||
// Unlike the master branch, don't skip the original so we can import
|
||||
// updates to the English translations
|
||||
Properties props = Utils.load(f);
|
||||
Object[] objKeys = props.keySet().toArray();
|
||||
Arrays.sort(objKeys);
|
||||
|
||||
String currentPkg = null;
|
||||
Writer w = null;
|
||||
String currentGroup = "zzz";
|
||||
|
||||
for (Object objKey : objKeys) {
|
||||
String key = (String) objKey;
|
||||
CompositeKey cKey = new CompositeKey(key);
|
||||
|
||||
if (!cKey.pkg.equals(currentPkg)) {
|
||||
currentPkg = cKey.pkg;
|
||||
if (w != null) {
|
||||
w.close();
|
||||
}
|
||||
File outFile = new File(currentPkg.replace('.', File.separatorChar), Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX);
|
||||
FileOutputStream fos = new FileOutputStream(outFile);
|
||||
w = new OutputStreamWriter(fos, StandardCharsets.UTF_8);
|
||||
insertLicense(w);
|
||||
}
|
||||
|
||||
if (!currentGroup.equals(cKey.group)) {
|
||||
currentGroup = cKey.group;
|
||||
w.write(System.lineSeparator());
|
||||
}
|
||||
|
||||
w.write(cKey.key + "=" + Utils.formatValue(props.getProperty(key)));
|
||||
w.write(System.lineSeparator());
|
||||
}
|
||||
if (w != null) {
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void insertLicense(Writer w) throws IOException {
|
||||
w.write("# Licensed to the Apache Software Foundation (ASF) under one or more");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# contributor license agreements. See the NOTICE file distributed with");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# this work for additional information regarding copyright ownership.");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# The ASF licenses this file to You under the Apache License, Version 2.0");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# (the \"License\"); you may not use this file except in compliance with");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# the License. You may obtain a copy of the License at");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("#");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# http://www.apache.org/licenses/LICENSE-2.0");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("#");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# Unless required by applicable law or agreed to in writing, software");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# distributed under the License is distributed on an \"AS IS\" BASIS,");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# See the License for the specific language governing permissions and");
|
||||
w.write(System.lineSeparator());
|
||||
w.write("# limitations under the License.");
|
||||
w.write(System.lineSeparator());
|
||||
}
|
||||
private static class CompositeKey {
|
||||
|
||||
public final String pkg;
|
||||
public final String key;
|
||||
public final String group;
|
||||
|
||||
public CompositeKey(String in) {
|
||||
int posPkg = in.indexOf(Constants.END_PACKAGE_MARKER);
|
||||
pkg = in.substring(0, posPkg);
|
||||
key = in.substring(posPkg + Constants.END_PACKAGE_MARKER.length());
|
||||
int posGroup = key.indexOf('.');
|
||||
if (posGroup == -1) {
|
||||
group = "";
|
||||
} else {
|
||||
group = key.substring(0, posGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
149
java/org/apache/tomcat/buildutil/translate/Utils.java
Normal file
149
java/org/apache/tomcat/buildutil/translate/Utils.java
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.buildutil.translate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Utils {
|
||||
|
||||
private static final Pattern ADD_CONTINUATION = Pattern.compile("\\n", Pattern.MULTILINE);
|
||||
private static final Pattern ESCAPE_LEADING_SPACE = Pattern.compile("^(\\s)", Pattern.MULTILINE);
|
||||
private static final Pattern FIX_SINGLE_QUOTE = Pattern.compile("(?<!')'(?!')", Pattern.MULTILINE);
|
||||
|
||||
private Utils() {
|
||||
// Utility class. Hide default constructor.
|
||||
}
|
||||
|
||||
|
||||
static String getLanguage(String name) {
|
||||
return name.substring(Constants.L10N_PREFIX.length(), name.length() - Constants.L10N_SUFFIX.length());
|
||||
}
|
||||
|
||||
|
||||
static Properties load(File f) {
|
||||
Properties props = new Properties();
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(f);
|
||||
Reader r = new InputStreamReader(fis, StandardCharsets.UTF_8)) {
|
||||
props.load(r);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
static String formatValue(String in) {
|
||||
String result = ADD_CONTINUATION.matcher(in).replaceAll("\\\\n\\\\\n");
|
||||
if (result.endsWith("\\\n")) {
|
||||
result = result.substring(0, result.length() - 2);
|
||||
}
|
||||
result = ESCAPE_LEADING_SPACE.matcher(result).replaceAll("\\\\$1");
|
||||
|
||||
if (result.contains("\n\\\t")) {
|
||||
result = result.replace("\n\\\t", "\n\\t");
|
||||
}
|
||||
|
||||
if (result.contains("[{0}]")) {
|
||||
result = FIX_SINGLE_QUOTE.matcher(result).replaceAll("''");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void processDirectory(File root, File dir, Map<String,Properties> translations) throws IOException {
|
||||
File[] files = dir.listFiles();
|
||||
if (files == null) {
|
||||
throw new IllegalArgumentException("Not a directory [" + dir.getAbsolutePath() + "]");
|
||||
}
|
||||
for (File f : files) {
|
||||
if (f.isDirectory()) {
|
||||
processDirectory(root, f, translations);
|
||||
} else if (f.isFile()) {
|
||||
processFile(root, f, translations);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void processFile(File root, File f, Map<String,Properties> translations) throws IOException {
|
||||
String name = f.getName();
|
||||
|
||||
// non-l10n files
|
||||
if (!name.startsWith(Constants.L10N_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine language
|
||||
String language = Utils.getLanguage(name);
|
||||
|
||||
String keyPrefix = getKeyPrefix(root, f);
|
||||
Properties props = Utils.load(f);
|
||||
|
||||
// Create a Map for the language if one does not exist.
|
||||
Properties translation = translations.get(language);
|
||||
if (translation == null) {
|
||||
translation = new Properties();
|
||||
translations.put(language, translation);
|
||||
}
|
||||
|
||||
// Add the properties from this file to the combined file, prefixing the
|
||||
// key with the package name to ensure uniqueness.
|
||||
for (Object obj : props.keySet()) {
|
||||
String key = (String) obj;
|
||||
String value = props.getProperty(key);
|
||||
|
||||
translation.put(keyPrefix + key, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static String getKeyPrefix(File root, File f) throws IOException {
|
||||
String prefix = f.getParentFile().getCanonicalPath();
|
||||
prefix = prefix.substring(root.getCanonicalPath().length() + 1);
|
||||
prefix = prefix.replace(File.separatorChar, '.');
|
||||
prefix = prefix + Constants.END_PACKAGE_MARKER;
|
||||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
static void export(String language, Properties translation, File storageDir) {
|
||||
File out = new File(storageDir, Constants.L10N_PREFIX + language + Constants.L10N_SUFFIX);
|
||||
try (FileOutputStream fos = new FileOutputStream(out);
|
||||
Writer w = new OutputStreamWriter(fos, StandardCharsets.UTF_8)) {
|
||||
String[] keys = translation.keySet().toArray(new String[0]);
|
||||
Arrays.sort(keys);
|
||||
for (Object key : keys) {
|
||||
w.write(key + "=" + Utils.formatValue(translation.getProperty((String) key)) + "\n");
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
180
java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
Normal file
180
java/org/apache/tomcat/dbcp/dbcp2/AbandonedTrace.java
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.TrackedUse;
|
||||
|
||||
/**
|
||||
* Tracks db connection usage for recovering and reporting abandoned db connections.
|
||||
* <p>
|
||||
* The JDBC Connection, Statement, and ResultSet classes extend this class.
|
||||
* </p>
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AbandonedTrace implements TrackedUse {
|
||||
|
||||
/** A list of objects created by children of this object. */
|
||||
private final List<WeakReference<AbandonedTrace>> traceList = new ArrayList<>();
|
||||
|
||||
/** Last time this connection was used. */
|
||||
private volatile long lastUsedMillis = 0;
|
||||
|
||||
/**
|
||||
* Creates a new AbandonedTrace without config and without doing abandoned tracing.
|
||||
*/
|
||||
public AbandonedTrace() {
|
||||
init(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new AbandonedTrace with a parent object.
|
||||
*
|
||||
* @param parent
|
||||
* AbandonedTrace parent object.
|
||||
*/
|
||||
public AbandonedTrace(final AbandonedTrace parent) {
|
||||
init(parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to the list of objects being traced.
|
||||
*
|
||||
* @param trace
|
||||
* AbandonedTrace object to add.
|
||||
*/
|
||||
protected void addTrace(final AbandonedTrace trace) {
|
||||
synchronized (this.traceList) {
|
||||
this.traceList.add(new WeakReference<>(trace));
|
||||
}
|
||||
setLastUsed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the list of objects being traced by this object.
|
||||
*/
|
||||
protected void clearTrace() {
|
||||
synchronized (this.traceList) {
|
||||
this.traceList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last time this object was used in milliseconds.
|
||||
*
|
||||
* @return long time in milliseconds.
|
||||
*/
|
||||
@Override
|
||||
public long getLastUsed() {
|
||||
return lastUsedMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of objects being traced by this object.
|
||||
*
|
||||
* @return List of objects.
|
||||
*/
|
||||
protected List<AbandonedTrace> getTrace() {
|
||||
final int size = traceList.size();
|
||||
if (size == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final ArrayList<AbandonedTrace> result = new ArrayList<>(size);
|
||||
synchronized (this.traceList) {
|
||||
final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final AbandonedTrace trace = iter.next().get();
|
||||
if (trace == null) {
|
||||
// Clean-up since we are here anyway
|
||||
iter.remove();
|
||||
} else {
|
||||
result.add(trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes abandoned tracing for this object.
|
||||
*
|
||||
* @param parent
|
||||
* AbandonedTrace parent object.
|
||||
*/
|
||||
private void init(final AbandonedTrace parent) {
|
||||
if (parent != null) {
|
||||
parent.addTrace(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes this object the source object is tracing.
|
||||
*
|
||||
* @param source The object tracing
|
||||
* @since 2.7.0
|
||||
*/
|
||||
protected void removeThisTrace(final Object source) {
|
||||
if (source instanceof AbandonedTrace) {
|
||||
AbandonedTrace.class.cast(source).removeTrace(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child object this object is tracing.
|
||||
*
|
||||
* @param trace
|
||||
* AbandonedTrace object to remove.
|
||||
*/
|
||||
protected void removeTrace(final AbandonedTrace trace) {
|
||||
synchronized (this.traceList) {
|
||||
final Iterator<WeakReference<AbandonedTrace>> iter = traceList.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final AbandonedTrace traceInList = iter.next().get();
|
||||
if (trace != null && trace.equals(traceInList)) {
|
||||
iter.remove();
|
||||
break;
|
||||
} else if (traceInList == null) {
|
||||
// Clean-up since we are here anyway
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time this object was last used to the current time in milliseconds.
|
||||
*/
|
||||
protected void setLastUsed() {
|
||||
lastUsedMillis = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the time in milliseconds this object was last used.
|
||||
*
|
||||
* @param lastUsedMillis
|
||||
* time in milliseconds.
|
||||
*/
|
||||
protected void setLastUsed(final long lastUsedMillis) {
|
||||
this.lastUsedMillis = lastUsedMillis;
|
||||
}
|
||||
}
|
||||
2460
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
Normal file
2460
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSource.java
Normal file
File diff suppressed because it is too large
Load Diff
602
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
Normal file
602
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceFactory.java
Normal file
File diff suppressed because it is too large
Load Diff
316
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
Normal file
316
java/org/apache/tomcat/dbcp/dbcp2/BasicDataSourceMXBean.java
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
/**
|
||||
* Defines the methods that will be made available via JMX.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface BasicDataSourceMXBean {
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getAbandonedUsageTracking()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getAbandonedUsageTracking()}
|
||||
*/
|
||||
boolean getAbandonedUsageTracking();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultAutoCommit()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultAutoCommit()}
|
||||
*/
|
||||
Boolean getDefaultAutoCommit();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultReadOnly()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultReadOnly()}
|
||||
*/
|
||||
Boolean getDefaultReadOnly();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultTransactionIsolation()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultTransactionIsolation()}
|
||||
*/
|
||||
int getDefaultTransactionIsolation();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultCatalog()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultCatalog()}
|
||||
*/
|
||||
String getDefaultCatalog();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDefaultSchema()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDefaultSchema()}
|
||||
* @since 2.5.0
|
||||
*/
|
||||
String getDefaultSchema();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getCacheState()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getCacheState()}
|
||||
*/
|
||||
boolean getCacheState();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDriverClassName()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDriverClassName()}
|
||||
*/
|
||||
String getDriverClassName();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLifo()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLifo()}
|
||||
*/
|
||||
boolean getLifo();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxTotal()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxTotal()}
|
||||
*/
|
||||
int getMaxTotal();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxIdle()}
|
||||
*/
|
||||
int getMaxIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMinIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMinIdle()}
|
||||
*/
|
||||
int getMinIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getInitialSize()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getInitialSize()}
|
||||
*/
|
||||
int getInitialSize();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxWaitMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxWaitMillis()}
|
||||
*/
|
||||
long getMaxWaitMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isPoolPreparedStatements()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isPoolPreparedStatements()}
|
||||
*/
|
||||
boolean isPoolPreparedStatements();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxOpenPreparedStatements()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxOpenPreparedStatements()}
|
||||
*/
|
||||
int getMaxOpenPreparedStatements();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestOnCreate()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestOnCreate()}
|
||||
*/
|
||||
boolean getTestOnCreate();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestOnBorrow()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestOnBorrow()}
|
||||
*/
|
||||
boolean getTestOnBorrow();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTimeBetweenEvictionRunsMillis()}
|
||||
*/
|
||||
long getTimeBetweenEvictionRunsMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumTestsPerEvictionRun()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumTestsPerEvictionRun()}
|
||||
*/
|
||||
int getNumTestsPerEvictionRun();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMinEvictableIdleTimeMillis()}
|
||||
*/
|
||||
long getMinEvictableIdleTimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getSoftMinEvictableIdleTimeMillis()}
|
||||
*/
|
||||
long getSoftMinEvictableIdleTimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getTestWhileIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getTestWhileIdle()}
|
||||
*/
|
||||
boolean getTestWhileIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumActive()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumActive()}
|
||||
*/
|
||||
int getNumActive();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getNumIdle()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getNumIdle()}
|
||||
*/
|
||||
int getNumIdle();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getPassword()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getPassword()}
|
||||
*/
|
||||
String getPassword();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getUrl()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getUrl()}
|
||||
*/
|
||||
String getUrl();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getUsername()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getUsername()}
|
||||
*/
|
||||
String getUsername();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getValidationQuery()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getValidationQuery()}
|
||||
*/
|
||||
String getValidationQuery();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getValidationQueryTimeout()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getValidationQueryTimeout()}
|
||||
*/
|
||||
int getValidationQueryTimeout();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getConnectionInitSqlsAsArray()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getConnectionInitSqlsAsArray()}
|
||||
*/
|
||||
String[] getConnectionInitSqlsAsArray();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isAccessToUnderlyingConnectionAllowed()}
|
||||
*/
|
||||
boolean isAccessToUnderlyingConnectionAllowed();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getMaxConnLifetimeMillis()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getMaxConnLifetimeMillis()}
|
||||
*/
|
||||
long getMaxConnLifetimeMillis();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLogExpiredConnections()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLogExpiredConnections()}
|
||||
* @since 2.1
|
||||
*/
|
||||
boolean getLogExpiredConnections();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedOnBorrow()}
|
||||
*/
|
||||
boolean getRemoveAbandonedOnBorrow();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedOnMaintenance()}
|
||||
*/
|
||||
boolean getRemoveAbandonedOnMaintenance();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getRemoveAbandonedTimeout()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getRemoveAbandonedTimeout()}
|
||||
*/
|
||||
int getRemoveAbandonedTimeout();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getLogAbandoned()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getLogAbandoned()}
|
||||
*/
|
||||
boolean getLogAbandoned();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#isClosed()}
|
||||
*
|
||||
* @return {@link BasicDataSource#isClosed()}
|
||||
*/
|
||||
boolean isClosed();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getFastFailValidation()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getFastFailValidation()}
|
||||
* @since 2.1
|
||||
*/
|
||||
boolean getFastFailValidation();
|
||||
|
||||
/**
|
||||
* See {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
|
||||
*
|
||||
* @return {@link BasicDataSource#getDisconnectionSqlCodesAsArray()}
|
||||
* @since 2.1
|
||||
*/
|
||||
String[] getDisconnectionSqlCodesAsArray();
|
||||
}
|
||||
36
java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java
Normal file
36
java/org/apache/tomcat/dbcp/dbcp2/ConnectionFactory.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Abstract factory interface for creating {@link java.sql.Connection}s.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface ConnectionFactory {
|
||||
/**
|
||||
* Create a new {@link java.sql.Connection} in an implementation specific fashion.
|
||||
*
|
||||
* @return a new {@link java.sql.Connection}
|
||||
* @throws SQLException
|
||||
* if a database error occurs creating the connection
|
||||
*/
|
||||
Connection createConnection() throws SQLException;
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/*
|
||||
* Creates {@link ConnectionFactory} instances.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class ConnectionFactoryFactory {
|
||||
|
||||
/**
|
||||
* Creates a new {@link DriverConnectionFactory} allowing for an override through
|
||||
* {@link BasicDataSource#getDriverClassName()}.
|
||||
*
|
||||
* @param basicDataSource Configures creation.
|
||||
* @param driver The JDBC driver.
|
||||
* @return a new {@link DriverConnectionFactory} allowing for a {@link BasicDataSource#getDriverClassName()}
|
||||
* override.
|
||||
* @throws SQLException Thrown when instantiation fails.
|
||||
*/
|
||||
static ConnectionFactory createConnectionFactory(final BasicDataSource basicDataSource, final Driver driver)
|
||||
throws SQLException {
|
||||
final Properties connectionProperties = basicDataSource.getConnectionProperties();
|
||||
final String url = basicDataSource.getUrl();
|
||||
// Set up the driver connection factory we will use
|
||||
final String user = basicDataSource.getUsername();
|
||||
if (user != null) {
|
||||
connectionProperties.put("user", user);
|
||||
} else {
|
||||
basicDataSource.log("DBCP DataSource configured without a 'username'");
|
||||
}
|
||||
|
||||
final String pwd = basicDataSource.getPassword();
|
||||
if (pwd != null) {
|
||||
connectionProperties.put("password", pwd);
|
||||
} else {
|
||||
basicDataSource.log("DBCP DataSource configured without a 'password'");
|
||||
}
|
||||
final String connectionFactoryClassName = basicDataSource.getConnectionFactoryClassName();
|
||||
if (connectionFactoryClassName != null) {
|
||||
try {
|
||||
final Class<?> connectionFactoryFromCCL = Class.forName(connectionFactoryClassName);
|
||||
return (ConnectionFactory) connectionFactoryFromCCL
|
||||
.getConstructor(Driver.class, String.class, Properties.class)
|
||||
.newInstance(driver, url, connectionProperties);
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot load ConnectionFactory implementation '" + connectionFactoryClassName
|
||||
+ "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
// Defaults to DriverConnectionFactory
|
||||
return new DriverConnectionFactory(driver, url, connectionProperties);
|
||||
}
|
||||
|
||||
}
|
||||
34
java/org/apache/tomcat/dbcp/dbcp2/Constants.java
Normal file
34
java/org/apache/tomcat/dbcp/dbcp2/Constants.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
/**
|
||||
* Constants for use with JMX.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class Constants {
|
||||
|
||||
public static final String JMX_CONNECTION_POOL_BASE_EXT = ",connectionpool=";
|
||||
public static final String JMX_CONNECTION_POOL_PREFIX = "connections";
|
||||
|
||||
public static final String JMX_CONNECTION_BASE_EXT = JMX_CONNECTION_POOL_BASE_EXT + JMX_CONNECTION_POOL_PREFIX
|
||||
+ ",connection=";
|
||||
|
||||
public static final String JMX_STATEMENT_POOL_BASE_EXT = JMX_CONNECTION_BASE_EXT;
|
||||
public static final String JMX_STATEMENT_POOL_PREFIX = ",statementpool=statements";
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* A {@link DataSource}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DataSourceConnectionFactory implements ConnectionFactory {
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final String userName;
|
||||
|
||||
private final char[] userPassword;
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource) {
|
||||
this(dataSource, null, (char[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
* @param userName
|
||||
* The user name.
|
||||
* @param userPassword
|
||||
* The user password.
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final char[] userPassword) {
|
||||
this.dataSource = dataSource;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.clone(userPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance for the given DataSource.
|
||||
*
|
||||
* @param dataSource
|
||||
* The DataSource for this factory.
|
||||
* @param userName
|
||||
* The user name.
|
||||
* @param password
|
||||
* The user password.
|
||||
*/
|
||||
public DataSourceConnectionFactory(final DataSource dataSource, final String userName, final String password) {
|
||||
this.dataSource = dataSource;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.toCharArray(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
if (null == userName && null == userPassword) {
|
||||
return dataSource.getConnection();
|
||||
}
|
||||
return dataSource.getConnection(userName, Utils.toString(userPassword));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The data source.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user name.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user password.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public char[] getUserPassword() {
|
||||
return userPassword;
|
||||
}
|
||||
}
|
||||
1271
java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java
Normal file
1271
java/org/apache/tomcat/dbcp/dbcp2/DelegatingCallableStatement.java
Normal file
File diff suppressed because it is too large
Load Diff
1001
java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
Normal file
1001
java/org/apache/tomcat/dbcp/dbcp2/DelegatingConnection.java
Normal file
File diff suppressed because it is too large
Load Diff
1917
java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
Normal file
1917
java/org/apache/tomcat/dbcp/dbcp2/DelegatingDatabaseMetaData.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2026
java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
Normal file
2026
java/org/apache/tomcat/dbcp/dbcp2/DelegatingResultSet.java
Normal file
File diff suppressed because it is too large
Load Diff
710
java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
Normal file
710
java/org/apache/tomcat/dbcp/dbcp2/DelegatingStatement.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@link Driver}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DriverConnectionFactory implements ConnectionFactory {
|
||||
|
||||
private final String connectionString;
|
||||
|
||||
private final Driver driver;
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* Constructs a connection factory for a given Driver.
|
||||
*
|
||||
* @param driver
|
||||
* The Driver.
|
||||
* @param connectString
|
||||
* The connection string.
|
||||
* @param properties
|
||||
* The connection properties.
|
||||
*/
|
||||
public DriverConnectionFactory(final Driver driver, final String connectString, final Properties properties) {
|
||||
this.driver = driver;
|
||||
this.connectionString = connectString;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
return driver.connect(connectionString, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The connection String.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getConnectionString() {
|
||||
return connectionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Driver.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Driver getDriver() {
|
||||
return driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Properties.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getClass().getName() + " [" + String.valueOf(driver) + ";" + String.valueOf(connectionString) + ";"
|
||||
+ String.valueOf(properties) + "]";
|
||||
}
|
||||
}
|
||||
81
java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
Normal file
81
java/org/apache/tomcat/dbcp/dbcp2/DriverFactory.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/*
|
||||
* Creates {@link Driver} instances.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class DriverFactory {
|
||||
|
||||
static Driver createDriver(final BasicDataSource basicDataSource) throws SQLException {
|
||||
// Load the JDBC driver class
|
||||
Driver driverToUse = basicDataSource.getDriver();
|
||||
String driverClassName = basicDataSource.getDriverClassName();
|
||||
ClassLoader driverClassLoader = basicDataSource.getDriverClassLoader();
|
||||
String url = basicDataSource.getUrl();
|
||||
|
||||
if (driverToUse == null) {
|
||||
Class<?> driverFromCCL = null;
|
||||
if (driverClassName != null) {
|
||||
try {
|
||||
try {
|
||||
if (driverClassLoader == null) {
|
||||
driverFromCCL = Class.forName(driverClassName);
|
||||
} else {
|
||||
driverFromCCL = Class.forName(driverClassName, true, driverClassLoader);
|
||||
}
|
||||
} catch (final ClassNotFoundException cnfe) {
|
||||
driverFromCCL = Thread.currentThread().getContextClassLoader().loadClass(driverClassName);
|
||||
}
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot load JDBC driver class '" + driverClassName + "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (driverFromCCL == null) {
|
||||
driverToUse = DriverManager.getDriver(url);
|
||||
} else {
|
||||
// Usage of DriverManager is not possible, as it does not
|
||||
// respect the ContextClassLoader
|
||||
// N.B. This cast may cause ClassCastException which is
|
||||
// handled below
|
||||
driverToUse = (Driver) driverFromCCL.getConstructor().newInstance();
|
||||
if (!driverToUse.acceptsURL(url)) {
|
||||
throw new SQLException("No suitable driver", "08001");
|
||||
}
|
||||
}
|
||||
} catch (final Exception t) {
|
||||
final String message = "Cannot create JDBC driver of class '"
|
||||
+ (driverClassName != null ? driverClassName : "") + "' for connect URL '" + url + "'";
|
||||
basicDataSource.log(message, t);
|
||||
throw new SQLException(message, t);
|
||||
}
|
||||
}
|
||||
return driverToUse;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@link DriverManager}-based implementation of {@link ConnectionFactory}.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class DriverManagerConnectionFactory implements ConnectionFactory {
|
||||
|
||||
static {
|
||||
// Related to DBCP-212
|
||||
// Driver manager does not sync loading of drivers that use the service
|
||||
// provider interface. This will cause issues is multi-threaded
|
||||
// environments. This hack makes sure the drivers are loaded before
|
||||
// DBCP tries to use them.
|
||||
DriverManager.getDrivers();
|
||||
}
|
||||
|
||||
private final String connectionUri;
|
||||
|
||||
private final String userName;
|
||||
|
||||
private final char[] userPassword;
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @since 2.2
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.properties = new Properties();
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code> jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param properties
|
||||
* a list of arbitrary string tag/value pairs as connection arguments; normally at least a "user" and
|
||||
* "password" property should be included.
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final Properties properties) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.properties = properties;
|
||||
this.userName = null;
|
||||
this.userPassword = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param userName
|
||||
* the database user
|
||||
* @param userPassword
|
||||
* the user's password
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final String userName,
|
||||
final char[] userPassword) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.clone(userPassword);
|
||||
this.properties = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DriverManagerConnectionFactory.
|
||||
*
|
||||
* @param connectionUri
|
||||
* a database url of the form <code>jdbc:<em>subprotocol</em>:<em>subname</em></code>
|
||||
* @param userName
|
||||
* the database user
|
||||
* @param userPassword
|
||||
* the user's password
|
||||
*/
|
||||
public DriverManagerConnectionFactory(final String connectionUri, final String userName,
|
||||
final String userPassword) {
|
||||
this.connectionUri = connectionUri;
|
||||
this.userName = userName;
|
||||
this.userPassword = Utils.toCharArray(userPassword);
|
||||
this.properties = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection createConnection() throws SQLException {
|
||||
if (null == properties) {
|
||||
if (userName == null && userPassword == null) {
|
||||
return DriverManager.getConnection(connectionUri);
|
||||
}
|
||||
return DriverManager.getConnection(connectionUri, userName, Utils.toString(userPassword));
|
||||
}
|
||||
return DriverManager.getConnection(connectionUri, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The connection URI.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getConnectionUri() {
|
||||
return connectionUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The Properties.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The user name.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
}
|
||||
482
java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
Normal file
482
java/org/apache/tomcat/dbcp/dbcp2/Jdbc41Bridge.java
Normal file
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URL;
|
||||
import java.sql.Array;
|
||||
import java.sql.Blob;
|
||||
import java.sql.Clob;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.Date;
|
||||
import java.sql.Ref;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.RowId;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.SQLXML;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.sql.CommonDataSource;
|
||||
|
||||
/**
|
||||
* Defines bridge methods to JDBC 4.1 (Java 7) methods to allow call sites to operate safely (without
|
||||
* {@link AbstractMethodError}) when using a JDBC driver written for JDBC 4.0 (Java 6).
|
||||
*
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public class Jdbc41Bridge {
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#abort(Executor)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#abort(Executor)}, then call {@link Connection#close()}.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param executor
|
||||
* See {@link Connection#abort(Executor)}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#abort(Executor)}.
|
||||
* @see Connection#abort(Executor)
|
||||
*/
|
||||
public static void abort(final Connection connection, final Executor executor) throws SQLException {
|
||||
try {
|
||||
connection.abort(executor);
|
||||
} catch (final AbstractMethodError e) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link DatabaseMetaData#generatedKeyAlwaysReturned()} without throwing a
|
||||
* {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link DatabaseMetaData#generatedKeyAlwaysReturned()}, then return false.
|
||||
* </p>
|
||||
*
|
||||
* @param databaseMetaData
|
||||
* See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @return See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @throws SQLException
|
||||
* See {@link DatabaseMetaData#generatedKeyAlwaysReturned()}
|
||||
* @see DatabaseMetaData#generatedKeyAlwaysReturned()
|
||||
*/
|
||||
public static boolean generatedKeyAlwaysReturned(final DatabaseMetaData databaseMetaData) throws SQLException {
|
||||
try {
|
||||
return databaseMetaData.generatedKeyAlwaysReturned();
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#getNetworkTimeout()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#getNetworkTimeout()}, then return 0.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @return See {@link Connection#getNetworkTimeout()}
|
||||
* @throws SQLException
|
||||
* See {@link Connection#getNetworkTimeout()}
|
||||
* @see Connection#getNetworkTimeout()
|
||||
*/
|
||||
public static int getNetworkTimeout(final Connection connection) throws SQLException {
|
||||
try {
|
||||
return connection.getNetworkTimeout();
|
||||
} catch (final AbstractMethodError e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link ResultSet#getObject(int, Class)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link ResultSet#getObject(int, Class)}, then return 0.
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param resultSet
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param columnIndex
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @param type
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @return See {@link ResultSet#getObject(int, Class)}
|
||||
* @throws SQLException
|
||||
* See {@link ResultSet#getObject(int, Class)}
|
||||
* @see ResultSet#getObject(int, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getObject(final ResultSet resultSet, final int columnIndex, final Class<T> type)
|
||||
throws SQLException {
|
||||
try {
|
||||
return resultSet.getObject(columnIndex, type);
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (type == String.class) {
|
||||
return (T) resultSet.getString(columnIndex);
|
||||
}
|
||||
// Numbers
|
||||
if (type == Integer.class) {
|
||||
return (T) Integer.valueOf(resultSet.getInt(columnIndex));
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return (T) Long.valueOf(resultSet.getLong(columnIndex));
|
||||
}
|
||||
if (type == Double.class) {
|
||||
return (T) Double.valueOf(resultSet.getDouble(columnIndex));
|
||||
}
|
||||
if (type == Float.class) {
|
||||
return (T) Float.valueOf(resultSet.getFloat(columnIndex));
|
||||
}
|
||||
if (type == Short.class) {
|
||||
return (T) Short.valueOf(resultSet.getShort(columnIndex));
|
||||
}
|
||||
if (type == BigDecimal.class) {
|
||||
return (T) resultSet.getBigDecimal(columnIndex);
|
||||
}
|
||||
if (type == Byte.class) {
|
||||
return (T) Byte.valueOf(resultSet.getByte(columnIndex));
|
||||
}
|
||||
// Dates
|
||||
if (type == Date.class) {
|
||||
return (T) resultSet.getDate(columnIndex);
|
||||
}
|
||||
if (type == Time.class) {
|
||||
return (T) resultSet.getTime(columnIndex);
|
||||
}
|
||||
if (type == Timestamp.class) {
|
||||
return (T) resultSet.getTimestamp(columnIndex);
|
||||
}
|
||||
// Streams
|
||||
if (type == InputStream.class) {
|
||||
return (T) resultSet.getBinaryStream(columnIndex);
|
||||
}
|
||||
if (type == Reader.class) {
|
||||
return (T) resultSet.getCharacterStream(columnIndex);
|
||||
}
|
||||
// Other
|
||||
if (type == Object.class) {
|
||||
return (T) resultSet.getObject(columnIndex);
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return (T) Boolean.valueOf(resultSet.getBoolean(columnIndex));
|
||||
}
|
||||
if (type == Array.class) {
|
||||
return (T) resultSet.getArray(columnIndex);
|
||||
}
|
||||
if (type == Blob.class) {
|
||||
return (T) resultSet.getBlob(columnIndex);
|
||||
}
|
||||
if (type == Clob.class) {
|
||||
return (T) resultSet.getClob(columnIndex);
|
||||
}
|
||||
if (type == Ref.class) {
|
||||
return (T) resultSet.getRef(columnIndex);
|
||||
}
|
||||
if (type == RowId.class) {
|
||||
return (T) resultSet.getRowId(columnIndex);
|
||||
}
|
||||
if (type == SQLXML.class) {
|
||||
return (T) resultSet.getSQLXML(columnIndex);
|
||||
}
|
||||
if (type == URL.class) {
|
||||
return (T) resultSet.getURL(columnIndex);
|
||||
}
|
||||
throw new SQLFeatureNotSupportedException(
|
||||
String.format("resultSet=%s, columnIndex=%,d, type=%s", resultSet, Integer.valueOf(columnIndex), type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link ResultSet#getObject(String, Class)} without throwing a {@link AbstractMethodError}.
|
||||
*
|
||||
* @param <T>
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param resultSet
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param columnLabel
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @param type
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @return See {@link ResultSet#getObject(String, Class)}
|
||||
* @throws SQLException
|
||||
* See {@link ResultSet#getObject(String, Class)}
|
||||
* @see ResultSet#getObject(int, Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getObject(final ResultSet resultSet, final String columnLabel, final Class<T> type)
|
||||
throws SQLException {
|
||||
try {
|
||||
return resultSet.getObject(columnLabel, type);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// Numbers
|
||||
if (type == Integer.class) {
|
||||
return (T) Integer.valueOf(resultSet.getInt(columnLabel));
|
||||
}
|
||||
if (type == Long.class) {
|
||||
return (T) Long.valueOf(resultSet.getLong(columnLabel));
|
||||
}
|
||||
if (type == Double.class) {
|
||||
return (T) Double.valueOf(resultSet.getDouble(columnLabel));
|
||||
}
|
||||
if (type == Float.class) {
|
||||
return (T) Float.valueOf(resultSet.getFloat(columnLabel));
|
||||
}
|
||||
if (type == Short.class) {
|
||||
return (T) Short.valueOf(resultSet.getShort(columnLabel));
|
||||
}
|
||||
if (type == BigDecimal.class) {
|
||||
return (T) resultSet.getBigDecimal(columnLabel);
|
||||
}
|
||||
if (type == Byte.class) {
|
||||
return (T) Byte.valueOf(resultSet.getByte(columnLabel));
|
||||
}
|
||||
// Dates
|
||||
if (type == Date.class) {
|
||||
return (T) resultSet.getDate(columnLabel);
|
||||
}
|
||||
if (type == Time.class) {
|
||||
return (T) resultSet.getTime(columnLabel);
|
||||
}
|
||||
if (type == Timestamp.class) {
|
||||
return (T) resultSet.getTimestamp(columnLabel);
|
||||
}
|
||||
// Streams
|
||||
if (type == InputStream.class) {
|
||||
return (T) resultSet.getBinaryStream(columnLabel);
|
||||
}
|
||||
if (type == Reader.class) {
|
||||
return (T) resultSet.getCharacterStream(columnLabel);
|
||||
}
|
||||
// Other
|
||||
if (type == Object.class) {
|
||||
return (T) resultSet.getObject(columnLabel);
|
||||
}
|
||||
if (type == Boolean.class) {
|
||||
return (T) Boolean.valueOf(resultSet.getBoolean(columnLabel));
|
||||
}
|
||||
if (type == Array.class) {
|
||||
return (T) resultSet.getArray(columnLabel);
|
||||
}
|
||||
if (type == Blob.class) {
|
||||
return (T) resultSet.getBlob(columnLabel);
|
||||
}
|
||||
if (type == Clob.class) {
|
||||
return (T) resultSet.getClob(columnLabel);
|
||||
}
|
||||
if (type == Ref.class) {
|
||||
return (T) resultSet.getRef(columnLabel);
|
||||
}
|
||||
if (type == RowId.class) {
|
||||
return (T) resultSet.getRowId(columnLabel);
|
||||
}
|
||||
if (type == SQLXML.class) {
|
||||
return (T) resultSet.getSQLXML(columnLabel);
|
||||
}
|
||||
if (type == URL.class) {
|
||||
return (T) resultSet.getURL(columnLabel);
|
||||
}
|
||||
throw new SQLFeatureNotSupportedException(
|
||||
String.format("resultSet=%s, columnLabel=%s, type=%s", resultSet, columnLabel, type));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)} without throwing a
|
||||
* {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)},
|
||||
* then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param databaseMetaData
|
||||
* the receiver
|
||||
* @param catalog
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param schemaPattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param tableNamePattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @param columnNamePattern
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @return See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @throws SQLException
|
||||
* See {@link DatabaseMetaData#getPseudoColumns(String, String, String, String)}
|
||||
* @see DatabaseMetaData#getPseudoColumns(String, String, String, String)
|
||||
*/
|
||||
public static ResultSet getPseudoColumns(final DatabaseMetaData databaseMetaData, final String catalog,
|
||||
final String schemaPattern, final String tableNamePattern, final String columnNamePattern)
|
||||
throws SQLException {
|
||||
try {
|
||||
return databaseMetaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#getSchema()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#getSchema()}, then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @return null for a JDBC 4 driver or a value per {@link Connection#getSchema()}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#getSchema()}.
|
||||
* @see Connection#getSchema()
|
||||
*/
|
||||
public static String getSchema(final Connection connection) throws SQLException {
|
||||
try {
|
||||
return connection.getSchema();
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#setNetworkTimeout(Executor, int)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#setNetworkTimeout(Executor, int)}, then do nothing.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param executor
|
||||
* See {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @param milliseconds
|
||||
* {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @throws SQLException
|
||||
* {@link Connection#setNetworkTimeout(Executor, int)}
|
||||
* @see Connection#setNetworkTimeout(Executor, int)
|
||||
*/
|
||||
public static void setNetworkTimeout(final Connection connection, final Executor executor, final int milliseconds)
|
||||
throws SQLException {
|
||||
try {
|
||||
connection.setNetworkTimeout(executor, milliseconds);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Connection#setSchema(String)} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Connection#setSchema(String)}, then do nothing.
|
||||
* </p>
|
||||
*
|
||||
* @param connection
|
||||
* the receiver
|
||||
* @param schema
|
||||
* See {@link Connection#setSchema(String)}.
|
||||
* @throws SQLException
|
||||
* See {@link Connection#setSchema(String)}.
|
||||
* @see Connection#setSchema(String)
|
||||
*/
|
||||
public static void setSchema(final Connection connection, final String schema) throws SQLException {
|
||||
try {
|
||||
connection.setSchema(schema);
|
||||
} catch (final AbstractMethodError e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Statement#closeOnCompletion()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Statement#closeOnCompletion()}, then just check that the connection
|
||||
* is closed to then throw an SQLException.
|
||||
* </p>
|
||||
*
|
||||
* @param statement
|
||||
* See {@link Statement#closeOnCompletion()}
|
||||
* @throws SQLException
|
||||
* See {@link Statement#closeOnCompletion()}
|
||||
* @see Statement#closeOnCompletion()
|
||||
*/
|
||||
public static void closeOnCompletion(final Statement statement) throws SQLException {
|
||||
try {
|
||||
statement.closeOnCompletion();
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (statement.isClosed()) {
|
||||
throw new SQLException("Statement closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link Statement#isCloseOnCompletion()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link Statement#isCloseOnCompletion()}, then just check that the
|
||||
* connection is closed to then throw an SQLException.
|
||||
* </p>
|
||||
*
|
||||
* @param statement
|
||||
* See {@link Statement#isCloseOnCompletion()}
|
||||
* @return See {@link Statement#isCloseOnCompletion()}
|
||||
* @throws SQLException
|
||||
* See {@link Statement#isCloseOnCompletion()}
|
||||
* @see Statement#closeOnCompletion()
|
||||
*/
|
||||
public static boolean isCloseOnCompletion(final Statement statement) throws SQLException {
|
||||
try {
|
||||
return statement.isCloseOnCompletion();
|
||||
} catch (final AbstractMethodError e) {
|
||||
if (statement.isClosed()) {
|
||||
throw new SQLException("Statement closed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link CommonDataSource#getParentLogger()} without throwing a {@link AbstractMethodError}.
|
||||
* <p>
|
||||
* If the JDBC driver does not implement {@link CommonDataSource#getParentLogger()}, then return null.
|
||||
* </p>
|
||||
*
|
||||
* @param commonDataSource
|
||||
* See {@link CommonDataSource#getParentLogger()}
|
||||
* @return See {@link CommonDataSource#getParentLogger()}
|
||||
* @throws SQLFeatureNotSupportedException
|
||||
* See {@link CommonDataSource#getParentLogger()}
|
||||
*/
|
||||
public static Logger getParentLogger(final CommonDataSource commonDataSource) throws SQLFeatureNotSupportedException {
|
||||
try {
|
||||
return commonDataSource.getParentLogger();
|
||||
} catch (final AbstractMethodError e) {
|
||||
throw new SQLFeatureNotSupportedException("javax.sql.CommonDataSource#getParentLogger()");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
/**
|
||||
* Exception thrown when a connection's maximum lifetime has been exceeded.
|
||||
*
|
||||
* @since 2.1
|
||||
*/
|
||||
class LifetimeExceededException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -3783783104516492659L;
|
||||
|
||||
/**
|
||||
* Create a LifetimeExceededException.
|
||||
*/
|
||||
public LifetimeExceededException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a LifetimeExceededException with the given message.
|
||||
*
|
||||
* @param message
|
||||
* The message with which to create the exception
|
||||
*/
|
||||
public LifetimeExceededException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
57
java/org/apache/tomcat/dbcp/dbcp2/ListException.java
Normal file
57
java/org/apache/tomcat/dbcp/dbcp2/ListException.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An exception wrapping a list of exceptions.
|
||||
*
|
||||
* @since 2.4.0
|
||||
*/
|
||||
public class ListException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final List<Throwable> exceptionList;
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
|
||||
* be initialized by a call to {@link #initCause}.
|
||||
*
|
||||
* @param message
|
||||
* the detail message. The detail message is saved for later retrieval by the {@link #getMessage()}
|
||||
* method.
|
||||
* @param exceptionList
|
||||
* a list of exceptions.
|
||||
*/
|
||||
public ListException(final String message, final List<Throwable> exceptionList) {
|
||||
super(message);
|
||||
this.exceptionList = exceptionList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of exceptions.
|
||||
*
|
||||
* @return the list of exceptions.
|
||||
*/
|
||||
public List<Throwable> getExceptionList() {
|
||||
return exceptionList;
|
||||
}
|
||||
|
||||
}
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=The lifetime of the connection [{0}] milliseconds exceeds the maximum permitted value of [{1}] milliseconds
|
||||
|
||||
pool.close.fail=Cannot close connection pool.
|
||||
|
||||
poolableConnection.validate.fastFail=Fatal SQLException was thrown previously on this connection.
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Failed to validate a poolable connection.
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory not linked to pool. Calling setPool() to fix the configuration.
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=An internal object pool swallowed an Exception.
|
||||
16
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_de.properties
Normal file
16
java/org/apache/tomcat/dbcp/dbcp2/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.
|
||||
|
||||
poolableConnection.validate.fastFail=Fatale SQLException wurde bereits vorher von dieser Verbindung geworfen
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_fr.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_fr.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=La durée de vie de la connection de [{0}] millisecondes excède la valeur maximale permis de [{1}] millisecondes
|
||||
|
||||
pool.close.fail=Impossible de fermer le pool de connections
|
||||
|
||||
poolableConnection.validate.fastFail=Une exception fatale SQLException avait déjà été lancée pour cette connection
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Impossible de valider la connection poolable
|
||||
|
||||
poolingDataSource.factoryConfig=La PoolableConnectionFactory n'est pas liée au pool, il faut appeler setPool() pour y remédier et corriger la configuration
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=Un object interne du pool a avalé une exception
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ja.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ja.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=コネクション[{0}]ミリ秒の有効期間が[{1}]ミリ秒の許容最大値を超えています
|
||||
|
||||
pool.close.fail=コネクションプールを停止できません。
|
||||
|
||||
poolableConnection.validate.fastFail=このコネクションは過去に致命的な SQLException を送出したことがあります。
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=プール可能なコネクションを検証できません。
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory がコネクションプールに接続していません。構成を修復するには setPool() を呼び出してください。
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=内部オブジェクトプールが例外を飲み込みました。
|
||||
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ko.properties
Normal file
26
java/org/apache/tomcat/dbcp/dbcp2/LocalStrings_ko.properties
Normal file
@@ -0,0 +1,26 @@
|
||||
# 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.
|
||||
|
||||
connectionFactory.lifetimeExceeded=해당 연결의 존속시간 [{0}] 밀리초가, 최대 허용치인 [{1}] 밀리초를 초과합니다.
|
||||
|
||||
pool.close.fail=데이터베이스 연결 풀을 닫을 수 없습니다.
|
||||
|
||||
poolableConnection.validate.fastFail=이 연결에서, 심각한 SQLException이 이전에 발생했습니다.
|
||||
|
||||
poolableConnectionFactory.validateObject.fail=Poolable connection이 유효한지 확인하지 못했습니다.
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory가 풀에 연결되지 않았습니다. setPool()을 호출하여 이 설정 문제를 해결합니다.
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=내부 객체 풀이 예외 발생을 무시했습니다.
|
||||
@@ -0,0 +1,20 @@
|
||||
# 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.
|
||||
|
||||
poolableConnection.validate.fastFail=此连接上预先抛出了致命的 SQLException。
|
||||
|
||||
poolingDataSource.factoryConfig=PoolableConnectionFactory 未连接到连接池。请调用 setPool() 修复此配置。
|
||||
|
||||
swallowedExceptionLogger.onSwallowedException=一个内部对象池吞并了一个异常。
|
||||
105
java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
Normal file
105
java/org/apache/tomcat/dbcp/dbcp2/ObjectNameWrapper.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.juli.logging.Log;
|
||||
import org.apache.juli.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Internal wrapper class that allows JMX to be a noop if absent or disabled.
|
||||
*
|
||||
* @since 2.2.1
|
||||
*/
|
||||
class ObjectNameWrapper {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ObjectNameWrapper.class);
|
||||
|
||||
private static MBeanServer MBEAN_SERVER = getPlatformMBeanServer();
|
||||
|
||||
private static MBeanServer getPlatformMBeanServer() {
|
||||
try {
|
||||
return ManagementFactory.getPlatformMBeanServer();
|
||||
} catch (LinkageError | Exception e) {
|
||||
// ignore - JMX not available
|
||||
log.debug("Failed to get platform MBeanServer", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static ObjectName unwrap(final ObjectNameWrapper wrapper) {
|
||||
return wrapper == null ? null : wrapper.unwrap();
|
||||
}
|
||||
|
||||
public static ObjectNameWrapper wrap(final ObjectName objectName) {
|
||||
return new ObjectNameWrapper(objectName);
|
||||
}
|
||||
|
||||
public static ObjectNameWrapper wrap(final String name) throws MalformedObjectNameException {
|
||||
return wrap(new ObjectName(name));
|
||||
}
|
||||
|
||||
private final ObjectName objectName;
|
||||
|
||||
public ObjectNameWrapper(final ObjectName objectName) {
|
||||
this.objectName = objectName;
|
||||
}
|
||||
|
||||
public void registerMBean(final Object object) {
|
||||
if (MBEAN_SERVER == null || objectName == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
MBEAN_SERVER.registerMBean(object, objectName);
|
||||
} catch (LinkageError | Exception e) {
|
||||
log.warn("Failed to complete JMX registration for " + objectName, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7.0
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return Objects.toString(objectName);
|
||||
}
|
||||
|
||||
public void unregisterMBean() {
|
||||
if (MBEAN_SERVER == null || objectName == null) {
|
||||
return;
|
||||
}
|
||||
if (MBEAN_SERVER.isRegistered(objectName)) {
|
||||
try {
|
||||
MBEAN_SERVER.unregisterMBean(objectName);
|
||||
} catch (LinkageError | Exception e) {
|
||||
log.warn("Failed to complete JMX unregistration for " + objectName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectName unwrap() {
|
||||
return objectName;
|
||||
}
|
||||
|
||||
}
|
||||
998
java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
Normal file
998
java/org/apache/tomcat/dbcp/dbcp2/PStmtKey.java
Normal file
File diff suppressed because it is too large
Load Diff
145
java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
Normal file
145
java/org/apache/tomcat/dbcp/dbcp2/PoolableCallableStatement.java
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.KeyedObjectPool;
|
||||
|
||||
/**
|
||||
* A {@link DelegatingCallableStatement} that cooperates with {@link PoolingConnection} to implement a pool of
|
||||
* {@link CallableStatement}s.
|
||||
* <p>
|
||||
* The {@link #close} method returns this statement to its containing pool. (See {@link PoolingConnection}.)
|
||||
*
|
||||
* @see PoolingConnection
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolableCallableStatement extends DelegatingCallableStatement {
|
||||
|
||||
/**
|
||||
* The {@link KeyedObjectPool} from which this CallableStatement was obtained.
|
||||
*/
|
||||
private final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool;
|
||||
|
||||
/**
|
||||
* Key for this statement in the containing {@link KeyedObjectPool}.
|
||||
*/
|
||||
private final PStmtKey key;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param callableStatement
|
||||
* the underlying {@link CallableStatement}
|
||||
* @param key
|
||||
* the key for this statement in the {@link KeyedObjectPool}
|
||||
* @param pool
|
||||
* the {@link KeyedObjectPool} from which this CallableStatement was obtained
|
||||
* @param connection
|
||||
* the {@link DelegatingConnection} that created this CallableStatement
|
||||
*/
|
||||
public PoolableCallableStatement(final CallableStatement callableStatement, final PStmtKey key,
|
||||
final KeyedObjectPool<PStmtKey, DelegatingPreparedStatement> pool,
|
||||
final DelegatingConnection<Connection> connection) {
|
||||
super(connection, callableStatement);
|
||||
this.pool = pool;
|
||||
this.key = key;
|
||||
|
||||
// Remove from trace now because this statement will be
|
||||
// added by the activate method.
|
||||
removeThisTrace(getConnectionInternal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the CallableStatement to the pool. If {{@link #isClosed()}, this is a No-op.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
// calling close twice should have no effect
|
||||
if (!isClosed()) {
|
||||
try {
|
||||
pool.returnObject(key, this);
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close CallableStatement (return to pool failed)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates after retrieval from the pool. Adds a trace for this CallableStatement to the Connection that created
|
||||
* it.
|
||||
*
|
||||
* @since 2.4.0 made public, was protected in 2.3.0.
|
||||
*/
|
||||
@Override
|
||||
public void activate() throws SQLException {
|
||||
setClosedInternal(false);
|
||||
if (getConnectionInternal() != null) {
|
||||
getConnectionInternal().addTrace(this);
|
||||
}
|
||||
super.activate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Passivates to prepare for return to the pool. Removes the trace associated with this CallableStatement from the
|
||||
* Connection that created it. Also closes any associated ResultSets.
|
||||
*
|
||||
* @since 2.4.0 made public, was protected in 2.3.0.
|
||||
*/
|
||||
@Override
|
||||
public void passivate() throws SQLException {
|
||||
setClosedInternal(true);
|
||||
removeThisTrace(getConnectionInternal());
|
||||
|
||||
// The JDBC spec requires that a statement close any open
|
||||
// ResultSet's when it is closed.
|
||||
// FIXME The PreparedStatement we're wrapping should handle this for us.
|
||||
// See DBCP-10 for what could happen when ResultSets are closed twice.
|
||||
final List<AbandonedTrace> resultSetList = getTrace();
|
||||
if (resultSetList != null) {
|
||||
final List<Exception> thrownList = new ArrayList<>();
|
||||
final ResultSet[] resultSets = resultSetList.toArray(new ResultSet[resultSetList.size()]);
|
||||
for (final ResultSet resultSet : resultSets) {
|
||||
if (resultSet != null) {
|
||||
try {
|
||||
resultSet.close();
|
||||
} catch (Exception e) {
|
||||
thrownList.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTrace();
|
||||
if (!thrownList.isEmpty()) {
|
||||
throw new SQLExceptionList(thrownList);
|
||||
}
|
||||
}
|
||||
|
||||
super.passivate();
|
||||
}
|
||||
|
||||
}
|
||||
348
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
Normal file
348
java/org/apache/tomcat/dbcp/dbcp2/PoolableConnection.java
Normal file
@@ -0,0 +1,348 @@
|
||||
/*
|
||||
* 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.dbcp.dbcp2;
|
||||
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.MBeanRegistrationException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.NotCompliantMBeanException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.apache.tomcat.dbcp.pool2.ObjectPool;
|
||||
|
||||
/**
|
||||
* A delegating connection that, rather than closing the underlying connection, returns itself to an {@link ObjectPool}
|
||||
* when closed.
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PoolableConnection extends DelegatingConnection<Connection> implements PoolableConnectionMXBean {
|
||||
|
||||
private static MBeanServer MBEAN_SERVER;
|
||||
|
||||
static {
|
||||
try {
|
||||
MBEAN_SERVER = ManagementFactory.getPlatformMBeanServer();
|
||||
} catch (NoClassDefFoundError | Exception ex) {
|
||||
// ignore - JMX not available
|
||||
}
|
||||
}
|
||||
|
||||
/** The pool to which I should return. */
|
||||
private final ObjectPool<PoolableConnection> pool;
|
||||
|
||||
private final ObjectNameWrapper jmxObjectName;
|
||||
|
||||
// Use a prepared statement for validation, retaining the last used SQL to
|
||||
// check if the validation query has changed.
|
||||
private PreparedStatement validationPreparedStatement;
|
||||
private String lastValidationSql;
|
||||
|
||||
/**
|
||||
* Indicate that unrecoverable SQLException was thrown when using this connection. Such a connection should be
|
||||
* considered broken and not pass validation in the future.
|
||||
*/
|
||||
private boolean fatalSqlExceptionThrown = false;
|
||||
|
||||
/**
|
||||
* SQL_STATE codes considered to signal fatal conditions. Overrides the defaults in
|
||||
* {@link Utils#DISCONNECTION_SQL_CODES} (plus anything starting with {@link Utils#DISCONNECTION_SQL_CODE_PREFIX}).
|
||||
*/
|
||||
private final Collection<String> disconnectionSqlCodes;
|
||||
|
||||
/** Whether or not to fast fail validation after fatal connection errors */
|
||||
private final boolean fastFailValidation;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param conn
|
||||
* my underlying connection
|
||||
* @param pool
|
||||
* the pool to which I should return when closed
|
||||
* @param jmxObjectName
|
||||
* JMX name
|
||||
* @param disconnectSqlCodes
|
||||
* SQL_STATE codes considered fatal disconnection errors
|
||||
* @param fastFailValidation
|
||||
* true means fatal disconnection errors cause subsequent validations to fail immediately (no attempt to
|
||||
* run query or isValid)
|
||||
*/
|
||||
public PoolableConnection(final Connection conn, final ObjectPool<PoolableConnection> pool,
|
||||
final ObjectName jmxObjectName, final Collection<String> disconnectSqlCodes,
|
||||
final boolean fastFailValidation) {
|
||||
super(conn);
|
||||
this.pool = pool;
|
||||
this.jmxObjectName = ObjectNameWrapper.wrap(jmxObjectName);
|
||||
this.disconnectionSqlCodes = disconnectSqlCodes;
|
||||
this.fastFailValidation = fastFailValidation;
|
||||
|
||||
if (jmxObjectName != null) {
|
||||
try {
|
||||
MBEAN_SERVER.registerMBean(this, jmxObjectName);
|
||||
} catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
|
||||
// For now, simply skip registration
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param conn
|
||||
* my underlying connection
|
||||
* @param pool
|
||||
* the pool to which I should return when closed
|
||||
* @param jmxName
|
||||
* JMX name
|
||||
*/
|
||||
public PoolableConnection(final Connection conn, final ObjectPool<PoolableConnection> pool,
|
||||
final ObjectName jmxName) {
|
||||
this(conn, pool, jmxName, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void passivate() throws SQLException {
|
||||
super.passivate();
|
||||
setClosedInternal(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>
|
||||
* This method should not be used by a client to determine whether or not a connection should be return to the
|
||||
* connection pool (by calling {@link #close()}). Clients should always attempt to return a connection to the pool
|
||||
* once it is no longer required.
|
||||
*/
|
||||
@Override
|
||||
public boolean isClosed() throws SQLException {
|
||||
if (isClosedInternal()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getDelegateInternal().isClosed()) {
|
||||
// Something has gone wrong. The underlying connection has been
|
||||
// closed without the connection being returned to the pool. Return
|
||||
// it now.
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns me to my pool.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void close() throws SQLException {
|
||||
if (isClosedInternal()) {
|
||||
// already closed
|
||||
return;
|
||||
}
|
||||
|
||||
boolean isUnderlyingConnectionClosed;
|
||||
try {
|
||||
isUnderlyingConnectionClosed = getDelegateInternal().isClosed();
|
||||
} catch (final SQLException e) {
|
||||
try {
|
||||
pool.invalidateObject(this);
|
||||
} catch (final IllegalStateException ise) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final Exception ie) {
|
||||
// DO NOTHING the original exception will be rethrown
|
||||
}
|
||||
throw new SQLException("Cannot close connection (isClosed check failed)", e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't set close before this code block since the connection needs to be open when validation runs. Can't set
|
||||
* close after this code block since by then the connection will have been returned to the pool and may have
|
||||
* been borrowed by another thread. Therefore, the close flag is set in passivate().
|
||||
*/
|
||||
if (isUnderlyingConnectionClosed) {
|
||||
// Abnormal close: underlying connection closed unexpectedly, so we
|
||||
// must destroy this proxy
|
||||
try {
|
||||
pool.invalidateObject(this);
|
||||
} catch (final IllegalStateException e) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close connection (invalidating pooled object failed)", e);
|
||||
}
|
||||
} else {
|
||||
// Normal close: underlying connection is still open, so we
|
||||
// simply need to return this proxy to the pool
|
||||
try {
|
||||
pool.returnObject(this);
|
||||
} catch (final IllegalStateException e) {
|
||||
// pool is closed, so close the connection
|
||||
passivate();
|
||||
getInnermostDelegate().close();
|
||||
} catch (final SQLException e) {
|
||||
throw e;
|
||||
} catch (final RuntimeException e) {
|
||||
throw e;
|
||||
} catch (final Exception e) {
|
||||
throw new SQLException("Cannot close connection (return to pool failed)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually close my underlying {@link Connection}.
|
||||
*/
|
||||
@Override
|
||||
public void reallyClose() throws SQLException {
|
||||
if (jmxObjectName != null) {
|
||||
jmxObjectName.unregisterMBean();
|
||||
}
|
||||
|
||||
if (validationPreparedStatement != null) {
|
||||
try {
|
||||
validationPreparedStatement.close();
|
||||
} catch (final SQLException sqle) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
super.closeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the {@link #toString()} method via a bean getter so it can be read as a property via JMX.
|
||||
*/
|
||||
@Override
|
||||
public String getToString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the connection, using the following algorithm:
|
||||
* <ol>
|
||||
* <li>If {@code fastFailValidation} (constructor argument) is {@code true} and this connection has previously
|
||||
* thrown a fatal disconnection exception, a {@code SQLException} is thrown.</li>
|
||||
* <li>If {@code sql} is null, the driver's #{@link Connection#isValid(int) isValid(timeout)} is called. If it
|
||||
* returns {@code false}, {@code SQLException} is thrown; otherwise, this method returns successfully.</li>
|
||||
* <li>If {@code sql} is not null, it is executed as a query and if the resulting {@code ResultSet} contains at
|
||||
* least one row, this method returns successfully. If not, {@code SQLException} is thrown.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param sql
|
||||
* The validation SQL query.
|
||||
* @param timeoutSeconds
|
||||
* The validation timeout in seconds.
|
||||
* @throws SQLException
|
||||
* Thrown when validation fails or an SQLException occurs during validation
|
||||
*/
|
||||
public void validate(final String sql, int timeoutSeconds) throws SQLException {
|
||||
if (fastFailValidation && fatalSqlExceptionThrown) {
|
||||
throw new SQLException(Utils.getMessage("poolableConnection.validate.fastFail"));
|
||||
}
|
||||
|
||||
if (sql == null || sql.length() == 0) {
|
||||
if (timeoutSeconds < 0) {
|
||||
timeoutSeconds = 0;
|
||||
}
|
||||
if (!isValid(timeoutSeconds)) {
|
||||
throw new SQLException("isValid() returned false");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sql.equals(lastValidationSql)) {
|
||||
lastValidationSql = sql;
|
||||
// Has to be the innermost delegate else the prepared statement will
|
||||
// be closed when the pooled connection is passivated.
|
||||
validationPreparedStatement = getInnermostDelegateInternal().prepareStatement(sql);
|
||||
}
|
||||
|
||||
if (timeoutSeconds > 0) {
|
||||
validationPreparedStatement.setQueryTimeout(timeoutSeconds);
|
||||
}
|
||||
|
||||
try (ResultSet rs = validationPreparedStatement.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
throw new SQLException("validationQuery didn't return a row");
|
||||
}
|
||||
} catch (final SQLException sqle) {
|
||||
throw sqle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the SQLState of the input exception and any nested SQLExceptions it wraps.
|
||||
* <p>
|
||||
* If {@link #disconnectionSqlCodes} has been set, sql states are compared to those in the
|
||||
* configured list of fatal exception codes. If this property is not set, codes are compared against the default
|
||||
* codes in {@link Utils#DISCONNECTION_SQL_CODES} and in this case anything starting with #{link
|
||||
* Utils.DISCONNECTION_SQL_CODE_PREFIX} is considered a disconnection.
|
||||
* </p>
|
||||
*
|
||||
* @param e
|
||||
* SQLException to be examined
|
||||
* @return true if the exception signals a disconnection
|
||||
*/
|
||||
private boolean isDisconnectionSqlException(final SQLException e) {
|
||||
boolean fatalException = false;
|
||||
final String sqlState = e.getSQLState();
|
||||
if (sqlState != null) {
|
||||
fatalException = disconnectionSqlCodes == null
|
||||
? sqlState.startsWith(Utils.DISCONNECTION_SQL_CODE_PREFIX)
|
||||
|| Utils.DISCONNECTION_SQL_CODES.contains(sqlState)
|
||||
: disconnectionSqlCodes.contains(sqlState);
|
||||
if (!fatalException) {
|
||||
final SQLException nextException = e.getNextException();
|
||||
if (nextException != null && nextException != e) {
|
||||
fatalException = isDisconnectionSqlException(e.getNextException());
|
||||
}
|
||||
}
|
||||
}
|
||||
return fatalException;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleException(final SQLException e) throws SQLException {
|
||||
fatalSqlExceptionThrown |= isDisconnectionSqlException(e);
|
||||
super.handleException(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The disconnection SQL codes.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public Collection<String> getDisconnectionSqlCodes() {
|
||||
return disconnectionSqlCodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether to fail-fast.
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public boolean isFastFailValidation() {
|
||||
return fastFailValidation;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user