KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > resources > Synchronizer


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.core.internal.resources;
12
13 import java.io.*;
14 import java.util.*;
15 import org.eclipse.core.internal.localstore.SafeChunkyInputStream;
16 import org.eclipse.core.internal.localstore.SafeFileInputStream;
17 import org.eclipse.core.internal.utils.Messages;
18 import org.eclipse.core.internal.utils.Policy;
19 import org.eclipse.core.internal.watson.IPathRequestor;
20 import org.eclipse.core.resources.*;
21 import org.eclipse.core.runtime.*;
22 import org.eclipse.osgi.util.NLS;
23
24 //
25
public class Synchronizer implements ISynchronizer {
26     protected Workspace workspace;
27     protected SyncInfoWriter writer;
28
29     // Registry of sync partners. Set of qualified names.
30
protected Set registry = new HashSet(5);
31
32     public Synchronizer(Workspace workspace) {
33         super();
34         this.workspace = workspace;
35         this.writer = new SyncInfoWriter(workspace, this);
36     }
37
38     /**
39      * @see ISynchronizer#accept(QualifiedName, IResource, IResourceVisitor, int)
40      */

41     public void accept(QualifiedName partner, IResource resource, IResourceVisitor visitor, int depth) throws CoreException {
42         Assert.isLegal(partner != null);
43         Assert.isLegal(resource != null);
44         Assert.isLegal(visitor != null);
45
46         // if we don't have sync info for the given identifier, then skip it
47
if (getSyncInfo(partner, resource) != null) {
48             // visit the resource and if the visitor says to stop the recursion then return
49
if (!visitor.visit(resource))
50                 return;
51         }
52
53         // adjust depth if necessary
54
if (depth == IResource.DEPTH_ZERO || resource.getType() == IResource.FILE)
55             return;
56         if (depth == IResource.DEPTH_ONE)
57             depth = IResource.DEPTH_ZERO;
58
59         // otherwise recurse over the children
60
IResource[] children = ((IContainer) resource).members();
61         for (int i = 0; i < children.length; i++)
62             accept(partner, children[i], visitor, depth);
63     }
64
65     /**
66      * @see ISynchronizer#add(QualifiedName)
67      */

68     public void add(QualifiedName partner) {
69         Assert.isLegal(partner != null);
70         registry.add(partner);
71     }
72
73     /**
74      * @see ISynchronizer#flushSyncInfo(QualifiedName, IResource, int)
75      */

76     public void flushSyncInfo(final QualifiedName partner, final IResource root, final int depth) throws CoreException {
77         Assert.isLegal(partner != null);
78         Assert.isLegal(root != null);
79
80         IWorkspaceRunnable body = new IWorkspaceRunnable() {
81             public void run(IProgressMonitor monitor) throws CoreException {
82                 IResourceVisitor visitor = new IResourceVisitor() {
83                     public boolean visit(IResource resource) throws CoreException {
84                         //only need to flush sync info if there is sync info
85
if (getSyncInfo(partner, resource) != null)
86                             setSyncInfo(partner, resource, null);
87                         return true;
88                     }
89                 };
90                 root.accept(visitor, depth, true);
91             }
92         };
93         workspace.run(body, root, IResource.NONE, null);
94     }
95
96     /**
97      * @see ISynchronizer#getPartners()
98      */

99     public QualifiedName[] getPartners() {
100         return (QualifiedName[]) registry.toArray(new QualifiedName[registry.size()]);
101     }
102
103     /**
104      * For use by the serialization code.
105      */

106     protected Set getRegistry() {
107         return registry;
108     }
109
110     /**
111      * @see ISynchronizer#getSyncInfo(QualifiedName, IResource)
112      */

113     public byte[] getSyncInfo(QualifiedName partner, IResource resource) throws CoreException {
114         Assert.isLegal(partner != null);
115         Assert.isLegal(resource != null);
116
117         if (!isRegistered(partner)) {
118             String JavaDoc message = NLS.bind(Messages.synchronizer_partnerNotRegistered, partner);
119             throw new ResourceException(new ResourceStatus(IResourceStatus.PARTNER_NOT_REGISTERED, message));
120         }
121
122         // namespace check, if the resource doesn't exist then return null
123
ResourceInfo info = workspace.getResourceInfo(resource.getFullPath(), true, false);
124         return (info == null) ? null : info.getSyncInfo(partner, true);
125     }
126
127     protected boolean isRegistered(QualifiedName partner) {
128         Assert.isLegal(partner != null);
129         return registry.contains(partner);
130     }
131
132     /**
133      * @see #savePartners(DataOutputStream)
134      */

135     public void readPartners(DataInputStream input) throws CoreException {
136         SyncInfoReader reader = new SyncInfoReader(workspace, this);
137         reader.readPartners(input);
138     }
139
140     public void restore(IResource resource, IProgressMonitor monitor) throws CoreException {
141         // first restore from the last save and then apply any snapshots
142
restoreFromSave(resource);
143         restoreFromSnap(resource);
144     }
145
146     protected void restoreFromSave(IResource resource) throws CoreException {
147         IPath sourceLocation = workspace.getMetaArea().getSyncInfoLocationFor(resource);
148         IPath tempLocation = workspace.getMetaArea().getBackupLocationFor(sourceLocation);
149         if (!sourceLocation.toFile().exists() && !tempLocation.toFile().exists())
150             return;
151         try {
152             DataInputStream input = new DataInputStream(new SafeFileInputStream(sourceLocation.toOSString(), tempLocation.toOSString()));
153             try {
154                 SyncInfoReader reader = new SyncInfoReader(workspace, this);
155                 reader.readSyncInfo(input);
156             } finally {
157                 input.close();
158             }
159         } catch (Exception JavaDoc e) {
160             //don't let runtime exceptions such as ArrayIndexOutOfBounds prevent startup
161
String JavaDoc msg = NLS.bind(Messages.resources_readMeta, sourceLocation);
162             throw new ResourceException(IResourceStatus.FAILED_READ_METADATA, sourceLocation, msg, e);
163         }
164     }
165
166     protected void restoreFromSnap(IResource resource) {
167         IPath sourceLocation = workspace.getMetaArea().getSyncInfoSnapshotLocationFor(resource);
168         if (!sourceLocation.toFile().exists())
169             return;
170         try {
171             DataInputStream input = new DataInputStream(new SafeChunkyInputStream(sourceLocation.toFile()));
172             try {
173                 SyncInfoSnapReader reader = new SyncInfoSnapReader(workspace, this);
174                 while (true)
175                     reader.readSyncInfo(input);
176             } catch (EOFException eof) {
177                 // ignore end of file -- proceed with what we successfully read
178
} finally {
179                 input.close();
180             }
181         } catch (Exception JavaDoc e) {
182             // only log the exception, we should not fail restoring the snapshot
183
String JavaDoc msg = NLS.bind(Messages.resources_readMeta, sourceLocation);
184             Policy.log(new ResourceStatus(IResourceStatus.FAILED_READ_METADATA, sourceLocation, msg, e));
185         }
186     }
187
188     /**
189      * @see ISynchronizer#remove(QualifiedName)
190      */

191     public void remove(QualifiedName partner) {
192         Assert.isLegal(partner != null);
193         if (isRegistered(partner)) {
194             // remove all sync info for this partner
195
try {
196                 flushSyncInfo(partner, workspace.getRoot(), IResource.DEPTH_INFINITE);
197                 registry.remove(partner);
198             } catch (CoreException e) {
199                 // XXX: flush needs to be more resilient and not throw exceptions all the time
200
Policy.log(e);
201             }
202         }
203     }
204
205     public void savePartners(DataOutputStream output) throws IOException {
206         writer.savePartners(output);
207     }
208
209     public void saveSyncInfo(ResourceInfo info, IPathRequestor requestor, DataOutputStream output, List writtenPartners) throws IOException {
210         writer.saveSyncInfo(info, requestor, output, writtenPartners);
211     }
212
213     protected void setRegistry(Set registry) {
214         this.registry = registry;
215     }
216
217     /**
218      * @see ISynchronizer#setSyncInfo(QualifiedName, IResource, byte[])
219      */

220     public void setSyncInfo(QualifiedName partner, IResource resource, byte[] info) throws CoreException {
221         Assert.isLegal(partner != null);
222         Assert.isLegal(resource != null);
223         try {
224             workspace.prepareOperation(resource, null);
225             workspace.beginOperation(true);
226             if (!isRegistered(partner)) {
227                 String JavaDoc message = NLS.bind(Messages.synchronizer_partnerNotRegistered, partner);
228                 throw new ResourceException(new ResourceStatus(IResourceStatus.PARTNER_NOT_REGISTERED, message));
229             }
230             // we do not store sync info on the workspace root
231
if (resource.getType() == IResource.ROOT)
232                 return;
233             // if the resource doesn't yet exist then create a phantom so we can set the sync info on it
234
Resource target = (Resource) resource;
235             ResourceInfo resourceInfo = workspace.getResourceInfo(target.getFullPath(), true, false);
236             int flags = target.getFlags(resourceInfo);
237             if (!target.exists(flags, false)) {
238                 if (info == null)
239                     return;
240                 //ensure it is possible to create this resource
241
target.checkValidPath(target.getFullPath(), target.getType(), false);
242                 Container parent = (Container)target.getParent();
243                 parent.checkAccessible(parent.getFlags(parent.getResourceInfo(true, false)));
244                 workspace.createResource(target, true);
245             }
246             resourceInfo = target.getResourceInfo(true, true);
247             resourceInfo.setSyncInfo(partner, info);
248             resourceInfo.incrementSyncInfoGenerationCount();
249             resourceInfo.set(ICoreConstants.M_SYNCINFO_SNAP_DIRTY);
250             flags = target.getFlags(resourceInfo);
251             if (target.isPhantom(flags) && resourceInfo.getSyncInfo(false) == null) {
252                 MultiStatus status = new MultiStatus(ResourcesPlugin.PI_RESOURCES, IResourceStatus.INTERNAL_ERROR, Messages.resources_deleteProblem, null);
253                 ((Resource) resource).deleteResource(false, status);
254                 if (!status.isOK())
255                     throw new ResourceException(status);
256             }
257         } finally {
258             workspace.endOperation(resource, false, null);
259         }
260     }
261
262     public void snapSyncInfo(ResourceInfo info, IPathRequestor requestor, DataOutputStream output) throws IOException {
263         writer.snapSyncInfo(info, requestor, output);
264     }
265 }
266
Popular Tags