001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: * Red Hat, Inc - Was ZipFileStructureProvider, performed changes from
011: * IImportStructureProvider to ILeveledImportStructureProvider
012: *******************************************************************************/package org.eclipse.ui.internal.wizards.datatransfer;
013:
014: import java.io.IOException;
015: import java.io.InputStream;
016: import java.util.ArrayList;
017: import java.util.Enumeration;
018: import java.util.HashMap;
019: import java.util.List;
020: import java.util.Map;
021: import java.util.zip.ZipEntry;
022: import java.util.zip.ZipFile;
023:
024: import org.eclipse.core.runtime.IPath;
025: import org.eclipse.core.runtime.Path;
026: import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
027:
028: /**
029: * This class provides information regarding the context structure and content
030: * of specified zip file entry objects.
031: *
032: * @since 3.1
033: */
034: public class ZipLeveledStructureProvider implements
035: ILeveledImportStructureProvider {
036: private ZipFile zipFile;
037:
038: private ZipEntry root = new ZipEntry("/");//$NON-NLS-1$
039:
040: private Map children;
041:
042: private Map directoryEntryCache = new HashMap();
043:
044: private int stripLevel;
045:
046: /**
047: * Creates a <code>ZipFileStructureProvider</code>, which will operate on
048: * the passed zip file.
049: *
050: * @param sourceFile
051: * The source file to create the ZipLeveledStructureProvider
052: * around
053: */
054: public ZipLeveledStructureProvider(ZipFile sourceFile) {
055: super ();
056: zipFile = sourceFile;
057: stripLevel = 0;
058: }
059:
060: /**
061: * Creates a new container zip entry with the specified name, iff it has
062: * not already been created. If the parent of the given element does not
063: * already exist it will be recursively created as well.
064: * @param pathname The path representing the container
065: * @return The element represented by this pathname (it may have already existed)
066: */
067: protected ZipEntry createContainer(IPath pathname) {
068: ZipEntry existingEntry = (ZipEntry) directoryEntryCache
069: .get(pathname);
070: if (existingEntry != null) {
071: return existingEntry;
072: }
073:
074: ZipEntry parent;
075: if (pathname.segmentCount() == 1) {
076: parent = root;
077: } else {
078: parent = createContainer(pathname.removeLastSegments(1));
079: }
080: ZipEntry newEntry = new ZipEntry(pathname.toString());
081: directoryEntryCache.put(pathname, newEntry);
082: List childList = new ArrayList();
083: children.put(newEntry, childList);
084:
085: List parentChildList = (List) children.get(parent);
086: parentChildList.add(newEntry);
087: return newEntry;
088: }
089:
090: /**
091: * Creates a new file zip entry with the specified name.
092: */
093: protected void createFile(ZipEntry entry) {
094: IPath pathname = new Path(entry.getName());
095: ZipEntry parent;
096: if (pathname.segmentCount() == 1) {
097: parent = root;
098: } else {
099: parent = (ZipEntry) directoryEntryCache.get(pathname
100: .removeLastSegments(1));
101: }
102:
103: List childList = (List) children.get(parent);
104: childList.add(entry);
105: }
106:
107: /*
108: * (non-Javadoc) Method declared on IImportStructureProvider
109: */
110: public List getChildren(Object element) {
111: if (children == null) {
112: initialize();
113: }
114:
115: return ((List) children.get(element));
116: }
117:
118: /*
119: * (non-Javadoc) Method declared on IImportStructureProvider
120: */
121: public InputStream getContents(Object element) {
122: try {
123: return zipFile.getInputStream((ZipEntry) element);
124: } catch (IOException e) {
125: IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e);
126: return null;
127: }
128: }
129:
130: /*
131: * Strip the leading directories from the path
132: */
133: private String stripPath(String path) {
134: String pathOrig = new String(path);
135: for (int i = 0; i < stripLevel; i++) {
136: int firstSep = path.indexOf('/');
137: // If the first character was a seperator we must strip to the next
138: // seperator as well
139: if (firstSep == 0) {
140: path = path.substring(1);
141: firstSep = path.indexOf('/');
142: }
143: // No seperator wasw present so we're in a higher directory right
144: // now
145: if (firstSep == -1) {
146: return pathOrig;
147: }
148: path = path.substring(firstSep);
149: }
150: return path;
151: }
152:
153: /*
154: * (non-Javadoc) Method declared on IImportStructureProvider
155: */
156: public String getFullPath(Object element) {
157: return stripPath(((ZipEntry) element).getName());
158: }
159:
160: /*
161: * (non-Javadoc) Method declared on IImportStructureProvider
162: */
163: public String getLabel(Object element) {
164: if (element.equals(root)) {
165: return ((ZipEntry) element).getName();
166: }
167:
168: return stripPath(new Path(((ZipEntry) element).getName())
169: .lastSegment());
170: }
171:
172: /**
173: * Returns the entry that this importer uses as the root sentinel.
174: *
175: * @return java.util.zip.ZipEntry
176: */
177: public Object getRoot() {
178: return root;
179: }
180:
181: /**
182: * Returns the zip file that this provider provides structure for.
183: *
184: * @return The zip file
185: */
186: public ZipFile getZipFile() {
187: return zipFile;
188: }
189:
190: /*
191: * (non-Javadoc)
192: * @see org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider#closeArchive()
193: */
194: public boolean closeArchive() {
195: try {
196: getZipFile().close();
197: } catch (IOException e) {
198: IDEWorkbenchPlugin.log(
199: DataTransferMessages.ZipImport_couldNotClose
200: + getZipFile().getName(), e);
201: return false;
202: }
203: return true;
204: }
205:
206: /**
207: * Initializes this object's children table based on the contents of the
208: * specified source file.
209: */
210: protected void initialize() {
211: children = new HashMap(1000);
212:
213: children.put(root, new ArrayList());
214: Enumeration entries = zipFile.entries();
215: while (entries.hasMoreElements()) {
216: ZipEntry entry = (ZipEntry) entries.nextElement();
217: IPath path = new Path(entry.getName())
218: .addTrailingSeparator();
219:
220: if (entry.isDirectory()) {
221: createContainer(path);
222: } else {
223: // Ensure the container structure for all levels above this is initialized
224: // Once we hit a higher-level container that's already added we need go no further
225: int pathSegmentCount = path.segmentCount();
226: if (pathSegmentCount > 1) {
227: createContainer(path
228: .uptoSegment(pathSegmentCount - 1));
229: }
230: createFile(entry);
231: }
232: }
233: }
234:
235: /*
236: * (non-Javadoc) Method declared on IImportStructureProvider
237: */
238: public boolean isFolder(Object element) {
239: return ((ZipEntry) element).isDirectory();
240: }
241:
242: public void setStrip(int level) {
243: stripLevel = level;
244: }
245:
246: public int getStrip() {
247: return stripLevel;
248: }
249: }
|