KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > ws > jaxme > js > JavaSourceFactory


1 /*
2  * Copyright 2003, 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.ws.jaxme.js;
17
18 import java.io.BufferedWriter JavaDoc;
19 import java.io.File JavaDoc;
20 import java.io.FileReader JavaDoc;
21 import java.io.FileWriter JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.Reader JavaDoc;
24 import java.io.StringWriter JavaDoc;
25 import java.io.Writer JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.StringTokenizer JavaDoc;
32
33 import org.apache.ws.jaxme.js.apps.JavaSourceResolver;
34 import org.apache.ws.jaxme.js.impl.TextFileImpl;
35 import org.apache.ws.jaxme.logging.Logger;
36 import org.apache.ws.jaxme.logging.LoggerAccess;
37
38 /** <p>Factory for generating JavaSource objects.</p>
39  * <p>
40  * The factory properties:
41  * </p>
42  * <ul>
43  * <li>{@link #setOverwriteForced}</li>
44  * <li>{@link #setSettingReadOnly}</li>
45  * </ul>
46  * <p>
47  * are used for finely grained controlled over the generated
48  * source files. Methods are provided to access abstract descriptions
49  * of the files to be created:
50  * </p>
51  * <ul>
52  * <li>{@link #getTextFiles} and {@link #getTextFile}</li>
53  * <li>{@link #getJavaSources} and {@link #getJavaSource}</li>
54  * </ul>
55  * <p>
56  * Concrete files (source and otherwise) are created by calling
57  * the following construction methods:
58  * </p>
59  * <ul>
60  * <li>{@link #newJavaSource(JavaQName)}, {@link #newJavaSource(JavaQName, String)}
61  * and {@link #newJavaSource(JavaQName, JavaSource.Protection)}</li>
62  * <li>{@link #newTextFile}</li>
63  * </ul>
64  *
65  * @author <a HREF="mailto:joe@ispsoft.de">Jochen Wiedmann</a>
66  * @version $Id: JavaSourceFactory.java,v 1.8 2004/12/13 11:56:10 jochen Exp $
67  */

68 public class JavaSourceFactory implements JavaSourceResolver {
69   private Logger logger = LoggerAccess.getLogger(JavaSourceFactory.class);
70   private boolean overwriteForced;
71   private boolean settingReadOnly;
72     private Map JavaDoc sources = new HashMap JavaDoc();
73   private List JavaDoc files = new ArrayList JavaDoc();
74
75   /** <p>Sets the {@link Logger} to use.</p>
76    */

77   public void setLogger(Logger pLogger) {
78     logger = pLogger;
79   }
80
81   /** <p>Returns the {@link Logger}.</p>
82    */

83   public Logger getLogger() {
84     return logger;
85   }
86
87   /** <p>Sets whether the generated files are created in read-only mode.</p>
88    */

89   public void setSettingReadOnly(boolean pSettingReadOnly) {
90     settingReadOnly = pSettingReadOnly;
91   }
92
93   /** <p>Returns whether the generated files are created in read-only mode.</p>
94    */

95   public boolean isSettingReadOnly() {
96     return settingReadOnly;
97   }
98
99   /** <p>By default the JavaSourceFactory will only overwrite existing
100    * files only, if they have different content. If the overwriteForced property is
101    * set to true, existing files will always be overwritten.</p>
102    * @see #isOverwriteForced()
103    */

104   public void setOverwriteForced(boolean pOverwriteForced) {
105     overwriteForced = pOverwriteForced;
106   }
107
108   /** <p>By default the JavaSourceFactory will only overwrite existing
109    * files, if they have different content. If the overwriteForced property is
110    * set to true, existing files will always be overwritten.</p>
111    * @see #setOverwriteForced(boolean)
112    */

113   public boolean isOverwriteForced() {
114     return overwriteForced;
115   }
116
117     /** <p>Creates a new instance of JavaSource with the given
118      * name and default protection.</p>
119      */

120     public JavaSource newJavaSource(JavaQName pName) {
121         return newJavaSource(pName, JavaSource.DEFAULT_PROTECTION);
122     }
123
124     /** <p>Creates a new instance of JavaSource with the given
125      * name and protection.</p>
126      */

127     public JavaSource newJavaSource(JavaQName pName, JavaSource.Protection pProtection) {
128         if (sources.containsKey(pName)) {
129             throw new IllegalStateException JavaDoc("The class " + pName + " has already been created.");
130         }
131         JavaSource result = new JavaSource(this, pName, pProtection);
132         sources.put(pName, result);
133         return result;
134     }
135
136     /** <p>Creates a new instance of JavaSource with the given
137      * name and protection. Shortcut for
138      * <code>newJavaSource(pName, JavaSource.Protection.valueOf(pProtection))</code>.</p>
139      */

140     public JavaSource newJavaSource(JavaQName pName, String JavaDoc pProtection) {
141         return newJavaSource(pName, JavaSource.Protection.valueOf(pProtection));
142     }
143
144   /** <p>Returns an iterator to the generated classes.</p>
145    */

146   public Iterator JavaDoc getJavaSources() {
147     return sources.values().iterator();
148   }
149
150   /** <p>Returns an iterator to the generated text files.</p>
151    */

152   public Iterator JavaDoc getTextFiles() {
153     return files.iterator();
154   }
155
156   /** <p>Returns the generated class with the given name or null, if
157    * no such class has been generated.</p>
158    */

159   public JavaSource getJavaSource(JavaQName pName) {
160     return (JavaSource) sources.get(pName);
161   }
162
163   /** <p>Returns the text file with the given name or null, if no such
164    * text file has been generated.</p>
165    */

166   public TextFile getTextFile(String JavaDoc pPackageName, String JavaDoc pFileName) {
167     for (Iterator JavaDoc iter = files.iterator(); iter.hasNext(); ) {
168       TextFile textFile = (TextFile) iter.next();
169       if (textFile.getPackageName().equals(pPackageName) && textFile.getFileName().equals(pFileName)) {
170         return textFile;
171       }
172     }
173     return null;
174   }
175
176   /** <p>Given a package name and a base directory, returns the package
177    * directory.</p>
178    *
179    * @param pBaseDir The base directory, where to create sources;
180    * may be null (current directory).
181    * @return Package directory; null is a valid value and indicates
182    * the current directory.
183    */

184   public File JavaDoc getPackageDirectory(File JavaDoc pBaseDir, String JavaDoc pPackageName) {
185     if (pPackageName != null) {
186         for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(pPackageName, ".");
187              st.hasMoreTokens(); ) {
188            String JavaDoc dir = st.nextToken();
189            pBaseDir = new File JavaDoc(pBaseDir, dir);
190         }
191     }
192     return pBaseDir;
193   }
194
195   /** <p>Given a fully qualified name, returns the name of the
196    * corresponding Java file.</p>
197    */

198   public File JavaDoc getSourceFile(File JavaDoc pBaseDir, JavaQName pQName) {
199     if (pQName == null) {
200         throw new NullPointerException JavaDoc("The class name must not be null.");
201     }
202     File JavaDoc packageDirectory = getPackageDirectory(pBaseDir, pQName.getPackageName());
203     String JavaDoc name = pQName.getClassName();
204         int offset = name.indexOf('.');
205         if (offset != -1) {
206             throw new IllegalArgumentException JavaDoc("Source files must not be generated for inner classes: " + name);
207         }
208         offset = name.indexOf('.');
209         if (offset != -1) {
210             throw new IllegalArgumentException JavaDoc("Source files must not be generated for inner classes: " + name);
211         }
212         return new File JavaDoc(packageDirectory, name + ".java");
213   }
214
215     /** <p>Returns a location the given package, relative to the given
216      * base directory. For example, if you have the base
217      * directory <code>c:\temp</code> and the package
218      * <code>com.mycompany.demo</code>, this would yield
219      * new File("c:\temp\com\mycompany\demo").</p>
220      *
221      * @param pBaseDir The base directory or null for the current directory.
222      * @param pPackage The JavaSource being stored; null or the empty
223      * string for the root package
224      * @return Directory related to the package; this may be null, if
225      * the base directory was null and the package was the root
226      * package
227      */

228     public File JavaDoc getLocation(File JavaDoc pBaseDir, String JavaDoc pPackage) {
229         for (StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(pPackage, "."); st.hasMoreTokens(); ) {
230             pBaseDir = new File JavaDoc(pBaseDir, st.nextToken());
231         }
232         return pBaseDir;
233     }
234
235   /** <p>Returns a location for storing the JavaSource class, relative
236    * to the given base directory. For example, if you have the base
237    * directory <code>c:\temp</code> and the class <code>Sample</code>
238    * in package <code>com.mycompany.demo</code>, this would yield
239    * new File("c:\temp\com\mycompany\demo\Sample.java").</p>
240    *
241    * @param pBaseDir The base directory or null for the current directory.
242    * @param pJs The JavaSource being stored.
243    */

244   public File JavaDoc getLocation(File JavaDoc pBaseDir, JavaSource pJs) {
245         if (pJs.isInnerClass()) {
246             throw new IllegalArgumentException JavaDoc("Inner classes have no assigned location in the file system.");
247         }
248     return new File JavaDoc(getLocation(pBaseDir, pJs.getPackageName()),
249                      pJs.getClassName() + ".java");
250   }
251
252   /** <p>Returns a location for storing the TextFile, relative
253    * to the given base directory. For example, if you have the base
254    * directory <code>c:\temp</code> and the class <code>Sample</code>
255    * in package <code>com.mycompany.demo</code>, this would yield
256    * new File("c:\temp\com\mycompany\demo\Sample.java").</p>
257    *
258    * @param pBaseDir The base directory or null for the current directory.
259    * @param pTextFile The text file being created.
260    */

261   public File JavaDoc getLocation(File JavaDoc pBaseDir, TextFile pTextFile) {
262     return new File JavaDoc(getLocation(pBaseDir, pTextFile.getPackageName()), pTextFile.getFileName());
263   }
264
265
266   /** <p>Verifies whether the given Java source and the contents of the
267    * given file are identical.</p>
268    */

269   protected boolean isSameFile(JavaSource pJs, File JavaDoc pFile) throws IOException JavaDoc {
270      StringWriter JavaDoc sw = new StringWriter JavaDoc();
271      pJs.write(sw);
272      sw.close();
273      return isSameFile(sw.toString(), pFile);
274   }
275
276   /** <p>Verifies whether the given string and the contents of the given
277    * file are identical.</p>
278    */

279   protected boolean isSameFile(String JavaDoc pContents, File JavaDoc pFile) throws IOException JavaDoc {
280      Reader JavaDoc r = new FileReader JavaDoc(pFile);
281      StringWriter JavaDoc sw = new StringWriter JavaDoc();
282      char[] buffer = new char[4096];
283      for (;;) {
284         int len = r.read(buffer);
285         if (len == -1) {
286            break;
287         } else if (len > 0) {
288            sw.write(buffer, 0, len);
289         }
290      }
291      return isSameFile(pContents, sw.toString());
292   }
293
294   /** <p>Verifies whether the given strings are identical.</p>
295    */

296   protected boolean isSameFile(String JavaDoc pContents1, String JavaDoc pContents2) {
297      return pContents1.equals(pContents2);
298   }
299
300   /** <p>Actually creates a file with the given name.</p>
301    */

302   protected void writeFile(File JavaDoc pFile, JavaSource pJs) throws IOException JavaDoc {
303     final String JavaDoc mName = "writeFile(File,JavaSource)";
304     File JavaDoc p = pFile.getParentFile();
305     if (p != null && !p.exists()) {
306       getLogger().fine(mName, "Creating directory " + p);
307       p.mkdirs();
308     }
309
310     if (isOverwriteForced() || !pFile.exists() || !isSameFile(pJs, pFile)) {
311       getLogger().fine(mName, "Creating " + pFile);
312       Writer JavaDoc w = new BufferedWriter JavaDoc(new FileWriter JavaDoc(pFile), 4096);
313       pJs.write(w);
314       w.close();
315       if (isSettingReadOnly()) {
316         pFile.setReadOnly();
317       }
318     } else {
319         getLogger().fine(mName, "Uptodate: " + pFile);
320     }
321   }
322
323   /** <p>Actually creates a file with the given name.</p>
324    */

325   protected void writeFile(File JavaDoc pFile, String JavaDoc pContents) throws IOException JavaDoc {
326     final String JavaDoc mName = "writeFile(File,String)";
327     File JavaDoc p = pFile.getParentFile();
328     if (p != null && !p.exists()) {
329       getLogger().fine(mName, "Creating directory " + p);
330       p.mkdirs();
331     }
332
333     if (isOverwriteForced() || !pFile.exists() || !isSameFile(pContents, pFile)) {
334       getLogger().fine(mName, "Creating " + pFile);
335       Writer JavaDoc w = new BufferedWriter JavaDoc(new FileWriter JavaDoc(pFile), 4096);
336       w.write(pContents);
337       w.close();
338       if (isSettingReadOnly()) {
339         pFile.setReadOnly();
340       }
341     } else {
342       getLogger().fine(mName, "Uptodate: " + pFile);
343     }
344   }
345
346   /** <p>Writes the given JavaSource class to the file system,
347    * relative to the given base directory.</p>
348    * @param pBaseDir The base directory or null for the current directory.
349    * @param pJs The JavaSource being stored.
350    * @see JavaSource#write(Writer)
351    */

352   public void write(File JavaDoc pBaseDir, JavaSource pJs) throws IOException JavaDoc {
353     writeFile(getLocation(pBaseDir, pJs), pJs);
354   }
355
356   /** <p>Writes the given text file to the file system, relative to the
357    * given base directory.</p>
358    * @param pBaseDir The base directory or null for the current directory.
359    * @param pFile The text file being stored.
360    * @see JavaSource#write(Writer)
361    */

362   public void write(File JavaDoc pBaseDir, TextFile pFile) throws IOException JavaDoc {
363     writeFile(getLocation(pBaseDir, pFile), pFile.getContents());
364   }
365
366     /** <p>Writes all JavaSource classes to the FileSystem, relative to the
367      * given base directory.</p>
368      * @param pBaseDir The base directory or null for the current directory.
369      */

370     public void write(File JavaDoc pBaseDir) throws IOException JavaDoc {
371         for (Iterator JavaDoc iter = getJavaSources(); iter.hasNext(); ) {
372             write(pBaseDir, (JavaSource) iter.next());
373         }
374         for (Iterator JavaDoc iter = getTextFiles(); iter.hasNext(); ) {
375           write(pBaseDir, (TextFile) iter.next());
376         }
377     }
378
379   /** <p>Creates a new text file.</p>
380    */

381   public TextFile newTextFile(String JavaDoc pPackageName, String JavaDoc pFileName) {
382     for (Iterator JavaDoc iter = files.iterator(); iter.hasNext(); ) {
383       TextFile f = (TextFile) iter.next();
384       if (f.getPackageName().equals(pPackageName) && f.getFileName().equals(pFileName)) {
385         throw new IllegalStateException JavaDoc("A file named " + pFileName + " in package " + pPackageName + " already exists.");
386       }
387     }
388     for (Iterator JavaDoc iter = sources.keySet().iterator(); iter.hasNext(); ) {
389       JavaQName qName = (JavaQName) iter.next();
390       if (qName.getPackageName().equals(pPackageName) && (qName.getClassName() + ".java").equals(pFileName)) {
391         throw new IllegalStateException JavaDoc("A Java source file names " + pFileName + " in package " + pPackageName + " already exists.");
392       }
393     }
394
395     TextFile result = new TextFileImpl(pPackageName, pFileName);
396     files.add(result);
397     return result;
398   }
399 }
400
Popular Tags