]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/DistributionBundleIndexer.java
7dfefc2a1ed9ca4f4fde3c2669004473684f512d
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / DistributionBundleIndexer.java
1 package org.argeo.slc.repo;
2
3 import java.io.BufferedReader;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.io.InputStreamReader;
7 import java.util.ArrayList;
8 import java.util.List;
9 import java.util.StringTokenizer;
10 import java.util.jar.JarEntry;
11 import java.util.jar.JarInputStream;
12 import java.util.jar.Manifest;
13
14 import javax.jcr.Binary;
15 import javax.jcr.Node;
16 import javax.jcr.Property;
17 import javax.jcr.Session;
18 import javax.jcr.nodetype.NodeType;
19
20 import org.apache.commons.io.FilenameUtils;
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.argeo.jcr.JcrUtils;
24 import org.argeo.slc.SlcException;
25 import org.argeo.slc.aether.AetherUtils;
26 import org.argeo.slc.jcr.SlcNames;
27 import org.argeo.slc.jcr.SlcTypes;
28 import org.osgi.framework.Constants;
29 import org.sonatype.aether.artifact.Artifact;
30
31 /**
32 * Index distribution bundles that is mainly dep artifacts that have generate a
33 * modular distribution csv index during maven build
34 */
35 public class DistributionBundleIndexer implements NodeIndexer {
36 private final static Log log = LogFactory
37 .getLog(DistributionBundleIndexer.class);
38
39 private final static String INDEX_FILE_NAME = "modularDistribution.csv";
40
41 // private final String url;
42
43 private Manifest manifest;
44 private String symbolicName;
45 private String version;
46
47 /** can be null */
48 // private String baseUrl;
49 /** can be null */
50 // private String relativeUrl;
51
52 private List<Artifact> artifacts;
53
54 private String separator = ",";
55
56 // public DistributionBundleIndexer(String url) {
57 // this.url = url;
58 // }
59 //
60 // public DistributionBundleIndexer(String baseUrl, String relativeUrl) {
61 // if (baseUrl == null || !baseUrl.endsWith("/"))
62 // throw new SlcException("Base url " + baseUrl + " badly formatted");
63 // if (relativeUrl.startsWith("http") || relativeUrl.startsWith("file:"))
64 // throw new SlcException("Relative URL " + relativeUrl
65 // + " badly formatted");
66 // this.url = baseUrl + relativeUrl;
67 // this.baseUrl = baseUrl;
68 // this.relativeUrl = relativeUrl;
69 // }
70
71 public Boolean support(String path) {
72 return FilenameUtils.getExtension(path).equals("jar");
73 }
74
75 public void index(Node fileNode) {
76 JarInputStream jarIn = null;
77 Binary fileBinary = null;
78 try {
79 if (!support(fileNode.getPath()))
80 return;
81
82 if (!fileNode.isNodeType(NodeType.NT_FILE))
83 return;
84
85 Session jcrSession = fileNode.getSession();
86 Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
87 fileBinary = contentNode.getProperty(Property.JCR_DATA).getBinary();
88 jarIn = new JarInputStream(fileBinary.getStream());
89
90 // meta data
91 manifest = jarIn.getManifest();
92 if (manifest == null) {
93 log.error(fileNode + " has no MANIFEST");
94 return;
95 }
96 symbolicName = manifest.getMainAttributes().getValue(
97 Constants.BUNDLE_SYMBOLICNAME);
98 version = manifest.getMainAttributes().getValue(
99 Constants.BUNDLE_VERSION);
100
101 JarEntry indexEntry;
102 while ((indexEntry = jarIn.getNextJarEntry()) != null) {
103 String entryName = indexEntry.getName();
104 if (entryName.equals(INDEX_FILE_NAME)) {
105 break;
106 }
107 jarIn.closeEntry();
108 }
109
110 // list artifacts
111 if (indexEntry == null)
112 return; // Not a modular definition artifact
113
114 // throw new SlcException("No index " + INDEX_FILE_NAME + " in "
115 // + fileNode.getPath());
116 //
117
118 artifacts = listArtifacts(jarIn);
119
120 if (artifacts == null || artifacts.isEmpty())
121 return; // no modules found
122 else {
123 Node modules;
124 if (fileNode.isNodeType(SlcTypes.SLC_MODULAR_DISTRIBUTION)) {
125 modules = fileNode.getNode(SlcNames.SLC_MODULES);
126 } else {
127 fileNode.addMixin(SlcTypes.SLC_MODULAR_DISTRIBUTION);
128 modules = JcrUtils.mkdirs(fileNode, SlcNames.SLC_MODULES,
129 NodeType.NT_UNSTRUCTURED);
130 }
131
132 for (Artifact artifact : artifacts) {
133 // TODO clean this once an overwrite policy has been
134 // decided.
135 if (!modules.hasNode(artifact.getArtifactId())) {
136 Node moduleCoord = modules.addNode(
137 artifact.getArtifactId(),
138 SlcTypes.SLC_MODULE_COORDINATES);
139 moduleCoord.setProperty(SlcNames.SLC_NAME,
140 artifact.getArtifactId());
141 moduleCoord.setProperty(SlcNames.SLC_VERSION,
142 artifact.getVersion());
143 String groupId = artifact.getGroupId();
144 if (groupId != null && !"".equals(groupId.trim()))
145 moduleCoord.setProperty(SlcNames.SLC_CATEGORY,
146 artifact.getGroupId());
147 }
148 }
149
150 }
151
152 jarIn.closeEntry();
153
154 // find base URL
155 // won't work if distribution artifact is not listed
156 // for (int i = 0; i < artifacts.size(); i++) {
157 // OsgiArtifact osgiArtifact = artifacts.get(i);
158 // if (osgiArtifact.getSymbolicName().equals(symbolicName)
159 // && osgiArtifact.getVersion().equals(version)) {
160 // String relativeUrl = osgiArtifact.getRelativeUrl();
161 // if (url.endsWith(relativeUrl)) {
162 // baseUrl = url.substring(0, url.length()
163 // - osgiArtifact.getRelativeUrl().length());
164 // break;
165 // }
166 // }
167 // }
168 } catch (Exception e) {
169 throw new SlcException("Cannot list dependencies from " + fileNode,
170 e);
171 } finally {
172 if (jarIn != null)
173 try {
174 jarIn.close();
175 } catch (IOException e) {
176 // silent
177 }
178 }
179 }
180
181 protected List<Artifact> listArtifacts(InputStream in) {
182 List<Artifact> artifacts = new ArrayList<Artifact>();
183 BufferedReader reader = null;
184 try {
185 reader = new BufferedReader(new InputStreamReader(in));
186 String line = null;
187 while ((line = reader.readLine()) != null) {
188
189 StringTokenizer st = new StringTokenizer(line, separator);
190 // String moduleName =
191 st.nextToken();
192 // String moduleVersion =
193 st.nextToken();
194 String relativeUrl = st.nextToken();
195
196 //
197 // String Category = getCategoryFromRelativeUrl(relativeUrl,
198 // moduleName);
199
200 artifacts.add(AetherUtils.convertPathToArtifact(relativeUrl,
201 null));
202
203 if (log.isTraceEnabled())
204 log.debug("Processed dependency: " + line);
205 }
206 } catch (Exception e) {
207 throw new SlcException("Cannot list artifacts", e);
208 }
209 return artifacts;
210 }
211
212 // /** Relative path to the directories where the files will be stored */
213 // private String getCategoryFromRelativeUrl(String relativeUrl,
214 // String moduleName) {
215 // int index = relativeUrl.indexOf("moduleName");
216 // if (index < 1)
217 // throw new SlcException("Unvalid relative URL: " + relativeUrl
218 // + " for module " + moduleName);
219 // // Remove trailing /
220 // String result = relativeUrl.substring(0, index - 1);
221 // return result.replace('/', '.');
222 // }
223
224 /**
225 * List full URLs of the bundles, based on base URL, usable directly for
226 * download.
227 */
228 // public List/* <String> */listUrls() {
229 // if (baseUrl == null)
230 // throw new SlcException("Base URL is not set");
231 //
232 // if (artifacts == null)
233 // throw new SlcException("Artifact list not initialized");
234 //
235 // List/* <String> */urls = new ArrayList();
236 // for (int i = 0; i < artifacts.size(); i++) {
237 // OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i);
238 // urls.add(baseUrl + osgiArtifact.getRelativeUrl());
239 // }
240 // return urls;
241 // }
242 //
243 // public void setBaseUrl(String baseUrl) {
244 // this.baseUrl = baseUrl;
245 // }
246
247 /** Separator used to parse the tabular file, default is "," */
248 public void setSeparator(String modulesUrlSeparator) {
249 this.separator = modulesUrlSeparator;
250 }
251
252 // public String getRelativeUrl() {
253 // return relativeUrl;
254 // }
255
256 /** One of the listed artifact */
257 protected static class OsgiArtifact {
258 private final String category;
259 private final String symbolicName;
260 private final String version;
261 private final String relativeUrl;
262
263 public OsgiArtifact(String category, String symbolicName,
264 String version, String relativeUrl) {
265 super();
266 this.category = category;
267 this.symbolicName = symbolicName;
268 this.version = version;
269 this.relativeUrl = relativeUrl;
270 }
271
272 public String getCategory() {
273 return category;
274 }
275
276 public String getSymbolicName() {
277 return symbolicName;
278 }
279
280 public String getVersion() {
281 return version;
282 }
283
284 public String getRelativeUrl() {
285 return relativeUrl;
286 }
287
288 }
289 }