]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoUtils.java
Fix bug with missing coma in version ranges
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / RepoUtils.java
1 package org.argeo.slc.repo;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.util.Enumeration;
10 import java.util.Iterator;
11 import java.util.StringTokenizer;
12 import java.util.jar.Attributes;
13 import java.util.jar.JarEntry;
14 import java.util.jar.JarFile;
15 import java.util.jar.JarInputStream;
16 import java.util.jar.JarOutputStream;
17 import java.util.jar.Manifest;
18
19 import javax.jcr.Node;
20 import javax.jcr.RepositoryException;
21
22 import org.apache.commons.io.FilenameUtils;
23 import org.apache.commons.io.IOUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.slc.BasicNameVersion;
27 import org.argeo.slc.NameVersion;
28 import org.argeo.slc.SlcException;
29 import org.argeo.slc.jcr.SlcNames;
30 import org.argeo.slc.jcr.SlcTypes;
31 import org.osgi.framework.Constants;
32 import org.sonatype.aether.artifact.Artifact;
33 import org.sonatype.aether.util.artifact.DefaultArtifact;
34
35 /** Utilities around repo */
36 public class RepoUtils implements SlcNames {
37 private final static Log log = LogFactory.getLog(RepoUtils.class);
38
39 /** Packages a regular sources jar as PDE source. */
40 public static void packagesAsPdeSource(File sourceFile,
41 NameVersion nameVersion, OutputStream out) throws IOException {
42 if (isAlreadyPdeSource(sourceFile)) {
43 FileInputStream in = new FileInputStream(sourceFile);
44 IOUtils.copy(in, out);
45 IOUtils.closeQuietly(in);
46 } else {
47 String sourceSymbolicName = nameVersion.getName() + ".source";
48
49 Manifest sourceManifest = null;
50 sourceManifest = new Manifest();
51 sourceManifest.getMainAttributes().put(
52 Attributes.Name.MANIFEST_VERSION, "1.0");
53 sourceManifest.getMainAttributes().putValue("Bundle-SymbolicName",
54 sourceSymbolicName);
55 sourceManifest.getMainAttributes().putValue("Bundle-Version",
56 nameVersion.getVersion());
57 sourceManifest.getMainAttributes().putValue(
58 "Eclipse-SourceBundle",
59 nameVersion.getName() + ";version="
60 + nameVersion.getVersion());
61 copyJar(sourceFile, out, sourceManifest);
62 }
63 }
64
65 public static byte[] packageAsPdeSource(InputStream sourceJar,
66 NameVersion nameVersion) {
67 String sourceSymbolicName = nameVersion.getName() + ".source";
68
69 Manifest sourceManifest = null;
70 sourceManifest = new Manifest();
71 sourceManifest.getMainAttributes().put(
72 Attributes.Name.MANIFEST_VERSION, "1.0");
73 sourceManifest.getMainAttributes().putValue("Bundle-SymbolicName",
74 sourceSymbolicName);
75 sourceManifest.getMainAttributes().putValue("Bundle-Version",
76 nameVersion.getVersion());
77 sourceManifest.getMainAttributes().putValue("Eclipse-SourceBundle",
78 nameVersion.getName() + ";version=" + nameVersion.getVersion());
79
80 return modifyManifest(sourceJar, sourceManifest);
81 }
82
83 /**
84 * Check whether the file as already been packaged as PDE source, in order
85 * not to mess with Jar signing
86 */
87 private static boolean isAlreadyPdeSource(File sourceFile) {
88 JarInputStream jarInputStream = null;
89
90 try {
91 jarInputStream = new JarInputStream(new FileInputStream(sourceFile));
92
93 Manifest manifest = jarInputStream.getManifest();
94 Iterator<?> it = manifest.getMainAttributes().keySet().iterator();
95 boolean res = false;
96 // containsKey() does not work, iterating...
97 while (it.hasNext())
98 if (it.next().toString().equals("Eclipse-SourceBundle")) {
99 res = true;
100 break;
101 }
102 // boolean res = manifest.getMainAttributes().get(
103 // "Eclipse-SourceBundle") != null;
104 if (res)
105 log.info(sourceFile + " is already a PDE source");
106 return res;
107 } catch (Exception e) {
108 // probably not a jar, skipping
109 if (log.isDebugEnabled())
110 log.debug("Skipping " + sourceFile + " because of "
111 + e.getMessage());
112 return false;
113 } finally {
114 IOUtils.closeQuietly(jarInputStream);
115 }
116 }
117
118 /**
119 * Copy a jar, replacing its manifest with the provided one
120 *
121 * @param manifest
122 * can be null
123 */
124 private static void copyJar(File source, OutputStream out, Manifest manifest)
125 throws IOException {
126 JarFile sourceJar = null;
127 JarOutputStream output = null;
128 try {
129 output = manifest != null ? new JarOutputStream(out, manifest)
130 : new JarOutputStream(out);
131 sourceJar = new JarFile(source);
132
133 entries: for (Enumeration<?> entries = sourceJar.entries(); entries
134 .hasMoreElements();) {
135 JarEntry entry = (JarEntry) entries.nextElement();
136 if (manifest != null
137 && entry.getName().equals("META-INF/MANIFEST.MF"))
138 continue entries;
139
140 InputStream entryStream = sourceJar.getInputStream(entry);
141 JarEntry newEntry = new JarEntry(entry.getName());
142 // newEntry.setMethod(JarEntry.DEFLATED);
143 output.putNextEntry(newEntry);
144 IOUtils.copy(entryStream, output);
145 }
146 } finally {
147 IOUtils.closeQuietly(output);
148 try {
149 if (sourceJar != null)
150 sourceJar.close();
151 } catch (IOException e) {
152 // silent
153 }
154 }
155 }
156
157 /** Copy a jar changing onlythe manifest */
158 public static void copyJar(InputStream in, OutputStream out,
159 Manifest manifest) {
160 JarInputStream jarIn = null;
161 JarOutputStream jarOut = null;
162 try {
163 jarIn = new JarInputStream(in);
164 jarOut = new JarOutputStream(out, manifest);
165 JarEntry jarEntry = null;
166 while ((jarEntry = jarIn.getNextJarEntry()) != null) {
167 jarOut.putNextEntry(jarEntry);
168 IOUtils.copy(jarIn, jarOut);
169 jarIn.closeEntry();
170 jarOut.closeEntry();
171 }
172 } catch (IOException e) {
173 throw new SlcException("Could not copy jar with MANIFEST "
174 + manifest.getMainAttributes(), e);
175 } finally {
176 IOUtils.closeQuietly(jarIn);
177 IOUtils.closeQuietly(jarOut);
178 }
179 }
180
181 /** Reads a jar file, modify its manifest */
182 public static byte[] modifyManifest(InputStream in, Manifest manifest) {
183 ByteArrayOutputStream out = new ByteArrayOutputStream(200 * 1024);
184 try {
185 copyJar(in, out, manifest);
186 return out.toByteArray();
187 } finally {
188 IOUtils.closeQuietly(out);
189 }
190 }
191
192 /** Read the OSGi {@link NameVersion} */
193 public static NameVersion readNameVersion(Artifact artifact) {
194 File artifactFile = artifact.getFile();
195 if (artifact.getExtension().equals("pom")) {
196 // hack to process jars which weirdly appear as POMs
197 File jarFile = new File(artifactFile.getParentFile(),
198 FilenameUtils.getBaseName(artifactFile.getPath()) + ".jar");
199 if (jarFile.exists()) {
200 log.warn("Use " + jarFile + " instead of " + artifactFile
201 + " for " + artifact);
202 artifactFile = jarFile;
203 }
204 }
205 return readNameVersion(artifactFile);
206 }
207
208 /** Read the OSGi {@link NameVersion} */
209 public static NameVersion readNameVersion(File artifactFile) {
210 JarInputStream jarInputStream = null;
211 try {
212 jarInputStream = new JarInputStream(new FileInputStream(
213 artifactFile));
214 return readNameVersion(jarInputStream.getManifest());
215 } catch (Exception e) {
216 // probably not a jar, skipping
217 if (log.isDebugEnabled()) {
218 log.debug("Skipping " + artifactFile + " because of " + e);
219 // e.printStackTrace();
220 }
221 } finally {
222 IOUtils.closeQuietly(jarInputStream);
223 }
224 return null;
225 }
226
227 /** Read the OSGi {@link NameVersion} */
228 public static NameVersion readNameVersion(Manifest manifest) {
229 BasicNameVersion nameVersion = new BasicNameVersion();
230 nameVersion.setName(manifest.getMainAttributes().getValue(
231 Constants.BUNDLE_SYMBOLICNAME));
232
233 // Skip additional specs such as
234 // ; singleton:=true
235 if (nameVersion.getName().indexOf(';') > -1) {
236 nameVersion
237 .setName(new StringTokenizer(nameVersion.getName(), " ;")
238 .nextToken());
239 }
240
241 nameVersion.setVersion(manifest.getMainAttributes().getValue(
242 Constants.BUNDLE_VERSION));
243
244 return nameVersion;
245 }
246
247 /*
248 * DATA MODEL
249 */
250 /** The artifact described by this node */
251 public static Artifact asArtifact(Node node) throws RepositoryException {
252 if (node.isNodeType(SlcTypes.SLC_ARTIFACT_VERSION_BASE)) {
253 // FIXME update data model to store packaging at this level
254 String extension = "jar";
255 return new DefaultArtifact(node.getProperty(SLC_GROUP_ID)
256 .getString(),
257 node.getProperty(SLC_ARTIFACT_ID).getString(), extension,
258 node.getProperty(SLC_ARTIFACT_VERSION).getString());
259 } else if (node.isNodeType(SlcTypes.SLC_ARTIFACT)) {
260 return new DefaultArtifact(node.getProperty(SLC_GROUP_ID)
261 .getString(),
262 node.getProperty(SLC_ARTIFACT_ID).getString(), node
263 .getProperty(SLC_ARTIFACT_CLASSIFIER).getString(),
264 node.getProperty(SLC_ARTIFACT_EXTENSION).getString(), node
265 .getProperty(SLC_ARTIFACT_VERSION).getString());
266 } else {
267 throw new SlcException("Unsupported node type for " + node);
268 }
269 }
270
271 private RepoUtils() {
272 }
273 }