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.plugins.parser.m2;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.net.URL;
024: import java.text.ParseException;
025: import java.util.Date;
026: import java.util.Iterator;
027: import java.util.Map;
028:
029: import org.apache.ivy.core.IvyContext;
030: import org.apache.ivy.core.module.descriptor.Artifact;
031: import org.apache.ivy.core.module.descriptor.DefaultArtifact;
032: import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor;
033: import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
034: import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
035: import org.apache.ivy.core.module.id.ModuleRevisionId;
036: import org.apache.ivy.core.resolve.ResolveData;
037: import org.apache.ivy.core.resolve.ResolveEngine;
038: import org.apache.ivy.core.resolve.ResolveOptions;
039: import org.apache.ivy.core.resolve.ResolvedModuleRevision;
040: import org.apache.ivy.plugins.parser.ModuleDescriptorParser;
041: import org.apache.ivy.plugins.parser.ParserSettings;
042: import org.apache.ivy.plugins.parser.xml.XmlModuleDescriptorWriter;
043: import org.apache.ivy.plugins.repository.Resource;
044: import org.apache.ivy.plugins.repository.url.URLResource;
045: import org.apache.ivy.plugins.resolver.DependencyResolver;
046: import org.apache.ivy.util.Message;
047: import org.xml.sax.SAXException;
048:
049: /**
050: * A parser for Maven 2 POM.
051: * <p>
052: * The configurations used in the generated module descriptor mimics the behavior defined by maven 2
053: * scopes, as documented here:<br/>
054: * http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
055: * The PomModuleDescriptorParser use a PomDomReader to read the pom, and the
056: * PomModuleDescriptorBuilder to write the ivy module descriptor using the info read by the
057: * PomDomReader.
058: */
059: public final class PomModuleDescriptorParser implements
060: ModuleDescriptorParser {
061:
062: private static final PomModuleDescriptorParser INSTANCE = new PomModuleDescriptorParser();
063:
064: public static PomModuleDescriptorParser getInstance() {
065: return INSTANCE;
066: }
067:
068: private PomModuleDescriptorParser() {
069: }
070:
071: public void toIvyFile(InputStream is, Resource res, File destFile,
072: ModuleDescriptor md) throws ParseException, IOException {
073: try {
074: XmlModuleDescriptorWriter.write(md, destFile);
075: } finally {
076: if (is != null) {
077: is.close();
078: }
079: }
080: }
081:
082: public boolean accept(Resource res) {
083: return res.getName().endsWith(".pom")
084: || res.getName().endsWith("pom.xml")
085: || res.getName().endsWith("project.xml");
086: }
087:
088: public String toString() {
089: return "pom parser";
090: }
091:
092: public Artifact getMetadataArtifact(ModuleRevisionId mrid,
093: Resource res) {
094: return DefaultArtifact.newPomArtifact(mrid, new Date(res
095: .getLastModified()));
096: }
097:
098: public String getType() {
099: return "pom";
100: }
101:
102: public ModuleDescriptor parseDescriptor(ParserSettings ivySettings,
103: URL descriptorURL, boolean validate) throws ParseException,
104: IOException {
105: URLResource resource = new URLResource(descriptorURL);
106: return parseDescriptor(ivySettings, descriptorURL, resource,
107: validate);
108: }
109:
110: public ModuleDescriptor parseDescriptor(ParserSettings ivySettings,
111: URL descriptorURL, Resource res, boolean validate)
112: throws ParseException, IOException {
113:
114: PomModuleDescriptorBuilder mdBuilder = new PomModuleDescriptorBuilder(
115: this , res);
116:
117: try {
118: PomReader domReader = new PomReader(descriptorURL, res);
119:
120: domReader.setProperty("parent.version", domReader
121: .getParentVersion());
122:
123: String groupId = domReader.getGroupId();
124: String artifactId = domReader.getArtifactId();
125: String version = domReader.getVersion();
126: mdBuilder.setModuleRevId(groupId, artifactId, version);
127:
128: ModuleRevisionId relocation = domReader.getRelocation();
129:
130: if (relocation != null) {
131: if (groupId != null && artifactId != null
132: && artifactId.equals(relocation.getName())
133: && groupId.equals(relocation.getOrganisation())) {
134: Message
135: .error("Relocation to an other version number not supported in ivy : "
136: + mdBuilder.getModuleDescriptor()
137: .getModuleRevisionId()
138: + " relocated to "
139: + relocation
140: + ". Please update your dependency to directly use the right version.");
141: Message
142: .warn("Resolution will only pick dependencies of the relocated element."
143: + " Artefact and other metadata will be ignored.");
144: ResolvedModuleRevision relocatedModule = parseOtherPom(
145: ivySettings, relocation);
146: DependencyDescriptor[] dds = relocatedModule
147: .getDescriptor().getDependencies();
148: for (int i = 0; i < dds.length; i++) {
149: mdBuilder.addDependency(dds[i]);
150: }
151: } else {
152: Message.info(mdBuilder.getModuleDescriptor()
153: .getModuleRevisionId()
154: + " is relocated to "
155: + relocation
156: + ". Please update your dependencies.");
157: Message
158: .verbose("Relocated module will be considered as a dependency");
159: DefaultDependencyDescriptor dd = new DefaultDependencyDescriptor(
160: mdBuilder.getModuleDescriptor(),
161: relocation, true, false, true);
162: /* Map all public dependencies */
163: dd.addDependencyConfiguration("compile", "compile");
164: dd.addDependencyConfiguration("runtime", "runtime");
165: dd.addDependencyConfiguration("default", "default");
166: dd.addDependencyConfiguration("master", "master");
167: dd.addDependencyConfiguration("provided",
168: "provided");
169: dd.addDependencyConfiguration("system", "system");
170: mdBuilder.addDependency(dd);
171: }
172: } else {
173: domReader.setProperty("project.groupId", groupId);
174: domReader.setProperty("pom.groupId", groupId);
175: domReader.setProperty("project.artifactId", artifactId);
176: domReader.setProperty("pom.artifactId", artifactId);
177: domReader.setProperty("project.version", version);
178: domReader.setProperty("pom.version", version);
179: domReader.setProperty("version", version);
180:
181: ModuleDescriptor parentDescr = null;
182: if (domReader.hasParent()) {
183: domReader.setProperty("parent.version", domReader
184: .getParentVersion());
185: //Is there any other parent properties?
186:
187: ModuleRevisionId parentModRevID = ModuleRevisionId
188: .newInstance(domReader.getParentGroupId(),
189: domReader.getParentArtifactId(),
190: domReader.getParentVersion());
191: ResolvedModuleRevision parentModule = parseOtherPom(
192: ivySettings, parentModRevID);
193: parentDescr = parentModule.getDescriptor();
194: }
195:
196: Map pomProperties = domReader.getPomProperties();
197: for (Iterator iter = pomProperties.entrySet()
198: .iterator(); iter.hasNext();) {
199: Map.Entry prop = (Map.Entry) iter.next();
200: domReader.setProperty((String) prop.getKey(),
201: (String) prop.getValue());
202: mdBuilder.addProperty((String) prop.getKey(),
203: (String) prop.getValue());
204: }
205:
206: if (parentDescr != null) {
207: Map parentPomProps = mdBuilder
208: .extractPomProperties(parentDescr
209: .getExtraInfo());
210: for (Iterator iter = parentPomProps.entrySet()
211: .iterator(); iter.hasNext();) {
212: Map.Entry prop = (Map.Entry) iter.next();
213: domReader.setProperty((String) prop.getKey(),
214: (String) prop.getValue());
215: }
216: }
217:
218: for (Iterator it = domReader.getDependencyMgt()
219: .iterator(); it.hasNext();) {
220: PomReader.PomDependencyMgt dep = (PomReader.PomDependencyMgt) it
221: .next();
222: mdBuilder.addDependencyMgt(dep);
223: }
224:
225: if (parentDescr != null) {
226: mdBuilder.addExtraInfos(parentDescr.getExtraInfo());
227: }
228:
229: for (Iterator it = domReader.getDependencies()
230: .iterator(); it.hasNext();) {
231: PomReader.PomDependencyData dep = (PomReader.PomDependencyData) it
232: .next();
233: mdBuilder.addDependency(res, dep);
234: }
235:
236: if (parentDescr != null) {
237: for (int i = 0; i < parentDescr.getDependencies().length; i++) {
238: mdBuilder.addDependency(parentDescr
239: .getDependencies()[i]);
240: }
241: }
242:
243: mdBuilder.addArtifact(artifactId, domReader
244: .getPackaging());
245: }
246: } catch (SAXException e) {
247: throw newParserException(e);
248: }
249:
250: return mdBuilder.getModuleDescriptor();
251: }
252:
253: private ResolvedModuleRevision parseOtherPom(
254: ParserSettings ivySettings, ModuleRevisionId parentModRevID)
255: throws ParseException {
256: DependencyDescriptor dd = new DefaultDependencyDescriptor(
257: parentModRevID, true);
258: ResolveData data = IvyContext.getContext().getResolveData();
259: if (data == null) {
260: ResolveEngine engine = IvyContext.getContext().getIvy()
261: .getResolveEngine();
262: ResolveOptions options = new ResolveOptions();
263: options.setDownload(false);
264: data = new ResolveData(engine, options);
265: }
266:
267: DependencyResolver resolver = ivySettings
268: .getResolver(parentModRevID);
269: if (resolver == null) {
270: // TODO: Throw exception here?
271: return null;
272: } else {
273: ResolvedModuleRevision otherModule = resolver
274: .getDependency(dd, data);
275: return otherModule;
276: }
277: }
278:
279: private ParseException newParserException(Exception e) {
280: Message.error(e.getMessage());
281: ParseException pe = new ParseException(e.getMessage(), 0);
282: pe.initCause(e);
283: return pe;
284: }
285:
286: }
|