org.eclipse.persistence.tools.PackageRenamer Maven / Gradle / Ivy
Show all versions of eclipselink Show documentation
/*
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024 IBM Corporation. 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
// 08/29/2016 Jody Grassel
// - 500441: Eclipselink core has System.getProperty() calls that are not potentially executed under doPriv()
package org.eclipse.persistence.tools;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Date;
import java.util.Iterator;
import java.util.Objects;
import java.util.Properties;
import java.util.Vector;
/**
* 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 {
int numberOfTotalFile = 0;
int numberOfChangedFile = 0;
// contains the option of Log file.
boolean specifyLogFile = false;
java.io.PrintWriter outLog = null;
// contains the Log File
String logFileString = null;
java.io.File logFile;
// contains the source-root-directory
java.io.File sourceRootDirFile;
// contains the destination-root-directory
java.io.File destinationRootDir;
// contains the properties file path
String sourceProperties;
// contains a reference for renaming
Properties properties = null;
String propertiesFileName;
boolean VERBOSE = true;
protected static final String SYSTEM_OUT = "System.out";
BufferedReader reader = null;
String[] UNSUPPORTED_EXTENSIONS = { "jar", "zip", "ear", "war", "dll", "class", "exe" };
int BUFSIZ = 1024 * 4;
final static String CR;
static {
// bug 2756643
CR = System.lineSeparator();
}
/**
* The constructor of a PackageRenamer class.
*/
public PackageRenamer() {
this(getDefaultPropertiesFileName());
}
public PackageRenamer(String propertiesFileName) {
System.out.println();
System.out.println("TopLink Package Renamer");
System.out.println("-----------------------");
System.out.println(bannerText());
sourceRootDirFile = existingDirectoryFromPrompt();
System.out.println();
destinationRootDir = promptForDestinationDirectory();
System.out.println();
this.propertiesFileName = propertiesFileName;
outLog = streamForNonExistentFilePrompt();
properties = readChangesFile(propertiesFileName);
}
public PackageRenamer(String[] args) {
this.propertiesFileName = args[0];
sourceRootDirFile = buildAndCheckExistingDirFile(args[1]);
destinationRootDir = buildAndCheckDestinationFile(args[2]);
if (args.length == 4) {
outLog = buildAndCheckLogWriter(args[3]);
} else {
outLog = buildAndCheckLogWriter(SYSTEM_OUT);
}
properties = readChangesFile(args[0]);
logln(bannerText());
}
protected String bannerText() {
StringBuilder stringBuilder = new StringBuilder(CR.length()*3+66+42);
stringBuilder.append(CR);
stringBuilder.append("NOTE: The package renamer is meant to be run on plain text files. ");
stringBuilder.append(CR);
stringBuilder.append("A rename will NOT be done on binary files.");
stringBuilder.append(CR);
return stringBuilder.toString();
}
/**
* Do a binary copy of the file byte buffer by byte buffer.
*
* @param inFile
* The file to copy
* @param outFile
* The destination file
* @throws FileNotFoundException
* if either of the two files does not exist
* @throws IOException
* if any other IO related error occurs
*/
public void binaryCopy(File inFile, File outFile) throws FileNotFoundException, IOException {
byte[] buf = new byte[BUFSIZ];
try (FileInputStream in = new FileInputStream(inFile);
FileOutputStream out = new FileOutputStream(outFile)) {
int nBytesRead;
while ((nBytesRead = in.read(buf)) != -1) {
out.write(buf, 0, nBytesRead);
}
}
}
protected boolean bufferContainsNullChar(byte[] buffer, int bufferLength) {
for (int i = 0; i < bufferLength; i++) {
if (buffer[i] == 0) {
return true;
}
}
return false;
}
/**
* INTERNAL Creates a destination directory File object under the path
* passed, verifying correctness.
*
* @param aDirString
* The path to the directory File object to create
* @return The destination directory File object
*/
public File buildAndCheckDestinationFile(String aDirString) {
if (aDirString == null) {
throw new PackageRenamerException("Invalid destination directory entered.");
}
File aDirFile = new File(aDirString);
if (aDirFile.exists()) {
File[] dirContent = aDirFile.listFiles();
if (dirContent != null && dirContent.length != 0) {
throw new PackageRenamerException("Output Directory:" + CR + " '" + aDirString + "'" + CR + "exists and is not empty.");
}
}
if (!aDirFile.isAbsolute()) {
throw new PackageRenamerException("A relative destination directory was entered:" + CR + " '" + aDirString + "'" + CR + "The directory must be absolute.");
}
// Check if the destination directory is within the source directory. This would create an infinite loop.
if (directoryIsSubdirectory(sourceRootDirFile, aDirFile)) {
throw new PackageRenamerException("Invalid destination directory entered:" + CR + " '" + aDirString + "'" + CR + "It cannot be a sub-directory of the source directory.");
}
return aDirFile;
}
public File buildAndCheckExistingDirFile(String aDirString) {
if (aDirString == null) {
throw new PackageRenamerException("Invalid source directory entered.");
}
File aDirFile = new File(aDirString);
if (!aDirFile.exists() || !aDirFile.isDirectory()) {
throw new PackageRenamerException("Input Directory:" + CR + " '" + aDirString + "'" + CR + "does not exist or is not a directory.");
}
if (!aDirFile.isAbsolute()) {
throw new PackageRenamerException("A relative source directory was entered:" + CR + " '" + aDirString + "'" + CR + "The directory must be absolute.");
}
return aDirFile;
}
public PrintWriter buildAndCheckLogWriter(String logFileString) {
if (logFileString == null) {
throw new PackageRenamerException("Invalid log file name entered.");
}
try {
if (logFileString.equals(SYSTEM_OUT)) {
return new PrintWriter(System.out);
} else {
File aLogFile = new File(logFileString);
if (aLogFile.exists()) {
throw new PackageRenamerException("Specified log file cannot be created:" + CR + " '" + logFileString + "'");
}
FileWriter writerLog = new FileWriter(logFileString);
return new java.io.PrintWriter(writerLog);
}
} catch (IOException ioException) {
throw new PackageRenamerException("Unhandled IOException occurred while configuring log file: '" + logFileString + "', " + ioException.getMessage());
}
}
protected void cleanup() {
//Closing the Log file in case it is being open.
if (outLog != null) {
outLog.close();
}
}
/**
* This method creates an output directory for post-rename file(s).
*
* @param aDirectory
* The output directory to create
*/
public void createDestinationDirectory(File aDirectory) {
if (!aDirectory.exists()) {
if (!aDirectory.mkdirs()) {
throw new PackageRenamerException("Error while creating directory:" + CR + " '" + aDirectory + "'");
}
} else {
throw new PackageRenamerException("Error directory: '" + aDirectory + "' already exists but shouldn't.");
}
}
/**
* Return true if directory2 is contained within directory1. Both
* directories must be absolute.
*
* @param directory1
* The higher level directory
* @param directory2
* The lower level directory
* @return TRUE if directory2 is a subdirectory of directory1
*/
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());
}
}
public File existingDirectoryFromPrompt() {
System.out.print("Enter the path of the directory which contains the files to rename:" + CR + "> ");
String aLine = null;
try {
aLine = getReader().readLine();
} catch (IOException exception) {
throw new PackageRenamerException("Error while reading the source directory: " + exception.getMessage());
}
return buildAndCheckExistingDirFile(aLine);
}
public static String getDefaultPropertiesFileName() {
String currentDirectory = PrivilegedAccessHelper.shouldUsePrivilegedAccess() ?
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public String run() {
return System.getProperty("user.dir");
}
})
: System.getProperty("user.dir");
return currentDirectory + File.separator + "packageRename.properties";
}
public synchronized BufferedReader getReader() {
if (reader == null) {
reader = new BufferedReader(new InputStreamReader(System.in));
}
return reader;
}
/**
* Return true if the PackageRenamer should work on the given file
* extension.
*
* @param extension
* The file extension to check for being supported
* @return TRUE if the extension is supported
*/
public boolean isExtensionSupported(String extension) {
/* This was cut out because the binary check recognize these files and just copy them byte by byte.
for (int i=0; i ");
String aLine = null;
try {
aLine = getReader().readLine();
} catch (IOException exception) {
throw new PackageRenamerException("Error while reading the destination directory specified: " + exception.getMessage());
}
return buildAndCheckDestinationFile(aLine);
}
/**
* This readChangesFile() method reads the given properties file to be a
* reference for renaming TopLink package name.
*
* @param filename
* The input file to use for the renaming
* @return The Properties object containing the renaming information
*/
public Properties readChangesFile(String filename) {
Properties props = new Properties();
try (InputStream in = new FileInputStream(filename)) {
props.load(in);
} catch (FileNotFoundException fileNotFoundException) {
throw new PackageRenamerException("Properties file was not found:" + CR + " '" + filename + "'");
} catch (IOException ioException) {
throw new PackageRenamerException("IO error occurred while reading the properties file:'" + filename + "'" + ioException.getMessage());
}
logln("Using properties file: " + filename);
return props;
}
/**
* This run() method performs,
* reading the properties file into properties variable to be a reference for changing package name.
* creating a destination-root-directory.
* and, calling traverseSourceDirectory() method.
*/
public void run() {
// Start loging.
logln("LOG MESSAGES FROM packageRenamer");
logln("" + new Date());
logln("");
logln("INPUT: -----------------> " + sourceRootDirFile.toString());
logln("OUTPUT: ----------------> " + destinationRootDir.toString());
// logln("PROPERTIES FILE: -------> "+sourceProperties);
// logln("LOG FILE: --------------> "+writerLog);
logln("");
// Root output directory.
logln("Verifying root output directory...");
if (!(destinationRootDir.exists())) {
// Create root directory for output first.
logln("");
logln("Creating root output directory...");
createDestinationDirectory(destinationRootDir);
logln("");
}
logln("Verifying root output directory...DONE");
logln("");
// Listing the changed file(s)
logln("List of changed file(s): ");
logln("");
traverseSourceDirectory(sourceRootDirFile);
logln("");
logln("Total Changed File(s): ------> " + numberOfChangedFile);
logln("Total File(s): ------> " + numberOfTotalFile);
logln("");
}
protected PrintWriter streamForNonExistentFilePrompt() {
System.out.print("Enter the absolute path of the log file [Hit Enter for SYSTEM.OUT]:" + CR + "> ");
String aLine = null;
try {
aLine = getReader().readLine();
} catch (IOException exception) {
throw new PackageRenamerException("Error while reading the name of the log file: " + exception.getMessage());
}
if ((aLine != null) && (aLine.isEmpty())) {
return buildAndCheckLogWriter(SYSTEM_OUT);
} else {
return buildAndCheckLogWriter(aLine);
}
}
/**
* This runSearchAndReplacePackageName() reads a pre-rename source file all
* into string variable and replacing the old package names with the new
* ones according to the properties file.
*
* @param sourceFile
* The source file to process
*/
public void runSearchAndReplacePackageName(java.io.File sourceFile) {
String stringContainAllFile = "";
String sourceFileName = sourceFile.toString();
String sourceFileNameWithoutRoot = sourceFile.toString().substring(sourceRootDirFile.toString().length() + 1);
// Rename the file name if required.
sourceFileNameWithoutRoot = returnNewFileNameIfRequired(sourceFileNameWithoutRoot);
String destinationFileName = destinationRootDir.toString() + File.separator + sourceFileNameWithoutRoot;
// Reading file into string.
// stringContainAllFile = readAllStringsFromFile(sourceFileName);
try (FileInputStream fis = new FileInputStream(sourceFileName)) {
byte[] buf = new byte[BUFSIZ];
StringBuilder strBuf = new StringBuilder((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 PackageRenamerException("Unexpected exception was thrown during file manipulation." + ioException.getMessage());
}
// Sorting key package name.
Vector