Java tutorial
/******************************************************************************* * Copyright (c) 2011, 2015 THALES GLOBAL SERVICES 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: * Obeo - initial API and implementation *******************************************************************************/ package org.eclipse.sirius.ui.tools.internal.views.common.modelingproject; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.HashSet; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource.Diagnostic; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.sirius.business.api.helper.SiriusUtil; import org.eclipse.sirius.business.api.modelingproject.AbstractRepresentationsFileJob; import org.eclipse.sirius.business.api.modelingproject.ModelingProject; import org.eclipse.sirius.business.api.session.Session; import org.eclipse.sirius.business.api.session.SessionManager; import org.eclipse.sirius.business.internal.modelingproject.manager.InitializeModelingProjectJob; import org.eclipse.sirius.business.internal.modelingproject.marker.ModelingMarker; import org.eclipse.sirius.common.tools.api.util.MarkerUtil; import org.eclipse.sirius.ext.base.Option; import org.eclipse.sirius.ui.business.api.session.IEditingSession; import org.eclipse.sirius.ui.business.api.session.SessionHelper; import org.eclipse.sirius.ui.business.api.session.SessionUIManager; import org.eclipse.sirius.ui.tools.api.project.ModelingProjectManager; import org.eclipse.sirius.viewpoint.SiriusPlugin; import org.eclipse.sirius.viewpoint.provider.Messages; import org.eclipse.sirius.viewpoint.provider.SiriusEditPlugin; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.statushandlers.StatusManager; import com.google.common.base.Predicates; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; /** * A job to load one or more representations files (load the aird file and all * the referenced resource). Warning before calling this job you must call * waitOtherJobs methods to ensure that there is no job of this kind currently * running. * * @author <a href="mailto:laurent.redor@obeo.fr">Laurent Redor</a> */ public class OpenRepresentationsFileJob extends AbstractRepresentationsFileJob { /** * The default label for the job that open a representations file. */ public static final String JOB_LABEL = Messages.OpenRepresentationsFileJob_label; /** * The list of representations files to load. This list is exclusive with * the list of modeling projects. */ List<URI> representationsFilesURIs = Lists.newArrayList(); /** * The list of modeling projects to initialize and for which to load the * main representations file. This list is exclusive with the list of * representations files. */ List<ModelingProject> modelingProjects = Lists.newArrayList(); /** * Constructor to open only one representations file. * * @param representationsFileURI * The URI of the representations file to open. */ public OpenRepresentationsFileJob(final URI representationsFileURI) { super(OpenRepresentationsFileJob.JOB_LABEL); this.representationsFilesURIs.add(representationsFileURI); } /** * Constructor to open several representations files. * * @param elements * A list of URIs of the representations files to open or a list * of the modeling projects to initialize and open. */ public OpenRepresentationsFileJob(List<? extends Object> elements) { super(OpenRepresentationsFileJob.JOB_LABEL); if (!(Iterators.all(elements.iterator(), Predicates.instanceOf(URI.class)) || Iterators.all(elements.iterator(), Predicates.instanceOf(ModelingProject.class)))) { throw new IllegalArgumentException(Messages.OpenRepresentationsFileJob_errorInvalidInputList); } Iterators.addAll(this.representationsFilesURIs, Iterators.filter(elements.iterator(), URI.class)); Iterators.addAll(this.modelingProjects, Iterators.filter(elements.iterator(), ModelingProject.class)); } /** * Launch this job when all other openRepresentationFile's job are finished. * * @param representationsFileURI * The URI of the representations file to open. * @param user * <code>true</code> if this job is a user-initiated job, and * <code>false</code> otherwise. */ public static void scheduleNewWhenPossible(URI representationsFileURI, boolean user) { // Just wait other job if some are already in progress OpenRepresentationsFileJob.waitOtherJobs(); // Schedule a new job for this representations file. Job job = new OpenRepresentationsFileJob(representationsFileURI); job.setUser(user); job.setPriority(Job.SHORT); job.schedule(); } /** * Launch this job when all other openRepresentationFile's job are finished. * * @param elements * A list of URIs of the representations files to open or a list * of the modeling projects to initialize and open. * @param user * <code>true</code> if this job is a user-initiated job, and * <code>false</code> otherwise. */ public static void scheduleNewWhenPossible(List<? extends Object> elements, boolean user) { if (!(Iterators.all(elements.iterator(), Predicates.instanceOf(URI.class)) || Iterators.all(elements.iterator(), Predicates.instanceOf(ModelingProject.class)))) { throw new IllegalArgumentException(Messages.OpenRepresentationsFileJob_errorInvalidInputList); } // Just wait other job if some are already in progress OpenRepresentationsFileJob.waitOtherJobs(); // Schedule a new job for this representations file. Job job = new OpenRepresentationsFileJob(elements); job.setUser(user); job.setPriority(Job.SHORT); job.schedule(); } @Override public IStatus runInWorkspace(IProgressMonitor monitor) { IStatus initializationStatus = Status.OK_STATUS; List<IStatus> openingStatuses = Lists.newArrayList(); try { monitor.beginTask(Messages.OpenRepresentationsFileJob_loadingModelsTask, 11); monitor.subTask(Messages.OpenRepresentationsFileJob_initModelingProjectsTask); if (!modelingProjects.isEmpty()) { // Initialize the modeling projects before open the main // representations files. List<IProject> projects = Lists.newArrayList(); for (ModelingProject modelingProject : modelingProjects) { projects.add(modelingProject.getProject()); } initializationStatus = InitializeModelingProjectJob.initializeModelingProjects(projects, true, new SubProgressMonitor(monitor, 2)); SubProgressMonitor getRepresentationsFilesMonitor = new SubProgressMonitor(monitor, 1); try { getRepresentationsFilesMonitor.beginTask("", modelingProjects.size()); //$NON-NLS-1$ for (ModelingProject modelingProject : modelingProjects) { Option<URI> optionalMainSessionFileURI = modelingProject.getMainRepresentationsFileURI( new SubProgressMonitor(getRepresentationsFilesMonitor, 1), false, false); if (optionalMainSessionFileURI.some()) { representationsFilesURIs.add(optionalMainSessionFileURI.get()); } } } finally { getRepresentationsFilesMonitor.done(); } } else { monitor.worked(3); } SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 8); try { subMonitor.beginTask("", 100 * representationsFilesURIs.size()); //$NON-NLS-1$ for (URI representationsFileURI : representationsFilesURIs) { // Clean existing marker if exists IProject project = null; if (representationsFileURI.isPlatform()) { String projectName = URI.decode(representationsFileURI.segment(1)); project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); } try { if (project != null) { project.deleteMarkers(ModelingMarker.MARKER_TYPE, false, IResource.DEPTH_ZERO); } } catch (final CoreException e) { SiriusPlugin.getDefault().getLog().log(e.getStatus()); } subMonitor.subTask( MessageFormat.format(Messages.OpenRepresentationsFileJob_loadingRepresentationFileTask, representationsFileURI.lastSegment())); final Set<Session> sessions = performOpenSession(representationsFileURI, new SubProgressMonitor(subMonitor, 90)); if (sessions.isEmpty()) { subMonitor.worked(10); String errorMessage = logLoadingProblem(project, representationsFileURI, null); openingStatuses.add( new Status(IStatus.ERROR, SiriusEditPlugin.ID, IStatus.OK, errorMessage, null)); } else { subMonitor.subTask(MessageFormat.format( Messages.OpenRepresentationsFileJob_openingStartRepresentationTask, representationsFileURI.lastSegment())); // Open the startup representations of each session for (final Session session : sessions) { SessionHelper.openStartupRepresentations(session, new SubProgressMonitor(subMonitor, 10 / sessions.size())); } } } } finally { subMonitor.done(); } } finally { monitor.done(); } List<IStatus> allStatuses = Lists.newArrayList(openingStatuses); if (!initializationStatus.isOK()) { if (initializationStatus instanceof MultiStatus) { allStatuses.addAll(0, Lists.newArrayList(((MultiStatus) initializationStatus).getChildren())); } else { allStatuses.add(0, initializationStatus); } } IStatus result = Status.OK_STATUS; if (allStatuses.size() == 1) { result = allStatuses.get(0); } else if (allStatuses.size() > 1) { result = new MultiStatus(SiriusEditPlugin.ID, IStatus.ERROR, allStatuses.toArray(new IStatus[0]), Messages.OpenRepresentationsFileJob_invalidModelingProjectsError, null); } return result; } /** * Log loading problem (Add a marker on this project, change valid status of * this modeling project, clean the cache of the ModelingProjectManager). * * @param project * The project concerned by this problem. * @param representationsFileURI * The URI of the representations file concerned by this problem. * @param exception * The thrown exception * @return The error message. */ protected String logLoadingProblem(IProject project, URI representationsFileURI, Exception exception) { String message = ""; //$NON-NLS-1$ if (project != null) { boolean isModelingProject = ModelingProject.hasModelingProjectNature(project); final String errorDetail; if (exception != null) { errorDetail = exception.getCause() != null ? exception.getCause().getMessage() : exception.getMessage(); } else { errorDetail = Messages.OpenRepresentationsFileJob_loadingProblem_defaultErrorDetail; } if (isModelingProject) { message = MessageFormat.format(Messages.OpenRepresentationsFileJob_loadingProblem_modelingProject, project.getName(), errorDetail); } else { message = MessageFormat.format( Messages.OpenRepresentationsFileJob_loadingProblem_representationFile, representationsFileURI.toPlatformString(true), errorDetail); } Option<IMarker> optionalMarker = MarkerUtil.addMarkerFor(project, message, IMarker.SEVERITY_ERROR, ModelingMarker.MARKER_TYPE); if (optionalMarker.some() && exception instanceof Diagnostic) { MarkerUtil.setAttribute(optionalMarker.get(), IMarker.LOCATION, ((Diagnostic) exception).getLocation()); } // Set this project in invalid state Option<ModelingProject> optionalModelingProject = ModelingProject.asModelingProject(project); if (optionalModelingProject.some()) { optionalModelingProject.get().setValid(false); } } // Clear modeling project manager cache for this representations file ModelingProjectManager.INSTANCE.clearCache(representationsFileURI); return message; } /** * Open session. * * @param representationsFileURI * The URI of the representations file corresponding to the * session to opened. * @param monitor * the progress monitor. * @return Resource associated to session. */ public Set<Session> performOpenSession(URI representationsFileURI, IProgressMonitor monitor) { Set<Session> openedSessions = new HashSet<Session>(); try { monitor.beginTask(Messages.OpenRepresentationsFileJob_loadRepresentationsTask, 16); if (SiriusUtil.SESSION_RESOURCE_EXTENSION.equals(representationsFileURI.fileExtension())) { monitor.worked(1); Session session = SessionManager.INSTANCE.getSession(representationsFileURI, new SubProgressMonitor(monitor, 10)); // Open the session if needed (load the referenced models by // a ResolveAll call) monitor.subTask(MessageFormat.format(Messages.OpenRepresentationsFileJob_loadReferencedModelsTask, representationsFileURI.lastSegment())); if (session != null) { if (!session.isOpen()) { session.open(new SubProgressMonitor(monitor, 4)); } IEditingSession editingSession; // JGO : Do not create an editing session in case the // session is // null // the session could be null if the session is not a local // session (CDO for example) and // if the remote CDO server is unreachable editingSession = SessionUIManager.INSTANCE.getOrCreateUISession(session); if (!editingSession.isOpen()) { editingSession.open(); } if (openedSessions != null) { openedSessions.add(session); } } monitor.worked(1); } // CHECKSTYLE:OFF } catch (RuntimeException e) { // CHECKSTYLE:ON SiriusEditPlugin.getPlugin().log(e); } finally { monitor.done(); } return openedSessions; } /** * Waits until all jobs of this kind are finished. This method must be * called from UI Thread. */ public static void waitOtherJobs() { if (OpenRepresentationsFileJob.shouldWaitOtherJobs()) { try { if (Display.getCurrent() != null) { PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InterruptedException { Job.getJobManager().join(AbstractRepresentationsFileJob.FAMILY, monitor); } }); } else { Job.getJobManager().join(AbstractRepresentationsFileJob.FAMILY, new NullProgressMonitor()); } } catch (InvocationTargetException e) { StatusManager.getManager().handle(new Status(IStatus.ERROR, SiriusEditPlugin.ID, IStatus.OK, OpenRepresentationsFileJob.getLocalizedMessage(e), OpenRepresentationsFileJob.getCause(e))); } catch (InterruptedException e) { // Do nothing; } } } /** * Check if other jobs of this kind are running. This method must be called * from UI Thread. * * @return true if other jobs of this kind are running. */ public static boolean shouldWaitOtherJobs() { Job[] jobs = Job.getJobManager().find(AbstractRepresentationsFileJob.FAMILY); return jobs != null && jobs.length > 0; } /** * Returns a localized message describing the given exception. If the given * exception does not have a localized message, this returns the string * "An error occurred". * * @param exception * The exception to deal with * @return The message */ protected static String getLocalizedMessage(Throwable exception) { String message = exception.getLocalizedMessage(); if (message == null) { // Workaround for the fact that CoreException does not implement a // getLocalizedMessage() method. // Remove this branch when and if CoreException implements // getLocalizedMessage() if (exception instanceof CoreException) { CoreException ce = (CoreException) exception; return ce.getStatus().getMessage(); } else { message = Messages.OpenRepresentationsFileJob_unexpectedException; } } return message; } /** * Returns the cause of the given exception. * * @param exception * The exception to deal with * @return the cause of the given exception. */ protected static Throwable getCause(Throwable exception) { // Figure out which exception should actually be logged -- if the given // exception is // a wrapper, unwrap it Throwable cause = null; if (exception != null) { if (exception instanceof CoreException) { // Workaround: CoreException contains a cause, but does not // actually implement getCause(). // If we get a CoreException, we need to manually unpack the // cause. Otherwise, use // the general-purpose mechanism. Remove this branch if // CoreException ever implements // a correct getCause() method. CoreException ce = (CoreException) exception; cause = ce.getStatus().getException(); } else { // use reflect instead of a direct call to getCause(), to allow // compilation against JCL Foundation try { Method causeMethod = exception.getClass().getMethod("getCause", new Class[0]); //$NON-NLS-1$ Object o = causeMethod.invoke(exception, new Object[0]); if (o instanceof Throwable) { cause = (Throwable) o; } } catch (NoSuchMethodException e) { // ignore } catch (IllegalArgumentException e) { // ignore } catch (IllegalAccessException e) { // ignore } catch (InvocationTargetException e) { // ignore } } if (cause == null) { cause = exception; } } return cause; } }