KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ui > synchronize > LocalResourceTypedElement


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ui.synchronize;
12
13 import java.io.*;
14
15 import org.eclipse.compare.ISharedDocumentAdapter;
16 import org.eclipse.compare.ResourceNode;
17 import org.eclipse.core.resources.IFile;
18 import org.eclipse.core.resources.IResource;
19 import org.eclipse.core.runtime.*;
20 import org.eclipse.ui.IEditorInput;
21
22 /**
23  * A buffered resource node with the following characteristics:
24  * <ul>
25  * <li>Supports the use of file buffers (see {@link ISharedDocumentAdapter}.
26  * <li>Does not support file systems hierarchies (i.e. should not be used to represent a folder).
27  * <li>Does not allow editing when the file does not exist (see {@link #isEditable()}
28  * <li>Tracks whether the file has been changed on disk since it was loaded through the element
29  * (see {@link #isSynchronized()}).
30  * <li>Any buffered contents must either be saved or discarded when the element is no longer needed
31  * (see {@link #commit(IProgressMonitor)}, {@link #saveDocument(boolean, IProgressMonitor)}
32  * and {@link #discardBuffer()})
33  * </ul>
34  * <p>
35  * This class may be instantiated but may not subclass it.
36  *
37  * @since 3.3
38  */

39 public class LocalResourceTypedElement extends ResourceNode implements IAdaptable {
40
41     private boolean fDirty = false;
42     private EditableSharedDocumentAdapter sharedDocumentAdapter;
43     private long timestamp;
44     private boolean exists;
45     private boolean useSharedDocument = true;
46     private EditableSharedDocumentAdapter.ISharedDocumentAdapterListener sharedDocumentListener;
47
48     /**
49      * Creates an element for the given resource.
50      * @param resource the resource
51      */

52     public LocalResourceTypedElement(IResource resource) {
53         super(resource);
54         exists = resource.exists();
55     }
56
57     /* (non-Javadoc)
58      * @see org.eclipse.compare.BufferedContent#setContent(byte[])
59      */

60     public void setContent(byte[] contents) {
61         fDirty = true;
62         super.setContent(contents);
63     }
64
65     /**
66      * Commits buffered contents to the underlying resource. Note that if the
67      * element has a shared document, the commit will not succeed since the
68      * contents will be buffered in the shared document and will not be pushed
69      * to this element using {@link #setContent(byte[])}. Clients should check
70      * whether the element {@link #isConnected()} and, if it is, they should call
71      * {@link #saveDocument(boolean, IProgressMonitor)} to save the buffered contents to
72      * the underlying resource.
73      * @param monitor a progress monitor
74      * @throws CoreException
75      */

76     public void commit(IProgressMonitor monitor) throws CoreException {
77         if (isDirty()) {
78             if (isConnected()) {
79                 saveDocument(true, monitor);
80             } else {
81                 IResource resource = getResource();
82                 if (resource instanceof IFile) {
83                     ByteArrayInputStream is = new ByteArrayInputStream(getContent());
84                     try {
85                         IFile file = (IFile) resource;
86                         if (file.exists())
87                             file.setContents(is, false, true, monitor);
88                         else
89                             file.create(is, false, monitor);
90                         fDirty = false;
91                     } finally {
92                         fireContentChanged();
93                         if (is != null)
94                             try {
95                                 is.close();
96                             } catch (IOException ex) {
97                             }
98                     }
99                 }
100                 updateTimestamp();
101             }
102         }
103     }
104     
105     /* (non-Javadoc)
106      * @see org.eclipse.compare.ResourceNode#getContents()
107      */

108     public InputStream getContents() throws CoreException {
109         if (exists)
110             return super.getContents();
111         return null;
112     }
113
114     /* (non-Javadoc)
115      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
116      */

117     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
118         if (adapter == ISharedDocumentAdapter.class) {
119             if (isSharedDocumentsEnable())
120                 return getSharedDocumentAdapter();
121             else
122                 return null;
123         }
124         return Platform.getAdapterManager().getAdapter(this, adapter);
125     }
126
127     /*
128      * Returned the shared document adapter for this element. If one does not exist
129      * yet, it will be created.
130      */

131     private synchronized ISharedDocumentAdapter getSharedDocumentAdapter() {
132         if (sharedDocumentAdapter == null)
133             sharedDocumentAdapter = new EditableSharedDocumentAdapter(new EditableSharedDocumentAdapter.ISharedDocumentAdapterListener() {
134                 public void handleDocumentConnected() {
135                     LocalResourceTypedElement.this.updateTimestamp();
136                     if (sharedDocumentListener != null)
137                         sharedDocumentListener.handleDocumentConnected();
138                 }
139                 public void handleDocumentFlushed() {
140                     LocalResourceTypedElement.this.fireContentChanged();
141                     if (sharedDocumentListener != null)
142                         sharedDocumentListener.handleDocumentFlushed();
143                 }
144                 public void handleDocumentDeleted() {
145                     LocalResourceTypedElement.this.update();
146                     if (sharedDocumentListener != null)
147                         sharedDocumentListener.handleDocumentDeleted();
148                 }
149                 public void handleDocumentSaved() {
150                     LocalResourceTypedElement.this.updateTimestamp();
151                     if (sharedDocumentListener != null)
152                         sharedDocumentListener.handleDocumentSaved();
153                 }
154                 public void handleDocumentDisconnected() {
155                     if (sharedDocumentListener != null)
156                         sharedDocumentListener.handleDocumentDisconnected();
157                 }
158             });
159         return sharedDocumentAdapter;
160     }
161
162     /* (non-Javadoc)
163      * @see org.eclipse.compare.ResourceNode#isEditable()
164      */

165     public boolean isEditable() {
166         // Do not allow non-existent files to be edited
167
IResource resource = getResource();
168         return resource.getType() == IResource.FILE && exists;
169     }
170
171     /**
172      * Return whether the element is connected to a shared document.
173      * When connected, the element can be saved using {@link #saveDocument(boolean, IProgressMonitor)}.
174      * Otherwise, {@link #commit(IProgressMonitor)} should be used to save the buffered contents.
175      * @return whether the element is connected to a shared document
176      */

177     public boolean isConnected() {
178         return sharedDocumentAdapter != null
179                 && sharedDocumentAdapter.isConnected();
180     }
181
182     /**
183      * ZSave the shared document for this element. The save can only be performed
184      * if the element is connected to a shared document. If the element is not
185      * connected, <code>false</code> is returned.
186      * @param overwrite indicates whether overwrite should be performed
187      * while saving the given element if necessary
188      * @param monitor a progress monitor
189      * @return whether the save succeeded or not
190      * @throws CoreException
191      */

192     public boolean saveDocument(boolean overwrite, IProgressMonitor monitor) throws CoreException {
193         if (isConnected()) {
194             IEditorInput input = sharedDocumentAdapter.getDocumentKey(this);
195             sharedDocumentAdapter.saveDocument(input, overwrite, monitor);
196             updateTimestamp();
197             return true;
198         }
199         return false;
200     }
201
202     /* (non-Javadoc)
203      * @see org.eclipse.compare.ResourceNode#createStream()
204      */

205     protected InputStream createStream() throws CoreException {
206         InputStream inputStream = super.createStream();
207         updateTimestamp();
208         return inputStream;
209     }
210     
211     /**
212      * Update the cached timestamp of the resource.
213      */

214     void updateTimestamp() {
215         if (getResource().exists())
216             timestamp = getResource().getLocalTimeStamp();
217         else
218             exists = false;
219     }
220
221     /**
222      * Return the cached timestamp of the resource.
223      * @return the cached timestamp of the resource
224      */

225     private long getTimestamp() {
226         return timestamp;
227     }
228     
229     /* (non-Javadoc)
230      * @see org.eclipse.compare.ResourceNode#hashCode()
231      */

232     public int hashCode() {
233         return getResource().hashCode();
234     }
235     
236     /* (non-Javadoc)
237      * @see org.eclipse.compare.ResourceNode#equals(java.lang.Object)
238      */

239     public boolean equals(Object JavaDoc other) {
240         if (other instanceof LocalResourceTypedElement) {
241             LocalResourceTypedElement otherElement = (LocalResourceTypedElement) other;
242             return otherElement.getResource().equals(getResource())
243                 && exists == otherElement.exists;
244         }
245         return super.equals(other);
246     }
247
248     /**
249      * Method called to update the state of this element when the compare input that
250      * contains this element is issuing a change event. It is not necessarily the
251      * case that the {@link #isSynchronized()} will return <code>true</code> after this
252      * call.
253      */

254     public void update() {
255         exists = getResource().exists();
256     }
257
258     /**
259      * Return whether the contents provided by this typed element are in-sync with what is on
260      * disk. This method will return <code>false</code> if the file has been changed
261      * externally since the last time the contents were obtained or saved through this
262      * element.
263      * @return whether the contents provided by this typed element are in-sync with what is on
264      * disk
265      */

266     public boolean isSynchronized() {
267         long current = getResource().getLocalTimeStamp();
268         return current == getTimestamp();
269     }
270
271     /**
272      * Return whether the resource of this element existed at the last time the typed
273      * element was updated.
274      * @return whether the resource of this element existed at the last time the typed
275      * element was updated
276      */

277     public boolean exists() {
278         return exists;
279     }
280     
281     /* (non-Javadoc)
282      * @see org.eclipse.compare.BufferedContent#fireContentChanged()
283      */

284     protected void fireContentChanged() {
285         super.fireContentChanged();
286     }
287     
288     /**
289      * Discard of any buffered contents. This must be called
290      * when the local element is no longer needed but is dirty since a
291      * the element will connect to a shared document when a merge viewer
292      * flushes its contents to the element and it must be disconnected or the
293      * buffer will remain.
294      * #see {@link #isDirty()}
295      */

296     public void discardBuffer() {
297         if (sharedDocumentAdapter != null)
298             sharedDocumentAdapter.releaseBuffer();
299         super.discardBuffer();
300     }
301
302     /**
303      * Return whether this element can use a shared document.
304      * @return whether this element can use a shared document
305      */

306     public boolean isSharedDocumentsEnable() {
307         return useSharedDocument && getResource().getType() == IResource.FILE && exists;
308     }
309
310     /**
311      * Set whether this element can use shared documents. The enablement
312      * will only apply to files (i.e. shared documents never apply to folders).
313      * @param enablement whether this element can use shared documents
314      */

315     public void enableSharedDocument(boolean enablement) {
316         this.useSharedDocument = enablement;
317     }
318
319     /**
320      * Return whether this element is dirty. The element is
321      * dirty if a merge viewer has flushed it's contents
322      * to the element and the contents have not been saved.
323      * @return whether this element is dirty
324      * @see #commit(IProgressMonitor)
325      * @see #saveDocument(boolean, IProgressMonitor)
326      * @see #discardBuffer()
327      */

328     public boolean isDirty() {
329         return fDirty || (sharedDocumentAdapter != null && sharedDocumentAdapter.hasBufferedContents());
330     }
331
332     public void setSharedDocumentListener(
333             EditableSharedDocumentAdapter.ISharedDocumentAdapterListener sharedDocumentListener) {
334         this.sharedDocumentListener = sharedDocumentListener;
335     }
336
337 }
338
Popular Tags