001: /*
002: Copyright (c) 2003, Andrew J. Glover
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028: package org.jibx.binding.ant;
029:
030: import java.io.File;
031: import java.util.ArrayList;
032: import java.util.List;
033:
034: import org.apache.tools.ant.AntClassLoader;
035: import org.apache.tools.ant.BuildException;
036: import org.apache.tools.ant.DirectoryScanner;
037: import org.apache.tools.ant.Task;
038: import org.apache.tools.ant.types.FileSet;
039: import org.apache.tools.ant.types.Path;
040: import org.jibx.binding.Compile;
041: import org.jibx.runtime.JiBXException;
042:
043: /**
044: * Class alters user defined class files for JiBX functionality.
045: * @author aglover
046: * @author pledbrook
047: */
048: public class CompileTask extends Task {
049: private boolean m_load;
050: private boolean m_verbose;
051: private Path m_classpath;
052: private List m_fileSet;
053: private List m_bindingFileSet;
054: private String m_bindingFile;
055:
056: /**
057: * Hook method called by ant framework to handle
058: * task initialization.
059: *
060: */
061: public void init() throws BuildException {
062: //
063: // Do aprent initialisation first.
064: //
065: super .init();
066:
067: //
068: // Now create the lists that store the classpathsets and
069: // the bindingsets.
070: //
071: m_fileSet = new ArrayList();
072: m_bindingFileSet = new ArrayList();
073: }
074:
075: /**
076: * Returns an array of paths of all the files specified by the
077: * <classpath> or <classpathset> tags. Note that the <classpath>
078: * and <classpathset> tags cannot both be specified.
079: */
080: private String[] getPaths() {
081: String[] pathArray = null;
082: if (m_classpath != null) {
083: //
084: // If a <classpath> tag has been set, m_classpath will
085: // not be null. In this case, just return the array of
086: // paths directly.
087: //
088: pathArray = m_classpath.list();
089: } else {
090: //
091: // Store the directory paths specified by each of the
092: // <classpathset> tags.
093: //
094: pathArray = new String[m_fileSet.size()];
095:
096: for (int i = 0; i < m_fileSet.size(); i++) {
097: FileSet fileSet = (FileSet) m_fileSet.get(i);
098: File directory = fileSet.getDir(project);
099: pathArray[i] = directory.getAbsolutePath();
100: }
101: }
102:
103: // make Ant classpath usable by application
104: try {
105: System.setProperty("java.class.path",
106: ((AntClassLoader) CompileTask.class
107: .getClassLoader()).getClasspath());
108: } catch (Exception e) {
109: System.err
110: .println("Failed setting classpath from Ant task");
111: }
112:
113: //
114: // If verbose mode is on, print out the paths we are using.
115: //
116: if (m_verbose) {
117: log("Using the following paths:");
118: for (int i = 0; i < pathArray.length; i++) {
119: log(" " + pathArray[i]);
120: }
121: }
122:
123: return pathArray;
124: }
125:
126: /**
127: * Returns an array of all the paths specified by the "binding"
128: * attribute or the <bindingfileset> tags.
129: */
130: private String[] getBindings() {
131: String[] bindings = null;
132: if (m_bindingFileSet.size() == 0) {
133: //
134: // No <bindingfileset> tags have been specified, so use
135: // the task's "binding" attribute instead.
136: //
137: bindings = new String[] { m_bindingFile };
138: } else {
139: //
140: // For each fileset, get all the file paths included by it.
141: //
142: ArrayList paths = new ArrayList();
143: for (int i = 0; i < m_bindingFileSet.size(); i++) {
144: FileSet bPath = (FileSet) m_bindingFileSet.get(i);
145:
146: DirectoryScanner dirScn = bPath
147: .getDirectoryScanner(project);
148: String[] bndingFiles = dirScn.getIncludedFiles();
149:
150: for (int x = 0; x < bndingFiles.length; x++) {
151: String fullPath = dirScn.getBasedir()
152: + System.getProperty("file.separator")
153: + bndingFiles[x];
154: paths.add(fullPath);
155: }
156: }
157:
158: //
159: // Convert the ArrayList of binding files into a native array.
160: //
161: bindings = (String[]) paths
162: .toArray(new String[paths.size()]);
163: }
164:
165: //
166: // If verbose mode is on, print out the binding files
167: // we are using.
168: //
169: if (m_verbose) {
170: log("Using the following binding paths:");
171: for (int i = 0; i < bindings.length; i++) {
172: log(" " + bindings[i]);
173: }
174: }
175:
176: return bindings;
177: }
178:
179: /**
180: * This checks that the build file has specified the correct
181: * mix of <classpath>, <classpathset>, <bindingfileset>
182: * and "binding". The rules are as follows:
183: * <ul>
184: * <li>Either the "binding" attribute <b>or</b> <bindingfileset>
185: * tags must be set. Not both.</li>
186: * <li>Either a single <classpath> tag <b>or</b> multiple
187: * <classpathset> tags must be set. Not both.</li>
188: * </ul>
189: * @throws BuildException
190: */
191: private void validateRequiredFields() throws BuildException {
192: //
193: // Check at least one of the binding file properties is set.
194: //
195: if (m_bindingFileSet.isEmpty() && m_bindingFile == null) {
196: throw new BuildException(
197: "Either the binding attribute or at "
198: + "least one bindingset nested element "
199: + "must be defined.");
200: }
201:
202: //
203: // Make sure that the "binding" attribute has not been used with the
204: // <bindingset> nested element.
205: //
206: if (!m_bindingFileSet.isEmpty() && m_bindingFile != null) {
207: throw new BuildException(
208: "You cannot specify both a binding attribute and a "
209: + "bindingset nested element.");
210: }
211:
212: //
213: // Check either <classpath> or <classpathset> has been set.
214: //
215: if (m_classpath == null && m_fileSet.isEmpty()) {
216: throw new BuildException(
217: "You must specify either a classpath "
218: + "or at least one nested classpathset element.");
219: }
220:
221: //
222: // Make sure that only one of the above is specified.
223: //
224: if (m_classpath != null && !m_fileSet.isEmpty()) {
225: throw new BuildException(
226: "You cannot specify both a classpath and a "
227: + "classpathset nested element.");
228: }
229: }
230:
231: /**
232: *
233: * Hook method called by Ant. Method first determines
234: * class file path from user defined value, then
235: * determines all binding files for class file weaving.
236: *
237: */
238: public void execute() throws BuildException {
239: try {
240: validateRequiredFields();
241:
242: String[] pathArr = getPaths();
243: String[] bindings = getBindings();
244:
245: Compile compiler = new Compile();
246:
247: //right now there is an issue with dynamically loading
248: //class files with ant. it doesnt work unless the class
249: //files are part of ANT's classpath. so I am forcing this
250: //to always be false until we can come up with a better solution.
251: compiler.setLoad(m_load);
252:
253: compiler.setVerbose(m_verbose);
254:
255: compiler.compile(pathArr, bindings);
256:
257: } catch (JiBXException jEx) {
258: jEx.printStackTrace();
259: throw new BuildException(
260: "JiBXException in JiBX binding compilation", jEx);
261: }
262: }
263:
264: /**
265: *
266: * @param fSet
267: */
268: public void addClassPathSet(FileSet fSet) {
269: m_fileSet.add(fSet);
270: }
271:
272: /**
273: * Returns the current classpath.
274: */
275: public Path getClasspath() {
276: return m_classpath;
277: }
278:
279: /**
280: * Sets the classpath for this task. Multiple calls append the
281: * new classpath to the current one, rather than overwriting it.
282: * @param classpath The new classpath as a Path object.
283: */
284: public void setClasspath(Path classpath) {
285: if (m_classpath == null) {
286: m_classpath = classpath;
287: } else {
288: m_classpath.append(classpath);
289: }
290: }
291:
292: /**
293: * Creates the classpath for this task and returns
294: * it. If the classpath has already been created,
295: * the method just returns that one.
296: */
297: public Path createClasspath() {
298: if (m_classpath == null) {
299: m_classpath = new Path(project);
300: }
301:
302: return m_classpath;
303: }
304:
305: /**
306: * @param file
307: */
308: public void setBinding(String file) {
309: m_bindingFile = file;
310: }
311:
312: /**
313: *
314: * @param bfSet
315: */
316: public void addBindingFileSet(FileSet bfSet) {
317: m_bindingFileSet.add(bfSet);
318: }
319:
320: /**
321: * @param bool
322: */
323: public void setLoad(boolean bool) {
324: m_load = bool;
325: }
326:
327: /**
328: * @param bool
329: */
330: public void setVerbose(boolean bool) {
331: m_verbose = bool;
332: }
333: }
|