1 package org.alfresco.plexus.archiver;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.Date;
9 import java.util.Enumeration;
10 import java.util.HashMap;
11 import java.util.Iterator;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.Properties;
15 import java.util.zip.ZipException;
16
17 import org.codehaus.plexus.archiver.ArchiveFilterException;
18 import org.codehaus.plexus.archiver.ArchiveFinalizer;
19 import org.codehaus.plexus.archiver.ArchiverException;
20 import org.codehaus.plexus.archiver.util.FilterSupport;
21 import org.codehaus.plexus.archiver.zip.AbstractZipUnArchiver;
22 import org.codehaus.plexus.archiver.zip.ZipEntry;
23 import org.codehaus.plexus.archiver.zip.ZipFile;
24 import org.codehaus.plexus.util.FileUtils;
25
26 public class AmpUnArchiver extends AbstractZipUnArchiver {
27
28 private static final String NATIVE_ENCODING = "native-encoding";
29
30 private String encoding = "UTF8";
31
32 private FilterSupport filterSupport;
33
34 private List finalizers;
35
36 private static String fileSeparator = System.getProperty("file.separator");
37
38
39 public void setArchiveFilters( List filters )
40 {
41 filterSupport = new FilterSupport( filters, getLogger() );
42 }
43
44 /***
45 * Sets the encoding to assume for file names and comments.
46 * <p/>
47 * <p>Set to <code>native-encoding</code> if you want your
48 * platform's native encoding, defaults to UTF8.</p>
49 */
50 public void setEncoding( String encoding )
51 {
52 if ( NATIVE_ENCODING.equals( encoding ) )
53 {
54 encoding = null;
55 }
56 this.encoding = encoding;
57 }
58
59
60 private static Map<String,String> ampMapping = new HashMap<String,String>();
61
62 @Override
63 protected void execute()
64 throws ArchiverException, IOException
65 {
66
67 getLogger().info( "Expanding: " + getSourceFile() + " into " + getDestDirectory() );
68 ZipFile zf = null;
69
70
71
72 try
73 {
74 zf = new ZipFile( getSourceFile(), encoding );
75 Enumeration e = zf.getEntries();
76
77
78 String moduleId = getModuleId(zf);
79
80
81 createAmpMapping(moduleId);
82
83 while ( e.hasMoreElements() )
84 {
85 ZipEntry ze = (ZipEntry) e.nextElement();
86 if (!ze.getName().startsWith("META-INF"))
87 {
88 String fileInAmp = getAmpMapping(ze.getName());
89
90 extractFileIfIncluded( getSourceFile(), getDestDirectory(), zf.getInputStream( ze ), fileInAmp, new Date( ze.getTime() ), ze.isDirectory() );
91 }
92 }
93
94 runArchiveFinalizers();
95
96 getLogger().debug( "expand complete" );
97 }
98 catch ( IOException ioe )
99 {
100 throw new ArchiverException( "Error while expanding " + getSourceFile().getAbsolutePath(), ioe );
101 }
102 finally
103 {
104 if ( zf != null )
105 {
106 try
107 {
108 zf.close();
109 }
110 catch ( IOException e )
111 {
112
113 }
114 }
115 }
116 }
117
118 private String getModuleId(ZipFile zf) throws IOException, ZipException, ArchiverException {
119 ZipEntry modulePropertiesEntry = zf.getEntry("module.properties");
120 Properties moduleProperties = new Properties();
121 moduleProperties.load(zf.getInputStream(modulePropertiesEntry));
122 String moduleId = moduleProperties.getProperty("module.id");
123 if(moduleId == null || "".equals(moduleId))
124 throw new ArchiverException("module.id property not found in module.properties");
125 return moduleId;
126 }
127
128
129 private String getAmpMapping(String name) {
130 if(name.startsWith("web/") && !name.startsWith("web/licenses"))
131 {
132 return name.substring(4);
133 }
134
135 for (Map.Entry<String, String> mapElelement : ampMapping.entrySet()) {
136 if(name.startsWith(mapElelement.getKey()))
137 {
138 String relativePath = "";
139
140 if((name.startsWith("config/")))
141 {
142 relativePath = name.substring(7);
143 }
144 else if((name.startsWith("lib/")))
145 {
146 relativePath = name.substring(4);
147 }
148 else
149 relativePath = FileUtils.removePath(name);
150
151 return mapElelement.getValue() + relativePath;
152 }
153
154 }
155 return "";
156 }
157
158
159 private void createAmpMapping(String moduleId) {
160 File zipFile = getSourceFile();
161
162 String ampName = zipFile.getName();
163 ampName = FileUtils.removeExtension(FileUtils.removePath(ampName));
164 ampName = ampName.substring(0, ampName.lastIndexOf('-'));
165
166 ampMapping.put("module.properties", "WEB-INF"+ fileSeparator +"classes" + fileSeparator +"alfresco" + fileSeparator +"module" + fileSeparator + moduleId + fileSeparator);
167 ampMapping.put("config", "WEB-INF"+fileSeparator+"classes"+ fileSeparator);
168 ampMapping.put("lib", "WEB-INF" + fileSeparator + "lib" +fileSeparator);
169 ampMapping.put("web"+ fileSeparator +"licenses", "WEB-INF" +fileSeparator);
170
171 }
172
173 private void extractFileIfIncluded( File sourceFile, File destDirectory, InputStream inputStream, String name,
174 Date time, boolean isDirectory )
175 throws IOException, ArchiverException
176 {
177 try
178 {
179 if ( filterSupport == null || filterSupport.include( inputStream, name ) )
180 {
181 extractFile( sourceFile, destDirectory, inputStream, name, time, isDirectory );
182 }
183 }
184 catch ( ArchiveFilterException e )
185 {
186 throw new ArchiverException( "Error verifying \'" + name + "\' for inclusion: " + e.getMessage(), e );
187 }
188 }
189
190 protected void extractFile( File srcF, File dir, InputStream compressedInputStream, String entryName,
191 Date entryDate, boolean isDirectory )
192 throws IOException
193 {
194 File f = null;
195 if (entryName != null && !"".equals(entryName))
196 f = FileUtils.resolveFile( dir, entryName );
197 else
198 return;
199
200 try
201 {
202 if ( !isOverwrite() && f.exists() && f.lastModified() >= entryDate.getTime() )
203 {
204 getLogger().debug( "Skipping " + f + " as it is up-to-date" );
205 return;
206 }
207
208 getLogger().debug( "expanding " + entryName + " to " + f );
209
210 File dirF = f.getParentFile();
211 if ( dirF != null )
212 {
213 dirF.mkdirs();
214 }
215
216 if ( isDirectory )
217 {
218 f.mkdirs();
219 }
220 else
221 {
222 byte[] buffer = new byte[1024];
223 int length;
224 FileOutputStream fos = null;
225 try
226 {
227 fos = new FileOutputStream( f );
228
229 while ( ( length = compressedInputStream.read( buffer ) ) >= 0 )
230 {
231 fos.write( buffer, 0, length );
232 }
233
234 fos.close();
235 fos = null;
236 }
237 finally
238 {
239 if ( fos != null )
240 {
241 try
242 {
243 fos.close();
244 }
245 catch ( IOException e )
246 {
247
248 }
249 }
250 }
251 }
252
253 f.setLastModified( entryDate.getTime() );
254 }
255 catch ( FileNotFoundException ex )
256 {
257 getLogger().warn( "Unable to expand to file " + f.getPath() );
258 }
259 }
260
261 public void setArchiveFinalizers( List archiveFinalizers )
262 {
263 this.finalizers = archiveFinalizers;
264 }
265
266 protected void runArchiveFinalizers()
267 throws ArchiverException
268 {
269 if ( finalizers != null )
270 {
271 for ( Iterator it = finalizers.iterator(); it.hasNext(); )
272 {
273 ArchiveFinalizer finalizer = (ArchiveFinalizer) it.next();
274
275 finalizer.finalizeArchiveExtraction( this );
276 }
277 }
278 }
279 }