| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.ivy.core.deliver; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.text.ParseException; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import org.apache.ivy.core.IvyPatternHelper; |
| import org.apache.ivy.core.cache.ResolutionCacheManager; |
| import org.apache.ivy.core.module.descriptor.DependencyDescriptor; |
| import org.apache.ivy.core.module.descriptor.ModuleDescriptor; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.plugins.parser.xml.UpdateOptions; |
| import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorUpdater; |
| import org.apache.ivy.plugins.report.XmlReportParser; |
| import org.apache.ivy.plugins.repository.Resource; |
| import org.apache.ivy.util.ConfigurationUtils; |
| import org.apache.ivy.util.Message; |
| import org.xml.sax.SAXException; |
| |
| public class DeliverEngine { |
| private DeliverEngineSettings settings; |
| |
| public DeliverEngine(DeliverEngineSettings settings) { |
| this.settings = settings; |
| } |
| |
| /** |
| * Delivers a resolved ivy file based upon last resolve call status. If resolve report file |
| * cannot be found in cache, then it throws an IllegalStateException (maybe resolve has not been |
| * called before ?). |
| * |
| * @param revision |
| * the revision to which the module should be delivered |
| * @param destIvyPattern |
| * the pattern to which the delivered ivy file should be written |
| * @param options |
| * the options with which deliver should be done |
| * @throws IOException if something goes wrong |
| * @throws ParseException if something goes wrong |
| */ |
| public void deliver(String revision, String destIvyPattern, DeliverOptions options) |
| throws IOException, ParseException { |
| String resolveId = options.getResolveId(); |
| if (resolveId == null) { |
| throw new IllegalArgumentException("A resolveId must be specified for delivering."); |
| } |
| File[] files = getCache().getConfigurationResolveReportsInCache(resolveId); |
| if (files.length == 0) { |
| throw new IllegalStateException("No previous resolve found for id '" + resolveId |
| + "' Please resolve dependencies before delivering."); |
| } |
| XmlReportParser parser = new XmlReportParser(); |
| parser.parse(files[0]); |
| ModuleRevisionId mrid = parser.getResolvedModule(); |
| deliver(mrid, revision, destIvyPattern, options); |
| } |
| |
| private ResolutionCacheManager getCache() { |
| return settings.getResolutionCacheManager(); |
| } |
| |
| /** |
| * Delivers a resolved ivy file based upon last resolve call status. If resolve report file |
| * cannot be found in cache, then it throws an IllegalStateException (maybe resolve has not been |
| * called before ?). |
| * |
| * @param mrid |
| * the module revision id of the module to deliver |
| * @param revision |
| * the revision to which the module should be delivered |
| * @param destIvyPattern |
| * the pattern to which the delivered ivy file should be written |
| * @param options |
| * the options with which deliver should be done |
| * @throws IOException if something goes wrong |
| * @throws ParseException if something goes wrong |
| */ |
| public void deliver(ModuleRevisionId mrid, String revision, String destIvyPattern, |
| DeliverOptions options) throws IOException, ParseException { |
| Message.info(":: delivering :: " + mrid + " :: " + revision + " :: " + options.getStatus() |
| + " :: " + options.getPubdate()); |
| Message.verbose("\toptions = " + options); |
| long start = System.currentTimeMillis(); |
| destIvyPattern = settings.substitute(destIvyPattern); |
| |
| // 1) find the resolved module descriptor in cache |
| ModuleDescriptor md = getCache().getResolvedModuleDescriptor(mrid); |
| md.setResolvedModuleRevisionId(ModuleRevisionId.newInstance(md.getModuleRevisionId(), |
| options.getPubBranch() == null ? mrid.getBranch() : options.getPubBranch(), revision)); |
| md.setResolvedPublicationDate(options.getPubdate()); |
| |
| // 2) parse resolvedRevisions From properties file |
| Map<ModuleRevisionId, String> resolvedRevisions = new HashMap<>(); // Map (ModuleId -> String revision) |
| Map<ModuleRevisionId, String> resolvedBranches = new HashMap<>(); // Map (ModuleId -> String branch) |
| Map<ModuleRevisionId, String> dependenciesStatus = new HashMap<>(); // Map (ModuleId -> String status) |
| File ivyProperties = getCache().getResolvedIvyPropertiesInCache(mrid); |
| if (!ivyProperties.exists()) { |
| throw new IllegalStateException("ivy properties not found in cache for " + mrid |
| + "; please resolve dependencies before delivering!"); |
| } |
| Properties props = new Properties(); |
| FileInputStream in = new FileInputStream(ivyProperties); |
| props.load(in); |
| in.close(); |
| |
| for (Object o : props.keySet()) { |
| String depMridStr = (String) o; |
| String[] parts = props.getProperty(depMridStr).split(" "); |
| ModuleRevisionId decodedMrid = ModuleRevisionId.decode(depMridStr); |
| if (options.isResolveDynamicRevisions()) { |
| resolvedRevisions.put(decodedMrid, parts[0]); |
| if (parts.length >= 4) { |
| if (parts[3] != null && !"null".equals(parts[3])) { |
| resolvedBranches.put(decodedMrid, parts[3]); |
| } |
| } |
| } |
| dependenciesStatus.put(decodedMrid, parts[1]); |
| |
| if (options.isReplaceForcedRevisions()) { |
| if (parts.length <= 2) { |
| // maybe the properties file was generated by an older Ivy version |
| // so it is possible that this part doesn't exist. |
| throw new IllegalStateException("ivy properties file generated by an older" |
| + " version of Ivy which doesn't support replacing forced revisions!"); |
| } |
| |
| resolvedRevisions.put(decodedMrid, parts[2]); |
| } |
| } |
| |
| // 3) use pdrResolver to resolve dependencies info |
| Map<ModuleRevisionId, String> resolvedDependencies = new HashMap<>(); |
| // Map (ModuleRevisionId -> String revision) |
| for (DependencyDescriptor dependency : md.getDependencies()) { |
| String rev = resolvedRevisions.get(dependency.getDependencyRevisionId()); |
| if (rev == null) { |
| rev = dependency.getDependencyRevisionId().getRevision(); |
| } |
| String bra = resolvedBranches.get(dependency.getDependencyRevisionId()); |
| if (bra == null || "null".equals(bra)) { |
| bra = dependency.getDependencyRevisionId().getBranch(); |
| } |
| String depStatus = dependenciesStatus.get(dependency.getDependencyRevisionId()); |
| ModuleRevisionId mrid2 = (bra == null) |
| ? ModuleRevisionId.newInstance(dependency.getDependencyRevisionId(), rev) |
| : ModuleRevisionId.newInstance(dependency.getDependencyRevisionId(), bra, rev); |
| resolvedDependencies.put(dependency.getDependencyRevisionId(), |
| options.getPdrResolver().resolve(md, options.getStatus(), mrid2, depStatus)); |
| } |
| |
| // 4) copy the source resolved ivy to the destination specified, |
| // updating status, revision and dependency revisions obtained by |
| // PublishingDependencyRevisionResolver |
| File publishedIvy = settings.resolveFile(IvyPatternHelper.substitute(destIvyPattern, |
| md.getResolvedModuleRevisionId())); |
| Message.info("\tdelivering ivy file to " + publishedIvy); |
| |
| String[] confs = ConfigurationUtils.replaceWildcards(options.getConfs(), md); |
| Set<String> confsToRemove = new HashSet<>(Arrays.asList(md.getConfigurationsNames())); |
| confsToRemove.removeAll(Arrays.asList(confs)); |
| |
| try { |
| UpdateOptions opts = new UpdateOptions() |
| .setSettings(settings) |
| .setResolvedRevisions(resolvedDependencies) |
| .setStatus(options.getStatus()) |
| .setRevision(revision) |
| .setBranch(options.getPubBranch()) |
| .setPubdate(options.getPubdate()) |
| .setGenerateRevConstraint(options.isGenerateRevConstraint()) |
| .setMerge(options.isMerge()) |
| .setMergedDescriptor(md) |
| .setConfsToExclude( |
| confsToRemove.toArray(new String[confsToRemove.size()])); |
| if (!resolvedBranches.isEmpty()) { |
| opts = opts.setResolvedBranches(resolvedBranches); |
| } |
| Resource res = md.getResource(); |
| XmlModuleDescriptorUpdater.update(res.openStream(), res, publishedIvy, opts); |
| } catch (SAXException ex) { |
| throw new RuntimeException("bad ivy file in cache for " + mrid, ex); |
| } |
| |
| Message.verbose("\tdeliver done (" + (System.currentTimeMillis() - start) + "ms)"); |
| } |
| } |