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.util.Map;
023:
024: import org.apache.ivy.core.IvyContext;
025: import org.apache.ivy.core.LogOptions;
026: import org.apache.ivy.core.cache.ArtifactOrigin;
027: import org.apache.ivy.core.cache.CacheDownloadOptions;
028: import org.apache.ivy.core.cache.CacheMetadataOptions;
029: import org.apache.ivy.core.cache.DownloadListener;
030: import org.apache.ivy.core.cache.RepositoryCacheManager;
031: import org.apache.ivy.core.event.EventManager;
032: import org.apache.ivy.core.event.download.EndArtifactDownloadEvent;
033: import org.apache.ivy.core.event.download.NeedArtifactEvent;
034: import org.apache.ivy.core.event.download.StartArtifactDownloadEvent;
035: import org.apache.ivy.core.module.descriptor.Artifact;
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.core.report.ArtifactDownloadReport;
040: import org.apache.ivy.core.report.DownloadReport;
041: import org.apache.ivy.core.report.DownloadStatus;
042: import org.apache.ivy.core.resolve.DownloadOptions;
043: import org.apache.ivy.core.resolve.IvyNode;
044: import org.apache.ivy.core.resolve.ResolveData;
045: import org.apache.ivy.core.resolve.ResolveOptions;
046: import org.apache.ivy.core.resolve.ResolvedModuleRevision;
047: import org.apache.ivy.core.search.ModuleEntry;
048: import org.apache.ivy.core.search.OrganisationEntry;
049: import org.apache.ivy.core.search.RevisionEntry;
050: import org.apache.ivy.plugins.latest.LatestStrategy;
051: import org.apache.ivy.plugins.namespace.NameSpaceHelper;
052: import org.apache.ivy.plugins.namespace.Namespace;
053: import org.apache.ivy.plugins.resolver.util.HasLatestStrategy;
054: import org.apache.ivy.plugins.resolver.util.ResolvedResource;
055: import org.apache.ivy.util.Message;
056:
057: /**
058: * This abstract resolver only provides handling for resolver name
059: */
060: public abstract class AbstractResolver implements DependencyResolver,
061: HasLatestStrategy {
062:
063: /**
064: * True if parsed ivy files should be validated against xsd, false if they should not, null if
065: * default behaviur should be used
066: */
067: private Boolean validate = null;
068:
069: private String name;
070:
071: private ResolverSettings settings;
072:
073: private EventManager eventManager = null; // may remain null
074:
075: /**
076: * The latest strategy to use to find latest among several artifacts
077: */
078: private LatestStrategy latestStrategy;
079:
080: private String latestStrategyName;
081:
082: /**
083: * The namespace to which this resolver belongs
084: */
085: private Namespace namespace;
086:
087: private String namespaceName;
088:
089: private String cacheManagerName;
090:
091: private RepositoryCacheManager repositoryCacheManager;
092:
093: // used to store default values for nested cache
094: private String changingMatcherName;
095:
096: private String changingPattern;
097:
098: private Boolean checkmodified;
099:
100: public ResolverSettings getSettings() {
101: return settings;
102: }
103:
104: public void setSettings(ResolverSettings ivy) {
105: settings = ivy;
106: }
107:
108: public String getName() {
109: return name;
110: }
111:
112: public void setName(String name) {
113: this .name = name;
114: }
115:
116: /**
117: * this method should remove sensitive information from a location to be displayed in a log
118: *
119: * @param name
120: * location
121: * @return location with sensitive data replaced by stars
122: */
123: public String hidePassword(String name) {
124: return name;
125: }
126:
127: protected boolean doValidate(ResolveData data) {
128: if (validate != null) {
129: return validate.booleanValue();
130: } else {
131: return data.isValidate();
132: }
133: }
134:
135: public boolean isValidate() {
136: return validate == null ? true : validate.booleanValue();
137: }
138:
139: public void setValidate(boolean validate) {
140: this .validate = Boolean.valueOf(validate);
141: }
142:
143: protected void checkInterrupted() {
144: IvyContext.getContext().getIvy().checkInterrupted();
145: }
146:
147: public void reportFailure() {
148: Message
149: .verbose("no failure report implemented by "
150: + getName());
151: }
152:
153: public void reportFailure(Artifact art) {
154: Message
155: .verbose("no failure report implemented by "
156: + getName());
157: }
158:
159: public String[] listTokenValues(String token, Map otherTokenValues) {
160: return new String[0];
161: }
162:
163: public OrganisationEntry[] listOrganisations() {
164: return new OrganisationEntry[0];
165: }
166:
167: public ModuleEntry[] listModules(OrganisationEntry org) {
168: return new ModuleEntry[0];
169: }
170:
171: public RevisionEntry[] listRevisions(ModuleEntry module) {
172: return new RevisionEntry[0];
173: }
174:
175: public String toString() {
176: return getName();
177: }
178:
179: public void dumpSettings() {
180: Message.verbose("\t" + getName() + " [" + getTypeName() + "]");
181: Message.debug("\t\tcache: " + cacheManagerName);
182: }
183:
184: public String getTypeName() {
185: return getClass().getName();
186: }
187:
188: /**
189: * Default implementation actually download the artifact Subclasses should overwrite this to
190: * avoid the download
191: */
192: public boolean exists(Artifact artifact) {
193: DownloadReport dr = download(new Artifact[] { artifact },
194: new DownloadOptions());
195: ArtifactDownloadReport adr = dr.getArtifactReport(artifact);
196: return adr.getDownloadStatus() != DownloadStatus.FAILED;
197: }
198:
199: public LatestStrategy getLatestStrategy() {
200: if (latestStrategy == null) {
201: if (getSettings() != null) {
202: if (latestStrategyName != null
203: && !"default".equals(latestStrategyName)) {
204: latestStrategy = getSettings().getLatestStrategy(
205: latestStrategyName);
206: if (latestStrategy == null) {
207: Message.error("unknown latest strategy: "
208: + latestStrategyName);
209: latestStrategy = getSettings()
210: .getDefaultLatestStrategy();
211: }
212: } else {
213: latestStrategy = getSettings()
214: .getDefaultLatestStrategy();
215: Message
216: .debug(getName()
217: + ": no latest strategy defined: using default");
218: }
219: } else {
220: throw new IllegalStateException(
221: "no ivy instance found: "
222: + "impossible to get a latest strategy without ivy instance");
223: }
224: }
225: return latestStrategy;
226: }
227:
228: public void setLatestStrategy(LatestStrategy latestStrategy) {
229: this .latestStrategy = latestStrategy;
230: }
231:
232: public void setLatest(String strategyName) {
233: latestStrategyName = strategyName;
234: }
235:
236: public String getLatest() {
237: if (latestStrategyName == null) {
238: latestStrategyName = "default";
239: }
240: return latestStrategyName;
241: }
242:
243: public Namespace getNamespace() {
244: if (namespace == null) {
245: if (getSettings() != null) {
246: if (namespaceName != null) {
247: namespace = getSettings().getNamespace(
248: namespaceName);
249: if (namespace == null) {
250: Message.error("unknown namespace: "
251: + namespaceName);
252: namespace = getSettings().getSystemNamespace();
253: }
254: } else {
255: namespace = getSettings().getSystemNamespace();
256: Message.debug(getName()
257: + ": no namespace defined: using system");
258: }
259: } else {
260: Message
261: .verbose(getName()
262: + ": no namespace defined nor ivy instance: using system namespace");
263: namespace = Namespace.SYSTEM_NAMESPACE;
264: }
265: }
266: return namespace;
267: }
268:
269: public void setNamespace(String namespaceName) {
270: this .namespaceName = namespaceName;
271: }
272:
273: // Namespace conversion methods
274: protected ModuleDescriptor toSystem(ModuleDescriptor md) {
275: return NameSpaceHelper.toSystem(md, getNamespace());
276: }
277:
278: protected Artifact fromSystem(Artifact artifact) {
279: return NameSpaceHelper.transform(artifact, getNamespace()
280: .getFromSystemTransformer());
281: }
282:
283: protected Artifact toSystem(Artifact artifact) {
284: return NameSpaceHelper.transform(artifact, getNamespace()
285: .getToSystemTransformer());
286: }
287:
288: protected ResolvedModuleRevision toSystem(ResolvedModuleRevision rmr) {
289: return NameSpaceHelper.toSystem(rmr, getNamespace());
290: }
291:
292: protected ModuleRevisionId toSystem(ModuleRevisionId resolvedMrid) {
293: return getNamespace().getToSystemTransformer().transform(
294: resolvedMrid);
295: }
296:
297: protected DependencyDescriptor fromSystem(DependencyDescriptor dd) {
298: return NameSpaceHelper.transform(dd, getNamespace()
299: .getFromSystemTransformer(), true);
300: }
301:
302: protected DependencyDescriptor toSystem(DependencyDescriptor dd) {
303: return NameSpaceHelper.transform(dd, getNamespace()
304: .getToSystemTransformer(), true);
305: }
306:
307: protected IvyNode getSystemNode(ResolveData data,
308: ModuleRevisionId resolvedMrid) {
309: return data.getNode(toSystem(resolvedMrid));
310: }
311:
312: protected ResolvedModuleRevision findModuleInCache(
313: DependencyDescriptor dd, CacheMetadataOptions options) {
314: return findModuleInCache(dd, options, false);
315: }
316:
317: protected ResolvedModuleRevision findModuleInCache(
318: DependencyDescriptor dd, CacheMetadataOptions options,
319: boolean anyResolver) {
320: return getRepositoryCacheManager().findModuleInCache(dd,
321: options, anyResolver ? null : getName());
322: }
323:
324: public void setChangingMatcher(String changingMatcherName) {
325: this .changingMatcherName = changingMatcherName;
326: }
327:
328: protected String getChangingMatcherName() {
329: return changingMatcherName;
330: }
331:
332: public void setChangingPattern(String changingPattern) {
333: this .changingPattern = changingPattern;
334: }
335:
336: protected String getChangingPattern() {
337: return changingPattern;
338: }
339:
340: public void setCheckmodified(boolean check) {
341: checkmodified = Boolean.valueOf(check);
342: }
343:
344: public RepositoryCacheManager getRepositoryCacheManager() {
345: if (repositoryCacheManager == null) {
346: if (cacheManagerName == null) {
347: repositoryCacheManager = settings
348: .getDefaultRepositoryCacheManager();
349: } else {
350: repositoryCacheManager = settings
351: .getRepositoryCacheManager(cacheManagerName);
352: }
353: }
354: return repositoryCacheManager;
355: }
356:
357: public void setRepositoryCacheManager(
358: RepositoryCacheManager repositoryCacheManager) {
359: this .repositoryCacheManager = repositoryCacheManager;
360: }
361:
362: public void setCache(String cacheName) {
363: cacheManagerName = cacheName;
364: }
365:
366: public void setEventManager(EventManager eventManager) {
367: this .eventManager = eventManager;
368: }
369:
370: public EventManager getEventManager() {
371: return eventManager;
372: }
373:
374: protected CacheMetadataOptions getCacheOptions(ResolveData data) {
375: return (CacheMetadataOptions) new CacheMetadataOptions()
376: .setChangingMatcherName(getChangingMatcherName())
377: .setChangingPattern(getChangingPattern())
378: .setCheckmodified(checkmodified).setValidate(
379: doValidate(data)).setNamespace(getNamespace())
380: .setForce(data.getOptions().isRefresh()).setListener(
381: getDownloadListener(getDownloadOptions(data
382: .getOptions())));
383: }
384:
385: protected CacheDownloadOptions getCacheDownloadOptions(
386: DownloadOptions options) {
387: return new CacheDownloadOptions()
388: .setListener(getDownloadListener(options));
389: }
390:
391: protected DownloadOptions getDownloadOptions(ResolveOptions options) {
392: return (DownloadOptions) new DownloadOptions().setLog(options
393: .getLog());
394: }
395:
396: public void abortPublishTransaction() throws IOException {
397: /* Default implementation is a no-op */
398: }
399:
400: public void commitPublishTransaction() throws IOException {
401: /* Default implementation is a no-op */
402: }
403:
404: public void beginPublishTransaction(ModuleRevisionId module,
405: boolean overwrite) throws IOException {
406: /* Default implementation is a no-op */
407: }
408:
409: private DownloadListener getDownloadListener(
410: final DownloadOptions options) {
411: return new DownloadListener() {
412: public void needArtifact(RepositoryCacheManager cache,
413: Artifact artifact) {
414: if (eventManager != null) {
415: eventManager.fireIvyEvent(new NeedArtifactEvent(
416: AbstractResolver.this , artifact));
417: }
418: }
419:
420: public void startArtifactDownload(
421: RepositoryCacheManager cache,
422: ResolvedResource rres, Artifact artifact,
423: ArtifactOrigin origin) {
424: if (artifact.isMetadata()
425: || LogOptions.LOG_QUIET
426: .equals(options.getLog())) {
427: Message.verbose("downloading " + rres.getResource()
428: + " ...");
429: } else {
430: Message.info("downloading " + rres.getResource()
431: + " ...");
432: }
433: if (eventManager != null) {
434: eventManager
435: .fireIvyEvent(new StartArtifactDownloadEvent(
436: AbstractResolver.this , artifact,
437: origin));
438: }
439: }
440:
441: public void endArtifactDownload(
442: RepositoryCacheManager cache, Artifact artifact,
443: ArtifactDownloadReport adr, File archiveFile) {
444: if (eventManager != null) {
445: eventManager
446: .fireIvyEvent(new EndArtifactDownloadEvent(
447: AbstractResolver.this, artifact,
448: adr, archiveFile));
449: }
450: }
451: };
452: }
453:
454: }
|