blob: 69558522dba70fbf5b4e0772350c8884c520853b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 Soyatec (http://www.soyatec.com) 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:
* Soyatec - initial API and implementation
* Sopot Cela - ongoing enhancements
*******************************************************************************/
package org.eclipse.e4.internal.tools.wizards.project;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.e4.internal.tools.ToolsPlugin;
import org.eclipse.pde.internal.ui.PDEUIMessages;
import org.eclipse.pde.ui.templates.IVariableProvider;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
public class TemplateOperation extends WorkspaceModifyOperation implements
IVariableProvider {
private final URL templateDirectory;
private final IContainer target;
private final Map<String, String> keys;
private final Set<String> binaryExtentions;
private final boolean isMinimalist;
public TemplateOperation(URL source, IContainer target,
Map<String, String> keys, Set<String> binaryExtentions, boolean justProduct) {
templateDirectory = source;
this.binaryExtentions = binaryExtentions;
this.target = target;
this.keys = keys;
isMinimalist = justProduct;
}
@Override
protected void execute(IProgressMonitor monitor) throws CoreException,
InvocationTargetException, InterruptedException {
monitor.setTaskName(PDEUIMessages.AbstractTemplateSection_generating);
if ("jar".equals(templateDirectory.getProtocol())) { //$NON-NLS-1$
final String file = templateDirectory.getFile();
final int exclamation = file.indexOf('!');
if (exclamation < 0) {
return;
}
URL fileUrl = null;
try {
fileUrl = new URL(file.substring(0, exclamation));
} catch (final MalformedURLException mue) {
ToolsPlugin.logError(mue);
return;
}
final File pluginJar = new File(fileUrl.getFile());
if (!pluginJar.exists()) {
return;
}
final String templateDirectory = file.substring(exclamation + 1); // "/some/path/"
final IPath path = new Path(templateDirectory);
ZipFile zipFile = null;
try {
zipFile = new ZipFile(pluginJar);
generateFiles(zipFile, path, target, monitor);
} catch (final ZipException ze) {
} catch (final IOException ioe) {
} finally {
if (zipFile != null) {
try {
zipFile.close();
} catch (final IOException e) {
}
}
}
} else if ("file".equals(templateDirectory.getProtocol())) { //$NON-NLS-1$
final File directory = new File(templateDirectory.getFile());
if (!directory.exists()) {
return;
}
generateFiles(directory, target, true, monitor);
}
}
private void generateFiles(File src, IContainer dst, boolean firstLevel,
IProgressMonitor monitor) throws CoreException {
if (!firstLevel && isMinimalist) {
return;
}
final File[] members = src.listFiles();
for (int i = 0; i < members.length; i++) {
final File member = members[i];
final String name = member.getName();
if (member.isDirectory()) {
if (".svn".equals(name) || "cvs".equalsIgnoreCase(name)) { //$NON-NLS-1$ //$NON-NLS-2$
continue;
}
IContainer dstContainer = null;
if (dstContainer == null) {
final String folderName = getProcessedString(name, name);
dstContainer = dst.getFolder(new Path(folderName));
}
if (dstContainer != null && !dstContainer.exists()) {
((IFolder) dstContainer).create(true, true, monitor);
}
generateFiles(member, dstContainer, false, monitor);
} else {
InputStream in = null;
try {
in = new FileInputStream(member);
copyFile(name, in, dst, monitor);
} catch (final IOException ioe) {
} finally {
if (in != null) {
try {
in.close();
} catch (final IOException ioe2) {
}
}
}
}
}
}
/**
*
*
* @param zipFile
* @param path
* @param dst
* @param monitor
* @throws CoreException
*/
private void generateFiles(ZipFile zipFile, IPath path, IContainer dst,
IProgressMonitor monitor) throws CoreException {
final int pathLength = path.segmentCount();
// Immidiate children
final Map childZipEntries = new HashMap(); // "dir/" or "dir/file.java"
for (final Enumeration zipEntries = zipFile.entries(); zipEntries
.hasMoreElements();) {
final ZipEntry zipEntry = (ZipEntry) zipEntries.nextElement();
final IPath entryPath = new Path(zipEntry.getName());
if (entryPath.segmentCount() <= pathLength) {
// ancestor or current directory
continue;
}
if (!path.isPrefixOf(entryPath)) {
// not a descendant
continue;
}
if (entryPath.segmentCount() == pathLength + 1) {
childZipEntries.put(zipEntry.getName(), zipEntry);
} else {
final String name = entryPath.uptoSegment(pathLength + 1)
.addTrailingSeparator().toString();
if (!childZipEntries.containsKey(name)) {
final ZipEntry dirEntry = new ZipEntry(name);
childZipEntries.put(name, dirEntry);
}
}
}
for (final Iterator it = childZipEntries.values().iterator(); it.hasNext();) {
final ZipEntry zipEnry = (ZipEntry) it.next();
final String name = new Path(zipEnry.getName()).lastSegment().toString();
if (zipEnry.isDirectory()) {
IContainer dstContainer = null;
if (dstContainer == null) {
final String folderName = getProcessedString(name, name);
dstContainer = dst.getFolder(new Path(folderName));
}
if (dstContainer != null && !dstContainer.exists()) {
((IFolder) dstContainer).create(true, true, monitor);
}
generateFiles(zipFile, path.append(name), dstContainer, monitor);
} else {
InputStream in = null;
try {
in = zipFile.getInputStream(zipEnry);
copyFile(name, in, dst, monitor);
} catch (final IOException ioe) {
} finally {
if (in != null) {
try {
in.close();
} catch (final IOException ioe2) {
}
}
}
}
}
}
private void copyFile(String fileName, InputStream input, IContainer dst,
IProgressMonitor monitor) throws CoreException {
final String targetFileName = getProcessedString(fileName, fileName);
monitor.subTask(targetFileName);
final IFile dstFile = dst.getFile(new Path(targetFileName));
try {
final InputStream stream = isBinary(fileName) ? input
: getProcessedStream(fileName, input);
if (dstFile.exists()) {
dstFile.setContents(stream, true, true, monitor);
} else {
dstFile.create(stream, true, monitor);
}
stream.close();
} catch (final IOException e) {
}
}
protected void copyFile(String fileName, InputStream input, IContainer dst,
final String destPath, IProgressMonitor monitor)
throws CoreException {
String targetFileName = null;
if (destPath == null) {
targetFileName = getProcessedString(fileName, fileName);
} else {
targetFileName = destPath;
}
monitor.subTask(targetFileName);
final IFile dstFile = dst.getFile(new Path(targetFileName));
try {
final InputStream stream = isBinary(fileName) ? input
: getProcessedStream(fileName, input);
if (dstFile.exists()) {
dstFile.setContents(stream, true, true, monitor);
} else {
dstFile.create(stream, true, monitor);
}
stream.close();
} catch (final IOException e) {
}
}
/**
*
* @param fileName
* @param input
* @param dst
* @param basePath
* @param monitor
* @throws CoreException
*/
public void copyFile(String fileName, InputStream input, IContainer dst,
final String basePath, final String destName,
IProgressMonitor monitor) throws CoreException {
if (basePath == null || basePath.equals("")) { //$NON-NLS-1$
copyFile(fileName, input, dst, monitor);
}
final String targetFileName = destName == null ? getProcessedString(fileName,
fileName) : destName;
monitor.subTask(targetFileName);
final IFile dstFile = dst.getFile(new Path(basePath + targetFileName));
try {
final InputStream stream = isBinary(fileName) ? input
: getProcessedStream(fileName, input);
if (dstFile.exists()) {
dstFile.setContents(stream, true, true, monitor);
} else {
dstFile.create(stream, true, monitor);
}
stream.close();
} catch (final IOException e) {
}
}
private boolean isBinary(String fileName) {
if (binaryExtentions == null) {
return false;
}
final String ext = getfileExtention(fileName);
if (ext == null) {
return false;
}
return binaryExtentions.contains(ext);
}
private String getfileExtention(String name) {
final int indexOf = name.lastIndexOf('.');
if (indexOf == -1) {
return null;
}
return name.substring(indexOf);
}
private InputStream getProcessedStream(String fileName, InputStream stream)
throws IOException, CoreException {
final InputStreamReader reader = new InputStreamReader(stream);
final int bufsize = 1024;
final char[] cbuffer = new char[bufsize];
int read = 0;
final StringBuffer keyBuffer = new StringBuffer();
final StringBuffer outBuffer = new StringBuffer();
boolean replacementMode = false;
boolean almostReplacementMode = false;
boolean escape = false;
while (read != -1) {
read = reader.read(cbuffer);
for (int i = 0; i < read; i++) {
final char c = cbuffer[i];
if (escape) {
final StringBuffer buf = outBuffer;
buf.append(c);
escape = false;
continue;
}
if (c == '@') {
if (replacementMode && almostReplacementMode) {
almostReplacementMode = false;
} else if (replacementMode) {
replacementMode = false;
final String key = keyBuffer.toString();
final String value = key.length() == 0 ? "@@" //$NON-NLS-1$
: getReplacementString(key);
outBuffer.append(value);
keyBuffer.delete(0, keyBuffer.length());
} else if (almostReplacementMode) {
replacementMode = true;
} else {
almostReplacementMode = true;
}
} else {
if (replacementMode) {
keyBuffer.append(c);
} else {
if (almostReplacementMode) {
outBuffer.append('@');
}
outBuffer.append(c);
almostReplacementMode = false;
}
}
}
}
return new ByteArrayInputStream(outBuffer.toString().getBytes());
// return new
// ByteArrayInputStream(outBuffer.toString().getBytes(project.
// getDefaultCharset()));
}
private String getProcessedString(String fileName, String source) {
if (source.indexOf('$') == -1) {
return source;
}
int loc = -1;
final StringBuffer buffer = new StringBuffer();
boolean replacementMode = false;
for (int i = 0; i < source.length(); i++) {
final char c = source.charAt(i);
if (c == '$') {
if (replacementMode) {
final String key = source.substring(loc, i);
final String value = key.length() == 0 ? "$" : getReplacementString(key); //$NON-NLS-1$
buffer.append(value);
replacementMode = false;
} else {
replacementMode = true;
loc = i + 1;
continue;
}
} else if (!replacementMode) {
buffer.append(c);
}
}
return buffer.toString();
}
public String getReplacementString(String key) {
final String result = keys.get(key);
return result != null ? result : key;
}
@Override
public Object getValue(String variable) {
return getReplacementString(variable);
}
}