package org.ops4j.pax.exam.quickbuild.internal; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarInputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import com.google.inject.Inject; import com.google.inject.Singleton; import org.ops4j.pax.exam.quickbuild.QType; import org.ops4j.pax.exam.quickbuild.Snapshot; import org.ops4j.pax.exam.quickbuild.SnapshotBuilder; import org.ops4j.pax.exam.quickbuild.SnapshotElement; import org.ops4j.store.Handle; import org.ops4j.store.Store; /** * @author Toni Menzel */ @Singleton public class DefaultSnapshotBuilder implements SnapshotBuilder { final private Store<InputStream> m_store; public static final String LINE_DELIM = "|"; @Inject DefaultSnapshotBuilder( Store<InputStream> store ) { m_store = store; } public Snapshot take( InputStream referenceBuild, File workFolders ) { try { return new DefaultSnapshot( merge( deflate( referenceBuild ), deflate( workFolders ) ) ); } catch( IOException e ) { e.printStackTrace(); } return null; } private List<SnapshotElement> merge( Map<String, Handle> reference, Map<String, Handle> dynamic ) throws IOException { List<SnapshotElement> res = new ArrayList<SnapshotElement>(); for( String name : reference.keySet() ) { if( dynamic.containsKey( name ) ) { res.add( newSnapshotElement( name, reference.get( name ), QType.OWN ) ); dynamic.remove( name ); } else { res.add( newSnapshotElement( name, reference.get( name ), QType.IMPORTED ) ); } } // content of dynamic that does not end up in artifact (directly for( String name : dynamic.keySet() ) { res.add( newSnapshotElement( name, dynamic.get( name ), QType.EXCLUDED ) ); } return res; } /** * Create a new SnapshotElement instance of name, handle and type. * Helper method. * * @param name name identifier of a snapshot entry * @param handle store handle * @param type the type * * @return new instance of type {@link SnapshotElement} * * @throws IOException in case something goes wrong when dealing with you supplied handle */ private SnapshotElement newSnapshotElement( String name, Handle handle, QType type ) throws IOException { return new DefaultSnapshotElement( name, m_store.getLocation( handle ), type, handle.getIdentification() ); } private Map<String, Handle> deflate( File folder ) throws IOException { Map<String, Handle> content = new HashMap<String, Handle>(); defl( content, folder.getCanonicalPath(), folder ); return content; } private void defl( Map<String, Handle> content, String basePath, File folder ) throws IOException { for( File f : folder.listFiles() ) { if( !f.isHidden() && f.isDirectory() ) { defl( content, basePath, f ); } else if( !f.isHidden() && f.getName().endsWith( ".class" ) ) { String p = f.getCanonicalPath().replaceAll( "\\\\", "/" ); // cut prefix p = p.substring( basePath.length() + 1 ); content.put( p, m_store.store( new FileInputStream( f ) ) ); } } } /** * Load Snapshot from disk. * Using format produced by {@link org.ops4j.pax.exam.quickbuild.internal.DefaultSnapshot#write} * * @param load reference to what has been produced by {@link Snapshot#write} * * @return a snapshot representation of argument load * * @throws IOException problems with reading and transforming to Snapshot. */ public Snapshot load( InputStream load ) throws IOException { final BufferedReader reader = new BufferedReader( new InputStreamReader( load ) ); final List<SnapshotElement> elements = new ArrayList<SnapshotElement>(); try { String line = null; while( ( line = reader.readLine() ) != null ) { String[] parts = line.split( "\\" + LINE_DELIM ); String name = parts[ 0 ]; String checksum = parts[ 1 ]; String uri = parts[ 2 ]; String type = parts[ 3 ]; elements.add( new DefaultSnapshotElement( name, new URI( uri ), QType.valueOf( type ), checksum ) ); } } catch( URISyntaxException e ) { throw new IOException( "At least one URI is not valid. Check snapshot export", e ); } finally { reader.close(); } return new DefaultSnapshot( elements ); } public Map<String, Handle> deflate( InputStream anchor ) throws IOException { Map<String, Handle> content = new HashMap<String, Handle>(); ZipInputStream jin = new ZipInputStream( anchor ); //while () ZipEntry entry = null; while( ( entry = jin.getNextEntry() ) != null ) { Handle handle = m_store.store( jin ); content.put( entry.getName(), handle ); } return content; } }