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.core.deliver;
019:
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.IOException;
023: import java.net.MalformedURLException;
024: import java.net.URL;
025: import java.text.ParseException;
026: import java.util.Arrays;
027: import java.util.HashMap;
028: import java.util.HashSet;
029: import java.util.Iterator;
030: import java.util.Map;
031: import java.util.Properties;
032: import java.util.Set;
033:
034: import org.apache.ivy.core.IvyPatternHelper;
035: import org.apache.ivy.core.cache.ResolutionCacheManager;
036: import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
037: import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
038: import org.apache.ivy.core.module.id.ModuleRevisionId;
039: import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorParser;
040: import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorUpdater;
041: import org.apache.ivy.plugins.report.XmlReportParser;
042: import org.apache.ivy.util.ConfigurationUtils;
043: import org.apache.ivy.util.Message;
044: import org.xml.sax.SAXException;
045:
046: public class DeliverEngine {
047: private DeliverEngineSettings settings;
048:
049: public DeliverEngine(DeliverEngineSettings settings) {
050: this .settings = settings;
051: }
052:
053: /**
054: * Delivers a resolved ivy file based upon last resolve call status. If resolve report file
055: * cannot be found in cache, then it throws an IllegalStateException (maybe resolve has not been
056: * called before ?).
057: *
058: * @param revision
059: * the revision to which the module should be delivered
060: * @param destIvyPattern
061: * the pattern to which the delivered ivy file should be written
062: * @param options
063: * the options with which deliver should be done
064: */
065: public void deliver(String revision, String destIvyPattern,
066: DeliverOptions options) throws IOException, ParseException {
067: String resolveId = options.getResolveId();
068: if (resolveId == null) {
069: throw new IllegalArgumentException(
070: "A resolveId must be specified for delivering.");
071: }
072: File[] files = getCache()
073: .getConfigurationResolveReportsInCache(resolveId);
074: if (files.length == 0) {
075: throw new IllegalStateException(
076: "No previous resolve found for id '"
077: + resolveId
078: + "' Please resolve dependencies before delivering.");
079: }
080: XmlReportParser parser = new XmlReportParser();
081: parser.parse(files[0]);
082: ModuleRevisionId mrid = parser.getResolvedModule();
083: deliver(mrid, revision, destIvyPattern, options);
084: }
085:
086: private ResolutionCacheManager getCache() {
087: return settings.getResolutionCacheManager();
088: }
089:
090: /**
091: * Delivers a resolved ivy file based upon last resolve call status. If resolve report file
092: * cannot be found in cache, then it throws an IllegalStateException (maybe resolve has not been
093: * called before ?).
094: *
095: * @param mrid
096: * the module revision id of the module to deliver
097: * @param revision
098: * the revision to which the module should be delivered
099: * @param destIvyPattern
100: * the pattern to which the delivered ivy file should be written
101: * @param options
102: * the options with which deliver should be done
103: */
104: public void deliver(ModuleRevisionId mrid, String revision,
105: String destIvyPattern, DeliverOptions options)
106: throws IOException, ParseException {
107: Message.info(":: delivering :: " + mrid + " :: " + revision
108: + " :: " + options.getStatus() + " :: "
109: + options.getPubdate());
110: Message.verbose("\toptions = " + options);
111: long start = System.currentTimeMillis();
112: destIvyPattern = settings.substitute(destIvyPattern);
113:
114: // 1) find the resolved module descriptor in cache
115: File ivyFile = getCache().getResolvedIvyFileInCache(mrid);
116: if (!ivyFile.exists()) {
117: throw new IllegalStateException(
118: "ivy file not found in cache for "
119: + mrid
120: + ": please resolve dependencies before delivering ("
121: + ivyFile + ")");
122: }
123: ModuleDescriptor md = null;
124: URL ivyFileURL = null;
125: try {
126: ivyFileURL = ivyFile.toURL();
127: md = XmlModuleDescriptorParser.getInstance()
128: .parseDescriptor(settings, ivyFileURL,
129: options.isValidate());
130: md.setResolvedModuleRevisionId(ModuleRevisionId
131: .newInstance(mrid, revision));
132: md.setResolvedPublicationDate(options.getPubdate());
133: } catch (MalformedURLException e) {
134: throw new RuntimeException(
135: "malformed url obtained for file " + ivyFile, e);
136: } catch (ParseException e) {
137: throw new RuntimeException("bad ivy file in cache for "
138: + mrid + ": please clean and resolve again", e);
139: }
140:
141: // 2) parse resolvedRevisions From properties file
142: Map resolvedRevisions = new HashMap(); // Map (ModuleId -> String revision)
143: Map dependenciesStatus = new HashMap(); // Map (ModuleId -> String status)
144: File ivyProperties = getCache()
145: .getResolvedIvyPropertiesInCache(mrid);
146: if (!ivyProperties.exists()) {
147: throw new IllegalStateException(
148: "ivy properties not found in cache for "
149: + mrid
150: + ": please resolve dependencies before delivering ("
151: + ivyFile + ")");
152: }
153: Properties props = new Properties();
154: FileInputStream in = new FileInputStream(ivyProperties);
155: props.load(in);
156: in.close();
157:
158: for (Iterator iter = props.keySet().iterator(); iter.hasNext();) {
159: String depMridStr = (String) iter.next();
160: String[] parts = props.getProperty(depMridStr).split(" ");
161: ModuleRevisionId decodedMrid = ModuleRevisionId
162: .decode(depMridStr);
163: if (options.isResolveDynamicRevisions()) {
164: resolvedRevisions.put(decodedMrid, parts[0]);
165: }
166: dependenciesStatus.put(decodedMrid, parts[1]);
167: }
168:
169: // 3) use pdrResolver to resolve dependencies info
170: Map resolvedDependencies = new HashMap(); // Map (ModuleRevisionId -> String revision)
171: DependencyDescriptor[] dependencies = md.getDependencies();
172: for (int i = 0; i < dependencies.length; i++) {
173: String rev = (String) resolvedRevisions.get(dependencies[i]
174: .getDependencyRevisionId());
175: if (rev == null) {
176: rev = dependencies[i].getDependencyRevisionId()
177: .getRevision();
178: }
179: String depStatus = (String) dependenciesStatus
180: .get(dependencies[i].getDependencyRevisionId());
181: resolvedDependencies.put(dependencies[i]
182: .getDependencyRevisionId(), options
183: .getPdrResolver().resolve(
184: md,
185: options.getStatus(),
186: ModuleRevisionId.newInstance(
187: dependencies[i]
188: .getDependencyRevisionId(),
189: rev), depStatus));
190: }
191:
192: // 4) copy the source resolved ivy to the destination specified,
193: // updating status, revision and dependency revisions obtained by
194: // PublishingDependencyRevisionResolver
195: String publishedIvy = IvyPatternHelper.substitute(
196: destIvyPattern, md.getResolvedModuleRevisionId());
197: Message.info("\tdelivering ivy file to " + publishedIvy);
198:
199: String[] confs = ConfigurationUtils.replaceWildcards(options
200: .getConfs(), md);
201: Set confsToRemove = new HashSet(Arrays.asList(md
202: .getConfigurationsNames()));
203: confsToRemove.removeAll(Arrays.asList(confs));
204:
205: try {
206: XmlModuleDescriptorUpdater.update(settings, ivyFileURL,
207: new File(publishedIvy), resolvedDependencies,
208: options.getStatus(), revision,
209: options.getPubdate(), null, true,
210: (String[]) confsToRemove
211: .toArray(new String[confsToRemove.size()]));
212: } catch (SAXException ex) {
213: throw new RuntimeException("bad ivy file in cache for "
214: + mrid + ": please clean and resolve again", ex);
215: }
216:
217: Message.verbose("\tdeliver done ("
218: + (System.currentTimeMillis() - start) + "ms)");
219: }
220: }
|