/******************************************************************************* * Copyright (c) 2003, 2006 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jst.common.jdt.internal.integration.ui; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; 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.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.javaeditor.ICompilationUnitDocumentProvider; import org.eclipse.jdt.internal.ui.javaeditor.InternalClassFileEditorInput; import org.eclipse.jdt.ui.IWorkingCopyManager; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jem.util.logger.proxy.Logger; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jst.common.jdt.internal.integration.WTPWorkingCopyManager; import org.eclipse.jst.j2ee.internal.plugin.J2EEUIPlugin; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.wst.common.frameworks.internal.SaveFailedException; /** * Insert the type's description here. Creation date: (4/25/2001 7:05:36 PM) * * @author: Administrator */ public class WTPUIWorkingCopyManager extends WTPWorkingCopyManager { private IWorkingCopyManager javaWorkingCopyManager; private ICompilationUnitDocumentProvider cuDocumentProvider; private HashMap editorInputs; private CoreException lastError; /** * WTPUIWorkingCopyManager constructor comment. */ public WTPUIWorkingCopyManager() { super(); cuDocumentProvider = JavaPlugin.getDefault().getCompilationUnitDocumentProvider(); javaWorkingCopyManager = JavaUI.getWorkingCopyManager(); } protected void syncConnect(final IEditorInput input, final ICompilationUnit cu) throws CoreException { Display d = Display.getCurrent(); if (d != null) { lastError = null; d.syncExec(new Runnable() { public void run() { try { connect(input, cu); } catch (CoreException e) { lastError = e; } } }); } else connect(input, cu); if (lastError != null) throw lastError; } /** * Connect the CompilationUnitDocumentProvider to the * * @input and connect the annotation model from the provider to the IDocument of the * @input. */ protected void connect(IEditorInput input, ICompilationUnit cu) throws CoreException { if (input != null && javaWorkingCopyManager != null && cuDocumentProvider != null ) { javaWorkingCopyManager.connect(input); getEditorInputs().put(cu, input); IDocument doc = cuDocumentProvider.getDocument(input); if (doc != null && cuDocumentProvider.getAnnotationModel(input)!= null) cuDocumentProvider.getAnnotationModel(input).connect(doc); } } protected void revertWorkingCopies() { if (getEditorInputs().isEmpty()) return; Iterator it = getEditorInputs().values().iterator(); IEditorInput input; while (it.hasNext()) { input = (IEditorInput) it.next(); revert(input); } } /** * Disonnect the CompilationUnitDocumentProvider from the * * @input and disconnect the annotation model from the provider from the IDocument of the * @input. */ protected void disconnect(IEditorInput input) { IDocument doc = cuDocumentProvider.getDocument(input); cuDocumentProvider.getAnnotationModel(input).disconnect(doc); javaWorkingCopyManager.disconnect(input); } protected void revert(IEditorInput input) { try { cuDocumentProvider.resetDocument(input); } catch (CoreException e) { Logger.getLogger().logError(e); } IDocument doc = cuDocumentProvider.getDocument(input); IAnnotationModel model = cuDocumentProvider.getAnnotationModel(input); if (model instanceof AbstractMarkerAnnotationModel) { AbstractMarkerAnnotationModel markerModel = (AbstractMarkerAnnotationModel) model; markerModel.resetMarkers(); } model.disconnect(doc); javaWorkingCopyManager.disconnect(input); } protected void disconnectEditorInputs() { Iterator it = getEditorInputs().values().iterator(); IEditorInput input; while (it.hasNext()) { input = (IEditorInput) it.next(); disconnect(input); } } protected void discardExistingCompilationUnits() { if (getEditorInputs().isEmpty()) return; Iterator it = getEditorInputs().values().iterator(); IEditorInput input; while (it.hasNext()) { input = (IEditorInput) it.next(); disconnect(input); } } @Override public Set getAffectedFiles() { Set aSet = new HashSet(); Iterator it = getEditorInputs().keySet().iterator(); ICompilationUnit unit = null; IResource resource = null; while (it.hasNext()) { unit = (ICompilationUnit) it.next(); if (isDirty(unit)) { try { resource = unit.getUnderlyingResource(); } catch (JavaModelException ignore) { continue; } if (resource instanceof IFile) aSet.add(resource); } } return aSet; } protected IEditorInput getEditorInput(ICompilationUnit cu) { IEditorInput input = primGetEditorInput(cu); if (input == null) { try { input = getEditorInput((IJavaElement) cu); } catch (JavaModelException e) { //Ignore } } return input; } protected IEditorInput getEditorInput(IJavaElement element) throws JavaModelException { IJavaElement localElement = element; while (localElement != null) { switch (localElement.getElementType()) { case IJavaElement.COMPILATION_UNIT : { ICompilationUnit cu = (ICompilationUnit) localElement; if (cu.isWorkingCopy()) cu = cu.getPrimary(); IResource resource = cu.getUnderlyingResource(); if (resource.getType() == IResource.FILE) return new FileEditorInput((IFile) resource); break; } case IJavaElement.CLASS_FILE : return new InternalClassFileEditorInput((IClassFile) localElement); } localElement = localElement.getParent(); } return null; } /** * Insert the method's description here. Creation date: (4/25/2001 7:30:20 PM) * * @return java.util.HashMap */ protected java.util.HashMap getEditorInputs() { if (editorInputs == null) editorInputs = new HashMap(20); return editorInputs; } /** * Returns the working copy remembered for the compilation unit encoded in the given editor * input. Does not connect the edit model to the working copy. * * @param input * ICompilationUnit * @return the working copy of the compilation unit, or <code>null</code> if the input does * not encode an editor input, or if there is no remembered working copy for this * compilation unit */ @Override public org.eclipse.jdt.core.ICompilationUnit getExistingWorkingCopy(ICompilationUnit cu) throws CoreException { if (cu == null || cu.isWorkingCopy()) { return cu; } ICompilationUnit newCU = super.getExistingWorkingCopy(cu); if (newCU != null) return newCU; IEditorInput editorInput = getEditorInput(cu); return javaWorkingCopyManager.getWorkingCopy(editorInput); } /** * Returns the working copy remembered for the compilation unit. * * @param input * ICompilationUnit * @return the working copy of the compilation unit, or <code>null</code> if there is no * remembered working copy for this compilation unit */ @Override public org.eclipse.jdt.core.ICompilationUnit getWorkingCopy(ICompilationUnit cu, boolean forNewCU) throws org.eclipse.core.runtime.CoreException { if (forNewCU) return super.getWorkingCopy(cu, forNewCU); return primGetWorkingCopy(cu); } public boolean isDirty(ICompilationUnit cu) { if (cu == null) return false; IDocumentProvider p = cuDocumentProvider; return p == null ? false : p.canSaveDocument(getEditorInput(cu)); } /** * mustSaveDocument method comment. */ public boolean isSaveNeeded() { Iterator it = getEditorInputs().entrySet().iterator(); while (it.hasNext()) { if (cuDocumentProvider.mustSaveDocument(it.next())) return true; } return false; } @Override protected void primDispose() { super.primDispose(); discardExistingCompilationUnits(); editorInputs = null; javaWorkingCopyManager = null; } @Override protected void primRevert() { super.primRevert(); revertWorkingCopies(); editorInputs = null; javaWorkingCopyManager = null; } protected IEditorInput primGetEditorInput(ICompilationUnit cu) { return (IEditorInput) getEditorInputs().get(cu); } /** * Returns the working copy remembered for the compilation unit encoded in the given editor * input. * * @param input * ICompilationUnit * @return the working copy of the compilation unit, or <code>null</code> if the input does * not encode an editor input, or if there is no remembered working copy for this * compilation unit */ @Override protected org.eclipse.jdt.core.ICompilationUnit primGetWorkingCopy(ICompilationUnit cu) throws CoreException { if (cu == null) { return cu; } ICompilationUnit primary = cu.getPrimary(); ICompilationUnit newCU = getNewCompilationUnitWorkingCopy(primary); if (newCU != null) return newCU; IEditorInput editorInput = primGetEditorInput(primary); if (editorInput == null) { editorInput = getEditorInput(cu); syncConnect(editorInput, cu); } if (cu.isWorkingCopy()) return cu; return javaWorkingCopyManager.getWorkingCopy(editorInput); } /** * This will save all of the referenced CompilationUnits to be saved. */ @Override protected void primSaveCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { super.primSaveCompilationUnits(null); saveExistingCompilationUnits(monitor); } protected void primSaveDocument(IEditorInput input, IDocument doc, IProgressMonitor monitor) throws CoreException { try { cuDocumentProvider.saveDocument(monitor, input, doc, true); // overwrite if needed } catch (CoreException ex) { if (!isFailedWriteFileFailure(ex)) throw ex; IResource resource = (IResource) input.getAdapter(IRESOURCE_CLASS); if (resource == null || resource.getType() != IResource.FILE || !resource.getResourceAttributes().isReadOnly()) throw ex; if (getSaveHandler().shouldContinueAndMakeFileEditable((IFile) resource)) cuDocumentProvider.saveDocument(monitor, input, doc, false); else throw ex; } } protected void saveDocument(IEditorInput input, IProgressMonitor monitor) { IDocument doc = cuDocumentProvider.getDocument(input); boolean canSave = cuDocumentProvider.canSaveDocument(input); try { if (canSave) { ICompilationUnit unit = javaWorkingCopyManager.getWorkingCopy(input); synchronized (unit) { cuDocumentProvider.aboutToChange(input); primSaveDocument(input, doc, monitor); } } } catch (CoreException e) { J2EEUIPlugin.logError(e); throw new SaveFailedException(e); } finally { if (canSave) cuDocumentProvider.changed(input); } } /** * This will save all of the referenced CompilationUnits to be saved. */ protected void saveExistingCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { if (getEditorInputs().isEmpty()) return; if (!validateState()) { if (monitor != null) monitor.setCanceled(true); return; } Iterator it = getEditorInputs().entrySet().iterator(); Map.Entry entry; // ICompilationUnit cu; IEditorInput input; try { while (it.hasNext()) { entry = (Map.Entry) it.next(); // cu = (ICompilationUnit) entry.getKey(); input = (IEditorInput) entry.getValue(); try { saveDocument(input, null); } finally { disconnect(input); } } } finally { getEditorInputs().clear(); } } /** * Call validateEdit for all read only IFiles corresponding to each WorkingCopy. * * @return boolean */ private boolean validateState() { List readOnlyFiles = getReadOnlyModifiedFiles(); if (readOnlyFiles != null && !readOnlyFiles.isEmpty()) { IFile[] files = new IFile[readOnlyFiles.size()]; readOnlyFiles.toArray(files); IWorkbenchWindow win = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); Object ctx = win == null ? null : win.getShell(); IStatus status = ResourcesPlugin.getWorkspace().validateEdit(files, ctx); return status.isOK(); } return true; } private List getReadOnlyModifiedFiles() { List readOnlyFiles = null; IFile readOnlyFile = null; Iterator it = getEditorInputs().entrySet().iterator(); Map.Entry entry; // ICompilationUnit cu; IEditorInput input; IDocumentProvider docProv = cuDocumentProvider; while (it.hasNext()) { readOnlyFile = null; entry = (Map.Entry) it.next(); // cu = (ICompilationUnit) entry.getKey(); input = (IEditorInput) entry.getValue(); if (docProv.canSaveDocument(input)) readOnlyFile = getReadOnlyFile(input); if (readOnlyFile != null) { if (readOnlyFiles == null) readOnlyFiles = new ArrayList(); readOnlyFiles.add(readOnlyFile); } } return readOnlyFiles; } private IFile getReadOnlyFile(IEditorInput input) { if (input instanceof IFileEditorInput) { IFileEditorInput finput = (IFileEditorInput) input; IFile file = finput.getFile(); if (file.isReadOnly()) return file; } return null; } @Override protected void addDeletedCompilationUnit(ICompilationUnit cu) { IEditorInput input = primGetEditorInput(cu); if (input != null) disconnect(input); getEditorInputs().remove(cu); super.addDeletedCompilationUnit(cu); } /** * @see com.ibm.etools.j2ee.workbench.IJ2EEWorkingCopyManager#hasWorkingCopies() */ @Override public boolean hasWorkingCopies() { return super.hasWorkingCopies() || (editorInputs != null && !editorInputs.isEmpty()); } }