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    package org.apache.geronimo.deployment.cli;
019    
020    import java.io.BufferedReader;
021    import java.io.File;
022    import java.io.FileReader;
023    import java.io.IOException;
024    import java.io.InputStream;
025    import java.io.OutputStreamWriter;
026    import java.io.PrintWriter;
027    import java.util.Arrays;
028    import java.util.IdentityHashMap;
029    import java.util.Iterator;
030    import java.util.LinkedList;
031    import java.util.List;
032    
033    import javax.enterprise.deploy.spi.factories.DeploymentFactory;
034    
035    import org.apache.geronimo.cli.deployer.CommandArgs;
036    import org.apache.geronimo.cli.deployer.CommandFileCommandMetaData;
037    import org.apache.geronimo.cli.deployer.CommandMetaData;
038    import org.apache.geronimo.cli.deployer.DeployCommandMetaData;
039    import org.apache.geronimo.cli.deployer.DeployerCLParser;
040    import org.apache.geronimo.cli.deployer.DistributeCommandMetaData;
041    import org.apache.geronimo.cli.deployer.InstallPluginCommandMetaData;
042    import org.apache.geronimo.cli.deployer.ListModulesCommandMetaData;
043    import org.apache.geronimo.cli.deployer.ListTargetsCommandMetaData;
044    import org.apache.geronimo.cli.deployer.LoginCommandMetaData;
045    import org.apache.geronimo.cli.deployer.RedeployCommandMetaData;
046    import org.apache.geronimo.cli.deployer.RestartCommandMetaData;
047    import org.apache.geronimo.cli.deployer.SearchPluginsCommandMetaData;
048    import org.apache.geronimo.cli.deployer.StartCommandMetaData;
049    import org.apache.geronimo.cli.deployer.StopCommandMetaData;
050    import org.apache.geronimo.cli.deployer.UndeployCommandMetaData;
051    import org.apache.geronimo.common.DeploymentException;
052    import org.apache.geronimo.gbean.GBeanInfo;
053    import org.apache.geronimo.gbean.GBeanInfoBuilder;
054    import org.apache.geronimo.kernel.Kernel;
055    import org.apache.geronimo.kernel.util.Main;
056    
057    
058    /**
059     * The main class for the CLI deployer.  Handles chunking the input arguments
060     * and formatting help text and maintaining the list of individual commands.
061     * Uses a ServerConnection to handle the server connection and arguments, and
062     * a list of DeployCommands to manage the details of the various available
063     * commands.
064     *
065     * Returns 0 normally, or 1 of any exceptions or error messages were generated
066     * (whether for syntax or other failure).
067     *
068     * @version $Rev: 535507 $ $Date: 2007-05-05 07:22:39 -0400 (Sat, 05 May 2007) $
069     */
070    public class DeployTool implements Main {
071    
072        private static final IdentityHashMap<CommandMetaData, DeployCommand> commands = new IdentityHashMap<CommandMetaData, DeployCommand>();
073    
074        static {
075            commands.put(LoginCommandMetaData.META_DATA, new CommandLogin());
076            commands.put(DeployCommandMetaData.META_DATA, new CommandDeploy());
077            commands.put(DistributeCommandMetaData.META_DATA, new CommandDistribute());
078            commands.put(ListModulesCommandMetaData.META_DATA, new CommandListModules());
079            commands.put(ListTargetsCommandMetaData.META_DATA, new CommandListTargets());
080            commands.put(RedeployCommandMetaData.META_DATA, new CommandRedeploy());
081            commands.put(StartCommandMetaData.META_DATA, new CommandStart());
082            commands.put(StopCommandMetaData.META_DATA, new CommandStop());
083            commands.put(RestartCommandMetaData.META_DATA, new CommandRestart());
084            commands.put(UndeployCommandMetaData.META_DATA, new CommandUndeploy());
085            commands.put(SearchPluginsCommandMetaData.META_DATA, new CommandListConfigurations());
086            commands.put(InstallPluginCommandMetaData.META_DATA, new CommandInstallCAR());
087        }
088    
089        private boolean failed = false;
090        String[] generalArgs = new String[0];
091        ServerConnection con = null;
092        private boolean multipleCommands = false;
093        private final Kernel kernel;
094        private final DeploymentFactory deploymentFactory;
095    
096        public DeployTool(Kernel kernel, DeploymentFactory deploymentFactory) {
097            if (null == kernel) {
098                throw new IllegalArgumentException("kernel is required");
099            } else if (null == deploymentFactory) {
100                throw new IllegalArgumentException("deploymentFactory is required");
101            }
102            this.kernel = kernel;
103            this.deploymentFactory = deploymentFactory;
104        }
105        
106        public int execute(Object opaque) {
107            if (! (opaque instanceof DeployerCLParser)) {
108                throw new IllegalArgumentException("Argument type is [" + opaque.getClass() + "]; expected [" + DeployerCLParser.class + "]");
109            }
110            DeployerCLParser parser = (DeployerCLParser) opaque;
111            
112            PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out), true);
113            InputStream in = System.in;
114    
115            CommandMetaData commandMetaData = parser.getCommandMetaData();
116            CommandArgs commandArgs = parser.getCommandArgs();
117            if(commandMetaData == CommandFileCommandMetaData.META_DATA) {
118                multipleCommands = true;
119                String arg = commandArgs.getArgs()[0];
120                File source = new File(arg);
121                if(!source.exists() || !source.canRead() || source.isDirectory()) {
122                    processException(out, new DeploymentSyntaxException("Cannot read command file "+source.getAbsolutePath()));
123                } else {
124                    try {
125                        BufferedReader commands = new BufferedReader(new FileReader(source));
126                        String line;
127                        boolean oneFailed = false;
128                        while((line = commands.readLine()) != null) {
129                            line = line.trim();
130                            if(!line.equals("")) {
131                                String[] lineArgs = splitCommand(line);
132                                if(failed) {
133                                    oneFailed = true;
134                                }
135                                failed = false;
136                                execute(lineArgs);
137                            }
138                        }
139                        failed = oneFailed;
140                    } catch (IOException e) {
141                        processException(out, new DeploymentException("Unable to read command file", e));
142                    } finally {
143                        try {
144                            con.close();
145                        } catch (DeploymentException e) {
146                            processException(out, e);
147                        }
148                    }
149                }
150            } else {
151                DeployCommand dc = commands.get(commandMetaData);
152                if(dc == null) {
153                    out.println();
154                    processException(out, new DeploymentSyntaxException("No such command: '"+commandMetaData+"'"));
155                } else {
156                    try {
157                        if(con == null) {
158                            con = new ServerConnection(parser, out, in, kernel, deploymentFactory);
159                        }
160                        try {
161                            dc.execute(out, con, commandArgs);
162                        } catch (DeploymentSyntaxException e) {
163                            processException(out, e);
164                        } catch (DeploymentException e) {
165                            processException(out, e);
166                        } finally {
167                            if(!multipleCommands) {
168                                try {
169                                    con.close();
170                                } catch(DeploymentException e) {
171                                    processException(out, e);
172                                }
173                            }
174                        }
175                    } catch(DeploymentException e) {
176                        processException(out, e);
177                    }
178                }
179            }
180            out.flush();
181            System.out.flush();
182            return failed ? 1 : 0;
183        }
184    
185        public static String[] splitCommand(String line) {
186            String[] chunks = line.split("\"");
187            List list = new LinkedList();
188            for (int i = 0; i < chunks.length; i++) {
189                String chunk = chunks[i];
190                if(i % 2 == 1) { // it's in quotes
191                    list.add(chunk);
192                } else { // it's not in quotes
193                    list.addAll(Arrays.asList(chunk.split("\\s")));
194                }
195            }
196            for (Iterator it = list.iterator(); it.hasNext();) {
197                String test = (String) it.next();
198                if(test.trim().equals("")) {
199                    it.remove();
200                }
201            }
202            return (String[]) list.toArray(new String[list.size()]);
203        }
204    
205        private void processException(PrintWriter out, Exception e) {
206            failed = true;
207            out.print(DeployUtils.reformat("Error: "+e.getMessage(),4,72));
208            if(e.getCause() != null) {
209                e.getCause().printStackTrace(out);
210            }
211        }
212    
213        public static final GBeanInfo GBEAN_INFO;
214        public static final String GBEAN_REF_DEPLOYMENT_FACTORY = "DeploymentFactory";
215        
216        static {
217            GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("DeployTool", DeployTool.class, "DeployTool");
218    
219            infoBuilder.addReference(GBEAN_REF_DEPLOYMENT_FACTORY, DeploymentFactory.class);
220            infoBuilder.addInterface(Main.class);
221            
222            infoBuilder.setConstructor(new String[] {"kernel", GBEAN_REF_DEPLOYMENT_FACTORY});
223            
224            GBEAN_INFO = infoBuilder.getBeanInfo();
225        }
226        
227        public static GBeanInfo getGBeanInfo() {
228            return GBEAN_INFO;
229        }
230    
231    }