Commit | Line | Data |
---|---|---|
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 | ||
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; | |
6120dc63 MAL |
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; | |
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 | */ | |
33 | public 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(); | |
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) { | |
5d5f933e MAL |
79 | entryEnumerationStream.close(); |
80 | } | |
6120dc63 | 81 | if (internalEntryStream != null) { |
5d5f933e MAL |
82 | internalEntryStream.close(); |
83 | } | |
6120dc63 MAL |
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 | } | |
5d5f933e | 180 | } |