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    package org.apache.activemq.console.command;
018    
019    import java.net.URI;
020    import java.net.URISyntaxException;
021    import java.util.ArrayList;
022    import java.util.Iterator;
023    import java.util.List;
024    
025    import javax.jms.Connection;
026    import javax.jms.ConnectionFactory;
027    import javax.jms.JMSException;
028    
029    import org.apache.activemq.ActiveMQConnectionFactory;
030    
031    public abstract class AbstractAmqCommand extends AbstractCommand {
032        private URI brokerUrl;
033        private ConnectionFactory factory;
034        private String factoryClassString;
035        private String username;
036        private String password;
037        private PasswordFactory passwordFactory;
038        private final List<Connection> connections = new ArrayList<Connection>();
039        private String passwordFactoryClassString;
040    
041        /**
042         * Establishes a connection to the remote broker specified by the broker
043         * url.
044         * 
045         * @return - connection to the broker
046         * @throws JMSException
047         */
048        protected Connection createConnection() throws JMSException {
049            return createConnection(getUsername(), getPassword());
050        }
051    
052        /**
053         * Establishes a connection to the remote broker specified by the broker
054         * url.
055         * 
056         * @param username - username for the connection
057         * @param password - password for the connection
058         * @return - connection to the broker
059         * @throws JMSException
060         */
061        protected Connection createConnection(String username, String password) throws JMSException {
062            if (getBrokerUrl() == null) {
063                context
064                    .printException(new IllegalStateException(
065                                                              "You must specify a broker URL to connect to using the --amqurl option."));
066                return null;
067            }
068    
069            ConnectionFactory factory = getConnectionFactory();
070            Connection conn;
071    
072            if (null == username && null == password)
073                conn = factory.createConnection();
074            else
075                conn = factory.createConnection(username, password);
076    
077            connections.add(conn);
078            conn.start();
079    
080            return conn;
081        }
082    
083        /**
084         * Close all created connections.
085         */
086        protected void closeAllConnections() {
087            for (Iterator<Connection> i = connections.iterator(); i.hasNext();) {
088                try {
089                    i.next().close();
090                } catch (Exception e) {
091                }
092            }
093    
094            connections.clear();
095        }
096    
097        /**
098         * Handle the --amqurl option.
099         * 
100         * @param token - current option
101         * @param tokens - succeeding list of arguments
102         * @throws Exception
103         */
104        protected void handleOption(String token, List tokens) throws Exception {
105            // Try to handle the options first
106            if (token.equals("--amqurl")) {
107                // If no broker url specified, or next token is a new option
108                if (tokens.isEmpty() || ((String)tokens.get(0)).startsWith("-")) {
109                    context.printException(new IllegalArgumentException("Broker URL not specified."));
110                    tokens.clear();
111                    return;
112                }
113    
114                // If broker url already specified
115                if (getBrokerUrl() != null) {
116                    context
117                        .printException(new IllegalArgumentException("Multiple broker URL cannot be specified."));
118                    tokens.clear();
119                    return;
120                }
121    
122                String strBrokerUrl = (String)tokens.remove(0);
123    
124                try {
125                    setBrokerUrl(new URI(strBrokerUrl));
126                } catch (URISyntaxException e) {
127                    context.printException(e);
128                    tokens.clear();
129                    return;
130                }
131            } else if (token.equals("--factory")) {
132                factoryClassString = (String) tokens.remove(0);
133            } else if (token.equals("--passwordFactory")) {
134                passwordFactoryClassString = (String) tokens.remove(0);
135            } else if (token.equals("--password")) {
136                password = (String) tokens.remove(0);
137            } else if (token.equals("--user")) {
138                username = (String) tokens.remove(0);
139            } else {
140                // Let the super class handle the option
141                super.handleOption(token, tokens);
142            }
143        }
144    
145        /**
146         * Set the broker url.
147         * 
148         * @param brokerUrl - new broker url
149         */
150        protected void setBrokerUrl(URI brokerUrl) {
151            this.brokerUrl = brokerUrl;
152        }
153    
154        /**
155         * Set the broker url.
156         * 
157         * @param address - address of the new broker url
158         * @throws URISyntaxException
159         */
160        protected void setBrokerUrl(String address) throws URISyntaxException {
161            this.brokerUrl = new URI(address);
162        }
163    
164        /**
165         * Get the current broker url.
166         * 
167         * @return current broker url
168         */
169        protected URI getBrokerUrl() {
170            return brokerUrl;
171        }
172    
173        /**
174         * @return the factory
175         */
176        @SuppressWarnings("unchecked")
177        public ConnectionFactory getConnectionFactory() {
178            if (factory == null && factoryClassString != null) {
179                try {
180                    Class klass = Class.forName(factoryClassString);
181    
182                    if (getUsername() != null || getPassword() != null) {
183                        factory = (ConnectionFactory) klass.getConstructor(
184                                String.class, String.class, URI.class).newInstance(
185                                getUsername(), getPassword(), getBrokerUrl());
186                    } else {
187                        factory = (ConnectionFactory) klass.getConstructor(
188                                URI.class).newInstance(getBrokerUrl());
189                    }
190                } catch (Exception e) {
191                    throw new RuntimeException(e);
192                }
193            }
194    
195            if (factory == null) {
196                if (getUsername() != null || getPassword() != null) {
197                    factory = new ActiveMQConnectionFactory(getUsername(),
198                            getPassword(), getBrokerUrl());
199                } else {
200                    factory = new ActiveMQConnectionFactory(getBrokerUrl());
201                }
202            }
203    
204            return factory;
205        }
206    
207        /**
208         * @return the username
209         */
210        public String getUsername() {
211            return username;
212        }
213    
214        /**
215         * @param factory the factory to set
216         */
217        public void setFactory(ConnectionFactory factory) {
218            this.factory = factory;
219        }
220    
221        /**
222         * @param username the username to set
223         */
224        public void setUsername(String username) {
225            this.username = username;
226        }
227    
228        /**
229         * @return the password
230         */
231        public String getPassword() {
232            if (null == password)
233                return null;
234    
235            return getPasswordFactory().getPassword(password);
236        }
237    
238        /**
239         * @param password the password to set
240         */
241        public void setPassword(String password) {
242            this.password = password;
243        }
244    
245        /**
246         * @return the passwordFactory
247         */
248        @SuppressWarnings("unchecked")
249        public PasswordFactory getPasswordFactory() {
250            if (passwordFactory == null && passwordFactoryClassString != null) {
251                try {
252                    Class klass = Class.forName(passwordFactoryClassString);
253                    passwordFactory = (PasswordFactory) klass.newInstance();
254                } catch (Exception e) {
255                    throw new RuntimeException(e);
256                }
257            }
258    
259            // Preserve the fallback case, if someone did specify a bad class, let them realize when things don't work.
260            if (passwordFactory == null) {
261                passwordFactory = DefaultPasswordFactory.factory;
262            }
263    
264            return passwordFactory;
265        }
266    
267        /**
268         * @param passwordFactory the passwordFactory to set
269         */
270        public void setPasswordFactory(PasswordFactory passwordFactory) {
271            this.passwordFactory = passwordFactory;
272        }
273    }