001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.commons.cli;
020
021import java.io.IOException;
022import java.io.InputStream;
023import java.util.ArrayList;
024
025import lucee.commons.io.IOUtil;
026import lucee.commons.io.SystemUtil;
027import lucee.commons.lang.StringUtil;
028
029public class Command {
030    
031    public static Process createProcess(String cmdline,boolean translate) throws IOException {
032        if(!translate)return Runtime.getRuntime().exec(cmdline);
033        return Runtime.getRuntime().exec(toArray(cmdline));
034    }
035        
036    /**
037     * @param cmdline command line
038     * @param translate translate the command line or not
039     * @return
040     * @throws IOException
041     * @throws InterruptedException
042     */
043    public static CommandResult execute(String cmdline,boolean translate) throws IOException, InterruptedException {
044        if(!translate)return execute(Runtime.getRuntime().exec(cmdline));
045        return execute(Runtime.getRuntime().exec(toArray(cmdline)));
046    }
047    
048        public static CommandResult execute(String[] cmdline) throws IOException, InterruptedException {
049                return execute(Runtime.getRuntime().exec(cmdline));
050    }
051    public static CommandResult execute(String cmd,String[] args) throws IOException, InterruptedException {
052        return execute(StringUtil.merge(cmd,args));
053    }
054
055    public static CommandResult execute(Process p) throws IOException, InterruptedException {
056        InputStream is=null;
057        InputStream es=null;
058        IOException ioe;
059            try {
060                StreamGobbler in=new StreamGobbler(is=p.getInputStream());
061                StreamGobbler err=new StreamGobbler(es=p.getErrorStream());
062                in.start();
063                err.start();
064                if(p.waitFor()!=0){
065                        err.join();
066                        if((ioe=err.getException())!=null) throw ioe;
067                        String str=err.getString();
068                        if(!StringUtil.isEmpty(str))
069                                throw new CommandException(str);
070                }
071                in.join();
072                if((ioe=in.getException())!=null) throw ioe;
073
074                        return new CommandResult( in.getString(), err.getString() );
075        }
076        finally {
077                IOUtil.closeEL(is);
078                IOUtil.closeEL(es);
079        }
080    }
081    
082    
083
084
085    private static String[] toArray(String str) {
086        if(StringUtil.isEmpty(str)) return new String[]{""};
087        str=str.trim();
088        StringBuilder sb=new StringBuilder();
089        ArrayList<String> list=new ArrayList<String>();
090                char[] carr = str.toCharArray();
091                char c;//,last=0;
092                char inside=0;
093                for(int i=0;i<carr.length;i++){
094                        c=carr[i];
095                        //if(i>0)last=carr[i-1];
096                        switch(c){
097                // DELIMITER
098                        /*case '\\':    
099                                if(i+1<carr.length){
100                                        sb.append(carr[++i]);
101                                }
102                                else sb.append(c);
103                                break;*/
104                // QUOTE
105                        case '\'':
106                        case '"':
107                                if(inside==0){
108                                        if(str.lastIndexOf(c)>i)
109                                                inside=c;
110                                        else
111                                                sb.append(c);
112                                }
113                                else if(inside==c) {
114                                        inside=0;
115                                }
116                                else sb.append(c);
117                        break;
118                // WHITE SPACE
119                        case ' ':
120                        case '\b':
121                        case '\t':
122                        case '\n':
123                        case '\r':
124                        case '\f':
125                                //if(last=='\\')sb.setCharAt(sb.length()-1,c);
126                                if(inside==0) {
127                                        populateList(sb,list);
128                                }
129                                else sb.append(c);
130                                break;
131                // OTHERS
132                        default:
133                                        sb.append(c);
134                        }
135                }
136                populateList(sb, list);
137                
138                
139        return  list.toArray(new String[list.size()]);
140        }
141    
142    private static void populateList(StringBuilder sb, ArrayList<String> list) {
143
144                String tmp = sb.toString();
145                tmp=tmp.trim();
146                if(tmp.length()>0)list.add(tmp);
147                sb.delete(0, sb.length());
148        }
149}
150
151
152class StreamGobbler extends Thread {
153  
154
155        InputStream is;
156        private String str;
157        private IOException ioe;
158    
159    StreamGobbler(InputStream is)       {
160        this.is = is;
161    }
162    
163    @Override
164    public void run() {
165        try {
166                        str=IOUtil.toString(is,SystemUtil.getCharset());
167                } catch (IOException ioe) {
168                        this.ioe=ioe;
169                }  
170    }
171    
172    /**
173         * @return the str
174         */
175        public String getString() {
176                return str;
177        }
178
179        /**
180         * @return the ioe
181         */
182        public IOException getException() {
183                return ioe;
184        }
185        
186}