| /* |
| * Copyright (c) 1998, 2020 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); |
| } |
| } |
| } |
| } |
| |
| /** |
| * |
| * @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); |
| } |
| } |
| } |
| } |