KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > formatter > CodeFormatterApplication


1 /*******************************************************************************
2  * Copyright (c) 2004 Ben Konrath <ben@bagu.org>
3  * Copyright (c) 2006 Red Hat Incorporated
4  * Copyright (c) 2007 IBM Corporation and others
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * Ben Konrath <ben@bagu.org> - initial implementation
12  * Red Hat Incorporated - improvements based on comments from JDT developers
13  * IBM Corporation - Code review and integration
14  *******************************************************************************/

15 package org.eclipse.jdt.core.formatter;
16
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.BufferedWriter JavaDoc;
19 import java.io.File JavaDoc;
20 import java.io.FileInputStream JavaDoc;
21 import java.io.FileWriter JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.text.MessageFormat JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Properties JavaDoc;
27
28 import org.eclipse.equinox.app.IApplication;
29 import org.eclipse.equinox.app.IApplicationContext;
30 import org.eclipse.jdt.core.ToolFactory;
31 import org.eclipse.jdt.internal.core.util.Util;
32 import org.eclipse.jface.text.BadLocationException;
33 import org.eclipse.jface.text.Document;
34 import org.eclipse.jface.text.IDocument;
35 import org.eclipse.osgi.util.NLS;
36 import org.eclipse.text.edits.TextEdit;
37
38 /**
39  * Implements an Eclipse Application for org.eclipse.jdt.core.JavaCodeFormatter.
40  *
41  * There are a couple improvments that could be made: 1. Make a list of all the
42  * files first so that a file does not get formatted twice. 2. Use a text based
43  * progress monitor for output.
44  * <p>
45  * This class is not intended to be instantiated or subclassed by clients.
46  * </p>
47  *
48  * @author Ben Konrath <bkonrath@redhat.com>
49  * @since 3.2
50  */

51 public class CodeFormatterApplication implements IApplication {
52
53     /**
54      * Deals with the messages in the properties file (cut n' pasted from a
55      * generated class).
56      */

57     private final static class Messages extends NLS {
58         private static final String JavaDoc BUNDLE_NAME = "org.eclipse.jdt.core.formatter.messages";//$NON-NLS-1$
59

60         public static String JavaDoc CommandLineConfigFile;
61
62         public static String JavaDoc CommandLineDone;
63
64         public static String JavaDoc CommandLineErrorConfig;
65
66         public static String JavaDoc CommandLineErrorFile;
67
68         public static String JavaDoc CommandLineErrorFileDir;
69
70         public static String JavaDoc CommandLineErrorQuietVerbose;
71         
72         public static String JavaDoc CommandLineErrorNoConfigFile;
73
74         public static String JavaDoc CommandLineFormatting;
75
76         public static String JavaDoc CommandLineStart;
77
78         public static String JavaDoc CommandLineUsage;
79
80         public static String JavaDoc ConfigFileReadingError;
81
82         public static String JavaDoc FormatProblem;
83
84         public static String JavaDoc CaughtException;
85
86         public static String JavaDoc ExceptionSkip;
87
88         static {
89             NLS.initializeMessages(BUNDLE_NAME, Messages.class);
90         }
91
92         /**
93          * Bind the given message's substitution locations with the given string
94          * values.
95          *
96          * @param message
97          * the message to be manipulated
98          * @return the manipulated String
99          */

100         public static String JavaDoc bind(String JavaDoc message) {
101             return bind(message, null);
102         }
103
104         /**
105          * Bind the given message's substitution locations with the given string
106          * values.
107          *
108          * @param message
109          * the message to be manipulated
110          * @param binding
111          * the object to be inserted into the message
112          * @return the manipulated String
113          */

114         public static String JavaDoc bind(String JavaDoc message, Object JavaDoc binding) {
115             return bind(message, new Object JavaDoc[] {
116                 binding
117             });
118         }
119
120         /**
121          * Bind the given message's substitution locations with the given string
122          * values.
123          *
124          * @param message
125          * the message to be manipulated
126          * @param binding1
127          * An object to be inserted into the message
128          * @param binding2
129          * A second object to be inserted into the message
130          * @return the manipulated String
131          */

132         public static String JavaDoc bind(String JavaDoc message, Object JavaDoc binding1, Object JavaDoc binding2) {
133             return bind(message, new Object JavaDoc[] {
134                     binding1, binding2
135             });
136         }
137
138         /**
139          * Bind the given message's substitution locations with the given string
140          * values.
141          *
142          * @param message
143          * the message to be manipulated
144          * @param bindings
145          * An array of objects to be inserted into the message
146          * @return the manipulated String
147          */

148         public static String JavaDoc bind(String JavaDoc message, Object JavaDoc[] bindings) {
149             return MessageFormat.format(message, bindings);
150         }
151     }
152
153     private static final String JavaDoc ARG_CONFIG = "-config"; //$NON-NLS-1$
154

155     private static final String JavaDoc ARG_HELP = "-help"; //$NON-NLS-1$
156

157     private static final String JavaDoc ARG_QUIET = "-quiet"; //$NON-NLS-1$
158

159     private static final String JavaDoc ARG_VERBOSE = "-verbose"; //$NON-NLS-1$
160

161     private String JavaDoc configName;
162
163     private Map JavaDoc options = null;
164
165     private static final String JavaDoc PDE_LAUNCH = "-pdelaunch"; //$NON-NLS-1$
166

167     private boolean quiet = false;
168
169     private boolean verbose = false;
170
171     /**
172      * Display the command line usage message.
173      */

174     private void displayHelp() {
175         System.out.println(Messages.bind(Messages.CommandLineUsage));
176     }
177
178     private void displayHelp(String JavaDoc message) {
179         System.err.println(message);
180         System.out.println();
181         displayHelp();
182     }
183
184     /**
185      * Recursively format the Java source code that is contained in the
186      * directory rooted at dir.
187      */

188     private void formatDirTree(File JavaDoc dir, CodeFormatter codeFormatter) {
189
190         File JavaDoc[] files = dir.listFiles();
191         if (files == null)
192             return;
193
194         for (int i = 0; i < files.length; i++) {
195             File JavaDoc file = files[i];
196             if (file.isDirectory()) {
197                 formatDirTree(file, codeFormatter);
198             } else if (Util.isJavaLikeFileName(file.getPath())) {
199                 formatFile(file, codeFormatter);
200             }
201         }
202     }
203
204     /**
205      * Format the given Java source file.
206      */

207     private void formatFile(File JavaDoc file, CodeFormatter codeFormatter) {
208         IDocument doc = new Document();
209         try {
210             // read the file
211
if (this.verbose) {
212                 System.out.println(Messages.bind(Messages.CommandLineFormatting, file.getAbsolutePath()));
213             }
214             String JavaDoc contents = new String JavaDoc(org.eclipse.jdt.internal.compiler.util.Util.getFileCharContent(file, null));
215             // format the file (the meat and potatoes)
216
doc.set(contents);
217             TextEdit edit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, contents, 0, contents.length(), 0, null);
218             if (edit != null) {
219                 edit.apply(doc);
220             } else {
221                 System.err.println(Messages.bind(Messages.FormatProblem, file.getAbsolutePath()));
222                 return;
223             }
224
225             // write the file
226
final BufferedWriter JavaDoc out = new BufferedWriter JavaDoc(new FileWriter JavaDoc(file));
227             try {
228                 out.write(doc.get());
229                 out.flush();
230             } finally {
231                 try {
232                     out.close();
233                 } catch (IOException JavaDoc e) {
234                     /* ignore */
235                 }
236             }
237         } catch (IOException JavaDoc e) {
238             String JavaDoc errorMessage = Messages.bind(Messages.CaughtException, "IOException", e.getLocalizedMessage()); //$NON-NLS-1$
239
Util.log(e, errorMessage);
240             System.err.println(Messages.bind(Messages.ExceptionSkip ,errorMessage));
241         } catch (BadLocationException e) {
242             String JavaDoc errorMessage = Messages.bind(Messages.CaughtException, "BadLocationException", e.getLocalizedMessage()); //$NON-NLS-1$
243
Util.log(e, errorMessage);
244             System.err.println(Messages.bind(Messages.ExceptionSkip ,errorMessage));
245         }
246     }
247
248     private File JavaDoc[] processCommandLine(String JavaDoc[] argsArray) {
249
250         ArrayList JavaDoc args = new ArrayList JavaDoc();
251         for (int i = 0, max = argsArray.length; i < max; i++) {
252             args.add(argsArray[i]);
253         }
254         int index = 0;
255         final int argCount = argsArray.length;
256
257         final int DEFAULT_MODE = 0;
258         final int CONFIG_MODE = 1;
259         
260         int mode = DEFAULT_MODE;
261         final int INITIAL_SIZE = 1;
262         int fileCounter = 0;
263         
264         File JavaDoc[] filesToFormat = new File JavaDoc[INITIAL_SIZE];
265
266         loop: while (index < argCount) {
267             String JavaDoc currentArg = argsArray[index++];
268
269             switch(mode) {
270                 case DEFAULT_MODE :
271                     if (PDE_LAUNCH.equals(currentArg)) {
272                         continue loop;
273                     }
274                     if (ARG_HELP.equals(currentArg)) {
275                         displayHelp();
276                         return null;
277                     }
278                     if (ARG_VERBOSE.equals(currentArg)) {
279                         this.verbose = true;
280                         continue loop;
281                     }
282                     if (ARG_QUIET.equals(currentArg)) {
283                         this.quiet = true;
284                         continue loop;
285                     }
286                     if (ARG_CONFIG.equals(currentArg)) {
287                         mode = CONFIG_MODE;
288                         continue loop;
289                     }
290                     // the current arg should be a file or a directory name
291
File JavaDoc file = new File JavaDoc(currentArg);
292                     if (file.exists()) {
293                         if (filesToFormat.length == fileCounter) {
294                             System.arraycopy(filesToFormat, 0, (filesToFormat = new File JavaDoc[fileCounter * 2]), 0, fileCounter);
295                         }
296                         filesToFormat[fileCounter++] = file;
297                     } else {
298                         displayHelp(Messages.bind(Messages.CommandLineErrorFile, currentArg));
299                         return null;
300                     }
301                     break;
302                 case CONFIG_MODE :
303                     this.configName = currentArg;
304                     this.options = readConfig(currentArg);
305                     if (this.options == null) {
306                         displayHelp(Messages.bind(Messages.CommandLineErrorConfig, currentArg));
307                         return null;
308                     }
309                     mode = DEFAULT_MODE;
310                     continue loop;
311             }
312         }
313
314         if (mode == CONFIG_MODE || this.options == null) {
315             displayHelp(Messages.bind(Messages.CommandLineErrorNoConfigFile));
316             return null;
317         }
318         if (this.quiet && this.verbose) {
319             displayHelp(
320                 Messages.bind(
321                     Messages.CommandLineErrorQuietVerbose,
322                     new String JavaDoc[] { ARG_QUIET, ARG_VERBOSE }
323                 ));
324             return null;
325         }
326         if (fileCounter == 0) {
327             displayHelp(Messages.bind(Messages.CommandLineErrorFileDir));
328             return null;
329         }
330         if (filesToFormat.length != fileCounter) {
331             System.arraycopy(filesToFormat, 0, (filesToFormat = new File JavaDoc[fileCounter]), 0, fileCounter);
332         }
333         return filesToFormat;
334     }
335
336     /**
337      * Return a Java Properties file representing the options that are in the
338      * specified config file.
339      */

340     private Properties JavaDoc readConfig(String JavaDoc filename) {
341         BufferedInputStream JavaDoc stream = null;
342         try {
343             stream = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(new File JavaDoc(filename)));
344             final Properties JavaDoc formatterOptions = new Properties JavaDoc();
345             formatterOptions.load(stream);
346             return formatterOptions;
347         } catch (IOException JavaDoc e) {
348             Util.log(e, Messages.bind(Messages.ConfigFileReadingError));
349         } finally {
350             if (stream != null) {
351                 try {
352                     stream.close();
353                 } catch (IOException JavaDoc e) {
354                     /* ignore */
355                 }
356             }
357         }
358         return null;
359     }
360
361     /**
362      * Runs the Java code formatter application
363      */

364     public Object JavaDoc start(IApplicationContext context) throws Exception JavaDoc {
365         File JavaDoc[] filesToFormat = processCommandLine((String JavaDoc[]) context.getArguments().get(IApplicationContext.APPLICATION_ARGS));
366
367         if (filesToFormat == null) {
368             return IApplication.EXIT_OK;
369         }
370
371         if (!this.quiet) {
372             if (this.configName != null) {
373                 System.out.println(Messages.bind(Messages.CommandLineConfigFile, this.configName));
374             }
375             System.out.println(Messages.bind(Messages.CommandLineStart));
376         }
377
378         final CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(this.options);
379         // format the list of files and/or directories
380
for (int i = 0, max = filesToFormat.length; i < max; i++) {
381             final File JavaDoc file = filesToFormat[i];
382             if (file.isDirectory()) {
383                 formatDirTree(file, codeFormatter);
384             } else if (Util.isJavaLikeFileName(file.getPath())) {
385                 formatFile(file, codeFormatter);
386             }
387         }
388         if (!this.quiet) {
389             System.out.println(Messages.bind(Messages.CommandLineDone));
390         }
391
392         return IApplication.EXIT_OK;
393     }
394     public void stop() {
395         // do nothing
396
}
397 }
398
Popular Tags