Commit | Line | Data |
---|---|---|
5d5f933e MAL |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2016 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 | * Red Hat, Inc - Was TarFileStructureProvider, performed changes from | |
11 | * IImportStructureProvider to ILeveledImportStructureProvider | |
12 | * Mickael Istria (Red Hat Inc.) - Bug 486901 | |
13 | * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Copied to Trace Compass to work around bug 501379 | |
6120dc63 | 14 | * Marc-Andre Laperle <marc-andre.laperle@ericsson.com> - Adapted to use Apache Common Compress |
5d5f933e MAL |
15 | *******************************************************************************/ |
16 | package org.eclipse.tracecompass.internal.tmf.ui.project.wizards.importtrace; | |
17 | ||
18 | import java.io.IOException; | |
19 | import java.io.InputStream; | |
20 | import java.util.ArrayList; | |
21 | import java.util.Enumeration; | |
22 | import java.util.HashMap; | |
23 | import java.util.List; | |
24 | import java.util.Map; | |
25 | ||
6120dc63 | 26 | import org.apache.commons.compress.archivers.tar.TarArchiveEntry; |
5d5f933e MAL |
27 | import org.eclipse.core.resources.ResourceAttributes; |
28 | import org.eclipse.core.runtime.IPath; | |
29 | import org.eclipse.core.runtime.Path; | |
30 | import org.eclipse.tracecompass.common.core.NonNullUtils; | |
31 | import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; | |
32 | import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages; | |
33 | import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider; | |
34 | ||
35 | /** | |
36 | * This class provides information regarding the context structure and content | |
37 | * of specified tar file entry objects. | |
38 | */ | |
39 | @SuppressWarnings("restriction") | |
40 | public class TarLeveledStructureProvider implements | |
c2750d24 MAL |
41 | ILeveledImportStructureProvider { |
42 | private TarFile tarFile; | |
5d5f933e | 43 | |
6120dc63 | 44 | private TarArchiveEntry root = new TarArchiveEntry("/", true);//$NON-NLS-1$ |
5d5f933e | 45 | |
6120dc63 | 46 | private Map<TarArchiveEntry, List<TarArchiveEntry>> children; |
5d5f933e | 47 | |
6120dc63 | 48 | private Map<IPath, TarArchiveEntry> directoryEntryCache = new HashMap<>(); |
5d5f933e | 49 | |
c2750d24 | 50 | private int stripLevel; |
5d5f933e | 51 | |
c2750d24 MAL |
52 | /** |
53 | * Creates a <code>TarFileStructureProvider</code>, which will operate on | |
54 | * the passed tar file. | |
55 | * | |
56 | * @param sourceFile | |
57 | * the source TarFile | |
58 | */ | |
59 | public TarLeveledStructureProvider(TarFile sourceFile) { | |
60 | super(); | |
61 | tarFile = sourceFile; | |
c2750d24 | 62 | } |
5d5f933e | 63 | |
c2750d24 MAL |
64 | /** |
65 | * Creates a new container tar entry with the specified name, iff it has | |
66 | * not already been created. If the parent of the given element does not | |
67 | * already exist it will be recursively created as well. | |
6120dc63 | 68 | * @param pathName The path representing the container |
c2750d24 MAL |
69 | * @return The element represented by this pathname (it may have already existed) |
70 | */ | |
6120dc63 MAL |
71 | protected TarArchiveEntry createContainer(IPath pathName) { |
72 | IPath newPathName = pathName; | |
73 | TarArchiveEntry existingEntry = directoryEntryCache.get(newPathName); | |
c2750d24 MAL |
74 | if (existingEntry != null) { |
75 | return existingEntry; | |
76 | } | |
5d5f933e | 77 | |
6120dc63 MAL |
78 | TarArchiveEntry parent; |
79 | if (newPathName.segmentCount() == 1) { | |
c2750d24 MAL |
80 | parent = root; |
81 | } else { | |
6120dc63 | 82 | parent = createContainer(newPathName.removeLastSegments(1)); |
c2750d24 | 83 | } |
6120dc63 MAL |
84 | // Add trailing / so that the entry knows it's a folder |
85 | newPathName = newPathName.addTrailingSeparator(); | |
86 | TarArchiveEntry newEntry = new TarArchiveEntry(newPathName.toString()); | |
87 | directoryEntryCache.put(newPathName, newEntry); | |
88 | List<TarArchiveEntry> childList = new ArrayList<>(); | |
c2750d24 | 89 | children.put(newEntry, childList); |
5d5f933e | 90 | |
6120dc63 | 91 | List<TarArchiveEntry> parentChildList = children.get(parent); |
c2750d24 MAL |
92 | NonNullUtils.checkNotNull(parentChildList).add(newEntry); |
93 | return newEntry; | |
94 | } | |
5d5f933e | 95 | |
c2750d24 MAL |
96 | /** |
97 | * Creates a new tar file entry with the specified name. | |
98 | * @param entry the entry to create the file for | |
99 | */ | |
6120dc63 | 100 | protected void createFile(TarArchiveEntry entry) { |
c2750d24 | 101 | IPath pathname = new Path(entry.getName()); |
6120dc63 | 102 | TarArchiveEntry parent; |
c2750d24 MAL |
103 | if (pathname.segmentCount() == 1) { |
104 | parent = root; | |
105 | } else { | |
106 | parent = directoryEntryCache.get(pathname | |
107 | .removeLastSegments(1)); | |
108 | } | |
5d5f933e | 109 | |
6120dc63 | 110 | List<TarArchiveEntry> childList = children.get(parent); |
c2750d24 MAL |
111 | NonNullUtils.checkNotNull(childList).add(entry); |
112 | } | |
5d5f933e | 113 | |
c2750d24 MAL |
114 | @Override |
115 | public List getChildren(Object element) { | |
116 | if (children == null) { | |
117 | initialize(); | |
118 | } | |
5d5f933e | 119 | |
c2750d24 MAL |
120 | return (children.get(element)); |
121 | } | |
5d5f933e MAL |
122 | |
123 | @Override | |
c2750d24 MAL |
124 | public InputStream getContents(Object element) { |
125 | try { | |
6120dc63 | 126 | return tarFile.getInputStream((TarArchiveEntry) element); |
c2750d24 MAL |
127 | } catch (IOException e) { |
128 | IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e); | |
129 | return null; | |
130 | } | |
131 | } | |
5d5f933e | 132 | |
c2750d24 MAL |
133 | /** |
134 | * Returns the resource attributes for this file. | |
135 | * | |
136 | * @param element the element to get the attributes from | |
137 | * @return the attributes of the file | |
138 | */ | |
139 | public ResourceAttributes getResourceAttributes(Object element) { | |
140 | ResourceAttributes attributes = new ResourceAttributes(); | |
6120dc63 | 141 | TarArchiveEntry entry = (TarArchiveEntry) element; |
c2750d24 MAL |
142 | attributes.setExecutable((entry.getMode() & 0100) != 0); |
143 | attributes.setReadOnly((entry.getMode() & 0200) == 0); | |
144 | return attributes; | |
145 | } | |
5d5f933e | 146 | |
c2750d24 MAL |
147 | @Override |
148 | public String getFullPath(Object element) { | |
6120dc63 | 149 | String name = stripPath(((TarArchiveEntry) element).getName()); |
c2750d24 MAL |
150 | return ArchiveUtil.toValidNamesPath(name).toOSString(); |
151 | } | |
5d5f933e | 152 | |
c2750d24 MAL |
153 | @Override |
154 | public String getLabel(Object element) { | |
155 | if (element.equals(root)) { | |
6120dc63 | 156 | return ((TarArchiveEntry) element).getName(); |
c2750d24 | 157 | } |
5d5f933e | 158 | |
6120dc63 | 159 | String name = ((TarArchiveEntry) element).getName(); |
c2750d24 MAL |
160 | return stripPath(ArchiveUtil.toValidNamesPath(name).lastSegment()); |
161 | } | |
5d5f933e | 162 | |
c2750d24 MAL |
163 | /** |
164 | * Returns the entry that this importer uses as the root sentinel. | |
165 | * | |
6120dc63 | 166 | * @return TarArchiveEntry entry |
c2750d24 MAL |
167 | */ |
168 | @Override | |
169 | public Object getRoot() { | |
170 | return root; | |
171 | } | |
5d5f933e | 172 | |
c2750d24 MAL |
173 | /** |
174 | * Returns the tar file that this provider provides structure for. | |
175 | * | |
176 | * @return TarFile file | |
177 | */ | |
178 | public TarFile getTarFile() { | |
179 | return tarFile; | |
180 | } | |
5d5f933e | 181 | |
c2750d24 MAL |
182 | @Override |
183 | public boolean closeArchive(){ | |
184 | try { | |
185 | getTarFile().close(); | |
186 | } catch (IOException e) { | |
187 | IDEWorkbenchPlugin.log(DataTransferMessages.ZipImport_couldNotClose | |
188 | + getTarFile().getName(), e); | |
189 | return false; | |
190 | } | |
191 | return true; | |
192 | } | |
5d5f933e | 193 | |
c2750d24 MAL |
194 | /** |
195 | * Initializes this object's children table based on the contents of the | |
196 | * specified source file. | |
197 | */ | |
198 | protected void initialize() { | |
199 | children = new HashMap<>(1000); | |
5d5f933e | 200 | |
c2750d24 | 201 | children.put(root, new ArrayList<>()); |
6120dc63 | 202 | Enumeration<TarArchiveEntry> entries = tarFile.entries(); |
c2750d24 | 203 | while (entries.hasMoreElements()) { |
6120dc63 | 204 | TarArchiveEntry entry = entries.nextElement(); |
c2750d24 | 205 | IPath path = new Path(entry.getName()).addTrailingSeparator(); |
5d5f933e | 206 | |
6120dc63 | 207 | if (entry.isDirectory()) { |
c2750d24 MAL |
208 | createContainer(path); |
209 | } else | |
210 | { | |
211 | // Ensure the container structure for all levels above this is initialized | |
212 | // Once we hit a higher-level container that's already added we need go no further | |
213 | int pathSegmentCount = path.segmentCount(); | |
214 | if (pathSegmentCount > 1) { | |
215 | createContainer(path.uptoSegment(pathSegmentCount - 1)); | |
216 | } | |
217 | createFile(entry); | |
218 | } | |
219 | } | |
220 | } | |
5d5f933e | 221 | |
c2750d24 MAL |
222 | @Override |
223 | public boolean isFolder(Object element) { | |
6120dc63 | 224 | return (((TarArchiveEntry) element).isDirectory()); |
c2750d24 | 225 | } |
5d5f933e | 226 | |
c2750d24 MAL |
227 | /* |
228 | * Strip the leading directories from the path | |
229 | */ | |
230 | private String stripPath(String path) { | |
231 | String strippedPath = path; | |
232 | String pathOrig = strippedPath; | |
233 | for (int i = 0; i < stripLevel; i++) { | |
234 | int firstSep = strippedPath.indexOf('/'); | |
235 | // If the first character was a seperator we must strip to the next | |
236 | // seperator as well | |
237 | if (firstSep == 0) { | |
238 | strippedPath = strippedPath.substring(1); | |
239 | firstSep = strippedPath.indexOf('/'); | |
240 | } | |
241 | // No seperator wasw present so we're in a higher directory right | |
242 | // now | |
243 | if (firstSep == -1) { | |
244 | return pathOrig; | |
245 | } | |
246 | strippedPath = strippedPath.substring(firstSep); | |
247 | } | |
248 | return strippedPath; | |
249 | } | |
5d5f933e | 250 | |
c2750d24 MAL |
251 | @Override |
252 | public void setStrip(int level) { | |
253 | stripLevel = level; | |
254 | } | |
5d5f933e | 255 | |
c2750d24 MAL |
256 | @Override |
257 | public int getStrip() { | |
258 | return stripLevel; | |
259 | } | |
5d5f933e | 260 | } |