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 */
017package org.apache.activemq.console.command;
018
019import java.net.URI;
020import java.net.URISyntaxException;
021import java.util.ArrayList;
022import java.util.Iterator;
023import java.util.List;
024
025import javax.jms.Connection;
026import javax.jms.ConnectionFactory;
027import javax.jms.JMSException;
028
029import org.apache.activemq.ActiveMQConnectionFactory;
030
031public 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}