001    /* 
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     *
017     */
018    
019    package org.apache.commons.exec.launcher;
020    
021    import java.io.File;
022    import java.io.FileWriter;
023    import java.io.IOException;
024    import java.io.PrintWriter;
025    import java.util.Iterator;
026    import java.util.Map;
027    import java.util.Map.Entry;
028    import java.util.Set;
029    
030    import org.apache.commons.exec.CommandLine;
031    import org.apache.commons.exec.util.StringUtils;
032    
033    /**
034     * A command launcher for VMS that writes the command to a temporary DCL script
035     * before launching commands. This is due to limitations of both the DCL
036     * interpreter and the Java VM implementation.
037     */
038    public class VmsCommandLauncher extends Java13CommandLauncher {
039    
040        /**
041         * Launches the given command in a new process.
042         */
043        public Process exec(final CommandLine cmd, final Map env)
044                throws IOException {
045            CommandLine vmsCmd = new CommandLine(
046                    createCommandFile(cmd, env).getPath()
047            );
048    
049            return super.exec(vmsCmd, env);
050        }
051    
052        /**
053         * Launches the given command in a new process, in the given working
054         * directory. Note that under Java 1.3.1, 1.4.0 and 1.4.1 on VMS this method
055         * only works if <code>workingDir</code> is null or the logical
056         * JAVA$FORK_SUPPORT_CHDIR needs to be set to TRUE.
057         */
058        public Process exec(final CommandLine cmd, final Map env,
059                final File workingDir) throws IOException {
060            CommandLine vmsCmd = new CommandLine(
061                    createCommandFile(cmd, env).getPath()
062            );
063    
064            return super.exec(vmsCmd, env, workingDir);
065        }
066    
067        /** @see org.apache.commons.exec.launcher.CommandLauncher#isFailure(int) */
068        public boolean isFailure( final int exitValue )
069        {
070            // even exit value signals failure
071            return (exitValue % 2) == 0;        
072        }
073    
074        /*
075         * Writes the command into a temporary DCL script and returns the
076         * corresponding File object. The script will be deleted on exit.
077         */
078        private File createCommandFile(final CommandLine cmd, final Map env)
079                throws IOException {
080            File script = File.createTempFile("EXEC", ".TMP");
081            script.deleteOnExit();
082            PrintWriter out = null;
083            try {
084                out = new PrintWriter(new FileWriter(script.getAbsolutePath(),true));
085    
086                // add the environment as global symbols for the DCL script
087                if (env != null) {
088                    Set entries = env.entrySet();
089    
090                    for (Iterator iter = entries.iterator(); iter.hasNext();) {
091                        Entry entry = (Entry) iter.next();
092                        out.print("$ ");
093                        out.print(entry.getKey());
094                        out.print(" == "); // define as global symbol
095                        out.println('\"');
096                        String value = (String) entry.getValue();
097                        // Any embedded " values need to be doubled
098                        if (value.indexOf('\"') > 0){
099                            StringBuffer sb = new StringBuffer();
100                            for (int i = 0; i < value.length(); i++) {
101                                char c = value.charAt(i);
102                                if (c == '\"') {
103                                    sb.append('\"');
104                                }
105                                sb.append(c);
106                            }
107                            value=sb.toString();
108                        }
109                        out.print(value);
110                        out.println('\"');
111                    }
112                }
113    
114                final String command = cmd.getExecutable();
115                if (cmd.isFile()){// We assume it is it a script file
116                    out.print("$ @");
117                    // This is a bit crude, but seems to work
118                    String parts[] = StringUtils.split(command,"/");
119                    out.print(parts[0]); // device
120                    out.print(":[");
121                    out.print(parts[1]); // top level directory
122                    final int lastPart = parts.length-1;
123                    for(int i=2; i< lastPart; i++){
124                        out.print(".");
125                        out.print(parts[i]);
126                    }
127                    out.print("]");
128                    out.print(parts[lastPart]);
129                } else {
130                    out.print("$ ");
131                    out.print(command);                
132                }
133                String[] args = cmd.getArguments();
134                for (int i = 0; i < args.length; i++) {
135                    out.println(" -");
136                    out.print(args[i]);
137                }
138                out.println();
139            } finally {
140                if (out != null) {
141                    out.close();
142                }
143            }
144            return script;
145        }
146    }