KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > project > ProjectProfile


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32 END_COPYRIGHT_BLOCK*/

33
34 package edu.rice.cs.drjava.project;
35
36 import java.util.ArrayList JavaDoc;
37 import java.util.List JavaDoc;
38 //import java.util.Vector;
39
import java.util.Date JavaDoc;
40 import java.text.SimpleDateFormat JavaDoc;
41 import java.io.*;
42
43 import edu.rice.cs.plt.tuple.Pair;
44 import edu.rice.cs.plt.io.IOUtil;
45 import edu.rice.cs.drjava.config.FileOption;
46 import edu.rice.cs.drjava.Version;
47 import edu.rice.cs.util.FileOps;
48 import edu.rice.cs.util.UnexpectedException;
49 import edu.rice.cs.util.swing.Utilities;
50 import edu.rice.cs.drjava.model.DocumentRegion;
51 import edu.rice.cs.drjava.model.debug.DebugBreakpointData;
52 import edu.rice.cs.drjava.model.debug.DebugWatchData;
53 import edu.rice.cs.drjava.model.debug.DebugException;
54
55 import static edu.rice.cs.util.StringOps.*;
56
57 /** The internal representation of a project; it is the internal analog of a project file. Includes support for
58  * writing corresponding project file.
59  */

60 public class ProjectProfile implements ProjectFileIR {
61   
62   /* Private fields */
63   
64   private List JavaDoc<DocFile> _sourceFiles = new ArrayList JavaDoc<DocFile>();
65   private List JavaDoc<DocFile> _auxFiles = new ArrayList JavaDoc<DocFile>();
66   private List JavaDoc<String JavaDoc> _collapsedPaths = new ArrayList JavaDoc<String JavaDoc>();
67   
68   private File _buildDir = null;
69   private File _workDir = null;
70   
71   private List JavaDoc<File> _classPathFiles = new ArrayList JavaDoc<File>();
72   
73   private File _mainClass = null;
74   
75   /** root of project source tree. Invariant: _projectRoot.exists() */
76   private File _projectRoot;
77   
78   private File _projectFile; /* Invariant: _projectFile.getParentFile().exists() */
79   
80   private File _createJarFile = null;
81   
82   private int _createJarFlags = 0;
83   
84   private List JavaDoc<DocumentRegion> _bookmarks = new ArrayList JavaDoc<DocumentRegion>();
85   private List JavaDoc<DebugBreakpointData> _breakpoints = new ArrayList JavaDoc<DebugBreakpointData>();
86   private List JavaDoc<DebugWatchData> _watches = new ArrayList JavaDoc<DebugWatchData>();
87   
88   /** Constructs a File for fileName and forwards this call to the main constructor. */
89   public ProjectProfile(String JavaDoc fileName) throws IOException { this(new File(fileName)); }
90   
91   /** Creates new ProjectProfiles with specifed project file name and project root that is parent folder of
92    * the project file. The project file presumably may not exist yet, but its parent folder is assumed to exist.
93    * @throws IOException parent directory of project file does not exist.
94    */

95   public ProjectProfile(File f) throws IOException {
96     _projectFile = f;
97     _projectRoot = _projectFile.getParentFile();
98     if (! _projectRoot.exists()) throw new IOException("Parent directory of project root " + _projectRoot +
99                                                        " does not exist");
100   }
101   
102   /* Public getters */
103   
104   /** @return an array of the source files in this project. */
105   public DocFile[] getSourceFiles() { return _sourceFiles.toArray(new DocFile[_sourceFiles.size()]); }
106     
107   /** @return an array full of all the aux files (project outside source tree) in this project. */
108   public DocFile[] getAuxiliaryFiles() { return _auxFiles.toArray(new DocFile[_auxFiles.size()]); }
109   
110   /** @return project file. */
111   public File getProjectFile() { return _projectFile; }
112     
113   /** @return the build directory stored in this project file */
114   public File getBuildDirectory() { return _buildDir; }
115   
116    /** @return the working directory stored in this project profile */
117   public File getWorkingDirectory() { return _workDir; }
118   
119   /** @return an array of path strings correspond to which folders in the tree should not be shown. Any paths not in
120    * this list will be expanded when the project is opened.
121    */

122   public String JavaDoc[] getCollapsedPaths() { return _collapsedPaths.toArray(new String JavaDoc[_collapsedPaths.size()]); }
123     
124   /** @return an array full of all the classpath path elements in the classpath for this project file */
125   public File[] getClassPaths() { return _classPathFiles.toArray(new File[_classPathFiles.size()]); }
126   
127   /** @return the name of the file that holds the Jar main class associated with this project */
128   public File getMainClass() { return _mainClass; }
129   
130   /** @return the project root directory which must exist. */
131   public File getProjectRoot() { return _projectRoot; }
132   
133   /** @return the output file used in the "Create Jar" dialog. */
134   public File getCreateJarFile() { return _createJarFile; }
135   
136   /** @return the output file used in the "Create Jar" dialog. */
137   public int getCreateJarFlags() { return _createJarFlags; }
138   
139   /** @return an array of the bookmarks in this project. */
140   public DocumentRegion[] getBookmarks() { return _bookmarks.toArray(new DocumentRegion[_bookmarks.size()]); }
141   
142   /** @return an array of the breakpoints in this project. */
143   public DebugBreakpointData[] getBreakpoints() { return _breakpoints.toArray(new DebugBreakpointData[_breakpoints.size()]); }
144   
145   /** @return an array of the watches in this project. */
146   public DebugWatchData[] getWatches() { return _watches.toArray(new DebugWatchData[_watches.size()]); }
147   
148   /** Public setters, modifiers */
149   
150   public void addSourceFile(DocFile df) { _sourceFiles.add(df); }
151   
152   public void addSourceFile(DocumentInfoGetter getter) {
153     if (!getter.isUntitled()) {
154       try { addSourceFile(docFileFromGetter(getter)); }
155       catch(IOException e) { throw new UnexpectedException(e); }
156     }
157   }
158   
159   public void addAuxiliaryFile(DocFile df) { _auxFiles.add(df); }
160     
161   public void addAuxiliaryFile(DocumentInfoGetter getter) {
162     if (! getter.isUntitled()) {
163       try { addAuxiliaryFile(docFileFromGetter(getter)); }
164       catch(IOException e) { throw new UnexpectedException(e); }
165     }
166   }
167   
168   public void addClassPathFile(File cp) { if (cp != null) _classPathFiles.add(cp); }
169   public void addCollapsedPath(String JavaDoc cp) { if (cp != null) _collapsedPaths.add(cp); }
170   public void setBuildDirectory(File dir) {
171 // System.err.println("setBuildDirectory(" + dir + ") called");
172
// removed call to validate to allow build directory that doesn't exist:
173
// it will be created when necessary
174
_buildDir = dir; // FileOps.validate(dir);
175
// System.err.println("Vaidated form is: " + _buildDir);
176
}
177   public void setWorkingDirectory(File dir) { _workDir = FileOps.validate(dir); }
178   public void setMainClass(File main) { _mainClass = main; }
179   public void setSourceFiles(List JavaDoc<DocFile> sf) { _sourceFiles = new ArrayList JavaDoc<DocFile>(sf); }
180   public void setClassPaths(List JavaDoc<? extends File> cpf) { _classPathFiles = new ArrayList JavaDoc<File>(cpf); }
181   public void setCollapsedPaths(List JavaDoc<String JavaDoc> cp) { _collapsedPaths = new ArrayList JavaDoc<String JavaDoc>(cp); }
182   public void setAuxiliaryFiles(List JavaDoc<DocFile> af) { _auxFiles = new ArrayList JavaDoc<DocFile>(af); }
183
184   /** Assumes that root.getParentFile != null */
185   public void setProjectRoot(File root) {
186     _projectRoot = root;
187     assert root.getParentFile() != null;
188   }
189   
190   public void setCreateJarFile(File createJarFile) { _createJarFile = createJarFile; }
191   public void setCreateJarFlags(int createJarFlags) { _createJarFlags = createJarFlags; }
192   
193   public void setBookmarks(List JavaDoc<? extends DocumentRegion> bms) { _bookmarks = new ArrayList JavaDoc<DocumentRegion>(bms); }
194   public void setBreakpoints(List JavaDoc<? extends DebugBreakpointData> bps) { _breakpoints = new ArrayList JavaDoc<DebugBreakpointData>(bps); }
195   public void setWatches(List JavaDoc<? extends DebugWatchData> ws) { _watches = new ArrayList JavaDoc<DebugWatchData>(ws); }
196   
197   /** This method writes what information has been passed to this builder so far to disk in s-expression format. */
198   public void write() throws IOException {
199     FileWriter fw = new FileWriter(_projectFile);
200     
201     // write opening comment line
202
fw.write(";; DrJava project file, written by build " + Version.getBuildTimeString());
203     fw.write("\n;; files in the source tree are relative to: " + _projectRoot.getCanonicalPath());
204     fw.write("\n;; other files with relative paths are rooted at (the parent of) this project file");
205     
206     // write the project root
207
/* In the new project file form, this property has been renamed "proj-root-and-base" (instead of "proj-root") to
208      * indicate that the project root now serves as the base for source file path names. */

209     if (_projectRoot != null) {
210       fw.write("\n(proj-root-and-base");
211 // Utilities.show("Writing project root = " + _projRoot);
212
fw.write("\n" + encodeFileRelative(_projectRoot, " ", _projectFile));
213       fw.write(")");
214     }
215     else fw.write("\n;; no project root; should never happen");
216         
217     // write source files
218
/* This property has been renamed "source-files" (instead of "source") so that old versions of DrJava will not
219      * recognize it. In the new project file format, source files are relative to the project root, not the parent
220      * of the project file. */

221     if (!_sourceFiles.isEmpty()) {
222       fw.write("\n(source-files");
223       DocFile active = null;
224       for(DocFile df: _sourceFiles) {
225         if(df.isActive()) {
226           active = df;
227           fw.write("\n" + encodeDocFileRelative(df, " "));
228           break; //Assert that there is only one active document in the project
229
}
230       }
231       for(DocFile df: _sourceFiles) {
232         if(df != active)
233           fw.write("\n" + encodeDocFileRelative(df, " "));
234       }
235       fw.write(")"); // close the source expression
236
}
237     else fw.write("\n;; no source files");
238     
239     // write aux files
240
if (!_auxFiles.isEmpty()) {
241       fw.write("\n(auxiliary");
242       for(DocFile df: _auxFiles) { fw.write("\n" + encodeDocFileAbsolute(df, " ")); }
243       fw.write(")"); // close the auxiliary expression
244
}
245     else fw.write("\n;; no aux files");
246     
247     // write collapsed paths
248
if (!_collapsedPaths.isEmpty()) {
249       fw.write("\n(collapsed");
250       for(String JavaDoc s: _collapsedPaths) {
251         fw.write("\n (path " + convertToLiteral(s) + ")");
252       }
253       fw.write(")"); // close the collapsed expression
254
}
255     else fw.write("\n;; no collapsed branches");
256     
257     // write classpaths
258
if (!_classPathFiles.isEmpty()) {
259       fw.write("\n(classpaths");
260       for(File f: _classPathFiles) {
261         fw.write("\n" + encodeFileAbsolute(f, " "));
262       }
263       fw.write(")"); // close the classpaths expression
264
}
265     else fw.write("\n;; no classpaths files");
266     
267     // write the build directory
268
if (_buildDir != null && _buildDir.getPath() != "") {
269       fw.write("\n(build-dir");
270       fw.write("\n" + encodeFileRelative(_buildDir, " ", _projectFile));
271       fw.write(")");
272     }
273     else fw.write("\n;; no build directory");
274     
275      // write the working directory
276
if (_workDir != null && _workDir.getPath() != "") {
277       fw.write("\n(work-dir");
278       fw.write("\n" + encodeFileRelative(_workDir, " ", _projectFile));
279       fw.write(")");
280     }
281     else fw.write("\n;; no working directory");
282     
283     // write the main class
284
if (_mainClass != null) {
285       fw.write("\n;; rooted at the (parent of the) project file");
286       fw.write("\n(main-class");
287       fw.write("\n" + encodeFileRelative(_mainClass, " ", _projectFile));
288       fw.write(")");
289     }
290     else fw.write("\n;; no main class");
291     
292 // // write the create jar file
293
// if (_createJarFile != null) {
294
// fw.write("\n(create-jar-file");
295
// fw.write("\n" + encodeFile(_createJarFile, " ", true));
296
// fw.write(")");
297
// }
298
// else fw.write("\n;; no create jar file");
299
//
300
// // write the create jar flags
301
// if (_createJarFlags != 0) {
302
// fw.write("\n(create-jar-flags " + _createJarFlags + ")");
303
// }
304
// else fw.write("\n;; no create jar flags");
305

306     // write breakpoints
307
if (!_breakpoints.isEmpty()) {
308       fw.write("\n(breakpoints");
309       for(DebugBreakpointData bp: _breakpoints) { fw.write("\n" + encodeBreakpointRelative(bp, " ")); }
310       fw.write(")"); // close the breakpoints expression
311
}
312     else fw.write("\n;; no breakpoints");
313
314     // write watches
315
if (!_watches.isEmpty()) {
316       fw.write("\n(watches");
317       for(DebugWatchData w: _watches) { fw.write("\n" + encodeWatch(w, " ")); }
318       fw.write(")"); // close the watches expression
319
}
320     else fw.write("\n;; no watches");
321
322     // write bookmarks
323
if (!_bookmarks.isEmpty()) {
324       fw.write("\n(bookmarks");
325       for(DocumentRegion bm: _bookmarks) { fw.write("\n" + encodeBookmarkRelative(bm, " ")); }
326       fw.write(")"); // close the bookmarks expression
327
}
328     else fw.write("\n;; no bookmarks");
329
330     fw.close();
331   }
332   
333
334   /* Private Methods */
335   
336   /** @param getter The getter that can get all the info needed to make the document file
337    * @return the document that contains the information retrieved from the getter
338    */

339   private DocFile docFileFromGetter(DocumentInfoGetter g) throws IOException {
340       return new DocFile(g.getFile().getCanonicalPath(), g.getSelection(), g.getScroll(), g.isActive(), g.getPackage());
341   }
342   
343   
344   /** This encodes a normal file relative to File base. None of the special tags are added.
345    * @param f the file to encode
346    * @param prefix the indent level to place the s-expression at
347    * @param relative whether this file should be made relative to the project path
348    * @return the s-expression syntax to describe the given file.
349    */

350   private String JavaDoc encodeFileRelative(File f, String JavaDoc prefix, File base) throws IOException {
351     String JavaDoc path = FileOps.makeRelativeTo(f, base).getPath();
352     path = replace(path, File.separator, "/");
353     return prefix + "(file (name " + convertToLiteral(path) + "))";
354   }
355
356   /** This encodes a normal file relative to _projectRoot. None of the special tags are added. */
357   private String JavaDoc encodeFileRelative(File f, String JavaDoc prefix) throws IOException {
358     return encodeFileRelative(f, prefix, _projectRoot);
359   }
360     
361   /** This encodes a normal file with its canonical path. None of the special tags are added.
362    * @param f the file to encode
363    * @param prefix the indent level to place the s-expression at
364    * @return the s-expression syntax to describe the given file.
365    */

366   private String JavaDoc encodeFileAbsolute(File f, String JavaDoc prefix) throws IOException {
367     String JavaDoc path = f.getCanonicalPath();
368     path = replace(path,File.separator, "/");
369     return prefix + "(file (name " + convertToLiteral(path) + "))";
370   }
371   
372   /** This encodes a docfile, adding all the special tags that store document-specific information.
373    * @param df the doc file to encode
374    * @param prefix the indent level to place the s-expression at
375    * @param relative whether this file should be made relative to _projectRoot
376    * @return the s-expression syntax to describe the given docfile.
377    */

378   private String JavaDoc encodeDocFile(DocFile df, String JavaDoc prefix, boolean relative) throws IOException {
379     String JavaDoc ret = "";
380     String JavaDoc path;
381     if (relative) path = FileOps.makeRelativeTo(df, _projectRoot).getPath();
382     else path = IOUtil.attemptCanonicalFile(df).getPath();
383
384     path = replace(path, File.separator, "/");
385     ret += prefix + "(file (name " + convertToLiteral(path) + ")";
386     
387     Pair<Integer JavaDoc,Integer JavaDoc> p1 = df.getSelection();
388     Pair<Integer JavaDoc,Integer JavaDoc> p2 = df.getScroll();
389     //boolean active = false; //df.isActive();
390
long modDate = df.lastModified();
391     // Add prefix to the next line if any tags exist
392
if (p1 != null || p2 != null /*|| active */) ret += "\n" + prefix + " ";
393
394     // The next three tags go on the same line (if they exist)
395
if (p1 != null) ret += "(select " + p1.first() + " " + p1.second() + ")";
396
397     if (p2 != null) ret += "(scroll " + p2.first() + " " + p2.second() + ")";
398
399     if (modDate > 0) {
400       String JavaDoc s = new SimpleDateFormat JavaDoc("dd-MMM-yyyy HH:mm:ss").format(new Date JavaDoc(modDate));
401       ret += "(mod-date " + convertToLiteral(s) + ")";
402     }
403     
404     //if (active) ret += "(active)"; //Active document is first on list
405

406     // the next tag goes on the next line if at all
407
String JavaDoc pack = df.getPackage();
408     if (pack != null) {
409       ret += "\n" + prefix + " "; // add prefix
410
ret += "(package " + convertToLiteral(pack) + ")";
411     }
412     
413     ret += ")"; // close the file expression
414

415     return ret;
416   }
417   /** Encodes a doc file relative to _projectRoot.
418    * @param df the DocFile to encode
419    * @param prefix the indent level
420    */

421   private String JavaDoc encodeDocFileRelative(DocFile df, String JavaDoc prefix) throws IOException {
422     return encodeDocFile(df, prefix, true);
423   }
424   private String JavaDoc encodeDocFileAbsolute(DocFile df, String JavaDoc prefix) throws IOException {
425     return encodeDocFile(df, prefix, false);
426   }
427   
428   /** This encodes a breakpoint relative to _projectRoot.
429    * @param bp the breakpoint to encode
430    * @param prefix the indent level to place the s-expression at
431    * @return the s-expression syntax to describe the given breakpoint.
432    */

433   private String JavaDoc encodeBreakpointRelative(DebugBreakpointData bp, String JavaDoc prefix) throws IOException {
434     String JavaDoc ret = "";
435     String JavaDoc path = FileOps.makeRelativeTo(bp.getFile(), _projectRoot).getPath();
436     
437     path = replace(path,File.separator,"/");
438     ret += prefix + "(breakpoint (name " + convertToLiteral(path) + ")";
439     
440     int offset = bp.getOffset();
441     int lineNumber = bp.getLineNumber();
442     ret += "\n" + prefix + " ";
443     ret += "(offset " + offset + ")";
444     ret += "(line " + lineNumber + ")";
445     if (bp.isEnabled()) ret += "(enabled)";
446     ret += ")"; // close the breakpoint expression
447

448     return ret;
449   }
450  
451   /** This encodes a watch.
452    * @param w the watch to encode
453    * @param prefix the indent level to place the s-expression at
454    * @return the s-expression syntax to describe the given watch.
455    */

456   private String JavaDoc encodeWatch(DebugWatchData w, String JavaDoc prefix) throws IOException {
457     String JavaDoc ret = "";
458
459     ret += prefix + "(watch " + convertToLiteral(w.getName()) + ")";
460     
461     return ret;
462   }
463
464   /** This encodes a bookmark relative to _projectRoot.
465    * @param bm the bookmark to encode
466    * @param prefix the indent level to place the s-expression at
467    * @return the s-expression syntax to describe the given breakpoint.
468    */

469   private String JavaDoc encodeBookmarkRelative(DocumentRegion bp, String JavaDoc prefix) throws IOException {
470     String JavaDoc ret = "";
471     String JavaDoc path = FileOps.makeRelativeTo(bp.getDocument().getFile(), _projectRoot).getPath();
472     
473     path = replace(path,File.separator,"/");
474     ret += prefix + "(bookmark (name " + convertToLiteral(path) + ")";
475     
476     int startOffset = bp.getStartOffset();
477     int endOffset = bp.getEndOffset();
478     ret += "\n" + prefix + " ";
479     ret += "(start " + startOffset + ")";
480     ret += "(end " + endOffset + ")";
481     ret += ")"; // close the bookmarks expression
482

483     return ret;
484   }
485 }
Popular Tags