839b8cd756785f82b9aa2e2f05861e1c7a5dd8cf
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / CommitWorkingCopyOperation.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core;
12
13 import java.io.ByteArrayInputStream;
14 import java.io.UnsupportedEncodingException;
15
16 import net.sourceforge.phpdt.core.IBuffer;
17 import net.sourceforge.phpdt.core.ICompilationUnit;
18 import net.sourceforge.phpdt.core.IJavaElement;
19 import net.sourceforge.phpdt.core.IJavaModelStatus;
20 import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
21 import net.sourceforge.phpdt.core.JavaModelException;
22 import net.sourceforge.phpdt.internal.core.util.Util;
23
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IResource;
26 import org.eclipse.core.resources.IWorkspace;
27 import org.eclipse.core.runtime.CoreException;
28 import org.eclipse.core.runtime.jobs.ISchedulingRule;
29
30 /**
31  * Commits the contents of a working copy compilation unit to its original element and resource, bringing the Java Model up-to-date
32  * with the current contents of the working copy.
33  * 
34  * <p>
35  * It is possible that the contents of the original resource have changed since the working copy was created, in which case there is
36  * an update conflict. This operation allows for two settings to resolve conflict set by the <code>fForce</code> flag:
37  * <ul>
38  * <li>force flag is <code>false</code>- in this case an <code>JavaModelException</code> is thrown</li>
39  * <li>force flag is <code>true</code>- in this case the contents of the working copy are applied to the underlying resource
40  * even though the working copy was created before a subsequent change in the resource</li>
41  * </ul>
42  * 
43  * <p>
44  * The default conflict resolution setting is the force flag is <code>false</code>
45  * 
46  * A JavaModelOperation exception is thrown either if the commit could not be performed or if the new content of the compilation
47  * unit violates some Java Model constraint (e.g. if the new package declaration doesn't match the name of the folder containing the
48  * compilation unit).
49  */
50 public class CommitWorkingCopyOperation extends JavaModelOperation {
51   /**
52    * Constructs an operation to commit the contents of a working copy to its original compilation unit.
53    */
54   public CommitWorkingCopyOperation(ICompilationUnit element, boolean force) {
55     super(new IJavaElement[] { element }, force);
56   }
57
58   /**
59    * @exception JavaModelException
60    *              if setting the source of the original compilation unit fails
61    */
62   protected void executeOperation() throws JavaModelException {
63     try {
64       beginTask(Util.bind("workingCopy.commit"), 2); //$NON-NLS-1$
65       CompilationUnit workingCopy = getCompilationUnit();
66       IFile resource = (IFile) workingCopy.getResource();
67       ICompilationUnit primary = workingCopy.getPrimary();
68       boolean isPrimary = workingCopy.isPrimary();
69
70       JavaElementDeltaBuilder deltaBuilder = null;
71       //                        PackageFragmentRoot root = (PackageFragmentRoot)workingCopy.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
72       boolean isIncluded = !Util.isExcluded(workingCopy);
73       //                        if (isPrimary || (root.isOnClasspath() && isIncluded && resource.isAccessible() &&
74       // Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
75       if (isPrimary || (isIncluded && resource.isAccessible() && Util.isValidCompilationUnitName(workingCopy.getElementName()))) {
76
77         // force opening so that the delta builder can get the old info
78         if (!isPrimary && !primary.isOpen()) {
79           primary.open(null);
80         }
81
82         // creates the delta builder (this remembers the content of the cu) if:
83         // - it is not excluded
84         // - and it is not a primary or it is a non-consistent primary
85         if (isIncluded && (!isPrimary || !workingCopy.isConsistent())) {
86           deltaBuilder = new JavaElementDeltaBuilder(primary);
87         }
88
89         // save the cu
90         IBuffer primaryBuffer = primary.getBuffer();
91         if (!isPrimary) {
92           if (primaryBuffer == null)
93             return;
94           char[] primaryContents = primaryBuffer.getCharacters();
95           boolean hasSaved = false;
96           try {
97             IBuffer workingCopyBuffer = workingCopy.getBuffer();
98             if (workingCopyBuffer == null)
99               return;
100             primaryBuffer.setContents(workingCopyBuffer.getCharacters());
101             primaryBuffer.save(this.progressMonitor, this.force);
102             primary.makeConsistent(this);
103             hasSaved = true;
104           } finally {
105             if (!hasSaved) {
106               // restore original buffer contents since something went wrong
107               primaryBuffer.setContents(primaryContents);
108             }
109           }
110         } else {
111           // for a primary working copy no need to set the content of the buffer again
112           primaryBuffer.save(this.progressMonitor, this.force);
113           primary.makeConsistent(this);
114         }
115       } else {
116         // working copy on cu outside classpath OR resource doesn't exist yet
117         String encoding = null;
118         try {
119           encoding = resource.getCharset();
120         } catch (CoreException ce) {
121           // use no encoding
122         }
123         String contents = workingCopy.getSource();
124         if (contents == null)
125           return;
126         try {
127           byte[] bytes = encoding == null ? contents.getBytes() : contents.getBytes(encoding);
128           ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
129           if (resource.exists()) {
130             resource.setContents(stream, this.force ? IResource.FORCE | IResource.KEEP_HISTORY : IResource.KEEP_HISTORY, null);
131           } else {
132             resource.create(stream, this.force, this.progressMonitor);
133           }
134         } catch (CoreException e) {
135           throw new JavaModelException(e);
136         } catch (UnsupportedEncodingException e) {
137           throw new JavaModelException(e, IJavaModelStatusConstants.IO_EXCEPTION);
138         }
139
140       }
141
142       setAttribute(HAS_MODIFIED_RESOURCE_ATTR, TRUE);
143
144       // make sure working copy is in sync
145       workingCopy.updateTimeStamp((CompilationUnit) primary);
146       workingCopy.makeConsistent(this);
147       worked(1);
148
149       // build the deltas
150       if (deltaBuilder != null) {
151         deltaBuilder.buildDeltas();
152
153         // add the deltas to the list of deltas created during this operation
154         if (deltaBuilder.delta != null) {
155           addDelta(deltaBuilder.delta);
156         }
157       }
158       worked(1);
159     } finally {
160       done();
161     }
162   }
163
164   /**
165    * Returns the compilation unit this operation is working on.
166    */
167   protected CompilationUnit getCompilationUnit() {
168     return (CompilationUnit) getElementToProcess();
169   }
170
171   protected ISchedulingRule getSchedulingRule() {
172     IResource resource = getElementToProcess().getResource();
173     IWorkspace workspace = resource.getWorkspace();
174     if (resource.exists()) {
175       return workspace.getRuleFactory().modifyRule(resource);
176     } else {
177       return workspace.getRuleFactory().createRule(resource);
178     }
179   }
180
181   /**
182    * Possible failures:
183    * <ul>
184    * <li>INVALID_ELEMENT_TYPES - the compilation unit supplied to this operation is not a working copy
185    * <li>ELEMENT_NOT_PRESENT - the compilation unit the working copy is based on no longer exists.
186    * <li>UPDATE_CONFLICT - the original compilation unit has changed since the working copy was created and the operation specifies
187    * no force
188    * <li>READ_ONLY - the original compilation unit is in read-only mode
189    * </ul>
190    */
191   public IJavaModelStatus verify() {
192     CompilationUnit cu = getCompilationUnit();
193     if (!cu.isWorkingCopy()) {
194       return new JavaModelStatus(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, cu);
195     }
196     if (cu.hasResourceChanged() && !this.force) {
197       // axelcl deleted start - force it to VERIFIED_OK, need to be fixed 
198       // return new JavaModelStatus(IJavaModelStatusConstants.UPDATE_CONFLICT);
199       // axelcl end
200     }
201
202     // no read-only check, since some repository adapters can change the flag on save
203     // operation.
204     return JavaModelStatus.VERIFIED_OK;
205   }
206 }