001    /**
002     *
003     * Copyright 2003-2004 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 java.io.File;
021    import java.io.PrintWriter;
022    import java.util.ArrayList;
023    import java.util.List;
024    import java.util.StringTokenizer;
025    
026    import javax.enterprise.deploy.spi.DeploymentManager;
027    import javax.enterprise.deploy.spi.Target;
028    import javax.enterprise.deploy.spi.TargetModuleID;
029    import javax.enterprise.deploy.spi.status.ProgressObject;
030    
031    import org.apache.geronimo.common.DeploymentException;
032    import org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager;
033    
034    /**
035     * The CLI deployer logic to distribute.
036     *
037     * @version $Rev: 405624 $ $Date: 2006-05-09 21:08:49 -0700 (Tue, 09 May 2006) $
038     */
039    public class CommandDistribute extends AbstractCommand {
040        public CommandDistribute() {
041            super("distribute", "2. Other Commands", "[--inPlace] [--targets target;target;...] [module] [plan]",
042                    "Processes a module and adds it to the server environment, but does "+
043                    "not start it or mark it to be started in the future. " +
044                    "Normally both a module and plan are passed to the deployer.  " +
045                    "Sometimes the module contains a plan, or requires no plan, in which case " +
046                    "the plan may be omitted.  Sometimes the plan references a module already " +
047                    "deployed in the Geronimo server environment, in which case a module does " +
048                    "not need to be provided.\n" +
049                    "If no targets are provided, the module is distributed to all available " +
050                    "targets.  Geronimo only provides one target (ever), so this is primarily " +
051                    "useful when using a different driver.\n" +
052                    "If inPlace is provided, the module is not copied to the configuration " +
053                    "store of the selected targets. The targets directly use the module.");
054        }
055    
056        protected CommandDistribute(String command, String group, String helpArgumentList, String helpText) {
057            super(command, group, helpArgumentList, helpText);
058        }
059    
060        protected ProgressObject runCommand(DeploymentManager mgr, PrintWriter out, boolean inPlace, Target[] tlist, File module, File plan) throws DeploymentException {
061            if (inPlace) {
062                if (!(mgr instanceof JMXDeploymentManager)) {
063                    throw new DeploymentSyntaxException(
064                            "Target DeploymentManager is not a Geronimo one. \n" +
065                            "Cannot perform in-place deployment.");
066                }
067                JMXDeploymentManager jmxMgr = (JMXDeploymentManager) mgr;
068                try {
069                    jmxMgr.setInPlace(true);
070                    return mgr.distribute(tlist, module, plan);
071                } finally {
072                    jmxMgr.setInPlace(false);
073                }
074            } else {
075                return mgr.distribute(tlist, module, plan);
076            }
077        }
078    
079        protected String getAction() {
080            return "Distributed";
081        }
082    
083        public void execute(PrintWriter out, ServerConnection connection, String[] args) throws DeploymentException {
084            if(args.length == 0) {
085                throw new DeploymentSyntaxException("Must specify a module or plan (or both)");
086            }
087            
088            BooleanHolder inPlaceHolder = new BooleanHolder();
089            args = processInPlace(args, inPlaceHolder);
090            
091            List targets = new ArrayList();
092            args = processTargets(args, targets);
093            if(args.length > 2) {
094                throw new DeploymentSyntaxException("Too many arguments");
095            }
096            File module = null;
097            File plan = null;
098            if(args.length > 0) {
099                File test = new File(args[0]);
100                if(DeployUtils.isJarFile(test) || test.isDirectory()) {
101                    if(module != null) {
102                        throw new DeploymentSyntaxException("Module and plan cannot both be JAR files or directories!");
103                    }
104                    module = test;
105                } else {
106                    if(plan != null) {
107                        throw new DeploymentSyntaxException("Module or plan must be a JAR file or directory!");
108                    }
109                    plan = test;
110                }
111            }
112            if(args.length > 1) {
113                File test = new File(args[1]);
114                if(DeployUtils.isJarFile(test) || test.isDirectory()) {
115                    if(module != null) {
116                        throw new DeploymentSyntaxException("Module and plan cannot both be JAR files or directories!");
117                    }
118                    module = test;
119                } else {
120                    if(plan != null) {
121                        throw new DeploymentSyntaxException("Module or plan must be a JAR file or directory!");
122                    }
123                    plan = test;
124                }
125            }
126            if(module != null) {
127                module = module.getAbsoluteFile();
128            }
129            if(plan != null) {
130                plan = plan.getAbsoluteFile();
131            }
132            executeOnline(connection, inPlaceHolder.inPlace, targets, out, module, plan);
133        }
134    
135        private void executeOnline(ServerConnection connection, boolean inPlace, List targets, PrintWriter out, File module, File plan) throws DeploymentException {
136            final DeploymentManager mgr = connection.getDeploymentManager();
137            TargetModuleID[] results;
138            boolean multipleTargets;
139            ProgressObject po;
140            if(targets.size() > 0) {
141                Target[] tlist = identifyTargets(targets, mgr);
142                multipleTargets = tlist.length > 1;
143                po = runCommand(mgr, out, inPlace, tlist, module, plan);
144                waitForProgress(out, po);
145            } else {
146                final Target[] tlist = mgr.getTargets();
147                multipleTargets = tlist.length > 1;
148                po = runCommand(mgr, out, inPlace, tlist, module, plan);
149                waitForProgress(out, po);
150            }
151    
152            // print the results that succeeded
153            results = po.getResultTargetModuleIDs();
154            for (int i = 0; i < results.length; i++) {
155                TargetModuleID result = results[i];
156                out.print(DeployUtils.reformat(getAction()+" "+result.getModuleID()+(multipleTargets ? " to "+result.getTarget().getName() : "")+(result.getWebURL() == null || !getAction().equals("Deployed") ? "" : " @ "+result.getWebURL()), 4, 72));
157                if(result.getChildTargetModuleID() != null) {
158                    for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
159                        TargetModuleID child = result.getChildTargetModuleID()[j];
160                        out.print(DeployUtils.reformat("  `-> "+child.getModuleID()+(child.getWebURL() == null || !getAction().equals("Deployed") ? "" : " @ "+child.getWebURL()),4, 72));
161                    }
162                }
163            }
164    
165            // if any results failed then throw so that we'll return non-0
166            // to the operating system
167            if(po.getDeploymentStatus().isFailed()) {
168                throw new DeploymentException("Operation failed: "+po.getDeploymentStatus().getMessage());
169            }
170        }
171    
172        private String[] processTargets(String[] args, List targets) {
173            if(args.length >= 2 && args[0].equals("--targets")) {
174                String value = args[1];
175                StringTokenizer tok = new StringTokenizer(value, ";", false);
176                while(tok.hasMoreTokens()) {
177                    targets.add(tok.nextToken());
178                }
179                String[] temp = new String[args.length-2];
180                System.arraycopy(args, 2, temp, 0, temp.length);
181                args = temp;
182            }
183            return args;
184        }
185        
186        private String[] processInPlace(String[] args, BooleanHolder inPlaceHolder) {
187            if(args.length >= 2 && args[0].equals("--inPlace")) {
188                    inPlaceHolder.inPlace = true;
189                String[] temp = new String[args.length - 1];
190                System.arraycopy(args, 1, temp, 0, temp.length);
191                args = temp;
192            }
193            return args;
194        }
195        
196        private final class BooleanHolder {
197            public boolean inPlace;
198        }
199    }