View Javadoc

1   package org.appfuse.tool;
2   
3   import java.io.File;
4   import java.io.FileNotFoundException;
5   import java.io.IOException;
6   import java.util.Iterator;
7   import java.util.Vector;
8   import java.util.regex.Matcher;
9   import java.util.regex.Pattern;
10  
11  import org.apache.commons.io.FileUtils;
12  import org.apache.maven.plugin.logging.Log;
13  import org.apache.maven.plugin.logging.SystemStreamLog;
14  import org.apache.tools.ant.BuildException;
15  import org.apache.tools.ant.DirectoryScanner;
16  import org.apache.tools.ant.types.FileSet;
17  
18  
19  /**
20   * This class is almost a complete copy of replacepackages
21   * by Ben Gill.  These utility methods can be used in the
22   * plugin to change package names of appfuse source
23   * contributions.  Liberties have been taken to make this
24   * open source code just work here. Some methods were removed
25   * and logging now uses SystemStreamLog from Apache (Maven)
26   *
27   * @author <a href="mailto:david@capehenrytech.com">David L. Whitehurst</a>
28   */
29  public class RenamePackages {
30  
31      static final boolean SAVE_FILE = true;
32      static final boolean DONT_SAVE_FILE = false;
33      boolean debug = false;
34      private String baseDir = "src"; // root
35      private String workBaseDir = "null"; // actually called null
36      private String existingPkgName = "org.appfuse"; // AppFuse
37      private String newPkgName;
38      private String existingPkgPath;
39      private String newPkgPath;
40      protected transient final Log log = new SystemStreamLog();
41  
42      StringBuffer logOutput = new StringBuffer();
43  
44      String[] invalidFileTypes = new String[]{"class", "jar", "jpg", "gif", "png", "ico"};
45  
46      private Vector filesets = new Vector();
47  
48      /**
49       * Constructor
50       */
51      public RenamePackages(String newPackage) {
52          this.newPkgName = newPackage;
53      }
54  
55      /**
56       * simple method to add filesets
57       *
58       * @param fileset
59       */
60      public void addFileset(FileSet fileset) {
61          filesets.add(fileset);
62      }
63  
64      /**
65       * Override the default set of invalid file types that will be moved to the
66       * new package structure.
67       * <p/>
68       * The invalidFileTypes must be a comma
69       * separated list of file extensions
70       * for example "class,jar,exe"
71       *
72       * @param invalidFileTypes
73       */
74      public void setInvalidFileTypes(String invalidFileTypes) {
75          this.invalidFileTypes = invalidFileTypes.split(",");
76  
77          if (debug) {
78              log.debug("default invalidFileTypes overriden with [" + invalidFileTypes
79                      + "]");
80          }
81      }
82  
83      /**
84       * Set the base directory. The base directory will be where the Task starts
85       * to recursively look for files with the given package name in it. This
86       * method will be called by ANT when it invokes the Task.
87       *
88       * @param baseDir
89       */
90      public void setBaseDir(String baseDir) {
91          if (!new File(baseDir.trim()).exists()) {
92              throw new ExceptionInInitializerError("Base dir [" + baseDir.trim()
93                      + "] does not exist");
94          }
95          this.baseDir = correctFileSeparators(baseDir.trim());
96          if (this.baseDir != null) {
97              if (this.baseDir.endsWith(File.separator)) {
98                  this.workBaseDir = this.baseDir.substring(0, this.baseDir
99                          .length())
100                         + ".work";
101             } else {
102                 this.workBaseDir = this.baseDir + ".work";
103             }
104 
105             if (debug) {
106                 log.debug("Set workBaseDir to [" + this.workBaseDir + "]");
107             }
108         }
109     }
110 
111     /**
112      * Validates the packagename
113      *
114      * @param packageName
115      * @throws ExceptionInInitializerError if the package name is invalid
116      */
117     private void validatePackageName(String packageName)
118             throws ExceptionInInitializerError {
119         if (packageName.indexOf("/") != -1) {
120             throw new ExceptionInInitializerError("packageName [" + packageName
121                     + "] is invalid because it contains slashes");
122         }
123         if (packageName.indexOf("\\") != -1) {
124             throw new ExceptionInInitializerError("packageName [" + packageName
125                     + "] is invalid because it contains slashes");
126         }
127     }
128 
129     /**
130      * Strips out start and end dots
131      *
132      * @param packageName
133      * @return package name without starting and ending dots
134      */
135     private String stripUnwantedDots(String packageName) {
136 
137         while (packageName.endsWith(".")) {
138             packageName = packageName.substring(0, packageName.length() - 1);
139         }
140         while (packageName.startsWith(".")) {
141             packageName = packageName.substring(1);
142         }
143 
144         if (debug) {
145             log.debug("returning stripped package name of [" + packageName + "]");
146         }
147 
148         return packageName;
149     }
150 
151     /**
152      * Set the existing package name. This will become the string that the Task
153      * looks to replace in the files look for files with the given package name
154      * in it. This method will be called by ANT when it invokes the Task.
155      *
156      * @param existingPkgName
157      */
158     public void setExistingPkgName(String existingPkgName) throws Exception {
159 
160         log.info("existingPkgName came in as [" + existingPkgName + "]");
161 
162         this.existingPkgName = stripUnwantedDots(existingPkgName.trim());
163         validatePackageName(this.existingPkgName);
164         if (this.existingPkgName.length() == 0) {
165             throw new Exception("Unsupported operation - cannot "
166                     + " repackage from empty package name as would "
167                     + " not know which imports to expand out");
168         }
169     }
170 
171     /**
172      * Set the new package name. This will become the package name and replace
173      * the existing package name in the source files. This method will be called
174      * by ANT when it invokes the Task.
175      *
176      * @param newPkgName
177      * @throws Exception
178      */
179     public void setNewPkgName(String newPkgName) throws Exception {
180         log.info("newPkgName came in as [" + newPkgName + "]");
181 
182         this.newPkgName = stripUnwantedDots(newPkgName.trim());
183         validatePackageName(this.newPkgName);
184         if (this.newPkgName.length() == 0) {
185             throw new Exception("Unimplemented operation");
186         }
187     }
188 
189     /**
190      * Set the package paths. Replace the . delimiter with the relevant file
191      * separator based on the o/s we are running on.
192      */
193     private void setPackagePaths() {
194         this.existingPkgPath = getPackagePath(existingPkgName);
195         this.newPkgPath = getPackagePath(newPkgName);
196 
197         if (debug) {
198             log.debug("Set existing package path as [" + existingPkgPath + "]");
199             log.debug("Set new package path as [" + newPkgPath + "]");
200         }
201     }
202 
203     /**
204      * Set the new package name. This will become the package name and replace
205      * the existing package name in the source files. This method will be called
206      * by ANT when it invokes the Task.
207      *
208      * @param pkgName
209      * @return path of the pkg name
210      */
211     private String getPackagePath(String pkgName) {
212         String[] pkgNames = pkgName.split("\\.");
213         String aPath = "";
214 
215         for (int i = 0; i < pkgNames.length; i++) {
216             if (aPath.length() != 0) {
217                 aPath += File.separator;
218             }
219 
220             aPath += pkgNames[i];
221         }
222         return aPath;
223     }
224 
225     /**
226      * Creates a new directory, if it does not exist already
227      *
228      * @param directoryName
229      */
230     private void createDirectory(String directoryName) {
231         File dir = new File(directoryName);
232 
233         if (!dir.exists()) {
234             if (dir.mkdirs()) {
235                 String message = "Created directory [" + directoryName + "]";
236 
237                 if (debug) {
238                     log.debug(message);
239                 }
240             } else {
241                 log.error("Failed to create directory [" + directoryName + "]");
242             }
243         }
244     }
245 
246     /*
247      * This method gets called recursively (mainly by itself) and walks through
248      * the directory structure looking for files with existingPkgPath in their
249      * fully qualified (absolute) names.
250      *
251      * If a file is found, then it is parsed for the existingPkgName and any
252      * instance of this string will be replaced by the newPkgName. The file is
253      * then saved back out in its new package directory.
254      *
255      * @param inDirName the directory to search
256      */
257     private void repackage(String inDirName, String inWorkDirName)
258             throws IOException {
259 
260         if (debug) {
261             log.debug("Inside repackage inDirName is [" + inDirName + "]");
262             log.debug("Inside repackage inWorkDirName is [" + inWorkDirName + "]");
263         }
264 
265         String[] files = new File(inDirName).list();
266 
267         if (files == null) {
268             return;
269         }
270 
271         if (debug) {
272             log.debug("There are [" + files.length + "] files in dir [" + inDirName
273                     + "]");
274         }
275 
276         for (int i = 0; i < files.length; i++) {
277             if (debug) {
278                 log.debug("file is [" + files[i] + "]");
279             }
280 
281             String fileName = inDirName + File.separator + files[i];
282             File aFile = new File(fileName);
283 
284             if (files[i].equals("CVS")) {
285                 if (debug) {
286                     log.debug("ignoring CVS dir");
287                 }
288             } else if (aFile.isDirectory()) {
289                 if (debug) {
290                     log.debug("Got a dir [" + fileName + "]");
291                 }
292 
293                 String newDirName = inDirName + File.separator + files[i];
294                 String newWorkDirName = inWorkDirName + File.separator
295                         + files[i];
296 
297                 if (isOldPackageDir(fileName)) {
298                     String newPath = convertOldPackageDirName(fileName);
299 
300                     if (debug) {
301                         log.debug("found old package dir [" + fileName + "] "
302                                 + "newPath is [" + newPath.toString() + "]");
303                     }
304                     createDirectory(newPath.toString());
305 
306                 } else {
307 
308                     // Replace existing baseDir
309                     String newPath = this.workBaseDir
310                             + fileName.substring(this.baseDir.length());
311 
312                     if (debug) {
313                         log.debug("found dir outside old package [" + fileName + "] "
314                                 + "newPath is [" + newPath + "]");
315                     }
316                     createDirectory(newPath);
317                 }
318 
319                 if (debug) {
320                     log.debug("Recursing with [" + newDirName + "]");
321                 }
322 
323                 repackage(newDirName, newWorkDirName);
324 
325             } else {
326                 // Normal file
327                 if (debug) {
328                     log.debug("Processing file [" + fileName + "] existingPkgPath is ["
329                             + existingPkgPath + "]");
330                 }
331 
332                 // Should we process this file at all or leave it?
333                 int existingPathIndexPos = fileName.indexOf(existingPkgPath);
334 
335                 if (existingPathIndexPos != -1) {
336                     // Normal file in old package structure
337                     if (debug) {
338                         log.debug("found file with existing package name ["
339                                 + fileName + "]");
340                     }
341 
342                     String newPath = convertOldPackageDirName(fileName
343                             .substring(0, fileName.lastIndexOf(File.separator)));
344                     String newFileName = newPath
345                             + fileName.substring(fileName
346                             .lastIndexOf(File.separator));
347 
348                     if (debug) {
349                         log.debug("creating directory [" + newPath + "]");
350                     }
351 
352                     createDirectory(newPath);
353 
354                     if (isValidFileType(fileName)) {
355                         String output = changePackageNamesInFile(fileName,
356                                 RenamePackages.DONT_SAVE_FILE);
357 
358                         if (debug) {
359                             log.debug("Saving file [" + fileName
360                                     + "] to new package directory ["
361                                     + newFileName + "]");
362                         }
363 
364                         toFile(newFileName, output);
365                     } else {
366                         if (debug) {
367                             log.debug("Renaming file non valid file type ["
368                                     + fileName + "]");
369                         }
370 
371                         if (!aFile.renameTo(new File(newFileName))) {
372                             log.error("Failed to rename file [" + fileName + "] to ["
373                                     + newFileName + "]");
374                         }
375                     }
376                 } else {
377                     // Normal file - not in old package structure
378 
379                     // Stip off existing baseDir
380                     String newFileName = this.workBaseDir
381                             + fileName.substring(this.baseDir.length());
382 
383                     if (aFile.renameTo(new File(newFileName))) {
384                         if (debug) {
385                             log.debug("Saved file [" + newFileName
386                                     + "] to new directory structure");
387                         }
388                     } else {
389                         log.error("Failed to rename file [" + fileName + "] to ["
390                                 + newFileName + "] to new directory structure");
391                     }
392                 }
393             }
394         }
395     }
396 
397     /*
398      * This method gets called recursively (mainly by itself) and walks through
399      * the directory structure looking for ANY valid files with existingPkgPath.
400      *
401      * If a file is found, then it is parsed then it is output for the caller to
402      * check.
403      *
404      * @param inDirName the directory to search
405      */
406     private void checkSummary(String inDirName)
407             throws IOException {
408         if (debug) {
409             log.debug("Inside checkSummary inDirName is [" + inDirName + "]");
410         }
411 
412         String[] files = new File(inDirName).list();
413 
414         if (files == null) {
415             return;
416         }
417 
418         if (debug) {
419             log.debug("There are [" + files.length + "] files in dir [" + inDirName + "]");
420         }
421 
422         for (String file : files) {
423 
424             if (debug) {
425                 log.debug("file is [" + file + "]");
426             }
427 
428             String fileName = inDirName + File.separator + file;
429             File aFile = new File(fileName);
430 
431             if (aFile.isDirectory()) {
432 
433                 if (debug) {
434                     log.debug("Got a dir [" + fileName + "]");
435                 }
436 
437                 String newDirName = inDirName + File.separator + file;
438 
439                 if (debug) {
440                     log.debug("Recursing with [" + newDirName + "]");
441                 }
442 
443                 checkSummary(newDirName);
444             } else {
445                 // Normal file
446                 if (debug) {
447                     log.debug("Checking file [" + fileName + "] existingPkgPath is ["
448                             + existingPkgPath + "]");
449                 }
450 
451                 if (isValidFileType(fileName)) {
452                     if (hasFileOldPathOrPkg(fileName)) {
453                         if (debug) {
454                             log.debug("File [" + fileName + "] still has old pkg [" + existingPkgPath + "]");
455                         }
456                     }
457                 }
458             }
459         }
460     }
461 
462 
463     private boolean matches(String patternStr, String fileContents) {
464 
465         Pattern pattern = Pattern.compile(patternStr);
466         Matcher matcher = pattern.matcher(fileContents);
467         return matcher.matches();
468     }
469 
470 
471     private boolean hasFileOldPathOrPkg(String fileName) {
472 
473         try {
474             String fileContents = fromFile(fileName);
475 
476             String patternStr = escape(existingPkgPath);
477 
478             if (matches(patternStr, fileContents)) {
479                 return true;
480             }
481 
482             patternStr = getUnixPath(existingPkgPath);
483             patternStr = escape(patternStr);
484 
485             if (matches(patternStr, fileContents)) {
486                 return true;
487             }
488 
489             patternStr = getWindowsPath(existingPkgPath);
490             patternStr = escape(patternStr);
491 
492             return matches(patternStr, fileContents);
493 
494         } catch (IOException e) {
495             log.error("Error loading fileContents in hasFileOldPathOrPkg [" + e.getMessage() + "]");
496             return false;
497         }
498 
499     }
500 
501     private String convertOldPackageDirName(String dirName) {
502         // Need to create new package directory
503         int startExistingPathIndexPos = dirName.indexOf(existingPkgPath);
504         int endExistingPathIndexPos = startExistingPathIndexPos
505                 + existingPkgPath.length();
506 
507         StringBuffer newPath = new StringBuffer();
508         newPath.append(this.workBaseDir);
509 
510         // Get the front bit
511         if (debug) {
512             log.debug("startExistingPathIndexPos is [" + startExistingPathIndexPos + "]");
513             log.debug("about to do substring on [" + dirName + "] positions ["
514                     + this.baseDir.length() + "] and [" + startExistingPathIndexPos
515                     + "]");
516         }
517 
518         String firstPartFileName = dirName.substring(this.baseDir.length(),
519                 startExistingPathIndexPos);
520 
521         if (debug) {
522             log.debug("firstPartFileName is [" + firstPartFileName + "]");
523         }
524 
525         newPath.append(firstPartFileName);
526         newPath.append(newPkgPath);
527 
528         String lastPartFileName = dirName.substring(endExistingPathIndexPos);
529 
530         if (debug) {
531             log.debug("appending lastPartFileName [" + lastPartFileName + "]");
532         }
533 
534         newPath.append(lastPartFileName);
535 
536         return newPath.toString();
537     }
538 
539 
540     private boolean isOldPackageDir(String dirName) {
541         if (debug) {
542             log.debug("inside isOldPackageDir with [" + dirName + "]");
543         }
544 
545         // Should we process this file at all or leave it?
546         int existingPathIndexPos = dirName.indexOf(existingPkgPath);
547 
548         if (existingPathIndexPos != -1) {
549             if (debug) {
550                 log.debug("found dir with existing package name [" + dirName + "]");
551             }
552             return true;
553         }
554 
555         if (debug) {
556             log.debug("dir [" + dirName + "] is not old package dir");
557         }
558 
559         return false;
560     }
561 
562     /*
563      * This method reads a file and returns a string suitable for some regex
564      * operation
565      *
566      * @param fileName the file name to open and read @return the file contents
567      */
568     public String fromFile(String fileName) throws IOException {
569         /*BufferedReader in = new BufferedReader(new FileReader(fileName));
570         StringBuffer fileContents = new StringBuffer();
571         String str;
572 
573         while ((str = in.readLine()) != null)
574         {
575             fileContents.append(str);
576             fileContents.append("\n");
577         }
578         in.close();
579         return fileContents.toString();*/
580         return FileUtils.readFileToString(new File(fileName), "UTF-8");
581     }
582 
583     /*
584      * This method saves a file to disk
585      *
586      * @param fileName the name of the file @param contents the files contents
587      * @throws IOException if there is an error writing the file
588      */
589     public void toFile(String fileName, String contents) throws IOException {
590         if (debug) {
591             log.debug("Saving file to fileName [" + fileName + "]");
592         }
593 
594         FileUtils.writeStringToFile(new File(fileName), contents, "UTF-8");
595     }
596 
597     /**
598      * Checks to see if the file is a valid type
599      *
600      * @return true if the file is a valid type, else false
601      */
602     private boolean isValidFileType(String fileName) {
603         for (int i = 0; i < invalidFileTypes.length; i++) {
604             if (fileName.endsWith(invalidFileTypes[i])) {
605                 if (debug) {
606                     log.debug("File [" + fileName
607                             + "] will just be moved as it is not a valid type");
608                 }
609                 return false;
610             }
611         }
612         return true;
613     }
614 
615     /**
616      * Escapes the search token so it is fit for a regex replacement
617      *
618      * @return true if the file is a valid type, else false
619      */
620     private String escape(String str) {
621         String newStr = "";
622         char[] strArr = str.toCharArray();
623 
624         for (int i = 0; i < strArr.length; i++) {
625             if (strArr[i] == '.') {
626                 newStr += "\\";
627             }
628             if (strArr[i] == '\\') {
629                 newStr += "\\";
630             }
631             newStr += strArr[i];
632         }
633 
634         if (debug) {
635             log.debug("escaped str is [" + newStr + "]");
636         }
637 
638         return newStr;
639     }
640 
641     /**
642      * This method changes the name of any strings in the file and saves the
643      * file back to disk
644      * <p/>
645      * With paths, there may be both \ path delimiters or / so we need to run
646      * the regex twice to ensure we have replaced both types
647      *
648      * @return the contents of the file after the package names have been
649      *         changed
650      */
651     private String changePackagePaths(String fileContents) {
652         String output = changeWindowsPaths(fileContents);
653         output = changeUnixPaths(output);
654         return output;
655     }
656 
657     /**
658      * This method changes the name of any strings in the file and saves the
659      * file back to disk
660      * <p/>
661      * With paths, there may be both \ path delimiters or / so we need to run
662      * the regex twice to ensure we have replaced both types
663      *
664      * @return the contents of the file after the package names have been
665      *         changed
666      */
667     private String changeUnixPaths(String fileContents) {
668         if (debug) {
669             log.debug("inside changeUnixPaths");
670         }
671 
672         String patternStr;
673 
674         if (newPkgPath.length() == 0) {
675             patternStr = getUnixPath(existingPkgPath) + "/";
676         } else {
677             if (debug) {
678                 log.debug("before calling getUnixPath existingPkgPath is ["
679                         + existingPkgPath + "]");
680             }
681 
682             patternStr = getUnixPath(existingPkgPath);
683         }
684 
685         if (debug) {
686             log.debug("patternStr before escaping is [" + patternStr + "]");
687         }
688 
689         patternStr = escape(patternStr);
690 
691         if (debug) {
692             log.debug("after escaping the search/match string is [" + patternStr
693                     + "]");
694             log.debug("newPkgPath is [" + newPkgPath + "] about to escape it");
695         }
696 
697         String replacementStr = escape(getUnixPath(newPkgPath));
698 
699         if (debug) {
700             log.debug("replacementStr after escaping is [" + replacementStr + "]");
701         }
702 
703         return performReplacement(fileContents, patternStr, replacementStr);
704     }
705 
706     /**
707      * This method replaces any UNIX style path separators for Windows style
708      * separators
709      *
710      * @return the path
711      */
712     private String getWindowsPath(String path) {
713         String newStr = "";
714         char[] strArr = path.toCharArray();
715 
716         for (int i = 0; i < strArr.length; i++) {
717             if (strArr[i] == '/') {
718                 newStr += "\\";
719             } else {
720                 newStr += strArr[i];
721             }
722         }
723 
724         if (debug) {
725             log.debug("escaped str is [" + newStr + "]");
726         }
727 
728         return newStr;
729     }
730 
731     /**
732      * This method replaces any Windows style path separators for UNIX style
733      * separators
734      *
735      * @return the path
736      */
737     private String getUnixPath(String path) {
738         if (debug) {
739             log.debug("inside getUnixPath with path [" + path + "]");
740         }
741 
742         String newStr = "";
743         char[] strArr = path.toCharArray();
744 
745         for (int i = 0; i < strArr.length; i++) {
746             if (strArr[i] == '\\') {
747                 newStr += "/";
748             } else {
749                 newStr += strArr[i];
750             }
751         }
752 
753         if (debug) {
754             log.debug("escaped str is [" + newStr + "]");
755         }
756 
757         return newStr;
758     }
759 
760     /**
761      * This method changes the name of any strings in the file and saves the
762      * file back to disk
763      * <p/>
764      * With paths, there may be both \ path delimiters or / so we need to run
765      * the regex twice to ensure we have replaced both types
766      *
767      * @return the contents of the file after the package names have been
768      *         changed
769      */
770     private String changeWindowsPaths(String fileContents) {
771         if (debug) {
772             log.debug("inside changeWindowsPaths");
773         }
774 
775         String patternStr;
776 
777         if (newPkgPath.length() == 0) {
778             patternStr = getWindowsPath(existingPkgPath) + "\\";
779         } else {
780             if (debug) {
781                 log.debug("existingPkgPath is currently [" + existingPkgPath
782                         + "] before calling getWindowsPath");
783             }
784 
785             patternStr = getWindowsPath(existingPkgPath);
786 
787         }
788 
789         if (debug) {
790             log.debug("patternStr is [" + patternStr
791                     + "] after calling getWindowsPath");
792         }
793 
794         patternStr = escape(patternStr);
795 
796         if (debug) {
797             log.debug("After escaping the pattern/search str it is [" + patternStr
798                     + "]");
799             log.debug("Before escaping and calling getWindowsPath the newPkgPath it is ["
800                     + newPkgPath + "]");
801         }
802 
803         String replacementStr = escape(getWindowsPath(newPkgPath));
804 
805         if (debug) {
806             log.debug("After escaping it, it is now [" + replacementStr + "]");
807         }
808 
809         return performReplacement(fileContents, patternStr, replacementStr);
810     }
811 
812     /**
813      * This method changes the name of any strings in the file and saves the
814      * file back to disk
815      * <p/>
816      * With paths, there may be both \ path delimiters or / so we need to run
817      * the regex twice to ensure we have replaced both types
818      *
819      * @return the contents of the file after the package names have been
820      *         changed
821      */
822     private String performReplacement(String fileContents, String patternStr,
823                                       String replacementStr) {
824         if (debug) {
825             log.debug("replacing [" + patternStr + "] with [" + replacementStr + "]");
826         }
827 
828         // Compile regular expression
829         Pattern pattern = Pattern.compile(patternStr);
830 
831         // Replace all occurrences of pattern in input
832         Matcher matcher = pattern.matcher(fileContents);
833         String output = matcher.replaceAll(replacementStr);
834 
835         /*
836          * if (debug) { debug("output is [" + output + "]"); }
837          */
838         return output;
839     }
840 
841     /**
842      * This method changes the name of any strings in the file and saves the
843      * file back to disk
844      *
845      * @return the contents of the file after the package names have been
846      *         changed
847      */
848     private String changePackageNames(String fileContents) {
849         String patternStr;
850 
851         if (newPkgName.length() == 0) {
852             patternStr = existingPkgName + ".";
853         } else {
854             patternStr = existingPkgName;
855         }
856         patternStr = escape(patternStr);
857 
858         String replacementStr = escape(newPkgName);
859 
860         return performReplacement(fileContents, patternStr, replacementStr);
861     }
862 
863     /**
864      * This method changes the name of any strings in the file and saves the
865      * file back to disk
866      *
867      * @return the contents of the file after the package names have been
868      *         changed
869      */
870     private String changePackageNamesInFile(String fileName,
871                                             boolean saveToSameFile) throws IOException {
872         if (debug) {
873             log.debug("calling fromFile with fileName [" + fileName + "]");
874         }
875 
876         String inputStr = fromFile(fileName);
877 
878         String output = changePackageNames(inputStr);
879         output = changePackagePaths(output);
880 
881         if (saveToSameFile) {
882             if (debug) {
883                 log.debug("replaced package names in file and now saving it to ["
884                         + fileName + "]");
885             }
886             toFile(fileName, output);
887         }
888 
889         return output;
890     }
891 
892     /**
893      * This method corrects the File separators on the file name
894      *
895      * @return the correct path to the file
896      */
897     private String correctFileSeparators(String fileName) {
898         String localSeparator = File.separator;
899 
900         if (localSeparator.equals("\\")) {
901             return fileName.replace('/', '\\');
902         } else {
903             return fileName.replace('\\', '/');
904         }
905     }
906 
907     /**
908      * This method changes the name of any strings in the file and saves the
909      * file back to disk, the difference is, it uses Spring Ant-style paths
910      * to load the files
911      */
912     private void renameOtherFiles() {
913         if (debug) {
914             log.debug("Inside renameOtherFiles");
915         }
916 
917         try {
918             for (Iterator itFSets = filesets.iterator(); itFSets.hasNext();) {
919                 FileSet fs = (FileSet) itFSets.next();
920                 fs.setDir(new File(workBaseDir));
921 
922                 if (debug) {
923                     log.debug("got fileset fs [" + fs + "]");
924                 }
925 
926                 DirectoryScanner ds = fs.getDirectoryScanner(new org.apache.tools.ant.Project());
927 
928                 if (debug) {
929                     log.debug("ds baseDir is [" + ds.getBasedir().getAbsolutePath() + "]");
930                 }
931 
932                 ds.scan();
933                 String[] includedFiles = ds.getIncludedFiles();
934 
935                 if (debug) {
936                     log.debug("Got includedFiles [" + includedFiles + "]");
937                 }
938 
939                 if (includedFiles != null) {
940                     for (int i = 0; i < includedFiles.length; i++) {
941                         processOtherFile(includedFiles[i]);
942                     }
943                 } else {
944                     if (debug) {
945                         log.debug("Did not find any matching files for one of the filesets");
946                     }
947 
948                 }
949             }
950         }
951         catch (Exception e) {
952             log.error("Exception at end of renaming other files [" + e.getMessage()
953                     + "]");
954         }
955     }
956 
957     /**
958      * This method changes paths and package names in the given file
959      */
960 
961     private void processOtherFile(String fileName) {
962         try {
963             if (debug) {
964                 log.debug("Processing file [" + fileName + "]");
965             }
966 
967             if (isValidFileType(fileName)) {
968                 fileName = correctFileSeparators(fileName);
969 
970                 if (debug) {
971                     log.debug("After correcting file separators fileName is ["
972                             + fileName + "]");
973                     log.debug("file is valid so changing package names");
974                 }
975 
976                 fileName = workBaseDir + File.separator + fileName;
977                 changePackageNamesInFile(fileName,
978                         RenamePackages.SAVE_FILE);
979 
980                 if (debug) {
981                     log.debug("processing change package names on other file ["
982                             + fileName + "]");
983                 }
984             } else {
985                 log.error("Not processing file [" + fileName + "] as it is not a valid type");
986             }
987         }
988         catch (FileNotFoundException f) {
989             // continue and process next
990             log.error("could not find resource from path ["
991                     + fileName
992                     + "]");
993         }
994         catch (IOException e) {
995             log.error("IOException when renaming other files [" + e.getMessage() + "]");
996         }
997     }
998 
999     /**
1000      * This method removes directory structures
1001      */
1002     public void deleteAll(String fileName) {
1003 
1004         File aFile = new File(fileName);
1005 
1006         if (debug) {
1007             log.debug("inside deleteAll with fileName [" + fileName + "]");
1008         }
1009 
1010         if (aFile.exists()) {
1011             boolean isDir = aFile.isDirectory();
1012             if (isDir) {
1013                 String[] inFiles = aFile.list();
1014 
1015                 for (int fileNum = 0; fileNum < inFiles.length; fileNum++) {
1016                     String subFileName = fileName + File.separator
1017                             + inFiles[fileNum];
1018                     deleteAll(subFileName);
1019                 }
1020             }
1021 
1022             if (debug) {
1023                 log.debug("About to delete file inside deleteAll [" + fileName + "]");
1024             }
1025 
1026             if (aFile.delete()) {
1027                 if (debug) {
1028                     if (isDir) {
1029                         log.debug("Deleted dir [" + fileName + "]");
1030                     } else {
1031                         log.debug("Deleted file [" + fileName + "]");
1032                     }
1033                 }
1034             } else {
1035                 log.error("Failed to delete file/dir [" + fileName + "]");
1036             }
1037         }
1038     }
1039 
1040     private void refactorNonPackageFiles() {
1041 
1042         try {
1043             String[] extensions = {"java", "page", "application", "properties", "tld", "xml"};
1044 
1045             Iterator filesInMain = FileUtils.iterateFiles(new File(this.workBaseDir), extensions, true);
1046 
1047             while (filesInMain.hasNext()) {
1048                 File f = (File) filesInMain.next();
1049                 changePackageNamesInFile(f.getAbsolutePath(), RenamePackages.SAVE_FILE);
1050             }
1051 
1052         } catch (IOException ioex) {
1053             log.error("IOException: " + ioex.getMessage());
1054         }
1055     }
1056 
1057     /**
1058      * This is the main method that gets invoked when ANT calls this task
1059      */
1060     public void execute() {
1061         try {
1062 
1063             if (newPkgName == null) {
1064                 throw new BuildException(
1065                         "The new package path needs to be set using <renamepackages "
1066                                 + "newPkgName=\"${new.pkg.name}\"");
1067             }
1068 
1069             if (baseDir == null) {
1070                 throw new BuildException(
1071                         "The base directory needs to be set using <renamepackages "
1072                                 + "baseDir=\"${src.base.dir}\"/>\n");
1073             }
1074 
1075             if (debug) {
1076                 log.info("existingPkgName is [" + this.existingPkgName + "]");
1077                 log.info("newPkgName is [" + this.newPkgName + "]");
1078             }
1079 
1080             setPackagePaths();
1081 
1082             if (debug) {
1083                 log.info("Package paths set");
1084             }
1085 
1086             repackage(this.baseDir, this.workBaseDir);
1087 
1088             if (debug) {
1089                 log.info("RePackage directories");
1090             }
1091 
1092             renameOtherFiles();
1093 
1094             if (debug) {
1095                 log.info("Rename other files");
1096             }
1097 
1098             // fix files with qualified names other than old package
1099             refactorNonPackageFiles();
1100 
1101             // Check the new dir structures for any files left over with the old pkg name in
1102             checkSummary(this.workBaseDir);
1103 
1104             if (debug) {
1105                 log.info("CheckSummary");
1106             }
1107 
1108             deleteAll(this.baseDir);
1109 
1110             if (debug) {
1111                 log.info("Delete all");
1112             }
1113 
1114             File workBaseDir = new File(this.workBaseDir);
1115             if (workBaseDir.renameTo(new File(this.baseDir))) {
1116                 if (debug) {
1117                     log.info("Successfully renamed work dir back to base dir");
1118                 }
1119             } else {
1120                 log.error("Error could not rename work dir");
1121             }
1122 
1123             // delete src/**/java/org if it exists
1124             deleteOrgPackage("main");
1125             deleteOrgPackage("test");
1126         }
1127         catch (IOException ioe) {
1128             log.error("Caught an IO:" + ioe.getMessage());
1129         }
1130         catch (Exception e) {
1131             log.error("Uncaught exception caught [" + e.getMessage() + "]");
1132         }
1133 
1134         // success!
1135         log.info("[AppFuse] Refactored all 'org.appfuse' packages and paths to '" + newPkgName + "'.");
1136     }
1137 
1138     private void deleteOrgPackage(String path) {
1139         File orgDir = new File(baseDir + "/" + path + "/java/org");
1140         if (orgDir.isDirectory() && orgDir.list().length == 0) {
1141             if (!orgDir.delete()) {
1142                 log.warn("Failed to delete '" + orgDir.getAbsolutePath() + "', please delete manually.");
1143             }
1144         }
1145     }
1146 
1147 }
1148