001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring.base;
011:
012: import org.eclipse.core.runtime.CoreException;
013: import org.eclipse.core.runtime.IAdaptable;
014: import org.eclipse.core.runtime.IProgressMonitor;
015: import org.eclipse.core.runtime.SubProgressMonitor;
016:
017: import org.eclipse.core.filebuffers.FileBuffers;
018: import org.eclipse.core.filebuffers.ITextFileBuffer;
019: import org.eclipse.core.filebuffers.ITextFileBufferManager;
020: import org.eclipse.core.filebuffers.LocationKind;
021:
022: import org.eclipse.core.resources.IFile;
023: import org.eclipse.core.resources.IResource;
024:
025: import org.eclipse.jface.text.IDocument;
026: import org.eclipse.jface.text.IDocumentExtension4;
027:
028: import org.eclipse.ltk.core.refactoring.Change;
029: import org.eclipse.ltk.core.refactoring.RefactoringStatus;
030:
031: import org.eclipse.jdt.core.ICompilationUnit;
032: import org.eclipse.jdt.core.IJavaElement;
033:
034: import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
035: import org.eclipse.jdt.internal.corext.util.Messages;
036: import org.eclipse.jdt.internal.corext.util.Resources;
037:
038: /**
039: * JDT specific change object.
040: */
041: public abstract class JDTChange extends Change {
042:
043: private long fModificationStamp;
044: private boolean fReadOnly;
045:
046: private static class ValidationState {
047: private IResource fResource;
048: private int fKind;
049: private boolean fDirty;
050: private boolean fReadOnly;
051: private long fModificationStamp;
052: private ITextFileBuffer fTextFileBuffer;
053: public static final int RESOURCE = 1;
054: public static final int DOCUMENT = 2;
055:
056: public ValidationState(IResource resource) {
057: fResource = resource;
058: if (resource instanceof IFile) {
059: initializeFile((IFile) resource);
060: } else {
061: initializeResource(resource);
062: }
063: }
064:
065: public void checkDirty(RefactoringStatus status,
066: long stampToMatch, IProgressMonitor pm)
067: throws CoreException {
068: if (fDirty) {
069: if (fKind == DOCUMENT && fTextFileBuffer != null
070: && stampToMatch == fModificationStamp) {
071: fTextFileBuffer.commit(pm, false);
072: } else {
073: status.addFatalError(Messages.format(
074: RefactoringCoreMessages.Change_is_unsaved,
075: fResource.getFullPath().toString()));
076: }
077: }
078: }
079:
080: public void checkDirty(RefactoringStatus status) {
081: if (fDirty) {
082: status.addFatalError(Messages.format(
083: RefactoringCoreMessages.Change_is_unsaved,
084: fResource.getFullPath().toString()));
085: }
086: }
087:
088: public void checkReadOnly(RefactoringStatus status) {
089: if (fReadOnly) {
090: status.addFatalError(Messages.format(
091: RefactoringCoreMessages.Change_is_read_only,
092: fResource.getFullPath().toString()));
093: }
094: }
095:
096: public void checkSameReadOnly(RefactoringStatus status,
097: boolean valueToMatch) {
098: if (fReadOnly != valueToMatch) {
099: status.addFatalError(Messages.format(
100: RefactoringCoreMessages.Change_same_read_only,
101: fResource.getFullPath().toString()));
102: }
103: }
104:
105: public void checkModificationStamp(RefactoringStatus status,
106: long stampToMatch) {
107: if (fKind == DOCUMENT) {
108: if (stampToMatch != IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP
109: && fModificationStamp != stampToMatch) {
110: status
111: .addFatalError(Messages
112: .format(
113: RefactoringCoreMessages.Change_has_modifications,
114: fResource.getFullPath()
115: .toString()));
116: }
117: } else {
118: if (stampToMatch != IResource.NULL_STAMP
119: && fModificationStamp != stampToMatch) {
120: status
121: .addFatalError(Messages
122: .format(
123: RefactoringCoreMessages.Change_has_modifications,
124: fResource.getFullPath()
125: .toString()));
126:
127: }
128: }
129: }
130:
131: private void initializeFile(IFile file) {
132: fTextFileBuffer = getBuffer(file);
133: if (fTextFileBuffer == null) {
134: initializeResource(file);
135: } else {
136: IDocument document = fTextFileBuffer.getDocument();
137: fDirty = fTextFileBuffer.isDirty();
138: fReadOnly = Resources.isReadOnly(file);
139: if (document instanceof IDocumentExtension4) {
140: fKind = DOCUMENT;
141: fModificationStamp = ((IDocumentExtension4) document)
142: .getModificationStamp();
143: } else {
144: fKind = RESOURCE;
145: fModificationStamp = file.getModificationStamp();
146: }
147: }
148:
149: }
150:
151: private void initializeResource(IResource resource) {
152: fKind = RESOURCE;
153: fDirty = false;
154: fReadOnly = Resources.isReadOnly(resource);
155: fModificationStamp = resource.getModificationStamp();
156: }
157: }
158:
159: protected static final int NONE = 0;
160: protected static final int READ_ONLY = 1 << 0;
161: protected static final int DIRTY = 1 << 1;
162: private static final int SAVE = 1 << 2;
163: protected static final int SAVE_IF_DIRTY = SAVE | DIRTY;
164:
165: protected JDTChange() {
166: fModificationStamp = IResource.NULL_STAMP;
167: fReadOnly = false;
168: }
169:
170: public void initializeValidationData(IProgressMonitor pm) {
171: IResource resource = getResource(getModifiedElement());
172: if (resource != null) {
173: fModificationStamp = getModificationStamp(resource);
174: fReadOnly = Resources.isReadOnly(resource);
175: }
176: }
177:
178: // protected final RefactoringStatus isValid(IProgressMonitor pm, boolean checkReadOnly, boolean checkDirty) throws CoreException {
179: protected final RefactoringStatus isValid(IProgressMonitor pm,
180: int flags) throws CoreException {
181: pm.beginTask("", 2); //$NON-NLS-1$
182: try {
183: RefactoringStatus result = new RefactoringStatus();
184: Object modifiedElement = getModifiedElement();
185: checkExistence(result, modifiedElement);
186: if (result.hasFatalError())
187: return result;
188: if (flags == NONE)
189: return result;
190: IResource resource = getResource(modifiedElement);
191: if (resource != null) {
192: ValidationState state = new ValidationState(resource);
193: state
194: .checkModificationStamp(result,
195: fModificationStamp);
196: if (result.hasFatalError())
197: return result;
198: state.checkSameReadOnly(result, fReadOnly);
199: if (result.hasFatalError())
200: return result;
201: if ((flags & READ_ONLY) != 0) {
202: state.checkReadOnly(result);
203: if (result.hasFatalError())
204: return result;
205: }
206: if ((flags & DIRTY) != 0) {
207: if ((flags & SAVE) != 0) {
208: state.checkDirty(result, fModificationStamp,
209: new SubProgressMonitor(pm, 1));
210: } else {
211: state.checkDirty(result);
212: }
213: }
214: }
215: return result;
216: } finally {
217: pm.done();
218: }
219: }
220:
221: protected static void checkIfModifiable(RefactoringStatus status,
222: Object element, int flags) {
223: checkIfModifiable(status, getResource(element), flags);
224: }
225:
226: protected static void checkIfModifiable(RefactoringStatus result,
227: IResource resource, int flags) {
228: checkExistence(result, resource);
229: if (result.hasFatalError())
230: return;
231: if (flags == NONE)
232: return;
233: ValidationState state = new ValidationState(resource);
234: if ((flags & READ_ONLY) != 0) {
235: state.checkReadOnly(result);
236: if (result.hasFatalError())
237: return;
238: }
239: if ((flags & DIRTY) != 0) {
240: state.checkDirty(result);
241: }
242: }
243:
244: protected static void checkExistence(RefactoringStatus status,
245: Object element) {
246: if (element == null) {
247: status
248: .addFatalError(RefactoringCoreMessages.DynamicValidationStateChange_workspace_changed);
249:
250: } else if (element instanceof IResource
251: && !((IResource) element).exists()) {
252: status.addFatalError(Messages.format(
253: RefactoringCoreMessages.Change_does_not_exist,
254: ((IResource) element).getFullPath().toString()));
255: } else if (element instanceof IJavaElement
256: && !((IJavaElement) element).exists()) {
257: status.addFatalError(Messages.format(
258: RefactoringCoreMessages.Change_does_not_exist,
259: ((IJavaElement) element).getElementName()));
260: }
261: }
262:
263: private static IResource getResource(Object element) {
264: if (element instanceof IResource) {
265: return (IResource) element;
266: }
267: if (element instanceof ICompilationUnit) {
268: return ((ICompilationUnit) element).getPrimary()
269: .getResource();
270: }
271: if (element instanceof IJavaElement) {
272: return ((IJavaElement) element).getResource();
273: }
274: if (element instanceof IAdaptable) {
275: return (IResource) ((IAdaptable) element)
276: .getAdapter(IResource.class);
277: }
278: return null;
279: }
280:
281: public String toString() {
282: return getName();
283: }
284:
285: public long getModificationStamp(IResource resource) {
286: if (!(resource instanceof IFile))
287: return resource.getModificationStamp();
288: IFile file = (IFile) resource;
289: ITextFileBuffer buffer = getBuffer(file);
290: if (buffer == null) {
291: return file.getModificationStamp();
292: } else {
293: IDocument document = buffer.getDocument();
294: if (document instanceof IDocumentExtension4) {
295: return ((IDocumentExtension4) document)
296: .getModificationStamp();
297: } else {
298: return file.getModificationStamp();
299: }
300: }
301: }
302:
303: private static ITextFileBuffer getBuffer(IFile file) {
304: ITextFileBufferManager manager = FileBuffers
305: .getTextFileBufferManager();
306: return manager.getTextFileBuffer(file.getFullPath(),
307: LocationKind.IFILE);
308: }
309: }
|