View Javadoc

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  			//	Based on the current AMP name creates the appropriate mapping to alfresco/module/<ampname>
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 					//ignore
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 //			create intermediary directories - sometimes zip don't add them
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 //							ignore
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 }