View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
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  package org.vafer.jdeb.producers;
17  
18  import java.io.File;
19  import java.io.FileInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.PushbackInputStream;
23  import java.util.zip.GZIPInputStream;
24  
25  import org.apache.tools.bzip2.CBZip2InputStream;
26  import org.apache.tools.tar.TarEntry;
27  import org.apache.tools.tar.TarInputStream;
28  import org.vafer.jdeb.DataConsumer;
29  import org.vafer.jdeb.DataProducer;
30  import org.vafer.jdeb.mapping.Mapper;
31  
32  /**
33   * Providing data from an archive keeping permissions and ownerships.
34   * 
35   * @author Torsten Curdt <tcurdt@vafer.org>
36   */
37  public final class DataProducerArchive extends AbstractDataProducer implements DataProducer {
38  
39  	private final File archive;
40  	
41  	public DataProducerArchive( final File pArchive, final String[] pIncludes, final String[] pExcludes, final Mapper[] pMappers ) {
42  		super(pIncludes, pExcludes, pMappers);
43  		archive = pArchive;
44  	}
45  		
46  	public void produce( final DataConsumer receiver ) throws IOException {
47  
48  		TarInputStream archiveInputStream = null;
49  		try {
50  			archiveInputStream = new TarInputStream(getCompressedInputStream(new FileInputStream(archive)));
51  
52  			while(true) {
53  				
54  				TarEntry entry = archiveInputStream.getNextEntry();
55  
56  				if (entry == null) {
57  					break;
58  				}
59  
60  				if (!isIncluded(entry.getName())) {
61  					continue;					
62  				}				
63  
64  				entry = map(entry);
65  				
66  				if (entry.isDirectory()) {
67  					receiver.onEachDir(entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());
68  					continue;
69  				}
70  				receiver.onEachFile(archiveInputStream, entry.getName(), entry.getLinkName(), entry.getUserName(), entry.getUserId(), entry.getGroupName(), entry.getGroupId(), entry.getMode(), entry.getSize());						
71  			}
72  
73  		} finally {
74  			if (archiveInputStream != null) {
75  				archiveInputStream.close();
76  			}
77  		}		
78  	}
79  
80  
81  	/**
82  	 * Guess the compression used by looking at the first bytes of the stream.
83  	 */
84  	private InputStream getCompressedInputStream(InputStream in) throws IOException {
85  		PushbackInputStream pin = new PushbackInputStream(in, 2);
86  		byte[] header = new byte[2];
87  		if (pin.read(header) != header.length) {
88  			throw new IOException("Could not read header");
89  		}
90  
91  		if (header[0] == (byte) 0x1f && header[1] == (byte) 0x8b) {
92  			pin.unread(header);
93  			return new GZIPInputStream(pin);
94  		} else if (header[0] == 'B' && header[1] == 'Z') {
95  			return new CBZip2InputStream(pin);
96  		} else {
97  			throw new IOException("Unsupported archive format : " + archive);
98  		}
99  	}
100 	
101 }