]> git.argeo.org Git - gpl/argeo-slc.git/blob - ArchiveWrapper.java
832b790bf91f94724aff64d9e572a4955060e193
[gpl/argeo-slc.git] / ArchiveWrapper.java
1 package org.argeo.slc.repo.osgi;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.TreeSet;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipInputStream;
14
15 import javax.jcr.Node;
16 import javax.jcr.Property;
17 import javax.jcr.RepositoryException;
18 import javax.jcr.Session;
19
20 import org.apache.commons.io.FilenameUtils;
21 import org.apache.commons.io.IOUtils;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.argeo.jcr.JcrUtils;
25 import org.argeo.slc.DefaultNameVersion;
26 import org.argeo.slc.ModuleSet;
27 import org.argeo.slc.NameVersion;
28 import org.argeo.slc.SlcException;
29 import org.argeo.slc.aether.ArtifactIdComparator;
30 import org.argeo.slc.build.Distribution;
31 import org.argeo.slc.build.License;
32 import org.argeo.slc.repo.OsgiFactory;
33 import org.argeo.slc.repo.RepoUtils;
34 import org.sonatype.aether.artifact.Artifact;
35 import org.sonatype.aether.util.artifact.DefaultArtifact;
36 import org.springframework.util.AntPathMatcher;
37 import org.springframework.util.PathMatcher;
38
39 /**
40 * Download a software distribution and generates the related OSGi bundles from
41 * the jars, or import them directly if they are already OSGi bundles and don't
42 * need further modification.
43 */
44 public class ArchiveWrapper implements Runnable, ModuleSet, Distribution {
45 private final static Log log = LogFactory.getLog(ArchiveWrapper.class);
46
47 private OsgiFactory osgiFactory;
48 private String version;
49 private License license;
50
51 private String uri;
52
53 /** Jars to wrap as OSGi bundles */
54 private Map<String, BndWrapper> wrappers = new HashMap<String, BndWrapper>();
55
56 // pattern of OSGi bundles to import
57 private PathMatcher pathMatcher = new AntPathMatcher();
58 private Map<String, String> includes = new HashMap<String, String>();
59 private List<String> excludes = new ArrayList<String>();
60
61 private Boolean mavenGroupIndexes = false;
62
63 public void init() {
64 for (BndWrapper wrapper : wrappers.values()) {
65 wrapper.setFactory(this);
66 if (version != null && wrapper.getVersion() == null)
67 wrapper.setVersion(version);
68 if (license != null && wrapper.getLicense() == null)
69 wrapper.setLicense(license);
70 }
71 }
72
73 public void destroy() {
74
75 }
76
77 public String getDistributionId() {
78 return uri;
79 }
80
81 public Iterator<? extends NameVersion> nameVersions() {
82 return wrappers.values().iterator();
83 }
84
85 public void run() {
86 if (mavenGroupIndexes && (version == null))
87 throw new SlcException(
88 "'mavenGroupIndexes' requires 'version' to be set");
89
90 Map<String, Set<Artifact>> binaries = new HashMap<String, Set<Artifact>>();
91 Map<String, Set<Artifact>> sources = new HashMap<String, Set<Artifact>>();
92
93 Session distSession = null;
94 Session javaSession = null;
95 ZipInputStream zin = null;
96 try {
97 javaSession = osgiFactory.openJavaSession();
98 distSession = osgiFactory.openDistSession();
99
100 if (log.isDebugEnabled())
101 log.debug("Wrapping " + uri);
102
103 Node distNode = osgiFactory.getDist(distSession, uri);
104 zin = new ZipInputStream(distNode.getNode(Node.JCR_CONTENT)
105 .getProperty(Property.JCR_DATA).getBinary().getStream());
106
107 ZipEntry zentry = null;
108 entries: while ((zentry = zin.getNextEntry()) != null) {
109 String name = zentry.getName();
110
111 // sources autodetect
112 String baseName = FilenameUtils.getBaseName(name);
113 if (baseName.endsWith("-sources")) {
114 String bundle = baseName.substring(0, baseName.length()
115 - "-sources".length());
116 log.debug(name + "," + baseName + ", " + bundle);
117 String bundlePath = FilenameUtils.getPath(name) + bundle
118 + ".jar";
119 if (wrappers.containsKey(bundlePath)) {
120 BndWrapper wrapper = wrappers.get(bundlePath);
121 NameVersion bundleNv = new DefaultNameVersion(
122 wrapper.getName(), wrapper.getVersion());
123 byte[] pdeSource = RepoUtils.packageAsPdeSource(zin,
124 bundleNv);
125 Node pdeSourceNode = RepoUtils.copyBytesAsArtifact(
126 javaSession.getRootNode(),
127 new DefaultArtifact(wrapper.getCategory(),
128 wrapper.getName() + ".source", "jar",
129 wrapper.getVersion()), pdeSource);
130 osgiFactory.indexNode(pdeSourceNode);
131 pdeSourceNode.getSession().save();
132 }
133 } else if (baseName.endsWith(".source")) {
134 // TODO Eclipse source already available
135 }
136
137 // binaries
138 if (wrappers.containsKey(name)) {
139 BndWrapper wrapper = (BndWrapper) wrappers.get(name);
140 // we must copy since the stream is closed by BND
141 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
142 Artifact artifact = wrapZipEntry(javaSession, zentry,
143 sourceJarBytes, wrapper);
144 addArtifactToIndex(binaries, wrapper.getGroupId(), artifact);
145 } else {
146 for (String wrapperKey : wrappers.keySet())
147 if (pathMatcher.match(wrapperKey, name)) {
148 // first matched is taken
149 BndWrapper wrapper = (BndWrapper) wrappers
150 .get(wrapperKey);
151 // we must copy since the stream is closed by BND
152 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
153 Artifact artifact = wrapZipEntry(javaSession,
154 zentry, sourceJarBytes, wrapper);
155 addArtifactToIndex(binaries, wrapper.getGroupId(),
156 artifact);
157 continue entries;
158 } else {
159 if (log.isTraceEnabled())
160 log.trace(name + " not matched by "
161 + wrapperKey);
162 }
163
164 for (String exclude : excludes)
165 if (pathMatcher.match(exclude, name))
166 continue entries;
167
168 for (String include : includes.keySet()) {
169 if (pathMatcher.match(include, name)) {
170 String groupId = includes.get(include);
171 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
172 Artifact artifact = importZipEntry(javaSession,
173 zentry, sourceJarBytes, groupId);
174 if (artifact.getArtifactId().endsWith(".source"))
175 addArtifactToIndex(sources, groupId, artifact);
176 else
177 addArtifactToIndex(binaries, groupId, artifact);
178 }
179 }
180 }
181 }
182
183 // indexes
184 if (mavenGroupIndexes && version != null) {
185 for (String groupId : binaries.keySet()) {
186 RepoUtils.writeGroupIndexes(javaSession, "/", groupId,
187 version, binaries.get(groupId),
188 sources.containsKey(groupId) ? sources.get(groupId)
189 : null);
190 }
191 }
192
193 } catch (Exception e) {
194 throw new SlcException("Cannot wrap distribution " + uri, e);
195 } finally {
196 IOUtils.closeQuietly(zin);
197 JcrUtils.logoutQuietly(distSession);
198 JcrUtils.logoutQuietly(javaSession);
199 }
200 }
201
202 protected Artifact wrapZipEntry(Session javaSession, ZipEntry zentry,
203 byte[] sourceJarBytes, BndWrapper wrapper)
204 throws RepositoryException {
205 ByteArrayOutputStream out = null;
206 ByteArrayInputStream in = null;
207 Node newJarNode;
208 try {
209 out = new ByteArrayOutputStream((int) zentry.getSize());
210 in = new ByteArrayInputStream(sourceJarBytes);
211 wrapper.wrapJar(in, out);
212
213 Artifact artifact = wrapper.getArtifact();
214 newJarNode = RepoUtils.copyBytesAsArtifact(
215 javaSession.getRootNode(), artifact, out.toByteArray());
216 osgiFactory.indexNode(newJarNode);
217 newJarNode.getSession().save();
218 if (log.isDebugEnabled())
219 log.debug("Wrapped jar " + zentry.getName() + " to "
220 + newJarNode.getPath());
221 return artifact;
222 } finally {
223 IOUtils.closeQuietly(in);
224 IOUtils.closeQuietly(out);
225 }
226 }
227
228 protected Artifact importZipEntry(Session javaSession, ZipEntry zentry,
229 byte[] sourceJarBytes, String groupId) throws RepositoryException {
230 ByteArrayInputStream in = null;
231 Node newJarNode;
232 try {
233 in = new ByteArrayInputStream(sourceJarBytes);
234 NameVersion nameVersion = RepoUtils.readNameVersion(in);
235 Artifact artifact = new DefaultArtifact(groupId,
236 nameVersion.getName(), "jar", nameVersion.getVersion());
237 newJarNode = RepoUtils.copyBytesAsArtifact(
238 javaSession.getRootNode(), artifact, sourceJarBytes);
239 osgiFactory.indexNode(newJarNode);
240 newJarNode.getSession().save();
241 if (log.isDebugEnabled())
242 log.debug("Imported OSGi bundle " + zentry.getName() + " to "
243 + newJarNode.getPath());
244 return artifact;
245 } finally {
246 IOUtils.closeQuietly(in);
247 }
248 }
249
250 private void addArtifactToIndex(Map<String, Set<Artifact>> index,
251 String groupId, Artifact artifact) {
252 if (!index.containsKey(groupId))
253 index.put(groupId,
254 new TreeSet<Artifact>(new ArtifactIdComparator()));
255 index.get(groupId).add(artifact);
256 }
257
258 public void setUri(String uri) {
259 this.uri = uri;
260 }
261
262 public void setWrappers(Map<String, BndWrapper> wrappers) {
263 this.wrappers = wrappers;
264 }
265
266 public void setOsgiFactory(OsgiFactory osgiFactory) {
267 this.osgiFactory = osgiFactory;
268 }
269
270 public void setVersion(String version) {
271 this.version = version;
272 }
273
274 public void setLicense(License license) {
275 this.license = license;
276 }
277
278 public void setPathMatcher(PathMatcher pathMatcher) {
279 this.pathMatcher = pathMatcher;
280 }
281
282 public void setIncludes(Map<String, String> includes) {
283 this.includes = includes;
284 }
285
286 public void setExcludes(List<String> excludes) {
287 this.excludes = excludes;
288 }
289
290 public void setMavenGroupIndexes(Boolean mavenGroupIndexes) {
291 this.mavenGroupIndexes = mavenGroupIndexes;
292 }
293
294 }