package org.carlspring.strongbox.artifact.generator; import org.carlspring.commons.encryption.EncryptionAlgorithmsEnum; import org.carlspring.commons.io.MultipleDigestInputStream; import org.carlspring.commons.io.MultipleDigestOutputStream; import org.carlspring.commons.io.RandomInputStream; import org.carlspring.maven.commons.model.ModelWriter; import org.carlspring.maven.commons.util.ArtifactUtils; import org.carlspring.strongbox.resource.ResourceCloser; import org.carlspring.strongbox.util.MessageDigestUtils; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.security.NoSuchAlgorithmException; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.metadata.Metadata; import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer; import org.apache.maven.model.Model; import org.codehaus.plexus.util.WriterFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author mtodorov */ public class MavenArtifactGenerator { private static final Logger logger = LoggerFactory.getLogger(MavenArtifactGenerator.class); public static final String PACKAGING_JAR = "jar"; private String basedir; public MavenArtifactGenerator() { } public MavenArtifactGenerator(String basedir) { this.basedir = basedir; } public MavenArtifactGenerator(File basedir) { this.basedir = basedir.getAbsolutePath(); } public void generate(String gavtc, String packaging, String... versions) throws IOException, XmlPullParserException, NoSuchAlgorithmException { if (packaging == null) { packaging = PACKAGING_JAR; } for (String version : versions) { Artifact artifact = ArtifactUtils.getArtifactFromGAVTC(gavtc); artifact.setVersion(version); artifact.setFile(new File(getBasedir() + "/" + ArtifactUtils.convertArtifactToPath(artifact))); generate(artifact, packaging); } } public void generate(String gavtc, String... versions) throws IOException, XmlPullParserException, NoSuchAlgorithmException { for (String version : versions) { Artifact artifact = ArtifactUtils.getArtifactFromGAVTC(gavtc); artifact.setVersion(version); artifact.setFile(new File(getBasedir() + "/" + ArtifactUtils.convertArtifactToPath(artifact))); generate(artifact); } } public void generate(Artifact artifact) throws IOException, XmlPullParserException, NoSuchAlgorithmException { generatePom(artifact, PACKAGING_JAR); createArchive(artifact); } public void generate(Artifact artifact, String packaging) throws IOException, XmlPullParserException, NoSuchAlgorithmException { generatePom(artifact, packaging); createArchive(artifact); } public void createArchive(Artifact artifact) throws NoSuchAlgorithmException, IOException { ZipOutputStream zos = null; File artifactFile = null; try { artifactFile = new File(basedir, ArtifactUtils.convertArtifactToPath(artifact)); // Make sure the artifact's parent directory exists before writing the model. //noinspection ResultOfMethodCallIgnored artifactFile.getParentFile().mkdirs(); zos = new ZipOutputStream(new FileOutputStream(artifactFile)); createMavenPropertiesFile(artifact, zos); addMavenPomFile(artifact, zos); createRandomSizeFile(zos); } finally { ResourceCloser.close(zos, logger); generateChecksumsForArtifact(artifactFile); } } protected void createMetadata(Metadata metadata, String metadataPath) throws NoSuchAlgorithmException, IOException { OutputStream os = null; Writer writer = null; File metadataFile = null; try { metadataFile = new File(basedir, metadataPath); if (metadataFile.exists()) { metadataFile.delete(); } // Make sure the artifact's parent directory exists before writing // the model. // noinspection ResultOfMethodCallIgnored metadataFile.getParentFile().mkdirs(); os = new MultipleDigestOutputStream(metadataFile, new FileOutputStream(metadataFile)); writer = WriterFactory.newXmlWriter(os); MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer(); mappingWriter.write(writer, metadata); os.flush(); } finally { ResourceCloser.close(os, logger); generateChecksumsForArtifact(metadataFile); } } private void addMavenPomFile(Artifact artifact, ZipOutputStream zos) throws IOException { final Artifact pomArtifact = ArtifactUtils.getPOMArtifact(artifact); File pomFile = new File(basedir, ArtifactUtils.convertArtifactToPath(pomArtifact)); ZipEntry ze = new ZipEntry("META-INF/maven/" + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" + "pom.xml"); zos.putNextEntry(ze); try (FileInputStream fis = new FileInputStream(pomFile)) { byte[] buffer = new byte[4096]; int len; while ((len = fis.read(buffer)) > 0) { zos.write(buffer, 0, len); } } finally { zos.closeEntry(); } } private void createMavenPropertiesFile(Artifact artifact, ZipOutputStream zos) throws IOException { ZipEntry ze = new ZipEntry("META-INF/maven/" + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" + "pom.properties"); zos.putNextEntry(ze); Properties properties = new Properties(); properties.setProperty("groupId", artifact.getGroupId()); properties.setProperty("artifactId", artifact.getArtifactId()); properties.setProperty("version", artifact.getVersion()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); properties.store(baos, null); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); byte[] buffer = new byte[4096]; int len; while ((len = bais.read(buffer)) > 0) { zos.write(buffer, 0, len); } bais.close(); zos.closeEntry(); } private void createRandomSizeFile(ZipOutputStream zos) throws IOException { ZipEntry ze = new ZipEntry("random-size-file"); zos.putNextEntry(ze); RandomInputStream ris = new RandomInputStream(true, 1000000); byte[] buffer = new byte[4096]; int len; while ((len = ris.read(buffer)) > 0) { zos.write(buffer, 0, len); } ris.close(); zos.closeEntry(); } public void generatePom(Artifact artifact, String packaging) throws IOException, XmlPullParserException, NoSuchAlgorithmException { final Artifact pomArtifact = ArtifactUtils.getPOMArtifact(artifact); File pomFile = new File(basedir, ArtifactUtils.convertArtifactToPath(pomArtifact)); // Make sure the artifact's parent directory exists before writing the model. //noinspection ResultOfMethodCallIgnored pomFile.getParentFile().mkdirs(); Model model = new Model(); model.setGroupId(artifact.getGroupId()); model.setArtifactId(artifact.getArtifactId()); model.setVersion(artifact.getVersion()); model.setPackaging(packaging); logger.debug("Generating pom file for " + artifact.toString() + "..."); ModelWriter writer = new ModelWriter(model, pomFile); writer.write(); generateChecksumsForArtifact(pomFile); } private void generateChecksumsForArtifact(File artifactFile) throws NoSuchAlgorithmException, IOException { InputStream is = new FileInputStream(artifactFile); MultipleDigestInputStream mdis = new MultipleDigestInputStream(is); int size = 4096; byte[] bytes = new byte[size]; //noinspection StatementWithEmptyBody while (mdis.read(bytes, 0, size) != -1); mdis.close(); String md5 = mdis.getMessageDigestAsHexadecimalString(EncryptionAlgorithmsEnum.MD5.getAlgorithm()); String sha1 = mdis.getMessageDigestAsHexadecimalString(EncryptionAlgorithmsEnum.SHA1.getAlgorithm()); MessageDigestUtils.writeChecksum(artifactFile, EncryptionAlgorithmsEnum.MD5.getExtension(), md5); MessageDigestUtils.writeChecksum(artifactFile, EncryptionAlgorithmsEnum.SHA1.getExtension(), sha1); } public String getBasedir() { return basedir; } public void setBasedir(String basedir) { this.basedir = basedir; } }