/** * Copyright (c) 2012-2016 Marsha Chechik, Alessio Di Sandro, Michalis Famelis, * Rick Salay. * 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: * Alessio Di Sandro - Implementation. */ package edu.toronto.cs.se.mmint.mid.utils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; import org.eclipse.core.filesystem.EFS; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.common.ui.URIEditorInput; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.XMIResource; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IDE; import edu.toronto.cs.se.mmint.MMINT; import edu.toronto.cs.se.mmint.MMINTActivator; import edu.toronto.cs.se.mmint.MMINTException; import edu.toronto.cs.se.mmint.mid.ui.GMFUtils; public class FileUtils { public static @NonNull URI createEMFUri(@NonNull String uri, boolean isWorkspaceRelative) { URI emfUri = (isWorkspaceRelative) ? URI.createPlatformResourceURI(uri, true) : URI.createFileURI(uri); return emfUri; } private static String getFirstSegmentFromUri(@NonNull String uri) { int firstSeparator = uri.indexOf(MMINT.URI_SEPARATOR, 1); return (firstSeparator == -1) ? uri.substring(1) : uri.substring(1, firstSeparator); } public static @NonNull String getLastSegmentFromUri(@NonNull String uri) { return uri.substring(uri.lastIndexOf(MMINT.URI_SEPARATOR) + 1, uri.length()); } public static String getFileNameFromUri(String uri) { String lastSegmentUri = getLastSegmentFromUri(uri); return lastSegmentUri.substring(0, lastSegmentUri.lastIndexOf(MMINT.MODEL_FILEEXTENSION_SEPARATOR)); } public static @NonNull String getFileExtensionFromUri(@NonNull String uri) { String lastSegmentUri = getLastSegmentFromUri(uri); return lastSegmentUri.substring(lastSegmentUri.lastIndexOf(MMINT.MODEL_FILEEXTENSION_SEPARATOR) + 1, lastSegmentUri.length()); } public static String replaceLastSegmentInUri(String uri, String newLastSegmentUri) { String lastSegmentUri = getLastSegmentFromUri(uri); return uri.replace(lastSegmentUri, newLastSegmentUri); } public static String replaceFileNameInUri(String uri, String newFileName) { String fileName = getFileNameFromUri(uri); return uri.replace(fileName + MMINT.MODEL_FILEEXTENSION_SEPARATOR, newFileName + MMINT.MODEL_FILEEXTENSION_SEPARATOR); } public static String replaceFileExtensionInUri(String uri, String newFileExtension) { String fileExtension = getFileExtensionFromUri(uri); return uri.replace(MMINT.MODEL_FILEEXTENSION_SEPARATOR + fileExtension, MMINT.MODEL_FILEEXTENSION_SEPARATOR + newFileExtension); } public static @NonNull String addFileNameSuffixInUri(@NonNull String uri, @NonNull String newFileNameSuffix) { String fileExtension = getFileExtensionFromUri(uri); return uri.replace(MMINT.MODEL_FILEEXTENSION_SEPARATOR + fileExtension, newFileNameSuffix + MMINT.MODEL_FILEEXTENSION_SEPARATOR + fileExtension); } public static @NonNull String getUniqueUri(@NonNull String baseUri, boolean isWorkspaceRelative, boolean isDirectory) { String uniqueUri = baseUri; if (!isFileOrDirectory(uniqueUri, isWorkspaceRelative)) { // baseUri itself is ok return uniqueUri; } int i = -1; do { // append a counter to baseUri until is ok i++; uniqueUri = (isDirectory) ? baseUri + i : replaceFileNameInUri(baseUri, getFileNameFromUri(baseUri) + i); } while (isFileOrDirectory(uniqueUri, isWorkspaceRelative)); return uniqueUri; } public static String prependWorkspacePathToUri(String uri) { String absoluteUri; String projectName = getFirstSegmentFromUri(uri); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IProject project = workspaceRoot.getProject(projectName); absoluteUri = (project == null) ? ResourcesPlugin.getWorkspace().getRoot().getLocation().toString() + uri : project.getLocation().toString() + uri.replace(MMINT.URI_SEPARATOR + projectName, ""); return absoluteUri; } public static @NonNull String prependStatePathToUri(@NonNull String uri) { return MMINTActivator.getDefault().getStateLocation().toOSString() + IPath.SEPARATOR + uri; } public static void createTextFile(String fileUri, String text, boolean isWorkspaceRelative) throws Exception { if (isWorkspaceRelative) { fileUri = prependWorkspacePathToUri(fileUri); } Path filePath = Paths.get(fileUri); try (BufferedWriter writer = Files.newBufferedWriter(filePath, Charset.forName("UTF-8"))) { writer.write(text); } } public static void createTextFileInState(String text, String relativeFileUri) throws Exception { createTextFile(prependStatePathToUri(relativeFileUri), text, false); } public static void copyTextFileAndReplaceText(String origFileUri, String newFileUri, String origText, String newText, boolean isWorkspaceRelative) throws Exception { if (isWorkspaceRelative) { origFileUri = prependWorkspacePathToUri(origFileUri); newFileUri = prependWorkspacePathToUri(newFileUri); } Path oldFilePath = Paths.get(origFileUri); Path newFilePath = Paths.get(newFileUri); try (BufferedReader oldBuffer = Files.newBufferedReader(oldFilePath, Charset.forName("UTF-8"))) { try (BufferedWriter newBuffer = Files.newBufferedWriter(newFilePath, Charset.forName("UTF-8"))) { String oldLine; while ((oldLine = oldBuffer.readLine()) != null) { //System.out.println(URLDecoder.decode(origText, "UTF-8")); newBuffer.write(oldLine.replace(origText, newText)); newBuffer.newLine(); } } } } public static void copyTextFileAndReplaceTextInState(String origRelativeFileUri, String newRelativeFileUri, String origText, String newText) throws Exception { copyTextFileAndReplaceText(prependStatePathToUri(origRelativeFileUri), prependStatePathToUri(newRelativeFileUri), origText, newText, false); } private static @NonNull Path getPath(@NonNull String uri, boolean isWorkspaceRelative) { if (isWorkspaceRelative) { uri = prependWorkspacePathToUri(uri); } Path path = Paths.get(uri); return path; } public static boolean isFile(@NonNull String uri, boolean isWorkspaceRelative) { Path filePath = getPath(uri, isWorkspaceRelative); return Files.exists(filePath) && !Files.isDirectory(filePath); } public static boolean isDirectory(@NonNull String uri, boolean isWorkspaceRelative) { Path dirPath = getPath(uri, isWorkspaceRelative); return Files.exists(dirPath) && Files.isDirectory(dirPath); } public static boolean isFileOrDirectory(@NonNull String uri, boolean isWorkspaceRelative) { Path path = getPath(uri, isWorkspaceRelative); return Files.exists(path); } public static boolean isFileInState(@NonNull String relativeUri) { return isFile(prependStatePathToUri(relativeUri), false); } public static boolean isDirectoryInState(@NonNull String relativeUri) { return isDirectory(prependStatePathToUri(relativeUri), false); } public static boolean isFileOrDirectoryInState(@NonNull String relativeUri) { return isFileOrDirectory(prependStatePathToUri(relativeUri), false); } /** * Writes the root of an ECore model into an ECore model file. * * @param rootModelObj * The root of the ECore model. * @param fileUri * The uri of the ECore model file. * @param isWorkspaceRelative * True if the uri is relative to the Eclipse workspace, false if it's absolute. * @throws Exception * If the ECore model file could not be created or overwritten. */ public static void writeModelFile(@NonNull EObject rootModelObj, @NonNull String fileUri, boolean isWorkspaceRelative) throws Exception { URI uri = FileUtils.createEMFUri(fileUri, isWorkspaceRelative); ResourceSet resourceSet = new ResourceSetImpl(); Resource resource = resourceSet.createResource(uri); resource.getContents().add(rootModelObj); Map<String, Object> options = new HashMap<>(); options.put(XMIResource.OPTION_SCHEMA_LOCATION, true); resource.save(options); } public static void writeModelFileInState(@NonNull EObject rootModelObj, @NonNull String relativeFileUri) throws Exception { writeModelFile(rootModelObj, prependStatePathToUri(relativeFileUri), false); } public static @NonNull EObject readModelFile(@NonNull String fileUri, boolean isWorkspaceRelative) throws Exception { URI uri = FileUtils.createEMFUri(fileUri, isWorkspaceRelative); ResourceSet set = new ResourceSetImpl(); Resource resource = set.getResource(uri, true); EObject rootModelObj = resource.getContents().get(0); return rootModelObj; } public static @NonNull EObject readModelFileInState(@NonNull String relativeFileUri) throws Exception { return readModelFile(prependStatePathToUri(relativeFileUri), false); } public static @NonNull EObject readModelObject(@NonNull String fileObjectUri, @Nullable Resource resource) throws Exception { URI emfUri = URI.createURI(fileObjectUri, false, URI.FRAGMENT_LAST_SEPARATOR); if (resource == null) { ResourceSet set = new ResourceSetImpl(); resource = set.getResource(emfUri, true); } return resource.getEObject(emfUri.fragment()); } public static void deleteFile(String fileUri, boolean isWorkspaceRelative) { if (isWorkspaceRelative) { fileUri = prependWorkspacePathToUri(fileUri); } Path filePath = Paths.get(fileUri); try { Files.deleteIfExists(filePath); } catch (Exception e) { MMINTException.print(IStatus.WARNING, "File " + fileUri + " not deleted", e); } } public static void deleteFileInState(String relativeFileUri) { deleteFile(prependStatePathToUri(relativeFileUri), false); } public static void createDirectory(String directoryUri, boolean isWorkspaceRelative) throws Exception { if (isWorkspaceRelative) { directoryUri = prependWorkspacePathToUri(directoryUri); } Path directoryPath = Paths.get(directoryUri); Files.createDirectory(directoryPath); } public static void createDirectoryInState(String relativeDirectoryUri) throws Exception { createDirectory(prependStatePathToUri(relativeDirectoryUri), false); } public static void deleteDirectory(String directoryUri, boolean isWorkspaceRelative) { if (isWorkspaceRelative) { directoryUri = prependWorkspacePathToUri(directoryUri); } Path directoryPath = Paths.get(directoryUri); try { Files.walkFileTree(directoryPath, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { Files.delete(file); return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { Files.delete(dir); return FileVisitResult.CONTINUE; } }); } catch (Exception e) { MMINTException.print(IStatus.WARNING, "Directory " + directoryUri + " not deleted", e); } } public static void deleteDirectoryInState(String relativeDirectoryUri) { deleteDirectory(prependStatePathToUri(relativeDirectoryUri), false); } public static @Nullable Object getModelObjectFeature(@NonNull EObject modelObj, @NonNull String featureName) throws MMINTException { EStructuralFeature feature = modelObj.eClass().getEStructuralFeature(featureName); if (feature == null) { throw new MMINTException("Feature " + featureName + " not found in " + modelObj); } return modelObj.eGet(feature); } public static void setModelObjectFeature(@NonNull EObject modelObj, @NonNull String featureName, @NonNull Object value) throws MMINTException { EStructuralFeature feature = modelObj.eClass().getEStructuralFeature(featureName); if (feature == null) { throw new MMINTException("Feature " + featureName + " not found in " + modelObj); } if (feature.isMany()) { if (value instanceof EList<?>) { modelObj.eSet(feature, value); } else { ((EList<Object>) modelObj.eGet(feature)).add(value); } } else { if (value instanceof EList<?>) { throw new MMINTException("Feature " + featureName + " is not multi-valued"); } modelObj.eSet(feature, value); } } public static void openEclipseEditor(@NonNull String filePath, @Nullable String editorId, boolean isWorkspaceRelative) throws MMINTException { IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); try { if (isWorkspaceRelative) { IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile( new org.eclipse.core.runtime.Path(filePath)); if (editorId != null) { IDE.openEditor(activePage, file, editorId); } else { IDE.openEditor(activePage, file); } } else { if (editorId != null) { if (filePath.endsWith(GMFUtils.DIAGRAM_SUFFIX)) { URI emfFileUri = FileUtils.createEMFUri(filePath, false); IDE.openEditor(activePage, new URIEditorInput(emfFileUri), editorId); } else { java.net.URI fileUri = new File(filePath).toURI(); IDE.openEditor(activePage, fileUri, editorId, true); } } else { java.net.URI fileUri = new File(filePath).toURI(); IFileStore file = EFS.getStore(fileUri); IDE.openEditorOnFileStore(activePage, file); } } } catch (CoreException e) { throw new MMINTException("Error opening Eclipse editor", e); } } public static void openEclipseEditorInState(@NonNull String filePath, @Nullable String editorId) throws MMINTException { FileUtils.openEclipseEditor(FileUtils.prependStatePathToUri(filePath), editorId, false); } }