5601 |
01 Apr 11 |
nicklas |
1 |
/** |
5601 |
01 Apr 11 |
nicklas |
$Id$ |
5601 |
01 Apr 11 |
nicklas |
3 |
|
5601 |
01 Apr 11 |
nicklas |
Copyright (C) 2011 Nicklas Nordborg |
5601 |
01 Apr 11 |
nicklas |
5 |
|
5601 |
01 Apr 11 |
nicklas |
This file is part of BASE - BioArray Software Environment. |
5601 |
01 Apr 11 |
nicklas |
Available at http://base.thep.lu.se/ |
5601 |
01 Apr 11 |
nicklas |
8 |
|
5601 |
01 Apr 11 |
nicklas |
BASE is free software; you can redistribute it and/or |
5601 |
01 Apr 11 |
nicklas |
modify it under the terms of the GNU General Public License |
5601 |
01 Apr 11 |
nicklas |
as published by the Free Software Foundation; either version 3 |
5601 |
01 Apr 11 |
nicklas |
of the License, or (at your option) any later version. |
5601 |
01 Apr 11 |
nicklas |
13 |
|
5601 |
01 Apr 11 |
nicklas |
BASE is distributed in the hope that it will be useful, |
5601 |
01 Apr 11 |
nicklas |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
5601 |
01 Apr 11 |
nicklas |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
5601 |
01 Apr 11 |
nicklas |
GNU General Public License for more details. |
5601 |
01 Apr 11 |
nicklas |
18 |
|
5601 |
01 Apr 11 |
nicklas |
You should have received a copy of the GNU General Public License |
5601 |
01 Apr 11 |
nicklas |
along with BASE. If not, see <http://www.gnu.org/licenses/>. |
5601 |
01 Apr 11 |
nicklas |
21 |
*/ |
5603 |
08 Apr 11 |
nicklas |
22 |
package net.sf.basedb.util.extensions.manager.processor; |
5601 |
01 Apr 11 |
nicklas |
23 |
|
5601 |
01 Apr 11 |
nicklas |
24 |
import java.io.File; |
5601 |
01 Apr 11 |
nicklas |
25 |
import java.io.FileInputStream; |
5601 |
01 Apr 11 |
nicklas |
26 |
import java.io.FileNotFoundException; |
5601 |
01 Apr 11 |
nicklas |
27 |
import java.io.FileOutputStream; |
5601 |
01 Apr 11 |
nicklas |
28 |
import java.io.OutputStream; |
5601 |
01 Apr 11 |
nicklas |
29 |
import java.util.regex.Matcher; |
5601 |
01 Apr 11 |
nicklas |
30 |
import java.util.regex.Pattern; |
5601 |
01 Apr 11 |
nicklas |
31 |
import java.util.zip.ZipEntry; |
5601 |
01 Apr 11 |
nicklas |
32 |
import java.util.zip.ZipInputStream; |
5601 |
01 Apr 11 |
nicklas |
33 |
|
5601 |
01 Apr 11 |
nicklas |
34 |
import net.sf.basedb.util.FileUtil; |
5603 |
08 Apr 11 |
nicklas |
35 |
import net.sf.basedb.util.extensions.manager.ExtensionsFile; |
5603 |
08 Apr 11 |
nicklas |
36 |
import net.sf.basedb.util.extensions.manager.ExtensionsFileProcessor; |
5603 |
08 Apr 11 |
nicklas |
37 |
import net.sf.basedb.util.extensions.manager.ExtensionsManager; |
5603 |
08 Apr 11 |
nicklas |
38 |
import net.sf.basedb.util.extensions.manager.ProcessResults; |
5602 |
07 Apr 11 |
nicklas |
39 |
import net.sf.basedb.util.extensions.manager.ExtensionsFile.WriteableExtensionsFile; |
5603 |
08 Apr 11 |
nicklas |
40 |
import net.sf.basedb.util.extensions.manager.filter.ValidAndNewOrModifiedFilter; |
5601 |
01 Apr 11 |
nicklas |
41 |
|
5601 |
01 Apr 11 |
nicklas |
42 |
/** |
5601 |
01 Apr 11 |
nicklas |
A file processor implementation that extracts resources from JAR files. |
5601 |
01 Apr 11 |
nicklas |
The main target directory must be specified when an instance is constructed. |
5601 |
01 Apr 11 |
nicklas |
Each processed JAR file is extracted into a subdirectory with the same name |
6021 |
19 Mar 12 |
nicklas |
as the JAR file. Existing files are always overwritten. |
5601 |
01 Apr 11 |
nicklas |
<p> |
5601 |
01 Apr 11 |
nicklas |
48 |
|
5601 |
01 Apr 11 |
nicklas |
The filter (in the form of a regular expressions pattern) can be |
5601 |
01 Apr 11 |
nicklas |
specified to limit which files are extracted from the JAR file. |
5601 |
01 Apr 11 |
nicklas |
The filter is also used to re-write target file names if they |
5601 |
01 Apr 11 |
nicklas |
need to be different from the file names in the JAR file. |
5603 |
08 Apr 11 |
nicklas |
<p> |
5603 |
08 Apr 11 |
nicklas |
54 |
|
5603 |
08 Apr 11 |
nicklas |
Note! It is recommended that this processor is paired with a |
5603 |
08 Apr 11 |
nicklas |
{@link ValidAndNewOrModifiedFilter} since it is usually no |
5603 |
08 Apr 11 |
nicklas |
point in extracting resources from invalid extensions. |
5601 |
01 Apr 11 |
nicklas |
58 |
|
5601 |
01 Apr 11 |
nicklas |
@author Nicklas |
5601 |
01 Apr 11 |
nicklas |
@since 3.0 |
5601 |
01 Apr 11 |
nicklas |
@base.modified $Date$ |
5601 |
01 Apr 11 |
nicklas |
62 |
*/ |
5601 |
01 Apr 11 |
nicklas |
63 |
public class ExtractResourcesProcessor |
5601 |
01 Apr 11 |
nicklas |
64 |
implements ExtensionsFileProcessor |
5601 |
01 Apr 11 |
nicklas |
65 |
{ |
5601 |
01 Apr 11 |
nicklas |
66 |
|
6444 |
09 Apr 14 |
nicklas |
67 |
private static final org.slf4j.Logger log = |
6444 |
09 Apr 14 |
nicklas |
68 |
org.slf4j.LoggerFactory.getLogger(ExtractResourcesProcessor.class); |
5601 |
01 Apr 11 |
nicklas |
69 |
|
5601 |
01 Apr 11 |
nicklas |
70 |
private final File mainDir; |
5601 |
01 Apr 11 |
nicklas |
71 |
private final Pattern filter; |
5601 |
01 Apr 11 |
nicklas |
72 |
private final String replacement; |
5602 |
07 Apr 11 |
nicklas |
73 |
private final ProcessResults results; |
5601 |
01 Apr 11 |
nicklas |
74 |
|
5603 |
08 Apr 11 |
nicklas |
75 |
private int numFiles; |
5603 |
08 Apr 11 |
nicklas |
76 |
private int numError; |
5603 |
08 Apr 11 |
nicklas |
77 |
private int numTotalExtracted; |
5603 |
08 Apr 11 |
nicklas |
78 |
|
5601 |
01 Apr 11 |
nicklas |
79 |
/** |
5601 |
01 Apr 11 |
nicklas |
Create a new processor. |
5601 |
01 Apr 11 |
nicklas |
81 |
|
5601 |
01 Apr 11 |
nicklas |
@param mainDir The main directory to where the resources should be extracted |
5601 |
01 Apr 11 |
nicklas |
83 |
*/ |
5605 |
12 Apr 11 |
nicklas |
84 |
public ExtractResourcesProcessor(File mainDir, ProcessResults results) |
5601 |
01 Apr 11 |
nicklas |
85 |
{ |
5605 |
12 Apr 11 |
nicklas |
86 |
this(mainDir, null, null, results); |
5601 |
01 Apr 11 |
nicklas |
87 |
} |
5601 |
01 Apr 11 |
nicklas |
88 |
|
5601 |
01 Apr 11 |
nicklas |
89 |
/** |
5601 |
01 Apr 11 |
nicklas |
Create a new processor. |
5601 |
01 Apr 11 |
nicklas |
91 |
|
5601 |
01 Apr 11 |
nicklas |
@param mainDir The main directory to where the resources should be extracted |
5601 |
01 Apr 11 |
nicklas |
@param filter A regular expression filter that must match the file name |
5601 |
01 Apr 11 |
nicklas |
in the JAR file |
5601 |
01 Apr 11 |
nicklas |
@param replacement A replacement string to create a new file name |
5601 |
01 Apr 11 |
nicklas |
using {@link Matcher#replaceAll(String)}. |
5601 |
01 Apr 11 |
nicklas |
97 |
*/ |
5605 |
12 Apr 11 |
nicklas |
98 |
public ExtractResourcesProcessor(File mainDir, Pattern filter, String replacement, ProcessResults results) |
5601 |
01 Apr 11 |
nicklas |
99 |
{ |
5601 |
01 Apr 11 |
nicklas |
100 |
this.mainDir = mainDir; |
5601 |
01 Apr 11 |
nicklas |
101 |
this.filter = filter; |
5601 |
01 Apr 11 |
nicklas |
102 |
this.replacement = replacement; |
5602 |
07 Apr 11 |
nicklas |
103 |
this.results = results; |
5601 |
01 Apr 11 |
nicklas |
104 |
} |
5601 |
01 Apr 11 |
nicklas |
105 |
|
5601 |
01 Apr 11 |
nicklas |
106 |
|
5601 |
01 Apr 11 |
nicklas |
107 |
/* |
5601 |
01 Apr 11 |
nicklas |
From the ExtensionsFileProcessor interface |
5601 |
01 Apr 11 |
nicklas |
109 |
------------------------------------------ |
5601 |
01 Apr 11 |
nicklas |
110 |
*/ |
5601 |
01 Apr 11 |
nicklas |
111 |
@Override |
5601 |
01 Apr 11 |
nicklas |
112 |
public void begin(ExtensionsManager manager, int numFiles) |
5603 |
08 Apr 11 |
nicklas |
113 |
{ |
5603 |
08 Apr 11 |
nicklas |
114 |
this.numFiles = 0; |
5603 |
08 Apr 11 |
nicklas |
115 |
this.numError = 0; |
5603 |
08 Apr 11 |
nicklas |
116 |
this.numTotalExtracted = 0; |
5603 |
08 Apr 11 |
nicklas |
117 |
} |
5601 |
01 Apr 11 |
nicklas |
118 |
|
5601 |
01 Apr 11 |
nicklas |
119 |
@Override |
5603 |
08 Apr 11 |
nicklas |
120 |
public void processFile(ExtensionsManager manager, WriteableExtensionsFile wFile) |
5601 |
01 Apr 11 |
nicklas |
121 |
{ |
5603 |
08 Apr 11 |
nicklas |
122 |
ExtensionsFile xtFile = wFile.getExtensionsFile(); |
5602 |
07 Apr 11 |
nicklas |
123 |
if (!xtFile.isJar()) |
5602 |
07 Apr 11 |
nicklas |
124 |
{ |
5603 |
08 Apr 11 |
nicklas |
125 |
log.info("File is not a JAR file (skipping): " + xtFile); |
5602 |
07 Apr 11 |
nicklas |
126 |
return; |
5602 |
07 Apr 11 |
nicklas |
127 |
} |
5603 |
08 Apr 11 |
nicklas |
128 |
|
5602 |
07 Apr 11 |
nicklas |
129 |
File jar = xtFile.getFile(); |
5601 |
01 Apr 11 |
nicklas |
130 |
File targetDir = new File(mainDir, jar.getName()); |
5601 |
01 Apr 11 |
nicklas |
131 |
|
5601 |
01 Apr 11 |
nicklas |
132 |
log.info("Extracting resources from '" + jar.getName() + |
6021 |
19 Mar 12 |
nicklas |
133 |
"' to " + targetDir); |
5601 |
01 Apr 11 |
nicklas |
134 |
log.debug("filter=" + filter + "; replacement=" + replacement); |
5601 |
01 Apr 11 |
nicklas |
135 |
|
5603 |
08 Apr 11 |
nicklas |
136 |
ZipInputStream zipStream = null; |
5601 |
01 Apr 11 |
nicklas |
137 |
int numExtracted = 0; |
5601 |
01 Apr 11 |
nicklas |
138 |
try |
5601 |
01 Apr 11 |
nicklas |
139 |
{ |
5601 |
01 Apr 11 |
nicklas |
140 |
zipStream = new ZipInputStream(new FileInputStream(jar)); |
5601 |
01 Apr 11 |
nicklas |
141 |
ZipEntry zipEntry = null; |
5601 |
01 Apr 11 |
nicklas |
142 |
while ((zipEntry = zipStream.getNextEntry()) != null) |
5601 |
01 Apr 11 |
nicklas |
143 |
{ |
5601 |
01 Apr 11 |
nicklas |
// Get the name of the zipped file, but strip first slash |
5601 |
01 Apr 11 |
nicklas |
145 |
String name = zipEntry.getName(); |
5601 |
01 Apr 11 |
nicklas |
146 |
if (name.startsWith("/")) name = name.substring(1); |
5601 |
01 Apr 11 |
nicklas |
147 |
|
5602 |
07 Apr 11 |
nicklas |
// Should the current entry be extracted or not? We start by assuming so ... |
5601 |
01 Apr 11 |
nicklas |
149 |
boolean extract = true; |
5601 |
01 Apr 11 |
nicklas |
// A filter may change the actual name of the extracted file |
5601 |
01 Apr 11 |
nicklas |
151 |
String extractionName = name; |
5601 |
01 Apr 11 |
nicklas |
152 |
if (zipEntry.isDirectory()) |
5601 |
01 Apr 11 |
nicklas |
153 |
{ |
5601 |
01 Apr 11 |
nicklas |
// Ignore directories |
5601 |
01 Apr 11 |
nicklas |
155 |
extract = false; |
5602 |
07 Apr 11 |
nicklas |
156 |
log.debug("Jar entry '" + name + "' is a directory (ignored)."); |
5601 |
01 Apr 11 |
nicklas |
157 |
} |
5601 |
01 Apr 11 |
nicklas |
158 |
else if (filter != null) |
5601 |
01 Apr 11 |
nicklas |
159 |
{ |
5601 |
01 Apr 11 |
nicklas |
// Ignore files not matched by the filter |
5601 |
01 Apr 11 |
nicklas |
161 |
Matcher matcher = filter.matcher(name); |
5601 |
01 Apr 11 |
nicklas |
162 |
if (!matcher.matches()) |
5601 |
01 Apr 11 |
nicklas |
163 |
{ |
5601 |
01 Apr 11 |
nicklas |
164 |
extract = false; |
5602 |
07 Apr 11 |
nicklas |
165 |
log.debug("Jar entry '" + name + "' doesn't match filter (ignored)."); |
5601 |
01 Apr 11 |
nicklas |
166 |
} |
5601 |
01 Apr 11 |
nicklas |
167 |
else |
5601 |
01 Apr 11 |
nicklas |
168 |
{ |
5601 |
01 Apr 11 |
nicklas |
169 |
extractionName = matcher.replaceAll(replacement); |
5601 |
01 Apr 11 |
nicklas |
170 |
} |
5601 |
01 Apr 11 |
nicklas |
171 |
} |
5601 |
01 Apr 11 |
nicklas |
172 |
|
5601 |
01 Apr 11 |
nicklas |
173 |
File targetFile = new File(targetDir, extractionName); |
5601 |
01 Apr 11 |
nicklas |
174 |
|
5601 |
01 Apr 11 |
nicklas |
// Now... it is finally time to extract the file |
5601 |
01 Apr 11 |
nicklas |
176 |
if (extract) |
5601 |
01 Apr 11 |
nicklas |
177 |
{ |
5601 |
01 Apr 11 |
nicklas |
178 |
log.debug("Extracting '" + name + "' to " + targetFile); |
5601 |
01 Apr 11 |
nicklas |
179 |
File dir = targetFile.getParentFile(); |
5601 |
01 Apr 11 |
nicklas |
180 |
dir.mkdirs(); |
5601 |
01 Apr 11 |
nicklas |
181 |
if (!dir.exists()) |
5601 |
01 Apr 11 |
nicklas |
182 |
{ |
5601 |
01 Apr 11 |
nicklas |
183 |
throw new FileNotFoundException("Failed to create directory: " + dir); |
5601 |
01 Apr 11 |
nicklas |
184 |
} |
5601 |
01 Apr 11 |
nicklas |
185 |
OutputStream out = null; |
5601 |
01 Apr 11 |
nicklas |
186 |
try |
5601 |
01 Apr 11 |
nicklas |
187 |
{ |
5601 |
01 Apr 11 |
nicklas |
188 |
out = new FileOutputStream(targetFile); |
5601 |
01 Apr 11 |
nicklas |
189 |
FileUtil.copy(zipStream, out); |
5601 |
01 Apr 11 |
nicklas |
190 |
out.close(); |
5601 |
01 Apr 11 |
nicklas |
191 |
} |
5601 |
01 Apr 11 |
nicklas |
192 |
finally |
5601 |
01 Apr 11 |
nicklas |
193 |
{ |
5601 |
01 Apr 11 |
nicklas |
194 |
FileUtil.close(out); |
5601 |
01 Apr 11 |
nicklas |
195 |
} |
5601 |
01 Apr 11 |
nicklas |
196 |
numExtracted++; |
6021 |
19 Mar 12 |
nicklas |
// Always set current time to force Tomcat to re-compile JSP files |
6021 |
19 Mar 12 |
nicklas |
198 |
if (!targetFile.setLastModified(System.currentTimeMillis())) |
5601 |
01 Apr 11 |
nicklas |
199 |
{ |
5601 |
01 Apr 11 |
nicklas |
200 |
log.warn("Could not set last modification time on file: " + targetFile); |
5601 |
01 Apr 11 |
nicklas |
201 |
} |
5601 |
01 Apr 11 |
nicklas |
202 |
else |
5601 |
01 Apr 11 |
nicklas |
203 |
{ |
5601 |
01 Apr 11 |
nicklas |
204 |
log.info("Extracted file '" + name + "' to " + targetFile); |
5601 |
01 Apr 11 |
nicklas |
205 |
} |
5601 |
01 Apr 11 |
nicklas |
206 |
} |
5601 |
01 Apr 11 |
nicklas |
207 |
} |
5603 |
08 Apr 11 |
nicklas |
208 |
numFiles++; |
5603 |
08 Apr 11 |
nicklas |
209 |
numTotalExtracted += numExtracted; |
5603 |
08 Apr 11 |
nicklas |
210 |
if (numExtracted > 0 && results != null) |
5603 |
08 Apr 11 |
nicklas |
211 |
{ |
5603 |
08 Apr 11 |
nicklas |
212 |
results.addMessage(xtFile, numExtracted + " resource(s) extracted successfully."); |
5603 |
08 Apr 11 |
nicklas |
213 |
} |
5602 |
07 Apr 11 |
nicklas |
214 |
log.info("Extracted " + numExtracted + " resources from '" + jar.getName() + "' to " + targetDir); |
5601 |
01 Apr 11 |
nicklas |
215 |
} |
6379 |
13 Dec 13 |
nicklas |
216 |
catch (Throwable ex) |
5601 |
01 Apr 11 |
nicklas |
217 |
{ |
5603 |
08 Apr 11 |
nicklas |
218 |
wFile.setError(true); |
5603 |
08 Apr 11 |
nicklas |
219 |
numError++; |
5603 |
08 Apr 11 |
nicklas |
220 |
if (results != null) |
5603 |
08 Apr 11 |
nicklas |
221 |
{ |
6379 |
13 Dec 13 |
nicklas |
222 |
results.addErrorMessage(xtFile, "Failed to extract resources: " + ex.getClass().getName() + "; " + ex.getMessage()); |
5603 |
08 Apr 11 |
nicklas |
223 |
} |
5603 |
08 Apr 11 |
nicklas |
224 |
log.error("Failed to extract resources to directory: " + targetDir, ex); |
5601 |
01 Apr 11 |
nicklas |
225 |
} |
5601 |
01 Apr 11 |
nicklas |
226 |
finally |
5601 |
01 Apr 11 |
nicklas |
227 |
{ |
5601 |
01 Apr 11 |
nicklas |
228 |
FileUtil.close(zipStream); |
5601 |
01 Apr 11 |
nicklas |
229 |
} |
5601 |
01 Apr 11 |
nicklas |
230 |
} |
5601 |
01 Apr 11 |
nicklas |
231 |
|
5601 |
01 Apr 11 |
nicklas |
232 |
@Override |
5601 |
01 Apr 11 |
nicklas |
233 |
public void done(ExtensionsManager manager) |
5601 |
01 Apr 11 |
nicklas |
234 |
{} |
5602 |
07 Apr 11 |
nicklas |
235 |
|
5601 |
01 Apr 11 |
nicklas |
236 |
@Override |
5601 |
01 Apr 11 |
nicklas |
237 |
public void done(ExtensionsManager manager, Throwable t) |
5601 |
01 Apr 11 |
nicklas |
238 |
{} |
5601 |
01 Apr 11 |
nicklas |
239 |
// --------------------------------------------------- |
5603 |
08 Apr 11 |
nicklas |
240 |
|
5603 |
08 Apr 11 |
nicklas |
241 |
/** |
5603 |
08 Apr 11 |
nicklas |
Get the number of files that was successfully processed. |
5603 |
08 Apr 11 |
nicklas |
243 |
*/ |
5603 |
08 Apr 11 |
nicklas |
244 |
public int getNumFiles() |
5603 |
08 Apr 11 |
nicklas |
245 |
{ |
5603 |
08 Apr 11 |
nicklas |
246 |
return numFiles; |
5603 |
08 Apr 11 |
nicklas |
247 |
} |
5603 |
08 Apr 11 |
nicklas |
248 |
|
5603 |
08 Apr 11 |
nicklas |
249 |
/** |
5603 |
08 Apr 11 |
nicklas |
Get the number of files that was had an error. |
5603 |
08 Apr 11 |
nicklas |
251 |
*/ |
5603 |
08 Apr 11 |
nicklas |
252 |
public int getNumError() |
5603 |
08 Apr 11 |
nicklas |
253 |
{ |
5603 |
08 Apr 11 |
nicklas |
254 |
return numError; |
5603 |
08 Apr 11 |
nicklas |
255 |
} |
5603 |
08 Apr 11 |
nicklas |
256 |
|
5603 |
08 Apr 11 |
nicklas |
257 |
/** |
5603 |
08 Apr 11 |
nicklas |
Get the total number of resources that was extracts. |
5603 |
08 Apr 11 |
nicklas |
259 |
*/ |
5603 |
08 Apr 11 |
nicklas |
260 |
public int getNumExtracted() |
5603 |
08 Apr 11 |
nicklas |
261 |
{ |
5603 |
08 Apr 11 |
nicklas |
262 |
return numTotalExtracted; |
5603 |
08 Apr 11 |
nicklas |
263 |
} |
5603 |
08 Apr 11 |
nicklas |
264 |
|
5603 |
08 Apr 11 |
nicklas |
265 |
|
5601 |
01 Apr 11 |
nicklas |
266 |
} |