001: /*
002: * @(#)AnalysisModuleType.java
003: *
004: * Copyright (C) 2002-2004 Matt Albrecht
005: * groboclown@users.sourceforge.net
006: * http://groboutils.sourceforge.net
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a
009: * copy of this software and associated documentation files (the "Software"),
010: * to deal in the Software without restriction, including without limitation
011: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
012: * and/or sell copies of the Software, and to permit persons to whom the
013: * Software is furnished to do so, subject to the following conditions:
014: *
015: * The above copyright notice and this permission notice shall be included in
016: * all copies or substantial portions of the Software.
017: *
018: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
019: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
020: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
021: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
022: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
023: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
024: * DEALINGS IN THE SOFTWARE.
025: */
026:
027: package net.sourceforge.groboutils.codecoverage.v2.ant;
028:
029: import java.util.Hashtable;
030:
031: import net.sourceforge.groboutils.codecoverage.v2.IAnalysisModule;
032: import net.sourceforge.groboutils.codecoverage.v2.module.BranchCountMeasure;
033: import net.sourceforge.groboutils.codecoverage.v2.module.BytecodeCountMeasure;
034: import net.sourceforge.groboutils.codecoverage.v2.module.CallPairMeasure;
035: import net.sourceforge.groboutils.codecoverage.v2.module.FunctionMeasure;
036: import net.sourceforge.groboutils.codecoverage.v2.module.LineCountMeasure;
037:
038: import org.apache.tools.ant.AntClassLoader;
039: import org.apache.tools.ant.BuildException;
040: import org.apache.tools.ant.types.DataType;
041: import org.apache.tools.ant.types.EnumeratedAttribute;
042: import org.apache.tools.ant.types.Path;
043: import org.apache.tools.ant.types.Reference;
044:
045: /**
046: * Loads an analysis module.
047: *
048: * @author Matt Albrecht <a href="mailto:groboclown@users.sourceforge.net">groboclown@users.sourceforge.net</a>
049: * @version $Date: 2004/04/15 05:48:25 $
050: * @since December 18, 2002
051: */
052: public class AnalysisModuleType extends DataType {
053: private static final Hashtable NAMES_TO_CLASSES = new Hashtable();
054: static {
055: NAMES_TO_CLASSES.put("line", LineCountMeasure.class);
056: NAMES_TO_CLASSES.put("linecount", LineCountMeasure.class);
057:
058: NAMES_TO_CLASSES.put("bytecode", BytecodeCountMeasure.class);
059:
060: NAMES_TO_CLASSES.put("branch", BranchCountMeasure.class);
061:
062: NAMES_TO_CLASSES.put("call", CallPairMeasure.class);
063: NAMES_TO_CLASSES.put("callpair", CallPairMeasure.class);
064: NAMES_TO_CLASSES.put("call-pair", CallPairMeasure.class);
065:
066: NAMES_TO_CLASSES.put("function", FunctionMeasure.class);
067: NAMES_TO_CLASSES.put("method", FunctionMeasure.class);
068: }
069:
070: public static final class TypeAttribute extends EnumeratedAttribute {
071: private String[] types = { "line", "linecount", "bytecode",
072: "branch", "call", "callpair", "call-pair", "function",
073: "method" };
074:
075: public String[] getValues() {
076: return this .types;
077: }
078: }
079:
080: private String moduleName;
081: private String className;
082: private Path classpath;
083: private String resource;
084: private String loaderId = null;
085: private String classpathId = null;
086:
087: public void setName(String n) {
088: this .moduleName = n;
089: }
090:
091: public void setType(TypeAttribute n) {
092: this .moduleName = n.getValue();
093: }
094:
095: public void setClassName(String c) {
096: this .className = c;
097: }
098:
099: /**
100: * Set the classpath to be used when searching for component being defined
101: *
102: * @param classpath an Ant Path object containing the classpath.
103: */
104: public void setClasspath(Path classpath) {
105: if (this .classpath == null) {
106: this .classpath = classpath;
107: } else {
108: this .classpath.append(classpath);
109: }
110: }
111:
112: /**
113: * Create the classpath to be used when searching for component being defined
114: */
115: public Path createClasspath() {
116: if (this .classpath == null) {
117: this .classpath = new Path(getProject());
118: }
119: return this .classpath.createPath();
120: }
121:
122: /**
123: * reference to a classpath to use when loading the files.
124: * To actually share the same loader, set loaderref as well
125: */
126: public void setClasspathRef(Reference r) {
127: this .classpathId = r.getRefId();
128: createClasspath().setRefid(r);
129: }
130:
131: /**
132: * Use the reference to locate the loader. If the loader is not
133: * found, taskdef will use the specified classpath and register it
134: * with the specified name.
135: *
136: * This allow multiple taskdef/typedef to use the same class loader,
137: * so they can be used together. It eliminate the need to
138: * put them in the CLASSPATH.
139: *
140: * @since Ant 1.5
141: */
142: public void setLoaderRef(Reference r) {
143: loaderId = r.getRefId();
144: }
145:
146: /**
147: * This method is guaranteed to never return <tt>null</tt>.
148: */
149: public IAnalysisModule getAnalysisModule() throws BuildException {
150: if (isReference()) {
151: return getRef().getAnalysisModule();
152: }
153:
154: Class c = null;
155: if (this .moduleName != null) {
156: c = (Class) NAMES_TO_CLASSES.get(this .moduleName
157: .toLowerCase());
158: if (c == null) {
159: throw new BuildException(
160: "Unknown analysis module name '"
161: + this .moduleName + "'.");
162: }
163: } else if (this .className != null) {
164: c = createClass(this .className);
165: if (c == null) {
166: throw new BuildException("Could not find class "
167: + this .className + " from classpath.");
168: }
169: } else {
170: throw new BuildException("Never set either the 'name' "
171: + "or the 'classname' attribute.");
172: }
173:
174: try {
175: return (IAnalysisModule) c.newInstance();
176: } catch (Exception ex) {
177: throw new BuildException(
178: "Error creating analysis module of type "
179: + c.getName() + ".", ex);
180: }
181: }
182:
183: protected AnalysisModuleType getRef() {
184: return (AnalysisModuleType) getCheckedRef(
185: AnalysisModuleType.class, "analysismodule");
186: }
187:
188: /**
189: * Stolen from o.a.t.a.taskdefs.Definer
190: */
191: private Class createClass(String classname) throws BuildException {
192: // If a loader has been set ( either by loaderRef or magic property )
193: if (loaderId != null) {
194: Object reusedLoader = getProject().getReference(loaderId);
195: if (reusedLoader != null) {
196: if (reusedLoader instanceof AntClassLoader) {
197: try {
198: return ((AntClassLoader) reusedLoader)
199: .loadClass(classname);
200: } catch (Exception e) {
201: throw new BuildException("Error loading class "
202: + classname, e);
203: }
204: }
205: // In future the reference object may be the <loader> type
206: // if( reusedLoader instanceof Loader ) {
207: // return ((Loader)reusedLoader).getLoader(project);
208: // }
209: }
210: }
211:
212: AntClassLoader al = null;
213: if (classpath != null) {
214: al = new AntClassLoader(getProject(), classpath, true);
215: } else {
216: al = new AntClassLoader(getProject(), Path.systemClasspath,
217: true);
218: }
219: // need to load Task via system classloader or the new
220: // task we want to define will never be a Task but always
221: // be wrapped into a TaskAdapter.
222: // al.addSystemPackageRoot("org.apache.tools.ant");
223:
224: // If the loader is new, record it for future uses by other
225: // task/typedefs
226: if (loaderId != null) {
227: if (getProject().getReference(loaderId) == null) {
228: getProject().addReference(loaderId, al);
229: }
230: }
231:
232: try {
233: return al.loadClass(classname);
234: } catch (Exception e) {
235: throw new BuildException(
236: "Error loading class " + classname, e);
237: }
238: }
239: }
|