/******************************************************************************* * Copyright (c) 1998, 2015 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.tools.workbench.test.mappingsmodel.spi.meta; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import org.eclipse.persistence.tools.workbench.test.utility.JavaTools; import org.eclipse.persistence.tools.workbench.utility.ClassTools; import org.eclipse.persistence.tools.workbench.utility.io.FileTools; import org.eclipse.persistence.tools.workbench.utility.io.IndentingPrintWriter; /** * This tool can be used to create a two versions of the same class that * can be used to test class loading. Create the files by calling #setUp() * and delete them by calling #tearDown(). The various files and directories * are stored in public instance variables. The names used for these are * stored in public static variables. * * The different versions will be compiled into: * - two different subdirectories (subdir1 and subdir2) * - two different jar files (jarFile1 and jarFile2) * - two different zip files (zipFile1 and zipFile2) * * The two versions of the class will differ by the presence of a single * method: the version in subdir1/jarFile1/zipFile1 will have a single * method named #version1(); while, predictably, the version in * subdir2/jarFile2/zipFile2 will have a single method named #version2(); * and the presence of a single attribute, similarly named. */ public class ClasspathTestTool { public String name; public File workingDirectory; public File subdir1; public File subdir2; public File jarFile1; public File jarFile2; public File zipFile1; public File zipFile2; public static final String PKG_QUALIFIER_1 = "foo"; public static final String PKG_QUALIFIER_2 = "bar"; public static final String PKG_NAME = PKG_QUALIFIER_1 + "." + PKG_QUALIFIER_2; public static final String SHORT_TEST_CLASS_NAME = ClassTools.shortNameFor(ClasspathTestTool.class) + "TestClass"; public static final String TEST_CLASS_NAME = PKG_NAME + "." + SHORT_TEST_CLASS_NAME; public static final String VERSION_MEMBER_PREFIX = "version"; public ClasspathTestTool(String name) { super(); this.name = name; } public void setUp() throws Exception { this.workingDirectory = this.buildWorkingDirectory(this.name); } public void tearDown() throws Exception { FileTools.deleteDirectory(this.workingDirectory); } /** * build a temporary directory with two different versions * of a Java source file; then compile them and package * them into jars and zips */ private File buildWorkingDirectory(String dirName) throws Exception { File dir = FileTools.emptyTemporaryDirectory(dirName); this.subdir1 = this.buildSourceSubdir(dir, 1); this.jarFile1 = buildJarFile(this.subdir1, 1); this.zipFile1 = buildZipFile(this.subdir1, 1); this.subdir2 = this.buildSourceSubdir(dir, 2); this.jarFile2 = buildJarFile(this.subdir2, 2); this.zipFile2 = buildZipFile(this.subdir2, 2); return dir; } /** * build a subdirectory "foo\bar" with the .java and .class * files for the class ClassPathEntryTestsTestClass */ private File buildSourceSubdir(File parentDir, int version) throws Exception { File subdir = new File(parentDir, "subdir" + version); subdir.mkdir(); File fooDir = new File(subdir, PKG_QUALIFIER_1); fooDir.mkdir(); File barDir = new File(fooDir, PKG_QUALIFIER_2); barDir.mkdir(); File sourceFile = new File(barDir, SHORT_TEST_CLASS_NAME + ".java"); IndentingPrintWriter pw = new IndentingPrintWriter(new FileWriter(sourceFile)); this.printSourceOn(pw, version); pw.close(); this.compile(sourceFile); return subdir; } private void printSourceOn(IndentingPrintWriter pw, int version) { printSourceOn(pw, version, this.buildSourceExtender()); } /** * subclasses can override this method if they want to add * to the source code generated for testing */ protected SourceExtender buildSourceExtender() { return buildNullSourceExtender(); } /** * build an archive of the specified subdirectory */ private File buildJarFile(File subdir, int version) throws Exception { String jarFileName = subdir.getParentFile().getName() + version + ".jar"; File jarFile = new File(subdir.getParentFile(), jarFileName); this.jar(jarFile, subdir); return jarFile; } /** * build a zip of the specified subdirectory */ private File buildZipFile(File subdir, int version) throws Exception { String zipFileName = subdir.getParentFile().getName() + version + ".zip"; File zipFile = new File(subdir.getParentFile(), zipFileName); this.zip(zipFile, subdir); return zipFile; } private void compile(File sourceFile) throws IOException, InterruptedException { JavaTools.compile(sourceFile); } private void jar(File jarFile, File directory) throws IOException, InterruptedException { JavaTools.jar(jarFile, directory); } private void zip(File zipFile, File directory) throws IOException, InterruptedException { JavaTools.zip(zipFile, directory); } public static SourceExtender buildNullSourceExtender() { return new SourceExtender() { public void extendSourceOn(IndentingPrintWriter pw, int version) { // do nothing } }; } private static void printSourceOn(IndentingPrintWriter pw, int version, SourceExtender extender) { pw.print("package "); pw.print(PKG_NAME); pw.println(';'); pw.print("public class "); pw.print(SHORT_TEST_CLASS_NAME); pw.println(" {"); pw.indent(); pw.print("public java.lang.String "); pw.print(VERSION_MEMBER_PREFIX); pw.print(version); pw.println(" = \"version" + version + "\";"); pw.print("public void "); pw.print(VERSION_MEMBER_PREFIX); pw.print(version); pw.println("() {"); pw.indent(); pw.println("System.out.println(\"version" + version + "\");"); pw.undent(); pw.println("}"); extender.extendSourceOn(pw, version); pw.undent(); pw.println("}"); } /** * use this method to check the formatting of the source file */ public static String buildSource(int version) { StringWriter sw = new StringWriter(200); IndentingPrintWriter pw = new IndentingPrintWriter(sw); pw.println(); pw.println(); printSourceOn(pw, version, buildNullSourceExtender()); pw.println(); return sw.toString(); } public static interface SourceExtender { void extendSourceOn(IndentingPrintWriter pw, int version); } }