KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > core > util > Util


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.util;
12
13
14 import java.io.IOException JavaDoc;
15 import java.io.InterruptedIOException JavaDoc;
16 import java.net.Socket JavaDoc;
17 import java.net.UnknownHostException JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.List JavaDoc;
20
21 import org.eclipse.core.resources.*;
22 import org.eclipse.core.runtime.*;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.team.internal.ccvs.core.*;
25 import org.eclipse.team.internal.ccvs.core.client.Session;
26 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
27 import org.eclipse.team.internal.ccvs.core.syncinfo.FolderSyncInfo;
28 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
29
30 /**
31  * Unsorted static helper-methods
32  */

33 public class Util {
34     
35     /**
36      * Return the last segment of the given path
37      * @param path
38      * @return String
39      */

40     public static String JavaDoc getLastSegment(String JavaDoc path) {
41         int index = path.lastIndexOf(Session.SERVER_SEPARATOR);
42         if (index == -1) {
43             return path;
44         }
45         if (index == path.length() - 1) {
46             return getLastSegment(path.substring(0, index));
47         }
48         return path.substring(index + 1);
49         
50     }
51     
52     /**
53      * Return the the given path with the last segment removed
54      * @param path
55      * @return String
56      */

57     public static String JavaDoc removeLastSegment(String JavaDoc path) {
58         int index = path.lastIndexOf(Session.SERVER_SEPARATOR);
59         if (index == -1)
60             return ""; //$NON-NLS-1$
61
else
62             return path.substring(0, index);
63
64     }
65     /**
66      * Return the path without a trailing /
67      * @param path
68      * @return String
69      */

70     public static String JavaDoc asPath(String JavaDoc path) {
71         if (path.endsWith(Session.SERVER_SEPARATOR)) {
72             return path.substring(0, path.length() - Session.SERVER_SEPARATOR.length());
73         }
74         return path;
75     }
76     /*
77      * *
78      * Get the extention of the path of resource
79      * relative to the path of root
80      *
81      * @throws CVSException if root is not a root-folder of resource
82      */

83     public static String JavaDoc getRelativePath(String JavaDoc rootName, String JavaDoc resourceName)
84         throws CVSException {
85
86         if (!resourceName.startsWith(rootName) || rootName.length() > resourceName.length()) {
87             throw new CVSException(CVSMessages.Util_Internal_error__resource_does_not_start_with_root_3);
88         }
89         
90         // Otherwise we would get an ArrayOutOfBoundException
91
// in case of two equal Resources
92
if (rootName.length() == resourceName.length()) {
93             return ""; //$NON-NLS-1$
94
}
95         
96         // Remove leading slash if there is one
97
String JavaDoc result = resourceName.substring(rootName.length());
98         if (result.startsWith("/")) { //$NON-NLS-1$
99
result = result.substring(1);
100         }
101         return result;
102     }
103     
104     /**
105      * Append the prefix and suffix to form a valid CVS path.
106      */

107     public static String JavaDoc appendPath(String JavaDoc prefix, String JavaDoc suffix) {
108         if (prefix.length() == 0 || prefix.equals(Session.CURRENT_LOCAL_FOLDER)) {
109             return suffix;
110         } else if (prefix.endsWith(Session.SERVER_SEPARATOR)) {
111             if (suffix.startsWith(Session.SERVER_SEPARATOR))
112                 return prefix + suffix.substring(1);
113             else
114                 return prefix + suffix;
115         } else if (suffix.startsWith(Session.SERVER_SEPARATOR))
116             return prefix + suffix;
117         else
118             return prefix + Session.SERVER_SEPARATOR + suffix;
119     }
120
121     public static void logError(String JavaDoc message, Throwable JavaDoc throwable) {
122         CVSProviderPlugin.log(IStatus.ERROR, message, throwable);
123     }
124
125     /**
126      * If the number of segments in the relative path of <code>resource</code> to <code>root</code> is
127      * greater than <code>split</code> then the returned path is truncated to <code>split</code> number
128      * of segments and '...' is shown as the first segment of the path.
129      */

130     public static String JavaDoc toTruncatedPath(ICVSResource resource, ICVSFolder root, int split) {
131         try {
132             String JavaDoc stringPath = resource.getRelativePath(root);
133             if (stringPath.equals(Session.CURRENT_LOCAL_FOLDER)) {
134                 return resource.getName();
135             }
136             String JavaDoc truncatedPath = toTruncatedPath(stringPath, split);
137             return truncatedPath;
138         } catch(CVSException e) {
139             return resource.getName();
140         }
141     }
142
143     public static String JavaDoc toTruncatedPath(String JavaDoc stringPath, int split) {
144         // Search backwards until split separators are found
145
int count = 0;
146         int index = stringPath.length();
147         while (count++ < split && index != -1) {
148             index = stringPath.lastIndexOf(Session.SERVER_SEPARATOR, index - 1);
149         }
150         if (index == -1) {
151             return stringPath;
152         } else {
153             return NLS.bind(CVSMessages.Util_truncatedPath, new String JavaDoc[] { stringPath.substring(index) });
154         }
155     }
156     
157     /**
158      * Helper method that will time out when making a socket connection.
159      * This is required because there is no way to provide a timeout value
160      * when creating a socket and in some instances, they don't seem to
161      * timeout at all.
162      */

163     public static Socket JavaDoc createSocket(final String JavaDoc host, final int port, IProgressMonitor monitor) throws UnknownHostException JavaDoc, IOException JavaDoc {
164         int timeout = CVSProviderPlugin.getPlugin().getTimeout();
165         if (timeout == 0) timeout = CVSProviderPlugin.DEFAULT_TIMEOUT;
166         ResponsiveSocketFactory factory = new ResponsiveSocketFactory(monitor, timeout);
167         return factory.createSocket(host, port);
168     }
169     
170     /**
171      * Helper method that will time out when running an external command.
172      * This is required because there is no way to provide a timeout value
173      * when executing an external command and in some instances, they don't seem to
174      * timeout at all.
175      */

176     public static Process JavaDoc createProcess(final String JavaDoc[] command, IProgressMonitor monitor) throws IOException JavaDoc {
177         
178         // Start a thread to execute the command and get a handle to the process
179
final Process JavaDoc[] process = new Process JavaDoc[] { null };
180         final Exception JavaDoc[] exception = new Exception JavaDoc[] {null };
181         final Thread JavaDoc thread = new Thread JavaDoc(new Runnable JavaDoc() {
182             public void run() {
183                 try {
184                     Process JavaDoc newProcess = Runtime.getRuntime().exec(command);
185                     synchronized (process) {
186                         if (Thread.interrupted()) {
187                             // we we're either cancelled or timed out so just destroy the process
188
newProcess.destroy();
189                         } else {
190                             process[0] = newProcess;
191                         }
192                     }
193                 } catch (IOException JavaDoc e) {
194                     exception[0] = e;
195                 }
196             }
197         });
198         thread.start();
199         
200         // Wait the appropriate number of seconds
201
int timeout = CVSProviderPlugin.getPlugin().getTimeout();
202         if (timeout == 0) timeout = CVSProviderPlugin.DEFAULT_TIMEOUT;
203         for (int i = 0; i < timeout; i++) {
204             try {
205                 // wait for the thread to complete or 1 second, which ever comes first
206
thread.join(1000);
207             } catch (InterruptedException JavaDoc e) {
208                 // I think this means the thread was interupted but not necessarily timed out
209
// so we don't need to do anything
210
}
211             synchronized (process) {
212                 // if the user cancelled, clean up before preempting the operation
213
if (monitor.isCanceled()) {
214                     if (thread.isAlive()) {
215                         thread.interrupt();
216                     }
217                     if (process[0] != null) {
218                         process[0].destroy();
219                     }
220                     // this method will throw the proper exception
221
Policy.checkCanceled(monitor);
222                 }
223             }
224         }
225         // If the thread is still running (i.e. we timed out) signal that it is too late
226
synchronized (process) {
227             if (thread.isAlive()) {
228                 thread.interrupt();
229             }
230         }
231         if (exception[0] != null) {
232             throw (IOException JavaDoc)exception[0];
233         }
234         if (process[0] == null) {
235             throw new InterruptedIOException JavaDoc(NLS.bind(CVSMessages.Util_processTimeout, new String JavaDoc[] { command[0] }));
236         }
237         return process[0];
238     }
239     
240     public static String JavaDoc[] parseIntoSubstrings(String JavaDoc string, String JavaDoc delimiter) {
241         List JavaDoc result = new ArrayList JavaDoc();
242         int start = 0;
243         int index = string.indexOf(delimiter);
244         String JavaDoc next;
245         while (index != -1) {
246             next = string.substring(start, index);
247             result.add(next);
248             start = index + 1;
249             index = string.indexOf(delimiter, start);
250         }
251         if (start >= string.length()) {
252             next = "";//$NON-NLS-1$
253
} else {
254             next = string.substring(start);
255         }
256         result.add(next);
257         return (String JavaDoc[]) result.toArray(new String JavaDoc[result.size()]);
258     }
259     
260     /**
261      * Return the substring at the given index (starting at 0) where each
262      * element is delimited by the provided delimiter.
263      *
264      * @param bytes
265      * @param delimiter
266      * @param index
267      * @param includeRest
268      * @return String
269      */

270     public static String JavaDoc getSubstring(byte[] bytes, byte delimiter, int index, boolean includeRest) {
271         byte[] bytesForSlot = getBytesForSlot(bytes, delimiter, index, includeRest);
272         if (bytesForSlot == null) {
273             return null;
274         }
275         return new String JavaDoc(bytesForSlot);
276     }
277     
278     /**
279      * Return the offset the the Nth delimeter from the given start index.
280      * @param bytes
281      * @param delimiter
282      * @param start
283      * @param n
284      * @return int
285      */

286     public static int getOffsetOfDelimeter(byte[] bytes, byte delimiter, int start, int n) {
287         int count = 0;
288         for (int i = start; i < bytes.length; i++) {
289             if (bytes[i] == delimiter) count++;
290             if (count == n) return i;
291         }
292         // the Nth delimeter was not found
293
return -1;
294     }
295     
296     /**
297      * Method getBytesForSlot.
298      * @param syncBytes
299      * @param SEPARATOR_BYTE
300      * @param i
301      * @param b
302      * @return byte[]
303      */

304     public static byte[] getBytesForSlot(byte[] bytes, byte delimiter, int index, boolean includeRest) {
305         // Find the starting index
306
int start;
307         if (index == 0) {
308             // make start -1 so that end determination will start at offset 0.
309
start = -1;
310         } else {
311             start = getOffsetOfDelimeter(bytes, delimiter, 0, index);
312             if (start == -1) return null;
313         }
314         // Find the ending index
315
int end = getOffsetOfDelimeter(bytes, delimiter, start + 1, 1);
316         // Calculate the length
317
int length;
318         if (end == -1 || includeRest) {
319             length = bytes.length - start - 1;
320         } else {
321             length = end - start - 1;
322         }
323         byte[] result = new byte[length];
324         System.arraycopy(bytes, start + 1, result, 0, length);
325         return result;
326     }
327     
328     /**
329      * Method equals.
330      * @param syncBytes
331      * @param oldBytes
332      * @return boolean
333      */

334     public static boolean equals(byte[] syncBytes, byte[] oldBytes) {
335         if (syncBytes == null || oldBytes == null) return syncBytes == oldBytes;
336         if (syncBytes.length != oldBytes.length) return false;
337         for (int i = 0; i < oldBytes.length; i++) {
338             if (oldBytes[i] != syncBytes[i]) return false;
339         }
340         return true;
341     }
342     
343     /**
344      * Workaround a CVS bug where a CVS Folder with no immediately contained files has an incorrect
345      * Tag type stored in the TAG file. In this case, the tag type is always BRANCH (Tv1)
346      *
347      * The fix is for folders with no files, use the tag type for the containing project. Since projects almost
348      * always have files the TAG file is usually correct.
349      *
350      * For the case where the folder tag name does not match the project tag name we can not do much so we just
351      * return the folder tag which will currently always be a branch.
352      *
353      * @param resource The IResource being tested. Can not be null.
354      * @param tag The CVSTag as reported by CVS for the IResource. May be null.
355      * @return CVSTag The corrected tag for the resource. May be null.
356      */

357     
358     public static CVSTag getAccurateFolderTag(IResource resource, CVSTag tag) {
359
360         // Determine if the folder contains files as immediate children.
361
if (resource.getType() != IResource.FOLDER) {
362             return tag;
363         }
364
365         IResource[] members = null;
366         try {
367             members = ((IFolder) resource).members();
368         } catch (CoreException e1) {
369             return tag;
370         }
371         
372         for (int i = 0; i < members.length; i++) {
373             if (members[i].getType() == IResource.FILE) {
374                 return tag;
375             }
376         }
377     
378         // Folder contains no files so this may not really be a branch.
379
// Make the type the same as the project tag type if both are the same tag name.
380
IProject project = resource.getProject();
381         if (project == null) {
382             return tag;
383         }
384         
385         ICVSFolder projectFolder = CVSWorkspaceRoot.getCVSFolderFor(project);
386         FolderSyncInfo projectSyncInfo;
387         try {
388             projectSyncInfo = projectFolder.getFolderSyncInfo();
389         } catch (CVSException e) {
390             return tag;
391         }
392         
393         if (projectSyncInfo == null) {
394             return tag;
395         }
396         
397         CVSTag projectTag = projectSyncInfo.getTag();
398                                 
399         if (projectTag != null && projectTag.getName().equals(tag.getName())) {
400             return projectTag;
401         } else {
402             return tag;
403         }
404     }
405     
406     /**
407      * Workaround for CVS "bug" where CVS ENTRIES file does not contain correct
408      * Branch vs. Version info. Entries files always record a Tv1 so all entries would
409      * appear as branches.
410      *
411      * By comparing the revision number to the tag name
412      * you can determine if the tag is a branch or version.
413      *
414      * @param cvsResource the resource to test. Must nut be null.
415      * @return the correct cVSTag. May be null.
416      */

417     
418     public static CVSTag getAccurateFileTag(ICVSResource cvsResource) throws CVSException {
419
420         CVSTag tag = null;
421         ResourceSyncInfo info = cvsResource.getSyncInfo();
422         if(info != null) {
423             tag = info.getTag();
424         }
425
426         FolderSyncInfo parentInfo = cvsResource.getParent().getFolderSyncInfo();
427         CVSTag parentTag = null;
428         if(parentInfo != null) {
429             parentTag = parentInfo.getTag();
430         }
431
432         if(tag != null) {
433             if(tag.getName().equals(info.getRevision())) {
434                 tag = new CVSTag(tag.getName(), CVSTag.VERSION);
435             } else if(parentTag != null){
436                 tag = new CVSTag(tag.getName(), parentTag.getType());
437             }
438         }
439         
440         return tag;
441     }
442
443     /**
444      * Return the fullest path that we can obtain for the given resource
445      * @param resource
446      * @return
447      */

448     public static String JavaDoc getFullestPath(ICVSResource resource) {
449         IResource local = resource.getIResource();
450         if (local != null) {
451             return local.getFullPath().toString();
452         }
453         try {
454             String JavaDoc remotePath = resource.getRepositoryRelativePath();
455             if (remotePath != null) {
456                 return remotePath;
457             }
458         } catch (CVSException e) {
459             // Ignore and try the next method;
460
}
461         return resource.getName();
462     }
463     
464     public static String JavaDoc getVariablePattern(String JavaDoc pattern, String JavaDoc variableName) {
465         return "(" + variableName + ":" + pattern + ":" + variableName + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
466
}
467
468     /**
469      * @param localRevision
470      * @return
471      */

472     public static int[] convertToDigits(String JavaDoc localRevision) {
473         try {
474             String JavaDoc digitStrings[] = localRevision.split("\\."); //$NON-NLS-1$
475
int[] digits = new int[digitStrings.length];
476             for (int i = 0; i < digitStrings.length; i++) {
477                 String JavaDoc digitString = digitStrings[i];
478                 digits[i] = Integer.parseInt(digitString);
479             }
480             return digits;
481         } catch (NumberFormatException JavaDoc e) {
482             CVSProviderPlugin.log(CVSException.wrapException(e));
483             return new int[0];
484         }
485     }
486
487     public static String JavaDoc toTruncatedPath(ICVSStorage file, ICVSFolder localRoot, int i) {
488         if (file instanceof ICVSResource) {
489             return toTruncatedPath((ICVSResource)file, localRoot, i);
490         }
491         return file.getName();
492     }
493     
494     /**
495      * If the status/log returns that the file is in the Attic, then remove the
496      * Attic segment. This is because files added to a branch that are not in
497      * the main trunk (HEAD) are added to the Attic but cvs does magic on
498      * update to put them in the correct location.
499      * (e.g. /project/Attic/file.txt -> /project/file.txt)
500      */

501     public static String JavaDoc removeAtticSegment(String JavaDoc path) {
502         int lastSeparator = path.lastIndexOf(Session.SERVER_SEPARATOR);
503         if (lastSeparator == -1) return path;
504         int secondLastSeparator = path.lastIndexOf(Session.SERVER_SEPARATOR, lastSeparator - 1);
505         if (secondLastSeparator == -1) return path;
506         String JavaDoc secondLastSegment = path.substring(secondLastSeparator + 1, lastSeparator);
507         if (secondLastSegment.equals("Attic")) { //$NON-NLS-1$
508
return path.substring(0, secondLastSeparator) + path.substring(lastSeparator);
509         }
510         return path;
511     }
512     
513     /**
514      * Flatten the text in the multiline comment
515      */

516     public static String JavaDoc flattenText(String JavaDoc string) {
517         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(string.length() + 20);
518         boolean skipAdjacentLineSeparator = true;
519         for (int i = 0; i < string.length(); i++) {
520             char c = string.charAt(i);
521             if (c == '\r' || c == '\n') {
522                 if (!skipAdjacentLineSeparator)
523                     buffer.append(Session.SERVER_SEPARATOR);
524                 skipAdjacentLineSeparator = true;
525             } else {
526                 buffer.append(c);
527                 skipAdjacentLineSeparator = false;
528             }
529         }
530         return buffer.toString();
531     }
532 }
533
Popular Tags