1 /*
2 * ========================================================================
3 *
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * ========================================================================
20 */
21 package org.apache.cactus.integration.maven;
22
23 import java.lang.reflect.InvocationTargetException;
24
25 import org.apache.commons.jelly.JellyTagException;
26 import org.apache.commons.jelly.TagSupport;
27 import org.apache.commons.jelly.XMLOutput;
28 import org.apache.commons.jelly.MissingAttributeException;
29 import org.apache.commons.jelly.tags.ant.TaskSource;
30 import org.apache.commons.jelly.tags.ant.AntTagLibrary;
31 import org.apache.commons.beanutils.BeanUtils;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.tools.ant.types.FileSet;
35 import org.apache.tools.ant.types.Path;
36 import org.apache.tools.ant.types.Reference;
37
38 /**
39 * Cactus Jelly Tag that scans Ant FileSets and return a list of
40 * qualified class name that are Cactus TestCases (i.e.
41 * ServletTestCase, JspTestCase or FilterTestCase) or subclasses
42 * of Cactus TestCases.
43 *
44 * Note: This is useful when used with the <junit> Ant
45 * task for example, in order to find out the list of tests to
46 * execute.
47 *
48 * @version $Id: CactusScannerTag.java 239180 2005-07-12 01:50:53Z felipeal $
49 */
50 public class CactusScannerTag extends TagSupport implements TaskSource
51 {
52 /**
53 * Log instance.
54 */
55 private Log log = LogFactory.getLog(CactusScannerTag.class);
56
57 /**
58 * The {@link CactusScanner} object that is exposed by this tag
59 * to the Jelly script.
60 */
61 private CactusScanner cactusScanner;
62
63 /**
64 * We need to save the fileset as its XML attributes are set after the
65 * fileset object is created and thus we need to wait until it is
66 * completely initialized before being able to process it using
67 * {@link CactusScanner#processFileSet}.
68 */
69 private FileSet fileset;
70
71 /**
72 * Nested <classpath> tag values. This is the classpath that will
73 * be used to dynamically load the test classes to decide whether they
74 * are Cactus tests or not.
75 *
76 * Note: There is a bug in Jelly and it does not work yet. ATM you should
77 * use the classpathref attribute instead.
78 */
79 private Path classpath;
80
81 /**
82 * Reference to an Ant {@link Path} object containing the classpath.
83 * @see #classpath
84 */
85 private String classpathref;
86
87 /**
88 * The Jelly variable (exposed to the Jelly script) that will
89 * contain a reference to the {@link CactusScanner} object.
90 */
91 private String var;
92
93 /**
94 * Initializations.
95 */
96 public CactusScannerTag()
97 {
98 this.cactusScanner = new CactusScanner();
99 }
100
101 /**
102 * @param theXmlOutput the xml to hold the tag being made
103 * @see TagSupport#doTag(XMLOutput)
104 * @throws JellyTagException when proccess fails
105 */
106 public void doTag(XMLOutput theXmlOutput) throws JellyTagException
107 {
108 this.cactusScanner.setProject(AntTagLibrary.getProject(context));
109 this.cactusScanner.clear();
110
111 // run the body first to configure the task via nested tags
112 invokeBody(theXmlOutput);
113
114 // Process the fileset to extract Cactus test cases. We need to pass
115 // the project dependency classpath as the CactusScanner will need
116 // to load the cactus test classes to decide whether they are Cactus
117 // test case or not and that needs the dependent jars to be in the
118 // classpath.
119 Path cp = this.classpath;
120 if (this.classpathref != null)
121 {
122 cp = (Path) AntTagLibrary.getProject(
123 context).getReference(this.classpathref);
124 }
125
126 this.cactusScanner.processFileSet(this.fileset, cp);
127
128 // output the cactusScanner
129 if (var == null)
130 {
131 throw new MissingAttributeException("var");
132 }
133 context.setVariable(var, cactusScanner);
134 }
135
136 /**
137 * This method is called internally by Jelly to know on which object to
138 * call the {@link TaskSource#setTaskProperty} method.
139 *
140 * {@inheritDoc}
141 * @see TaskSource#getTaskObject()
142 */
143 public Object getTaskObject()
144 {
145 return this;
146 }
147
148 /**
149 * {@inheritDoc}
150 * @see TaskSource#setTaskProperty(String, Object)
151 */
152 public void setTaskProperty(String theName, Object theValue)
153 throws JellyTagException
154 {
155 try
156 {
157 BeanUtils.setProperty(this, theName, theValue);
158 }
159 catch (IllegalAccessException anException)
160 {
161 throw new JellyTagException(anException);
162 }
163 catch (InvocationTargetException anException)
164 {
165 throw new JellyTagException(anException);
166 }
167
168 }
169
170 /**
171 * Adds a set of files (nested fileset attribute). This method is called
172 * dynamically by {@link #setTaskProperty}.
173 *
174 * @param theSet the Ant fileset to add
175 */
176 public void addFileset(FileSet theSet)
177 {
178 log.debug("Adding fileset");
179 this.fileset = theSet;
180 }
181
182 /**
183 * @return a newly created and empty {@link Path} object
184 */
185 public Path createClasspath()
186 {
187 log.debug("Creating classpath");
188 if (this.classpath == null)
189 {
190 this.classpath = new Path(AntTagLibrary.getProject(context));
191 }
192 return this.classpath.createPath();
193 }
194
195 /**
196 * @return the classpath in which we will look for Cactus test cases.
197 */
198 public Path getClasspath()
199 {
200 return this.classpath;
201 }
202
203 /**
204 * Sets the classapth in which we will look for Cactus test cases.
205 * @param theClasspath the classapth to set
206 */
207 public void setClasspath(Path theClasspath)
208 {
209 log.debug("Setting classpath [" + theClasspath + "]");
210 if (this.classpath == null)
211 {
212 this.classpath = theClasspath;
213 }
214 else
215 {
216 this.classpath.append(theClasspath);
217 }
218 }
219
220 /**
221 * Sets the classpath in which we will look for Cactus test cases, using
222 * a reference.
223 *
224 * @param theReference the classpath reference
225 */
226 public void setClasspathRef(Reference theReference)
227 {
228 createClasspath().setRefid(theReference);
229 }
230
231 /**
232 * @return the Cactus scanner object
233 */
234 public CactusScanner getCactusScanner()
235 {
236 return this.cactusScanner;
237 }
238
239 /**
240 * Sets the name of the variable exported by this tag.
241 * @param theVar the variable that will be exported by this tag and which
242 * will contain the list of Cactus test cases
243 */
244 public void setVar(String theVar)
245 {
246 this.var = theVar;
247 }
248
249 /**
250 * Sets the classpath in which we will look for Cactus test cases, using
251 * a String reference.
252 * @param theClasspathref the classpath reference
253 */
254 public void setClasspathref(String theClasspathref)
255 {
256 this.classpathref = theClasspathref;
257 }
258 }