001    /**
002     *
003     * Copyright 2003-2005 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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    package org.apache.geronimo.deployment.cli;
019    
020    import org.apache.geronimo.common.DeploymentException;
021    import org.apache.geronimo.common.GeronimoEnvironment;
022    
023    import java.util.*;
024    import java.io.*;
025    
026    /**
027     * The main class for the CLI deployer.  Handles chunking the input arguments
028     * and formatting help text and maintaining the list of individual commands.
029     * Uses a ServerConnection to handle the server connection and arguments, and
030     * a list of DeployCommands to manage the details of the various available
031     * commands.
032     *
033     * Returns 0 normally, or 1 of any exceptions or error messages were generated
034     * (whether for syntax or other failure).
035     *
036     * @version $Rev: 430319 $ $Date: 2006-08-10 01:52:16 -0700 (Thu, 10 Aug 2006) $
037     */
038    public class DeployTool {
039        private final static Map commands = new HashMap();
040    
041        public static void registerCommand(DeployCommand command) {
042            String key = command.getCommandName();
043            if(commands.containsKey(key)) {
044                throw new IllegalArgumentException("Command "+key+" is already registered!");
045            } else {
046                commands.put(key, command);
047            }
048        }
049    
050        private static DeployCommand getCommand(String name) {
051            return (DeployCommand) commands.get(name);
052        }
053    
054        private static DeployCommand[] getAllCommands() {
055            DeployCommand[] list = (DeployCommand[]) commands.values().toArray(new DeployCommand[0]);
056            Arrays.sort(list, new Comparator() {
057                public int compare(Object o1, Object o2) {
058                    return ((DeployCommand)o1).getCommandName().compareTo(((DeployCommand)o2).getCommandName());
059                }
060            });
061            return list;
062        }
063    
064        static {
065            // Perform initialization tasks common with the various Geronimo process environments.
066            GeronimoEnvironment.init();
067            
068            registerCommand(new CommandLogin());
069            registerCommand(new CommandDeploy());
070            registerCommand(new CommandDistribute());
071            registerCommand(new CommandListModules());
072            registerCommand(new CommandListTargets());
073            registerCommand(new CommandRedeploy());
074            registerCommand(new CommandStart());
075            registerCommand(new CommandStop());
076            registerCommand(new CommandRestart());
077            registerCommand(new CommandUndeploy());
078            registerCommand(new CommandListConfigurations());
079            registerCommand(new CommandInstallCAR());
080        }
081    
082        private boolean failed = false;
083        String[] generalArgs = new String[0];
084        ServerConnection con = null;
085        private boolean multipleCommands = false;
086    
087        public boolean execute(String args[]) {
088            PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out), true);
089            InputStream in = System.in;
090    
091            String command;
092            String[] commandArgs = new String[0];
093            if(args.length == 0) {
094                command = "help";
095            } else {
096                String[] temp = getCommonArgsAndCommand(args);
097                if(temp == null || temp.length == 0) {
098                    command = "help";
099                } else {
100                    command = temp[temp.length-1];
101                    if(generalArgs.length == 0 && temp.length > 1) {
102                        generalArgs = new String[temp.length-1];
103                        System.arraycopy(temp, 0, generalArgs, 0, temp.length-1);
104                    }
105                    commandArgs = new String[args.length - temp.length];
106                    System.arraycopy(args, temp.length, commandArgs, 0, commandArgs.length);
107                }
108            }
109            if(command.equals("help")) {
110                showHelp(out, commandArgs);
111            } else if(command.equals("command-file")) {
112                multipleCommands = true;
113                if(commandArgs.length != 1) {
114                    processException(out, new DeploymentSyntaxException("Must provide a command file to read from and no other arguments"));
115                } else {
116                    String arg = commandArgs[0];
117                    File source = new File(arg);
118                    if(!source.exists() || !source.canRead() || source.isDirectory()) {
119                        processException(out, new DeploymentSyntaxException("Cannot read command file "+source.getAbsolutePath()));
120                    } else {
121                        try {
122                            BufferedReader commands = new BufferedReader(new FileReader(source));
123                            String line;
124                            boolean oneFailed = false;
125                            while((line = commands.readLine()) != null) {
126                                line = line.trim();
127                                if(!line.equals("")) {
128                                    String[] lineArgs = splitCommand(line);
129                                    if(failed) {
130                                        oneFailed = true;
131                                    }
132                                    failed = false;
133                                    execute(lineArgs);
134                                }
135                            }
136                            failed = oneFailed;
137                        } catch (IOException e) {
138                            processException(out, new DeploymentException("Unable to read command file", e));
139                        } finally {
140                            try {
141                                con.close();
142                            } catch (DeploymentException e) {
143                                processException(out, e);
144                            }
145                        }
146                    }
147                }
148            } else {
149                DeployCommand dc = getCommand(command);
150                if(dc == null) {
151                    out.println();
152                    processException(out, new DeploymentSyntaxException("No such command: '"+command+"'"));
153                    showHelp(out, new String[0]);
154                } else {
155                    try {
156                        if(con == null) {
157                            con = new ServerConnection(generalArgs, out, in);
158                        }
159                        try {
160                            dc.execute(out, con, commandArgs);
161                        } catch (DeploymentSyntaxException e) {
162                            processException(out, e);
163                        } catch (DeploymentException e) {
164                            processException(out, e);
165                        } finally {
166                            if(!multipleCommands) {
167                                try {
168                                    con.close();
169                                } catch(DeploymentException e) {
170                                    processException(out, e);
171                                }
172                            }
173                        }
174                    } catch(DeploymentException e) {
175                        processException(out, e);
176                    }
177                }
178            }
179            out.flush();
180            System.out.flush();
181            return !failed;
182        }
183    
184        public static String[] splitCommand(String line) {
185            String[] chunks = line.split("\"");
186            List list = new LinkedList();
187            for (int i = 0; i < chunks.length; i++) {
188                String chunk = chunks[i];
189                if(i % 2 == 1) { // it's in quotes
190                    list.add(chunk);
191                } else { // it's not in quotes
192                    list.addAll(Arrays.asList(chunk.split("\\s")));
193                }
194            }
195            for (Iterator it = list.iterator(); it.hasNext();) {
196                String test = (String) it.next();
197                if(test.trim().equals("")) {
198                    it.remove();
199                }
200            }
201            return (String[]) list.toArray(new String[list.size()]);
202        }
203    
204        private void processException(PrintWriter out, Exception e) {
205            failed = true;
206            out.print(DeployUtils.reformat("Error: "+e.getMessage(),4,72));
207            if(e.getCause() != null) {
208                e.getCause().printStackTrace(out);
209            }
210        }
211    
212        private void showHelp(PrintWriter out, String[] args) {
213            out.println();
214            out.println("Command-line deployer syntax:");
215            out.println("    deployer [general options] command [command options]");
216            out.println();
217            if(args.length > 0) {
218                DeployCommand command = getCommand(args[0]);
219                if(command != null) {
220                    out.println("Help for command: "+command.getCommandName());
221                    out.println();
222                    out.println("    deployer "+hangingIndent(command.getCommandName()+" "+command.getHelpArgumentList(), 13));
223                    out.println();
224                    out.print(DeployUtils.reformat(command.getHelpText(), 8, 72));
225                    out.println();
226                    return;
227                } else if(args[0].equals("options")) {
228                    out.println("Help on general options:");
229                    out.println();
230                    Map map = ServerConnection.getOptionHelp();
231                    for (Iterator it = map.keySet().iterator(); it.hasNext();) {
232                        String s = (String) it.next();
233                        out.println("   "+s);
234                        out.println();
235                        out.print(DeployUtils.reformat((String)map.get(s), 8, 72));
236                    }
237                    return;
238                } else if(args[0].equals("all")) {
239                    DeployCommand[] all = getAllCommands();
240                    out.println();
241                    out.println("All commands");
242                    out.println();
243                    for (int i = 0; i < all.length; i++) {
244                        DeployCommand cmd = all[i];
245                        out.println("    deployer "+hangingIndent(cmd.getCommandName()+" "+cmd.getHelpArgumentList(), 13));
246                        out.print(DeployUtils.reformat(cmd.getHelpText(), 8, 72));
247                    }
248                    out.println();
249                    return;
250                }
251            }
252            out.println("The general options are:");
253            Map map = ServerConnection.getOptionHelp();
254            for (Iterator it = map.keySet().iterator(); it.hasNext();) {
255                String s = (String) it.next();
256                out.println("    "+s);
257            }
258            out.println();
259            out.println("The available commands are:");
260            renderCommandList(out, getAllCommands());
261            out.println();
262            out.println("For more information about a specific command, run");
263            out.println("    deployer help [command name]");
264            out.println();
265            out.println("For more information about general options, run");
266            out.println("    deployer help options");
267            out.println();
268        }
269    
270        private String hangingIndent(String source, int cols) {
271            String s = DeployUtils.reformat(source, cols, 72);
272            return s.substring(cols);
273        }
274    
275        private void renderCommandList(PrintWriter out, DeployCommand[] all) {
276            Map temp = new HashMap();
277            for (int i = 0; i < all.length; i++) {
278                DeployCommand command = all[i];
279                List list = (List) temp.get(command.getCommandGroup());
280                if(list == null) {
281                    list = new ArrayList();
282                    temp.put(command.getCommandGroup(), list);
283                }
284                list.add(command.getCommandName());
285            }
286            List groups = new ArrayList(temp.keySet());
287            Collections.sort(groups);
288            for (int i = 0; i < groups.size(); i++) {
289                String name = (String) groups.get(i);
290                out.println("    "+name);
291                List list = (List) temp.get(name);
292                Collections.sort(list);
293                for (int j = 0; j < list.size(); j++) {
294                    String cmd = (String) list.get(j);
295                    out.println("        "+cmd);
296                }
297            }
298        }
299    
300        private String[] getCommonArgsAndCommand(String[] all) {
301            List list = new ArrayList();
302            for (int i = 0; i < all.length; i++) {
303                String s = all[i];
304                boolean option = ServerConnection.isGeneralOption(list, s);
305                list.add(s);
306                if(!option) {
307                    break;
308                }
309            }
310            return (String[]) list.toArray(new String[list.size()]);
311        }
312    
313        public static void main(String[] args) {
314            if(!new DeployTool().execute(args)) {
315                System.exit(1);
316            } else {
317                System.exit(0);
318            }
319        }
320    }