/*
 * 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
 *
 *      http://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.commons.exec.launcher;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.util.StringUtils;

/**
 * A command launcher for VMS that writes the command to a temporary DCL script
 * before launching commands. This is due to limitations of both the DCL
 * interpreter and the Java VM implementation.
 *
 */
public class VmsCommandLauncher extends Java13CommandLauncher {

    /**
     * Launches the given command in a new process.
     */
    @Override
    public Process exec(final CommandLine cmd, final Map<String, String> env)
            throws IOException {
        final CommandLine vmsCmd = new CommandLine(
                createCommandFile(cmd, env).getPath()
        );

        return super.exec(vmsCmd, env);
    }

    /**
     * Launches the given command in a new process, in the given working
     * directory. Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this method
     * only works if {@code workingDir} is null or the logical
     * JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
     */
    @Override
    public Process exec(final CommandLine cmd, final Map<String, String> env,
            final File workingDir) throws IOException {
        final CommandLine vmsCmd = new CommandLine(
                createCommandFile(cmd, env).getPath()
        );

        return super.exec(vmsCmd, env, workingDir);
    }

    /** @see org.apache.commons.exec.launcher.CommandLauncher#isFailure(int) */
    @Override
    public boolean isFailure(final int exitValue) {
        // even exit value signals failure
        return exitValue % 2 == 0;
    }

    /*
     * Writes the command into a temporary DCL script and returns the
     * corresponding File object. The script will be deleted on exit.
     */
    private File createCommandFile(final CommandLine cmd, final Map<String, String> env)
            throws IOException {
        final File script = File.createTempFile("EXEC", ".TMP");
        script.deleteOnExit();
        try (PrintWriter out = new PrintWriter(new FileWriter(script.getAbsolutePath(),true))) {
            // add the environment as global symbols for the DCL script
            if (env != null) {
                final Set<Entry<String, String>> entries = env.entrySet();

                for (final Entry<String, String> entry : entries) {
                    out.print("$ ");
                    out.print(entry.getKey());
                    out.print(" == "); // define as global symbol
                    out.println('\"');
                    String value = entry.getValue();
                    // Any embedded " values need to be doubled
                    if (value.indexOf('\"') > 0) {
                        final StringBuilder sb = new StringBuilder();
                        for (int i = 0; i < value.length(); i++) {
                            final char c = value.charAt(i);
                            if (c == '\"') {
                                sb.append('\"');
                            }
                            sb.append(c);
                        }
                        value=sb.toString();
                    }
                    out.print(value);
                    out.println('\"');
                }
            }

            final String command = cmd.getExecutable();
            if (cmd.isFile()) {// We assume it is it a script file
                out.print("$ @");
                // This is a bit crude, but seems to work
                final String[] parts = StringUtils.split(command,"/");
                out.print(parts[0]); // device
                out.print(":[");
                out.print(parts[1]); // top level directory
                final int lastPart = parts.length-1;
                for (int i=2; i< lastPart; i++) {
                    out.print(".");
                    out.print(parts[i]);
                }
                out.print("]");
                out.print(parts[lastPart]);
            } else {
                out.print("$ ");
                out.print(command);
            }
            final String[] args = cmd.getArguments();
            for (final String arg : args) {
                out.println(" -");
                out.print(arg);
            }
            out.println();
        }
        return script;
    }
}

@@ -878,35 +878,8 @@
 le;%0A
-import java.io.FileWriter;%0A
 impo
@@ -930,16 +930,104 @@
 Writer;%0A
+import java.nio.charset.Charset;%0Aimport java.nio.file.Files;%0Aimport java.nio.file.Path;%0A
 import j
@@ -1616,36 +1616,24 @@
 String%3E env)
-%0A           
  throws IOEx
@@ -1654,150 +1654,80 @@
     
-final CommandLine vmsCmd = new CommandLine(%0A                createCommandFile(cmd, env).getPath()%0A        );%0A%0A        return super.exec(vmsCmd
+return super.exec(new CommandLine(createCommandFile(cmd, env).getPath())
 , en
@@ -1817,23 +1817,16 @@
  working
-%0A     *
  directo
@@ -1891,23 +1891,16 @@
 s method
-%0A     *
  only wo
@@ -1905,16 +1905,23 @@
 works if
+%0A     *
  %7B@code 
@@ -1954,23 +1954,16 @@
  logical
-%0A     *
  JAVA$FO
@@ -2103,28 +2103,16 @@
 ng%3E env,
-%0A           
  final F
@@ -2160,150 +2160,80 @@
     
-final CommandLine vmsCmd = new CommandLine(%0A                createCommandFile(cmd, env).getPath()%0A        );%0A%0A        return super.exec(vmsCmd
+return super.exec(new CommandLine(createCommandFile(cmd, env).getPath())
 , en
@@ -2781,26 +2781,25 @@
 nal 
-File script
+Path path
  = File
+s
 .cre
@@ -2823,24 +2823,67 @@
 %22, %22.TMP%22);%0A
+        final File script = path.toFile();%0A
         scri
@@ -2952,52 +2952,62 @@
 ter(
-new FileWriter(script.getAbsolutePath(),true
+Files.newBufferedWriter(path, Charset.defaultCharset()
 ))) 
@@ -4030,17 +4030,19 @@
    value
-=
+ = 
 sb.toStr
@@ -4460,16 +4460,17 @@
 command,
+ 
 %22/%22);%0A  
@@ -4656,17 +4656,19 @@
 s.length
--
+ - 
 1;%0A     
@@ -4692,13 +4692,16 @@
 nt i
-=
+ = 
 2; i
+ 
 %3C la

Use the default platform encoding explicitly to write scripts