1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools;
24  
25  import com.liferay.portal.kernel.util.ClassUtil;
26  import com.liferay.portal.kernel.util.StringMaker;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.StringUtil;
29  import com.liferay.util.FileUtil;
30  import com.liferay.util.ListUtil;
31  
32  import java.io.BufferedReader;
33  import java.io.File;
34  import java.io.IOException;
35  import java.io.StringReader;
36  import java.util.ArrayList;
37  import java.util.Collections;
38  import java.util.List;
39  import java.util.Set;
40  
41  import org.apache.tools.ant.DirectoryScanner;
42  
43  /**
44   * <a href="SourceFormatter.java.html"><b><i>View Source</i></b></a>
45   *
46   * @author Brian Wing Shun Chan
47   *
48   */
49  public class SourceFormatter {
50  
51      public static void main(String[] args) {
52          SourceFormatter sf = new SourceFormatter();
53  
54          sf.formatJava();
55          sf.formatJSP();
56      }
57  
58      public void formatJava() {
59          try {
60              String basedir = "../";
61  
62              List list = new ArrayList();
63  
64              DirectoryScanner ds = new DirectoryScanner();
65              ds.setIncludes(
66                  new String[] {
67                      "**\\*.java"
68                  });
69              ds.setExcludes(
70                  new String[] {
71                      "**\\classes\\*", "**\\jsp\\*", "**\\tmp\\**",
72                      "**\\EARXMLBuilder.java", "**\\EJBXMLBuilder.java",
73                      "**\\JSMin.java", "**\\PropsUtil.java",
74                      "**\\InstanceWrapperBuilder.java",
75                      "**\\ServiceBuilder.java", "**\\SourceFormatter.java",
76                      "**\\UserAttributes.java", "**\\WebKeys.java",
77                      "**\\*_IW.java", "**\\XHTMLComplianceFormatter.java",
78                      "**\\portal-service\\**\\model\\*Model.java",
79                      "**\\portal-service\\**\\model\\*Soap.java",
80                      "**\\model\\impl\\*ModelImpl.java",
81                      "**\\portal\\service\\**", "**\\portal-client\\**",
82                      "**\\portlet\\**\\service\\**", "**\\tools\\ext_tmpl\\**",
83                      "**\\util-wsrp\\**"
84                  });
85              ds.setBasedir(basedir);
86              ds.scan();
87  
88              list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
89  
90              ds = new DirectoryScanner();
91              ds.setIncludes(
92                  new String[] {
93                      "**\\service\\http\\*HttpTest.java",
94                      "**\\service\\http\\*SoapTest.java",
95                      "**\\service\\impl\\*.java", "**\\service\\jms\\*.java",
96                      "**\\service\\permission\\*.java",
97                      "**\\service\\persistence\\BasePersistence.java",
98                      "**\\service\\persistence\\*Finder.java",
99                      "**\\portal-service\\**\\liferay\\counter\\**.java",
100                     "**\\portal-service\\**\\liferay\\documentlibrary\\**.java",
101                     "**\\portal-service\\**\\liferay\\lock\\**.java",
102                     "**\\portal-service\\**\\liferay\\mail\\**.java",
103                     "**\\util-bridges\\**\\*.java"
104                 });
105             ds.setExcludes(
106                 new String[] {
107                     "**\\tools\\ext_tmpl\\**", "**\\*_IW.java",
108                 });
109             ds.setBasedir(basedir);
110             ds.scan();
111 
112             list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
113 
114             ds = new DirectoryScanner();
115             ds.setIncludes(
116                 new String[] {
117                     "**\\test\\src\\**\\*.java",
118                 });
119             ds.setBasedir(basedir);
120             ds.scan();
121 
122             list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
123 
124             String copyright = FileUtil.read("../copyright.txt");
125 
126             String[] files = (String[])list.toArray(new String[list.size()]);
127 
128             for (int i = 0; i < files.length; i++) {
129                 File file = new File(basedir + files[i]);
130 
131                 String content = FileUtil.read(file);
132 
133                 String className = file.getName();
134                 className = className.substring(0, className.length() - 5);
135 
136                 String packageDir = files[i];
137 
138                 int packageDirX = packageDir.indexOf(
139                     File.separator + "src" + File.separator);
140                 int packageDirY = packageDir.lastIndexOf(File.separator);
141 
142                 packageDir = packageDir.substring(packageDirX + 5, packageDirY);
143                 packageDir = StringUtil.replace(
144                     packageDir, File.separator, StringPool.PERIOD);
145 
146                 if (packageDir.endsWith(".model")) {
147                     if (content.indexOf(
148                             "extends " + className + "Model {") != -1) {
149 
150                         continue;
151                     }
152                 }
153 
154                 String newContent = _formatJavaContent(files[i], content);
155 
156                 if (newContent.indexOf("$\n */") != -1) {
157                     System.out.println("*: " + files[i]);
158 
159                     newContent = StringUtil.replace(
160                         newContent, "$\n */", "$\n *\n */");
161                 }
162 
163                 if (newContent.indexOf(copyright) == -1) {
164                     System.out.println("(c): " + files[i]);
165                 }
166 
167                 if (newContent.indexOf(className + ".java.html") == -1) {
168                     System.out.println("Java2HTML: " + files[i]);
169                 }
170 
171                 // Sort imports
172 
173                 if (newContent.indexOf("import ") != -1) {
174                     int x = newContent.indexOf("import ");
175 
176                     int y = newContent.indexOf("{", x);
177                     y = newContent.substring(0, y).lastIndexOf(";") + 1;
178 
179                     String imports =
180                         _formatImports(newContent.substring(x, y));
181 
182                     newContent =
183                         newContent.substring(0, x) +
184                         imports +
185                         newContent.substring(y + 1, newContent.length());
186                 }
187 
188                 // Check for unused imports
189 
190                 if (newContent.indexOf("import ") != -1) {
191                     Set classes = ClassUtil.getClasses(file);
192 
193                     // Some classes are not picked up properly
194 
195                     classes.add("_getMarkup");
196                     classes.add("_performBlockingInteraction");
197 
198                     int x = newContent.indexOf("import ");
199 
200                     int y = newContent.indexOf("{", x);
201                     y = newContent.substring(0, y).lastIndexOf(";") + 1;
202 
203                     String imports = newContent.substring(x, y);
204 
205                     StringMaker sm = new StringMaker();
206 
207                     BufferedReader br =
208                         new BufferedReader(new StringReader(imports));
209 
210                     String line = null;
211 
212                     while ((line = br.readLine()) != null) {
213                         if (line.indexOf("import ") != -1) {
214                             int importX = line.indexOf(" ");
215                             int importY = line.lastIndexOf(".");
216 
217                             String importPackage =
218                                 line.substring(importX + 1, importY);
219                             String importClass =
220                                 line.substring(importY + 1, line.length() - 1);
221 
222                             if (!packageDir.equals(importPackage)) {
223                                 if (!importClass.equals("*")) {
224                                     if (!classes.contains(importClass)) {
225                                         System.out.println(
226                                             "Unused imports: " + importClass +
227                                             " " + files[i]);
228                                     }
229                                     else {
230                                         sm.append(line).append("\n");
231                                     }
232                                 }
233                                 else {
234                                     sm.append(line).append("\n");
235                                 }
236                             }
237                         }
238                     }
239 
240                     imports = _formatImports(sm.toString());
241 
242                     newContent =
243                         newContent.substring(0, x) +
244                         imports +
245                         newContent.substring(y + 1, newContent.length());
246                 }
247 
248                 if (newContent.indexOf(";\n/**") != -1) {
249                     newContent = StringUtil.replace(
250                         newContent,
251                         ";\n/**",
252                         ";\n\n/**");
253                 }
254 
255                 if (newContent.indexOf("\t/*\n\t *") != -1) {
256                     newContent = StringUtil.replace(
257                         newContent,
258                         "\t/*\n\t *",
259                         "\t/**\n\t *");
260                 }
261 
262                 if (newContent.indexOf("if(") != -1) {
263                     newContent = StringUtil.replace(
264                         newContent,
265                         "if(",
266                         "if (");
267                 }
268 
269                 if (newContent.indexOf("while(") != -1) {
270                     newContent = StringUtil.replace(
271                         newContent,
272                         "while(",
273                         "while (");
274                 }
275 
276                 if (newContent.indexOf("\n\n\n") != -1) {
277                     newContent = StringUtil.replace(
278                         newContent,
279                         "\n\n\n",
280                         "\n\n");
281                 }
282 
283                 if  (newContent.indexOf("*/\npackage ") != -1) {
284                     System.out.println("package: " + files[i]);
285                 }
286 
287                 if (!newContent.endsWith("\n\n}") &&
288                     !newContent.endsWith("{\n}")) {
289 
290                     System.out.println("}: " + files[i]);
291                 }
292 
293                 if ((newContent != null) && !content.equals(newContent)) {
294                     FileUtil.write(file, newContent);
295 
296                     System.out.println(file.toString());
297                 }
298             }
299         }
300         catch (Exception e) {
301             e.printStackTrace();
302         }
303     }
304 
305     public void formatJSP() {
306         try {
307             String basedir = "../";
308 
309             List list = new ArrayList();
310 
311             DirectoryScanner ds = new DirectoryScanner();
312             ds.setIncludes(
313                 new String[] {
314                     "**\\*.jsp", "**\\*.jspf", "**\\*.vm"
315                 });
316             ds.setExcludes(
317                 new String[] {
318                     "**\\null.jsp", "**\\tmp\\**"
319                 });
320             ds.setBasedir(basedir);
321             ds.scan();
322 
323             list.addAll(ListUtil.fromArray(ds.getIncludedFiles()));
324 
325             String copyright = FileUtil.read("../copyright.txt");
326 
327             String[] files = (String[])list.toArray(new String[list.size()]);
328 
329             for (int i = 0; i < files.length; i++) {
330                 File file = new File(basedir + files[i]);
331 
332                 String content = FileUtil.read(file, true);
333                 String newContent = _formatJSPContent(files[i], content);
334 
335                 if (files[i].endsWith(".jsp")) {
336                     if (newContent.indexOf(copyright) == -1) {
337                         System.out.println("(c): " + files[i]);
338                     }
339                 }
340 
341                 if (newContent.indexOf("alert('<%= LanguageUtil.") != -1) {
342                     newContent = StringUtil.replace(newContent,
343                         "alert('<%= LanguageUtil.",
344                         "alert('<%= UnicodeLanguageUtil.");
345                 }
346 
347                 if (newContent.indexOf("alert(\"<%= LanguageUtil.") != -1) {
348                     newContent = StringUtil.replace(newContent,
349                         "alert(\"<%= LanguageUtil.",
350                         "alert(\"<%= UnicodeLanguageUtil.");
351                 }
352 
353                 if (newContent.indexOf("confirm('<%= LanguageUtil.") != -1) {
354                     newContent = StringUtil.replace(newContent,
355                         "confirm('<%= LanguageUtil.",
356                         "confirm('<%= UnicodeLanguageUtil.");
357                 }
358 
359                 if (newContent.indexOf("confirm(\"<%= LanguageUtil.") != -1) {
360                     newContent = StringUtil.replace(newContent,
361                         "confirm(\"<%= LanguageUtil.",
362                         "confirm(\"<%= UnicodeLanguageUtil.");
363                 }
364 
365                 if ((newContent != null) && !content.equals(newContent)) {
366                     FileUtil.write(file, newContent);
367 
368                     System.out.println(file.toString());
369                 }
370             }
371         }
372         catch (Exception e) {
373             e.printStackTrace();
374         }
375     }
376 
377     private String _formatImports(String imports) throws IOException {
378 
379         // Ignore if there are comments
380 
381         if ((imports.indexOf("/*") != -1) ||
382             (imports.indexOf("*/") != -1) ||
383             (imports.indexOf("//") != -1)) {
384             return imports + "\n";
385         }
386 
387         List importsList = new ArrayList();
388 
389         BufferedReader br =
390             new BufferedReader(new StringReader(imports));
391 
392         String line = null;
393 
394         while ((line = br.readLine()) != null) {
395             if (line.indexOf("import ") != -1) {
396                 if (!importsList.contains(line)) {
397                     importsList.add(line);
398                 }
399             }
400         }
401 
402         Collections.sort(importsList);
403 
404         StringMaker sm = new StringMaker();
405 
406         String temp = null;
407 
408         for (int i = 0; i < importsList.size(); i++) {
409             String s = (String)importsList.get(i);
410 
411             int pos = s.indexOf(".");
412             pos = s.indexOf(".", pos + 1);
413             if (pos == -1) {
414                 pos = s.indexOf(".");
415             }
416 
417             String packageLevel = s.substring(7, pos);
418 
419             if ((i != 0) && (!packageLevel.equals(temp))) {
420                 sm.append("\n");
421             }
422 
423             temp = packageLevel;
424 
425             sm.append(s).append("\n");
426         }
427 
428         return sm.toString();
429     }
430 
431     private String _formatJavaContent(String fileName, String content)
432         throws IOException {
433 
434         StringMaker sm = new StringMaker();
435 
436         BufferedReader br =
437             new BufferedReader(new StringReader(content));
438 
439         int lineCount = 0;
440 
441         String line = null;
442 
443         while ((line = br.readLine()) != null) {
444             lineCount++;
445 
446             if (line.trim().length() == 0) {
447                 line = StringPool.BLANK;
448             }
449 
450             line = StringUtil.trimTrailing(line);
451 
452             sm.append(line).append("\n");
453 
454             line = StringUtil.replace(line, "\t", "    ");
455 
456             if (((line.length() - 1) > 79) && !line.startsWith("import ")) {
457                 System.out.println("> 80: " + fileName + " " + lineCount);
458             }
459         }
460 
461         br.close();
462 
463         String newContent = sm.toString();
464 
465         if (newContent.endsWith("\n")) {
466             newContent = newContent.substring(0, newContent.length() -1);
467         }
468 
469         return newContent;
470     }
471 
472     private String _formatJSPContent(String fileName, String content)
473         throws IOException {
474 
475         StringMaker sm = new StringMaker();
476 
477         BufferedReader br =
478             new BufferedReader(new StringReader(content));
479 
480         int lineCount = 0;
481 
482         String line = null;
483 
484         while ((line = br.readLine()) != null) {
485             lineCount++;
486 
487             int x = line.indexOf("\"<%=");
488             int y = line.indexOf("%>\"", x);
489 
490             boolean hasTagLibrary = false;
491 
492             for (int i = 0; i < _TAG_LIBRARIES.length; i++) {
493                 if (line.indexOf("<" + _TAG_LIBRARIES[i] + ":") != -1) {
494                     hasTagLibrary = true;
495 
496                     break;
497                 }
498             }
499 
500             if ((x != -1) && (y != -1) && hasTagLibrary) {
501                 String regexp = line.substring(x, y + 3);
502 
503                 if (regexp.indexOf("\\\"") == -1) {
504                     regexp = regexp.substring(1, regexp.length() - 1);
505 
506                     if (regexp.indexOf("\"") != -1) {
507                         line =
508                             line.substring(0, x) + "'" + regexp + "'" +
509                                 line.substring(y + 3, line.length());
510                     }
511                 }
512             }
513 
514             if (line.trim().length() == 0) {
515                 line = StringPool.BLANK;
516             }
517 
518             line = StringUtil.trimTrailing(line);
519 
520             sm.append(line).append("\n");
521         }
522 
523         br.close();
524 
525         String newContent = sm.toString();
526 
527         if (newContent.endsWith("\n")) {
528             newContent = newContent.substring(0, newContent.length() -1);
529         }
530 
531         return newContent;
532     }
533 
534     private static final String[] _TAG_LIBRARIES = new String[] {
535         "c", "html", "jsp", "liferay-portlet", "liferay-security",
536         "liferay-theme", "liferay-ui", "liferay-util", "portlet", "struts",
537         "tiles"
538     };
539 
540 }