View Javadoc
1   /*
2    * REPOWEB, repository manager.
3    *
4    * Terms of license - http://opensource.org/licenses/apachepl.php
5    */
6   package org.repoweb.model.file;
7   import java.io.BufferedWriter;
8   import java.io.File;
9   import java.io.FileWriter;
10  import java.io.IOException;
11  import java.io.Writer;
12  import java.util.ArrayList;
13  import java.util.Arrays;
14  import java.util.HashMap;
15  import java.util.HashSet;
16  import java.util.Iterator;
17  import java.util.List;
18  import java.util.Map;
19  import java.util.Set;
20  import java.util.jar.JarFile;
21  import javax.xml.parsers.ParserConfigurationException;
22  import javax.xml.transform.TransformerException;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.repoweb.model.Artifact;
26  import org.repoweb.model.ArtifactList;
27  import org.repoweb.model.BadRepositoryLocationException;
28  import org.repoweb.model.BuildFailureException;
29  import org.repoweb.model.Group;
30  import org.repoweb.model.GroupList;
31  import org.repoweb.model.Repository;
32  import org.repoweb.model.UnknownArtifactException;
33  import org.repoweb.model.UnknownGroupIdException;
34  import org.repoweb.model.common.AbstractArtifact;
35  import org.repoweb.model.file.util.DirectoryScanner;
36  import org.repoweb.pom.Project;
37  import org.repoweb.pom.XMLProject;
38  /***
39   * Represent a maven repository accessed trought file.
40   */
41  public class FileRepository implements Repository {
42      private static final Log LOG = LogFactory.getLog(FileRepository.class);
43      private static final String[] MD5_EXCLUDES = new String[] {
44              "**/*.md5"
45          };
46      private static final String POM_TYPE = "pom";
47      private static final String POM_TYPES = "poms";
48      private final File _root;
49  
50      public FileRepository(String root) throws BadRepositoryLocationException {
51          this(new File(root));
52      }
53  
54  
55      public FileRepository(File root) throws BadRepositoryLocationException {
56          _root = root;
57          if (!_root.exists()) {
58              throw new BadRepositoryLocationException();
59          }
60      }
61  
62      public String toString() {
63          return "FileRepository(" + _root.toString() + ")";
64      }
65  
66  
67      public Group getGroup(String groupId) throws UnknownGroupIdException {
68          File groupFolder = new File(_root, groupId);
69          if (!groupFolder.exists()) {
70              throw new UnknownGroupIdException(groupId);
71          }
72  
73          return new FGroup(groupId, findArtifacts(groupId, "*s", "*"));
74      }
75  
76  
77      public GroupList findGroups(String pattern) {
78          DirectoryScanner ds = newScanner();
79          ds.setIncludes(new String[] {
80                  "*" + pattern + "*"
81              });
82          ds.scan();
83  
84          return buildGroups(ds.getIncludedDirectories());
85      }
86  
87  
88      public ArtifactList findArtifacts(String groupId, String typeId, String filename) {
89          DirectoryScanner ds = newScanner();
90          if (POM_TYPES.equals(typeId)) {
91              ds.setIncludes(new String[] {
92                      groupId + "/" + typeId + "/" + filename
93                  });
94          }
95          else {
96              ds.setIncludes(new String[] {
97                      groupId + "/" + typeId + "/" + filename,
98                      groupId + "/poms/" + pomNameFor(filename)
99                  });
100         }
101         ds.scan();
102 
103         List artifacts = toArtifact(ds.getIncludedFiles());
104 
105         return new FArtifactList((Artifact[])artifacts.toArray(
106                 new Artifact[artifacts.size()]));
107     }
108 
109 
110     public ArtifactList findArtifactByClass(String fullClassName) {
111         DirectoryScanner ds = newScanner();
112         ds.setIncludes(new String[] {
113                 "*/*s/*.jar"
114             });
115         ds.scan();
116 
117         List result = new ArrayList(Arrays.asList(ds.getIncludedFiles()));
118 
119         String classFile = toClassFile(fullClassName);
120 
121         for (Iterator iter = result.iterator(); iter.hasNext();) {
122             File artifact = (File)iter.next();
123             if (!containsFile(artifact, classFile)) {
124                 iter.remove();
125             }
126         }
127         return new FArtifactList((Artifact[])toArtifact(
128                 (File[])result.toArray(new File[result.size()])).toArray(new Artifact[] {}));
129     }
130 
131 
132     public Artifact buildPom(Project project) throws BuildFailureException {
133         if (isInvalid(project.getArtifactId())
134                 || isInvalid(project.getGroupId())
135                 || isInvalid(project.getCurrentVersion())) {
136             throw new BuildFailureException("Invalid Data");
137         }
138 
139         try {
140             String xmlContent = XMLProject.toXml(project);
141 
142             File artifactFile =
143                 new File(_root,
144                     project.getGroupId() + File.separator + "poms" + File.separator
145                     + project.getArtifactId() + "-" + project.getCurrentVersion()
146                     + ".pom");
147             artifactFile.getParentFile().mkdirs();
148 
149             Writer writer = new BufferedWriter(new FileWriter(artifactFile));
150             try {
151                 writer.write(xmlContent);
152             }
153             finally {
154                 writer.close();
155             }
156             return new FArtifact(artifactFile);
157         }
158         catch (IOException ex) {
159             throw new BuildFailureException("IO error !", ex);
160         }
161         catch (AbstractArtifact.BadArtifactFileException ex) {
162             // Should never occur
163             throw new BuildFailureException("Unexpected Error!", ex);
164         }
165         catch (ParserConfigurationException ex) {
166             throw new BuildFailureException("Unable to configure XML stuff!", ex);
167         }
168         catch (TransformerException ex) {
169             throw new BuildFailureException("Unable to build XML!", ex);
170         }
171     }
172 
173 
174     public Artifact getArtifact(String groupId, String typeId, String filename)
175         throws UnknownArtifactException {
176         ArtifactList list = findArtifacts(groupId, typeId + "s", filename);
177 
178         if (list.getArtifactCount() != 1) {
179             throw new UnknownArtifactException();
180         }
181 
182         return (Artifact)list.getArtifacts().get(0);
183     }
184 
185 
186     public GroupList getAllGroups() {
187         return buildGroups(_root.listFiles());
188     }
189 
190 
191     private GroupList buildGroups(File[] grpFolders) {
192         long start = System.currentTimeMillis();
193 
194         Group[] groups = new Group[grpFolders.length];
195 
196         for (int i = 0; i < grpFolders.length; i++) {
197             groups[i] = new FGroup(grpFolders[i].getName());
198         }
199 
200         long end = System.currentTimeMillis();
201 
202         LOG.debug("***********************************************");
203         LOG.debug("scanne de " + groups.length + " groupes");
204         LOG.debug("delay = " + (end - start) + " ms");
205         LOG.debug("***********************************************");
206 
207         return new FGroupList(groups);
208     }
209 
210 
211     private DirectoryScanner newScanner() {
212         DirectoryScanner ds = new DirectoryScanner();
213         ds.setBasedir(_root);
214         ds.setCaseSensitive(false);
215         ds.setExcludes(MD5_EXCLUDES);
216         return ds;
217     }
218 
219 
220     private List toArtifact(File[] files) {
221         List result = new ArrayList(files.length);
222         Map poms = new HashMap();
223         Set attachedPoms = new HashSet();
224 
225         for (int i = 0; i < files.length; i++) {
226             File file = files[i];
227             try {
228                 final FArtifact artifact = new FArtifact(file);
229                 if (POM_TYPE.equals(artifact.getType())) {
230                     poms.put(idVersionKey(artifact), artifact);
231                 }
232                 result.add(artifact);
233             }
234             catch (AbstractArtifact.BadArtifactFileException e) {
235                 LOG.error("Bad artifact file detected " + file, e);
236             }
237         }
238 
239         // Attach Poms
240         for (Iterator iter = result.iterator(); iter.hasNext();) {
241             FArtifact artifact = (FArtifact)iter.next();
242             if (!POM_TYPE.equals(artifact.getType())) {
243                 FArtifact pom = (FArtifact)poms.get(idVersionKey(artifact));
244                 if (pom != null) {
245                     attachedPoms.add(pom);
246                 }
247                 artifact.setPom(pom);
248             }
249         }
250         result.removeAll(attachedPoms);
251         return result;
252     }
253 
254 
255     private String idVersionKey(final FArtifact artifact) {
256         return artifact.getId() + artifact.getVersion();
257     }
258 
259 
260     private boolean containsFile(File artifactFile, String fileName) {
261         try {
262             final JarFile jarFile = new JarFile(artifactFile);
263             try {
264                 return jarFile.getEntry(fileName) != null;
265             }
266             finally {
267                 jarFile.close();
268             }
269         }
270         catch (IOException e) {
271             return false;
272         }
273     }
274 
275 
276     private static String toClassFile(String fullClassName) {
277         return fullClassName.replace('.', '/') + ".class";
278     }
279 
280 
281     private static String pomNameFor(String filename) {
282         int idx = filename.lastIndexOf('.');
283         if (idx != -1) {
284             return filename.substring(0, idx) + ".pom";
285         }
286         return filename + ".pom";
287     }
288 
289 
290     private static boolean isInvalid(String value) {
291         return value == null || "".equals(value.trim());
292     }
293 }