blob: f6186365b208db670fe9388df5284a9b83e47ba6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.ctx.filesystem;
import static org.eclipse.rcptt.ctx.filesystem.FilesystemContextPlugin.createErr;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.variables.VariablesPlugin;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.rcptt.filesystem.FSFile;
import org.eclipse.rcptt.filesystem.FSFolder;
import org.eclipse.rcptt.filesystem.FSResource;
import org.eclipse.rcptt.filesystem.FilesystemContext;
import org.eclipse.rcptt.filesystem.FilesystemFactory;
import org.eclipse.rcptt.util.FileSystemResolver;
import org.eclipse.rcptt.util.FileUtil;
import org.eclipse.rcptt.util.PrefixScheme;
public class FSUtils {
private static final FilesystemFactory factory = FilesystemFactory.eINSTANCE;
public static void apply(FilesystemContext context,
FileSystemResolver resolver) throws CoreException {
String path = context.getPath();
if (path == null)
path = "";
// Tries to substitute variables
try {
path = VariablesPlugin
.getDefault()
.getStringVariableManager()
.performStringSubstitution(path, true);
} catch (NoClassDefFoundError e) {
}
if (path.equals(PrefixScheme.WORKSPACE))
throw new CoreException(
createErr("Cannot clear entire workspace. Please use workspace context for that purpose."));
if (path.equals(PrefixScheme.HOME)) {
throw new CoreException(
createErr("Cannot clear user's home directory. Please use more detailed root path."));
}
String resolved = resolver.resolve(path);
if (resolved == null)
resolved = path;
try {
File filePath = new File(resolved);
if (context.isClear() && filePath.exists()) {
if (filePath.isDirectory())
FileUtil.deleteFile(filePath, false);
if (filePath.exists()
&& (filePath.isFile() || (filePath.isDirectory() && filePath
.listFiles().length > 0)))
throw new CoreException(createErr("Unable to clear '%s'",
resolved));
}
if (!filePath.exists() && !filePath.mkdirs())
throw new CoreException(createErr("Unable to create '%s'",
resolved));
if (context.getRoot() != null)
apply(context.getRoot(), filePath);
} catch (CoreException e) {
throw e;
} catch (Exception e) {
throw new CoreException(createErr(e, "Error while applying '%s'",
resolved));
}
}
private static void apply(FSFolder folder, File path) throws CoreException {
try {
for (FSFile f : folder.getFiles()) {
File filePath = new File(path, f.getName());
if ((!filePath.exists() && !filePath.createNewFile())
|| !filePath.isFile())
throw new CoreException(new Status(IStatus.ERROR,
FilesystemContextPlugin.PLUGIN_ID,
"Unable to create " + filePath));
save(f, filePath);
}
for (FSFolder f : folder.getFolders()) {
File folderPath = new File(path, f.getName());
if ((!folderPath.exists() && !folderPath.mkdirs())
|| !folderPath.isDirectory())
throw new CoreException(new Status(IStatus.ERROR,
FilesystemContextPlugin.PLUGIN_ID,
"Unable to create " + folderPath));
apply(f, folderPath);
}
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR,
FilesystemContextPlugin.PLUGIN_ID, "Error while applying "
+ path.toString(), e));
}
}
public static void capture(FilesystemContext context, String path,
FileSystemResolver resolver) throws CoreException {
if (path == null)
path = "";
FSFolder root = factory.createFSFolder();
String resolved = resolver.resolve(path);
if (resolved == null)
resolved = path;
capture(root, new File(resolved));
context.setRoot(root);
}
private static final FSFile[] EMPTY_FILES = new FSFile[0];
public static FSFile[] addFiles(FSFolder parent, File[] files)
throws CoreException {
String parentName = parent.getName() == null ? "Context" : parent
.getName();
File duplicate = findFirstDuplicate(files);
if (duplicate != null)
throw new CoreException(createErr("Name collision detected: '%s'",
duplicate.getName()));
List<FSFile> result = new ArrayList<FSFile>();
for (File f : files) {
if (findResource(f.getName(), parent) != null)
throw new CoreException(createErr(
"%s already contains file '%s'", parentName,
f.getName()));
FSFile file = factory.createFSFile();
file.setName(f.getName());
load(file, f);
parent.getFiles().add(file);
result.add(file);
}
return result.toArray(EMPTY_FILES);
}
public static FSResource findResource(String name, FSFolder folder) {
for (FSResource r : folder.getFolders())
if (r.getName().equalsIgnoreCase(name))
return r;
for (FSResource r : folder.getFiles())
if (r.getName().equalsIgnoreCase(name))
return r;
return null;
}
public static FSFolder addFolder(FSFolder parent, String path)
throws CoreException {
File folderPath = new File(path);
String name = folderPath.getName();
String parentName = parent.getName() == null ? "Context" : parent
.getName();
if (findResource(folderPath.getName(), parent) != null) {
throw new CoreException(createErr(
"%s already contains folder '%s'", parentName, name));
}
FSFolder newFolder = factory.createFSFolder();
newFolder.setName(folderPath.getName());
capture(newFolder, folderPath);
parent.getFolders().add(newFolder);
return newFolder;
}
public static void remove(FSResource resource) {
EReference ref = resource.eContainmentFeature();
List<?> list = (List<?>) resource.eContainer().eGet(ref);
list.remove(resource);
}
private static File findFirstDuplicate(File[] list) {
Set<String> members = new HashSet<String>();
for (File f : list)
if (!members.add(f.getName().toLowerCase()))
return f;
return null;
}
private static void capture(FSFolder folder, File path)
throws CoreException {
try {
if (!path.exists() || !path.isDirectory()) {
throw new CoreException(
createErr("Directory '%s' does not exist",
path.getAbsolutePath()));
}
File[] files = path.listFiles();
if (files == null)
return;
File duplicate = findFirstDuplicate(files);
if (duplicate != null)
throw new CoreException(createErr(
"Name collision detected: '%s'", duplicate.getName()));
for (File f : files) {
if (f.isDirectory()) {
FSFolder newFolder = factory.createFSFolder();
newFolder.setName(f.getName());
capture(newFolder, f);
folder.getFolders().add(newFolder);
} else if (f.isFile() /* ;) */) {
FSFile newFile = factory.createFSFile();
newFile.setName(f.getName());
load(newFile, f);
folder.getFiles().add(newFile);
}
}
} catch (CoreException e) {
throw e;
} catch (Exception e) {
throw new CoreException(createErr(e,
"Error while capturing '%s':\n\n%s",
path.getAbsolutePath(), e.getMessage()));
}
}
private static void save(FSFile f, File file) throws FileNotFoundException,
IOException {
byte[] data = f.getData();
if (data != null) {
BufferedOutputStream stream = new BufferedOutputStream(
new FileOutputStream(file));
stream.write(data, 0, data.length);
stream.close();
}
}
private static void load(FSFile file, File path) throws CoreException {
if (!path.exists()) {
throw new CoreException(createErr("File '%s' does not exist",
path.getAbsolutePath()));
}
try {
file.setData(getStreamContent(new BufferedInputStream(
new FileInputStream(path))));
} catch (IOException e) {
throw new CoreException(createErr("Error reading file '%s'",
path.getAbsolutePath()));
}
}
private static byte[] getStreamContent(InputStream stream)
throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
byte[] buffer = new byte[4096];
int len = 0;
while ((len = stream.read(buffer)) > 0) {
output.write(buffer, 0, len);
}
} finally {
safeClose(stream);
}
return output.toByteArray();
}
private static void safeClose(Closeable closeable) {
try {
closeable.close();
} catch (Exception e) {
}
}
}