2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
19 package org.apache.karaf.tooling;
21 import java.io.BufferedOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.nio.file.DirectoryStream;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
29 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
30 import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
31 import org.apache.commons.compress.archivers.tar.TarConstants;
32 import org.apache.commons.compress.archivers.zip.UnixStat;
33 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
34 import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
35 import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
36 import org.apache.karaf.tooling.utils.MojoSupport;
37 import org.apache.maven.artifact.Artifact;
38 import org.apache.maven.plugin.MojoExecutionException;
39 import org.apache.maven.plugin.MojoFailureException;
40 import org.apache.maven.plugins.annotations.LifecyclePhase;
41 import org.apache.maven.plugins.annotations.Mojo;
42 import org.apache.maven.plugins.annotations.Parameter;
43 import org.apache.maven.plugins.annotations.ResolutionScope;
46 * Package a server archive from an assembled server
48 @Mojo(name = "archive", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true)
49 public class ArchiveMojo extends MojoSupport {
52 * The target directory of the project.
54 @Parameter(defaultValue="${project.build.directory}")
58 * The location of the server repository.
60 @Parameter(defaultValue="${project.build.directory}/assembly")
61 private File targetServerDirectory;
64 * Path prefix of files in the created archive.
66 @Parameter(defaultValue="${project.artifactId}-${project.version}")
67 private String pathPrefix;
70 * Use a path prefix of files in the created archive
73 private boolean usePathPrefix = true;
76 * The target file to set as the project's artifact.
78 @Parameter(defaultValue="${project.artifactId}-${project.version}")
79 private File targetFile;
82 * pack a assembly as a tar.gz archive
85 private boolean archiveTarGz = true;
88 * pack a assembly as a zip archive
91 private boolean archiveZip = true;
94 * Whether to attach the resulting assembly to the project as an artifact.
96 @Parameter(defaultValue="true")
97 private boolean attach = true;
100 * If supplied, the classifer for the artifact when attached.
103 private String classifier;
106 * use symbolic links in tar.gz or zip archives
108 * Symbolic links are not very well supported by windows Platform.
109 * At least, is does not work on WinXP + NTFS, so do not include them
110 * for now. So the default is false.
113 private boolean useSymLinks = false;
115 public void execute() throws MojoExecutionException, MojoFailureException {
116 getLog().debug("Setting artifact file: " + targetFile);
117 org.apache.maven.artifact.Artifact artifact = project.getArtifact();
118 artifact.setFile(targetFile);
120 //now pack up the server.
127 } catch (Exception e) {
128 throw new MojoExecutionException("Could not archive plugin", e);
132 @SuppressWarnings("deprecation")
133 private void archive(String type) throws IOException {
134 Artifact artifact1 = factory.createArtifactWithClassifier(project.getArtifact().getGroupId(), project.getArtifact().getArtifactId(), project.getArtifact().getVersion(), type, "bin");
135 File target1 = archive(targetServerDirectory, destDir, artifact1);
137 // artifact1 is created with explicit classifier "bin", which is dropped below when attachArtifact is called
138 // which means we can't use artifact1.equals(artifact) directly with artifact1
139 Artifact artifact2 = factory.createArtifact(artifact1.getGroupId(), artifact1.getArtifactId(), artifact1.getVersion(), artifact1.getScope(), artifact1.getType());
140 for (Artifact artifact : project.getAttachedArtifacts()) {
141 if (artifact2.equals(artifact)) {
142 getLog().debug("Artifact " + artifact2 + " already attached");
147 projectHelper.attachArtifact(project, artifact1.getType(), classifier, target1);
151 public File archive(File source, File dest, Artifact artifact) throws //ArchiverException,
153 String serverName = null;
154 if (targetFile != null) {
155 serverName = targetFile.getName();
157 serverName = artifact.getArtifactId() + "-" + artifact.getVersion();
159 dest = new File(dest, serverName + "." + artifact.getType());
163 prefix = pathPrefix.trim();
164 if( prefix.length() > 0 && !prefix.endsWith("/") ) {
169 if ("tar.gz".equals(artifact.getType())) {
171 OutputStream fOut = Files.newOutputStream(dest.toPath());
172 OutputStream bOut = new BufferedOutputStream(fOut);
173 OutputStream gzOut = new GzipCompressorOutputStream(bOut);
174 TarArchiveOutputStream tOut = new TarArchiveOutputStream(gzOut);
175 DirectoryStream<Path> children = Files.newDirectoryStream(source.toPath())
178 tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
179 tOut.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
180 for (Path child : children) {
181 addFileToTarGz(tOut, child, prefix);
184 } else if ("zip".equals(artifact.getType())) {
186 OutputStream fOut = Files.newOutputStream(dest.toPath());
187 OutputStream bOut = new BufferedOutputStream(fOut);
188 ZipArchiveOutputStream tOut = new ZipArchiveOutputStream(bOut);
189 DirectoryStream<Path> children = Files.newDirectoryStream(source.toPath())
192 for (Path child : children) {
193 addFileToZip(tOut, child, prefix);
197 throw new IllegalArgumentException("Unknown target type: " + artifact.getType());
203 private void addFileToTarGz(TarArchiveOutputStream tOut, Path f, String base) throws IOException {
204 if (Files.isDirectory(f)) {
205 String entryName = base + f.getFileName().toString() + "/";
206 TarArchiveEntry tarEntry = new TarArchiveEntry(entryName);
207 tOut.putArchiveEntry(tarEntry);
208 tOut.closeArchiveEntry();
209 try (DirectoryStream<Path> children = Files.newDirectoryStream(f)) {
210 for (Path child : children) {
211 addFileToTarGz(tOut, child, entryName);
214 } else if (useSymLinks && Files.isSymbolicLink(f)) {
215 String entryName = base + f.getFileName().toString();
216 TarArchiveEntry tarEntry = new TarArchiveEntry(entryName, TarConstants.LF_SYMLINK);
217 tarEntry.setLinkName(Files.readSymbolicLink(f).toString());
218 tOut.putArchiveEntry(tarEntry);
219 tOut.closeArchiveEntry();
221 String entryName = base + f.getFileName().toString();
222 TarArchiveEntry tarEntry = new TarArchiveEntry(entryName);
223 tarEntry.setSize(Files.size(f));
224 if (entryName.contains("/bin/") || (!usePathPrefix && entryName.startsWith("bin/"))) {
225 if (entryName.endsWith(".bat")) {
226 tarEntry.setMode(0644);
228 tarEntry.setMode(0755);
231 tOut.putArchiveEntry(tarEntry);
233 tOut.closeArchiveEntry();
237 private void addFileToZip(ZipArchiveOutputStream tOut, Path f, String base) throws IOException {
238 if (Files.isDirectory(f)) {
239 String entryName = base + f.getFileName().toString() + "/";
240 ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
241 tOut.putArchiveEntry(zipEntry);
242 tOut.closeArchiveEntry();
243 try (DirectoryStream<Path> children = Files.newDirectoryStream(f)) {
244 for (Path child : children) {
245 addFileToZip(tOut, child, entryName);
248 } else if (useSymLinks && Files.isSymbolicLink(f)) {
249 String entryName = base + f.getFileName().toString();
250 ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
251 zipEntry.setUnixMode(UnixStat.LINK_FLAG | UnixStat.DEFAULT_FILE_PERM);
252 tOut.putArchiveEntry(zipEntry);
253 tOut.write(Files.readSymbolicLink(f).toString().getBytes());
254 tOut.closeArchiveEntry();
256 String entryName = base + f.getFileName().toString();
257 ZipArchiveEntry zipEntry = new ZipArchiveEntry(entryName);
258 zipEntry.setSize(Files.size(f));
259 if (entryName.contains("/bin/") || (!usePathPrefix && entryName.startsWith("bin"))) {
260 if (!entryName.endsWith(".bat")) {
261 zipEntry.setUnixMode(0755);
263 zipEntry.setUnixMode(0644);
266 tOut.putArchiveEntry(zipEntry);
268 tOut.closeArchiveEntry();