tmf: Bug 507415: Fix some random file wrongly seen as Tar
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / internal / tmf / ui / project / wizards / importtrace / TarFile.java
CommitLineData
5d5f933e
MAL
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
15package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace;
16
17import java.io.File;
18import java.io.FileInputStream;
19import java.io.IOException;
20import java.io.InputStream;
21import java.util.Enumeration;
6120dc63
MAL
22
23import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
24import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
25import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
5d5f933e
MAL
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 */
33public class TarFile {
6120dc63
MAL
34 private File file;
35 private TarArchiveInputStream entryEnumerationStream;
36 private TarArchiveEntry curEntry;
37 private TarArchiveInputStream entryStream;
5d5f933e 38
6120dc63 39 private InputStream internalEntryStream;
5d5f933e
MAL
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
6120dc63
MAL
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();
c4d84203
MAL
66 if (!curEntry.isCheckSumOK()) {
67 throw new IOException("Error detected parsing initial entry header"); //$NON-NLS-1$
68 }
6120dc63
MAL
69 } catch (IOException e) {
70 fInputStream.close();
71 throw e;
72 }
73 }
74
75 /**
76 * Close the tar file input stream.
77 *
78 * @throws IOException if the file cannot be successfully closed
79 */
80 public void close() throws IOException {
81 if (entryEnumerationStream != null) {
5d5f933e
MAL
82 entryEnumerationStream.close();
83 }
6120dc63 84 if (internalEntryStream != null) {
5d5f933e
MAL
85 internalEntryStream.close();
86 }
6120dc63
MAL
87 }
88
89 /**
90 * Create a new TarFile for the given path name.
91 *
92 * @param filename the file name to create the TarFile from
93 * @throws IOException on i/o error (bad format, etc)
94 */
95 public TarFile(String filename) throws IOException {
96 this(new File(filename));
97 }
98
99 /**
100 * Returns an enumeration cataloguing the tar archive.
101 *
102 * @return enumeration of all files in the archive
103 */
104 public Enumeration<TarArchiveEntry> entries() {
105 return new Enumeration<TarArchiveEntry>() {
106 @Override
107 public boolean hasMoreElements() {
108 return (curEntry != null);
109 }
110
111 @Override
112 public TarArchiveEntry nextElement() {
113 TarArchiveEntry oldEntry = curEntry;
114 try {
115 curEntry = (TarArchiveEntry) entryEnumerationStream.getNextEntry();
116 } catch(IOException e) {
117 curEntry = null;
118 }
119 return oldEntry;
120 }
121 };
122 }
123
124 /**
125 * Returns a new InputStream for the given file in the tar archive.
126 *
127 * @param entry the entry to get the InputStream from
128 * @return an input stream for the given file
129 * @throws IOException on i/o error (bad format, etc)
130 */
131 public InputStream getInputStream(TarArchiveEntry entry) throws IOException {
132 if(entryStream == null || !skipToEntry(entryStream, entry)) {
133 if (internalEntryStream != null) {
134 internalEntryStream.close();
135 }
136 internalEntryStream = new FileInputStream(file);
137 // First, check if it's a GzipCompressorInputStream.
138 try {
139 internalEntryStream = new GzipCompressorInputStream(internalEntryStream);
140 } catch(IOException e) {
141 //If it is not compressed we close
142 //the old one and recreate
143 internalEntryStream.close();
144 internalEntryStream = new FileInputStream(file);
145 }
146 entryStream = new TarArchiveInputStream(internalEntryStream) {
147 @Override
148 public void close() {
149 // Ignore close() since we want to reuse the stream.
150 }
151 };
152 skipToEntry(entryStream, entry);
153 }
154 return entryStream;
155 }
156
157 private static boolean skipToEntry(TarArchiveInputStream entryStream, TarArchiveEntry entry) throws IOException {
158 TarArchiveEntry e = entryStream.getNextTarEntry();
159 while (e != null) {
160 if (e.equals(entry)) {
161 return true;
162 }
163
164 e = entryStream.getNextTarEntry();
165 }
166
167 return false;
168 }
169
170 /**
171 * Returns the path name of the file this archive represents.
172 *
173 * @return path
174 */
175 public String getName() {
176 return file.getPath();
177 }
178
179 @Override
180 protected void finalize() throws Throwable {
181 close();
182 }
5d5f933e 183}
This page took 0.031134 seconds and 5 git commands to generate.