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.resolver;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.text.ParseException;
024: import java.util.ArrayList;
025: import java.util.Collections;
026: import java.util.Date;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.Map;
030:
031: import javax.xml.parsers.ParserConfigurationException;
032:
033: import org.apache.ivy.core.IvyPatternHelper;
034: import org.apache.ivy.core.module.descriptor.Artifact;
035: import org.apache.ivy.core.module.descriptor.DefaultArtifact;
036: import org.apache.ivy.core.module.descriptor.DependencyDescriptor;
037: import org.apache.ivy.core.module.id.ModuleRevisionId;
038: import org.apache.ivy.core.report.DownloadReport;
039: import org.apache.ivy.core.resolve.DownloadOptions;
040: import org.apache.ivy.core.resolve.ResolveData;
041: import org.apache.ivy.core.resolve.ResolvedModuleRevision;
042: import org.apache.ivy.core.search.ModuleEntry;
043: import org.apache.ivy.core.search.OrganisationEntry;
044: import org.apache.ivy.core.search.RevisionEntry;
045: import org.apache.ivy.plugins.repository.Repository;
046: import org.apache.ivy.plugins.repository.Resource;
047: import org.apache.ivy.plugins.resolver.util.ResolvedResource;
048: import org.apache.ivy.util.ContextualSAXHandler;
049: import org.apache.ivy.util.Message;
050: import org.apache.ivy.util.XMLHelper;
051: import org.xml.sax.SAXException;
052:
053: /**
054: * IBiblioResolver is a resolver which can be used to resolve dependencies found in the ibiblio
055: * maven repository, or similar repositories.
056: * <p>
057: * For more flexibility with url and patterns, see
058: * {@link org.apache.ivy.plugins.resolver.URLResolver}.
059: */
060: public class IBiblioResolver extends URLResolver {
061: private static final String M2_PATTERN = "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]";
062:
063: public static final String DEFAULT_PATTERN = "[module]/[type]s/[artifact]-[revision].[ext]";
064:
065: public static final String DEFAULT_ROOT = "http://www.ibiblio.org/maven/";
066:
067: private String root = null;
068:
069: private String pattern = null;
070:
071: // use poms if m2 compatible is true
072: private boolean usepoms = true;
073:
074: // use maven-metadata.xml is exists to list revisions
075: private boolean useMavenMetadata = true;
076:
077: public IBiblioResolver() {
078: }
079:
080: public ResolvedResource findIvyFileRef(DependencyDescriptor dd,
081: ResolveData data) {
082: if (isM2compatible() && isUsepoms()) {
083: ModuleRevisionId mrid = dd.getDependencyRevisionId();
084: mrid = convertM2IdForResourceSearch(mrid);
085: ResolvedResource rres = findResourceUsingPatterns(mrid,
086: getIvyPatterns(), DefaultArtifact.newPomArtifact(
087: mrid, data.getDate()), getRMDParser(dd,
088: data), data.getDate());
089: return rres;
090: } else {
091: return null;
092: }
093: }
094:
095: public void setM2compatible(boolean m2compatible) {
096: super .setM2compatible(m2compatible);
097: if (m2compatible) {
098: if (root == null) {
099: root = "http://repo1.maven.org/maven2/";
100: }
101: if (pattern == null) {
102: pattern = M2_PATTERN;
103: }
104: updateWholePattern();
105: }
106: }
107:
108: public void ensureConfigured(ResolverSettings settings) {
109: if (settings != null && (root == null || pattern == null)) {
110: if (root == null) {
111: String root = settings
112: .getVariable("ivy.ibiblio.default.artifact.root");
113: if (root != null) {
114: this .root = root;
115: } else {
116: settings.configureRepositories(true);
117: this .root = settings
118: .getVariable("ivy.ibiblio.default.artifact.root");
119: }
120: }
121: if (pattern == null) {
122: String pattern = settings
123: .getVariable("ivy.ibiblio.default.artifact.pattern");
124: if (pattern != null) {
125: this .pattern = pattern;
126: } else {
127: settings.configureRepositories(false);
128: this .pattern = settings
129: .getVariable("ivy.ibiblio.default.artifact.pattern");
130: }
131: }
132: updateWholePattern();
133: }
134: }
135:
136: private String getWholePattern() {
137: return root + pattern;
138: }
139:
140: public String getPattern() {
141: return pattern;
142: }
143:
144: public void setPattern(String pattern) {
145: if (pattern == null) {
146: throw new NullPointerException("pattern must not be null");
147: }
148: this .pattern = pattern;
149: ensureConfigured(getSettings());
150: updateWholePattern();
151: }
152:
153: public String getRoot() {
154: return root;
155: }
156:
157: /**
158: * Sets the root of the maven like repository. The maven like repository is necessarily an http
159: * repository.
160: *
161: * @param root
162: * the root of the maven like repository
163: * @throws IllegalArgumentException
164: * if root does not start with "http://"
165: */
166: public void setRoot(String root) {
167: if (root == null) {
168: throw new NullPointerException("root must not be null");
169: }
170: if (!root.endsWith("/")) {
171: this .root = root + "/";
172: } else {
173: this .root = root;
174: }
175: ensureConfigured(getSettings());
176: updateWholePattern();
177: }
178:
179: private void updateWholePattern() {
180: if (isM2compatible() && isUsepoms()) {
181: setIvyPatterns(Collections.singletonList(getWholePattern()));
182: }
183: setArtifactPatterns(Collections
184: .singletonList(getWholePattern()));
185: }
186:
187: public void publish(Artifact artifact, File src) {
188: throw new UnsupportedOperationException(
189: "publish not supported by IBiblioResolver");
190: }
191:
192: // we do not allow to list organisations on ibiblio, nor modules in ibiblio 1
193: public String[] listTokenValues(String token, Map otherTokenValues) {
194: if (IvyPatternHelper.ORGANISATION_KEY.equals(token)) {
195: return new String[0];
196: }
197: if (IvyPatternHelper.MODULE_KEY.equals(token)
198: && !isM2compatible()) {
199: return new String[0];
200: }
201: ensureConfigured(getSettings());
202: return super .listTokenValues(token, otherTokenValues);
203: }
204:
205: public OrganisationEntry[] listOrganisations() {
206: return new OrganisationEntry[0];
207: }
208:
209: public ModuleEntry[] listModules(OrganisationEntry org) {
210: if (isM2compatible()) {
211: ensureConfigured(getSettings());
212: return super .listModules(org);
213: }
214: return new ModuleEntry[0];
215: }
216:
217: public RevisionEntry[] listRevisions(ModuleEntry mod) {
218: ensureConfigured(getSettings());
219: return super .listRevisions(mod);
220: }
221:
222: protected ResolvedResource[] listResources(Repository repository,
223: ModuleRevisionId mrid, String pattern, Artifact artifact) {
224: if (isUseMavenMetadata() && isM2compatible()
225: && pattern.endsWith(M2_PATTERN)) {
226: // use maven-metadata.xml if it exists
227: InputStream metadataStream = null;
228: try {
229: String metadataLocation = IvyPatternHelper
230: .substitute(
231: root
232: + "[organisation]/[module]/maven-metadata.xml",
233: mrid);
234: Resource metadata = repository
235: .getResource(metadataLocation);
236: if (metadata.exists()) {
237: Message
238: .verbose("\tlisting revisions from maven-metadata: "
239: + metadata);
240: final List revs = new ArrayList();
241: metadataStream = metadata.openStream();
242: XMLHelper.parse(metadataStream, null,
243: new ContextualSAXHandler() {
244: public void endElement(String uri,
245: String localName, String qName)
246: throws SAXException {
247: if ("metadata/versioning/versions/version"
248: .equals(getContext())) {
249: revs.add(getText().trim());
250: }
251: super .endElement(uri, localName,
252: qName);
253: }
254: }, null);
255: Message.debug("\tfound revs: " + revs);
256: List rres = new ArrayList();
257: for (Iterator iter = revs.iterator(); iter
258: .hasNext();) {
259: String rev = (String) iter.next();
260: String resolvedPattern = IvyPatternHelper
261: .substitute(pattern, ModuleRevisionId
262: .newInstance(mrid, rev),
263: artifact);
264: try {
265: Resource res = repository
266: .getResource(resolvedPattern);
267: if ((res != null) && res.exists()) {
268: rres
269: .add(new ResolvedResource(res,
270: rev));
271: }
272: } catch (IOException e) {
273: Message
274: .warn("impossible to get resource from name listed by maven-metadata.xml:"
275: + rres
276: + ": "
277: + e.getMessage());
278: }
279: }
280: return (ResolvedResource[]) rres
281: .toArray(new ResolvedResource[rres.size()]);
282: } else {
283: Message.verbose("\tmaven-metadata not available: "
284: + metadata);
285: }
286: } catch (IOException e) {
287: Message
288: .verbose("impossible to access maven metadata file, ignored: "
289: + e.getMessage());
290: } catch (SAXException e) {
291: Message
292: .verbose("impossible to parse maven metadata file, ignored: "
293: + e.getMessage());
294: } catch (ParserConfigurationException e) {
295: Message
296: .verbose("impossible to parse maven metadata file, ignored: "
297: + e.getMessage());
298: } finally {
299: if (metadataStream != null) {
300: try {
301: metadataStream.close();
302: } catch (IOException e) {
303: // ignored
304: }
305: }
306: }
307: // maven metadata not available or something went wrong, use default listing capability
308: return super .listResources(repository, mrid, pattern,
309: artifact);
310: } else {
311: return super .listResources(repository, mrid, pattern,
312: artifact);
313: }
314: }
315:
316: public String getTypeName() {
317: return "ibiblio";
318: }
319:
320: // override some methods to ensure configuration
321: public ResolvedModuleRevision getDependency(
322: DependencyDescriptor dd, ResolveData data)
323: throws ParseException {
324: ensureConfigured(data.getSettings());
325: return super .getDependency(dd, data);
326: }
327:
328: protected ResolvedResource findArtifactRef(Artifact artifact,
329: Date date) {
330: ensureConfigured(getSettings());
331: return super .findArtifactRef(artifact, date);
332: }
333:
334: public DownloadReport download(Artifact[] artifacts,
335: DownloadOptions options) {
336: ensureConfigured(getSettings());
337: return super .download(artifacts, options);
338: }
339:
340: public boolean exists(Artifact artifact) {
341: ensureConfigured(getSettings());
342: return super .exists(artifact);
343: }
344:
345: public List getArtifactPatterns() {
346: ensureConfigured(getSettings());
347: return super .getArtifactPatterns();
348: }
349:
350: public boolean isUsepoms() {
351: return usepoms;
352: }
353:
354: public void setUsepoms(boolean usepoms) {
355: this .usepoms = usepoms;
356: updateWholePattern();
357: }
358:
359: public boolean isUseMavenMetadata() {
360: return useMavenMetadata;
361: }
362:
363: public void setUseMavenMetadata(boolean useMavenMetadata) {
364: this .useMavenMetadata = useMavenMetadata;
365: }
366:
367: public void dumpSettings() {
368: ensureConfigured(getSettings());
369: super .dumpSettings();
370: Message.debug("\t\troot: " + getRoot());
371: Message.debug("\t\tpattern: " + getPattern());
372: Message.debug("\t\tusepoms: " + usepoms);
373: Message.debug("\t\tuseMavenMetadata: " + useMavenMetadata);
374: }
375: }
|