1
2
3
4
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
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
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 }