KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > Project


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2003-2005 University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */

19
20 /*
21  * Project.java
22  *
23  * Created on March 30, 2003, 2:22 PM
24  */

25
26 package edu.umd.cs.findbugs;
27
28 import java.io.BufferedReader JavaDoc;
29 import java.io.BufferedWriter JavaDoc;
30 import java.io.File JavaDoc;
31 import java.io.FileReader JavaDoc;
32 import java.io.FileWriter JavaDoc;
33 import java.io.IOException JavaDoc;
34 import java.io.InputStream JavaDoc;
35 import java.io.PrintWriter JavaDoc;
36 import java.net.MalformedURLException JavaDoc;
37 import java.net.URL JavaDoc;
38 import java.util.HashMap JavaDoc;
39 import java.util.HashSet JavaDoc;
40 import java.util.LinkedList JavaDoc;
41 import java.util.List JavaDoc;
42 import java.util.Map JavaDoc;
43 import java.util.jar.Attributes JavaDoc;
44 import java.util.jar.Manifest JavaDoc;
45
46 import edu.umd.cs.findbugs.ba.URLClassPath;
47 import edu.umd.cs.findbugs.xml.XMLAttributeList;
48 import edu.umd.cs.findbugs.xml.XMLOutput;
49 import edu.umd.cs.findbugs.xml.XMLOutputUtil;
50 import edu.umd.cs.findbugs.xml.XMLWriteable;
51
52 /**
53  * A project in the GUI.
54  * This consists of some number of Jar files to analyze for bugs, and optionally
55  * <p/>
56  * <ul>
57  * <li> some number of source directories, for locating the program's
58  * source code
59  * <li> some number of auxiliary classpath entries, for locating classes
60  * referenced by the program which the user doesn't want to analyze
61  * <li> some number of boolean options
62  * </ul>
63  *
64  * @author David Hovemeyer
65  */

66 public class Project implements XMLWriteable {
67     private static final boolean DEBUG = SystemProperties.getBoolean("findbugs.project.debug");
68
69     /**
70      * Project filename.
71      */

72     private String JavaDoc projectFileName;
73
74     /**
75      * Options.
76      */

77     private Map JavaDoc<String JavaDoc, Boolean JavaDoc> optionsMap;
78
79     /**
80      * The list of project files.
81      */

82     private LinkedList JavaDoc<String JavaDoc> fileList;
83
84     /**
85      * The list of source directories.
86      */

87     private LinkedList JavaDoc<String JavaDoc> srcDirList;
88
89     /**
90      * The list of auxiliary classpath entries.
91      */

92     private LinkedList JavaDoc<String JavaDoc> auxClasspathEntryList;
93
94     /**
95      * Flag to indicate that this Project has been modified.
96      */

97     private boolean isModified;
98
99     /**
100      * Constant used to name anonymous projects.
101      */

102     public static final String JavaDoc UNNAMED_PROJECT = "<<unnamed project>>";
103
104     private long timestamp = 0L;
105     
106     /**
107      * Create an anonymous project.
108      */

109     public Project() {
110         this.projectFileName = UNNAMED_PROJECT;
111         optionsMap = new HashMap JavaDoc<String JavaDoc, Boolean JavaDoc>();
112         optionsMap.put(RELATIVE_PATHS, Boolean.FALSE);
113         fileList = new LinkedList JavaDoc<String JavaDoc>();
114         srcDirList = new LinkedList JavaDoc<String JavaDoc>();
115         auxClasspathEntryList = new LinkedList JavaDoc<String JavaDoc>();
116         isModified = false;
117     }
118
119     /**
120      * Return an exact copy of this Project.
121      */

122     public Project duplicate() {
123         Project dup = new Project();
124         dup.projectFileName = this.projectFileName;
125         dup.optionsMap.clear();
126         dup.optionsMap.putAll(this.optionsMap);
127         dup.fileList.addAll(this.fileList);
128         dup.srcDirList.addAll(this.srcDirList);
129         dup.auxClasspathEntryList.addAll(this.auxClasspathEntryList);
130         dup.timestamp = timestamp;
131
132         return dup;
133     }
134
135     /**
136      * Return whether or not this Project has unsaved modifications.
137      */

138     public boolean isModified() {
139         return isModified;
140     }
141
142     /**
143      * Set whether or not this Project has unsaved modifications.
144      */

145     public void setModified(boolean isModified) {
146         this.isModified = isModified;
147     }
148
149     /**
150      * Get the project filename.
151      */

152     public String JavaDoc getProjectFileName() {
153         return projectFileName;
154     }
155
156     /**
157      * Set the project filename.
158      *
159      * @param projectFileName the new filename
160      */

161     public void setProjectFileName(String JavaDoc projectFileName) {
162         this.projectFileName = projectFileName;
163     }
164
165     /**
166      * Add a file to the project.
167      *
168      * @param fileName the file to add
169      * @return true if the file was added, or false if the
170      * file was already present
171      */

172     public boolean addFile(String JavaDoc fileName) {
173         return addToListInternal(fileList, makeAbsoluteCWD(fileName));
174     }
175
176     /**
177      * Add a source directory to the project.
178      * @param dirName the directory to add
179      * @return true if the source directory was added, or false if the
180      * source directory was already present
181      */

182     public boolean addSourceDir(String JavaDoc dirName) {
183         return addToListInternal(srcDirList, makeAbsoluteCWD(dirName));
184     }
185
186     /**
187      * Retrieve the Options value.
188      *
189      * @param option the name of option to get
190      * @return the value of the option
191      */

192     public boolean getOption(String JavaDoc option) {
193         Boolean JavaDoc value = optionsMap.get(option);
194         return value != null && value.booleanValue();
195     }
196
197     /**
198      * Get the number of files in the project.
199      *
200      * @return the number of files in the project
201      */

202     public int getFileCount() {
203         return fileList.size();
204     }
205
206     /**
207      * Get the given file in the list of project files.
208      *
209      * @param num the number of the file in the list of project files
210      * @return the name of the file
211      */

212     public String JavaDoc getFile(int num) {
213         return fileList.get(num);
214     }
215
216     /**
217      * Remove file at the given index in the list of project files
218      *
219      * @param num index of the file to remove in the list of project files
220      */

221     public void removeFile(int num) {
222         fileList.remove(num);
223         isModified = true;
224     }
225
226     /**
227      * Get the list of files, directories, and zip files in the project.
228      */

229     public List JavaDoc<String JavaDoc> getFileList() {
230         return fileList;
231     }
232
233     /**
234      * Get the number of source directories in the project.
235      *
236      * @return the number of source directories in the project
237      */

238     public int getNumSourceDirs() {
239         return srcDirList.size();
240     }
241
242     /**
243      * Get the given source directory.
244      *
245      * @param num the number of the source directory
246      * @return the source directory
247      */

248     public String JavaDoc getSourceDir(int num) {
249         return srcDirList.get(num);
250     }
251
252     /**
253      * Remove source directory at given index.
254      *
255      * @param num index of the source directory to remove
256      */

257     public void removeSourceDir(int num) {
258         srcDirList.remove(num);
259         isModified = true;
260     }
261
262     /**
263      * Get project files as an array of Strings.
264      */

265     public String JavaDoc[] getFileArray() {
266         return fileList.toArray(new String JavaDoc[fileList.size()]);
267     }
268
269     /**
270      * Get source dirs as an array of Strings.
271      */

272     public String JavaDoc[] getSourceDirArray() {
273         return srcDirList.toArray(new String JavaDoc[srcDirList.size()]);
274     }
275
276     /**
277      * Get the source dir list.
278      */

279     public List JavaDoc<String JavaDoc> getSourceDirList() {
280         return srcDirList;
281     }
282
283     /**
284      * Add an auxiliary classpath entry
285      *
286      * @param auxClasspathEntry the entry
287      * @return true if the entry was added successfully, or false
288      * if the given entry is already in the list
289      */

290     public boolean addAuxClasspathEntry(String JavaDoc auxClasspathEntry) {
291         return addToListInternal(auxClasspathEntryList, makeAbsoluteCWD(auxClasspathEntry));
292     }
293
294     /**
295      * Get the number of auxiliary classpath entries.
296      */

297     public int getNumAuxClasspathEntries() {
298         return auxClasspathEntryList.size();
299     }
300
301     /**
302      * Get the n'th auxiliary classpath entry.
303      */

304     public String JavaDoc getAuxClasspathEntry(int n) {
305         return auxClasspathEntryList.get(n);
306     }
307
308     /**
309      * Remove the n'th auxiliary classpath entry.
310      */

311     public void removeAuxClasspathEntry(int n) {
312         auxClasspathEntryList.remove(n);
313         isModified = true;
314     }
315
316     /**
317      * Return the list of aux classpath entries.
318      */

319     public List JavaDoc<String JavaDoc> getAuxClasspathEntryList() {
320         return auxClasspathEntryList;
321     }
322
323     /**
324      * Worklist item for finding implicit classpath entries.
325      */

326     private static class WorkListItem {
327         private URL JavaDoc url;
328
329         /**
330          * Constructor.
331          *
332          * @param url the URL of the Jar or Zip file
333          */

334         public WorkListItem(URL JavaDoc url) {
335             this.url = url;
336         }
337
338         /**
339          * Get URL of Jar/Zip file.
340          */

341         public URL JavaDoc getURL() {
342             return this.url;
343         }
344     }
345
346     /**
347      * Worklist for finding implicit classpath entries.
348      */

349     private static class WorkList {
350         private LinkedList JavaDoc<WorkListItem> itemList;
351         private HashSet JavaDoc<String JavaDoc> addedSet;
352
353         /**
354          * Constructor.
355          * Creates an empty worklist.
356          */

357         public WorkList() {
358             this.itemList = new LinkedList JavaDoc<WorkListItem>();
359             this.addedSet = new HashSet JavaDoc<String JavaDoc>();
360         }
361
362         /**
363          * Create a URL from a filename specified in the project file.
364          */

365         public URL JavaDoc createURL(String JavaDoc fileName) throws MalformedURLException JavaDoc {
366             String JavaDoc protocol = URLClassPath.getURLProtocol(fileName);
367             if (protocol == null) {
368                 fileName = "file:" + fileName;
369             }
370             return new URL JavaDoc(fileName);
371         }
372
373         /**
374          * Create a URL of a file relative to another URL.
375          */

376         public URL JavaDoc createRelativeURL(URL JavaDoc base, String JavaDoc fileName) throws MalformedURLException JavaDoc {
377             return new URL JavaDoc(base, fileName);
378         }
379
380         /**
381          * Add a worklist item.
382          *
383          * @param item the WorkListItem representing a zip/jar file to be examined
384          * @return true if the item was added, false if not (because it was
385          * examined already)
386          */

387         public boolean add(WorkListItem item) {
388             if (DEBUG) System.out.println("Adding " + item.getURL().toString());
389             if (!addedSet.add(item.getURL().toString())) {
390                 if (DEBUG) System.out.println("\t==> Already processed");
391                 return false;
392             }
393
394             itemList.add(item);
395             return true;
396         }
397
398         /**
399          * Return whether or not the worklist is empty.
400          */

401         public boolean isEmpty() {
402             return itemList.isEmpty();
403         }
404
405         /**
406          * Get the next item in the worklist.
407          */

408         public WorkListItem getNextItem() {
409             return itemList.removeFirst();
410         }
411     }
412
413     /**
414      * Return the list of implicit classpath entries. The implicit
415      * classpath is computed from the closure of the set of jar files
416      * that are referenced by the <code>"Class-Path"</code> attribute
417      * of the manifest of the any jar file that is part of this project
418      * or by the <code>"Class-Path"</code> attribute of any directly or
419      * indirectly referenced jar. The referenced jar files that exist
420      * are the list of implicit classpath entries.
421      *
422      * @deprecated FindBugs2 and ClassPathBuilder take care of this automatically
423      */

424     public List JavaDoc<String JavaDoc> getImplicitClasspathEntryList() {
425         final LinkedList JavaDoc<String JavaDoc> implicitClasspath = new LinkedList JavaDoc<String JavaDoc>();
426         WorkList workList = new WorkList();
427
428         // Prime the worklist by adding the zip/jar files
429
// in the project.
430
for (String JavaDoc fileName : fileList) {
431             try {
432                 URL JavaDoc url = workList.createURL(fileName);
433                 WorkListItem item = new WorkListItem(url);
434                 workList.add(item);
435             } catch (MalformedURLException JavaDoc ignore) {
436                 // Ignore
437
}
438         }
439
440         // Scan recursively.
441
while (!workList.isEmpty()) {
442             WorkListItem item = workList.getNextItem();
443             processComponentJar(item.getURL(), workList, implicitClasspath);
444         }
445
446         return implicitClasspath;
447     }
448
449     /**
450      * Examine the manifest of a single zip/jar file for implicit
451      * classapth entries.
452      *
453      * @param jarFileURL URL of the zip/jar file
454      * @param workList worklist of zip/jar files to examine
455      * @param implicitClasspath list of implicit classpath entries found
456      */

457     private void processComponentJar(URL JavaDoc jarFileURL, WorkList workList,
458         List JavaDoc<String JavaDoc> implicitClasspath) {
459
460         if (DEBUG) System.out.println("Processing " + jarFileURL.toString());
461
462         if (!jarFileURL.toString().endsWith(".zip") && !jarFileURL.toString().endsWith(".jar"))
463             return;
464
465         try {
466             URL JavaDoc manifestURL = new URL JavaDoc("jar:" + jarFileURL.toString() + "!/META-INF/MANIFEST.MF");
467
468             InputStream JavaDoc in = null;
469             try {
470                 in = manifestURL.openStream();
471                 Manifest JavaDoc manifest = new Manifest JavaDoc(in);
472
473                 Attributes JavaDoc mainAttrs = manifest.getMainAttributes();
474                 String JavaDoc classPath = mainAttrs.getValue("Class-Path");
475                 if (classPath != null) {
476                     String JavaDoc[] fileList = classPath.split("\\s+");
477
478                     for (String JavaDoc jarFile : fileList) {
479                         URL JavaDoc referencedURL = workList.createRelativeURL(jarFileURL, jarFile);
480                         if (workList.add(new WorkListItem(referencedURL))) {
481                             implicitClasspath.add(referencedURL.toString());
482                             if (DEBUG) System.out.println("Implicit jar: " + referencedURL.toString());
483                         }
484                     }
485                 }
486             } finally {
487                 if (in != null) {
488                     in.close();
489                 }
490             }
491         } catch (IOException JavaDoc ignore) {
492             // Ignore
493
}
494     }
495
496     private static final String JavaDoc OPTIONS_KEY = "[Options]";
497     private static final String JavaDoc JAR_FILES_KEY = "[Jar files]";
498     private static final String JavaDoc SRC_DIRS_KEY = "[Source dirs]";
499     private static final String JavaDoc AUX_CLASSPATH_ENTRIES_KEY = "[Aux classpath entries]";
500
501     // Option keys
502
public static final String JavaDoc RELATIVE_PATHS = "relative_paths";
503
504     /**
505      * Save the project to an output file.
506      *
507      * @param outputFile name of output file
508      * @param useRelativePaths true if the project should be written
509      * using only relative paths
510      * @param relativeBase if useRelativePaths is true,
511      * this file is taken as the base directory in terms of which
512      * all files should be made relative
513      * @throws IOException if an error occurs while writing
514      */

515     public void write(String JavaDoc outputFile, boolean useRelativePaths, String JavaDoc relativeBase)
516             throws IOException JavaDoc {
517         PrintWriter JavaDoc writer = new PrintWriter JavaDoc(new BufferedWriter JavaDoc(new FileWriter JavaDoc(outputFile)));
518         try {
519             writer.println(JAR_FILES_KEY);
520             for (String JavaDoc jarFile : fileList) {
521                 if (useRelativePaths)
522                     jarFile = convertToRelative(jarFile, relativeBase);
523                 writer.println(jarFile);
524             }
525
526             writer.println(SRC_DIRS_KEY);
527             for (String JavaDoc srcDir : srcDirList) {
528                 if (useRelativePaths)
529                     srcDir = convertToRelative(srcDir, relativeBase);
530                 writer.println(srcDir);
531             }
532
533             writer.println(AUX_CLASSPATH_ENTRIES_KEY);
534             for (String JavaDoc auxClasspathEntry : auxClasspathEntryList) {
535                 if (useRelativePaths)
536                     auxClasspathEntry = convertToRelative(auxClasspathEntry, relativeBase);
537                 writer.println(auxClasspathEntry);
538             }
539
540             if (useRelativePaths) {
541                 writer.println(OPTIONS_KEY);
542                 writer.println(RELATIVE_PATHS + "=true");
543             }
544         } finally {
545             writer.close();
546         }
547         
548         // Project successfully saved
549
isModified = false;
550     }
551
552     /**
553      * Read the project from an input file.
554      * This method should only be used on an empty Project
555      * (created with the default constructor).
556      *
557      * @param inputFile name of the input file to read the project from
558      * @throws IOException if an error occurs while reading
559      */

560     public void read(String JavaDoc inputFile) throws IOException JavaDoc {
561         if (isModified)
562             throw new IllegalStateException JavaDoc("Reading into a modified Project!");
563
564         // Make the input file absolute, if necessary
565
File JavaDoc file = new File JavaDoc(inputFile);
566         if (!file.isAbsolute())
567             inputFile = file.getAbsolutePath();
568
569         // Store the project filename
570
setProjectFileName(inputFile);
571
572         BufferedReader JavaDoc reader = null;
573
574         try {
575             reader = new BufferedReader JavaDoc(new FileReader JavaDoc(inputFile));
576             String JavaDoc line;
577             line = getLine(reader);
578
579             if (line == null || !line.equals(JAR_FILES_KEY))
580                 throw new IOException JavaDoc("Bad format: missing jar files key");
581             while ((line = getLine(reader)) != null && !line.equals(SRC_DIRS_KEY)) {
582                 addToListInternal(fileList, line);
583             }
584
585             if (line == null)
586                 throw new IOException JavaDoc("Bad format: missing source dirs key");
587             while ((line = getLine(reader)) != null && !line.equals(AUX_CLASSPATH_ENTRIES_KEY)) {
588                 addToListInternal(srcDirList, line);
589             }
590
591             // The list of aux classpath entries is optional
592
if (line != null) {
593                 while ((line = getLine(reader)) != null) {
594                     if (line.equals(OPTIONS_KEY))
595                         break;
596                     addToListInternal(auxClasspathEntryList, line);
597                 }
598             }
599
600             // The Options section is also optional
601
if (line != null && line.equals(OPTIONS_KEY)) {
602                 while ((line = getLine(reader)) != null && !line.equals(JAR_FILES_KEY))
603                     parseOption(line);
604             }
605
606             // If this project has the relative paths option set,
607
// resolve all internal relative paths into absolute
608
// paths, using the absolute path of the project
609
// file as a base directory.
610
if (getOption(RELATIVE_PATHS)) {
611                 makeListAbsoluteProject(fileList);
612                 makeListAbsoluteProject(srcDirList);
613                 makeListAbsoluteProject(auxClasspathEntryList);
614             }
615     
616             // Clear the modification flag set by the various "add" methods.
617
isModified = false;
618         } finally {
619             if (reader != null)
620                 reader.close();
621         }
622     }
623
624     /**
625      * Read a line from a BufferedReader, ignoring blank lines
626      * and comments.
627      */

628     private static String JavaDoc getLine(BufferedReader JavaDoc reader) throws IOException JavaDoc {
629         String JavaDoc line;
630         while ((line = reader.readLine()) != null) {
631             line = line.trim();
632             if (!line.equals("") && !line.startsWith("#"))
633                 break;
634         }
635         return line;
636     }
637
638     /**
639      * Convert to a string in a nice (displayable) format.
640      */

641     @Override JavaDoc
642     public String JavaDoc toString() {
643         String JavaDoc name = projectFileName;
644         int lastSep = name.lastIndexOf(File.separatorChar);
645         if (lastSep >= 0)
646             name = name.substring(lastSep + 1);
647         //int dot = name.lastIndexOf('.');
648
//Don't hide every suffix--some are informative and/or disambiguative.
649
int dot = (name.endsWith(".fb") ? name.length()-3 : -1);
650         if (dot >= 0)
651             name = name.substring(0, dot);
652         return name;
653     }
654
655     /**
656      * Transform a user-entered filename into a proper filename,
657      * by adding the ".fb" file extension if it isn't already present.
658      */

659     public static String JavaDoc transformFilename(String JavaDoc fileName) {
660         if (!fileName.endsWith(".fb"))
661             fileName = fileName + ".fb";
662         return fileName;
663     }
664
665     static final String JavaDoc JAR_ELEMENT_NAME = "Jar";
666     static final String JavaDoc AUX_CLASSPATH_ENTRY_ELEMENT_NAME = "AuxClasspathEntry";
667     static final String JavaDoc SRC_DIR_ELEMENT_NAME = "SrcDir";
668     static final String JavaDoc FILENAME_ATTRIBUTE_NAME = "filename";
669
670     public void writeXML(XMLOutput xmlOutput) throws IOException JavaDoc {
671         xmlOutput.openTag(
672                 BugCollection.PROJECT_ELEMENT_NAME,
673                 new XMLAttributeList().addAttribute(FILENAME_ATTRIBUTE_NAME, getProjectFileName()));
674
675         XMLOutputUtil.writeElementList(xmlOutput, JAR_ELEMENT_NAME, fileList);
676         XMLOutputUtil.writeElementList(xmlOutput, AUX_CLASSPATH_ENTRY_ELEMENT_NAME, auxClasspathEntryList);
677         XMLOutputUtil.writeElementList(xmlOutput, SRC_DIR_ELEMENT_NAME, srcDirList);
678
679         xmlOutput.closeTag(BugCollection.PROJECT_ELEMENT_NAME);
680     }
681
682     /**
683      * Parse one line in the [Options] section.
684      *
685      * @param option one line in the [Options] section
686      */

687     private void parseOption(String JavaDoc option) throws IOException JavaDoc {
688         int equalPos = option.indexOf("=");
689         if (equalPos < 0)
690             throw new IOException JavaDoc("Bad format: invalid option format");
691         String JavaDoc name = option.substring(0, equalPos);
692         String JavaDoc value = option.substring(equalPos + 1);
693         optionsMap.put(name, Boolean.valueOf(value));
694     }
695
696     /**
697      * Hack for whether files are case insensitive.
698      * For now, we'll assume that Windows is the only
699      * case insensitive OS. (OpenVMS users,
700      * feel free to submit a patch :-)
701      */

702     private static final boolean FILE_IGNORE_CASE =
703             SystemProperties.getProperty("os.name", "unknown").startsWith("Windows");
704
705     /**
706      * Converts a full path to a relative path if possible
707      *
708      * @param srcFile path to convert
709      * @return the converted filename
710      */

711     private String JavaDoc convertToRelative(String JavaDoc srcFile, String JavaDoc base) {
712         String JavaDoc slash = SystemProperties.getProperty("file.separator");
713
714         if (FILE_IGNORE_CASE) {
715             srcFile = srcFile.toLowerCase();
716             base = base.toLowerCase();
717         }
718
719         if (base.equals(srcFile))
720             return ".";
721
722         if (!base.endsWith(slash))
723             base = base + slash;
724
725         if (base.length() <= srcFile.length()) {
726             String JavaDoc root = srcFile.substring(0, base.length());
727             if (root.equals(base)) {
728                 // Strip off the base directory, make relative
729
return "." + SystemProperties.getProperty("file.separator") + srcFile.substring(base.length());
730             }
731         }
732         
733         //See if we can build a relative path above the base using .. notation
734
int slashPos = srcFile.indexOf(slash);
735         int branchPoint;
736         if (slashPos >= 0) {
737             String JavaDoc subPath = srcFile.substring(0, slashPos);
738             if ((subPath.length() == 0) || base.startsWith(subPath)) {
739                 branchPoint = slashPos + 1;
740                 slashPos = srcFile.indexOf(slash, branchPoint);
741                 while (slashPos >= 0) {
742                     subPath = srcFile.substring(0, slashPos);
743                     if (base.startsWith(subPath))
744                         branchPoint = slashPos + 1;
745                     else
746                         break;
747                     slashPos = srcFile.indexOf(slash, branchPoint);
748                 }
749
750                 int slashCount = 0;
751                 slashPos = base.indexOf(slash, branchPoint);
752                 while (slashPos >= 0) {
753                     slashCount++;
754                     slashPos = base.indexOf(slash, slashPos + 1);
755                 }
756
757                 StringBuffer JavaDoc path = new StringBuffer JavaDoc();
758                 String JavaDoc upDir = ".." + slash;
759                 for (int i = 0; i < slashCount; i++)
760                     path.append(upDir);
761                 path.append(srcFile.substring(branchPoint));
762                 return path.toString();
763             }
764         }
765
766
767         return srcFile;
768
769     }
770
771     /**
772      * Converts a relative path to an absolute path if possible.
773      *
774      * @param fileName path to convert
775      * @return the converted filename
776      */

777     private String JavaDoc convertToAbsolute(String JavaDoc fileName) throws IOException JavaDoc {
778         // At present relative paths are only calculated if the fileName is
779
// below the project file. This need not be the case, and we could use ..
780
// syntax to move up the tree. (To Be Added)
781

782         File JavaDoc file = new File JavaDoc(fileName);
783
784         if (!file.isAbsolute()) {
785             // Only try to make the relative path absolute
786
// if the project file is absolute.
787
File JavaDoc projectFile = new File JavaDoc(projectFileName);
788             if (projectFile.isAbsolute()) {
789                 // Get base directory (parent of the project file)
790
String JavaDoc base = new File JavaDoc(projectFileName).getParent();
791
792                 // Make the file absolute in terms of the parent directory
793
fileName = new File JavaDoc(base, fileName).getCanonicalPath();
794             }
795         }
796         return fileName;
797     }
798
799     /**
800      * Make the given filename absolute relative to the
801      * current working directory.
802      */

803     private static String JavaDoc makeAbsoluteCWD(String JavaDoc fileName) {
804         File JavaDoc file = new File JavaDoc(fileName);
805         boolean hasProtocol = (URLClassPath.getURLProtocol(fileName) != null);
806         if (!hasProtocol && !file.isAbsolute())
807             fileName = file.getAbsolutePath();
808         return fileName;
809     }
810
811     /**
812      * Add a value to given list, making the Project modified
813      * if the value is not already present in the list.
814      *
815      * @param list the list
816      * @param value the value to be added
817      * @return true if the value was not already present in the list,
818      * false otherwise
819      */

820     private boolean addToListInternal(List JavaDoc<String JavaDoc> list, String JavaDoc value) {
821         if (!list.contains(value)) {
822             list.add(value);
823             isModified = true;
824             return true;
825         } else
826             return false;
827     }
828
829     /**
830      * Make the given list of pathnames absolute relative
831      * to the absolute path of the project file.
832      */

833     private void makeListAbsoluteProject(List JavaDoc<String JavaDoc> list) throws IOException JavaDoc {
834         List JavaDoc<String JavaDoc> replace = new LinkedList JavaDoc<String JavaDoc>();
835         for (String JavaDoc fileName : list) {
836             fileName = convertToAbsolute(fileName);
837             replace.add(fileName);
838         }
839
840         list.clear();
841         list.addAll(replace);
842     }
843
844     /**
845      * @param timestamp The timestamp to set.
846      */

847     public void setTimestamp(long timestamp) {
848         this.timestamp = timestamp;
849     }
850     
851     public void addTimestamp(long timestamp) {
852         if (this.timestamp < timestamp)
853             this.timestamp = timestamp;
854     }
855     /**
856      * @return Returns the timestamp.
857      */

858     public long getTimestamp() {
859         return timestamp;
860     }
861 }
862
863 // vim:ts=4
864
Popular Tags