001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018: package org.apache.tools.ant.taskdefs.condition;
019:
020: import org.apache.tools.ant.types.Path;
021: import org.apache.tools.ant.types.Reference;
022: import org.apache.tools.ant.AntClassLoader;
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.ProjectComponent;
025:
026: import java.lang.reflect.Method;
027: import java.lang.reflect.Field;
028:
029: /**
030: * test for a method
031: */
032: public class HasMethod extends ProjectComponent implements Condition {
033: private String classname;
034: private String method;
035: private String field;
036: private Path classpath;
037: private AntClassLoader loader;
038: private boolean ignoreSystemClasses = false;
039:
040: /**
041: * Set the classpath to be used when searching for classes and resources.
042: *
043: * @param classpath an Ant Path object containing the search path.
044: */
045: public void setClasspath(Path classpath) {
046: createClasspath().append(classpath);
047: }
048:
049: /**
050: * Classpath to be used when searching for classes and resources.
051: *
052: * @return an empty Path instance to be configured by Ant.
053: */
054: public Path createClasspath() {
055: if (this .classpath == null) {
056: this .classpath = new Path(getProject());
057: }
058: return this .classpath.createPath();
059: }
060:
061: /**
062: * Set the classpath by reference.
063: *
064: * @param r a Reference to a Path instance to be used as the classpath
065: * value.
066: */
067: public void setClasspathRef(Reference r) {
068: createClasspath().setRefid(r);
069: }
070:
071: /**
072: * Set the classname attribute.
073: * @param classname the name of the class to check.
074: */
075: public void setClassname(String classname) {
076: this .classname = classname;
077: }
078:
079: /**
080: * Set the name of the method.
081: * @param method the name of the method to check.
082: */
083: public void setMethod(String method) {
084: this .method = method;
085: }
086:
087: /**
088: * Set the name of the field.
089: * @param field the name of the field to check.
090: */
091: public void setField(String field) {
092: this .field = field;
093: }
094:
095: /**
096: * Set whether to ignore system classes when looking for the class.
097: * @param ignoreSystemClasses a <code>boolean</code> value.
098: */
099: public void setIgnoreSystemClasses(boolean ignoreSystemClasses) {
100: this .ignoreSystemClasses = ignoreSystemClasses;
101: }
102:
103: /**
104: * Check if a given class can be loaded.
105: */
106: private Class loadClass(String classname) {
107: try {
108: if (ignoreSystemClasses) {
109: loader = getProject().createClassLoader(classpath);
110: loader.setParentFirst(false);
111: loader.addJavaLibraries();
112: if (loader != null) {
113: try {
114: return loader.findClass(classname);
115: } catch (SecurityException se) {
116: // class found but restricted name; this is
117: // actually the case we're looking for in JDK 1.3+,
118: // so catch the exception and return
119: return null;
120: }
121: } else {
122: return null;
123: }
124: } else if (loader != null) {
125: return loader.loadClass(classname);
126: } else {
127: ClassLoader l = this .getClass().getClassLoader();
128: // Can return null to represent the bootstrap class loader.
129: // see API docs of Class.getClassLoader.
130: if (l != null) {
131: return Class.forName(classname, true, l);
132: } else {
133: return Class.forName(classname);
134: }
135: }
136: } catch (ClassNotFoundException e) {
137: throw new BuildException("class \"" + classname
138: + "\" was not found");
139: } catch (NoClassDefFoundError e) {
140: throw new BuildException(
141: "Could not load dependent class \""
142: + e.getMessage() + "\" for class \""
143: + classname + "\"");
144: }
145: }
146:
147: /** {@inheritDoc}. */
148: public boolean eval() throws BuildException {
149: if (classname == null) {
150: throw new BuildException("No classname defined");
151: }
152: Class clazz = loadClass(classname);
153: if (method != null) {
154: return isMethodFound(clazz);
155: }
156: if (field != null) {
157: return isFieldFound(clazz);
158: }
159: throw new BuildException("Neither method nor field defined");
160: }
161:
162: private boolean isFieldFound(Class clazz) {
163: Field[] fields = clazz.getDeclaredFields();
164: for (int i = 0; i < fields.length; i++) {
165: Field fieldEntry = fields[i];
166: if (fieldEntry.getName().equals(field)) {
167: return true;
168: }
169: }
170: return false;
171: }
172:
173: private boolean isMethodFound(Class clazz) {
174: Method[] methods = clazz.getDeclaredMethods();
175: for (int i = 0; i < methods.length; i++) {
176: Method methodEntry = methods[i];
177: if (methodEntry.getName().equals(method)) {
178: return true;
179: }
180: }
181: return false;
182: }
183:
184: }
|