tmf: Use Apache Common Compress for importing from archive
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / wizards / importtrace / TarFile.java
1 /*******************************************************************************
2 * Copyright (c) 2004, 2015 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 * Remy Chi Jian Suen <remy.suen@gmail.com> - Bug 243347 TarFile should not throw NPE in finalize()
11 * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Bug 463633
12 * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
16
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.util.Enumeration;
22
23 import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
24 import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
25 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
26
27
28 /**
29 * Reads a .tar or .tar.gz archive file, providing an index enumeration
30 * and allows for accessing an InputStream for arbitrary files in the
31 * archive.
32 */
33 public class TarFile {
34 private File file;
35 private TarArchiveInputStream entryEnumerationStream;
36 private TarArchiveEntry curEntry;
37 private TarArchiveInputStream entryStream;
38
39 private InputStream internalEntryStream;
40 // This field is just to prevent try with resources error and keep the code
41 // similar to the original
42 private InputStream fInputStream;
43
44 /**
45 * Create a new TarFile for the given file.
46 *
47 * @param file the file
48 * @throws IOException on i/o error (bad format, etc)
49 */
50 public TarFile(File file) throws IOException {
51 this.file = file;
52
53 fInputStream = new FileInputStream(file);
54 // First, check if it's a GZIPInputStream.
55 try {
56 fInputStream = new GzipCompressorInputStream(fInputStream);
57 } catch (IOException e) {
58 //If it is not compressed we close
59 //the old one and recreate
60 fInputStream.close();
61 fInputStream = new FileInputStream(file);
62 }
63 entryEnumerationStream = new TarArchiveInputStream(fInputStream);
64 try {
65 curEntry = (TarArchiveEntry) entryEnumerationStream.getNextEntry();
66 } catch (IOException e) {
67 fInputStream.close();
68 throw e;
69 }
70 }
71
72 /**
73 * Close the tar file input stream.
74 *
75 * @throws IOException if the file cannot be successfully closed
76 */
77 public void close() throws IOException {
78 if (entryEnumerationStream != null) {
79 entryEnumerationStream.close();
80 }
81 if (internalEntryStream != null) {
82 internalEntryStream.close();
83 }
84 }
85
86 /**
87 * Create a new TarFile for the given path name.
88 *
89 * @param filename the file name to create the TarFile from
90 * @throws IOException on i/o error (bad format, etc)
91 */
92 public TarFile(String filename) throws IOException {
93 this(new File(filename));
94 }
95
96 /**
97 * Returns an enumeration cataloguing the tar archive.
98 *
99 * @return enumeration of all files in the archive
100 */
101 public Enumeration<TarArchiveEntry> entries() {
102 return new Enumeration<TarArchiveEntry>() {
103 @Override
104 public boolean hasMoreElements() {
105 return (curEntry != null);
106 }
107
108 @Override
109 public TarArchiveEntry nextElement() {
110 TarArchiveEntry oldEntry = curEntry;
111 try {
112 curEntry = (TarArchiveEntry) entryEnumerationStream.getNextEntry();
113 } catch(IOException e) {
114 curEntry = null;
115 }
116 return oldEntry;
117 }
118 };
119 }
120
121 /**
122 * Returns a new InputStream for the given file in the tar archive.
123 *
124 * @param entry the entry to get the InputStream from
125 * @return an input stream for the given file
126 * @throws IOException on i/o error (bad format, etc)
127 */
128 public InputStream getInputStream(TarArchiveEntry entry) throws IOException {
129 if(entryStream == null || !skipToEntry(entryStream, entry)) {
130 if (internalEntryStream != null) {
131 internalEntryStream.close();
132 }
133 internalEntryStream = new FileInputStream(file);
134 // First, check if it's a GzipCompressorInputStream.
135 try {
136 internalEntryStream = new GzipCompressorInputStream(internalEntryStream);
137 } catch(IOException e) {
138 //If it is not compressed we close
139 //the old one and recreate
140 internalEntryStream.close();
141 internalEntryStream = new FileInputStream(file);
142 }
143 entryStream = new TarArchiveInputStream(internalEntryStream) {
144 @Override
145 public void close() {
146 // Ignore close() since we want to reuse the stream.
147 }
148 };
149 skipToEntry(entryStream, entry);
150 }
151 return entryStream;
152 }
153
154 private static boolean skipToEntry(TarArchiveInputStream entryStream, TarArchiveEntry entry) throws IOException {
155 TarArchiveEntry e = entryStream.getNextTarEntry();
156 while (e != null) {
157 if (e.equals(entry)) {
158 return true;
159 }
160
161 e = entryStream.getNextTarEntry();
162 }
163
164 return false;
165 }
166
167 /**
168 * Returns the path name of the file this archive represents.
169 *
170 * @return path
171 */
172 public String getName() {
173 return file.getPath();
174 }
175
176 @Override
177 protected void finalize() throws Throwable {
178 close();
179 }
180 }
This page took 0.034139 seconds and 5 git commands to generate.