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.File;
021    import java.io.PrintWriter;
022    import java.io.IOException;
023    import java.util.Arrays;
024    import java.util.List;
025    import java.util.StringTokenizer;
026    
027    import javax.enterprise.deploy.spi.DeploymentManager;
028    import javax.enterprise.deploy.spi.Target;
029    import javax.enterprise.deploy.spi.TargetModuleID;
030    import javax.enterprise.deploy.spi.status.ProgressObject;
031    
032    import org.apache.geronimo.cli.deployer.CommandArgs;
033    import org.apache.geronimo.cli.deployer.DistributeCommandArgs;
034    import org.apache.geronimo.common.DeploymentException;
035    import org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager;
036    import jline.ConsoleReader;
037    
038    /**
039     * The CLI deployer logic to distribute.
040     *
041     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
042     */
043    public class CommandDistribute extends AbstractCommand {
044    
045        protected ProgressObject runCommand(DeploymentManager mgr, ConsoleReader out, boolean inPlace, Target[] tlist, File module, File plan) throws DeploymentException {
046            if (inPlace) {
047                if (!(mgr instanceof JMXDeploymentManager)) {
048                    throw new DeploymentSyntaxException(
049                            "Target DeploymentManager is not a Geronimo one. \n" +
050                            "Cannot perform in-place deployment.");
051                }
052                JMXDeploymentManager jmxMgr = (JMXDeploymentManager) mgr;
053                try {
054                    jmxMgr.setInPlace(true);
055                    return mgr.distribute(tlist, module, plan);
056                } finally {
057                    jmxMgr.setInPlace(false);
058                }
059            } else {
060                return mgr.distribute(tlist, module, plan);
061            }
062        }
063    
064        protected String getAction() {
065            return "Distributed";
066        }
067    
068        public void execute(ConsoleReader consoleReader, ServerConnection connection, CommandArgs commandArgs) throws DeploymentException {
069            if (!(commandArgs instanceof DistributeCommandArgs)) {
070                throw new DeploymentSyntaxException("CommandArgs has the type [" + commandArgs.getClass() + "]; expected [" + DistributeCommandArgs.class + "]");
071            }
072            DistributeCommandArgs distributeCommandArgs = (DistributeCommandArgs) commandArgs;
073            
074            BooleanHolder inPlaceHolder = new BooleanHolder();
075            inPlaceHolder.inPlace = distributeCommandArgs.isInPlace();
076            
077            List<String> targets = Arrays.asList(distributeCommandArgs.getTargets());
078    
079            String[] args = distributeCommandArgs.getArgs();
080            File module = null;
081            File plan = null;
082            if(args.length > 0) {
083                File test = new File(args[0]);
084                if(DeployUtils.isJarFile(test) || test.isDirectory()) {
085                    if(module != null) {
086                        throw new DeploymentSyntaxException("Module and plan cannot both be JAR files or directories!");
087                    }
088                    module = test;
089                } else {
090                    if(plan != null) {
091                        throw new DeploymentSyntaxException("Module or plan must be a JAR file or directory!");
092                    }
093                    plan = test;
094                }
095            }
096            if(args.length > 1) {
097                File test = new File(args[1]);
098                if(DeployUtils.isJarFile(test) || test.isDirectory()) {
099                    if(module != null) {
100                        throw new DeploymentSyntaxException("Module and plan cannot both be JAR files or directories!");
101                    }
102                    module = test;
103                } else {
104                    if(plan != null) {
105                        throw new DeploymentSyntaxException("Module or plan must be a JAR file or directory!");
106                    }
107                    plan = test;
108                }
109            }
110            if(module != null) {
111                module = module.getAbsoluteFile();
112            }
113            if(plan != null) {
114                plan = plan.getAbsoluteFile();
115            }
116            try {
117                executeOnline(connection, inPlaceHolder.inPlace, targets, consoleReader, module, plan);
118            } catch (IOException e) {
119                throw new DeploymentException("Could not write to output", e);
120            }
121        }
122    
123        private void executeOnline(ServerConnection connection, boolean inPlace, List targets, ConsoleReader out, File module, File plan) throws DeploymentException, IOException {
124            final DeploymentManager mgr = connection.getDeploymentManager();
125            TargetModuleID[] results;
126            boolean multipleTargets;
127            ProgressObject po;
128            if(targets.size() > 0) {
129                Target[] tlist = identifyTargets(targets, mgr);
130                multipleTargets = tlist.length > 1;
131                po = runCommand(mgr, out, inPlace, tlist, module, plan);
132                waitForProgress(out, po);
133            } else {
134                Target[] tlist = mgr.getTargets();
135                if (null == tlist) {
136                    throw new IllegalStateException("No target to distribute to");
137                }
138                tlist = new Target[] {tlist[0]};
139    
140                multipleTargets = tlist.length > 1;
141                po = runCommand(mgr, out, inPlace, tlist, module, plan);
142                waitForProgress(out, po);
143            }
144    
145            // print the results that succeeded
146            results = po.getResultTargetModuleIDs();
147            for (int i = 0; i < results.length; i++) {
148                TargetModuleID result = results[i];
149                out.printString(DeployUtils.reformat(getAction()+" "+result.getModuleID()+(multipleTargets ? " to "+result.getTarget().getName() : "")+(result.getWebURL() == null || !getAction().equals("Deployed") ? "" : " @ "+result.getWebURL()), 4, 72));
150                if(result.getChildTargetModuleID() != null) {
151                    for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
152                        TargetModuleID child = result.getChildTargetModuleID()[j];
153                        out.printString(DeployUtils.reformat("  `-> "+child.getModuleID()+(child.getWebURL() == null || !getAction().equals("Deployed") ? "" : " @ "+child.getWebURL()),4, 72));
154                    }
155                }
156            }
157    
158            // if any results failed then throw so that we'll return non-0
159            // to the operating system
160            if(po.getDeploymentStatus().isFailed()) {
161                throw new DeploymentException("Operation failed: "+po.getDeploymentStatus().getMessage());
162            }
163        }
164    
165        private String[] processTargets(String[] args, List targets) {
166            if(args.length >= 2 && args[0].equals("--targets")) {
167                String value = args[1];
168                StringTokenizer tok = new StringTokenizer(value, ";", false);
169                while(tok.hasMoreTokens()) {
170                    targets.add(tok.nextToken());
171                }
172                String[] temp = new String[args.length-2];
173                System.arraycopy(args, 2, temp, 0, temp.length);
174                args = temp;
175            }
176            return args;
177        }
178        
179        private String[] processInPlace(String[] args, BooleanHolder inPlaceHolder) {
180            if(args.length >= 2 && args[0].equals("--inPlace")) {
181                    inPlaceHolder.inPlace = true;
182                String[] temp = new String[args.length - 1];
183                System.arraycopy(args, 1, temp, 0, temp.length);
184                args = temp;
185            }
186            return args;
187        }
188        
189        private final class BooleanHolder {
190            public boolean inPlace;
191        }
192    }