/*******************************************************************************
* Copyright (c) 2014 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.cdi.core.test;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
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.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import org.jboss.tools.tests.ImportProvider;
import org.osgi.framework.Bundle;
/**
* @author Viacheslav Kabanovich
*/
public class TemplateMerger {
/**
* Creates ImportOperation that adds resources to containerPath
* from updatingTemplateLocation in bundle, excluding files with same paths
* existing in currentTemplateLocation in bundle.
*
* @param containerPath - path to container in the workspace to be updated
* @param bundle - root for templates
* @param currentTemplateLocation - templates that should not be updated
* @param updatingTemplateLocation - templates that should be copied into container if they are not in currentTemplateLocation
* @return
* @throws IOException
* @throws CoreException
* @throws InvocationTargetException
*/
public static ImportOperation createImportOperation(IPath containerPath, Bundle bundle, String currentTemplateLocation, String updatingTemplateLocation) throws IOException, CoreException, InvocationTargetException {
IOverwriteQuery overwrite = new IOverwriteQuery() {
public String queryOverwrite(String pathString) {
return ALL;
}
};
ProviderWrapper currentProvider = new ProviderWrapper(bundle, currentTemplateLocation);
ProviderWrapper updatingProvider = new ProviderWrapper(bundle, updatingTemplateLocation);
MergingProvider mergingProvider = new MergingProvider(
currentProvider.getStructureProvider(), currentProvider.getStructureRootHandle(),
updatingProvider.getStructureProvider(), updatingProvider.getStructureRootHandle());
ImportOperation result = new ImportOperation(
containerPath,
mergingProvider.source,
mergingProvider,
overwrite);
// import files just to project folder ( without old structure )
result.setCreateContainerStructure(false);
return result;
}
/**
* Helper that creates for templLocation in bundle its structure provider
* and that structure's root handle object.
*
*/
public static class ProviderWrapper {
private IImportStructureProvider provider = null;
private Object source = null;
public ProviderWrapper(Bundle bundle, String templLocation) throws IOException, CoreException, InvocationTargetException {
String path = FileLocator.resolve(bundle.getEntry(templLocation)).getFile();
String protocol = FileLocator.resolve(bundle.getEntry(templLocation)).getProtocol();
if("jar".equals(protocol)) {
String pathToZip = path.substring(0,path.indexOf("!"));
String zipEntryName = path.substring(path.indexOf("!") + 2, path.length());
pathToZip = pathToZip.substring("file:".length());
ZipFileStructureProvider zipStrProvider = new ZipFileStructureProvider(new ZipFile(pathToZip));
provider = zipStrProvider;
source = getZipEntry(zipStrProvider, zipEntryName);
} else {
ImportProvider importProvider = new ImportProvider();
provider = importProvider;
source = new File(path);
// need to remove from imported project "svn" files
List<String> unimportedFiles = new ArrayList<String>();
unimportedFiles.add(".svn"); //$NON-NLS-1$
importProvider.setUnimportedFiles(unimportedFiles);
}
}
/**
* Returns computed structure provider.
*
* @return
*/
public IImportStructureProvider getStructureProvider() {
return provider;
}
/**
* Returns root handle object for the structure provider.
* @return
*/
public Object getStructureRootHandle() {
return source;
}
}
private static ZipEntry getZipEntry(ZipFileStructureProvider zipStrProvider, String zipEntryName) {
String[] entries = zipEntryName.split("/");
ZipEntry parent = zipStrProvider.getRoot();
for (String string : entries) {
List<?> children = zipStrProvider.getChildren(parent);
for (Object object : children) {
ZipEntry current = (ZipEntry)object;
String name = parent== zipStrProvider.getRoot()? string + "/": parent.getName() + string + "/";
if(name.equals(current.getName())) {
parent = current;
break;
}
}
}
return parent;
}
/**
* Provider that returns structure of updatingSource obtained with updatingProvider
* minus structure of currentSource obtained with currentProvider.
*
*/
public static class MergingProvider implements IImportStructureProvider {
private static class CombinedSource {
Object currentSource;
Object updatingSource;
CombinedSource(Object currentSource, Object updatingSource) {
this.updatingSource = updatingSource;
this.currentSource = currentSource;
}
}
IImportStructureProvider currentProvider;
IImportStructureProvider updatingProvider;
CombinedSource source;
public MergingProvider(IImportStructureProvider currentProvider, Object currentSource,
IImportStructureProvider updatingProvider, Object updatingSource) {
this.updatingProvider = updatingProvider;
this.currentProvider = currentProvider;
source = new CombinedSource(currentSource, updatingSource);
}
@Override
public List<Object> getChildren(Object element) {
if(element instanceof CombinedSource) {
List<Object> result = new ArrayList<Object>();
Map<String, Object> map12 = new HashMap<String, Object>();
if(((CombinedSource)element).currentSource != null) {
for (Object c12: currentProvider.getChildren(((CombinedSource)element).currentSource)) {
map12.put(currentProvider.getLabel(c12), c12);
}
}
for (Object c11: updatingProvider.getChildren(((CombinedSource)element).updatingSource)) {
String label = updatingProvider.getLabel(c11);
Object c12 = map12.get(label);
if(c12 == null || (currentProvider.isFolder(c12) && !"lib".equals(label))) {
result.add(new CombinedSource(c12, c11));
} else {
// System.out.println("Filtered out: " + updatingProvider.getFullPath(c11));
}
}
return result;
}
return null;
}
@Override
public InputStream getContents(Object element) {
if(element instanceof CombinedSource) {
return updatingProvider.getContents(((CombinedSource)element).updatingSource);
}
return null;
}
@Override
public String getFullPath(Object element) {
if(element instanceof CombinedSource) {
return updatingProvider.getFullPath(((CombinedSource)element).updatingSource);
}
return null;
}
@Override
public String getLabel(Object element) {
if(element instanceof CombinedSource) {
return updatingProvider.getLabel(((CombinedSource)element).updatingSource);
}
return null;
}
@Override
public boolean isFolder(Object element) {
if(element instanceof CombinedSource) {
return updatingProvider.isFolder(((CombinedSource)element).updatingSource);
}
return false;
}
}
}