PageRenderTime 29ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/container-build/src/main/java/com/atlassian/plugin/remotable/container/build/PackageScanningShader.java

https://bitbucket.org/rodogu/remotable-plugins
Java | 220 lines | 192 code | 15 blank | 13 comment | 27 complexity | 4d8c593ef4125a52bd7cfd2ed522d360 MD5 | raw file
  1. package com.atlassian.plugin.remotable.container.build;
  2. import org.apache.commons.io.FileUtils;
  3. import org.apache.commons.io.IOUtils;
  4. import org.apache.maven.plugin.MojoExecutionException;
  5. import org.apache.maven.plugins.shade.DefaultShader;
  6. import org.apache.maven.plugins.shade.Shader;
  7. import org.apache.maven.plugins.shade.filter.Filter;
  8. import org.apache.maven.plugins.shade.relocation.Relocator;
  9. import org.apache.maven.plugins.shade.resource.ResourceTransformer;
  10. import org.codehaus.plexus.component.annotations.Component;
  11. import org.codehaus.plexus.logging.AbstractLogEnabled;
  12. import org.dom4j.DocumentFactory;
  13. import org.dom4j.Element;
  14. import org.dom4j.io.OutputFormat;
  15. import org.dom4j.io.XMLWriter;
  16. import org.twdata.pkgscanner.DefaultOsgiVersionConverter;
  17. import org.twdata.pkgscanner.ExportPackage;
  18. import org.twdata.pkgscanner.PackageScanner;
  19. import org.yaml.snakeyaml.Yaml;
  20. import java.io.*;
  21. import java.net.URL;
  22. import java.net.URLClassLoader;
  23. import java.util.*;
  24. import java.util.jar.JarEntry;
  25. import java.util.jar.JarFile;
  26. import java.util.jar.Manifest;
  27. import java.util.zip.ZipEntry;
  28. import java.util.zip.ZipInputStream;
  29. import java.util.zip.ZipOutputStream;
  30. import static org.twdata.pkgscanner.PackageScanner.*;
  31. /**
  32. * A shader impl that will scan the result and add a package export report file to it
  33. */
  34. @Component( role = Shader.class, hint = "pkgscanner" )
  35. public class PackageScanningShader
  36. extends AbstractLogEnabled implements Shader
  37. {
  38. private final DefaultShader delegate = new DefaultShader();
  39. private final DefaultOsgiVersionConverter versionConverter = new
  40. DefaultOsgiVersionConverter();
  41. @Override
  42. public void shade( Set<File> toShadeJars, File uberJar, List<Filter> filters, List<Relocator> relocators,
  43. List<ResourceTransformer> resourceTransformers) throws IOException,
  44. MojoExecutionException
  45. {
  46. delegate.enableLogging(getLogger());
  47. delegate.shade(toShadeJars, uberJar, filters, relocators, resourceTransformers);
  48. Yaml yaml = new Yaml();
  49. File yamlFile = new File(uberJar.getParentFile(), "classes/pkgscanner-config.yaml");
  50. Map<String, Object> config = (Map<String, Object>) yaml.load(
  51. FileUtils.readFileToString(yamlFile));
  52. Map<String,Collection<String>> packageIncludes = (Map<String, Collection<String>>) config.get("package_includes");
  53. Collection<String> includes = packageIncludes.get("include");
  54. Collection<String> excludes = packageIncludes.get("exclude");
  55. Map<String,String> versions = getScannedVersions(toShadeJars);
  56. for (Map<String,String> entry : (Collection<Map<String,String>>) config.get("package_versions"))
  57. {
  58. versions.put(entry.get("package"), versionConverter.getVersion(entry.get("version")));
  59. }
  60. Collection < ExportPackage > exports = new PackageScanner()
  61. .select(
  62. jars(include("*.jar"), exclude()),
  63. packages(
  64. include(includes.toArray(new String[includes.size()])),
  65. exclude(excludes.toArray(new String[excludes.size()]))))
  66. .withMappings(versions)
  67. .useClassLoader(new URLClassLoader(new URL[]{uberJar.toURI().toURL()},
  68. null))
  69. .scan();
  70. Element root = DocumentFactory.getInstance().createDocument().addElement("exports");
  71. for (ExportPackage export : exports)
  72. {
  73. root.addElement("export")
  74. .addAttribute("package", export.getPackageName())
  75. .addAttribute("version", export.getVersion())
  76. .addAttribute("location", export.getLocation().getName());
  77. }
  78. ByteArrayOutputStream bout = new ByteArrayOutputStream();
  79. new XMLWriter(bout, OutputFormat.createPrettyPrint()).write(root.getDocument());
  80. addFileToExistingZip(uberJar, "package-scanner-exports.xml",
  81. new ByteArrayInputStream(bout.toByteArray()));
  82. }
  83. private Map<String, String> getScannedVersions(Set<File> toShadeJars)
  84. {
  85. Map<String, String> versions = new HashMap<String, String>();
  86. for (File file : toShadeJars) {
  87. JarFile jarFile = null;
  88. try
  89. {
  90. jarFile = new JarFile(file);
  91. Manifest mf = jarFile.getManifest();
  92. if (mf != null && mf.getMainAttributes() != null)
  93. {
  94. String version = mf.getMainAttributes().getValue("Bundle-Version");
  95. if (version == null) {
  96. version = mf.getMainAttributes().getValue("Specification-Version");
  97. }
  98. if (version == null) {
  99. version = mf.getMainAttributes().getValue("Implementation-Version");
  100. }
  101. if (version == null) {
  102. version = determineVersionFromMavenProperties(jarFile);
  103. }
  104. if (version != null)
  105. {
  106. String osgiVersion = versionConverter.getVersion(version);
  107. for (Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements(); ) {
  108. JarEntry entry = e.nextElement();
  109. if (entry.isDirectory())
  110. {
  111. versions.put(entry.getName().substring(0, entry.getName().length() - 1).replace(
  112. '/', '.'), osgiVersion);
  113. }
  114. }
  115. }
  116. }
  117. }
  118. catch (IOException e)
  119. {
  120. getLogger().error("Unable to scan shaded jar " + file.getName(), e);
  121. }
  122. }
  123. return versions;
  124. }
  125. private String determineVersionFromMavenProperties(JarFile jarFile)
  126. {
  127. for (Enumeration<JarEntry> e = jarFile.entries(); e.hasMoreElements(); ) {
  128. JarEntry entry = e.nextElement();
  129. if (entry.getName().endsWith("/pom.properties")) {
  130. InputStream in = null;
  131. try {
  132. in = jarFile.getInputStream(entry);
  133. Properties props = new Properties();
  134. props.load(in);
  135. return props.getProperty("version");
  136. }
  137. catch (IOException ex) {
  138. getLogger().debug("Exception reading maven properties file", ex);
  139. }
  140. finally {
  141. if (in != null) {
  142. try {
  143. in.close();
  144. } catch (IOException ex) {
  145. // ignore
  146. }
  147. }
  148. }
  149. }
  150. }
  151. return null;
  152. }
  153. public static void addFileToExistingZip(File zipFile,
  154. String path, InputStream inputStream) throws IOException {
  155. // get a temp file
  156. File tempFile = File.createTempFile(zipFile.getName(), null);
  157. // delete it, otherwise you cannot rename your existing zip to it.
  158. tempFile.delete();
  159. FileUtils.moveFile(zipFile,tempFile);
  160. if (!tempFile.exists())
  161. {
  162. throw new RuntimeException("could not move the file "+zipFile.getAbsolutePath()+" to "+tempFile.getAbsolutePath());
  163. }
  164. byte[] buf = new byte[1024];
  165. ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
  166. ZipOutputStream out = null;
  167. try
  168. {
  169. out = new ZipOutputStream(new FileOutputStream(zipFile));
  170. ZipEntry entry = zin.getNextEntry();
  171. while (entry != null) {
  172. String name = entry.getName();
  173. if (path.equals(name)) {
  174. break;
  175. }
  176. // Add ZIP entry to output stream.
  177. out.putNextEntry(new ZipEntry(name));
  178. // Transfer bytes from the ZIP file to the output file
  179. int len;
  180. while ((len = zin.read(buf)) > 0) {
  181. out.write(buf, 0, len);
  182. }
  183. entry = zin.getNextEntry();
  184. }
  185. // Close the streams
  186. zin.close();
  187. // Add ZIP entry to output stream.
  188. out.putNextEntry(new ZipEntry(path));
  189. // Transfer bytes from the file to the ZIP file
  190. int len;
  191. while ((len = inputStream.read(buf)) > 0) {
  192. out.write(buf, 0, len);
  193. }
  194. // Complete the entry
  195. out.closeEntry();
  196. }
  197. finally
  198. {
  199. // Complete the ZIP file
  200. IOUtils.closeQuietly(out);
  201. IOUtils.closeQuietly(inputStream);
  202. tempFile.delete();
  203. }
  204. }
  205. }