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