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.util;
019:
020: import java.io.IOException;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.util.ArrayList;
024: import java.util.Arrays;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.regex.Matcher;
028: import java.util.regex.Pattern;
029:
030: import org.apache.ivy.core.IvyPatternHelper;
031: import org.apache.ivy.core.module.descriptor.Artifact;
032: import org.apache.ivy.core.module.id.ModuleRevisionId;
033: import org.apache.ivy.plugins.repository.Repository;
034: import org.apache.ivy.plugins.repository.Resource;
035: import org.apache.ivy.util.Message;
036:
037: public final class ResolverHelper {
038: private ResolverHelper() {
039: }
040:
041: // lists all the values a token can take in a pattern, as listed by a given url lister
042: public static String[] listTokenValues(Repository rep,
043: String pattern, String token) {
044: String fileSep = rep.getFileSeparator();
045: pattern = rep.standardize(pattern);
046: String tokenString = IvyPatternHelper.getTokenString(token);
047: int index = pattern.indexOf(tokenString);
048: if (index == -1) {
049: Message.verbose("unable to list " + token + " in "
050: + pattern + ": token not found in pattern");
051: return null;
052: }
053: if (((pattern.length() <= index + tokenString.length()) || fileSep
054: .equals(pattern.substring(index + tokenString.length(),
055: index + tokenString.length() + 1)))
056: && (index == 0 || fileSep.equals(pattern.substring(
057: index - 1, index)))) {
058: // the searched token is a whole name
059: String root = pattern.substring(0, index);
060: return listAll(rep, root);
061: } else {
062: int slashIndex = pattern.substring(0, index).lastIndexOf(
063: fileSep);
064: String root = slashIndex == -1 ? "" : pattern.substring(0,
065: slashIndex);
066:
067: try {
068: Message.debug("\tusing " + rep + " to list all in "
069: + root);
070: List all = rep.list(root);
071: if (all != null) {
072: Message.debug("\t\tfound " + all.size() + " urls");
073: List ret = new ArrayList(all.size());
074: int endNameIndex = pattern.indexOf(fileSep,
075: slashIndex + 1);
076: String namePattern;
077: if (endNameIndex != -1) {
078: namePattern = pattern.substring(slashIndex + 1,
079: endNameIndex);
080: } else {
081: namePattern = pattern.substring(slashIndex + 1);
082: }
083: String acceptNamePattern = ".*"
084: + IvyPatternHelper.substituteToken(
085: namePattern, token, "([^" + fileSep
086: + "]+)") + ".*";
087: Pattern p = Pattern.compile(acceptNamePattern
088: .toString());
089: for (Iterator iter = all.iterator(); iter.hasNext();) {
090: String path = (String) iter.next();
091: Matcher m = p.matcher(path);
092: if (m.matches()) {
093: String value = m.group(1);
094: ret.add(value);
095: }
096: }
097: Message.debug("\t\t" + ret.size() + " matched "
098: + pattern);
099: return (String[]) ret
100: .toArray(new String[ret.size()]);
101: } else {
102: return null;
103: }
104: } catch (IOException e) {
105: Message.verbose("problem while listing resources in "
106: + root + " with " + rep + ":");
107: Message.verbose(" " + e.getClass().getName() + " "
108: + e.getMessage());
109: return null;
110: } catch (Exception e) {
111: Message.warn("problem while listing resources in "
112: + root + " with " + rep + ":");
113: Message.warn(" " + e.getClass().getName() + " "
114: + e.getMessage());
115: return null;
116: }
117: }
118: }
119:
120: public static String[] listAll(Repository rep, String parent) {
121: try {
122: String fileSep = rep.getFileSeparator();
123: Message.debug("\tusing " + rep + " to list all in "
124: + parent);
125: List all = rep.list(parent);
126: if (all != null) {
127: Message.debug("\t\tfound " + all.size() + " resources");
128: List names = new ArrayList(all.size());
129: for (Iterator iter = all.iterator(); iter.hasNext();) {
130: String path = (String) iter.next();
131: if (path.endsWith(fileSep)) {
132: path = path.substring(0, path.length() - 1);
133: }
134: int slashIndex = path.lastIndexOf(fileSep);
135: names.add(path.substring(slashIndex + 1));
136: }
137: return (String[]) names
138: .toArray(new String[names.size()]);
139: } else {
140: Message.debug("\t\tno resources found");
141: return null;
142: }
143: } catch (IOException e) {
144: Message.verbose("problem while listing resources in "
145: + parent + " with " + rep + ":");
146: Message.verbose(" " + e.getClass().getName() + " "
147: + e.getMessage());
148: return null;
149: } catch (Exception e) {
150: Message.warn("problem while listing resources in " + parent
151: + " with " + rep + ":");
152: Message.warn(" " + e.getClass().getName() + " "
153: + e.getMessage());
154: return null;
155: }
156: }
157:
158: public static ResolvedResource[] findAll(Repository rep,
159: ModuleRevisionId mrid, String pattern, Artifact artifact) {
160: // substitute all but revision
161: String partiallyResolvedPattern = IvyPatternHelper
162: .substitute(
163: pattern,
164: ModuleRevisionId
165: .newInstance(
166: mrid,
167: IvyPatternHelper
168: .getTokenString(IvyPatternHelper.REVISION_KEY)),
169: artifact);
170: Message.debug("\tlisting all in " + partiallyResolvedPattern);
171:
172: String[] revs = listTokenValues(rep, partiallyResolvedPattern,
173: IvyPatternHelper.REVISION_KEY);
174: if (revs != null) {
175: Message.debug("\tfound revs: " + Arrays.asList(revs));
176: List ret = new ArrayList(revs.length);
177: for (int i = 0; i < revs.length; i++) {
178: String rres = IvyPatternHelper.substituteToken(
179: partiallyResolvedPattern,
180: IvyPatternHelper.REVISION_KEY, revs[i]);
181: try {
182: Resource res = rep.getResource(rres);
183: if ((res != null) && res.exists()) {
184: ret.add(new ResolvedResource(res, revs[i]));
185: }
186: } catch (IOException e) {
187: Message
188: .warn("impossible to get resource from name listed by repository: "
189: + rres + ": " + e.getMessage());
190: }
191: }
192: if (revs.length != ret.size()) {
193: Message.debug("\tfound resolved res: " + ret);
194: }
195: return (ResolvedResource[]) ret
196: .toArray(new ResolvedResource[ret.size()]);
197: } else if (partiallyResolvedPattern.indexOf("["
198: + IvyPatternHelper.REVISION_KEY + "]") == -1) {
199: // the partially resolved pattern is completely resolved, check the resource
200: try {
201: Resource res = rep
202: .getResource(partiallyResolvedPattern);
203: if (res.exists()) {
204: Message
205: .debug("\tonly one resource found without real listing: "
206: + "using and defining it as working@"
207: + rep.getName()
208: + " revision: "
209: + res.getName());
210: return new ResolvedResource[] { new ResolvedResource(
211: res, "working@" + rep.getName()) };
212: }
213: } catch (IOException e) {
214: Message
215: .debug("\timpossible to get resource from name listed by repository: "
216: + partiallyResolvedPattern
217: + ": "
218: + e.getMessage());
219: }
220: Message.debug("\tno revision found");
221: }
222: return null;
223: }
224:
225: // public static ResolvedResource[] findAll(Repository rep, ModuleRevisionId mrid, String
226: // pattern, Artifact artifact, VersionMatcher versionMatcher, ResourceMDParser mdParser) {
227: // // substitute all but revision
228: // String partiallyResolvedPattern = IvyPatternHelper.substitute(pattern, new
229: // ModuleRevisionId(mrid.getModuleId(),
230: // IvyPatternHelper.getTokenString(IvyPatternHelper.REVISION_KEY), mrid.getExtraAttributes()),
231: // artifact);
232: // Message.debug("\tlisting all in "+partiallyResolvedPattern);
233: //
234: // String[] revs = listTokenValues(rep, partiallyResolvedPattern,
235: // IvyPatternHelper.REVISION_KEY);
236: // if (revs != null) {
237: // Message.debug("\tfound revs: "+Arrays.asList(revs));
238: // List ret = new ArrayList(revs.length);
239: // String rres = null;
240: // for (int i = 0; i < revs.length; i++) {
241: // ModuleRevisionId foundMrid = new ModuleRevisionId(mrid.getModuleId(), revs[i],
242: // mrid.getExtraAttributes());
243: // if (versionMatcher.accept(mrid, foundMrid)) {
244: // rres = IvyPatternHelper.substituteToken(partiallyResolvedPattern,
245: // IvyPatternHelper.REVISION_KEY, revs[i]);
246: // try {
247: // ResolvedResource resolvedResource;
248: // if (versionMatcher.needModuleDescriptor(mrid, foundMrid)) {
249: // resolvedResource = mdParser.parse(rep.getResource(rres), revs[i]);
250: // if (!versionMatcher.accept(mrid,
251: // ((MDResolvedResource)resolvedResource).getResolvedModuleRevision().getDescriptor())) {
252: // continue;
253: // }
254: // } else {
255: // resolvedResource = new ResolvedResource(rep.getResource(rres), revs[i]);
256: // }
257: // ret.add(resolvedResource);
258: // } catch (IOException e) {
259: // Message.warn("impossible to get resource from name listed by repository: "+rres+":
260: // "+e.getMessage());
261: // }
262: // }
263: // }
264: // if (revs.length != ret.size()) {
265: // Message.debug("\tfound resolved res: "+ret);
266: // }
267: // return (ResolvedResource[])ret.toArray(new ResolvedResource[ret.size()]);
268: // } else {
269: // // maybe the partially resolved pattern is completely resolved ?
270: // try {
271: // Resource res = rep.getResource(partiallyResolvedPattern);
272: // if (res.exists()) {
273: // Message.debug("\tonly one resource found without real listing: using and defining it as
274: // working@"+rep.getName()+" revision: "+res.getName());
275: // return new ResolvedResource[] {new ResolvedResource(res, "working@"+rep.getName())};
276: // }
277: // } catch (IOException e) {
278: // Message.debug("\timpossible to get resource from name listed by repository:
279: // "+partiallyResolvedPattern+": "+e.getMessage());
280: // }
281: // Message.debug("\tno revision found");
282: // }
283: // return null;
284: // }
285:
286: // lists all the values a token can take in a pattern, as listed by a given url lister
287: public static String[] listTokenValues(URLLister lister,
288: String pattern, String token) {
289: pattern = standardize(pattern);
290: if (lister.accept(pattern)) {
291: String tokenString = IvyPatternHelper.getTokenString(token);
292: int index = pattern.indexOf(tokenString);
293: if (index == -1) {
294: Message.verbose("unable to list " + token + " in "
295: + pattern + ": token not found in pattern");
296: return null;
297: }
298: if (((pattern.length() <= index + tokenString.length()) || "/"
299: .equals(pattern.substring(index
300: + tokenString.length(), index
301: + tokenString.length() + 1)))
302: && (index == 0 || "/".equals(pattern.substring(
303: index - 1, index)))) {
304: // the searched token is a whole name
305: String root = pattern.substring(0, index);
306: try {
307: return listAll(lister, new URL(root));
308: } catch (MalformedURLException e) {
309: Message.warn("malformed url from pattern root: "
310: + root + ": " + e.getMessage());
311: return null;
312: }
313: } else {
314: int slashIndex = pattern.substring(0, index)
315: .lastIndexOf('/');
316: String root = slashIndex == -1 ? "" : pattern
317: .substring(0, slashIndex);
318:
319: try {
320: Message.debug("\tusing " + lister
321: + " to list all in " + root);
322: List all = lister.listAll(new URL(root));
323: Message.debug("\t\tfound " + all.size() + " urls");
324: List ret = new ArrayList(all.size());
325: int endNameIndex = pattern.indexOf('/',
326: slashIndex + 1);
327: String namePattern;
328: if (endNameIndex != -1) {
329: namePattern = pattern.substring(slashIndex + 1,
330: endNameIndex);
331: } else {
332: namePattern = pattern.substring(slashIndex + 1);
333: }
334: String acceptNamePattern = ".*"
335: + IvyPatternHelper.substituteToken(
336: namePattern, token, "([^/]+)")
337: + ".*";
338: Pattern p = Pattern.compile(acceptNamePattern
339: .toString());
340: for (Iterator iter = all.iterator(); iter.hasNext();) {
341: URL url = (URL) iter.next();
342: String path = standardize(url.getPath());
343: Matcher m = p.matcher(path);
344: if (m.matches()) {
345: String value = m.group(1);
346: ret.add(value);
347: }
348: }
349: Message.debug("\t\t" + ret.size() + " matched "
350: + pattern);
351: return (String[]) ret
352: .toArray(new String[ret.size()]);
353: } catch (Exception e) {
354: Message.warn("problem while listing files in "
355: + root + ": " + e.getClass() + " "
356: + e.getMessage());
357: return null;
358: }
359: }
360: }
361: return null;
362: }
363:
364: private static String standardize(String path) {
365: return path.replace('\\', '/');
366: }
367:
368: public static String[] listAll(URLLister lister, URL root) {
369: try {
370: if (lister.accept(root.toExternalForm())) {
371: Message.debug("\tusing " + lister + " to list all in "
372: + root);
373: List all = lister.listAll(root);
374: Message.debug("\t\tfound " + all.size() + " urls");
375: List names = new ArrayList(all.size());
376: for (Iterator iter = all.iterator(); iter.hasNext();) {
377: URL dir = (URL) iter.next();
378: String path = dir.getPath();
379: if (path.endsWith("/")) {
380: path = path.substring(0, path.length() - 1);
381: }
382: int slashIndex = path.lastIndexOf('/');
383: names.add(path.substring(slashIndex + 1));
384: }
385: return (String[]) names
386: .toArray(new String[names.size()]);
387: }
388: return null;
389: } catch (Exception e) {
390: Message.warn("problem while listing directories in " + root
391: + ": " + e.getClass() + " " + e.getMessage());
392: return null;
393: }
394: }
395: }
|