View Javadoc

1   package de.matthias_burbach.deputy.core.repository;
2   
3   import java.io.File;
4   import java.util.ArrayList;
5   import java.util.Collections;
6   import java.util.HashMap;
7   import java.util.HashSet;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Set;
11  
12  import org.jdom.Document;
13  import org.jdom.Element;
14  import org.jdom.xpath.XPath;
15  
16  /***
17   * Scans a given path and group id for all POMs of this group and returns
18   * all artifact ids of that group available there.
19   *
20   * @author Matthias Burbach
21   */
22  public class ArtifactScanner {
23      /***
24       * A temporary table to speed up the list method on a directory.
25       * Maps dir names of type {@link java.lang.String} to file name arrays of
26       * type String[].
27       */
28      private Map fileListMap = new HashMap();
29  
30      /***
31       * The cache for lists of artifact ids that have been returned already,
32       * keyed by the group directories.
33       */
34      private static Map resultCache = new HashMap();
35  
36      /***
37       * Clears the internal cache of already scanned artifacts.
38       * The cache is shared by all instances of this class.
39       */
40      public static void clearCache() {
41          resultCache = new HashMap();
42      }
43  
44      /***
45       * Scans a given group directory for all artifact ids of the group.<br/>
46       * Returns the result from a local cache if possible.
47       *
48       * @param groupDir The absolute file system path of a group directory to
49       *                 scan for all artifact ids of the group.
50       * @return The list of artifact ids of type {@link String}.
51       *         Is never <code>null</code>.
52       */
53      public List getAllArtifactIds(final String groupDir) {
54          final String key = groupDir;
55          List result = (List) resultCache.get(key);
56          if (result == null) {
57              result = doGetAllArtifactIds(groupDir);
58              if (result != null) {
59                  Collections.sort(result);
60                  resultCache.put(key, result);
61              }
62          }
63          return result;
64      }
65  
66      /***
67       * Scans a given group directory for all artifact ids of the group.<br/>
68       *
69       * @param groupDir The absolute file system path of a group directory to
70       *                 scan for all artifact ids of the group.
71       * @return The list of artifact ids of type {@link String}.
72       *         Is never <code>null</code>.
73       */
74      private List doGetAllArtifactIds(final String groupDir) {
75          Set result = new HashSet();
76          File pomsDir = new File(groupDir + File.separator + "poms");
77          if (pomsDir.isDirectory()) {
78              String[] fileNames = list(pomsDir);
79              for (int i = 0; i < fileNames.length; i++) {
80                  String fileName = fileNames[i];
81                  if (!isExcludedFileName(fileName)) {
82                      String artifactId =
83                          extractArtifactId(pomsDir.getAbsolutePath(), fileName);
84                      if (artifactId != null
85                              && fileName.startsWith(artifactId)) {
86                          result.add(artifactId);
87                      }
88                  }
89              }
90          }
91          return new ArrayList(result);
92      }
93  
94      /***
95       * Loads and parses the POM XML document and returns the artifact id.
96       *
97       * @param path The absolute file system path of the file to parse
98       *             without the file name.
99       * @param fileName The simple name of the file to parse.
100      * @return The artifact id parsed or null in case of any failure.
101      */
102     private String extractArtifactId(final String path, final String fileName) {
103         String result = null;
104         if (fileName.startsWith("vrp-") && fileName.indexOf("SNAPSHOT") == -1) {
105             result = extractArtifactIdFromFileName(fileName);
106         } else {
107             Document document = PomLoader.getInstance().loadPom(
108                     path + File.separator + fileName);
109             try {
110                 result = parseElementText(document, "project/artifactId");
111             } catch (Exception e) {
112                 e.printStackTrace();
113             }
114         }
115         return result;
116     }
117 
118     /***
119      * Optimizes overall performance by assuming that the file name is composed
120      * as artifactId-version.pom and that the version does not contain a '-'.
121      *
122      * @param fileName The file name to extract the artifact id from.
123      * @return The artifact id extracted.
124      */
125     private String extractArtifactIdFromFileName(final String fileName) {
126         int artifactEndIndex = fileName.lastIndexOf("-");
127         String result = fileName.substring(0, artifactEndIndex);
128         return result;
129     }
130 
131     /***
132      * Tries to parse the element named <code>elementName.</code>.
133      *
134      * @param xmlNode The XML node to that contains the element to parse.
135      * @param elementName The name of the element to parse.
136      * @return The contents of the element to parse or <code>null</code>.
137      * @throws Exception if anything goes unexpectedly wrong
138      */
139     private String parseElementText(
140             final Object xmlNode,
141             final String elementName)
142             throws Exception {
143         Element element =
144             (Element) XPath.newInstance(elementName).selectSingleNode(xmlNode);
145         String result = null;
146         if (element != null) {
147             result = element.getText();
148         }
149         return result;
150     }
151 
152     /***
153      * @param fileName The simple name of the file to check.
154      * @return <code>true</code> if the fileName is to be excluded from the
155      *         artifact id scanning
156      */
157     private boolean isExcludedFileName(final String fileName) {
158         boolean result = true;
159         String candidate = fileName.toLowerCase();
160         if (candidate.endsWith(".pom")
161                 && !candidate.endsWith("openedition.pom")
162                 && candidate.indexOf("snapshot-") == -1) {
163             result = false;
164         }
165         return result;
166     }
167 
168     /***
169      * Returns a cached result of list performed on file, if
170      * available. Invokes the method and caches the result otherwise.
171      *
172      * @param dir A directory to list the contents of.
173      * @return The array of files and dirs in the directory.
174      */
175     private String[] list(final File dir) {
176         String[] files = (String[]) fileListMap.get(dir);
177         if (files == null) {
178             files = dir.list();
179             if (files != null) {
180                 fileListMap.put(dir, files);
181             }
182         }
183         return files;
184     }
185 }