KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > client > listeners > UpdateListener


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.ccvs.core.client.listeners;
12
13 import java.util.Map JavaDoc;
14
15 import org.eclipse.core.resources.IResource;
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.osgi.util.NLS;
19 import org.eclipse.team.internal.ccvs.core.*;
20 import org.eclipse.team.internal.ccvs.core.CVSException;
21 import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin;
22 import org.eclipse.team.internal.ccvs.core.CVSStatus;
23 import org.eclipse.team.internal.ccvs.core.ICVSFile;
24 import org.eclipse.team.internal.ccvs.core.ICVSFolder;
25 import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
26 import org.eclipse.team.internal.ccvs.core.client.CommandOutputListener;
27 import org.eclipse.team.internal.ccvs.core.client.Update;
28 import org.eclipse.team.internal.ccvs.core.util.Util;
29
30 public class UpdateListener extends CommandOutputListener {
31
32     // Pattern matchers
33
private static ServerMessageLineMatcher MERGED_BINARY_FILE_LINE_1;
34     private static ServerMessageLineMatcher MERGED_BINARY_FILE_LINE_2;
35     
36     // Pattern Variables
37
private static final String JavaDoc REVISION_VARIABLE_NAME = "revision"; //$NON-NLS-1$
38
private static final String JavaDoc LOCAL_FILE_PATH_VARIABLE_NAME = "localFilePath"; //$NON-NLS-1$
39
private static final String JavaDoc BACKUP_FILE_VARIABLE_NAME = "backupFile"; //$NON-NLS-1$
40

41     static {
42         try {
43             String JavaDoc line1 = "revision " //$NON-NLS-1$
44
+ Util.getVariablePattern(IMessagePatterns.REVISION_PATTERN, REVISION_VARIABLE_NAME)
45                 + " from repository is now in " //$NON-NLS-1$
46
+ Util.getVariablePattern(IMessagePatterns.FILE_PATH_PATTERN, LOCAL_FILE_PATH_VARIABLE_NAME);
47             MERGED_BINARY_FILE_LINE_1 = new ServerMessageLineMatcher(
48                     line1,
49                     new String JavaDoc[] {REVISION_VARIABLE_NAME, LOCAL_FILE_PATH_VARIABLE_NAME});
50             String JavaDoc line2 = "file from working directory is now in " //$NON-NLS-1$
51
+ Util.getVariablePattern(IMessagePatterns.REVISION_PATTERN, BACKUP_FILE_VARIABLE_NAME);
52             MERGED_BINARY_FILE_LINE_2 = new ServerMessageLineMatcher(
53                     line2,
54                     new String JavaDoc[] {BACKUP_FILE_VARIABLE_NAME});
55
56         } catch (CVSException e) {
57             // Shouldn't happen
58
CVSProviderPlugin.log(e);
59         }
60     }
61     
62     IUpdateMessageListener updateMessageListener;
63     boolean merging = false;
64     boolean mergingBinary = false;
65     String JavaDoc mergedBinaryFileRevision, mergedBinaryFilePath;
66
67     public UpdateListener(IUpdateMessageListener updateMessageListener) {
68         this.updateMessageListener = updateMessageListener;
69     }
70     
71     public IStatus messageLine(String JavaDoc line, ICVSRepositoryLocation location, ICVSFolder commandRoot,
72         IProgressMonitor monitor) {
73         mergingBinary = false;
74         if (updateMessageListener == null) return OK;
75         if(line.startsWith("Merging differences")) { //$NON-NLS-1$
76
merging = true;
77         } else if(line.indexOf(' ')==1) {
78             // We have a message that indicates the type of update. The possible messages are
79
// defined by the prefix constants MLP_*.
80
String JavaDoc path = line.substring(2);
81             char changeType = line.charAt(0);
82             
83             // calculate change type
84
int type = 0;
85             switch(changeType) {
86                 case 'A': type = Update.STATE_ADDED_LOCAL; break; // new file locally that was added but not comitted to server yet
87
case '?': type = Update.STATE_UNKOWN; break; // new file locally but not added to server
88
case 'U': type = Update.STATE_REMOTE_CHANGES; break; // remote changes to an unmodified local file
89
case 'R': type = Update.STATE_DELETED; break; // removed locally but still exists on the server
90
case 'M': type = Update.STATE_MODIFIED; break; // modified locally
91
case 'C': type = Update.STATE_CONFLICT; break; // modified locally and on the server but cannot be auto-merged
92
case 'D': type = Update.STATE_DELETED; break; // deleted locally but still exists on server
93
default: type = Update.STATE_NONE;
94             }
95                 
96             if (merging) {
97                 // If we are merging the modified prefix is used both to show merges and
98
// local changes. We have to detect this case and use a more specific change
99
// type.
100
if (type == Update.STATE_MODIFIED)
101                     type = Update.STATE_MERGEABLE_CONFLICT;
102                 merging = false;
103             }
104             updateMessageListener.fileInformation(type, commandRoot, path);
105         }
106         return OK;
107     }
108
109     /**
110      * This handler is used by the RemoteResource hierarchy to retrieve E messages
111      * from the CVS server in order to determine the folders contained in a parent folder.
112      *
113      * WARNING: This class parses the message output to determine the state of files in the
114      * repository. Unfortunately, these messages seem to be customizable on a server by server basis.
115      *
116      * Here's a list of responses we expect in various situations:
117      *
118      * Directory exists remotely:
119      * cvs server: Updating folder1/folder2
120      * Directory doesn't exist remotely:
121      * cvs server: skipping directory folder1/folder2
122      * New (or unknown) remote directory
123      * cvs server: New Directory folder1/folder2
124      * File removed remotely
125      * cvs server: folder1/file.ext is no longer in the repository
126      * cvs server: warning: folder1/file.ext is not (any longer) pertinent
127      * Locally added file was added remotely as well
128      * cvs server: conflict: folder/file.ext created independently by second party
129      * File removed locally and modified remotely
130      * cvs server: conflict: removed file.txt was modified by second party
131      * File modified locally but removed remotely
132      * cvs server: conflict: file.txt is modified but no longer in the repository
133      * Ignored Messages
134      * cvs server: cannot open directory ...
135      * cvs server: nothing known about ...
136      * Tag error that really means there are no files in a directory
137      * cvs [server aborted]: no such tag
138      * Merge contained conflicts
139      * rcsmerge: warning: conflicts during merge
140      * Binary file conflict
141      * cvs server: nonmergeable file needs merge
142      * cvs server: revision 1.4 from repository is now in a1/a2/test
143      * cvs server: file from working directory is now in .#test.1.3
144      */

145     public IStatus errorLine(String JavaDoc line, ICVSRepositoryLocation location, ICVSFolder commandRoot,
146         IProgressMonitor monitor) {
147         
148         try {
149             // Reset flag globally here because we have to many exit points
150
boolean wasMergingBinary = mergingBinary;
151             mergingBinary = false;
152             String JavaDoc serverMessage = getServerMessage(line, location);
153             if (serverMessage != null) {
154                 // Strip the prefix from the line
155
String JavaDoc message = serverMessage;
156                 if (message.startsWith("Updating")) { //$NON-NLS-1$
157
if (updateMessageListener != null) {
158                         String JavaDoc path = message.substring(9);
159                         updateMessageListener.directoryInformation(commandRoot, path, false);
160                     }
161                     return OK;
162                 } else if (message.startsWith("skipping directory")) { //$NON-NLS-1$
163
if (updateMessageListener != null) {
164                         String JavaDoc path = message.substring(18).trim();
165                         updateMessageListener.directoryDoesNotExist(commandRoot, path);
166                     }
167                     return OK;
168                 } else if (message.startsWith("New directory")) { //$NON-NLS-1$
169
if (updateMessageListener != null) {
170                         String JavaDoc path = message.substring(15, message.lastIndexOf('\''));
171                         updateMessageListener.directoryInformation(commandRoot, path, true);
172                     }
173                     return OK;
174                 } else if (message.endsWith("is no longer in the repository")) { //$NON-NLS-1$
175
if (updateMessageListener != null) {
176                         String JavaDoc filename = message.substring(0, message.length() - 31);
177                         filename = stripQuotes(filename);
178                         updateMessageListener.fileDoesNotExist(commandRoot, filename);
179                     }
180                     return OK;
181                 } else if (message.startsWith("conflict:")) { //$NON-NLS-1$
182
/*
183                      * We can get the following conflict warnings
184                      * cvs server: conflict: folder/file.ext created independently by second party
185                      * cvs server: conflict: removed file.txt was modified by second party
186                      * cvs server: conflict: file.txt is modified but no longer in the repository
187                      * If we get the above line, we have conflicting additions or deletions and we can expect a server error.
188                      * We still get "C foler/file.ext" so we don't need to do anything else (except in the remotely deleted case)
189                      */

190                     if (updateMessageListener != null) {
191                         if (message.endsWith("is modified but no longer in the repository")) { //$NON-NLS-1$
192
// The "C foler/file.ext" will come after this so if whould be ignored!
193
String JavaDoc filename = message.substring(10, message.length() - 44);
194                             filename = stripQuotes(filename);
195                             updateMessageListener.fileDoesNotExist(commandRoot, filename);
196                         }
197                     }
198                     return new CVSStatus(IStatus.WARNING, CVSStatus.CONFLICT, line, commandRoot);
199                 } else if (message.startsWith("warning:")) { //$NON-NLS-1$
200
/*
201                      * We can get the following conflict warnings
202                      * cvs server: warning: folder1/file.ext is not (any longer) pertinent
203                      * If we get the above line, we have local changes to a remotely deleted file.
204                      */

205                     if (updateMessageListener != null) {
206                         if (message.endsWith("is not (any longer) pertinent")) { //$NON-NLS-1$
207
String JavaDoc filename = message.substring(9, message.length() - 30);
208                             updateMessageListener.fileDoesNotExist(commandRoot, filename);
209                         }
210                     }
211                     return new CVSStatus(IStatus.WARNING, CVSStatus.CONFLICT, line, commandRoot);
212                 } else if (message.startsWith("conflicts")) { //$NON-NLS-1$
213
// This line is info only. The server doesn't report an error.
214
return new CVSStatus(IStatus.INFO, CVSStatus.CONFLICT, line, commandRoot);
215                 } else if (message.startsWith("nonmergeable file needs merge")) { //$NON-NLS-1$
216
mergingBinary = true;
217                     mergedBinaryFileRevision = null;
218                     mergedBinaryFilePath = null;
219                     return OK;
220                 } else if (wasMergingBinary) {
221                     Map JavaDoc variables = MERGED_BINARY_FILE_LINE_1.processServerMessage(message);
222                     if (variables != null) {
223                         mergedBinaryFileRevision = (String JavaDoc)variables.get(REVISION_VARIABLE_NAME);
224                         mergedBinaryFilePath = (String JavaDoc)variables.get(LOCAL_FILE_PATH_VARIABLE_NAME);
225                         mergingBinary = true;
226                         return OK;
227                     }
228                     variables = MERGED_BINARY_FILE_LINE_2.processServerMessage(message);
229                     if (variables != null) {
230                         String JavaDoc backupFile = (String JavaDoc)variables.get(BACKUP_FILE_VARIABLE_NAME);
231                         try {
232                             if (mergedBinaryFileRevision != null && mergedBinaryFilePath != null) {
233                                 ICVSFile file = commandRoot.getFile(mergedBinaryFilePath);
234                                 IResource resource = file.getIResource();
235                                 if (resource != null) {
236                                     return new CVSStatus(IStatus.ERROR, CVSStatus.UNMEGERED_BINARY_CONFLICT,
237                                         NLS.bind(CVSMessages.UpdateListener_0, (new Object JavaDoc[] {
238                                         resource.getFullPath().toString(),
239                                         mergedBinaryFileRevision,
240                                         resource.getFullPath().removeLastSegments(1).append(backupFile).toString()})), commandRoot);
241                                 }
242                             }
243                         } catch (CVSException e1) {
244                             CVSProviderPlugin.log(e1);
245                         }
246                         return OK;
247                     }
248                 }
249                 
250                 // Fallthrough case for "cvs server" messages
251
if (!message.startsWith("cannot open directory") //$NON-NLS-1$
252
&& !message.startsWith("nothing known about")) { //$NON-NLS-1$
253
return super.errorLine(line, location, commandRoot, monitor);
254                 }
255             } else {
256                 String JavaDoc serverAbortedMessage = getServerAbortedMessage(line, location);
257                 if (serverAbortedMessage != null) {
258                     // Strip the prefix from the line
259
String JavaDoc message = serverAbortedMessage;
260                     if (message.startsWith("no such tag")) { //$NON-NLS-1$
261
// This is reported from CVS when a tag is used on the update there are no files in the directory
262
// To get the folders, the update request should be re-issued for HEAD
263
return new CVSStatus(IStatus.WARNING, CVSStatus.NO_SUCH_TAG, line, commandRoot);
264                     } else if (message.startsWith("Numeric join") && message.endsWith("may not contain a date specifier")) { //$NON-NLS-1$ //$NON-NLS-2$
265
// This error indicates a join failed because a date tag was used
266
return super.errorLine(line, location, commandRoot, monitor);
267                     } else {
268                         return super.errorLine(line, location, commandRoot, monitor);
269                     }
270                 } else if (line.equals("rcsmerge: warning: conflicts during merge")) { //$NON-NLS-1$
271
// There were conflicts in the merge
272
return new CVSStatus(IStatus.WARNING, CVSStatus.CONFLICT, line, commandRoot);
273                 }
274             }
275         } catch (StringIndexOutOfBoundsException JavaDoc e) {
276             // Something went wrong in the parsing of the message.
277
// Return a status indicating the problem
278
if (CVSProviderPlugin.getPlugin().isDebugging()) {
279                 System.out.println("Error parsing E line: " + line); //$NON-NLS-1$
280
}
281             return new CVSStatus(IStatus.ERROR, CVSStatus.ERROR_LINE_PARSE_FAILURE, line, commandRoot);
282         }
283         return super.errorLine(line, location, commandRoot, monitor);
284     }
285
286     private String JavaDoc stripQuotes(String JavaDoc filename) {
287         // CVS version 12 fix - filenames are returned inside quotes
288
// Fixes bug 49056
289
if (filename.startsWith("`") && filename.endsWith("'")) //$NON-NLS-1$ //$NON-NLS-2$
290
filename = filename.substring(1,filename.length()-1);
291         return filename;
292     }
293
294 }
295
Popular Tags