001: /*******************************************************************************
002: * Copyright (c) 2006, 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.ui.internal.ide.undo;
011:
012: import java.io.ByteArrayInputStream;
013: import java.io.InputStream;
014: import java.net.URI;
015:
016: import org.eclipse.core.resources.IFile;
017: import org.eclipse.core.resources.IFileState;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.IResourceStatus;
020: import org.eclipse.core.resources.IWorkspaceRoot;
021: import org.eclipse.core.runtime.Assert;
022: import org.eclipse.core.runtime.CoreException;
023: import org.eclipse.core.runtime.IPath;
024: import org.eclipse.core.runtime.IProgressMonitor;
025: import org.eclipse.core.runtime.OperationCanceledException;
026: import org.eclipse.core.runtime.SubProgressMonitor;
027:
028: /**
029: * FileDescription is a lightweight description that describes a file to be
030: * created.
031: *
032: * This class is not intended to be instantiated or used by clients.
033: *
034: * @since 3.3
035: *
036: */
037: public class FileDescription extends AbstractResourceDescription {
038:
039: String name;
040:
041: URI location;
042:
043: String charset;
044:
045: private IFileContentDescription fileContentDescription;
046:
047: /**
048: * Create a FileDescription that can be used to later restore the given
049: * file. The file typically already exists, but this constructor will not
050: * fail if the file does not exist.
051: *
052: * @param file
053: * the file to be restored.
054: */
055: public FileDescription(IFile file) {
056: super (file);
057: this .name = file.getName();
058: try {
059: this .charset = file.getCharset(false);
060: } catch (CoreException e) {
061: // we don't care, a null charset is fine.
062: }
063: if (file.isLinked()) {
064: location = file.getLocationURI();
065: }
066:
067: }
068:
069: /**
070: * Create a file description from the specified file handle. The handle does
071: * not exist, so no information should be derived from it. If a location
072: * path is specified, this file should represent a link to another location.
073: * The content description describes any state that should be used when the
074: * file resource is created.
075: *
076: * @param file
077: * the file to be described
078: * @param linkLocation
079: * the location of the file's link, or <code>null</code> if the
080: * file is not linked
081: * @param fileContentDescription
082: * the file content description that can be used to get
083: * information about the file, such as its initial content
084: */
085: public FileDescription(IFile file, URI linkLocation,
086: IFileContentDescription fileContentDescription) {
087: super (file);
088: this .name = file.getName();
089: this .location = linkLocation;
090: this .charset = null;
091: this .fileContentDescription = fileContentDescription;
092: }
093:
094: /*
095: * (non-Javadoc)
096: *
097: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#recordStateFromHistory(org.eclipse.core.resources.IResource,
098: * org.eclipse.core.runtime.IProgressMonitor)
099: */
100: public void recordStateFromHistory(IResource resource,
101: IProgressMonitor monitor) throws CoreException {
102: Assert.isLegal(resource.getType() == IResource.FILE);
103:
104: if (location != null) {
105: // file is linked, no need to record any history
106: return;
107: }
108: IFileState[] states = ((IFile) resource).getHistory(monitor);
109: if (states.length > 0) {
110: final IFileState state = getMatchingFileState(states);
111: this .fileContentDescription = new IFileContentDescription() {
112: /*
113: * (non-Javadoc)
114: *
115: * @see org.eclipse.ui.internal.ide.undo.IFileContentDescription#exists()
116: */
117: public boolean exists() {
118: return state.exists();
119: }
120:
121: /*
122: * (non-Javadoc)
123: *
124: * @see org.eclipse.ui.internal.ide.undo.IFileContentDescription#getContents()
125: */
126: public InputStream getContents() throws CoreException {
127: return state.getContents();
128: }
129:
130: /*
131: * (non-Javadoc)
132: *
133: * @see org.eclipse.ui.internal.ide.undo.IFileContentDescription#getCharset()
134: */
135: public String getCharset() throws CoreException {
136: return state.getCharset();
137: }
138: };
139: }
140: }
141:
142: /*
143: * (non-Javadoc)
144: *
145: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#createResourceHandle()
146: */
147: public IResource createResourceHandle() {
148: IWorkspaceRoot workspaceRoot = parent.getWorkspace().getRoot();
149: IPath fullPath = parent.getFullPath().append(name);
150: return workspaceRoot.getFile(fullPath);
151: }
152:
153: /*
154: * (non-Javadoc)
155: *
156: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#createExistentResourceFromHandle(org.eclipse.core.resources.IResource,
157: * org.eclipse.core.runtime.IProgressMonitor)
158: */
159: public void createExistentResourceFromHandle(IResource resource,
160: IProgressMonitor monitor) throws CoreException {
161:
162: Assert.isLegal(resource instanceof IFile);
163: if (resource.exists()) {
164: return;
165: }
166: IFile fileHandle = (IFile) resource;
167: monitor.beginTask("", 200); //$NON-NLS-1$
168: monitor
169: .setTaskName(UndoMessages.FileDescription_NewFileProgress);
170: try {
171: if (monitor.isCanceled()) {
172: throw new OperationCanceledException();
173: }
174: if (location != null) {
175: fileHandle.createLink(location,
176: IResource.ALLOW_MISSING_LOCAL,
177: new SubProgressMonitor(monitor, 200));
178: } else {
179: InputStream contents = new ByteArrayInputStream(
180: UndoMessages.FileDescription_ContentsCouldNotBeRestored
181: .getBytes());
182: // Retrieve the contents from the file content
183: // description. Other file state attributes, such as timestamps,
184: // have already been retrieved from the original IResource
185: // object and are restored in #restoreResourceAttributes
186: if (fileContentDescription != null
187: && fileContentDescription.exists()) {
188: contents = fileContentDescription.getContents();
189: }
190: fileHandle.create(contents, false,
191: new SubProgressMonitor(monitor, 100));
192: fileHandle.setCharset(charset, new SubProgressMonitor(
193: monitor, 100));
194: }
195: if (monitor.isCanceled()) {
196: throw new OperationCanceledException();
197: }
198: } catch (CoreException e) {
199: if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) {
200: fileHandle.refreshLocal(IResource.DEPTH_ZERO, null);
201: } else {
202: throw e;
203: }
204: } finally {
205: monitor.done();
206: }
207: }
208:
209: /*
210: * (non-Javadoc)
211: *
212: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#isValid()
213: */
214: public boolean isValid() {
215: if (location != null) {
216: return super .isValid();
217: }
218: return super .isValid() && fileContentDescription != null
219: && fileContentDescription.exists();
220: }
221:
222: /*
223: * (non-Javadoc)
224: *
225: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#getName()
226: */
227: public String getName() {
228: return name;
229: }
230:
231: /*
232: * Get the file state that matches this file description. The local time
233: * stamp is used to try to find a matching file state. If none can be found,
234: * the most recent copy of the file state is used.
235: */
236: private IFileState getMatchingFileState(IFileState[] states) {
237: for (int i = 0; i < states.length; i++) {
238: if (localTimeStamp == states[i].getModificationTime()) {
239: return states[i];
240: }
241: }
242: return states[0];
243:
244: }
245:
246: /*
247: * (non-Javadoc)
248: *
249: * @see org.eclipse.ui.internal.ide.undo.ResourceDescription#restoreResourceAttributes(org.eclipse.core.resources.IResource)
250: */
251: protected void restoreResourceAttributes(IResource resource)
252: throws CoreException {
253: super .restoreResourceAttributes(resource);
254: Assert.isLegal(resource instanceof IFile);
255: IFile file = (IFile) resource;
256: if (charset != null) {
257: file.setCharset(charset, null);
258: }
259: }
260: }
|