blob: 2969f052b85b0cf98bb92c8d705b0b74078a2257 [file] [log] [blame]
/*
* Copyright (c) 1998, 2021 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 v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// 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);
}
}
}
}
/**
*
*/
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); }
*/
}
/**
*
*/
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);
}
}
}
}