]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/DistributionBundleIndexer.java
7441490bcbad0f3c145543a51b2815dad73fc4ca
[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_MODULE_NAME,
140 artifact.getArtifactId());
141 moduleCoord.setProperty(SlcNames.SLC_MODULE_VERSION,
142 artifact.getVersion());
143 String groupId = artifact.getGroupId();
144 if (groupId != null && !"".equals(groupId.trim()))
145 moduleCoord.setProperty(
146 SlcNames.SLC_MODULE_CATEGORY,
147 artifact.getGroupId());
148 }
149 }
150
151 }
152
153 jarIn.closeEntry();
154
155 // find base URL
156 // won't work if distribution artifact is not listed
157 // for (int i = 0; i < artifacts.size(); i++) {
158 // OsgiArtifact osgiArtifact = artifacts.get(i);
159 // if (osgiArtifact.getSymbolicName().equals(symbolicName)
160 // && osgiArtifact.getVersion().equals(version)) {
161 // String relativeUrl = osgiArtifact.getRelativeUrl();
162 // if (url.endsWith(relativeUrl)) {
163 // baseUrl = url.substring(0, url.length()
164 // - osgiArtifact.getRelativeUrl().length());
165 // break;
166 // }
167 // }
168 // }
169 } catch (Exception e) {
170 throw new SlcException("Cannot list dependencies from " + fileNode,
171 e);
172 } finally {
173 if (jarIn != null)
174 try {
175 jarIn.close();
176 } catch (IOException e) {
177 // silent
178 }
179 }
180 }
181
182 protected List<Artifact> listArtifacts(InputStream in) {
183 List<Artifact> artifacts = new ArrayList<Artifact>();
184 BufferedReader reader = null;
185 try {
186 reader = new BufferedReader(new InputStreamReader(in));
187 String line = null;
188 while ((line = reader.readLine()) != null) {
189
190 StringTokenizer st = new StringTokenizer(line, separator);
191 String moduleName = st.nextToken();
192 String moduleVersion = st.nextToken();
193 String relativeUrl = st.nextToken();
194
195 //
196 // String Category = getCategoryFromRelativeUrl(relativeUrl,
197 // moduleName);
198
199 artifacts.add(AetherUtils.convertPathToArtifact(relativeUrl,
200 null));
201
202 if (log.isTraceEnabled())
203 log.debug("Processed dependency: " + line);
204 }
205 } catch (Exception e) {
206 throw new SlcException("Cannot list artifacts", e);
207 }
208 return artifacts;
209 }
210
211 /** Relative path to the directories where the files will be stored */
212 private String getCategoryFromRelativeUrl(String relativeUrl,
213 String moduleName) {
214 int index = relativeUrl.indexOf("moduleName");
215 if (index < 1)
216 throw new SlcException("Unvalid relative URL: " + relativeUrl
217 + " for module " + moduleName);
218 // Remove trailing /
219 String result = relativeUrl.substring(0, index - 1);
220 return result.replace('/', '.');
221 }
222
223 /**
224 * List full URLs of the bundles, based on base URL, usable directly for
225 * download.
226 */
227 // public List/* <String> */listUrls() {
228 // if (baseUrl == null)
229 // throw new SlcException("Base URL is not set");
230 //
231 // if (artifacts == null)
232 // throw new SlcException("Artifact list not initialized");
233 //
234 // List/* <String> */urls = new ArrayList();
235 // for (int i = 0; i < artifacts.size(); i++) {
236 // OsgiArtifact osgiArtifact = (OsgiArtifact) artifacts.get(i);
237 // urls.add(baseUrl + osgiArtifact.getRelativeUrl());
238 // }
239 // return urls;
240 // }
241 //
242 // public void setBaseUrl(String baseUrl) {
243 // this.baseUrl = baseUrl;
244 // }
245
246 /** Separator used to parse the tabular file, default is "," */
247 public void setSeparator(String modulesUrlSeparator) {
248 this.separator = modulesUrlSeparator;
249 }
250
251 // public String getRelativeUrl() {
252 // return relativeUrl;
253 // }
254
255 /** One of the listed artifact */
256 protected static class OsgiArtifact {
257 private final String category;
258 private final String symbolicName;
259 private final String version;
260 private final String relativeUrl;
261
262 public OsgiArtifact(String category, String symbolicName,
263 String version, String relativeUrl) {
264 super();
265 this.category = category;
266 this.symbolicName = symbolicName;
267 this.version = version;
268 this.relativeUrl = relativeUrl;
269 }
270
271 public String getCategory() {
272 return category;
273 }
274
275 public String getSymbolicName() {
276 return symbolicName;
277 }
278
279 public String getVersion() {
280 return version;
281 }
282
283 public String getRelativeUrl() {
284 return relativeUrl;
285 }
286
287 }
288 }