| /******************************************************************************* |
| * 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) { |
| } |
| } |
| |
| } |