1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package util.build;
18 
19 import java.io.BufferedInputStream;
20 import java.io.File;
21 import java.io.FileInputStream;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.nio.file.Paths;
27 import java.util.jar.JarEntry;
28 import java.util.jar.JarOutputStream;
29 
30 /**
31  * JarBuildStep takes a single input file and embeds it into a (new) jar file as a single entry.
32  */
33 public class JarBuildStep extends BuildStep {
34 
35     String outputJarEntryName;
36     private final boolean deleteInputFileAfterBuild;
37 
JarBuildStep(BuildFile inputFile, String outputJarEntryName, BuildFile outputJarFile, boolean deleteInputFileAfterBuild)38     public JarBuildStep(BuildFile inputFile, String outputJarEntryName,
39             BuildFile outputJarFile, boolean deleteInputFileAfterBuild) {
40         super(inputFile, outputJarFile);
41         this.outputJarEntryName = outputJarEntryName;
42         this.deleteInputFileAfterBuild = deleteInputFileAfterBuild;
43     }
44 
45     @Override
build()46     boolean build() {
47         if (super.build()) {
48             File tempFile = new File(inputFile.folder, outputJarEntryName);
49             try {
50                 if (!inputFile.fileName.equals(tempFile)) {
51                     copyFile(inputFile.fileName, tempFile);
52                 } else {
53                     tempFile = null;
54                 }
55             } catch (IOException e) {
56                 System.err.println("io exception:"+e.getMessage());
57                 e.printStackTrace();
58                 return false;
59             }
60 
61             File outDir = outputFile.fileName.getParentFile();
62             if (!outDir.exists() && !outDir.mkdirs()) {
63                 System.err.println("failed to create output dir: "
64                         + outDir.getAbsolutePath());
65                 return false;
66             }
67 
68             // Find the input. We'll need to look into the input folder, but check with the
69             // (relative) destination filename (this is effectively removing the inputFile folder
70             // from the entry path in the jar file).
71             Path absoluteInputPath = Paths.get(inputFile.folder.getAbsolutePath())
72                     .resolve(outputJarEntryName);
73             File absoluteInputFile = absoluteInputPath.toFile();
74             if (!absoluteInputFile.exists()) {
75                 // Something went wrong.
76                 throw new IllegalArgumentException(absoluteInputFile.getAbsolutePath());
77             }
78 
79             // Use a JarOutputStream to create the output jar file.
80             File jarOutFile = outputFile.fileName;
81             try (JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(jarOutFile))) {
82                 // Create the JAR entry for the file. Use destFileName, and copy the timestamp
83                 // from the input.
84                 JarEntry entry = new JarEntry(outputJarEntryName);
85                 entry.setTime(absoluteInputFile.lastModified());
86 
87                 // Push the entry. The stream will then be ready to accept content.
88                 jarOut.putNextEntry(entry);
89 
90                 // Copy absoluteInputFile into the jar file.
91                 Files.copy(absoluteInputPath, jarOut);
92 
93                 // Finish the entry.
94                 jarOut.closeEntry();
95 
96                 // (Implicitly close the stream, finishing the jar file.)
97             } catch (Exception e) {
98                 System.err.println("exception in JarBuildStep for " +
99                         outputFile.fileName.getAbsolutePath() + ", " + outputJarEntryName);
100                 e.printStackTrace(System.err);
101                 jarOutFile.delete();
102                 return false;
103             }
104 
105             // Clean up.
106             if (tempFile != null) {
107                 tempFile.delete();
108             }
109             if (deleteInputFileAfterBuild) {
110                 inputFile.fileName.delete();
111             }
112 
113             return true;
114         }
115         return false;
116     }
117 
118     @Override
hashCode()119     public int hashCode() {
120         return inputFile.hashCode() ^ outputFile.hashCode()
121                 ^ outputJarEntryName.hashCode();
122     }
123 
124     @Override
equals(Object obj)125     public boolean equals(Object obj) {
126         if (super.equals(obj)) {
127             JarBuildStep other = (JarBuildStep) obj;
128             return inputFile.equals(other.inputFile)
129                     && outputFile.equals(other.outputFile)
130                     && outputJarEntryName.equals(other.outputJarEntryName);
131 
132         }
133         return false;
134     }
135 
136 }
137