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.ivy.ant;
019:
020: import java.io.File;
021: import java.util.Arrays;
022: import java.util.HashSet;
023:
024: import org.apache.ivy.Ivy;
025: import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
026: import org.apache.ivy.core.module.id.ModuleId;
027: import org.apache.ivy.core.module.id.ModuleRevisionId;
028: import org.apache.ivy.core.report.ResolveReport;
029: import org.apache.ivy.core.resolve.ResolveOptions;
030: import org.apache.ivy.core.settings.IvySettings;
031: import org.apache.ivy.util.Message;
032: import org.apache.ivy.util.StringUtils;
033: import org.apache.ivy.util.filter.Filter;
034: import org.apache.ivy.util.filter.FilterHelper;
035: import org.apache.tools.ant.BuildException;
036:
037: /**
038: * Base class for tasks needing to be performed after a resolve.
039: */
040: public abstract class IvyPostResolveTask extends IvyTask {
041: private String conf;
042:
043: private boolean haltOnFailure = true;
044:
045: private boolean transitive = true;
046:
047: private boolean inline = false;
048:
049: private String organisation;
050:
051: private String module;
052:
053: private String revision = "latest.integration";
054:
055: private String resolveId;
056:
057: private String type;
058:
059: private File file;
060:
061: private Filter artifactFilter = null;
062:
063: private boolean useOrigin = false;
064:
065: private Boolean keep = null;
066:
067: private String log = ResolveOptions.LOG_DEFAULT;
068:
069: public boolean isUseOrigin() {
070: return useOrigin;
071: }
072:
073: public void setUseOrigin(boolean useOrigin) {
074: this .useOrigin = useOrigin;
075: }
076:
077: public String getLog() {
078: return log;
079: }
080:
081: public void setLog(String log) {
082: this .log = log;
083: }
084:
085: protected void prepareAndCheck() {
086: Ivy ivy = getIvyInstance();
087: IvySettings settings = ivy.getSettings();
088:
089: boolean orgAndModSetManually = (organisation != null)
090: && (module != null);
091:
092: organisation = getProperty(organisation, settings,
093: "ivy.organisation");
094: module = getProperty(module, settings, "ivy.module");
095:
096: if (file == null) {
097: String fileName = getProperty(settings,
098: "ivy.resolved.file", resolveId);
099: if (fileName != null) {
100: file = new File(fileName);
101: }
102: }
103:
104: if (isInline()) {
105: conf = conf == null ? "*" : conf;
106: if (organisation == null) {
107: throw new BuildException(
108: "no organisation provided for ivy cache task in inline mode: "
109: + "It can either be set explicitely via the attribute 'organisation' "
110: + "or via 'ivy.organisation' property");
111: }
112: if (module == null) {
113: throw new BuildException(
114: "no module name provided for ivy cache task in inline mode: "
115: + "It can either be set explicitely via the attribute 'module' "
116: + "or via 'ivy.module' property");
117: }
118: String[] toResolve = getConfsToResolve(getOrganisation(),
119: getModule() + "-caller", conf, true);
120: //When we make an inline resolution, we can not resolve private confs.
121: for (int i = 0; i < toResolve.length; i++) {
122: if ("*".equals(toResolve[i])) {
123: toResolve[i] = "*(public)";
124: }
125: }
126: if (toResolve.length > 0) {
127: Message.verbose("using inline mode to resolve "
128: + getOrganisation() + " " + getModule() + " "
129: + getRevision() + " ("
130: + StringUtils.join(toResolve, ", ") + ")");
131: IvyResolve resolve = createResolve(isHaltonfailure(),
132: isUseOrigin());
133: resolve.setOrganisation(getOrganisation());
134: resolve.setModule(getModule());
135: resolve.setRevision(getRevision());
136: resolve.setInline(true);
137: resolve.setConf(conf);
138: resolve.setResolveId(resolveId);
139: resolve.execute();
140: } else {
141: Message.verbose("inline resolve already done for "
142: + getOrganisation() + " " + getModule() + " "
143: + getRevision() + " (" + conf + ")");
144: }
145: if ("*".equals(conf)) {
146: conf = StringUtils.join(getResolvedConfigurations(
147: getOrganisation(), getModule() + "-caller",
148: true), ", ");
149: }
150: } else {
151: Message.debug("using standard ensure resolved");
152:
153: // if the organization and module has been manually specified, we'll reuse the resolved
154: // data from another build (there is no way to know which configurations were resolved
155: // there (TODO: maybe we can check which reports exist and extract the configurations
156: // from these report names?)
157: if (!orgAndModSetManually) {
158: ensureResolved(settings);
159: }
160:
161: conf = getProperty(conf, settings,
162: "ivy.resolved.configurations");
163: if ("*".equals(conf)) {
164: conf = getProperty(settings,
165: "ivy.resolved.configurations");
166: if (conf == null) {
167: throw new BuildException(
168: "bad conf provided for ivy cache task: "
169: + "'*' can only be used with a prior call to <resolve/>");
170: }
171: }
172: }
173: organisation = getProperty(organisation, settings,
174: "ivy.organisation");
175: module = getProperty(module, settings, "ivy.module");
176: if (organisation == null) {
177: throw new BuildException(
178: "no organisation provided for ivy cache task: "
179: + "It can either be set explicitely via the attribute 'organisation' "
180: + "or via 'ivy.organisation' property or a prior call to <resolve/>");
181: }
182: if (module == null) {
183: throw new BuildException(
184: "no module name provided for ivy cache task: "
185: + "It can either be set explicitely via the attribute 'module' "
186: + "or via 'ivy.module' property or a prior call to <resolve/>");
187: }
188: if (conf == null) {
189: throw new BuildException(
190: "no conf provided for ivy cache task: "
191: + "It can either be set explicitely via the attribute 'conf' or "
192: + "via 'ivy.resolved.configurations' property or a prior call to <resolve/>");
193: }
194:
195: artifactFilter = FilterHelper.getArtifactTypeFilter(type);
196: }
197:
198: protected void ensureResolved(IvySettings settings) {
199: String requestedConfigs = getProperty(getConf(), settings,
200: "ivy.resolved.configurations");
201:
202: String[] confs = null;
203: if (getResolveId() != null) {
204: confs = getConfsToResolve(getResolveId(), requestedConfigs);
205: } else {
206: confs = getConfsToResolve(getOrganisation(), getModule(),
207: requestedConfigs, false);
208: }
209:
210: if (confs.length > 0) {
211: IvyResolve resolve = createResolve(isHaltonfailure(),
212: isUseOrigin());
213: resolve.setFile(getFile());
214: resolve.setTransitive(isTransitive());
215: resolve.setConf(StringUtils.join(confs, ", "));
216: resolve.setResolveId(getResolveId());
217: resolve.execute();
218: }
219: }
220:
221: protected String[] getConfsToResolve(String org, String module,
222: String conf, boolean strict) {
223: ModuleDescriptor reference = (ModuleDescriptor) getResolvedDescriptor(
224: org, module, strict);
225: String[] rconfs = getResolvedConfigurations(org, module, strict);
226: return getConfsToResolve(reference, conf, rconfs);
227: }
228:
229: protected String[] getConfsToResolve(String resolveId, String conf) {
230: ModuleDescriptor reference = (ModuleDescriptor) getResolvedDescriptor(
231: resolveId, false);
232: if (reference == null) {
233: // assume the module has been resolved outside this build, resolve the required
234: // configurations again
235: // TODO: find a way to discover which confs were resolved by that previous resolve
236: if (conf == null) {
237: return new String[] { "*" };
238: } else {
239: return splitConfs(conf);
240: }
241: }
242: String[] rconfs = (String[]) getProject().getReference(
243: "ivy.resolved.configurations.ref." + resolveId);
244: return getConfsToResolve(reference, conf, rconfs);
245: }
246:
247: private String[] getConfsToResolve(ModuleDescriptor reference,
248: String conf, String[] rconfs) {
249: Message.debug("calculating configurations to resolve");
250:
251: if (reference == null) {
252: Message
253: .debug("module not yet resolved, all confs still need to be resolved");
254: if (conf == null) {
255: return new String[] { "*" };
256: } else {
257: return splitConfs(conf);
258: }
259: } else if (conf != null) {
260: String[] confs;
261: if ("*".equals(conf)) {
262: confs = reference.getConfigurationsNames();
263: } else {
264: confs = splitConfs(conf);
265: }
266: HashSet rconfsSet = new HashSet(Arrays.asList(rconfs));
267: HashSet confsSet = new HashSet(Arrays.asList(confs));
268: Message.debug("resolved configurations: " + rconfsSet);
269: Message.debug("asked configurations: " + confsSet);
270: confsSet.removeAll(rconfsSet);
271: Message.debug("to resolve configurations: " + confsSet);
272: return (String[]) confsSet.toArray(new String[confsSet
273: .size()]);
274: } else {
275: Message
276: .debug("module already resolved, no configuration to resolve");
277: return new String[0];
278: }
279:
280: }
281:
282: protected IvyResolve createResolve(boolean haltOnFailure,
283: boolean useOrigin) {
284: Message
285: .verbose("no resolved descriptor found: launching default resolve");
286: IvyResolve resolve = new IvyResolve();
287: resolve.setTaskName(getTaskName());
288: resolve.setProject(getProject());
289: resolve.setHaltonfailure(haltOnFailure);
290: resolve.setUseOrigin(useOrigin);
291: resolve.setValidate(isValidate());
292: resolve.setKeep(isKeep());
293: resolve.setLog(getLog());
294: return resolve;
295: }
296:
297: protected ModuleRevisionId getResolvedMrid() {
298: return new ModuleRevisionId(getResolvedModuleId(),
299: getRevision() == null ? Ivy.getWorkingRevision()
300: : getRevision());
301: }
302:
303: protected ModuleId getResolvedModuleId() {
304: return isInline() ? new ModuleId(getOrganisation(), getModule()
305: + "-caller") : new ModuleId(getOrganisation(),
306: getModule());
307: }
308:
309: protected ResolveReport getResolvedReport() {
310: return getResolvedReport(getOrganisation(),
311: isInline() ? getModule() + "-caller" : getModule(),
312: resolveId);
313: }
314:
315: public String getType() {
316: return type;
317: }
318:
319: public void setType(String type) {
320: this .type = type;
321: }
322:
323: public String getConf() {
324: return conf;
325: }
326:
327: public void setConf(String conf) {
328: this .conf = conf;
329: }
330:
331: public String getModule() {
332: return module;
333: }
334:
335: public void setModule(String module) {
336: this .module = module;
337: }
338:
339: public String getOrganisation() {
340: return organisation;
341: }
342:
343: public void setOrganisation(String organisation) {
344: this .organisation = organisation;
345: }
346:
347: public boolean isHaltonfailure() {
348: return haltOnFailure;
349: }
350:
351: public void setHaltonfailure(boolean haltOnFailure) {
352: this .haltOnFailure = haltOnFailure;
353: }
354:
355: public void setCache(File cache) {
356: cacheAttributeNotSupported();
357: }
358:
359: public String getRevision() {
360: return revision;
361: }
362:
363: public void setRevision(String rev) {
364: revision = rev;
365: }
366:
367: public Filter getArtifactFilter() {
368: return artifactFilter;
369: }
370:
371: public boolean isTransitive() {
372: return transitive;
373: }
374:
375: public void setTransitive(boolean transitive) {
376: this .transitive = transitive;
377: }
378:
379: public boolean isInline() {
380: return inline;
381: }
382:
383: public void setInline(boolean inline) {
384: this .inline = inline;
385: }
386:
387: public void setResolveId(String resolveId) {
388: this .resolveId = resolveId;
389: }
390:
391: public String getResolveId() {
392: return resolveId;
393: }
394:
395: public void setFile(File file) {
396: this .file = file;
397: }
398:
399: public File getFile() {
400: return file;
401: }
402:
403: public void setKeep(boolean keep) {
404: this .keep = Boolean.valueOf(keep);
405: }
406:
407: public boolean isKeep() {
408: return this.keep == null ? !isInline() : this.keep
409: .booleanValue();
410: }
411:
412: }
|