KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > operations > RemoteLogOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 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.ccvs.ui.operations;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.HashMap JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.core.resources.ResourcesPlugin;
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.eclipse.core.runtime.IStatus;
20 import org.eclipse.osgi.util.NLS;
21 import org.eclipse.team.core.TeamException;
22 import org.eclipse.team.internal.ccvs.core.CVSException;
23 import org.eclipse.team.internal.ccvs.core.CVSTag;
24 import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile;
25 import org.eclipse.team.internal.ccvs.core.ICVSRemoteResource;
26 import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
27 import org.eclipse.team.internal.ccvs.core.ILogEntry;
28 import org.eclipse.team.internal.ccvs.core.client.Command;
29 import org.eclipse.team.internal.ccvs.core.client.RLog;
30 import org.eclipse.team.internal.ccvs.core.client.Session;
31 import org.eclipse.team.internal.ccvs.core.client.listeners.ILogEntryListener;
32 import org.eclipse.team.internal.ccvs.core.client.listeners.LogListener;
33 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
34 import org.eclipse.team.internal.ccvs.core.util.Util;
35 import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
36 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
37 import org.eclipse.team.internal.ccvs.ui.Policy;
38 import org.eclipse.ui.IWorkbenchPart;
39
40 /**
41  * Performs an rlog on the resources and caches the results.
42  */

43 public class RemoteLogOperation extends RepositoryLocationOperation {
44     
45     private RLog rlog = new RLog();
46     private CVSTag tag1;
47     private CVSTag tag2;
48     private LogEntryCache entryCache;
49     
50     /**
51      * A log entry cache that can be shared by multiple instances of the
52      * remote log operation.
53      */

54     public static class LogEntryCache implements ILogEntryListener {
55         
56         /*
57          * Cache of all log entries
58          */

59         private Map JavaDoc entries = new HashMap JavaDoc(); /* Map String:remoteFilePath->Map (String:revision -> ILogEntry) */
60         
61         private Map JavaDoc internalGetLogEntries(String JavaDoc path) {
62             return (Map JavaDoc)entries.get(path);
63         }
64         
65         /**
66          * Return all the log entries at the given path
67          * @param path the file path
68          * @return the log entries for the file
69          */

70         public ILogEntry[] getLogEntries(String JavaDoc path) {
71             Map JavaDoc map = internalGetLogEntries(path);
72             return (ILogEntry[]) map.values().toArray(new ILogEntry[map.values().size()]);
73         }
74         
75         private ILogEntry internalGetLogEntry(String JavaDoc path, String JavaDoc revision) {
76             Map JavaDoc fileEntries = internalGetLogEntries(path);
77             if (fileEntries != null) {
78                 return (ILogEntry)fileEntries.get(revision);
79             }
80             return null;
81         }
82         
83         public String JavaDoc[] getCachedFilePaths() {
84             return (String JavaDoc[]) entries.keySet().toArray(new String JavaDoc[entries.size()]);
85         }
86         
87         /**
88          * Return the log entry that for the given resource
89          * or <code>null</code> if no entry was fetched or the
90          * resource is not a file.
91          * @param getFullPath(resource) the resource
92          * @return the log entry or <code>null</code>
93          */

94         public synchronized ILogEntry getLogEntry(ICVSRemoteResource resource) {
95             if (resource instanceof ICVSRemoteFile) {
96                 try {
97                     String JavaDoc path = getFullPath(resource);
98                     String JavaDoc revision = ((ICVSRemoteFile)resource).getRevision();
99                     return internalGetLogEntry(path, revision);
100                 } catch (TeamException e) {
101                     // Log and return null
102
CVSUIPlugin.log(e);
103                 }
104             }
105             return null;
106         }
107
108         /**
109          * Return the log entries that were fetched for the given resource
110          * or an empty list if no entry was fetched.
111          * @param getFullPath(resource) the resource
112          * @return the fetched log entries or an empty list is none were found
113          */

114         public synchronized ILogEntry[] getLogEntries(ICVSRemoteResource resource) {
115             Map JavaDoc fileEntries = internalGetLogEntries(getFullPath(resource));
116             if (fileEntries != null) {
117                 return (ILogEntry[]) fileEntries.values().toArray(new ILogEntry[fileEntries.size()]);
118             }
119             return new ILogEntry[0];
120         }
121         
122         /*
123          * Return the full path that uniquely identifies the resource
124          * accross repositories. This path include the repository and
125          * resource path but does not include the revision so that
126          * all log entries for a file can be retrieved.
127          */

128         private String JavaDoc getFullPath(ICVSRemoteResource resource) {
129             return Util.appendPath(resource.getRepository().getLocation(false), resource.getRepositoryRelativePath());
130         }
131         
132         public synchronized void clearEntries() {
133             entries.clear();
134         }
135         
136         public synchronized ICVSRemoteFile getImmediatePredecessor(ICVSRemoteFile file) throws TeamException {
137             ILogEntry[] allLogs = getLogEntries(file);
138             String JavaDoc revision = file.getRevision();
139             // First decrement the last digit and see if that revision exists
140
String JavaDoc predecessorRevision = getPredecessorRevision(revision);
141             ICVSRemoteFile predecessor = findRevison(allLogs, predecessorRevision);
142             // If nothing was found, try to fond the base of a branch
143
if (predecessor == null && isBrancheRevision(revision)) {
144                 predecessorRevision = getBaseRevision(revision);
145                 predecessor = findRevison(allLogs, predecessorRevision);
146             }
147             // If that fails, it is still possible that there is a revision.
148
// This can happen if the revision has been manually set.
149
if (predecessor == null) {
150                 // We don't search in this case since this is costly and would be done
151
// for any file that is new as well.
152
}
153             return predecessor;
154         }
155         
156         /*
157          * Find the given revision in the list of log entries.
158          * Return null if the revision wasn't found.
159          */

160         private ICVSRemoteFile findRevison(ILogEntry[] allLogs, String JavaDoc predecessorRevision) throws TeamException {
161             for (int i = 0; i < allLogs.length; i++) {
162                 ILogEntry entry = allLogs[i];
163                 ICVSRemoteFile file = entry.getRemoteFile();
164                 if (file.getRevision().equals(predecessorRevision)) {
165                     return file;
166                 }
167             }
168             return null;
169         }
170         /*
171          * Decrement the trailing digit by one.
172          */

173         private String JavaDoc getPredecessorRevision(String JavaDoc revision) {
174             int digits[] = Util.convertToDigits(revision);
175             digits[digits.length -1]--;
176             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(revision.length());
177             for (int i = 0; i < digits.length; i++) {
178                 buffer.append(Integer.toString(digits[i]));
179                 if (i < digits.length - 1) {
180                     buffer.append('.');
181                 }
182             }
183             return buffer.toString();
184         }
185         
186         /*
187          * Return true if there are more than 2 digits in the revision number
188          * (i.e. the revision is on a branch)
189          */

190         private boolean isBrancheRevision(String JavaDoc revision) {
191             return Util.convertToDigits(revision).length > 2;
192         }
193         
194         /*
195          * Remove the trailing revision digits such that the
196          * returned revision is shorter than the given revision
197          * and is an even number of digits long
198          */

199         private String JavaDoc getBaseRevision(String JavaDoc revision) {
200             int digits[] = Util.convertToDigits(revision);
201             int length = digits.length - 1;
202             if (length % 2 == 1) {
203                 length--;
204             }
205             StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(revision.length());
206             for (int i = 0; i < length; i++) {
207                 buffer.append(Integer.toString(digits[i]));
208                 if (i < length - 1) {
209                     buffer.append('.');
210                 }
211             }
212             return buffer.toString();
213         }
214         /**
215          * Remove any entries for the remote resources
216          * @param resource the remote resource
217          */

218         public synchronized void clearEntries(ICVSRemoteResource resource) {
219             String JavaDoc remotePath = getFullPath(resource);
220             entries.remove(remotePath);
221         }
222
223         /* (non-Javadoc)
224          * @see org.eclipse.team.internal.ccvs.core.client.listeners.ILogEntryListener#addEntry(org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry)
225          */

226         public void handleLogEntryReceived(ILogEntry entry) {
227             ICVSRemoteFile file = entry.getRemoteFile();
228             String JavaDoc fullPath = getFullPath(file);
229             String JavaDoc revision = entry.getRevision();
230             Map JavaDoc fileEntries = internalGetLogEntries(fullPath);
231             if (fileEntries == null) {
232                 fileEntries = new HashMap JavaDoc();
233                 entries.put(fullPath, fileEntries);
234             }
235             fileEntries.put(revision, entry);
236         }
237     }
238     
239     public RemoteLogOperation(IWorkbenchPart part, ICVSRemoteResource[] remoteResources, CVSTag tag1, CVSTag tag2, LogEntryCache cache) {
240         super(part, remoteResources);
241         this.tag1 = tag1;
242         this.tag2 = tag2;
243         this.entryCache = cache;
244     }
245
246     /* (non-Javadoc)
247      * @see org.eclipse.team.internal.ccvs.ui.operations.RepositoryLocationOperation#execute(org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation, org.eclipse.team.internal.ccvs.core.ICVSRemoteResource[], org.eclipse.core.runtime.IProgressMonitor)
248      */

249     protected void execute(ICVSRepositoryLocation location, ICVSRemoteResource[] remoteResources, IProgressMonitor monitor) throws CVSException {
250         monitor.beginTask(NLS.bind(CVSUIMessages.RemoteLogOperation_0, new String JavaDoc[] { location.getHost() }), 100);
251         Session s = new Session(location, CVSWorkspaceRoot.getCVSFolderFor(ResourcesPlugin.getWorkspace().getRoot()), false /* do not output to console */);
252         // Create a log listener that will update the cache as entries are received
253
LogListener listener = new LogListener(entryCache);
254         
255         ICVSRemoteResource[] remotes = remoteResources;
256         Command.LocalOption[] localOptions = getLocalOptions(tag1, tag2);
257         if(tag1 == null || tag2 == null) {
258             // Optimize the cases were we are only fetching the history for a single revision. If it is
259
// already cached, don't fetch it again.
260
ArrayList JavaDoc unCachedRemotes = new ArrayList JavaDoc();
261             for (int i = 0; i < remoteResources.length; i++) {
262                 ICVSRemoteResource r = remoteResources[i];
263                 if(entryCache.getLogEntry(r) == null) {
264                     unCachedRemotes.add(r);
265                 }
266             }
267             remotes = (ICVSRemoteResource[]) unCachedRemotes.toArray(new ICVSRemoteResource[unCachedRemotes.size()]);
268         }
269         if (remotes.length > 0) {
270             try {
271                 s.open(Policy.subMonitorFor(monitor, 10));
272                 IStatus status = rlog.execute(s, Command.NO_GLOBAL_OPTIONS, localOptions, remotes, listener, Policy.subMonitorFor(monitor, 90));
273                 collectStatus(status);
274             } finally {
275                 s.close();
276             }
277         }
278     }
279
280     /* (non-Javadoc)
281      * @see org.eclipse.team.internal.ccvs.ui.operations.CVSOperation#getTaskName()
282      */

283     protected String JavaDoc getTaskName() {
284         return CVSUIMessages.RemoteLogOperation_1;
285     }
286     
287     protected Command.LocalOption[] getLocalOptions(CVSTag tag1, CVSTag tag2) {
288         if(tag1 != null && tag2 != null) {
289             return new Command.LocalOption[] {RLog.NO_TAGS, RLog.ONLY_INCLUDE_CHANGES, RLog.makeTagOption(tag1, tag2)};
290         }
291         else if (tag1 != null){
292             if (tag1.getType() == CVSTag.HEAD ||
293                 tag1.getType() == CVSTag.VERSION)
294                 return new Command.LocalOption[] {RLog.NO_TAGS, RLog.ONLY_INCLUDE_CHANGES, RLog.getCurrentTag(tag1)};
295             
296             if (tag1.getType() == CVSTag.DATE)
297                 return new Command.LocalOption[] {RLog.NO_TAGS, RLog.ONLY_INCLUDE_CHANGES, RLog.REVISIONS_ON_DEFAULT_BRANCH, RLog.getCurrentTag(tag1)};
298             //branch tag
299
return new Command.LocalOption[] {RLog.getCurrentTag(tag1)};
300         }
301         else {
302             return new Command.LocalOption[] {RLog.NO_TAGS, RLog.ONLY_INCLUDE_CHANGES};
303         }
304     }
305 }
306
Popular Tags