blob: a7e75033b63edc6870eb2e3e56b320a95d54851a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Red Hat, Inc - Was ZipFileStructureProvider, performed changes from
* IImportStructureProvider to ILeveledImportStructureProvider
*******************************************************************************/
package org.eclipse.ui.internal.wizards.datatransfer;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
/**
* This class provides information regarding the context structure and content
* of specified zip file entry objects.
*
* @since 3.1
*/
public class ZipLeveledStructureProvider implements
ILeveledImportStructureProvider {
private ZipFile zipFile;
private ZipEntry root = new ZipEntry("/");//$NON-NLS-1$
private Map children;
private Map directoryEntryCache = new HashMap();
private int stripLevel;
/**
* Creates a <code>ZipFileStructureProvider</code>, which will operate on
* the passed zip file.
*
* @param sourceFile
* The source file to create the ZipLeveledStructureProvider
* around
*/
public ZipLeveledStructureProvider(ZipFile sourceFile) {
super();
zipFile = sourceFile;
stripLevel = 0;
}
/**
* Creates a new container zip entry with the specified name, iff it has
* not already been created. If the parent of the given element does not
* already exist it will be recursively created as well.
* @param pathname The path representing the container
* @return The element represented by this pathname (it may have already existed)
*/
protected ZipEntry createContainer(IPath pathname) {
ZipEntry existingEntry = (ZipEntry) directoryEntryCache.get(pathname);
if (existingEntry != null)
return existingEntry;
ZipEntry parent;
if (pathname.segmentCount() == 1)
parent = root;
else
parent = createContainer(pathname.removeLastSegments(1));
ZipEntry newEntry = new ZipEntry(pathname.toString());
directoryEntryCache.put(pathname, newEntry);
List childList = new ArrayList();
children.put(newEntry, childList);
List parentChildList = (List) children.get(parent);
parentChildList.add(newEntry);
return newEntry;
}
/**
* Creates a new file zip entry with the specified name.
*/
protected void createFile(ZipEntry entry) {
IPath pathname = new Path(entry.getName());
ZipEntry parent;
if (pathname.segmentCount() == 1)
parent = root;
else
parent = (ZipEntry) directoryEntryCache.get(pathname
.removeLastSegments(1));
List childList = (List) children.get(parent);
childList.add(entry);
}
/*
* (non-Javadoc) Method declared on IImportStructureProvider
*/
public List getChildren(Object element) {
if (children == null)
initialize();
return ((List) children.get(element));
}
/*
* (non-Javadoc) Method declared on IImportStructureProvider
*/
public InputStream getContents(Object element) {
try {
return zipFile.getInputStream((ZipEntry) element);
} catch (IOException e) {
return null;
}
}
/*
* Strip the leading directories from the path
*/
private String stripPath(String path) {
String pathOrig = new String(path);
for (int i = 0; i < stripLevel; i++) {
int firstSep = path.indexOf('/');
// If the first character was a seperator we must strip to the next
// seperator as well
if (firstSep == 0) {
path = path.substring(1);
firstSep = path.indexOf('/');
}
// No seperator wasw present so we're in a higher directory right
// now
if (firstSep == -1)
return pathOrig;
path = path.substring(firstSep);
}
return path;
}
/*
* (non-Javadoc) Method declared on IImportStructureProvider
*/
public String getFullPath(Object element) {
return stripPath(((ZipEntry) element).getName());
}
/*
* (non-Javadoc) Method declared on IImportStructureProvider
*/
public String getLabel(Object element) {
if (element.equals(root))
return ((ZipEntry) element).getName();
return stripPath(new Path(((ZipEntry) element).getName()).lastSegment());
}
/**
* Returns the entry that this importer uses as the root sentinel.
*
* @return java.util.zip.ZipEntry
*/
public Object getRoot() {
return root;
}
/**
* Returns the zip file that this provider provides structure for.
*
* @return The zip file
*/
public ZipFile getZipFile() {
return zipFile;
}
/**
* Initializes this object's children table based on the contents of the
* specified source file.
*/
protected void initialize() {
children = new HashMap(1000);
children.put(root, new ArrayList());
Enumeration entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
IPath path = new Path(entry.getName()).addTrailingSeparator();
if (entry.isDirectory())
createContainer(path);
else
{
// Ensure the container structure for all levels above this is initialized
// Once we hit a higher-level container that's already added we need go no further
int pathSegmentCount = path.segmentCount();
if (pathSegmentCount > 1)
createContainer(path.uptoSegment(pathSegmentCount - 1));
createFile(entry);
}
}
}
/*
* (non-Javadoc) Method declared on IImportStructureProvider
*/
public boolean isFolder(Object element) {
return ((ZipEntry) element).isDirectory();
}
public void setStrip(int level) {
stripLevel = level;
}
public int getStrip() {
return stripLevel;
}
}