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.optional.extension;
019:
020: import java.io.File;
021: import java.util.ArrayList;
022: import java.util.jar.Manifest;
023: import org.apache.tools.ant.BuildException;
024: import org.apache.tools.ant.Project;
025: import org.apache.tools.ant.Task;
026: import org.apache.tools.ant.taskdefs.optional.extension.resolvers.AntResolver;
027: import org.apache.tools.ant.taskdefs.optional.extension.resolvers.LocationResolver;
028: import org.apache.tools.ant.taskdefs.optional.extension.resolvers.URLResolver;
029:
030: /**
031: * Tries to locate a JAR to satisfy an extension and place
032: * location of JAR into property.
033: *
034: * @ant.task name="jarlib-resolve"
035: */
036: public class JarLibResolveTask extends Task {
037: /**
038: * The name of the property in which the location of
039: * library is stored.
040: */
041: private String propertyName;
042:
043: /**
044: * The extension that is required.
045: */
046: private Extension requiredExtension;
047:
048: /**
049: * The set of resolvers to use to attempt to locate library.
050: */
051: private final ArrayList resolvers = new ArrayList();
052:
053: /**
054: * Flag to indicate that you should check that
055: * the librarys resolved actually contain
056: * extension and if they don't then raise
057: * an exception.
058: */
059: private boolean checkExtension = true;
060:
061: /**
062: * Flag indicating whether or not you should
063: * throw a BuildException if you cannot resolve
064: * library.
065: */
066: private boolean failOnError = true;
067:
068: /**
069: * The name of the property in which the location of
070: * library is stored.
071: *
072: * @param property The name of the property in which the location of
073: * library is stored.
074: */
075: public void setProperty(final String property) {
076: this .propertyName = property;
077: }
078:
079: /**
080: * Check nested libraries for extensions
081: *
082: * @param checkExtension if true, libraries returned by nested
083: * resolvers should be checked to see if they supply extension.
084: */
085: public void setCheckExtension(final boolean checkExtension) {
086: this .checkExtension = checkExtension;
087: }
088:
089: /**
090: * Set whether to fail if error.
091: *
092: * @param failOnError if true, failure to locate library should fail build.
093: */
094: public void setFailOnError(final boolean failOnError) {
095: this .failOnError = failOnError;
096: }
097:
098: /**
099: * Adds location resolver to look for a library in a location
100: * relative to project directory.
101: *
102: * @param loc the resolver location to search.
103: */
104: public void addConfiguredLocation(final LocationResolver loc) {
105: resolvers.add(loc);
106: }
107:
108: /**
109: * Adds a URL resolver to download a library from a URL
110: * to a local file.
111: *
112: * @param url the URL resolver from which to download the library
113: */
114: public void addConfiguredUrl(final URLResolver url) {
115: resolvers.add(url);
116: }
117:
118: /**
119: * Adds Ant resolver to run an Ant build file to generate a library.
120: *
121: * @param ant the AntResolver to generate the library.
122: */
123: public void addConfiguredAnt(final AntResolver ant) {
124: resolvers.add(ant);
125: }
126:
127: /**
128: * Set the Extension looking for.
129: *
130: * @param extension Set the Extension looking for.
131: */
132: public void addConfiguredExtension(final ExtensionAdapter extension) {
133: if (null != requiredExtension) {
134: final String message = "Can not specify extension to "
135: + "resolve multiple times.";
136: throw new BuildException(message);
137: }
138: requiredExtension = extension.toExtension();
139: }
140:
141: /**
142: * Execute the task.
143: *
144: * @throws BuildException if the task fails.
145: */
146: public void execute() throws BuildException {
147: validate();
148:
149: getProject().log("Resolving extension: " + requiredExtension,
150: Project.MSG_VERBOSE);
151:
152: String candidate = getProject().getProperty(propertyName);
153:
154: if (null != candidate) {
155: final String message = "Property Already set to: "
156: + candidate;
157: if (failOnError) {
158: throw new BuildException(message);
159: }
160: getProject().log(message, Project.MSG_ERR);
161: return;
162: }
163:
164: final int size = resolvers.size();
165: for (int i = 0; i < size; i++) {
166: final ExtensionResolver resolver = (ExtensionResolver) resolvers
167: .get(i);
168:
169: getProject().log(
170: "Searching for extension using Resolver:"
171: + resolver, Project.MSG_VERBOSE);
172:
173: try {
174: final File file = resolver.resolve(requiredExtension,
175: getProject());
176: try {
177: checkExtension(file);
178: return;
179: } catch (final BuildException be) {
180: final String message = "File "
181: + file
182: + " returned by "
183: + "resolver failed to satisfy extension due to: "
184: + be.getMessage();
185: getProject().log(message, Project.MSG_WARN);
186: }
187: } catch (final BuildException be) {
188: final String message = "Failed to resolve extension to file "
189: + "using resolver "
190: + resolver
191: + " due to: "
192: + be;
193: getProject().log(message, Project.MSG_WARN);
194: }
195: }
196:
197: missingExtension();
198: }
199:
200: /**
201: * Utility method that will throw a {@link BuildException}
202: * if {@link #failOnError} is true else it just displays
203: * a warning.
204: */
205: private void missingExtension() {
206: final String message = "Unable to resolve extension to a file";
207: if (failOnError) {
208: throw new BuildException(message);
209: }
210: getProject().log(message, Project.MSG_ERR);
211: }
212:
213: /**
214: * Check if specified file satisfies extension.
215: * If it does then set the relevent property
216: * else throw a BuildException.
217: *
218: * @param file the candidate library
219: * @throws BuildException if library does not satisfy extension
220: */
221: private void checkExtension(final File file) {
222: if (!file.exists()) {
223: final String message = "File " + file + " does not exist";
224: throw new BuildException(message);
225: }
226: if (!file.isFile()) {
227: final String message = "File " + file + " is not a file";
228: throw new BuildException(message);
229: }
230:
231: if (!checkExtension) {
232: final String message = "Setting property to " + file
233: + " without verifying library satisfies extension";
234: getProject().log(message, Project.MSG_VERBOSE);
235: setLibraryProperty(file);
236: } else {
237: getProject().log(
238: "Checking file " + file
239: + " to see if it satisfies extension",
240: Project.MSG_VERBOSE);
241: final Manifest manifest = ExtensionUtil.getManifest(file);
242: final Extension[] extensions = Extension
243: .getAvailable(manifest);
244: for (int i = 0; i < extensions.length; i++) {
245: final Extension extension = extensions[i];
246: if (extension.isCompatibleWith(requiredExtension)) {
247: setLibraryProperty(file);
248: return;
249: }
250: }
251:
252: getProject().log(
253: "File " + file + " skipped as it "
254: + "does not satisfy extension",
255: Project.MSG_VERBOSE);
256:
257: final String message = "File " + file
258: + " does not satisfy extension";
259: throw new BuildException(message);
260: }
261: }
262:
263: /**
264: * Utility method to set the appropriate property
265: * to indicate that specified file satisfies library
266: * requirements.
267: *
268: * @param file the library
269: */
270: private void setLibraryProperty(final File file) {
271: getProject().setNewProperty(propertyName,
272: file.getAbsolutePath());
273: }
274:
275: /**
276: * Validate the tasks parameters.
277: *
278: * @throws BuildException if invalid parameters found
279: */
280: private void validate() throws BuildException {
281: if (null == propertyName) {
282: final String message = "Property attribute must be specified.";
283: throw new BuildException(message);
284: }
285:
286: if (null == requiredExtension) {
287: final String message = "Extension element must be specified.";
288: throw new BuildException(message);
289: }
290: }
291: }
|