content: /*
   *  Licensed to the Apache Software Foundation (ASF) under one or more
   *  contributor license agreements.  See the NOTICE file distributed with
   *  this work for additional information regarding copyright ownership.
   *  The ASF licenses this file to You under the Apache License, Version 2.0
   *  (the "License"); you may not use this file except in compliance with
   *  the License.  You may obtain a copy of the License at
   *
   *      https://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   *
   */
  
  package org.apache.tools.ant.taskdefs.optional.junitlauncher.confined;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Commandline;
  import org.apache.tools.ant.types.CommandlineJava;
  import org.apache.tools.ant.types.EnumeratedAttribute;
  import org.apache.tools.ant.types.Environment;
  import org.apache.tools.ant.types.Path;
  import org.apache.tools.ant.types.PropertySet;
  
  /**
   * Represents the {@code fork} element within test definitions of the
   * {@code junitlauncher} task
   */
  public class ForkDefinition {
  
      private static final String STANDALONE_LAUNCHER_CLASS_NAME = "org.apache.tools.ant.taskdefs.optional.junitlauncher.StandaloneLauncher";
  
      private boolean includeAntRuntimeLibraries = true;
      private boolean includeJUnitPlatformLibraries = true;
      private ForkMode forkMode;
  
      private final CommandlineJava commandLineJava;
      private final Environment env = new Environment();
  
      private String dir;
      private long timeout = -1;
  
      ForkDefinition() {
          this.commandLineJava = new CommandlineJava();
      }
  
      public void setDir(final String dir) {
          this.dir = dir;
      }
  
      String getDir() {
          return this.dir;
      }
  
      public void setTimeout(final long timeout) {
          this.timeout = timeout;
      }
  
      long getTimeout() {
          return this.timeout;
      }
  
      public void setIncludeJUnitPlatformLibraries(final boolean include) {
          this.includeJUnitPlatformLibraries = include;
      }
  
      public void setIncludeAntRuntimeLibraries(final boolean include) {
          this.includeAntRuntimeLibraries = include;
      }
  
      public Commandline.Argument createJvmArg() {
          return this.commandLineJava.createVmArgument();
      }
  
      public void addConfiguredSysProperty(final Environment.Variable sysProp) {
          // validate that key/value are present
          sysProp.validate();
          this.commandLineJava.addSysproperty(sysProp);
      }
  
      public void addConfiguredSysPropertySet(final PropertySet propertySet) {
          this.commandLineJava.addSyspropertyset(propertySet);
      }
  
      public void addConfiguredEnv(final Environment.Variable var) {
          this.env.addVariable(var);
      }
  
      public void addConfiguredModulePath(final Path modulePath) {
          this.commandLineJava.createModulepath(modulePath.getProject()).add(modulePath);
      }
  
      public void addConfiguredUpgradeModulePath(final Path upgradeModulePath) {
          this.commandLineJava.createUpgrademodulepath(upgradeModulePath.getProject()).add(upgradeModulePath);
      }
  
      Environment getEnv() {
          return this.env;
      }
  
      /**
       * The command used to launch {@code java}. This can be a path to the {@code java}
       * binary that will be used to launch the forked {@code java} process.
       *
       * @param java Path to the java command
       * @since Ant 1.10.14
       */
      public void setJava(String java) {
          this.commandLineJava.setVm(java);
      }
  
      /**
       * The {@code forkMode} to use when launching the tests in a forked JVM.
       *
       * @param forkMode Can be null, in which case an internal implementation default will be used.
       * @since Ant 1.10.14
       */
      public void setForkMode(final ForkMode forkMode) {
          this.forkMode = forkMode;
      }
  
      ForkMode getForkMode() {
          return this.forkMode;
      }
  
      /**
       * Generates a new {@link CommandlineJava} constructed out of the configurations set on this
       * {@link ForkDefinition}
       *
       * @param task The junitlaunchertask for which this is a fork definition
       * @return
       */
      CommandlineJava generateCommandLine(final JUnitLauncherTask task) {
          final CommandlineJava cmdLine;
          try {
              cmdLine = (CommandlineJava) this.commandLineJava.clone();
          } catch (CloneNotSupportedException e) {
              throw new BuildException(e);
          }
          cmdLine.setClassname(STANDALONE_LAUNCHER_CLASS_NAME);
          // VM arguments
          final Project project = task.getProject();
          final ClassLoader taskClassLoader = task.getClass().getClassLoader();
          // Ant runtime classes
          if (this.includeAntRuntimeLibraries) {
              final Path antRuntimeResources = new Path(project);
              JUnitLauncherClassPathUtil.addAntRuntimeResourceLocations(antRuntimeResources, taskClassLoader);
              final Path classPath = cmdLine.createClasspath(project);
              classPath.createPath().append(antRuntimeResources);
          } else {
              task.log("Excluding Ant runtime libraries from forked JVM classpath", Project.MSG_DEBUG);
          }
          // JUnit platform classes
          if (this.includeJUnitPlatformLibraries) {
              final Path junitPlatformResources = new Path(project);
              JUnitLauncherClassPathUtil.addJUnitPlatformResourceLocations(junitPlatformResources, taskClassLoader);
              final Path classPath = cmdLine.createClasspath(project);
              classPath.createPath().append(junitPlatformResources);
          } else {
              task.log("Excluding JUnit platform libraries from forked JVM classpath", Project.MSG_DEBUG);
          }
          return cmdLine;
      }
  
      public static final class ForkMode extends EnumeratedAttribute {
  
          static final String FORK_EVERY_TEST_CLASS = "perTestClass";
  
          public ForkMode() {
              // public no-arg constructor required by Ant introspection
          }
  
          private ForkMode(final String val) {
              this.setValue(val);
          }
  
          @Override
          public String[] getValues() {
              return new String[] {FORK_EVERY_TEST_CLASS};
          }
      }
  }
  