tzaeschke commented on code in PR #85:
URL: https://github.com/apache/db-jdo/pull/85#discussion_r1383891081


##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -140,37 +141,178 @@ private String getTrimmedPropertyValue(Properties props, 
String key) {
     return value == null ? "" : value.trim();
   }
 
+  private static String fileToString(String fileName) {
+    try {
+      byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+      return new String(encoded);
+    } catch (IOException ex) {
+      return "Problems reading " + fileName + ": " + ex.getMessage();
+    }
+  }
+
+  /** */
   @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
+  public void execute() throws MojoExecutionException {
     if (!doRunTCK) {
       System.out.println("Skipping RunTCK goal!");
       return;
     }
 
-    Properties props = null;
     boolean alreadyran = false;
-    String runonce = "false";
-    List<String> propsString = new ArrayList<>();
-    List<String> command;
+    boolean runonce = false;
     String cpString = null;
-    InvocationResult result;
-    File fromFile = null;
-    File toFile = null;
 
+    List<String> propsString = initTCKRun();
+    String excludeFile = confDirectory + File.separator + exclude;
+    propsString.add(
+        "-Djdo.tck.exclude="
+            + 
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude"));
+
+    // Create configuration log directory
+    String thisLogDir = logsDirectory + File.separator + Utilities.now();

Review Comment:
   Why `this`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -116,17 +117,17 @@ public class RunTCK extends AbstractTCKMojo {
 
   /** Class used to run a batch of tests. */
   @Parameter(
-      property = "jdo.tck.testrunnerclass",
-      defaultValue = "org.apache.jdo.tck.util.BatchTestRunner",
+      property = "jdo.tck.testrunner.class",
+      defaultValue = "org.junit.platform.console.ConsoleLauncher",
       required = true)
   private String testRunnerClass;
 
-  /** Class used to output test result and configuration information. */
-  @Parameter(
-      property = "jdo.tck.resultprinterclass",
-      defaultValue = "org.apache.jdo.tck.util.BatchResultPrinter",
-      required = true)
-  private String resultPrinterClass;
+  /**
+   * output details mode for test run. Use one of: none, summary, flat, tree, 
verbose, testfeed. If

Review Comment:
   Is this sentence complete? Maybe change to "Output mode for test run ..."



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -140,37 +141,178 @@ private String getTrimmedPropertyValue(Properties props, 
String key) {
     return value == null ? "" : value.trim();
   }
 
+  private static String fileToString(String fileName) {
+    try {
+      byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+      return new String(encoded);
+    } catch (IOException ex) {
+      return "Problems reading " + fileName + ": " + ex.getMessage();
+    }
+  }
+
+  /** */
   @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
+  public void execute() throws MojoExecutionException {
     if (!doRunTCK) {
       System.out.println("Skipping RunTCK goal!");
       return;
     }
 
-    Properties props = null;
     boolean alreadyran = false;
-    String runonce = "false";
-    List<String> propsString = new ArrayList<>();
-    List<String> command;
+    boolean runonce = false;
     String cpString = null;
-    InvocationResult result;
-    File fromFile = null;
-    File toFile = null;
 
+    List<String> propsString = initTCKRun();
+    String excludeFile = confDirectory + File.separator + exclude;
+    propsString.add(
+        "-Djdo.tck.exclude="
+            + 
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude"));
+
+    // Create configuration log directory
+    String thisLogDir = logsDirectory + File.separator + Utilities.now();
+    String cfgDirName = thisLogDir + File.separator + "configuration";
+    File cfgDir = new File(cfgDirName);
+    if (!(cfgDir.exists()) && !(cfgDir.mkdirs())) {
+      throw new MojoExecutionException("Failed to create directory " + 
cfgDirName);
+    }
+    propsString.add("-Djdo.tck.log.directory=" + thisLogDir);
+
+    copyConfigurationFiles();
+
+    // Get ClassLoader URLs to build classpath below
+    List<URL> urlList =
+        new ArrayList<>(
+            Arrays.asList(
+                ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs()));
+
+    // Get contents of pmf properties file to build new file below
+    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
+    String defaultPropsContents = "";
+    try {
+      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+
+    // Reset logfile content (may not be empty if previous run crashed)
+    resetFileContent(implLogFile);
+    resetFileContent(TCK_LOG_FILE);
+
+    int failureCount = 0;
+    for (String db : dbs) {
+      System.setProperty("jdo.tck.database", db);
+      alreadyran = false;

Review Comment:
   `alreadyrun` -> `alreadyRun`



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)
+      throws MojoExecutionException {
+    String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
+    if (classes == null) {
+      throw new MojoExecutionException("Could not find classes value in conf 
file: " + cfg);
+    }
+    String excludeList =
+        getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
+    classes = Utilities.removeSubstrs(classes, excludeList);
+    List<String> classesList = new ArrayList();
+    PropertyUtils.string2Collection(classes, classesList);
+    return classesList;
+  }
 
-          // invoke class runner
-          System.out.print(
-              "*> Running tests for "
-                  + cfg
-                  + " with "
-                  + idtype
-                  + " on '"
-                  + db
-                  + "'"
-                  + " mapping="
-                  + mapping
-                  + " ... ");
-          try {
-            result = (new Utilities()).invokeTest(command);
-            if (result.getExitValue() == 0) {
-              System.out.println("success");
-            } else {
-              System.out.println("FAIL");
-              failureCount++;
-            }
-            if (runtckVerbose) {
-              System.out.println("\nCommand line is: \n" + command.toString());
-              System.out.println("Test exit value is " + 
result.getExitValue());
-              System.out.println("Test result output:\n" + 
result.getOutputString());
-              System.out.println("Test result error:\n" + 
result.getErrorString());
-            }
-          } catch (java.lang.RuntimeException re) {
-            System.out.println("Exception on command " + command);
-          }
+  /**
+   * Returns the perfix of the log file name. It includes the path, followed 
by an indicator for the
+   * identitytype followed by the name of the configuration.
+   *
+   * @param thisLogDir
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @return
+   */
+  private String getLogFilePrefix(String thisLogDir, String idtype, String 
cfg) {
+    String idname = idtype.trim().equals("applicationidentity") ? "app" : 
"dsid";
+    String configName = cfg.indexOf('.') > 0 ? cfg.substring(0, 
cfg.indexOf('.')) : cfg;
+    return thisLogDir + File.separator + idname + "-" + configName + "-";
+  }
 
-          // Move log to per-test location
-          String idname = "dsid";
-          if (idtype.trim().equals("applicationidentity")) {
-            idname = "app";
-          }
-          String configName = cfg;
-          if (cfg.indexOf('.') > 0) {
-            configName = configName.substring(0, cfg.indexOf('.'));
-          }
-          String testLogFilename = thisLogDir + idname + "-" + configName + 
"-" + impl + ".txt";
-          try {
-            File logFile = new File(implLogFile);
-            FileUtils.copyFile(logFile, new File(testLogFilename));
-            resetFileContent(implLogFile);
-          } catch (Exception e) {
-            System.out.println(">> Error copying implementation log file: " + 
e.getMessage());
-          }
-          String tckLogFilename = thisLogDir + idname + "-" + configName + "-" 
+ TCK_LOG_FILE;
-          try {
-            File logFile = new File(TCK_LOG_FILE);
-            FileUtils.copyFile(logFile, new File(tckLogFilename));
-            resetFileContent(TCK_LOG_FILE);
-          } catch (Exception e) {
-            System.out.println(">> Error copying tck log file: " + 
e.getMessage());
-          }
+  /**
+   * Creates the java command to run a TCK test class and executes the command.
+   *
+   * @param cpString classpath
+   * @param cfgPropsString configuration properties
+   * @param classesList
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param db the database
+   * @param mapping the mapping index
+   * @param
+   * @param
+   * @param thisLogFilePrefix
+   * @return
+   */
+  private int executeTestClass(
+      String cpString,
+      List<String> cfgPropsString,
+      List<String> classesList,
+      String idtype,
+      String cfg,
+      String db,
+      String mapping,
+      String thisLogFilePrefix) {
+    // build command line string
+    List<String> command = new ArrayList<>();
+    command.add("java");
+    command.add("-cp");
+    command.add(cpString);
+    command.addAll(cfgPropsString);
+    command.add(dbproperties);
+    command.add(jvmproperties);
+    if (debugTCK) {
+      command.add(debugDirectives);
+    }
+    command.add(testRunnerClass);
+    command.add("--disable-banner");
+    command.add("--details=" + testRunnerDetails);
+    // add Test classes
+    for (String testClass : classesList) {
+      // skip empty entries
+      if (testClass != null && testClass.trim().length() > 0) {
+        command.add("-c");
+        command.add(testClass);
+      }
+    }
 
-          if (runonce.equals("true")) {
-            alreadyran = true;
-          }
+    if (debugTCK) {
+      System.out.println("Using debug arguments: \n" + debugDirectives);
+    }
 
-          if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount 
> 0) {
-            break;
-          }
-        }
-        if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-          break;
-        }
+    // invoke class runner
+    System.out.print(
+        "*> Running tests for "
+            + cfg
+            + " with "
+            + idtype
+            + " on '"
+            + db
+            + "'"
+            + " mapping="
+            + mapping
+            + " ... ");
+
+    String junitLogFilename = thisLogFilePrefix + JUNIT_LOG_FILE;
+    int resultValue = 0;
+    try {
+      resultValue = Utilities.invokeCommand(command, new File(buildDirectory), 
junitLogFilename);
+      if (resultValue == 0) {
+        System.out.println("success");
+      } else {
+        System.out.println("FAIL");
       }
-      if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-        break;
+      if (runtckVerbose) {
+        System.out.println("\nCommand line is: \n" + command.toString());
+        System.out.println("Test exit value is " + resultValue);
+        System.out.println("Test result output:\n" + 
fileToString(junitLogFilename));
       }
+    } catch (java.lang.RuntimeException re) {
+      System.out.println("Exception on command " + command);
+    }
+    return resultValue;
+  }
+
+  /**
+   * Copies the implementation log file and TCK log file to the current log 
directory
+   *
+   * @param thisLogFilePrefix the prefix of the log file consisting of idtype 
and conf
+   */
+  private void handleLogFiles(String thisLogFilePrefix) {
+    // Move log to per-test location
+    String testLogFilename = thisLogFilePrefix + impl + ".txt";
+    try {
+      File logFile = new File(implLogFile);
+      FileUtils.copyFile(logFile, new File(testLogFilename));
+      resetFileContent(implLogFile);
+    } catch (Exception e) {
+      System.out.println(">> Error copying implementation log file: " + 
e.getMessage());
+    }
+    String tckLogFilename = thisLogFilePrefix + TCK_LOG_FILE;
+    try {
+      File logFile = new File(TCK_LOG_FILE);
+      FileUtils.copyFile(logFile, new File(tckLogFilename));
+      resetFileContent(TCK_LOG_FILE);
+    } catch (Exception e) {
+      System.out.println(">> Error copying tck log file: " + e.getMessage());
     }
+  }
+
+  /**
+   * Finalizes the TCK run: delete log files create the result summray file 
TCK-results.txt create
+   * system configuration description file Copy metadata from enhanced to 
configuration logs
+   * directory This method is called once per TCK run.
+   *
+   * @param thisLogDir the path of the log directory
+   * @param cpString classpath
+   * @param cfgDirName configuration directory
+   * @param failureCount number of TCK test failures
+   * @throws MojoExecutionException
+   */
+  private void finitTCKRun(String thisLogDir, String cpString, String 
cfgDirName, int failureCount)

Review Comment:
   This look like a typo -> `finishTCKRun` / `finalizeTCKRun`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)
+      throws MojoExecutionException {
+    String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
+    if (classes == null) {
+      throw new MojoExecutionException("Could not find classes value in conf 
file: " + cfg);
+    }
+    String excludeList =
+        getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
+    classes = Utilities.removeSubstrs(classes, excludeList);
+    List<String> classesList = new ArrayList();
+    PropertyUtils.string2Collection(classes, classesList);
+    return classesList;
+  }
 
-          // invoke class runner
-          System.out.print(
-              "*> Running tests for "
-                  + cfg
-                  + " with "
-                  + idtype
-                  + " on '"
-                  + db
-                  + "'"
-                  + " mapping="
-                  + mapping
-                  + " ... ");
-          try {
-            result = (new Utilities()).invokeTest(command);
-            if (result.getExitValue() == 0) {
-              System.out.println("success");
-            } else {
-              System.out.println("FAIL");
-              failureCount++;
-            }
-            if (runtckVerbose) {
-              System.out.println("\nCommand line is: \n" + command.toString());
-              System.out.println("Test exit value is " + 
result.getExitValue());
-              System.out.println("Test result output:\n" + 
result.getOutputString());
-              System.out.println("Test result error:\n" + 
result.getErrorString());
-            }
-          } catch (java.lang.RuntimeException re) {
-            System.out.println("Exception on command " + command);
-          }
+  /**
+   * Returns the perfix of the log file name. It includes the path, followed 
by an indicator for the
+   * identitytype followed by the name of the configuration.
+   *
+   * @param thisLogDir
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @return
+   */
+  private String getLogFilePrefix(String thisLogDir, String idtype, String 
cfg) {
+    String idname = idtype.trim().equals("applicationidentity") ? "app" : 
"dsid";
+    String configName = cfg.indexOf('.') > 0 ? cfg.substring(0, 
cfg.indexOf('.')) : cfg;
+    return thisLogDir + File.separator + idname + "-" + configName + "-";
+  }
 
-          // Move log to per-test location
-          String idname = "dsid";
-          if (idtype.trim().equals("applicationidentity")) {
-            idname = "app";
-          }
-          String configName = cfg;
-          if (cfg.indexOf('.') > 0) {
-            configName = configName.substring(0, cfg.indexOf('.'));
-          }
-          String testLogFilename = thisLogDir + idname + "-" + configName + 
"-" + impl + ".txt";
-          try {
-            File logFile = new File(implLogFile);
-            FileUtils.copyFile(logFile, new File(testLogFilename));
-            resetFileContent(implLogFile);
-          } catch (Exception e) {
-            System.out.println(">> Error copying implementation log file: " + 
e.getMessage());
-          }
-          String tckLogFilename = thisLogDir + idname + "-" + configName + "-" 
+ TCK_LOG_FILE;
-          try {
-            File logFile = new File(TCK_LOG_FILE);
-            FileUtils.copyFile(logFile, new File(tckLogFilename));
-            resetFileContent(TCK_LOG_FILE);
-          } catch (Exception e) {
-            System.out.println(">> Error copying tck log file: " + 
e.getMessage());
-          }
+  /**
+   * Creates the java command to run a TCK test class and executes the command.
+   *
+   * @param cpString classpath
+   * @param cfgPropsString configuration properties
+   * @param classesList
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param db the database
+   * @param mapping the mapping index
+   * @param
+   * @param
+   * @param thisLogFilePrefix
+   * @return
+   */
+  private int executeTestClass(
+      String cpString,
+      List<String> cfgPropsString,
+      List<String> classesList,
+      String idtype,
+      String cfg,
+      String db,
+      String mapping,
+      String thisLogFilePrefix) {
+    // build command line string
+    List<String> command = new ArrayList<>();
+    command.add("java");
+    command.add("-cp");
+    command.add(cpString);
+    command.addAll(cfgPropsString);
+    command.add(dbproperties);
+    command.add(jvmproperties);
+    if (debugTCK) {
+      command.add(debugDirectives);
+    }
+    command.add(testRunnerClass);
+    command.add("--disable-banner");
+    command.add("--details=" + testRunnerDetails);
+    // add Test classes
+    for (String testClass : classesList) {
+      // skip empty entries
+      if (testClass != null && testClass.trim().length() > 0) {
+        command.add("-c");
+        command.add(testClass);
+      }
+    }
 
-          if (runonce.equals("true")) {
-            alreadyran = true;
-          }
+    if (debugTCK) {
+      System.out.println("Using debug arguments: \n" + debugDirectives);
+    }
 
-          if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount 
> 0) {
-            break;
-          }
-        }
-        if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-          break;
-        }
+    // invoke class runner
+    System.out.print(
+        "*> Running tests for "
+            + cfg
+            + " with "
+            + idtype
+            + " on '"
+            + db
+            + "'"
+            + " mapping="
+            + mapping
+            + " ... ");
+
+    String junitLogFilename = thisLogFilePrefix + JUNIT_LOG_FILE;
+    int resultValue = 0;
+    try {
+      resultValue = Utilities.invokeCommand(command, new File(buildDirectory), 
junitLogFilename);
+      if (resultValue == 0) {
+        System.out.println("success");
+      } else {
+        System.out.println("FAIL");
       }
-      if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-        break;
+      if (runtckVerbose) {
+        System.out.println("\nCommand line is: \n" + command.toString());
+        System.out.println("Test exit value is " + resultValue);
+        System.out.println("Test result output:\n" + 
fileToString(junitLogFilename));
       }
+    } catch (java.lang.RuntimeException re) {
+      System.out.println("Exception on command " + command);
+    }
+    return resultValue;
+  }
+
+  /**
+   * Copies the implementation log file and TCK log file to the current log 
directory
+   *
+   * @param thisLogFilePrefix the prefix of the log file consisting of idtype 
and conf
+   */
+  private void handleLogFiles(String thisLogFilePrefix) {

Review Comment:
   Maybe rename to `copyLogFiles`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -140,37 +141,178 @@ private String getTrimmedPropertyValue(Properties props, 
String key) {
     return value == null ? "" : value.trim();
   }
 
+  private static String fileToString(String fileName) {
+    try {
+      byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+      return new String(encoded);
+    } catch (IOException ex) {
+      return "Problems reading " + fileName + ": " + ex.getMessage();
+    }
+  }
+
+  /** */
   @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
+  public void execute() throws MojoExecutionException {
     if (!doRunTCK) {
       System.out.println("Skipping RunTCK goal!");
       return;
     }
 
-    Properties props = null;
     boolean alreadyran = false;
-    String runonce = "false";
-    List<String> propsString = new ArrayList<>();
-    List<String> command;
+    boolean runonce = false;
     String cpString = null;
-    InvocationResult result;
-    File fromFile = null;
-    File toFile = null;
 
+    List<String> propsString = initTCKRun();
+    String excludeFile = confDirectory + File.separator + exclude;
+    propsString.add(
+        "-Djdo.tck.exclude="
+            + 
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude"));
+
+    // Create configuration log directory
+    String thisLogDir = logsDirectory + File.separator + Utilities.now();
+    String cfgDirName = thisLogDir + File.separator + "configuration";
+    File cfgDir = new File(cfgDirName);
+    if (!(cfgDir.exists()) && !(cfgDir.mkdirs())) {

Review Comment:
   Simplify to `if (!cfgDir.exists() && !cfgDir.mkdirs())` ?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -238,8 +371,8 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
 
     // Copy JDO config files to classes dir
     try {
-      fromFile = new File(confDirectory + File.separator + impl + 
"-jdoconfig.xml");
-      toFile =
+      File fromFile = new File(confDirectory + File.separator + impl + 
"-jdoconfig.xml");

Review Comment:
   Maybe replace the 30+ occurences of `File.separate` with a short constant, 
e.g. `String FS = File.separator; `? This may make the code more compact.



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -528,13 +693,14 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
               + File.separator;
       String[] metadataExtensions = {"jdo", "jdoquery", "orm", "xml", 
"properties"};
       String fromFileName = null;
+      File toFile = null;
       String pkgName = null;
       int startIdx = -1;
       // iterator over list of abs name of metadata files in src
       Iterator<File> fi = FileUtils.iterateFiles(new File(fromDirName), 
metadataExtensions, true);
       while (fi.hasNext()) {
         try {
-          fromFile = fi.next();
+          File fromFile = fi.next();

Review Comment:
   I know this was already in p[lace before the refactoring. However: 
   
   - I think this may be cleaner if the try-clause only contained the 
FileUtil.copy 
   - Why not move() the file here?
   - If the try-clause is minimized, All variables can be declared in-place: 
fromFileName, pkgName, toFile.
   



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;

Review Comment:
   This may be an actual bug. `mapping` is assigned here, but the new value is 
never exported outside the method.



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)
+      throws MojoExecutionException {
+    String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
+    if (classes == null) {
+      throw new MojoExecutionException("Could not find classes value in conf 
file: " + cfg);
+    }
+    String excludeList =
+        getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
+    classes = Utilities.removeSubstrs(classes, excludeList);
+    List<String> classesList = new ArrayList();
+    PropertyUtils.string2Collection(classes, classesList);
+    return classesList;
+  }
 
-          // invoke class runner
-          System.out.print(
-              "*> Running tests for "
-                  + cfg
-                  + " with "
-                  + idtype
-                  + " on '"
-                  + db
-                  + "'"
-                  + " mapping="
-                  + mapping
-                  + " ... ");
-          try {
-            result = (new Utilities()).invokeTest(command);
-            if (result.getExitValue() == 0) {
-              System.out.println("success");
-            } else {
-              System.out.println("FAIL");
-              failureCount++;
-            }
-            if (runtckVerbose) {
-              System.out.println("\nCommand line is: \n" + command.toString());
-              System.out.println("Test exit value is " + 
result.getExitValue());
-              System.out.println("Test result output:\n" + 
result.getOutputString());
-              System.out.println("Test result error:\n" + 
result.getErrorString());
-            }
-          } catch (java.lang.RuntimeException re) {
-            System.out.println("Exception on command " + command);
-          }
+  /**
+   * Returns the perfix of the log file name. It includes the path, followed 
by an indicator for the
+   * identitytype followed by the name of the configuration.
+   *
+   * @param thisLogDir
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @return
+   */
+  private String getLogFilePrefix(String thisLogDir, String idtype, String 
cfg) {

Review Comment:
   remove `this` from `thisLogDir`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)
+      throws MojoExecutionException {
+    String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
+    if (classes == null) {
+      throw new MojoExecutionException("Could not find classes value in conf 
file: " + cfg);
+    }
+    String excludeList =
+        getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
+    classes = Utilities.removeSubstrs(classes, excludeList);
+    List<String> classesList = new ArrayList();
+    PropertyUtils.string2Collection(classes, classesList);
+    return classesList;
+  }
 
-          // invoke class runner
-          System.out.print(
-              "*> Running tests for "
-                  + cfg
-                  + " with "
-                  + idtype
-                  + " on '"
-                  + db
-                  + "'"
-                  + " mapping="
-                  + mapping
-                  + " ... ");
-          try {
-            result = (new Utilities()).invokeTest(command);
-            if (result.getExitValue() == 0) {
-              System.out.println("success");
-            } else {
-              System.out.println("FAIL");
-              failureCount++;
-            }
-            if (runtckVerbose) {
-              System.out.println("\nCommand line is: \n" + command.toString());
-              System.out.println("Test exit value is " + 
result.getExitValue());
-              System.out.println("Test result output:\n" + 
result.getOutputString());
-              System.out.println("Test result error:\n" + 
result.getErrorString());
-            }
-          } catch (java.lang.RuntimeException re) {
-            System.out.println("Exception on command " + command);
-          }
+  /**
+   * Returns the perfix of the log file name. It includes the path, followed 
by an indicator for the
+   * identitytype followed by the name of the configuration.
+   *
+   * @param thisLogDir
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @return
+   */
+  private String getLogFilePrefix(String thisLogDir, String idtype, String 
cfg) {
+    String idname = idtype.trim().equals("applicationidentity") ? "app" : 
"dsid";
+    String configName = cfg.indexOf('.') > 0 ? cfg.substring(0, 
cfg.indexOf('.')) : cfg;
+    return thisLogDir + File.separator + idname + "-" + configName + "-";
+  }
 
-          // Move log to per-test location
-          String idname = "dsid";
-          if (idtype.trim().equals("applicationidentity")) {
-            idname = "app";
-          }
-          String configName = cfg;
-          if (cfg.indexOf('.') > 0) {
-            configName = configName.substring(0, cfg.indexOf('.'));
-          }
-          String testLogFilename = thisLogDir + idname + "-" + configName + 
"-" + impl + ".txt";
-          try {
-            File logFile = new File(implLogFile);
-            FileUtils.copyFile(logFile, new File(testLogFilename));
-            resetFileContent(implLogFile);
-          } catch (Exception e) {
-            System.out.println(">> Error copying implementation log file: " + 
e.getMessage());
-          }
-          String tckLogFilename = thisLogDir + idname + "-" + configName + "-" 
+ TCK_LOG_FILE;
-          try {
-            File logFile = new File(TCK_LOG_FILE);
-            FileUtils.copyFile(logFile, new File(tckLogFilename));
-            resetFileContent(TCK_LOG_FILE);
-          } catch (Exception e) {
-            System.out.println(">> Error copying tck log file: " + 
e.getMessage());
-          }
+  /**
+   * Creates the java command to run a TCK test class and executes the command.
+   *
+   * @param cpString classpath
+   * @param cfgPropsString configuration properties
+   * @param classesList
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param db the database
+   * @param mapping the mapping index
+   * @param
+   * @param
+   * @param thisLogFilePrefix
+   * @return
+   */
+  private int executeTestClass(
+      String cpString,
+      List<String> cfgPropsString,
+      List<String> classesList,
+      String idtype,
+      String cfg,
+      String db,
+      String mapping,
+      String thisLogFilePrefix) {
+    // build command line string
+    List<String> command = new ArrayList<>();
+    command.add("java");
+    command.add("-cp");
+    command.add(cpString);
+    command.addAll(cfgPropsString);
+    command.add(dbproperties);
+    command.add(jvmproperties);
+    if (debugTCK) {
+      command.add(debugDirectives);
+    }
+    command.add(testRunnerClass);
+    command.add("--disable-banner");
+    command.add("--details=" + testRunnerDetails);
+    // add Test classes
+    for (String testClass : classesList) {
+      // skip empty entries
+      if (testClass != null && testClass.trim().length() > 0) {
+        command.add("-c");
+        command.add(testClass);
+      }
+    }
 
-          if (runonce.equals("true")) {
-            alreadyran = true;
-          }
+    if (debugTCK) {
+      System.out.println("Using debug arguments: \n" + debugDirectives);
+    }
 
-          if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount 
> 0) {
-            break;
-          }
-        }
-        if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-          break;
-        }
+    // invoke class runner
+    System.out.print(
+        "*> Running tests for "
+            + cfg
+            + " with "
+            + idtype
+            + " on '"
+            + db
+            + "'"
+            + " mapping="
+            + mapping
+            + " ... ");
+
+    String junitLogFilename = thisLogFilePrefix + JUNIT_LOG_FILE;
+    int resultValue = 0;
+    try {
+      resultValue = Utilities.invokeCommand(command, new File(buildDirectory), 
junitLogFilename);
+      if (resultValue == 0) {
+        System.out.println("success");
+      } else {
+        System.out.println("FAIL");
       }
-      if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-        break;
+      if (runtckVerbose) {
+        System.out.println("\nCommand line is: \n" + command.toString());
+        System.out.println("Test exit value is " + resultValue);
+        System.out.println("Test result output:\n" + 
fileToString(junitLogFilename));
       }
+    } catch (java.lang.RuntimeException re) {
+      System.out.println("Exception on command " + command);
+    }
+    return resultValue;
+  }
+
+  /**
+   * Copies the implementation log file and TCK log file to the current log 
directory
+   *
+   * @param thisLogFilePrefix the prefix of the log file consisting of idtype 
and conf
+   */
+  private void handleLogFiles(String thisLogFilePrefix) {

Review Comment:
   Also: why `this` in `thisLogFilePrefix`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -140,37 +141,178 @@ private String getTrimmedPropertyValue(Properties props, 
String key) {
     return value == null ? "" : value.trim();
   }
 
+  private static String fileToString(String fileName) {
+    try {
+      byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+      return new String(encoded);
+    } catch (IOException ex) {
+      return "Problems reading " + fileName + ": " + ex.getMessage();
+    }
+  }
+
+  /** */
   @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
+  public void execute() throws MojoExecutionException {
     if (!doRunTCK) {
       System.out.println("Skipping RunTCK goal!");
       return;
     }
 
-    Properties props = null;
     boolean alreadyran = false;
-    String runonce = "false";
-    List<String> propsString = new ArrayList<>();
-    List<String> command;
+    boolean runonce = false;
     String cpString = null;
-    InvocationResult result;
-    File fromFile = null;
-    File toFile = null;
 
+    List<String> propsString = initTCKRun();
+    String excludeFile = confDirectory + File.separator + exclude;
+    propsString.add(
+        "-Djdo.tck.exclude="
+            + 
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude"));
+
+    // Create configuration log directory
+    String thisLogDir = logsDirectory + File.separator + Utilities.now();
+    String cfgDirName = thisLogDir + File.separator + "configuration";
+    File cfgDir = new File(cfgDirName);
+    if (!(cfgDir.exists()) && !(cfgDir.mkdirs())) {
+      throw new MojoExecutionException("Failed to create directory " + 
cfgDirName);
+    }
+    propsString.add("-Djdo.tck.log.directory=" + thisLogDir);
+
+    copyConfigurationFiles();
+
+    // Get ClassLoader URLs to build classpath below
+    List<URL> urlList =
+        new ArrayList<>(
+            Arrays.asList(
+                ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs()));
+
+    // Get contents of pmf properties file to build new file below
+    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
+    String defaultPropsContents = "";
+    try {
+      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+
+    // Reset logfile content (may not be empty if previous run crashed)
+    resetFileContent(implLogFile);
+    resetFileContent(TCK_LOG_FILE);
+
+    int failureCount = 0;
+    for (String db : dbs) {
+      System.setProperty("jdo.tck.database", db);
+      alreadyran = false;
+
+      for (String idtype : idtypes) {
+        List<String> idPropsString = new ArrayList<>();
+        idPropsString.addAll(propsString);
+        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
+        String enhancedDirName =
+            buildDirectory
+                + File.separator
+                + "enhanced"
+                + File.separator
+                + impl
+                + File.separator
+                + idtype
+                + File.separator;
+        File enhancedDir = new File(enhancedDirName);
+        if (!(enhancedDir.exists())) {

Review Comment:
   remove unnecessary `(` / `)`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -140,37 +141,178 @@ private String getTrimmedPropertyValue(Properties props, 
String key) {
     return value == null ? "" : value.trim();
   }
 
+  private static String fileToString(String fileName) {
+    try {
+      byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+      return new String(encoded);
+    } catch (IOException ex) {
+      return "Problems reading " + fileName + ": " + ex.getMessage();
+    }
+  }
+
+  /** */
   @Override
-  public void execute() throws MojoExecutionException, MojoFailureException {
+  public void execute() throws MojoExecutionException {
     if (!doRunTCK) {
       System.out.println("Skipping RunTCK goal!");
       return;
     }
 
-    Properties props = null;
     boolean alreadyran = false;
-    String runonce = "false";
-    List<String> propsString = new ArrayList<>();
-    List<String> command;
+    boolean runonce = false;

Review Comment:
   `alreadyRan` and `runOnce` -> snakeCase?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)

Review Comment:
   Rename to `getTestClasses`?



##########
exectck/src/main/java/org/apache/jdo/exectck/RunTCK.java:
##########
@@ -263,231 +396,261 @@ public void execute() throws MojoExecutionException, 
MojoFailureException {
     } catch (IOException ex) {
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+  }
 
-    // Get ClassLoader URLs to build classpath below
-    URL[] cpURLs = ((URLClassLoader) 
Thread.currentThread().getContextClassLoader()).getURLs();
-    ArrayList<URL> urlList = new ArrayList<>(Arrays.asList(cpURLs));
-
-    // Get contents of pmf properties file to build new file below
-    String pmfPropsReadFileName = confDirectory + File.separator + 
pmfProperties;
-    String defaultPropsContents = "";
+  /**
+   * Get classpath string: add new entries to URLS from loader
+   *
+   * @param urlList ClassLoader URLs
+   * @param enhancedDir
+   * @return
+   */
+  private String getClasspathString(List<URL> urlList, File enhancedDir) {
+    String cpString;
+    ArrayList<URL> cpList = new ArrayList<>();
+    cpList.addAll(urlList);
     try {
-      defaultPropsContents = Utilities.readFile(pmfPropsReadFileName);
-    } catch (IOException ex) {
+      URL url1 = enhancedDir.toURI().toURL();
+      URL url2 =
+          new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
+              .toURI()
+              .toURL();
+      if (runtckVerbose) {
+        System.out.println("url2 is " + url2.toString());
+      }
+      cpList.add(url1);
+      cpList.add(url2);
+      String[] jars = {"jar"};
+      Iterator<File> fi = FileUtils.iterateFiles(new File(extLibsDirectory), 
jars, true);
+      while (fi.hasNext()) {
+        cpList.add(fi.next().toURI().toURL());
+      }
+      for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
+        cpList.add(new File(dependency).toURI().toURL());
+      }
+    } catch (MalformedURLException ex) {
+      ex.printStackTrace();
       Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
     }
+    cpString = Utilities.urls2ClasspathString(cpList);
+    if (runtckVerbose) {
+      System.out.println("\nClasspath is " + cpString);
+    }
+    return cpString;
+  }
 
-    // Reset logfile content (may not be empty if previous run crashed)
-    resetFileContent(implLogFile);
-    resetFileContent(TCK_LOG_FILE);
-
-    int failureCount = 0;
-    for (String db : dbs) {
-      System.setProperty("jdo.tck.database", db);
-      alreadyran = false;
-
-      for (String idtype : idtypes) {
-        List<String> idPropsString = new ArrayList<>();
-        idPropsString.addAll(propsString);
-        idPropsString.add("-Djdo.tck.identitytype=" + idtype);
-        String enhancedDirName =
-            buildDirectory
-                + File.separator
-                + "enhanced"
-                + File.separator
-                + impl
-                + File.separator
-                + idtype
-                + File.separator;
-        File enhancedDir = new File(enhancedDirName);
-        if (!(enhancedDir.exists())) {
-          throw new MojoExecutionException(
-              "Could not find enhanced directory "
-                  + enhancedDirName
-                  + ". Execute Enhance goal before RunTCK.");
-        }
-
-        // Set classpath string: add new entries to URLS from loader
-        ArrayList<URL> cpList = new ArrayList<>();
-        cpList.addAll(urlList);
-        try {
-          URL url1 = enhancedDir.toURI().toURL();
-          URL url2 =
-              new File(buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator)
-                  .toURI()
-                  .toURL();
-          if (runtckVerbose) {
-            System.out.println("url2 is " + url2.toString());
-          }
-          cpList.add(url1);
-          cpList.add(url2);
-          String[] jars = {"jar"};
-          Iterator<File> fi = FileUtils.iterateFiles(new 
File(extLibsDirectory), jars, true);
-          while (fi.hasNext()) {
-            cpList.add(fi.next().toURI().toURL());
-          }
-          for (String dependency : 
this.dependencyClasspath.split(File.pathSeparator)) {
-            cpList.add(new File(dependency).toURI().toURL());
-          }
-        } catch (MalformedURLException ex) {
-          ex.printStackTrace();
-          Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        cpString = Utilities.urls2ClasspathString(cpList);
-        if (runtckVerbose) {
-          System.out.println("\nClasspath is " + cpString);
-        }
-
-        for (String cfg : cfgs) {
-          List<String> cfgPropsString = new ArrayList<>();
-          cfgPropsString.addAll(idPropsString);
-          // Parse conf file and set properties String
-          props = PropertyUtils.getProperties(confDirectory + File.separator + 
cfg);
-          cfgPropsString.add(
-              "-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
-          cfgPropsString.add(
-              "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
-          cfgPropsString.add(
-              "-Djdo.tck.mapping.companyfactory="
-                  + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
-          cfgPropsString.add(
-              "-Djdo.tck.requiredOptions="
-                  + getTrimmedPropertyValue(props, "jdo.tck.requiredOptions"));
-          cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
-          String mapping = getTrimmedPropertyValue(props, "jdo.tck.mapping");
-          if (mapping == null) {
-            throw new MojoExecutionException("Could not find mapping value in 
conf file: " + cfg);
-          }
-          String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
-          String excludeList =
-              
getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
-          if (classes == null) {
-            throw new MojoExecutionException("Could not find classes value in 
conf file: " + cfg);
-          }
-          classes = Utilities.removeSubstrs(classes, excludeList);
-          if (classes.equals("")) {
-            System.out.println("Skipping configuration " + cfg + ": classes 
excluded");
-            continue;
-          }
-          List<String> classesList = Arrays.asList(classes.split(" "));
-
-          cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
-          cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
-
-          runonce = getTrimmedPropertyValue(props, "runOnce");
-          runonce = (runonce == null) ? "false" : runonce;
-
-          // Add Mapping and schemaname to properties file
-          StringBuilder propsFileData = new StringBuilder();
-          propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
-          propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + 
mapping);
-          mapping = (mapping.equals("0")) ? "" : mapping;
-          propsFileData.append("\njavax.jdo.option.Mapping=standard" + 
mapping);
-          propsFileData.append("\n");
-          String pmfPropsWriteFileName =
-              buildDirectory + File.separator + CLASSES_DIR_NAME + 
File.separator + pmfProperties;
-          try {
-            BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false));
-            out.write(defaultPropsContents + propsFileData.toString());
-            out.close();
-          } catch (IOException ex) {
-            Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, 
ex);
-          }
-
-          // build command line string
-          command = new ArrayList<>();
-          command.add("java");
-          command.add("-cp");
-          command.add(cpString);
-          command.addAll(cfgPropsString);
-          command.add(dbproperties);
-          command.add(jvmproperties);
-          if (debugTCK) {
-            command.add(debugDirectives);
-          }
-          command.add(testRunnerClass);
-          command.addAll(classesList);
+  /**
+   * Create the jdo pmf properties file.
+   *
+   * @param idtype identity type
+   * @param mapping the mapping index
+   * @param defaultPropsContents default pmf properties
+   */
+  private void writePMFPropsFile(String idtype, String mapping, String 
defaultPropsContents) {
+    StringBuilder propsFileData = new StringBuilder();
+    propsFileData.append("\n### Properties below added by maven 2 goal 
RunTCK.jdori");
+    propsFileData.append("\njavax.jdo.mapping.Schema=" + idtype + mapping);
+    mapping = (mapping.equals("0")) ? "" : mapping;
+    propsFileData.append("\njavax.jdo.option.Mapping=standard" + mapping);
+    propsFileData.append("\n");
+    String pmfPropsWriteFileName =
+        buildDirectory + File.separator + CLASSES_DIR_NAME + File.separator + 
pmfProperties;
+    try (BufferedWriter out = new BufferedWriter(new 
FileWriter(pmfPropsWriteFileName, false))) {
+      out.write(defaultPropsContents + propsFileData.toString());
+    } catch (IOException ex) {
+      Logger.getLogger(RunTCK.class.getName()).log(Level.SEVERE, null, ex);
+    }
+  }
 
-          if (runonce.equals("true") && alreadyran) {
-            continue;
-          }
+  /**
+   * Returns the configuration properties as List
+   *
+   * @param idPropsString
+   * @param props the Properties object including the properties defined in 
the conf file
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param mapping the mapping index
+   * @return configuration properties
+   */
+  private List<String> getCfgProps(
+      List<String> idPropsString, Properties props, String idtype, String cfg, 
String mapping) {
+    List<String> cfgPropsString = new ArrayList<>();
+    cfgPropsString.addAll(idPropsString);
+    cfgPropsString.add("-Djdo.tck.testdata=" + getTrimmedPropertyValue(props, 
"jdo.tck.testdata"));
+    cfgPropsString.add(
+        "-Djdo.tck.standarddata=" + getTrimmedPropertyValue(props, 
"jdo.tck.standarddata"));
+    cfgPropsString.add(
+        "-Djdo.tck.mapping.companyfactory="
+            + getTrimmedPropertyValue(props, 
"jdo.tck.mapping.companyfactory"));
+    cfgPropsString.add(
+        "-Djdo.tck.requiredOptions=" + getTrimmedPropertyValue(props, 
"jdo.tck.requiredOptions"));
+    cfgPropsString.add("-Djdo.tck.signaturefile=" + signaturefile);
+    cfgPropsString.add("-Djdo.tck.schemaname=" + idtype + mapping);
+    cfgPropsString.add("-Djdo.tck.cfg=" + cfg);
+    return cfgPropsString;
+  }
 
-          if (debugTCK) {
-            System.out.println("Using debug arguments: \n" + debugDirectives);
-          }
+  /**
+   * Returns a list of class names of TCK test classes. Classes mentioned in 
the excludeFile are not
+   * part of the result.
+   *
+   * @param props
+   * @param cfg name of the configuration
+   * @param excludeFile
+   * @return
+   * @throws MojoExecutionException
+   */
+  private List<String> getClassesList(Properties props, String cfg, String 
excludeFile)
+      throws MojoExecutionException {
+    String classes = getTrimmedPropertyValue(props, "jdo.tck.classes");
+    if (classes == null) {
+      throw new MojoExecutionException("Could not find classes value in conf 
file: " + cfg);
+    }
+    String excludeList =
+        getTrimmedPropertyValue(PropertyUtils.getProperties(excludeFile), 
"jdo.tck.exclude");
+    classes = Utilities.removeSubstrs(classes, excludeList);
+    List<String> classesList = new ArrayList();
+    PropertyUtils.string2Collection(classes, classesList);
+    return classesList;
+  }
 
-          // invoke class runner
-          System.out.print(
-              "*> Running tests for "
-                  + cfg
-                  + " with "
-                  + idtype
-                  + " on '"
-                  + db
-                  + "'"
-                  + " mapping="
-                  + mapping
-                  + " ... ");
-          try {
-            result = (new Utilities()).invokeTest(command);
-            if (result.getExitValue() == 0) {
-              System.out.println("success");
-            } else {
-              System.out.println("FAIL");
-              failureCount++;
-            }
-            if (runtckVerbose) {
-              System.out.println("\nCommand line is: \n" + command.toString());
-              System.out.println("Test exit value is " + 
result.getExitValue());
-              System.out.println("Test result output:\n" + 
result.getOutputString());
-              System.out.println("Test result error:\n" + 
result.getErrorString());
-            }
-          } catch (java.lang.RuntimeException re) {
-            System.out.println("Exception on command " + command);
-          }
+  /**
+   * Returns the perfix of the log file name. It includes the path, followed 
by an indicator for the
+   * identitytype followed by the name of the configuration.
+   *
+   * @param thisLogDir
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @return
+   */
+  private String getLogFilePrefix(String thisLogDir, String idtype, String 
cfg) {
+    String idname = idtype.trim().equals("applicationidentity") ? "app" : 
"dsid";
+    String configName = cfg.indexOf('.') > 0 ? cfg.substring(0, 
cfg.indexOf('.')) : cfg;
+    return thisLogDir + File.separator + idname + "-" + configName + "-";
+  }
 
-          // Move log to per-test location
-          String idname = "dsid";
-          if (idtype.trim().equals("applicationidentity")) {
-            idname = "app";
-          }
-          String configName = cfg;
-          if (cfg.indexOf('.') > 0) {
-            configName = configName.substring(0, cfg.indexOf('.'));
-          }
-          String testLogFilename = thisLogDir + idname + "-" + configName + 
"-" + impl + ".txt";
-          try {
-            File logFile = new File(implLogFile);
-            FileUtils.copyFile(logFile, new File(testLogFilename));
-            resetFileContent(implLogFile);
-          } catch (Exception e) {
-            System.out.println(">> Error copying implementation log file: " + 
e.getMessage());
-          }
-          String tckLogFilename = thisLogDir + idname + "-" + configName + "-" 
+ TCK_LOG_FILE;
-          try {
-            File logFile = new File(TCK_LOG_FILE);
-            FileUtils.copyFile(logFile, new File(tckLogFilename));
-            resetFileContent(TCK_LOG_FILE);
-          } catch (Exception e) {
-            System.out.println(">> Error copying tck log file: " + 
e.getMessage());
-          }
+  /**
+   * Creates the java command to run a TCK test class and executes the command.
+   *
+   * @param cpString classpath
+   * @param cfgPropsString configuration properties
+   * @param classesList
+   * @param idtype identity type
+   * @param cfg name of the configuration
+   * @param db the database
+   * @param mapping the mapping index
+   * @param
+   * @param
+   * @param thisLogFilePrefix
+   * @return
+   */
+  private int executeTestClass(
+      String cpString,
+      List<String> cfgPropsString,
+      List<String> classesList,
+      String idtype,
+      String cfg,
+      String db,
+      String mapping,
+      String thisLogFilePrefix) {
+    // build command line string
+    List<String> command = new ArrayList<>();
+    command.add("java");
+    command.add("-cp");
+    command.add(cpString);
+    command.addAll(cfgPropsString);
+    command.add(dbproperties);
+    command.add(jvmproperties);
+    if (debugTCK) {
+      command.add(debugDirectives);
+    }
+    command.add(testRunnerClass);
+    command.add("--disable-banner");
+    command.add("--details=" + testRunnerDetails);
+    // add Test classes
+    for (String testClass : classesList) {
+      // skip empty entries
+      if (testClass != null && testClass.trim().length() > 0) {
+        command.add("-c");
+        command.add(testClass);
+      }
+    }
 
-          if (runonce.equals("true")) {
-            alreadyran = true;
-          }
+    if (debugTCK) {
+      System.out.println("Using debug arguments: \n" + debugDirectives);
+    }
 
-          if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount 
> 0) {
-            break;
-          }
-        }
-        if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-          break;
-        }
+    // invoke class runner
+    System.out.print(
+        "*> Running tests for "
+            + cfg
+            + " with "
+            + idtype
+            + " on '"
+            + db
+            + "'"
+            + " mapping="
+            + mapping
+            + " ... ");
+
+    String junitLogFilename = thisLogFilePrefix + JUNIT_LOG_FILE;
+    int resultValue = 0;
+    try {
+      resultValue = Utilities.invokeCommand(command, new File(buildDirectory), 
junitLogFilename);
+      if (resultValue == 0) {
+        System.out.println("success");
+      } else {
+        System.out.println("FAIL");
       }
-      if (TCK_PARAM_ON_FAILURE_FAIL_FAST.equals(onFailure) && failureCount > 
0) {
-        break;
+      if (runtckVerbose) {
+        System.out.println("\nCommand line is: \n" + command.toString());
+        System.out.println("Test exit value is " + resultValue);
+        System.out.println("Test result output:\n" + 
fileToString(junitLogFilename));
       }
+    } catch (java.lang.RuntimeException re) {
+      System.out.println("Exception on command " + command);
+    }
+    return resultValue;
+  }
+
+  /**
+   * Copies the implementation log file and TCK log file to the current log 
directory
+   *
+   * @param thisLogFilePrefix the prefix of the log file consisting of idtype 
and conf
+   */
+  private void handleLogFiles(String thisLogFilePrefix) {
+    // Move log to per-test location
+    String testLogFilename = thisLogFilePrefix + impl + ".txt";
+    try {
+      File logFile = new File(implLogFile);
+      FileUtils.copyFile(logFile, new File(testLogFilename));
+      resetFileContent(implLogFile);

Review Comment:
   This seems more like a "move" than a "copy", does it make sense to have a 
method maybe `FileUtils.moveFile()`? 



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: jdo-dev-unsubscr...@db.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to