All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.activiti.designer.eclipse.util.FileService Maven / Gradle / Ivy

The newest version!
/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.activiti.designer.eclipse.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.activiti.designer.eclipse.editor.ActivitiDiagramEditor;
import org.activiti.designer.eclipse.editor.ActivitiDiagramEditorInput;
import org.activiti.designer.util.ActivitiConstants;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
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.emf.common.command.CommandStack;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.WrappedException;
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.transaction.RecordingCommand;
import org.eclipse.emf.transaction.Transaction;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.ui.editor.DiagramEditorInput;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.part.FileEditorInput;

public class FileService {

   /**
   * Returns a temporary file used as diagram file. Conceptually, this is a placeholder used by
   * Graphiti as editor input file. The real data file is found at the given data file path.
   *
   * @param dataFilePath path of the actual BPMN2 model file
   * @param diagramFileTempFolder folder containing the diagram files
   * @return an IFile for the temporary file. If the file exists, it is first
   *         deleted.
   */
  public static IFile getTemporaryDiagramFile(IPath dataFilePath, IFolder diagramFileTempFolder) {

    final IPath path = dataFilePath.removeFileExtension().addFileExtension(
            ActivitiConstants.DIAGRAM_FILE_EXTENSION_RAW);
    final IFile tempFile = diagramFileTempFolder.getFile(path.lastSegment());

    // We don't need anything from that file and to be sure there are no side
    // effects we delete the file
    if (tempFile.exists()) {
      try {
        tempFile.delete(true, null);
      } catch (CoreException e) {
        e.printStackTrace();
      }
    }
    return tempFile;
  }

  /**
   * Returns or constructs a temporary folder for diagram files used as Graphiti editor input
   * files. The given path reflects the path where the original data file is located. The folder
   * is constructed in the project root named after the data file extension
   * {@link #DATA_FILE_EXTENSION_RAW}.
   *
   * @param dataFilePath path of the actual BPMN2 model file
   * @return an IFolder for the temporary folder.
   * @throws CoreException in case the folder could not be created.
   */
  public static IFolder getOrCreateTempFolder(IPath dataFilePath) throws CoreException {
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

    String name = dataFilePath.getFileExtension();
    if (name == null || name.length() == 0) {
      name = "bpmn";
    }

    String dir = dataFilePath.segment(0);
    IFolder folder = root.getProject(dir).getFolder("." + name);
    if (!folder.exists()) {
      folder.create(true, true, null);
    }
    String[] segments = dataFilePath.segments();
    for (int i = 1; i < segments.length - 1; i++) {
      String segment = segments[i];
      folder = folder.getFolder(segment);
      if (!folder.exists()) {
        folder.create(true, true, null);
      }
    }
    return folder;
  }

  /**
   * Recreates the data file from the given input path. In case the given path reflects a temporary
   * diagram file, it's path is used to recreate the data file, otherwise the given path is simply
   * made absolute and returned.
   *
   * @param inputPath the path to recreate the data file from
   * @return a file object representing the data file
   */
  public static IFile recreateDataFile(final IPath inputPath) {
    final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    final IProject project = root.getFile(inputPath).getProject();

    final int matchingSegments = project.getFullPath().matchingFirstSegments(inputPath);
    final int totalSegments = inputPath.segmentCount();
    final String extension = inputPath.getFileExtension();

    IFile result = null;

    if (totalSegments > matchingSegments) {
      // it shall be more than just the project

      IPath resultPath = null;

      if (ActivitiConstants.DIAGRAM_FILE_EXTENSION_RAW.equals(extension)) {
        // we got a temporary file here, so rebuild the file of the model from its path
        String originalExtension = inputPath.segment(matchingSegments);
        if (originalExtension.startsWith(".")) {
          originalExtension = originalExtension.substring(1);
        }

        final String[] segments = inputPath.segments();
        IPath originalPath = project.getFullPath();
        for (int index = matchingSegments + 1; index < segments.length; ++index) {
          originalPath = originalPath.append(segments[index]);
        }

        resultPath = originalPath.removeFileExtension().addFileExtension(originalExtension);
      }
      else {
        resultPath = inputPath.makeAbsolute();
      }

      result = root.getFile(resultPath);
    }

    return result;
  }

  /**
   * Returns the appropriate data file for the given input. The data file is the BPMN file with
   * the file extension {@link #DATA_FILE_EXTENSION_RAW}. This method can handle various different
   * editor input versions:
   *
   * 
    *
  • the special {@link ActivitiDiagramEditorInput} that directly references the data file
  • *
  • a {@link DiagramEditorInput} that may either point to a data- or diagram file
  • *
  • a {@link FileEditorInput} that points to a data file
  • *
  • a {@link IURIEditorInput} that points to an external file outside Eclipse
  • *
* * @param input the input to handle * @return the appropriate data file or null if none could be determined. */ public static IFile getDataFileForInput(final IEditorInput input) { final IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); if (input instanceof ActivitiDiagramEditorInput) { final ActivitiDiagramEditorInput adei = (ActivitiDiagramEditorInput) input; return adei.getDataFile(); } else if (input instanceof DiagramEditorInput) { final DiagramEditorInput dei = (DiagramEditorInput) input; IPath path = new Path(dei.getUri().trimFragment().toPlatformString(true)); return recreateDataFile(path); } else if (input instanceof FileEditorInput) { final FileEditorInput fei = (FileEditorInput) input; return fei.getFile(); } else if (input instanceof IURIEditorInput) { // opened externally to Eclipse final IURIEditorInput uei = (IURIEditorInput) input; final java.net.URI uri = uei.getURI(); final String path = uri.getPath(); try { final IProject importProject = root.getProject("import"); if (!importProject.exists()) { importProject.create(null); } importProject.open(null); final InputStream is = new FileInputStream(path); final String fileName; if (path.contains("/")) { fileName = path.substring(path.lastIndexOf("/") + 1); } else { fileName = path.substring(path.lastIndexOf("\\") + 1); } IFile importFile = importProject.getFile(fileName); if (importFile.exists()) { importFile.delete(true, null); } importFile.create(is, true, null); return importProject.getFile(fileName); } catch (CoreException exception) { exception.printStackTrace(); } catch (FileNotFoundException exception) { exception.printStackTrace(); } } return null; } public static TransactionalEditingDomain createEmfFileForDiagram(final URI diagramResourceUri , final Diagram diagram , final ActivitiDiagramEditor diagramEditor , final InputStream contentStream , final IFile resourceFile) { TransactionalEditingDomain editingDomain = null; ResourceSet resourceSet = null; if (diagramEditor == null || diagramEditor.getDiagramBehavior() == null || diagramEditor.getDiagramBehavior().getResourceSet() == null || diagramEditor.getEditingDomain() == null) { // nothing found, create a new one resourceSet = new ResourceSetImpl(); // try to retrieve an editing domain for this resource set editingDomain = TransactionUtil.getEditingDomain(resourceSet); if (editingDomain == null) { // not existing yet, create a new one editingDomain = TransactionalEditingDomain.Factory.INSTANCE.createEditingDomain(resourceSet); } } else { editingDomain = diagramEditor.getEditingDomain(); resourceSet = diagramEditor.getDiagramBehavior().getResourceSet(); } // Create a resource for this file. final Resource resource = resourceSet.createResource(diagramResourceUri); final CommandStack commandStack = editingDomain.getCommandStack(); commandStack.execute(new RecordingCommand(editingDomain) { @Override protected void doExecute() { resource.setTrackingModification(true); if (contentStream == null || resourceFile == null) { resource.getContents().add(diagram); } else { try { resourceFile.create(contentStream, true, null); } catch (CoreException exception) { exception.printStackTrace(); } } } }); save(editingDomain, Collections.> emptyMap()); return editingDomain; } private static void save(TransactionalEditingDomain editingDomain, Map> options) { saveInWorkspaceRunnable(editingDomain, options); } private static void saveInWorkspaceRunnable(final TransactionalEditingDomain editingDomain, final Map> options) { final Map failedSaves = new HashMap(); final IWorkspaceRunnable wsRunnable = new IWorkspaceRunnable() { @Override public void run(final IProgressMonitor monitor) throws CoreException { final Runnable runnable = new Runnable() { @Override public void run() { Transaction parentTx; if (editingDomain != null && (parentTx = ((TransactionalEditingDomainImpl) editingDomain).getActiveTransaction()) != null) { do { if (!parentTx.isReadOnly()) { throw new IllegalStateException( "FileService.save() called from within a command (likely produces a deadlock)"); //$NON-NLS-1$ } } while ((parentTx = ((TransactionalEditingDomainImpl) editingDomain) .getActiveTransaction().getParent()) != null); } final EList resources = editingDomain.getResourceSet().getResources(); // Copy list to an array to prevent // ConcurrentModificationExceptions // during the saving of the dirty resources Resource[] resourcesArray = new Resource[resources.size()]; resourcesArray = resources.toArray(resourcesArray); final Set savedResources = new HashSet(); for (final Resource resource : resourcesArray) { if (resource.isModified()) { try { resource.save(options.get(resource)); savedResources.add(resource); } catch (final Throwable t) { failedSaves.put(resource.getURI(), t); } } } } }; try { editingDomain.runExclusive(runnable); } catch (final InterruptedException e) { throw new RuntimeException(e); } editingDomain.getCommandStack().flush(); } }; try { ResourcesPlugin.getWorkspace().run(wsRunnable, null); if (!failedSaves.isEmpty()) { throw new WrappedException(createMessage(failedSaves), new RuntimeException()); } } catch (final CoreException e) { final Throwable cause = e.getStatus().getException(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } throw new RuntimeException(e); } } private static String createMessage(Map failedSaves) { final StringBuilder buf = new StringBuilder("The following resources could not be saved:"); for (final Entry entry : failedSaves.entrySet()) { buf.append("\nURI: ").append(entry.getKey().toString()).append(", cause: \n") .append(getExceptionAsString(entry.getValue())); } return buf.toString(); } private static String getExceptionAsString(Throwable t) { final StringWriter stringWriter = new StringWriter(); final PrintWriter printWriter = new PrintWriter(stringWriter); t.printStackTrace(printWriter); final String result = stringWriter.toString(); try { stringWriter.close(); } catch (final IOException e) { // $JL-EXC$ ignore } printWriter.close(); return result; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy