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.IOException;
021    import java.io.OutputStreamWriter;
022    import java.util.HashSet;
023    import java.util.List;
024    import java.util.Set;
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.ProgressEvent;
030    import javax.enterprise.deploy.spi.status.ProgressListener;
031    import javax.enterprise.deploy.spi.status.ProgressObject;
032    
033    import jline.ConsoleReader;
034    import org.apache.geronimo.common.DeploymentException;
035    
036    /**
037     * Base class for CLI deployer commands.  Tracks some simple properties and
038     * has common utility methods.
039     *
040     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
041     */
042    public abstract class AbstractCommand implements DeployCommand {
043    
044        public AbstractCommand() {
045        }
046    
047        public boolean isLocalOnly() {
048            return false;
049        }
050    
051        protected void emit(ConsoleReader out, String message) throws IOException {
052            out.printString(DeployUtils.reformat(message, 4, 72));
053            out.flushConsole();
054        }
055    
056        /**
057         * Busy-waits until the provided <code>ProgressObject</code>
058         * indicates that it's no longer running.
059         *
060         * @param out a <code>PrintWriter</code> value, only used in case
061         *            of an <code>InterruptedException</code> to output the stack
062         *            trace.
063         * @param po  a <code>ProgressObject</code> value
064         */
065        protected void waitForProgress(final ConsoleReader out, ProgressObject po) {
066            po.addProgressListener(new ProgressListener() {
067                String last = null;
068    
069                public void handleProgressEvent(ProgressEvent event) {
070                    String msg = event.getDeploymentStatus().getMessage();
071                    if (last != null && !last.equals(msg)) {
072                        try {
073                            emit(out, last);
074                        } catch (IOException e1) {
075                            //ignore
076                        }
077                    }
078                    last = msg;
079                }
080            });
081            while (po.getDeploymentStatus().isRunning()) {
082                try {
083                    Thread.sleep(100);
084                } catch (InterruptedException e) {
085                    try {
086                        out.printString(e.getMessage());
087                        out.printNewline();
088                    } catch (IOException e1) {
089                        //ignore
090                    }
091                }
092            }
093            return;
094        }
095    
096        protected static boolean isMultipleTargets(TargetModuleID[] ids) {
097            Set set = new HashSet();
098            for (int i = 0; i < ids.length; i++) {
099                TargetModuleID id = ids[i];
100                set.add(id.getTarget().getName());
101            }
102            return set.size() > 1;
103        }
104    
105        protected static Target[] identifyTargets(List targetNames, final DeploymentManager mgr) throws DeploymentException {
106            //TODO consider if nicknames that match multiple servers should be allowed.  Also if regexps should be used in matching
107            Target[] tlist = new Target[targetNames.size()];
108            Target[] all = mgr.getTargets();
109            Set found = new HashSet();
110            for (int i = 0; i < tlist.length; i++) {
111                for (int j = 0; j < all.length; j++) {
112                    Target server = all[j];
113                    // check for exact target name match
114                    if (server.getName().equals(targetNames.get(i))
115                            // check for "target-nickname" match (they match if
116                            // the full target name contains the user-provided
117                            // nickname)
118                            || server.getName().indexOf(targetNames.get(i).toString()) > -1) {
119                        tlist[i] = server;
120                        if (found.contains(server.getName())) {
121                            throw new DeploymentException("Target list should not contain duplicates or nicknames that match duplicates (" + targetNames.get(i) + ")");
122                        }
123                        found.add(server.getName());
124                        break;
125                    }
126                }
127                if (tlist[i] == null) {
128                    throw new DeploymentException("No target named or matching '" + targetNames.get(i) + "' was found");
129                }
130            }
131            return tlist;
132        }
133    }