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
9 * IBM Corporation - initial API and implementation
10 * Red Hat, Inc - Was ZipFileStructureProvider, 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
14 * Compass to use Apache Common Compress and fix bug 501664
15 *******************************************************************************/
16 package org
.eclipse
.tracecompass
.internal
.tmf
.ui
.project
.wizards
.importtrace
;
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
;
26 import org
.apache
.commons
.compress
.archivers
.zip
.ZipArchiveEntry
;
27 import org
.apache
.commons
.compress
.archivers
.zip
.ZipFile
;
28 import org
.eclipse
.core
.runtime
.IPath
;
29 import org
.eclipse
.core
.runtime
.Path
;
30 import org
.eclipse
.jdt
.annotation
.Nullable
;
31 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
32 import org
.eclipse
.ui
.internal
.ide
.IDEWorkbenchPlugin
;
33 import org
.eclipse
.ui
.internal
.wizards
.datatransfer
.DataTransferMessages
;
34 import org
.eclipse
.ui
.internal
.wizards
.datatransfer
.ILeveledImportStructureProvider
;
37 * This class provides information regarding the context structure and content
38 * of specified zip file entry objects.
40 * This structure provider also makes sure to return safe paths. For example,
41 * if a Zip entry contains a ':' and is extracted on Windows, it will be changed
44 @SuppressWarnings("restriction")
45 public class ZipLeveledStructureProvider
implements
46 ILeveledImportStructureProvider
{
47 private ZipFile zipFile
;
49 private ZipArchiveEntry root
= new ZipArchiveEntry("/");//$NON-NLS-1$
51 private Map
<ZipArchiveEntry
, List
<ZipArchiveEntry
>> children
;
53 private Map
<IPath
, ZipArchiveEntry
> directoryEntryCache
= new HashMap
<>();
55 private int stripLevel
;
58 * Creates a <code>ZipFileStructureProvider</code>, which will operate on
59 * the passed zip file.
62 * The source file to create the ZipLeveledStructureProvider
65 public ZipLeveledStructureProvider(ZipFile sourceFile
) {
72 * Creates a new container zip entry with the specified name, iff it has
73 * not already been created. If the parent of the given element does not
74 * already exist it will be recursively created as well.
75 * @param pathname The path representing the container
76 * @return The element represented by this pathname (it may have already existed)
78 protected ZipArchiveEntry
createContainer(IPath pathname
) {
79 ZipArchiveEntry existingEntry
= directoryEntryCache
.get(pathname
);
80 if (existingEntry
!= null) {
84 ZipArchiveEntry parent
;
85 if (pathname
.segmentCount() == 0) {
87 } else if (pathname
.segmentCount() == 1) {
90 parent
= createContainer(pathname
.removeLastSegments(1));
92 ZipArchiveEntry newEntry
= new ZipArchiveEntry(pathname
.toString());
93 directoryEntryCache
.put(pathname
, newEntry
);
94 List
<ZipArchiveEntry
> childList
= new ArrayList
<>();
95 children
.put(newEntry
, childList
);
97 List
<ZipArchiveEntry
> parentChildList
= children
.get(parent
);
98 NonNullUtils
.checkNotNull(parentChildList
).add(newEntry
);
103 * Creates a new file zip entry with the specified name.
104 * @param entry the entry to create the file for
106 protected void createFile(ZipArchiveEntry entry
) {
107 IPath pathname
= new Path(entry
.getName());
108 ZipArchiveEntry parent
;
109 if (pathname
.segmentCount() == 1) {
112 parent
= directoryEntryCache
.get(pathname
113 .removeLastSegments(1));
116 @Nullable List
<ZipArchiveEntry
> childList
= children
.get(parent
);
117 NonNullUtils
.checkNotNull(childList
).add(entry
);
121 public List
getChildren(Object element
) {
122 if (children
== null) {
126 return (children
.get(element
));
130 public InputStream
getContents(Object element
) {
132 return zipFile
.getInputStream((ZipArchiveEntry
) element
);
133 } catch (IOException e
) {
134 IDEWorkbenchPlugin
.log(e
.getLocalizedMessage(), e
);
140 * Strip the leading directories from the path
142 private String
stripPath(String path
) {
143 String strippedPath
= path
;
144 String pathOrig
= strippedPath
;
145 for (int i
= 0; i
< stripLevel
; i
++) {
146 int firstSep
= strippedPath
.indexOf('/');
147 // If the first character was a separator we must strip to the next
150 strippedPath
= strippedPath
.substring(1);
151 firstSep
= strippedPath
.indexOf('/');
153 // No separator was present so we're in a higher directory right
155 if (firstSep
== -1) {
158 strippedPath
= strippedPath
.substring(firstSep
);
164 public String
getFullPath(Object element
) {
165 String name
= ((ZipArchiveEntry
) element
).getName();
166 return ArchiveUtil
.toValidNamesPath(name
).toOSString();
170 public String
getLabel(Object element
) {
171 if (element
.equals(getRoot())) {
172 return ((ZipArchiveEntry
) element
).getName();
174 String name
= ((ZipArchiveEntry
) element
).getName();
175 return stripPath(ArchiveUtil
.toValidNamesPath(name
).lastSegment());
179 * Returns the entry that this importer uses as the root sentinel.
181 * @return ZipArchiveEntry
184 public Object
getRoot() {
189 * Returns the zip file that this provider provides structure for.
191 * @return The zip file
193 public ZipFile
getZipFile() {
199 public boolean closeArchive(){
201 getZipFile().close();
202 } catch (IOException e
) {
203 IDEWorkbenchPlugin
.log(DataTransferMessages
.ZipImport_couldNotClose
211 * Initializes this object's children table based on the contents of the
212 * specified source file.
214 protected void initialize() {
215 children
= new HashMap
<>(1000);
217 children
.put(root
, new ArrayList
<>());
218 Enumeration
<ZipArchiveEntry
> entries
= zipFile
.getEntries();
219 while (entries
.hasMoreElements()) {
220 ZipArchiveEntry entry
= entries
.nextElement();
221 IPath path
= new Path(entry
.getName()).addTrailingSeparator();
223 if (entry
.isDirectory()) {
224 createContainer(path
);
227 // Ensure the container structure for all levels above this is initialized
228 // Once we hit a higher-level container that's already added we need go no further
229 int pathSegmentCount
= path
.segmentCount();
230 if (pathSegmentCount
> 1) {
231 createContainer(path
.uptoSegment(pathSegmentCount
- 1));
239 public boolean isFolder(Object element
) {
240 return ((ZipArchiveEntry
) element
).isDirectory();
244 public void setStrip(int level
) {
249 public int getStrip() {