aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java')
-rw-r--r--framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java265
1 files changed, 265 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
new file mode 100644
index 00000000..417da9a7
--- /dev/null
+++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/types/resources/AbstractClasspathResource.java
@@ -0,0 +1,265 @@
+/*
+ * 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.tools.ant.types.resources;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Stack;
+
+import org.apache.tools.ant.AntClassLoader;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ *
+ * A Resource representation of anything that is accessed via a Java classloader.
+ * The core methods to set/resolve the classpath are provided.
+ * @since Ant 1.8.0
+ *
+ */
+
+public abstract class AbstractClasspathResource extends Resource {
+ private Path classpath;
+ private Reference loader;
+ private boolean parentFirst = true;
+
+ /**
+ * Set the classpath to use when looking up a resource.
+ * @param classpath to add to any existing classpath
+ */
+ public void setClasspath(Path classpath) {
+ checkAttributesAllowed();
+ if (this.classpath == null) {
+ this.classpath = classpath;
+ } else {
+ this.classpath.append(classpath);
+ }
+ setChecked(false);
+ }
+
+ /**
+ * Add a classpath to use when looking up a resource.
+ * @return The classpath to be configured
+ */
+ public Path createClasspath() {
+ checkChildrenAllowed();
+ if (classpath == null) {
+ classpath = new Path(getProject());
+ }
+ setChecked(false);
+ return classpath.createPath();
+ }
+
+ /**
+ * Set the classpath to use when looking up a resource,
+ * given as reference to a <path> defined elsewhere
+ * @param r The reference value
+ */
+ public void setClasspathRef(Reference r) {
+ checkAttributesAllowed();
+ createClasspath().setRefid(r);
+ }
+
+ /**
+ * get the classpath used by this <code>LoadProperties</code>.
+ * @return The classpath
+ */
+ public Path getClasspath() {
+ if (isReference()) {
+ return ((AbstractClasspathResource) getCheckedRef()).getClasspath();
+ }
+ dieOnCircularReference();
+ return classpath;
+ }
+
+ /**
+ * Get the loader.
+ * @return the loader.
+ */
+ public Reference getLoader() {
+ if (isReference()) {
+ return ((AbstractClasspathResource) getCheckedRef()).getLoader();
+ }
+ dieOnCircularReference();
+ return loader;
+ }
+
+ /**
+ * Use the reference to locate the loader. If the loader is not
+ * found, taskdef will use the specified classpath and register it
+ * with the specified name.
+ *
+ * This allow multiple taskdef/typedef to use the same class loader,
+ * so they can be used together. It eliminate the need to
+ * put them in the CLASSPATH.
+ *
+ * @param r the reference to locate the loader.
+ */
+ public void setLoaderRef(Reference r) {
+ checkAttributesAllowed();
+ loader = r;
+ }
+
+ /**
+ * Whether to consult the parent classloader first.
+ *
+ * <p>Only relevant if a classpath has been specified.</p>
+ *
+ * @since Ant 1.8.0
+ */
+ public void setParentFirst(boolean b) {
+ parentFirst = b;
+ }
+
+ /**
+ * Overrides the super version.
+ * @param r the Reference to set.
+ */
+ public void setRefid(Reference r) {
+ if (loader != null || classpath != null) {
+ throw tooManyAttributes();
+ }
+ super.setRefid(r);
+ }
+
+ /**
+ * Learn whether this resource exists. This implementation opens the input stream
+ * as the test.
+ * @return true if this resource exists.
+ */
+ public boolean isExists() {
+ if (isReference()) {
+ return ((Resource) getCheckedRef()).isExists();
+ }
+ dieOnCircularReference();
+ InputStream is = null;
+ try {
+ is = getInputStream();
+ return is != null;
+ } catch (IOException ex) {
+ return false;
+ } finally {
+ FileUtils.close(is);
+ }
+ }
+
+ /**
+ * Return an InputStream for reading the contents of this Resource.
+ * @return an InputStream object.
+ * @throws IOException if an error occurs.
+ */
+ public InputStream getInputStream() throws IOException {
+ if (isReference()) {
+ return ((Resource) getCheckedRef()).getInputStream();
+ }
+ dieOnCircularReference();
+
+ final ClassLoaderWithFlag classLoader = getClassLoader();
+ return !classLoader.needsCleanup()
+ ? openInputStream(classLoader.getLoader())
+ : new FilterInputStream(openInputStream(classLoader.getLoader())) {
+ public void close() throws IOException {
+ FileUtils.close(in);
+ classLoader.cleanup();
+ }
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+ };
+ }
+
+ /**
+ * combines the various ways that could specify a ClassLoader and
+ * potentially creates one that needs to be cleaned up when it is
+ * no longer needed so that classes can get garbage collected.
+ */
+ protected ClassLoaderWithFlag getClassLoader() {
+ ClassLoader cl = null;
+ boolean clNeedsCleanup = false;
+ if (loader != null) {
+ cl = (ClassLoader) loader.getReferencedObject();
+ }
+ if (cl == null) {
+ if (getClasspath() != null) {
+ Path p = getClasspath().concatSystemClasspath("ignore");
+ if (parentFirst) {
+ cl = getProject().createClassLoader(p);
+ } else {
+ cl = AntClassLoader.newAntClassLoader(getProject()
+ .getCoreLoader(),
+ getProject(),
+ p, false);
+ }
+ clNeedsCleanup = loader == null;
+ } else {
+ cl = JavaResource.class.getClassLoader();
+ }
+ if (loader != null && cl != null) {
+ getProject().addReference(loader.getRefId(), cl);
+ }
+ }
+ return new ClassLoaderWithFlag(cl, clNeedsCleanup);
+ }
+
+ /**
+ * open the input stream from a specific classloader
+ * @param cl the classloader to use. Will be null if the system classloader is used
+ * @return an open input stream for the resource
+ * @throws IOException if an error occurs.
+ */
+ protected abstract InputStream openInputStream(ClassLoader cl) throws IOException;
+
+ protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p) {
+ if (isChecked()) {
+ return;
+ }
+ if (isReference()) {
+ super.dieOnCircularReference(stk, p);
+ } else {
+ if (classpath != null) {
+ pushAndInvokeCircularReferenceCheck(classpath, stk, p);
+ }
+ setChecked(true);
+ }
+ }
+
+ public static class ClassLoaderWithFlag {
+ private final ClassLoader loader;
+ private final boolean cleanup;
+
+ ClassLoaderWithFlag(ClassLoader l, boolean needsCleanup) {
+ loader = l;
+ cleanup = needsCleanup && l instanceof AntClassLoader;
+ }
+ public ClassLoader getLoader() { return loader; }
+ public boolean needsCleanup() { return cleanup; }
+ public void cleanup() {
+ if (cleanup) {
+ ((AntClassLoader) loader).cleanup();
+ }
+ }
+ }
+}