/*******************************************************************************
* Copyright (c) 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
*******************************************************************************/
package org.eclipse.buckminster.pde.internal.imports;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipFile;
import org.eclipse.buckminster.pde.PDEPlugin;
import org.eclipse.buckminster.pde.internal.datatransfer.IImportStructureProvider;
import org.eclipse.buckminster.pde.internal.datatransfer.ImportOperation;
import org.eclipse.buckminster.pde.internal.datatransfer.ZipFileStructureProvider;
import org.eclipse.buckminster.pde.internal.dialogs.IOverwriteQuery;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.pde.internal.core.util.CoreUtility;
@SuppressWarnings({ "rawtypes", "unchecked", "restriction" })
public abstract class JarImportOperation implements IWorkspaceRunnable {
protected void collectAdditionalResources(ZipFileStructureProvider provider, Object element, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
// ignore source folders
if (folderContainsFileExtension(provider, curr, ".java")) //$NON-NLS-1$
continue;
collected.add(curr);
} else if (!provider.getLabel(curr).endsWith(".java")) { //$NON-NLS-1$
collected.add(curr);
}
}
}
}
protected void collectJavaFiles(ZipFileStructureProvider provider, Object element, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (provider.getLabel(curr).equals("src")) { //$NON-NLS-1$
ArrayList list = new ArrayList();
collectResources(provider, curr, false, list);
collected.addAll(list);
}
}
}
}
}
protected void collectJavaResources(ZipFileStructureProvider provider, Object element, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (isClassFolder(provider, curr)) {
ArrayList list = new ArrayList();
collectResources(provider, curr, false, list);
collected.addAll(list);
}
}
}
}
}
/**
* Recursively searches the children of the given element inside of a zip
* file. If the folder path is in the set of folders to ignore, the folder
* will be skipped. All files found, except for .class files, will be added.
* The given list will be updated with the source files.
*
* @param provider
* zip provider
* @param element
* current element inside the zip
* @param ignoreFolders
* list of IPath folder paths to skip while searching
* @param collected
* list to update with new files found to import
* @since 3.4
*/
protected void collectJavaSource(ZipFileStructureProvider provider, Object element, List ignoreFolders, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
// Check if we are in an ignored folder
List ignoreSubFolders = new ArrayList();
boolean ignoreThisChild = false;
for (Iterator iterator = ignoreFolders.iterator(); iterator.hasNext();) {
IPath currentPath = (IPath) iterator.next();
if (provider.getLabel(curr).equals(currentPath.segment(0))) {
if (currentPath.segmentCount() > 1) {
// There is a subfolder that should be ignored.
// Remove segment referencing current
// folder.
ignoreSubFolders.add(currentPath.removeFirstSegments(1));
} else {
// This folder should be ignored
ignoreThisChild = true;
break;
}
}
}
if (!ignoreThisChild) {
collectJavaSource(provider, curr, ignoreSubFolders, collected);
}
// Add the file to the list
} else if (!provider.getLabel(curr).endsWith(".class")) { //$NON-NLS-1$
collected.add(curr);
}
}
}
}
/**
* Searches through the zip file for java source folders. Collects the files
* within the source folders. If a folder is in the list of folder paths to
* ignore, the folder will be skipped.
*
* @param provider
* zip provider
* @param ignoreFolders
* list of IPaths describing folders to ignore
* @param collected
* list that source files will be added to
* @since 3.4
*/
protected void collectJavaSourceFromRoot(ZipFileStructureProvider provider, List ignoreFolders, ArrayList collected) {
List children = provider.getChildren(provider.getRoot());
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr) && folderContainsFileExtension(provider, curr, ".java")) { //$NON-NLS-1$
// Check if we are in an ignored folder
List ignoreSubFolders = new ArrayList();
boolean ignoreThisChild = false;
for (Iterator iterator = ignoreFolders.iterator(); iterator.hasNext();) {
IPath currentPath = (IPath) iterator.next();
if (provider.getLabel(curr).equals(currentPath.segment(0))) {
if (currentPath.segmentCount() > 1) {
// There is a subfolder that should be ignored
ignoreSubFolders.add(currentPath.removeFirstSegments(1));
} else {
// This folder should be ignored
ignoreThisChild = true;
break;
}
}
}
if (!ignoreThisChild) {
collectJavaSource(provider, curr, ignoreSubFolders, collected);
}
}
}
}
}
protected void collectNonJavaResources(ZipFileStructureProvider provider, Object element, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (!provider.getLabel(curr).equals("src") && !isClassFolder(provider, curr)) { //$NON-NLS-1$
ArrayList list = new ArrayList();
collectResources(provider, curr, false, list);
collected.addAll(list);
}
} else if (!provider.getLabel(curr).endsWith(".class")) { //$NON-NLS-1$
collected.add(curr);
}
}
}
}
/**
* Recursively searches through the zip files searching for files inside of
* the specified folder. The files found will be added to the given list.
*
* @param provider
* zip provider
* @param element
* element of the zip currently being looked at
* @param folderPath
* location of the folder to get resources from
* @param collected
* list of files found
* @since 3.4
*/
protected void collectResourcesFromFolder(ZipFileStructureProvider provider, Object element, IPath folderPath, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (provider.getLabel(curr).equals(folderPath.segment(0))) {
if (folderPath.segmentCount() > 1) {
collectResourcesFromFolder(provider, curr, folderPath.removeFirstSegments(1), collected);
} else {
collectResources(provider, curr, false, collected);
}
}
}
}
}
}
protected boolean containsCode(File file) {
try {
ZipFile zipFile = new ZipFile(file);
try {
return containsCode(new ZipFileStructureProvider(zipFile));
} finally {
zipFile.close();
}
} catch (IOException e) {
return false;
}
}
protected boolean containsCode(ZipFileStructureProvider provider) {
List children = provider.getChildren(provider.getRoot());
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr) && isClassFolder(provider, curr)) {
return true;
}
}
}
return false;
}
protected void extractJavaResources(File file, IResource dest, IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(file);
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
ArrayList collected = new ArrayList();
collectJavaResources(provider, provider.getRoot(), collected);
importContent(provider.getRoot(), dest.getFullPath(), provider, collected, monitor);
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
/**
* Searches the given archive file for java source folders. Imports the
* files in the source folders to the specified destination unless the
* folder is in the list of folders to exclude.
*
* @param file
* archive file to search for source in
* @param excludeFolders
* list of IPaths describing folders to ignore while searching
* @param dest
* destination to put the extracted source
* @param monitor
* progress monitor
* @throws CoreException
* if there is a problem extracting source from the zip
* @since 3.4
*/
protected void extractJavaSource(File file, List excludeFolders, IResource dest, IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(file);
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
ArrayList collected = new ArrayList();
collectJavaSourceFromRoot(provider, excludeFolders, collected);
importContent(provider.getRoot(), dest.getFullPath(), provider, collected, monitor);
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
protected void extractResources(File file, IResource dest, IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(file);
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
ArrayList collected = new ArrayList();
collectResources(provider, provider.getRoot(), true, collected);
importContent(provider.getRoot(), dest.getFullPath(), provider, collected, monitor);
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
/**
* Extracts all of the files and subfolders from a single folder within an
* archive file.
*
* @param file
* archive file to search for files
* @param folderPath
* path to the folder to extract from
* @param dest
* destination to import content to
* @param monitor
* progress monitor
* @throws CoreException
* if a problem occurs while extracting
* @since 3.4
*/
protected void extractResourcesFromFolder(File file, IPath folderPath, IResource dest, IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(file);
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
ArrayList collected = new ArrayList();
collectResourcesFromFolder(provider, provider.getRoot(), folderPath, collected);
importContent(provider.getRoot(), dest.getFullPath(), provider, collected, monitor);
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
protected void extractZipFile(File file, IPath destPath, IProgressMonitor monitor) throws CoreException {
try {
ZipFile zipFile = new ZipFile(file);
try {
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
importContent(provider.getRoot(), destPath, provider, null, monitor);
} finally {
zipFile.close();
}
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.ERROR, e.getMessage(), e);
throw new CoreException(status);
}
}
protected String[] getTopLevelResources(File file) {
ArrayList result = new ArrayList();
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
ZipFileStructureProvider provider = new ZipFileStructureProvider(zipFile);
List children = provider.getChildren(provider.getRoot());
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (!isClassFolder(provider, curr))
result.add(provider.getLabel(curr) + "/"); //$NON-NLS-1$
else {
if (!result.contains(".")) //$NON-NLS-1$
result.add("."); //$NON-NLS-1$
}
} else {
result.add(provider.getLabel(curr));
}
}
}
} catch (IOException e) {
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (IOException e) {
}
}
}
return (String[]) result.toArray(new String[result.size()]);
}
protected boolean hasEmbeddedSource(ZipFileStructureProvider provider) {
List children = provider.getChildren(provider.getRoot());
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr) && provider.getLabel(curr).equals("src")) { //$NON-NLS-1$
return true;
}
}
}
return false;
}
protected void importArchive(IProject project, File archive, IPath destPath) throws CoreException {
try {
if (destPath.segmentCount() > 2)
CoreUtility.createFolder(project.getFolder(destPath.removeLastSegments(1)));
IFile file = project.getFile(destPath);
FileInputStream fstream = new FileInputStream(archive);
if (file.exists())
file.setContents(fstream, true, false, null);
else
file.create(fstream, true, null);
fstream.close();
} catch (IOException e) {
IStatus status = new Status(IStatus.ERROR, PDEPlugin.getPluginId(), IStatus.OK, e.getMessage(), e);
throw new CoreException(status);
}
}
protected void importContent(Object source, IPath destPath, IImportStructureProvider provider, List filesToImport, IProgressMonitor monitor)
throws CoreException {
IOverwriteQuery query = new IOverwriteQuery() {
@Override
public String queryOverwrite(String file) {
return ALL;
}
};
ImportOperation op = new ImportOperation(destPath, source, provider, query);
op.setCreateContainerStructure(false);
if (filesToImport != null) {
op.setFilesToImport(filesToImport);
}
IStatus status = op.runInWorkspace(monitor);
if (status.getSeverity() == IStatus.ERROR)
throw new CoreException(status);
}
private void collectResources(ZipFileStructureProvider provider, Object element, boolean excludeMeta, ArrayList collected) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (!excludeMeta || !provider.getLabel(curr).equals("META-INF")) { //$NON-NLS-1$
collectResources(provider, curr, excludeMeta, collected);
}
} else if (!provider.getLabel(curr).endsWith(".class")) { //$NON-NLS-1$
collected.add(curr);
}
}
}
}
private boolean folderContainsFileExtension(ZipFileStructureProvider provider, Object element, String fileExtension) {
List children = provider.getChildren(element);
if (children != null && !children.isEmpty()) {
for (int i = 0; i < children.size(); i++) {
Object curr = children.get(i);
if (provider.isFolder(curr)) {
if (folderContainsFileExtension(provider, curr, fileExtension)) {
return true;
}
} else if (provider.getLabel(curr).endsWith(fileExtension)) {
return true;
}
}
}
return false;
}
private boolean isClassFolder(ZipFileStructureProvider provider, Object element) {
return folderContainsFileExtension(provider, element, ".class"); //$NON-NLS-1$
}
}