Add .tox/ to .gitignore
[odlparent.git] / karaf / karaf-maven-plugin / src / main / java / org / apache / karaf / tooling / ArchiveMojo.java
1 /*
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
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
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
17  * under the License.
18  */
19 package org.apache.karaf.tooling;
20
21 import java.io.BufferedOutputStream;
22 import java.io.File;
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;
28
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;
44
45 /**
46  * Package a server archive from an assembled server
47  */
48 @Mojo(name = "archive", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.RUNTIME, threadSafe = true)
49 public class ArchiveMojo extends MojoSupport {
50
51     /**
52      * The target directory of the project.
53      */
54     @Parameter(defaultValue="${project.build.directory}")
55     private File destDir;
56
57     /**
58      * The location of the server repository.
59      */
60     @Parameter(defaultValue="${project.build.directory}/assembly")
61     private File targetServerDirectory;
62
63     /**
64      * Path prefix of files in the created archive.
65      */
66     @Parameter(defaultValue="${project.artifactId}-${project.version}")
67     private String pathPrefix;
68
69     /**
70      * Use a path prefix of files in the created archive
71      */
72     @Parameter
73     private boolean usePathPrefix = true;
74
75     /**
76      * The target file to set as the project's artifact.
77      */
78     @Parameter(defaultValue="${project.artifactId}-${project.version}")
79     private File targetFile;
80
81     /**
82      * pack a assembly as a tar.gz archive
83      */
84     @Parameter
85     private boolean archiveTarGz = true;
86
87     /**
88      * pack a assembly as a zip archive
89      */
90     @Parameter
91     private boolean archiveZip = true;
92
93     /**
94      * Whether to attach the resulting assembly to the project as an artifact.
95      */
96     @Parameter(defaultValue="true")
97     private boolean attach = true;
98
99     /**
100      * If supplied, the classifer for the artifact when attached.
101      */
102     @Parameter
103     private String classifier;
104
105     /**
106      * use symbolic links in tar.gz or zip archives
107      *
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.
111      */
112     @Parameter
113     private boolean useSymLinks = false;
114
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);
119         try {
120             //now pack up the server.
121             if(archiveTarGz){
122                 archive("tar.gz");
123             }
124             if(archiveZip) {
125                 archive("zip");
126             }
127         } catch (Exception e) {
128             throw new MojoExecutionException("Could not archive plugin", e);
129         }
130     }
131
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);
136
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");
143                 return;
144             }
145         }
146         if (attach) {
147             projectHelper.attachArtifact(project, artifact1.getType(), classifier, target1);
148         }
149     }
150
151     public File archive(File source, File dest, Artifact artifact) throws //ArchiverException,
152             IOException {
153         String serverName = null;
154         if (targetFile != null) {
155             serverName = targetFile.getName();
156         } else {
157            serverName = artifact.getArtifactId() + "-" + artifact.getVersion();
158         }
159         dest = new File(dest, serverName + "." + artifact.getType());
160         
161         String prefix = "";
162         if (usePathPrefix) {
163                 prefix = pathPrefix.trim();
164                 if( prefix.length() > 0 && !prefix.endsWith("/") ) {
165                     prefix += "/";
166                 }
167         }
168
169         if ("tar.gz".equals(artifact.getType())) {
170             try (
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())
176
177             ) {
178                 tOut.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
179                 tOut.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
180                 for (Path child : children) {
181                     addFileToTarGz(tOut, child, prefix);
182                 }
183             }
184         } else if ("zip".equals(artifact.getType())) {
185             try (
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())
190
191             ) {
192                 for (Path child : children) {
193                     addFileToZip(tOut, child, prefix);
194                 }
195             }
196         } else {
197             throw new IllegalArgumentException("Unknown target type: " + artifact.getType());
198         }
199
200         return dest;
201     }
202
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);
212                 }
213             }
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();
220         }  else {
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);
227                 } else {
228                     tarEntry.setMode(0755);
229                 }
230             }
231             tOut.putArchiveEntry(tarEntry);
232             Files.copy(f, tOut);
233             tOut.closeArchiveEntry();
234         }
235     }
236
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);
246                 }
247             }
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();
255         }  else {
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);
262                 } else {
263                     zipEntry.setUnixMode(0644);
264                 }
265             }
266             tOut.putArchiveEntry(zipEntry);
267             Files.copy(f, tOut);
268             tOut.closeArchiveEntry();
269         }
270     }
271
272 }