/******************************************************************************* | |
* Copyright (c) 1998, 2013 Oracle and/or its affiliates. All rights reserved. | |
* This program and the accompanying materials are made available under the | |
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 | |
* which accompanies this distribution. | |
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html | |
* and the Eclipse Distribution License is available at | |
* http://www.eclipse.org/org/documents/edl-v10.php. | |
* | |
* Contributors: | |
* Oracle - initial API and implementation from Oracle TopLink | |
******************************************************************************/ | |
package org.eclipse.persistence.utils.rename; | |
import java.io.*; | |
import java.util.*; | |
/** | |
* This class performs package renaming. It demonstrates the following: | |
* | |
* a) Reading the properties file to be a reference for changing the package | |
* name from your source code. | |
* | |
* b) Traverse source root directory for creating a corresponding output | |
* directory and finding the java source file(s) to be changing the package | |
* name. | |
* | |
* c) Search and replace the old TopLink package name(s) with new one(s) | |
* according to the reference. | |
* | |
* You will be able to see the logging message at the command line window where | |
* the PackageRenamer is running. | |
* | |
*/ | |
public class PackageRenamer { | |
private static int BUFSIZ = 1024 * 4; | |
private List<File> ignoreFiles = new ArrayList<File>(); | |
private List<RenameValue> renameValues = new ArrayList<RenameValue>(); | |
private int numberOfTotalFile = 0; | |
private int numberOfChangedFile = 0; | |
// contains the source-root-directory | |
File sourceRootDirFile; | |
// contains the destination-root-directory | |
File destinationRootDir; | |
public PackageRenamer(String sourceFolder, String targetFolder, | |
Properties properties) { | |
this.sourceRootDirFile = buildAndCheckExistingDirFile(sourceFolder); | |
this.destinationRootDir = buildAndCheckDestinationFile(targetFolder); | |
initialize(this.sourceRootDirFile, properties); | |
} | |
public List<File> getIgnoreFiles() { | |
return ignoreFiles; | |
} | |
public List<RenameValue> getRenameValues() { | |
return renameValues; | |
} | |
/** | |
* Do a binary copy of the file byte buffer by byte buffer. | |
*/ | |
public void binaryCopy(File inFile, File outFile) | |
throws FileNotFoundException, IOException { | |
byte[] buf = new byte[BUFSIZ]; | |
FileInputStream in = new FileInputStream(inFile); | |
// make sure the directories under this file are available | |
String parent = outFile.getParent(); | |
if (parent != null) { | |
File parentFile = new File(parent); | |
if (!parentFile.exists()) { | |
parentFile.mkdirs(); | |
} | |
} | |
FileOutputStream out = new FileOutputStream(outFile); | |
int nBytesRead; | |
while ((nBytesRead = in.read(buf)) != -1) { | |
out.write(buf, 0, nBytesRead); | |
} | |
in.close(); | |
out.close(); | |
} | |
private boolean bufferContainsNullChar(byte[] buffer, int bufferLength) { | |
for (int i = 0; i < bufferLength; i++) { | |
if (buffer[i] == 0) { | |
return true; | |
} | |
} | |
return false; | |
} | |
public File buildAndCheckDestinationFile(String aDirString) { | |
if (aDirString == null) { | |
throw new RuntimeException("Invalid destination directory entered."); | |
} | |
File aDirFile = new File(aDirString); | |
// Check if the destination directory is within the source directory. | |
// This would create an infinite loop. | |
if (directoryIsSubdirectory(sourceRootDirFile, aDirFile)) { | |
throw new RuntimeException("Invalid destination directory entered:" | |
+ " '" + aDirString + "'" | |
+ "It cannot be a sub-directory of the source directory."); | |
} | |
return aDirFile; | |
} | |
public File buildAndCheckExistingDirFile(String aDirString) { | |
if (aDirString == null) { | |
throw new RuntimeException("Invalid source directory entered."); | |
} | |
File aDirFile = new File(aDirString); | |
if (!aDirFile.exists() || !aDirFile.isDirectory()) { | |
throw new RuntimeException("Input Directory: '" + aDirString + "'" | |
+ "does not exist or is not a directory."); | |
} | |
return aDirFile; | |
} | |
/** | |
* Returns the extension of the given file. Returns and empty string if none | |
* was found. | |
*/ | |
protected static String parseFileExtension(String fileName) { | |
int index = fileName.lastIndexOf('.'); | |
if (index == -1) { | |
return ""; | |
} else { | |
return fileName.substring(index + 1); | |
} | |
} | |
/** | |
* Return true if directory2 is contained within directory1. Both | |
* directories must be absolute. | |
*/ | |
public static boolean directoryIsSubdirectory(File directory1, | |
File directory2) { | |
// System.out.println(directory1 + " contains " + directory2); | |
if (directory2 == null) { | |
return false; | |
} else if (directory1.equals(directory2)) { | |
return true; | |
} else { | |
return directoryIsSubdirectory(directory1, directory2 | |
.getParentFile()); | |
} | |
} | |
/** | |
* Return true if the PackageRenamer should work on the given file | |
* extension. | |
*/ | |
public boolean isExtensionSupported(String extension) { | |
return extension.equalsIgnoreCase("java") | |
|| extension.equalsIgnoreCase("xml") | |
|| extension.equalsIgnoreCase("mwp"); | |
} | |
/** | |
* This run() method performs, reading the properties file into properties | |
* variable to be a reference for changing package name. creating an | |
* destination-root-direetory. and, calling traverseSourceDirectory() | |
* method. | |
*/ | |
public void run() { | |
System.out.println("LOG MESSAGES FROM packageRenamer"); | |
System.out.println(""); | |
System.out.println("INPUT: -----------------> " | |
+ sourceRootDirFile.toString()); | |
System.out.println("OUTPUT: ----------------> " | |
+ destinationRootDir.toString()); | |
// Listing the changed file(s) | |
System.out.println("List of changed file(s): "); | |
traverseSourceDirectory(sourceRootDirFile); | |
System.out.println("Total Changed File(s): ------> " | |
+ numberOfChangedFile); | |
System.out.println("Total File(s): ------> " | |
+ numberOfTotalFile); | |
} | |
/** | |
* This runSearchAndReplacePackageName() reads an pre-rename source file all | |
* into string variable and replacing the old package names with the new | |
* ones according to the properties file. | |
*/ | |
public void runSearchAndReplacePackageName(File sourceFile) { | |
if (getIgnoreFiles().contains(sourceFile)) { | |
return; | |
} | |
String stringContainAllFile = ""; | |
String sourceFileName = sourceFile.toString(); | |
String sourceFileNameWithoutRoot = sourceFile.toString().substring( | |
sourceRootDirFile.toString().length() + 1); | |
String destinationFileNameWithoutRoot = renameFile(sourceFileNameWithoutRoot); | |
String destinationFileName = destinationRootDir.toString() | |
+ File.separator + destinationFileNameWithoutRoot; | |
File destFile = new File(destinationFileName); | |
if (destFile.exists()) { | |
System.out.println("WARNING: Skipping pre-existing: " + destFile); | |
return; | |
} | |
System.out.print("MIGRATING: " + sourceFileName); | |
// Reading file into string. | |
// stringContainAllFile = readAllStringsFromFile(sourceFileName); | |
try { | |
FileInputStream fis = new FileInputStream(new File(sourceFileName)); | |
byte[] buf = new byte[BUFSIZ]; | |
StringBuffer strBuf = new StringBuffer((int) new File( | |
sourceFileName).length()); | |
int i = 0; | |
while ((i = fis.read(buf)) != -1) { | |
if (bufferContainsNullChar(buf, i)) { | |
// This is a binary file, just copy it byte by byte to the | |
// new location. Do not do any renaming. | |
fis.close(); | |
binaryCopy(sourceFile, new File(destinationFileName)); | |
return; | |
} | |
String str = new String(buf, 0, i); | |
strBuf.append(str); | |
} | |
fis.close(); | |
stringContainAllFile = new String(strBuf); | |
} catch (IOException ioException) { | |
throw new RuntimeException( | |
"Unexpected exception was thrown during file manipulation." | |
+ ioException.getMessage()); | |
} | |
System.out.print(" -> "); | |
// Starting to rename. | |
RenameFileData fileData = new RenameFileData(stringContainAllFile, | |
false); | |
// Make sure package is correct | |
String sourcePackageName = null; | |
String destPackageName = null; | |
if (sourceFileNameWithoutRoot.lastIndexOf('\\') >= 0) { | |
sourceFileNameWithoutRoot = sourceFileNameWithoutRoot.substring(0, | |
sourceFileNameWithoutRoot.lastIndexOf('\\')); | |
destinationFileNameWithoutRoot = destinationFileNameWithoutRoot | |
.substring(0, destinationFileNameWithoutRoot | |
.lastIndexOf('\\')); | |
} | |
sourcePackageName = sourceFileNameWithoutRoot.replace('\\', '.'); | |
destPackageName = destinationFileNameWithoutRoot.replace('\\', '.'); | |
fileData = new RenameValue("package " + sourcePackageName + ";", | |
"package " + destPackageName + ";").replace(fileData); | |
for (RenameValue rv : getRenameValues()) { | |
fileData = rv.replace(fileData); | |
} | |
if (fileData.isChanged()) { | |
this.numberOfChangedFile++; | |
} | |
System.out.println(destFile); | |
// Writing output file. | |
try { | |
destFile.getParentFile().mkdirs(); | |
FileWriter writer = new FileWriter(destFile); | |
java.io.PrintWriter out = new java.io.PrintWriter(writer); | |
out.print(fileData.getFileContentsString()); | |
out.close(); | |
} catch (FileNotFoundException fileNotFoundException) { | |
throw new RuntimeException("Could not find file to write:" + " '" | |
+ destinationFileName + "'" | |
+ fileNotFoundException.getMessage()); | |
} catch (IOException ioException) { | |
throw new RuntimeException( | |
"Unexpected exception was thrown while writing the file: '" | |
+ destinationFileName + "', " | |
+ ioException.getMessage()); | |
} | |
} | |
public String renameFile(String source) { | |
String extension = parseFileExtension(source); | |
String resourceName = source.substring(0, source.length() | |
- (extension.length() + 1)); | |
String packageName = resourceName; | |
if ("java".equals(extension)) { | |
packageName = resourceName.replace('\\', '.'); | |
} | |
String targetPackageName = packageName; | |
RenameFileData fileData = new RenameFileData(targetPackageName, true); | |
for (RenameValue rv : getRenameValues()) { | |
fileData = rv.replace(fileData); | |
} | |
if ("java".equals(extension)) { | |
fileData.setFileContentsString(fileData.getFileContentsString().replace('.', '\\')); | |
} | |
if (extension != null && extension.length() > 0) { | |
fileData.setFileContentsString(fileData.getFileContentsString() | |
+ "." + extension); | |
} | |
return fileData.getFileContentsString(); | |
} | |
/** | |
* This traverseSourceDirectory() traverse source-root-directory, creating | |
* an corresponding output directory, and calling another method for | |
* replacing old TopLink package name. | |
*/ | |
public void traverseSourceDirectory(File directory) { | |
File[] filesAndDirectories = directory.listFiles(); | |
for (int i = 0; i < filesAndDirectories.length; i++) { | |
File fileOrDirectory = filesAndDirectories[i]; | |
if (fileOrDirectory.isDirectory()) { | |
if (!fileOrDirectory.getName().equalsIgnoreCase(".svn")) { | |
traverseSourceDirectory(fileOrDirectory); | |
} | |
} else { | |
this.numberOfTotalFile++; | |
// Check that it does not have an unsupported file extension | |
String fileExtension = parseFileExtension(fileOrDirectory | |
.getName()); | |
if (isExtensionSupported(fileExtension)) { | |
runSearchAndReplacePackageName(fileOrDirectory); | |
} | |
} | |
} | |
} | |
/** | |
* | |
* @param srcRoot | |
* @param properties | |
* @return | |
*/ | |
private void initialize(File srcRoot, Properties properties) { | |
for (Object key : properties.keySet()) { | |
String packageOrClassName = (String) key; | |
String value = properties.getProperty(packageOrClassName); | |
if (value.equalsIgnoreCase("ignore")) { | |
File folder = new File(srcRoot, packageOrClassName.replace('.', | |
'\\')); | |
if (folder.exists() && folder.isDirectory()) { | |
addIgnoreFolder(folder, ignoreFiles); | |
} else { | |
File file = new File(srcRoot, packageOrClassName.replace( | |
'.', '\\') | |
+ ".java"); | |
if (file.exists()) { | |
ignoreFiles.add(file); | |
}/* | |
* else { throw new IllegalArgumentException( "Could not | |
* find src to ignore: " + srcRoot + " :: " + | |
* packageOrClassName); } | |
*/ | |
} | |
} else { | |
renameValues.add(new RenameValue(packageOrClassName, value)); | |
} | |
} | |
Collections.sort(renameValues, RenameValue.renameValueComparator()); | |
/* | |
* System.out.println("FILES TO IGNORE"); for (File file : ignoreFiles) { | |
* System.out.println("\t> " + file); } | |
* | |
* System.out.println("\nRENAME VALUES"); for (RenameValue rv : | |
* renameValues) { System.out.println("\t" + rv); } | |
*/ | |
} | |
/** | |
* | |
* @param folder | |
* @param ignoreFiles | |
*/ | |
private void addIgnoreFolder(File folder, List<File> ignoreFiles) { | |
File[] files = folder.listFiles(); | |
for (int index = 0; index < files.length; index++) { | |
File file = files[index]; | |
if (file.isFile() | |
&& isExtensionSupported(parseFileExtension(file.getName()))) { | |
ignoreFiles.add(file); | |
} else if (file.isDirectory() | |
&& !file.getName().equalsIgnoreCase(".svn")) { | |
addIgnoreFolder(file, ignoreFiles); | |
} | |
} | |
} | |
} |