+ * Returns a {@link SignatureTestDriver} appropriate for the particular TCK + * (using API check or the Signature Test Framework). + *
+ * + *+ * The default implementation of this method will return a + * {@link SignatureTestDriver} that will use API Check. TCK developers can + * override this to return the desired {@link SignatureTestDriver} for their + * TCK. + */ + protected SignatureTestDriver getSigTestDriver() { + + if (driver == null) { + driver = SignatureTestDriverFactory.getInstance(SignatureTestDriverFactory.SIG_TEST); + } + + return driver; + + } // END getSigTestDriver + + + /** + * Returns the list of packages that must be tested by the siganture test + * framework. TCK developers must implement this method in their signature + * test sub-class. + * + * @return String A list of packages that the developer wishes to test using + * the signature test framework. + */ + protected abstract String[] getPackages(); + + /** + * Returns an array of individual classes that must be tested by the signature + * test framwork. TCK developers may override this method when this + * functionality is needed. Most will only need package level granularity. + * + * @return an Array of Strings containing the individual classes the framework + * should test. The default implementation of this method returns a + * zero-length array. + */ + protected String[] getClasses() { + + return new String[] {}; + + } // END getClasses + + protected SigTestData testInfo; + + /** + * Called by the test framework to initialize this test. The method simply + * retrieves some state information that is necessary to run the test when + * when the test framework invokes the run method (actually the test1 method). + * + * @param args + * List of arguments passed to this test. + * @param p + * Properties specified by the test user and passed to this test via + * the test framework. + */ + public void setup() { + try { + logger.log(Logger.Level.TRACE, "$$$ SigTest.setup() called"); + this.testInfo = new SigTestData(); + logger.log(Logger.Level.TRACE, "$$$ SigTest.setup() complete"); + } catch (Exception e) { + logger.log(Logger.Level.ERROR, "Unexpected exception " + e.getMessage()); + } + } + + /** + * Called by the test framework to run this test. This method utilizes the + * state information set in the setup method to run the signature tests. All + * signature test code resides in the utility class so it can be reused by the + * signature test framework base classes. + * + * @throws Exception + * When an error occurs executing the signature tests. + */ + public void signatureTest(String mapFile, String packageFile, Properties mapFileAsProps, String[] packages) + throws Exception { + + SigTestResult results = null; + String repositoryDir = System.getProperty("java.io.tmpdir"); + String[] classes = getClasses(); + String testClasspath = testInfo.getTestClasspath(); + + // If testing with Java 9+, extract the JDK's modules so they can be used + // on the testcase's classpath. + + String jimageDir = testInfo.getJImageDir(); + File f = new File(jimageDir); + f.mkdirs(); + + String javaHome = System.getProperty("java.home"); + logger.log(Logger.Level.INFO, "Executing JImage"); + + try { + ProcessBuilder pb = new ProcessBuilder(javaHome + "/bin/jimage", "extract", "--dir=" + jimageDir, javaHome + "/lib/modules"); + logger.log(Logger.Level.INFO, javaHome + "/bin/jimage extract --dir=" + jimageDir + " " + javaHome + "/lib/modules"); + pb.redirectErrorStream(true); + Process proc = pb.start(); + BufferedReader out = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = null; + while ((line = out.readLine()) != null) { + logger.log(Logger.Level.INFO, line); + } + + int rc = proc.waitFor(); + logger.log(Logger.Level.INFO,"JImage RC = " + rc); + out.close(); + } catch (Exception e) { + logger.log(Logger.Level.INFO, "Exception while executing JImage! Some tests may fail."); + e.printStackTrace(); + } + + + try { + results = getSigTestDriver().executeSigTest(packageFile, mapFile, + repositoryDir, packages, classes, testClasspath); + logger.log(Logger.Level.INFO,results.toString()); + if (!results.passed()) { + logger.log(Logger.Level.TRACE, "results.passed() returned false"); + throw new Exception(); + } + logger.log(Logger.Level.TRACE, "$$$ SigTest.test1() returning"); + } catch (Exception e) { + if (results != null && !results.passed()) { + throw new Exception("SigTest.test1() failed!, diffs found"); + } else { + logger.log(Logger.Level.ERROR, "Unexpected exception " + e.getMessage()); + throw new Exception("test failed with an unexpected exception", e); + } + } + } + + public File writeStreamToTempFile(InputStream inputStream, String tempFilePrefix, String tempFileSuffix) throws IOException { + FileOutputStream outputStream = null; + try { + File file = File.createTempFile(tempFilePrefix, tempFileSuffix); + file.deleteOnExit(); + outputStream = new FileOutputStream(file); + byte[] buffer = new byte[1024]; + while (true) { + int bytesRead = inputStream.read(buffer); + if (bytesRead == -1) { + break; + } + outputStream.write(buffer, 0, bytesRead); + } + return file; + } + finally { + if (outputStream != null) { + outputStream.close(); + } + } + } + + public File writeStreamToSigFile(InputStream inputStream, String apiPackage, String packageVersion) throws IOException { + FileOutputStream outputStream = null; + String tmpdir = System.getProperty("java.io.tmpdir"); + try { + File sigfile = new File(tmpdir+ File.separator + apiPackage + ".sig_"+packageVersion); + if(sigfile.exists()){ + sigfile.delete(); + logger.log(Logger.Level.INFO, "Existing signature file deleted to create new one"); + } + if(!sigfile.createNewFile()){ + logger.log(Logger.Level.ERROR, "signature file is not created"); + } + outputStream = new FileOutputStream(sigfile); + byte[] buffer = new byte[1024]; + while (true) { + int bytesRead = inputStream.read(buffer); + if (bytesRead == -1) { + break; + } + outputStream.write(buffer, 0, bytesRead); + } + return sigfile; + } + + finally { + if (outputStream != null) { + outputStream.close(); + } + } + } + + /** + * Called by the test framework to cleanup any outstanding state. + * + */ + public void cleanup() { + logger.log(Logger.Level.TRACE, "$$$ SigTest.cleanup()"); + } + +} // end class SigTest diff --git a/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestData.java b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestData.java new file mode 100644 index 0000000000..ff19c22fbb --- /dev/null +++ b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestData.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2007, 2024 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. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package com.sun.ts.tests.signaturetest.el; + +import java.util.Properties; + +/** + * This class holds the data passed to a signature test invocation during the + * setup phase. This allows us to keep the passed data separate and reuse the + * data between the signature test framework base classes. + */ +public class SigTestData { + + private Properties props; + + public SigTestData() { + this.props = System.getProperties(); + } + + public String getTestClasspath() { + return props.getProperty("sigTestClasspath", ""); + } + + public String getProperty(String prop) { + return props.getProperty(prop); + } + + public String getJImageDir() { + return props.getProperty("jimage.dir", ""); + } +} // end class SigTestData diff --git a/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestDriver.java b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestDriver.java new file mode 100644 index 0000000000..7880ce98ce --- /dev/null +++ b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SigTestDriver.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2007, 2024 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. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the + * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, + * version 2 with the GNU Classpath Exception, which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + */ + +package com.sun.ts.tests.signaturetest.el; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintWriter; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.lang.System.Logger; + + +/** + *
+ * Wrapper for the Sig Test
framework.
+ *
+ * Execute the signature test. By default, this method passes the result of
+ * {@link #createTestArguments(String, String, String, String, String)} and
+ * passes the result to {@link #runSignatureTest(String, String[])}.
+ *
+ * @param packageListFile
+ * - file containing the packages/classes that are to be verified
+ * @param mapFile
+ * sig-test.map file
+ * @param signatureRepositoryDir
+ * directory containing the recorded signatures
+ * @param packagesUnderTest
+ * packages, defined by the test client, that should be tested
+ * @param classesUnderTest
+ * classes, defined by the test client, that should be tested
+ * @param classpath
+ * The location of the API being verified. Normally the checked API
+ * will be available in the test environment and testClasspath will
+ * be null. In some rare cases the tested API may not be part of the
+ * test environment and will have to specified using this parameter.
+ *
+ * @return a {@link SigTestResult} containing the result of the test execution
+ */
+ public SigTestResult executeSigTest(String packageListFile, String mapFile,
+ String signatureRepositoryDir, String[] packagesUnderTest,
+ String[] classesUnderTest, String classpath)
+ throws Exception {
+
+ SigTestResult result = new SigTestResult();
+
+ if (packagesUnderTest != null && packagesUnderTest.length > 0) {
+ logger.log(Logger.Level.INFO, "********** BEGIN PACKAGE LEVEL SIGNATURE "
+ + "VALIDATION **********\n\n");
+ for (int i = 0; i < packagesUnderTest.length; i++) {
+
+ String packageName = packagesUnderTest[i];
+
+ logger.log(Logger.Level.INFO, "********** BEGIN VALIDATE PACKAGE '"
+ + packagesUnderTest[i] + "' **********\n");
+
+ logger.log(Logger.Level.INFO,
+ "********** VALIDATE IN STATIC MODE - TO CHECK CONSANT VALUES ****");
+ logger.log(Logger.Level.INFO, "Static mode supports checks of static constants values ");
+
+ String[] args = createTestArguments(packageListFile, mapFile,
+ signatureRepositoryDir, packageName, classpath, true);
+ dumpTestArguments(args);
+
+ if (runSignatureTest(packageName, args)) {
+ logger.log(Logger.Level.INFO, "********** Package '" + packageName
+ + "' - PASSED (STATIC MODE) **********");
+ result.addPassedPkg(packageName + "(static mode)");
+ } else {
+ result.addFailedPkg(packageName + "(static mode)");
+ logger.log(Logger.Level.INFO, "********** Package '" + packageName
+ + "' - FAILED (STATIC MODE) **********");
+ }
+
+ logger.log(Logger.Level.INFO, "\n\n");
+ logger.log(Logger.Level.INFO, "********** VALIDATE IN REFLECTIVE MODE ****");
+ logger.log(Logger.Level.INFO,
+ "Reflective mode supports verification within containers (ie ejb, servlet, etc)");
+
+ String[] args2 = createTestArguments(packageListFile, mapFile,
+ signatureRepositoryDir, packageName, classpath, false);
+ dumpTestArguments(args2);
+
+ if (runSignatureTest(packageName, args2)) {
+ logger.log(Logger.Level.INFO, "********** Package '" + packageName
+ + "' - PASSED (REFLECTION MODE) **********");
+ result.addPassedPkg(packageName + "(reflection mode)");
+ } else {
+ result.addFailedPkg(packageName + "(reflection mode)");
+ logger.log(Logger.Level.INFO, "********** Package '" + packageName
+ + "' - FAILED (REFLECTION MODE) **********");
+ }
+
+ logger.log(Logger.Level.INFO, "********** END VALIDATE PACKAGE '"
+ + packagesUnderTest[i] + "' **********\n");
+
+ logger.log(Logger.Level.INFO, "\n");
+ logger.log(Logger.Level.INFO, "\n");
+
+ }
+ }
+
+ if (classesUnderTest != null && classesUnderTest.length > 0) {
+ logger.log(Logger.Level.INFO, "********** BEGIN CLASS LEVEL SIGNATURE "
+ + "VALIDATION **********\n\n");
+
+ for (int i = 0; i < classesUnderTest.length; i++) {
+
+ String className = classesUnderTest[i];
+
+ logger.log(Logger.Level.INFO, "********** BEGIN VALIDATE CLASS '"
+ + classesUnderTest[i] + "' **********\n");
+
+ logger.log(Logger.Level.INFO,
+ "********** VALIDATE IN STATIC MODE - TO CHECK CONSANT VALUES ****");
+ logger.log(Logger.Level.INFO, "Static mode supports checks of static constants values ");
+
+ String[] args = createTestArguments(packageListFile, mapFile,
+ signatureRepositoryDir, className, classpath, true);
+ dumpTestArguments(args);
+
+ if (runSignatureTest(className, args)) {
+ logger.log(Logger.Level.INFO, "********** Class '" + className
+ + "' - PASSED (STATIC MODE) **********");
+ result.addPassedClass(className + "(static mode)");
+ } else {
+ logger.log(Logger.Level.INFO, "********** Class '" + className
+ + "' - FAILED (STATIC MODE) **********");
+ result.addFailedClass(className + "(static mode)");
+ }
+
+ logger.log(Logger.Level.INFO, "\n\n");
+ logger.log(Logger.Level.INFO, "********** VALIDATE IN REFLECTIVE MODE ****");
+ logger.log(Logger.Level.INFO,
+ "Reflective mode supports verification within containers (ie ejb, servlet, etc)");
+
+ String[] args2 = createTestArguments(packageListFile, mapFile,
+ signatureRepositoryDir, className, classpath, false);
+ dumpTestArguments(args2);
+
+ if (runSignatureTest(className, args2)) {
+ logger.log(Logger.Level.INFO, "********** Class '" + className
+ + "' - PASSED (REFLECTION MODE) **********");
+ result.addPassedClass(className + "(reflection mode)");
+ } else {
+ logger.log(Logger.Level.INFO, "********** Class '" + className
+ + "' - FAILED (REFLECTION MODE) **********");
+ result.addFailedClass(className + "(reflection mode)");
+ }
+
+ logger.log(Logger.Level.INFO, "********** END VALIDATE CLASS '" + classesUnderTest[i]
+ + "' **********\n");
+
+ logger.log(Logger.Level.INFO, "\n");
+ logger.log(Logger.Level.INFO, "\n");
+
+ }
+ }
+
+ return result;
+
+ } // END executeSigTest
+
+ // ------------------------------------------------------- Protected Methods
+
+ /**
+ * Using a common set of information, create arguments that are appropriate to
+ * be used with the underlying signature test framework.
+ *
+ * @param packageListFile
+ * - file containing the packages/classes that are to be verified
+ * @param mapFile
+ * sig-test.map file
+ * @param signatureRepositoryDir
+ * directory containing the recorded signatures
+ * @param packageOrClassUnderTest
+ * the class or package
+ * @param classpath
+ * The location of the API being verified. Normally the checked API
+ * will be available in the test environment and testClasspath will
+ * be null. In some rare cases the tested API may not be part of the
+ * test environment and will have to specified using this parameter.
+ */
+ protected abstract String[] createTestArguments(String packageListFile,
+ String mapFile, String signatureRepositoryDir,
+ String packageOrClassUnderTest, String classpath, boolean bStaticMode)
+ throws Exception;
+
+ /**
+ * Invoke the underlying signature test framework for the specified package or
+ * class.
+ *
+ * @param packageOrClassName
+ * the package or class to be validated
+ * @param testArguments
+ * the arguments necessary to invoke the signature test framework
+ *
+ * @return true
if the test passed, otherwise false
+ */
+ protected abstract boolean runSignatureTest(String packageOrClassName,
+ String[] testArguments) throws Exception;
+
+
+ /**
+ * Loads the specified file into a Properties object provided the specified
+ * file exists and is a regular file. The call to new FileInputStream verifies
+ * that the specfied file is a regular file and exists.
+ *
+ * @param mapFile
+ * the path and name of the map file to be loaded
+ *
+ * @return Properties The Properties object initialized with the contents of
+ * the specified file
+ *
+ * @throws java.io.IOException
+ * If the specified map file does not exist or is not a regular
+ * file, can also be thrown if there is an error creating an input
+ * stream from the specified file.
+ */
+ public Properties loadMapFile(String mapFile)
+ throws IOException, FileNotFoundException {
+
+ FileInputStream in = null;
+ try {
+ File map = new File(mapFile);
+ Properties props = new Properties();
+ in = new FileInputStream(map);
+ props.load(in);
+ return props;
+ } finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ } catch (Throwable t) {
+ // do nothing
+ }
+ }
+
+ } // END loadMapFile
+
+ /**
+ * This method will attempt to build a fully-qualified filename in the format
+ * of respositoryDir
+ baseName +
+ * .sig_
+ version.
+ *
+ * @param baseName
+ * the base portion of the signature filename
+ * @param repositoryDir
+ * the directory in which the signatures are stored
+ * @param version
+ * the version of the signature file
+ * @throws FileNotFoundException
+ * if the file cannot be validated as existing and is in fact a file
+ * @return a valid, fully qualified filename, appropriate for the system the
+ * test is being run on
+ */
+ protected String getSigFileName(String baseName, String repositoryDir,
+ String version) throws FileNotFoundException {
+
+ String sigFile;
+ if (repositoryDir.endsWith(File.separator)) {
+ sigFile = repositoryDir + baseName + SIG_FILE_EXT + SIG_FILE_VER_SEP
+ + version;
+ } else {
+ sigFile = repositoryDir + File.separator + baseName + SIG_FILE_EXT
+ + SIG_FILE_VER_SEP + version;
+ }
+
+ File testFile = new File(sigFile);
+
+ if (!testFile.exists() && !testFile.isFile()) {
+ throw new FileNotFoundException(
+ "Signature file \"" + sigFile + "\" does not exist.");
+ }
+
+ // we are actually requiring this normalizeFileName call to get
+ // things working on Windows. Without this, if we just return the
+ // testFile; we will fail on windows. (Solaris works either way)
+ // IMPORTANT UPDATE!! (4/5/2011)
+ // in sigtest 2.2: they stopped supporting the normalized version which
+ // created a string filename =
+ // "file://com/sun/ts/tests/signaturetest/foo.sig"
+ // so now use file path and name only.
+ // return normalizeFileName(testFile);
+ return testFile.toString();
+
+ } // END getSigFileName
+
+
+ /**
+ * Returns the name and path to the signature file that contains the specified
+ * package's signatures.
+ *
+ * @param packageName
+ * The package under test
+ * @param mapFile
+ * The name of the file that maps package names to versions
+ * @param repositoryDir
+ * The directory that conatisn all signature files
+ *
+ * @return String The path and name of the siganture file that contains the
+ * specified package's signatures
+ *
+ * @throws Exception
+ * if the determined signature file is not a regular file or does
+ * not exist
+ */
+ protected SignatureFileInfo getSigFileInfo(String packageName, String mapFile,
+ String repositoryDir) throws Exception {
+
+ String originalPackage = packageName;
+ String name = null;
+ String version = null;
+ Properties props = loadMapFile(mapFile);
+
+ while (true) {
+ boolean packageFound = false;
+ for (Enumeration> e = props.propertyNames(); e.hasMoreElements();) {
+ name = (String) (e.nextElement());
+ if (name.equals(packageName)) {
+ version = props.getProperty(name);
+ packageFound = true;
+ break;
+ } // end if
+ } // end for
+
+ if (packageFound) {
+ break;
+ }
+
+ /*
+ * If we get here we did not find a package name in the properties file
+ * that matches the package name under test. So we look for a package name
+ * in the properties file that could be the parent package for the package
+ * under test. We do this by removing the specified packages last package
+ * name section. So jakarta.ejb.spi would become jakarta.ejb
+ */
+ int index = packageName.lastIndexOf(".");
+ if (index <= 0) {
+ throw new Exception("Package \"" + originalPackage
+ + "\" not specified in mapping file \"" + mapFile + "\".");
+ }
+ packageName = packageName.substring(0, index);
+ } // end while
+
+ /* Return the expected name of the signature file */
+
+ return new SignatureFileInfo(getSigFileName(name, repositoryDir, version),
+ version);
+
+ } // END getSigFileInfo
+
+ // --------------------------------------------------------- Private Methods
+
+ /**
+ * Prints the specified list of parameters to the message log. Used for
+ * debugging purposes only.
+ *
+ * @param params
+ * The list of parameters to dump.
+ */
+ private static void dumpTestArguments(String[] params) {
+
+ if (params != null && params.length > 0) {
+ logger.log(Logger.Level.TRACE, "----------------- BEGIN SIG PARAM DUMP -----------------");
+ for (int i = 0; i < params.length; i++) {
+ logger.log(Logger.Level.TRACE, " Param[" + i + "]: " + params[i]);
+ }
+ logger.log(Logger.Level.TRACE, "------------------ END SIG PARAM DUMP ------------------");
+ }
+
+ } // END dumpTestArguments
+
+ // ----------------------------------------------------------- Inner Classes
+
+ /**
+ * A simple data structure containing the fully qualified path to the
+ * signature file as well as the version being tested.
+ */
+ protected static class SignatureFileInfo {
+
+ private String file;
+
+ private String version;
+
+ // -------------------------------------------------------- Constructors
+
+ public SignatureFileInfo(String file, String version) {
+
+ if (file == null) {
+ throw new IllegalArgumentException("'file' argument cannot be null");
+ }
+
+ if (version == null) {
+ throw new IllegalArgumentException("'version' argument cannot be null");
+ }
+
+ this.file = file;
+ this.version = version;
+
+ } // END SignatureFileInfo
+
+ // ------------------------------------------------------ Public Methods
+
+ public String getFile() {
+
+ return file;
+
+ } // END getFileIncludingPath
+
+ public String getVersion() {
+
+ return version;
+
+ } // END getVersion
+
+ }
+
+} // END SigTestDriver
diff --git a/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SignatureTestDriverFactory.java b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SignatureTestDriverFactory.java
new file mode 100644
index 0000000000..aa22502de7
--- /dev/null
+++ b/el/src/main/java/com/sun/ts/tests/el/signaturetest/el/SignatureTestDriverFactory.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2007, 2024 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.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+
+package com.sun.ts.tests.signaturetest.el;
+
+/**
+ *
+ * Factory to obtain SignatureTestDriver implementations. + *
+ */ +public class SignatureTestDriverFactory { + + /** + *+ * Identifier for the driver that uses the Signature Test framwork for + * signature validation. + *
+ */ + public static final String SIG_TEST = "sigtest"; + + // ------------------------------------------------------------ Constructors + + // Access via factory method + private SignatureTestDriverFactory() { + } // END SignatureTestDriverFactory + + // ---------------------------------------------------------- Public Methods + + /** + *
+ * Obtain a {@link SignatureTestDriver} instance based on the
+ * type
argument.
+ *
+ * @param type
+ * the driver type to create
+ * @return a {@link SignatureTestDriver} implementation
+ */
+ public static SignatureTestDriver getInstance(String type) {
+
+ if (type == null || type.length() == 0) {
+ throw new IllegalArgumentException("Type was null or empty");
+ }
+
+ if (SIG_TEST.equals(type)) {
+ return new SigTestDriver();
+ } else {
+ throw new IllegalArgumentException("Unknown Type: '" + type + '\'');
+ }
+
+ } // END getInstance
+
+} // END SignatureTestDriverFactory