/******************************************************************************* * Copyright (c) 2009 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 * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.ui.phar.wizard; import java.io.IOException; import java.io.InputStream; import java.util.*; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.php.internal.core.phar.PharEntry; import org.eclipse.php.internal.core.phar.PharFile; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.wizards.datatransfer.DataTransferMessages; import org.eclipse.ui.internal.wizards.datatransfer.ILeveledImportStructureProvider; public class PharLeveledStructureProvider implements ILeveledImportStructureProvider { private PharFile tarFile; private PharEntry root = new PharEntry(); private Map children; private Map directoryEntryCache = new HashMap(); private int stripLevel; /** * Creates a <code>TarFileStructureProvider</code>, which will operate on * the passed tar file. * * @param sourceFile * the source TarFile */ public PharLeveledStructureProvider(PharFile sourceFile) { super(); tarFile = sourceFile; root.setName("/"); //$NON-NLS-1$ } /** * Creates a new container tar 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 PharEntry createContainer(IPath pathname) { PharEntry existingEntry = (PharEntry) directoryEntryCache.get(pathname); if (existingEntry != null) { return existingEntry; } PharEntry parent; if (pathname.segmentCount() == 1) { parent = root; } else { parent = createContainer(pathname.removeLastSegments(1)); } PharEntry newEntry = new PharEntry(); newEntry.setName(pathname.toString()); // newEntry.setFileType(TarEntry.DIRECTORY); 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 tar file entry with the specified name. */ protected void createFile(PharEntry entry) { IPath pathname = new Path(entry.getName()); PharEntry parent; if (pathname.segmentCount() == 1) { parent = root; } else { parent = (PharEntry) directoryEntryCache.get(pathname.removeLastSegments(1)); } List childList = (List) children.get(parent); childList.add(entry); } /* * (non-Javadoc) Method declared on IImportStructureProvider */ @Override public List getChildren(Object element) { if (children == null) { initialize(); } return ((List) children.get(element)); } /* * (non-Javadoc) Method declared on IImportStructureProvider */ @Override public InputStream getContents(Object element) { try { return tarFile.getInputStream((PharEntry) element); } catch (IOException e) { IDEWorkbenchPlugin.log(e.getLocalizedMessage(), e); return null; } } /** * Returns the resource attributes for this file. * * @param element * @return the attributes of the file */ // public ResourceAttributes getResourceAttributes(Object element) { // ResourceAttributes attributes = new ResourceAttributes(); // PharEntry entry = (PharEntry) element; // // attributes.setExecutable((entry.getMode() & 0100) != 0); // // attributes.setReadOnly((entry.getMode() & 0200) == 0); // return attributes; // } /* * (non-Javadoc) Method declared on IImportStructureProvider */ @Override public String getFullPath(Object element) { return stripPath(((PharEntry) element).getName()); } /* * (non-Javadoc) Method declared on IImportStructureProvider */ @Override public String getLabel(Object element) { if (element.equals(root)) { return ((PharEntry) element).getName(); } return stripPath(new Path(((PharEntry) element).getName()).lastSegment()); } /** * Returns the entry that this importer uses as the root sentinel. * * @return TarEntry entry */ @Override public Object getRoot() { return root; } /** * Returns the tar file that this provider provides structure for. * * @return TarFile file */ public PharFile getPharFile() { return tarFile; } /* * (non-Javadoc) * * @see org.eclipse.ui.internal.wizards.datatransfer. * ILeveledImportStructureProvider #closeArchive() */ @Override public boolean closeArchive() { try { getPharFile().close(); } catch (IOException e) { IDEWorkbenchPlugin.log(DataTransferMessages.ZipImport_couldNotClose + getPharFile().getName(), e); return false; } return true; } /** * 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()); Iterator<PharEntry> entries = tarFile.getPharEntryMap().values().iterator(); while (entries.hasNext()) { PharEntry entry = (PharEntry) entries.next(); 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 */ @Override public boolean isFolder(Object element) { return ((PharEntry) element).isDirectory(); } /* * Strip the leading directories from the path */ private String stripPath(String path) { String pathOrig = 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; } @Override public void setStrip(int level) { stripLevel = level; } @Override public int getStrip() { return stripLevel; } }