| // $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString, com.instantiations.assist.eclipse.analysis.deserializeabilitySecurity, com.instantiations.assist.eclipse.analysis.enforceCloneableUsageSecurity |
| /******************************************************************************* |
| * Copyright (c) 2010, 2012 Ericsson AB 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 |
| * |
| * Description: |
| * |
| * This class implements the context-sensitive command to find review items |
| * in the parent project to add to the review |
| * |
| * Contributors: |
| * Sebastien Dubois - Created for Mylyn Review R4E project |
| * |
| ******************************************************************************/ |
| |
| package org.eclipse.mylyn.reviews.r4e.ui.internal.commands.handlers; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.List; |
| import java.util.concurrent.atomic.AtomicInteger; |
| import java.util.concurrent.locks.ReentrantLock; |
| |
| import org.eclipse.compare.rangedifferencer.RangeDifference; |
| import org.eclipse.core.commands.AbstractHandler; |
| import org.eclipse.core.commands.ExecutionEvent; |
| import org.eclipse.core.commands.ExecutionException; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.OperationCanceledException; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
| import org.eclipse.core.runtime.jobs.ISchedulingRule; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.runtime.jobs.JobChangeAdapter; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jface.dialogs.ErrorDialog; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.mylyn.reviews.frame.core.utils.Tracer; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EContextType; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EFileVersion; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EFormalReview; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EReview; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EReviewComponent; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EReviewPhase; |
| import org.eclipse.mylyn.reviews.r4e.core.model.R4EReviewType; |
| import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.OutOfSyncException; |
| import org.eclipse.mylyn.reviews.r4e.core.model.serial.impl.ResourceHandlingException; |
| import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.IRFSRegistry; |
| import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.RFSRegistryFactory; |
| import org.eclipse.mylyn.reviews.r4e.core.rfs.spi.ReviewsFileStorageException; |
| import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.dialogs.R4EUIDialogFactory; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.editors.R4ECompareEditorInput; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.IR4EUIPosition; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIDeltaContainer; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIFileContext; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIModelController; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewBasic; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUIReviewItem; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.model.R4EUITextPosition; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.preferences.PreferenceConstants; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.CommandUtils; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.Diff; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.DiffUtils; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.MailServicesProxy; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.R4EUIConstants; |
| import org.eclipse.mylyn.reviews.r4e.ui.internal.utils.UIUtils; |
| import org.eclipse.mylyn.versions.core.Change; |
| import org.eclipse.mylyn.versions.core.ChangeSet; |
| import org.eclipse.mylyn.versions.core.ScmArtifact; |
| import org.eclipse.mylyn.versions.ui.spi.ScmConnectorUi; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.team.core.history.IFileRevision; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.handlers.HandlerUtil; |
| import org.eclipse.ui.progress.IProgressConstants; |
| |
| /** |
| * @author Sebastien Dubois |
| * @version $Revision: 1.0 $ |
| */ |
| public class FindReviewItemsHandler extends AbstractHandler { |
| |
| // ------------------------------------------------------------------------ |
| // Constants |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Field FETCH_JOB_FAMILY. (value is ""fetchFamily"") |
| */ |
| private static final String FETCH_JOB_FAMILY = "fetchFamily"; |
| |
| /** |
| * Field DELTA_JOB_FAMILY. (value is ""deltaFamily"") |
| */ |
| private static final String DELTA_JOB_FAMILY = "deltaFamily"; |
| |
| /** |
| * Field ADD_JOB_FAMILY. (value is ""addFamily"") |
| */ |
| private static final String ADD_JOB_FAMILY = "addFamily"; |
| |
| /** |
| * Field IMPORTING_FILES_MSG. (value is ""Importing Files..."") |
| */ |
| private static final String IMPORTING_FILES_MSG = "Importing Files..."; |
| |
| /** |
| * Field FETCHING_FILES_MSG. (value is ""Fetching Files..."") |
| */ |
| private static final String FETCHING_FILES_MSG = "Fetching Files..."; |
| |
| /** |
| * Field FETCHING_FILE_MSG. (value is ""Fetching File..."") |
| */ |
| private static final String FETCHING_FILE_MSG = "Fetching File..."; |
| |
| /** |
| * Field CALCULATE_DELTAS_MSG. (value is ""Computing differences..."") |
| */ |
| private static final String CALCULATE_DELTAS_MSG = "Computing differences..."; |
| |
| /** |
| * Field CALCULATE_DELTAS_FILE_MSG. (value is ""Computing differences for file "") |
| */ |
| private static final String CALCULATE_DELTAS_FILE_MSG = "Computing differences for file "; |
| |
| /** |
| * Field ADD_ELEMENT_MSG. (value is ""Adding Elements to R4E model..."") |
| */ |
| private static final String ADD_ELEMENT_MSG = "Adding Elements to R4E model..."; |
| |
| /** |
| * Field ADD_REVIEW_ITEM_MSG. (value is ""Adding Review Item to R4E Model..."") |
| */ |
| private static final String ADD_REVIEW_ITEM_MSG = "Adding Review Item to R4E Model..."; |
| |
| /** |
| * Field MAX_CONCURRRENT_JOBS. (value is 20) |
| */ |
| private static final int MAX_CONCURRRENT_JOBS = 20; |
| |
| // ------------------------------------------------------------------------ |
| // Members |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Field fLock. |
| */ |
| private final ReentrantLock fLock = new ReentrantLock(); |
| |
| /** |
| * Field fRunningJobs. |
| */ |
| private final AtomicInteger fRunningJobs = new AtomicInteger(0); |
| |
| /** |
| * Field fExceptionError. |
| */ |
| private Exception fExceptionError; |
| |
| // ------------------------------------------------------------------------ |
| // Methods |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Method execute. |
| * |
| * @param aEvent |
| * ExecutionEvent |
| * @return Object |
| * @throws ExecutionException |
| * @see org.eclipse.core.commands.IHandler#execute(ExecutionEvent) |
| */ |
| public Object execute(final ExecutionEvent aEvent) { |
| |
| fExceptionError = null; |
| |
| //Make sure that Reentrant lock is in the proper state |
| if (fLock.isLocked()) { |
| fLock.unlock(); |
| } |
| |
| // Get project to use (use adapters if needed) |
| final ISelection selection = HandlerUtil.getCurrentSelection(aEvent); |
| if (selection instanceof IStructuredSelection) { |
| final Object selectedElement = ((IStructuredSelection) selection).getFirstElement(); |
| IProject project = null; |
| |
| // NOTE: The validity tests are done if the ProjectPropertyTester class |
| if (selectedElement instanceof IProject) { |
| project = (IProject) selectedElement; |
| } else if (R4EUIPlugin.isJDTAvailable() && selectedElement instanceof IJavaProject) { |
| project = ((IJavaProject) selectedElement).getProject(); |
| } else if (R4EUIPlugin.isCDTAvailable() && selectedElement instanceof org.eclipse.cdt.core.model.ICProject) { |
| project = ((org.eclipse.cdt.core.model.ICProject) selectedElement).getProject(); |
| } else if (selectedElement instanceof IPackageFragment || selectedElement instanceof IPackageFragmentRoot) { |
| project = ((IJavaElement) selectedElement).getJavaProject().getProject(); |
| } else if (selectedElement instanceof IFolder) { |
| project = ((IFolder) selectedElement).getProject(); |
| } else if (selectedElement instanceof IAdaptable) { |
| final IAdaptable adaptableProject = (IAdaptable) selectedElement; |
| project = (IProject) adaptableProject.getAdapter(IProject.class); |
| } else { |
| // Should never happen |
| R4EUIPlugin.Ftracer.traceError("No project defined for selection of class " //$NON-NLS-1$ |
| + ((null != selectedElement) ? selectedElement.getClass() : "")); |
| R4EUIPlugin.getDefault() |
| .logError( |
| "No project defined for selection of class " + ((null != selectedElement) ? selectedElement.getClass() : ""), null); //$NON-NLS-1$ |
| final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_ERROR, |
| "Find Review Item Error", new Status(IStatus.ERROR, R4EUIPlugin.PLUGIN_ID, 0, |
| "No project defined for selection", null), IStatus.ERROR); |
| dialog.open(); |
| return null; |
| } |
| |
| Cursor cursor = new Cursor(PlatformUI.getWorkbench().getDisplay(), SWT.CURSOR_WAIT); |
| Shell activeShell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); |
| activeShell.setCursor(cursor); |
| final ScmConnectorUi uiConnector = R4EUIDialogFactory.getInstance().getScmUiConnector(project); |
| if (null != uiConnector) { |
| R4EUIPlugin.Ftracer.traceDebug("Resolved Scm Ui connector: " + uiConnector); //$NON-NLS-1$ |
| final ChangeSet changeSet = uiConnector.getChangeSet(null, project); |
| activeShell.setCursor(null); |
| cursor.dispose(); |
| createReviewItem(aEvent, changeSet); |
| } else { |
| activeShell.setCursor(null); |
| cursor.dispose(); |
| // We could not find any version control system, thus no items |
| final String strProject = ((null == project) ? "(no project)" : project.getName()); //$NON-NLS-1$ |
| R4EUIPlugin.Ftracer.traceDebug("No Scm Ui connector found for project: " + strProject); //$NON-NLS-1$ |
| final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_WARNING, |
| "Cannot find new Review Items", new Status(IStatus.WARNING, R4EUIPlugin.PLUGIN_ID, 0, |
| "No SCM Connector detected for Project " + strProject, null), IStatus.WARNING); |
| dialog.open(); |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Create and serialize the changeset in a Review Item |
| * |
| * @param aChangeSet |
| * ChangeSet |
| * @param aEvent |
| * ExecutionEvent |
| */ |
| private void createReviewItem(final ExecutionEvent aEvent, final ChangeSet aChangeSet) { |
| |
| if (null == aChangeSet) { |
| R4EUIPlugin.Ftracer.traceInfo("Received null ChangeSet"); //$NON-NLS-1$ |
| return; |
| } |
| |
| final int size = aChangeSet.getChanges().size(); |
| R4EUIPlugin.Ftracer.traceInfo("Received ChangeSet with " + size + " elements"); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (0 == size) { |
| return; // nothing to add |
| } |
| |
| //Check if Review Item already exists |
| final R4EUIReviewBasic uiReview = R4EUIModelController.getActiveReview(); |
| if (null == uiReview) { |
| return; |
| } |
| for (R4EUIReviewItem uiItem : uiReview.getReviewItems()) { |
| if (null != uiItem) { |
| if (aChangeSet.getId().equals(uiItem.getItem().getRepositoryRef())) { |
| //The commit item already exists so ignore command |
| R4EUIPlugin.Ftracer.traceWarning("Review Item already exists. Ignoring"); |
| final ErrorDialog dialog = new ErrorDialog(null, R4EUIConstants.DIALOG_TITLE_WARNING, |
| "Cannot add Review Item", new Status(IStatus.WARNING, R4EUIPlugin.PLUGIN_ID, 0, |
| "Review Item already exists", null), IStatus.WARNING); |
| dialog.open(); |
| return; |
| } |
| } |
| } |
| |
| try { |
| // Get handle to local storage repository |
| final IRFSRegistry localRepository = RFSRegistryFactory.getRegistry(R4EUIModelController.getActiveReview() |
| .getReview()); |
| |
| //Create Synchronized list that will temporarily hold the elements to be added |
| final List<TempFileContext> filesToAddlist = Collections.synchronizedList(new ArrayList<TempFileContext>()); |
| |
| //The Main Job is the parent of all the child jobs that execute the work |
| final Job mainJob = new Job(IMPORTING_FILES_MSG) { |
| @Override |
| public IStatus run(final IProgressMonitor aMonitor) { |
| if (null == aMonitor) { |
| return Status.CANCEL_STATUS; |
| } |
| R4EUIModelController.setJobInProgress(true); //Disable operations on UI |
| aMonitor.beginTask(IMPORTING_FILES_MSG, 3); |
| |
| //First fetch base and target files from remote repository and copy them to the R4E local repository using parallel jobs |
| aMonitor.subTask(FETCHING_FILES_MSG); |
| |
| //Prepare to collect performance trace information (if enabled). |
| Date startImportingTime = null; |
| Date startFetchTime = null; |
| if (Tracer.isInfo()) { |
| startImportingTime = new Date(); |
| startFetchTime = new Date(); |
| } |
| |
| for (final Change change : aChangeSet.getChanges()) { |
| |
| final Job fetchJob = new Job(FETCHING_FILE_MSG) { |
| @Override |
| public boolean belongsTo(Object aFamily) { |
| return FETCH_JOB_FAMILY.equals(aFamily); |
| } |
| |
| @Override |
| public IStatus run(IProgressMonitor aFetchMonitor) { |
| if (null == aFetchMonitor) { |
| return Status.CANCEL_STATUS; |
| } |
| |
| //If the main task is cancelled, abort here |
| if (aMonitor.isCanceled()) { |
| return Status.CANCEL_STATUS; |
| } |
| |
| aFetchMonitor.beginTask(FETCHING_FILE_MSG, 2); |
| try { |
| TempFileContext file = fetchFiles(change, localRepository, aMonitor, aFetchMonitor); |
| filesToAddlist.add(file); |
| aFetchMonitor.done(); |
| return Status.OK_STATUS; |
| } catch (final ReviewsFileStorageException e) { |
| R4EUIPlugin.Ftracer.traceError(R4EUIConstants.EXCEPTION_MSG + e.toString() |
| + " (" + e.getMessage() //$NON-NLS-1$ |
| + ")"); //$NON-NLS-1$ |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + e.toString(), e); |
| if (null == fExceptionError) { |
| fExceptionError = e; |
| } |
| aFetchMonitor.done(); |
| return Status.CANCEL_STATUS; |
| } catch (final CoreException e) { |
| if (!e.getMessage().equals(R4EUIConstants.CANCEL_EXCEPTION_MSG)) { |
| R4EUIPlugin.Ftracer.traceError(R4EUIConstants.EXCEPTION_MSG + e.toString() |
| + " (" + e.getMessage() //$NON-NLS-1$ |
| + ")"); //$NON-NLS-1$ |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + e.toString(), |
| e); |
| if (null == fExceptionError) { |
| fExceptionError = e; |
| } |
| } |
| aFetchMonitor.done(); |
| return Status.CANCEL_STATUS; |
| } |
| } |
| }; |
| |
| /* Listen to Job's Lifecycle */ |
| fetchJob.addJobChangeListener(new JobChangeAdapter() { |
| |
| /* Count the number of running Jobs for the Rule */ |
| @Override |
| public void running(IJobChangeEvent aEvent) { |
| if (null == aEvent || (null == aEvent.getResult()) |
| || !aEvent.getResult().equals(Status.CANCEL_STATUS)) { |
| fRunningJobs.getAndIncrement(); |
| } |
| } |
| |
| /* Update Fields when a Job is Done */ |
| @Override |
| public void done(IJobChangeEvent aEvent) { |
| fRunningJobs.decrementAndGet(); |
| } |
| }); |
| |
| /* Apply the internal Rule */ |
| fetchJob.setRule(new JobQueueSchedulingRule()); |
| |
| /* Do not interrupt on any Error */ |
| fetchJob.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); |
| |
| fetchJob.setUser(false); |
| fetchJob.schedule(); |
| } |
| try { |
| Job.getJobManager().join(FETCH_JOB_FAMILY, null); |
| } catch (OperationCanceledException ex) { |
| return Status.CANCEL_STATUS; |
| } catch (InterruptedException ex) { |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + ex.toString(), ex); |
| return Status.CANCEL_STATUS; |
| } |
| |
| //If the task is cancelled, abort here |
| if (aMonitor.isCanceled()) { |
| aMonitor.done(); |
| R4EUIModelController.setJobInProgress(false); |
| if (null != fExceptionError) { |
| if (fExceptionError instanceof ReviewsFileStorageException) { |
| UIUtils.displayReviewsFileStorageErrorDialog((ReviewsFileStorageException) fExceptionError); |
| } else if (fExceptionError instanceof CoreException) { |
| UIUtils.displayCoreErrorDialog((CoreException) fExceptionError); |
| } |
| } |
| return Status.CANCEL_STATUS; |
| } |
| aMonitor.worked(1); |
| |
| //Tracing add fetch time |
| if (startFetchTime != null) { |
| R4EUIPlugin.Ftracer.traceInfo("Total time to Import/Push files is: " //$NON-NLS-1$ |
| + ((new Date()).getTime() - startFetchTime.getTime())); |
| } |
| |
| //Reset Tracing benchmark timer |
| Date startingComputeTime = null; |
| if (Tracer.isInfo()) { |
| startingComputeTime = new Date(); |
| } |
| |
| //Second calculate deltas for all fetched files using parallel jobs (if configured in preferences) |
| if (R4EUIPlugin.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.P_USE_DELTAS)) { |
| aMonitor.subTask(CALCULATE_DELTAS_MSG); |
| for (final TempFileContext file : filesToAddlist) { |
| if (null == file) { |
| continue; |
| } |
| |
| final Job deltaJob = new Job(CALCULATE_DELTAS_MSG) { |
| @Override |
| public boolean belongsTo(Object aFamily) { |
| return DELTA_JOB_FAMILY.equals(aFamily); |
| } |
| |
| @Override |
| public IStatus run(IProgressMonitor aDeltaMonitor) { |
| if (null == aDeltaMonitor) { |
| return Status.CANCEL_STATUS; |
| } |
| aDeltaMonitor.beginTask(CALCULATE_DELTAS_FILE_MSG + file.toString(), 1); |
| |
| try { |
| updateFilesWithDeltas(file); |
| } catch (CoreException e) { |
| R4EUIPlugin.Ftracer.traceError(R4EUIConstants.EXCEPTION_MSG + e.toString() |
| + " (" + e.getMessage() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + e.toString(), |
| e); |
| } |
| aDeltaMonitor.worked(1); |
| aDeltaMonitor.done(); |
| return Status.OK_STATUS; |
| } |
| }; |
| |
| /* Listen to Job's Lifecycle */ |
| deltaJob.addJobChangeListener(new JobChangeAdapter() { |
| |
| /* Count the number of running Jobs for the Rule */ |
| @Override |
| public void running(IJobChangeEvent aEvent) { |
| if (null == aEvent || (null == aEvent.getResult()) |
| || !aEvent.getResult().equals(Status.CANCEL_STATUS)) { |
| fRunningJobs.getAndIncrement(); |
| } |
| } |
| |
| /* Update Fields when a Job is Done */ |
| @Override |
| public void done(IJobChangeEvent aEvent) { |
| fRunningJobs.decrementAndGet(); |
| } |
| }); |
| |
| /* Apply the internal Rule */ |
| deltaJob.setRule(new JobQueueSchedulingRule()); |
| |
| /* Do not interrupt on any Error */ |
| deltaJob.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); |
| |
| deltaJob.setUser(false); |
| deltaJob.schedule(); |
| } |
| try { |
| Job.getJobManager().join(DELTA_JOB_FAMILY, null); |
| } catch (OperationCanceledException ex) { |
| return Status.CANCEL_STATUS; |
| } catch (InterruptedException ex) { |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + ex.toString(), ex); |
| return Status.CANCEL_STATUS; |
| } |
| } |
| //If the task is cancelled, exit |
| if (aMonitor.isCanceled()) { |
| aMonitor.done(); |
| R4EUIModelController.setJobInProgress(false); |
| return Status.CANCEL_STATUS; |
| } |
| aMonitor.worked(1); |
| |
| //Tracing add calculate changes time |
| if (startingComputeTime != null) { |
| R4EUIPlugin.Ftracer.traceInfo("Total time to Compute changes is: " //$NON-NLS-1$ |
| + ((new Date()).getTime() - startingComputeTime.getTime())); |
| } |
| |
| //Reset Tracing benchmark timer |
| Date startUpdatingModel = null; |
| if (Tracer.isInfo()) { |
| startUpdatingModel = new Date(); |
| } |
| |
| //Third add all elements to the UI model |
| aMonitor.subTask(ADD_ELEMENT_MSG); |
| final Job addJob = new Job(ADD_ELEMENT_MSG) { |
| @Override |
| public boolean belongsTo(Object aFamily) { |
| return ADD_JOB_FAMILY.equals(aFamily); |
| } |
| |
| @Override |
| public IStatus run(IProgressMonitor aAddMonitor) { |
| if (null == aAddMonitor) { |
| return Status.CANCEL_STATUS; |
| } |
| try { |
| final R4EUIReviewItem uiReviewItem; |
| if (filesToAddlist.size() > 0) { |
| aAddMonitor.beginTask(ADD_ELEMENT_MSG, filesToAddlist.size() + 1); |
| |
| aAddMonitor.subTask(ADD_REVIEW_ITEM_MSG); |
| uiReviewItem = uiReview.createCommitReviewItem(aChangeSet, null); |
| aAddMonitor.worked(1); |
| |
| //Lock the resource to the user review items to avoid parallel updates from other users |
| Resource resource = uiReviewItem.getItem().eResource(); |
| final Long bookNum = R4EUIModelController.FResourceUpdater.checkOut( |
| uiReviewItem.getItem(), R4EUIModelController.getReviewer()); |
| |
| //Prevent serialization for each individual child element and wait till the end |
| R4EUIModelController.stopSerialization(resource); |
| |
| for (TempFileContext file : filesToAddlist) { |
| //May need to Test if the target or base files are empty, means this is a folder |
| if (file.getTarget() != null || file.getBase() != null) { |
| addFileToModel(uiReviewItem, file, aAddMonitor); |
| } else { |
| R4EUIPlugin.Ftracer.traceWarning("Warning No Base and NO target files, so no ADD"); //$NON-NLS-1$ |
| } |
| } |
| |
| //Resume serialization |
| R4EUIModelController.resetToDefaultSerialization(); |
| |
| //Check-in to serialize the whole commit element with children |
| R4EUIModelController.FResourceUpdater.checkIn(bookNum); |
| |
| UIUtils.setNavigatorViewFocus(uiReviewItem, 1); |
| |
| //Notify users if need be |
| final List<R4EReviewComponent> addedItems = new ArrayList<R4EReviewComponent>(); |
| addedItems.add(uiReviewItem.getItem()); |
| final R4EReview review = uiReview.getReview(); |
| if (review.getType().equals(R4EReviewType.R4E_REVIEW_TYPE_FORMAL)) { |
| if (((R4EFormalReview) review).getCurrent() |
| .getType() |
| .equals(R4EReviewPhase.R4E_REVIEW_PHASE_PREPARATION)) { |
| MailServicesProxy.sendItemsAddedNotification(addedItems); |
| |
| } |
| } |
| } |
| } catch (CoreException e) { |
| UIUtils.displayCoreErrorDialog(e); |
| } catch (ResourceHandlingException e) { |
| UIUtils.displayResourceErrorDialog(e); |
| } catch (OutOfSyncException e) { |
| UIUtils.displaySyncErrorDialog(e); |
| } finally { |
| //Minimize the possibility to remain with serialization off |
| R4EUIModelController.resetToDefaultSerialization(); |
| } |
| return Status.OK_STATUS; |
| } |
| }; |
| addJob.setUser(false); |
| addJob.schedule(); |
| try { |
| Job.getJobManager().join(ADD_JOB_FAMILY, null); |
| } catch (OperationCanceledException ex) { |
| return Status.CANCEL_STATUS; |
| } catch (InterruptedException ex) { |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + ex.toString(), ex); |
| return Status.CANCEL_STATUS; |
| } |
| |
| //Tracing add updating model time |
| if (startUpdatingModel != null) { |
| Date jobEnd = new Date(); |
| R4EUIPlugin.Ftracer.traceInfo("Total time to update model is: " //$NON-NLS-1$ |
| + (jobEnd.getTime() - startUpdatingModel.getTime())); |
| } |
| |
| //Tracing add total time |
| if (startImportingTime != null) { |
| Date jobEnd = new Date(); |
| R4EUIPlugin.Ftracer.traceInfo("Total time to fetch files, compute deltas and update model is: " //$NON-NLS-1$ |
| + (jobEnd.getTime() - startImportingTime.getTime())); |
| } |
| |
| aMonitor.worked(1); |
| aMonitor.done(); |
| R4EUIModelController.setJobInProgress(false); |
| return Status.OK_STATUS; |
| } |
| }; |
| mainJob.setUser(true); |
| mainJob.schedule(); |
| } catch (ReviewsFileStorageException e) { |
| UIUtils.displayReviewsFileStorageErrorDialog(e); |
| } |
| } |
| |
| /** |
| * Method fetchFiles. |
| * |
| * @param aChange |
| * Change |
| * @param aLocalRepository |
| * IRFSRegistry |
| * @param aMainMonitor |
| * IProgressMonitor |
| * @param aSubMonitor |
| * IProgressMonitor |
| * @return TempFileContext |
| * @throws CoreException |
| * @throws ReviewsFileStorageException |
| * @throws SubJobCancelledException |
| * @throws MainJobCancelledException |
| */ |
| private TempFileContext fetchFiles(final Change aChange, IRFSRegistry aLocalRepository, |
| IProgressMonitor aMainMonitor, IProgressMonitor aSubMonitor) throws ReviewsFileStorageException, |
| CoreException { |
| |
| R4EFileVersion baseLocalVersion = null; |
| R4EFileVersion targetLocalVersion = null; |
| |
| //Get Base artifact |
| final ScmArtifact baseArt = aChange.getBase(); |
| if (null != baseArt) { |
| // Copy to the local repository |
| aSubMonitor.subTask(FETCHING_FILE_MSG + baseArt.getPath() + " (base) from remote repository"); //$NON-NLS-1$ |
| baseLocalVersion = CommandUtils.copyRemoteFileToLocalRepository(fLock, aLocalRepository, baseArt, |
| aMainMonitor); |
| } |
| aSubMonitor.worked(1); |
| |
| //Get Target artifact |
| final ScmArtifact targetArt = aChange.getTarget(); |
| if (null != targetArt) { |
| aSubMonitor.subTask(FETCHING_FILE_MSG + targetArt.getPath() + " (target) from remote repository"); //$NON-NLS-1$ |
| targetLocalVersion = CommandUtils.copyRemoteFileToLocalRepository(fLock, aLocalRepository, targetArt, |
| aMainMonitor); |
| } |
| aSubMonitor.worked(1); |
| |
| // Add File Context to the list to be added |
| return new TempFileContext(aLocalRepository, baseLocalVersion, targetLocalVersion, |
| CommandUtils.adaptType(aChange.getChangeType())); |
| } |
| |
| /** |
| * Method updateFilesWithDeltas. |
| * |
| * @param aFile |
| * TempFileContext |
| * @throws CoreException |
| */ |
| private void updateFilesWithDeltas(final TempFileContext aFile) throws CoreException { |
| |
| //Find all differences between Base and Target files |
| final R4ECompareEditorInput input = CommandUtils.createCompareEditorInput(aFile.getBase(), aFile.getTarget()); |
| input.prepareCompareInputNoEditor(); |
| |
| final DiffUtils diffUtils = new DiffUtils(); |
| final List<Diff> diffs; |
| |
| fLock.lock(); |
| try { |
| diffs = diffUtils.doDiff(false, true, input); |
| } finally { |
| fLock.unlock(); |
| } |
| |
| //Add Deltas from the list of differences |
| for (Diff diff : diffs) { |
| IR4EUIPosition position = CommandUtils.getPosition(diff.getPosition(R4EUIConstants.LEFT_CONTRIBUTOR) |
| .getOffset(), diff.getPosition(R4EUIConstants.LEFT_CONTRIBUTOR).getLength(), |
| diff.getDocument(R4EUIConstants.LEFT_CONTRIBUTOR)); |
| |
| if ((null == position) || (RangeDifference.NOCHANGE == diff.getKind())) { |
| continue; //Cannot resolve position for this delta or no change |
| } |
| aFile.getPositions().add(position); |
| } |
| } |
| |
| /** |
| * Method addFileToModel. |
| * |
| * @param aUiReviewItem |
| * R4EUIReviewItem |
| * @param aFile |
| * TempFileContext |
| * @param aMonitor |
| * IProgressMonitor |
| */ |
| private void addFileToModel(R4EUIReviewItem aUiReviewItem, TempFileContext aFile, IProgressMonitor aMonitor) { |
| try { |
| String addedFilename; |
| if (null != aFile.getTarget()) { |
| addedFilename = aFile.getTarget().getName(); |
| } else if (null != aFile.getBase()) { |
| addedFilename = aFile.getBase().getName(); |
| } else { |
| addedFilename = ""; //Should never happen //$NON-NLS-1$ |
| } |
| aMonitor.subTask("Adding file " + addedFilename + " to R4E model"); //$NON-NLS-1$//$NON-NLS-2$ |
| final R4EUIFileContext uiFileContext = aUiReviewItem.createFileContext(aFile.getBase(), aFile.getTarget(), |
| aFile.getType()); |
| |
| for (IR4EUIPosition position : aFile.getPositions()) { |
| //Lazily create the Delta container if not already done |
| R4EUIDeltaContainer deltaContainer = (R4EUIDeltaContainer) uiFileContext.getContentsContainerElement(); |
| deltaContainer.createDelta((R4EUITextPosition) position); |
| } |
| } catch (OutOfSyncException e) { |
| R4EUIPlugin.Ftracer.traceError(R4EUIConstants.EXCEPTION_MSG + e.toString() + " (" + e.getMessage() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + e.toString(), e); |
| } catch (ResourceHandlingException e) { |
| R4EUIPlugin.Ftracer.traceError(R4EUIConstants.EXCEPTION_MSG + e.toString() + " (" + e.getMessage() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| R4EUIPlugin.getDefault().logError(R4EUIConstants.EXCEPTION_MSG + e.toString(), e); |
| } |
| aMonitor.worked(1); |
| } |
| |
| /** |
| * Class TempFileContext internal class that aggregates info needed to import files into R4E |
| * |
| * @author Sebastien Dubois |
| */ |
| private static class TempFileContext { |
| /** |
| * Field base. |
| */ |
| private final R4EFileVersion fBase; |
| |
| /** |
| * Field target. |
| */ |
| private final R4EFileVersion fTarget; |
| |
| /** |
| * Field type. |
| */ |
| private final R4EContextType fType; |
| |
| /** |
| * Field positions. |
| */ |
| private final List<IR4EUIPosition> fPositions; |
| |
| /** |
| * Constructor for TempFileContext. |
| * |
| * @param aRepository |
| * IRFSRegistry |
| * @param aBase |
| * R4EFileVersion |
| * @param aTarget |
| * R4EFileVersion |
| * @param aType |
| * R4EContextType |
| */ |
| TempFileContext(IRFSRegistry aRepository, R4EFileVersion aBase, R4EFileVersion aTarget, R4EContextType aType) { |
| fBase = aBase; |
| //Add IFileRevision info |
| if ((null != fBase) && (null != aRepository)) { |
| try { |
| final IFileRevision fileRev = aRepository.getIFileRevision(null, fBase); |
| fBase.setFileRevision(fileRev); |
| } catch (ReviewsFileStorageException e) { |
| R4EUIPlugin.Ftracer.traceInfo(R4EUIConstants.EXCEPTION_MSG + e.toString() + " (" + e.getMessage() //$NON-NLS-1$ |
| + ")"); //$NON-NLS-1$ |
| } |
| } |
| |
| fTarget = aTarget; |
| //Add IFileRevision info |
| if ((null != fTarget) && (null != aRepository)) { |
| try { |
| final IFileRevision fileRev = aRepository.getIFileRevision(null, fTarget); |
| fTarget.setFileRevision(fileRev); |
| } catch (ReviewsFileStorageException e) { |
| R4EUIPlugin.Ftracer.traceInfo(R4EUIConstants.EXCEPTION_MSG + e.toString() + " (" + e.getMessage() //$NON-NLS-1$ |
| + ")"); //$NON-NLS-1$ |
| } |
| } |
| |
| fType = aType; |
| fPositions = new ArrayList<IR4EUIPosition>(); |
| } |
| |
| /** |
| * Method getBase. |
| * |
| * @return R4EFileVersion |
| */ |
| public R4EFileVersion getBase() { |
| return fBase; |
| } |
| |
| /** |
| * Method getTarget. |
| * |
| * @return R4EFileVersion |
| */ |
| public R4EFileVersion getTarget() { |
| return fTarget; |
| } |
| |
| /** |
| * Method getType. |
| * |
| * @return R4EContextType |
| */ |
| public R4EContextType getType() { |
| return fType; |
| } |
| |
| /** |
| * Method getPositions. |
| * |
| * @return List<IR4EUIPosition> |
| */ |
| public List<IR4EUIPosition> getPositions() { |
| return fPositions; |
| } |
| } |
| |
| /** |
| * Class JobQueueSchedulingRule Job scheduling rule that only allows a certain number of concurrent Jobs |
| * |
| * @author Sebastien Dubois |
| */ |
| class JobQueueSchedulingRule implements ISchedulingRule { |
| |
| /** |
| * Method contains. |
| * |
| * @param aRule |
| * - ISchedulingRule |
| * @return boolean |
| * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(ISchedulingRule) |
| */ |
| public boolean contains(ISchedulingRule aRule) { |
| return aRule.equals(this); |
| } |
| |
| /** |
| * Method isConflicting. |
| * |
| * @param aRule |
| * - ISchedulingRule |
| * @return boolean |
| * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(ISchedulingRule) |
| */ |
| public boolean isConflicting(ISchedulingRule aRule) { |
| if (aRule.equals(this)) { |
| return true; |
| } |
| |
| if (!(aRule instanceof JobQueueSchedulingRule)) { |
| return false; |
| } |
| |
| /* Conflict if number of running Jobs already greater maximum */ |
| return FindReviewItemsHandler.this.fRunningJobs.intValue() >= MAX_CONCURRRENT_JOBS; |
| } |
| } |
| } |