| /******************************************************************************* |
| * Copyright (c) 2003, 2004 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; |
| |
| |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| 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.IWorkspace; |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.IPackageFragment; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jem.util.logger.proxy.Logger; |
| import org.eclipse.wst.common.frameworks.internal.ISaveHandler; |
| import org.eclipse.wst.common.frameworks.internal.SaveFailedException; |
| import org.eclipse.wst.common.frameworks.internal.SaveHandlerHeadless; |
| import org.eclipse.wst.common.frameworks.internal.SaveHandlerRegister; |
| import org.eclipse.wst.common.frameworks.internal.plugin.WTPCommonPlugin; |
| |
| /** |
| * Insert the type's description here. Creation date: (4/27/2001 4:14:30 PM) |
| * |
| * @author: Administrator |
| */ |
| public class WTPWorkingCopyManager implements WorkingCopyManager { |
| |
| //New CUs that will need to be deleted upon dispose |
| private List originalNewCompilationUnits; |
| //New CUs that were created that need saved immediately (after each gen) |
| private List needsSavingCompilationUnits; |
| //A complete list of new CUs that is only cleared on save and dispose |
| private List newCompilationUnits; |
| private HashMap deletedCompilationUnits; |
| protected static final Class IRESOURCE_CLASS = IResource.class; |
| |
| /** |
| * WTPWorkingCopyManager constructor comment. |
| */ |
| public WTPWorkingCopyManager() { |
| super(); |
| } |
| |
| protected void addDeletedCompilationUnit(ICompilationUnit cu) { |
| getNeedsSavingCompilationUnits().remove(cu); |
| if (!getOriginalNewCompilationUnits().contains(cu) && !getDeletedCompilationUnits().containsKey(cu)) |
| primAddDeletedCompilationUnit(cu); |
| getOriginalNewCompilationUnits().remove(cu); |
| } |
| |
| protected void addNewCompilationUnit(ICompilationUnit cu, ICompilationUnit workingCopy) { |
| getNewCompilationUnits().add(cu); |
| getNeedsSavingCompilationUnits().add(workingCopy); |
| if (!getDeletedCompilationUnits().containsKey(cu)) |
| getOriginalNewCompilationUnits().add(cu); |
| } |
| |
| /** |
| * This will save all of the new CompilationUnits to be saved. |
| */ |
| protected void commitWorkingCopy(ICompilationUnit wc, IProgressMonitor monitor) { |
| try { |
| try { |
| wc.commitWorkingCopy(false, monitor); |
| } catch (JavaModelException e) { |
| if (isFailedWriteFileFailure(e) && shouldSaveReadOnly(wc)) |
| wc.commitWorkingCopy(false, monitor); |
| else |
| throw e; |
| } |
| } catch (JavaModelException e) { |
| org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e); |
| throw new SaveFailedException(e); |
| } finally { |
| try { |
| wc.discardWorkingCopy(); |
| } catch (JavaModelException e1) { |
| org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e1); |
| throw new SaveFailedException(e1); |
| } |
| } |
| } |
| |
| /** |
| * This will delete |
| * |
| * @cu from the workbench and fix the internal references for this working copy manager. |
| */ |
| public void delete(ICompilationUnit cu, IProgressMonitor monitor) { |
| if (cu.isWorkingCopy()) |
| cu = cu.getPrimary(); |
| addDeletedCompilationUnit(cu); |
| try { |
| cu.delete(false, monitor); |
| } catch (JavaModelException e) { |
| if (e.getStatus().getCode() != org.eclipse.jdt.core.IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST) |
| org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e); |
| } |
| } |
| |
| protected void discardOriginalNewCompilationUnits() { |
| if (getOriginalNewCompilationUnits().isEmpty()) |
| return; |
| List cus = getOriginalNewCompilationUnits(); |
| ICompilationUnit cu; |
| ICompilationUnit wc = null; |
| for (int i = 0; i < cus.size(); i++) { |
| cu = (ICompilationUnit) cus.get(i); |
| if (cu.isWorkingCopy()) { |
| wc = cu; |
| cu = wc.getPrimary(); |
| } |
| primDelete(cu); |
| if (wc != null) |
| try { |
| wc.discardWorkingCopy(); |
| } catch (JavaModelException e) { |
| Logger.getLogger().logError(e); |
| } |
| } |
| } |
| |
| public void dispose() { |
| IWorkspaceRunnable runnable = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor aMonitor) { |
| primDispose(); |
| } |
| }; |
| try { |
| if (!WTPCommonPlugin.getWorkspace().isTreeLocked()) { |
| WTPCommonPlugin.getWorkspace().run(runnable,null, IWorkspace.AVOID_UPDATE,null); |
| } else { |
| runnable.run(null); |
| } |
| } catch (CoreException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| //runOperation(runnable, null, true); |
| } |
| |
| public void revert() { |
| IWorkspaceRunnable runnable = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor aMonitor) { |
| primRevert(); |
| } |
| }; |
| runOperation(runnable, null, true); |
| } |
| |
| public Set getAffectedFiles() { |
| return Collections.EMPTY_SET; |
| } |
| |
| /** |
| * Insert the method's description here. Creation date: (7/11/2001 6:43:37 PM) |
| * |
| * @return java.util.HashMap |
| */ |
| protected HashMap getDeletedCompilationUnits() { |
| if (deletedCompilationUnits == null) |
| deletedCompilationUnits = new HashMap(); |
| return deletedCompilationUnits; |
| } |
| |
| /** |
| * 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 |
| */ |
| public org.eclipse.jdt.core.ICompilationUnit getExistingWorkingCopy(ICompilationUnit cu) throws CoreException { |
| ICompilationUnit newCU = getNewCompilationUnitWorkingCopy(cu); |
| if (newCU != null) |
| return newCU; |
| return null; |
| } |
| |
| /** |
| * Insert the method's description here. Creation date: (7/19/2001 11:00:19 AM) |
| * |
| * @return java.util.List |
| */ |
| protected java.util.List getNeedsSavingCompilationUnits() { |
| if (needsSavingCompilationUnits == null) |
| needsSavingCompilationUnits = new ArrayList(); |
| return needsSavingCompilationUnits; |
| } |
| |
| /** |
| * Insert the method's description here. Creation date: (4/26/2001 3:49:05 PM) |
| * |
| * @return java.util.List |
| */ |
| protected java.util.List getNewCompilationUnits() { |
| if (newCompilationUnits == null) |
| newCompilationUnits = new ArrayList(); |
| return newCompilationUnits; |
| } |
| |
| /** |
| * It is possible that we have already created this CompilationUnit and its working copy. If |
| * this is the case, return our new working copy and do not create a new one. |
| */ |
| protected ICompilationUnit getNewCompilationUnitWorkingCopy(ICompilationUnit cu) { |
| if (hasNewCompilationUnit(cu)) { |
| List list = getNeedsSavingCompilationUnits(); |
| ICompilationUnit copy; |
| for (int i = 0; i < list.size(); i++) { |
| copy = (ICompilationUnit) list.get(i); |
| if (cu.equals(copy.getPrimary())) |
| return copy; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * Insert the method's description here. Creation date: (4/26/2001 3:49:05 PM) |
| * |
| * @return java.util.List |
| */ |
| protected java.util.List getOriginalNewCompilationUnits() { |
| if (originalNewCompilationUnits == null) |
| originalNewCompilationUnits = new ArrayList(); |
| return originalNewCompilationUnits; |
| } |
| |
| /** |
| * Return the IPackageFragment for the given ICompilationUnit. |
| */ |
| protected IPackageFragment getPackageFragment(ICompilationUnit cu) { |
| if (cu == null) |
| return null; |
| IJavaElement parent = cu; |
| int elementType = cu.getElementType(); |
| while (parent != null && elementType != IJavaElement.PACKAGE_FRAGMENT) { |
| parent = parent.getParent(); |
| if (parent != null) |
| elementType = parent.getElementType(); |
| else |
| elementType = -1; |
| } |
| return (IPackageFragment) parent; |
| } |
| |
| protected ISaveHandler getSaveHandler() { |
| return SaveHandlerRegister.getSaveHandler(); |
| } |
| |
| /** |
| * 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 |
| */ |
| public ICompilationUnit getWorkingCopy(ICompilationUnit cu, boolean forNewCU) throws org.eclipse.core.runtime.CoreException { |
| if (cu == null || cu.isWorkingCopy()) |
| return cu; |
| ICompilationUnit newCU = getNewCompilationUnitWorkingCopy(cu); |
| if (newCU != null) |
| return newCU; |
| ICompilationUnit workingCopy = cu.getWorkingCopy(null); |
| addNewCompilationUnit(cu, workingCopy); |
| return workingCopy; |
| } |
| |
| /** |
| * Has a new compilation unit already been created. |
| */ |
| protected boolean hasNewCompilationUnit(ICompilationUnit cu) { |
| return getNewCompilationUnits().contains(cu); |
| } |
| |
| protected boolean isFailedWriteFileFailure(Exception ex) { |
| return SaveHandlerHeadless.isFailedWriteFileFailure(ex); |
| } |
| |
| protected void primAddDeletedCompilationUnit(ICompilationUnit cu) { |
| if (cu == null) |
| return; |
| Object[] info = new Object[2]; |
| info[0] = getPackageFragment(cu); |
| try { |
| info[1] = cu.getSource(); |
| } catch (JavaModelException e) { |
| info[1] = null; |
| } |
| getDeletedCompilationUnits().put(cu, info); |
| } |
| |
| // This is an internal delete call. |
| protected void primDelete(ICompilationUnit cu) { |
| try { |
| if (cu.exists()) |
| cu.delete(true, new org.eclipse.core.runtime.NullProgressMonitor()); |
| } catch (JavaModelException e) { |
| org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e); |
| //What to do here? |
| } |
| } |
| |
| protected void primDispose() { |
| discardOriginalNewCompilationUnits(); |
| reviveDeletedCompilationUnits(); |
| newCompilationUnits = null; |
| needsSavingCompilationUnits = null; |
| originalNewCompilationUnits = null; |
| deletedCompilationUnits = null; |
| } |
| |
| protected void primRevert() { |
| discardOriginalNewCompilationUnits(); |
| reviveDeletedCompilationUnits(); |
| newCompilationUnits = null; |
| needsSavingCompilationUnits = null; |
| originalNewCompilationUnits = null; |
| deletedCompilationUnits = null; |
| } |
| |
| /** |
| * 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 |
| */ |
| protected ICompilationUnit primGetWorkingCopy(ICompilationUnit cu) throws CoreException { |
| return null; |
| } |
| |
| /** |
| * This will save all of the referenced CompilationUnits to be saved. |
| */ |
| protected void primSaveCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { |
| saveNewCompilationUnits(monitor); |
| getDeletedCompilationUnits().clear(); |
| } |
| |
| /** |
| * This will save all of the new CompilationUnits to be saved. |
| */ |
| protected void primSaveOnlyNewCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { |
| List cus = getNeedsSavingCompilationUnits(); |
| ICompilationUnit wc; |
| for (int i = 0; i < cus.size(); i++) { |
| wc = (ICompilationUnit) cus.get(i); |
| commitWorkingCopy(wc, monitor); |
| } |
| cus.clear(); |
| } |
| |
| protected void removeDeletedCompilationUnit(ICompilationUnit cu) { |
| if (getDeletedCompilationUnits().remove(cu) != null) { |
| if (cu.isWorkingCopy()) { |
| ICompilationUnit original, nextCU, testCU; |
| original = cu.getPrimary(); |
| Set cus = getDeletedCompilationUnits().keySet(); |
| Iterator it = cus.iterator(); |
| while (it.hasNext()) { |
| nextCU = (ICompilationUnit) it.next(); |
| testCU = nextCU.isWorkingCopy() ? (ICompilationUnit) nextCU.getPrimary() : nextCU; |
| if (testCU.equals(original)) { |
| cus.remove(nextCU); |
| return; |
| } |
| } |
| } |
| } |
| } |
| |
| protected void reviveDeletedCompilationUnit(ICompilationUnit cu, Object[] info, IProgressMonitor pm) { |
| if (info[0] != null && info[1] != null) { |
| String typeName = cu.getElementName(); |
| IPackageFragment pack = (IPackageFragment) info[0]; |
| String source = (String) info[1]; |
| try { |
| ICompilationUnit existingCU = pack.getCompilationUnit(typeName); |
| if (existingCU.exists() && getNewCompilationUnits().contains(existingCU)) |
| existingCU.delete(false, pm); |
| pack.createCompilationUnit(typeName, source, false, pm); |
| } catch (JavaModelException e) { |
| org.eclipse.jem.util.logger.proxy.Logger.getLogger().logError(e); |
| } |
| } |
| } |
| |
| protected void reviveDeletedCompilationUnits() { |
| if (getDeletedCompilationUnits().isEmpty()) |
| return; |
| IProgressMonitor pm = new org.eclipse.core.runtime.NullProgressMonitor(); |
| Iterator it = getDeletedCompilationUnits().entrySet().iterator(); |
| Map.Entry entry; |
| ICompilationUnit cu; |
| Object[] info; |
| while (it.hasNext()) { |
| entry = (Map.Entry) it.next(); |
| cu = (ICompilationUnit) entry.getKey(); |
| info = (Object[]) entry.getValue(); |
| reviveDeletedCompilationUnit(cu, info, pm); |
| } |
| |
| } |
| |
| protected void runOperation(IWorkspaceRunnable aRunnable, IProgressMonitor monitor, boolean validate) { |
| primRunOperation(aRunnable, monitor); |
| |
| // TODO Break the validator depedency |
| // if (validate) |
| // primRunOperation(aRunnable, monitor); |
| // else { |
| // IProject proj = getValidationProject(); |
| // |
| // ValidatorManager mgr = ValidatorManager.getManager(); |
| // boolean disableValidators = proj != null; |
| // boolean wasSuspended = false; |
| // if (disableValidators) { |
| // wasSuspended = mgr.isSuspended(proj); |
| // if (!wasSuspended) |
| // mgr.suspendValidation(proj, true); |
| // } |
| // try { |
| // primRunOperation(aRunnable, monitor); |
| // } finally { |
| // if (disableValidators && !wasSuspended) |
| // mgr.suspendValidation(proj, false); |
| // } |
| // } |
| } |
| |
| protected void primRunOperation(IWorkspaceRunnable aRunnable, IProgressMonitor monitor) { |
| |
| if (aRunnable != null) { |
| //if (workspace.isTreeLocked()) |
| //Logger.getLogger().logTrace(ResourceHandler.getString("Cannot_run_J2EEUIWorkingCo_ERROR_")); |
| // //$NON-NLS-1$ = "Cannot run J2EEUIWorkingCopyManager operation because the Workspace |
| // tree is locked." |
| //else { |
| if (!WTPCommonPlugin.getWorkspace().isTreeLocked()) { |
| try { |
| WTPCommonPlugin.getWorkspace().run(aRunnable, monitor); |
| } catch (CoreException e) { |
| throw new SaveFailedException(e); |
| } |
| } |
| } |
| } |
| |
| /** |
| * This will save all of the referenced CompilationUnits to be saved. |
| */ |
| public void saveCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { |
| getSaveHandler().access(); |
| try { |
| IWorkspaceRunnable runnable = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor aMonitor) { |
| primSaveCompilationUnits(aMonitor); |
| } |
| }; |
| runOperation(runnable, monitor, true); |
| } catch (SaveFailedException ex) { |
| getSaveHandler().handleSaveFailed(ex, monitor); |
| } finally { |
| getSaveHandler().release(); |
| } |
| } |
| |
| /** |
| * This will save all of the referenced CompilationUnits to be saved. |
| */ |
| protected void saveNewCompilationUnits(IProgressMonitor monitor) { |
| primSaveOnlyNewCompilationUnits(monitor); |
| getOriginalNewCompilationUnits().clear(); |
| getNewCompilationUnits().clear(); |
| } |
| |
| /** |
| * This will save all of the new CompilationUnits to be saved. |
| */ |
| public void saveOnlyNewCompilationUnits(org.eclipse.core.runtime.IProgressMonitor monitor) { |
| getSaveHandler().access(); |
| try { |
| IWorkspaceRunnable runnable = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor aMonitor) { |
| primSaveOnlyNewCompilationUnits(aMonitor); |
| } |
| }; |
| runOperation(runnable, monitor, false); |
| } catch (SaveFailedException ex) { |
| getSaveHandler().handleSaveFailed(ex, monitor); |
| } finally { |
| getSaveHandler().release(); |
| } |
| } |
| |
| protected boolean shouldSaveReadOnly(ICompilationUnit wc) { |
| IResource resource = null; |
| |
| resource = (IResource) wc.getPrimary().getAdapter(IRESOURCE_CLASS); |
| |
| if (resource == null || resource.getType() != IResource.FILE || !resource.getResourceAttributes().isReadOnly()) |
| return false; |
| |
| return getSaveHandler().shouldContinueAndMakeFileEditable((IFile) resource); |
| } |
| |
| /** |
| * @see com.ibm.etools.j2ee.workbench.IJ2EEWorkingCopyManager#hasWorkingCopies() |
| */ |
| public boolean hasWorkingCopies() { |
| return (deletedCompilationUnits != null && !deletedCompilationUnits.isEmpty()) || (needsSavingCompilationUnits != null && !needsSavingCompilationUnits.isEmpty()) || (newCompilationUnits != null && !newCompilationUnits.isEmpty()); |
| } |
| |
| } |