001 /**
002 *
003 * Copyright 2004 Protique Ltd
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.activemq.transport;
019
020 import org.apache.commons.logging.Log;
021 import org.apache.commons.logging.LogFactory;
022 import org.activemq.ConfigurationException;
023 import org.activemq.io.WireFormat;
024 import org.activemq.transport.reliable.ReliableTransportChannel;
025 import org.activemq.transport.composite.CompositeTransportChannelFactory;
026 import org.activemq.util.Callback;
027 import org.activemq.util.ExceptionTemplate;
028 import org.activemq.util.MapHelper;
029
030 import javax.jms.JMSException;
031 import java.net.URI;
032 import java.net.URISyntaxException;
033 import java.util.List;
034 import java.util.Map;
035 import java.util.ArrayList;
036 import java.util.Iterator;
037
038 /**
039 * A {@link ReliableTransportChannel} which uses a {@link DiscoveryAgent} to discover remote broker
040 * instances and dynamically connect to them.
041 *
042 * @version $Revision: 1.1.1.1 $
043 */
044 public class DiscoveryTransportChannel extends ReliableTransportChannel implements DiscoveryListener {
045 private static final Log log = LogFactory.getLog(DiscoveryTransportChannel.class);
046
047
048 private DiscoveryAgent discoveryAgent;
049 private String remoteUserName;
050 private String remotePassword;
051
052
053 public DiscoveryTransportChannel(WireFormat wireFormat, DiscoveryAgent discoveryAgent) {
054 super(wireFormat);
055 this.discoveryAgent = discoveryAgent;
056 }
057
058 public void start() throws JMSException {
059 if (discoveryAgent == null) {
060 throw new ConfigurationException("Must be configured with a discoveryAgent property");
061 }
062
063 // lets pass into the agent the broker name and connection details
064 discoveryAgent.addDiscoveryListener(this);
065 discoveryAgent.start();
066
067 super.start();
068 }
069
070 public void stop() {
071 ExceptionTemplate template = new ExceptionTemplate();
072 template.run(new Callback() {
073 public void execute() throws Throwable {
074 discoveryAgent.stop();
075 }
076 });
077 template.run(new Callback() {
078 public void execute() throws Throwable {
079 DiscoveryTransportChannel.super.stop();
080 }
081 });
082 Throwable e = template.getFirstException();
083 log.warn("Failed to stop the transport channel cleanly due to: " + e, e);
084 }
085
086
087 public synchronized void addService(DiscoveryEvent event) {
088 Map details = event.getServiceDetails();
089 String url = MapHelper.getString(details, "connectURL");
090 if (url != null) {
091 try {
092 List uris = parseURIs(new URI(url));
093 for (Iterator uter = uris.iterator(); uter.hasNext();) {
094 URI uri = (URI) uter.next();
095 addURI(uri, details);
096 }
097 }
098 catch (URISyntaxException e) {
099 log.warn("Could not connect to remote URI: " + url + " due to bad URI syntax: " + e, e);
100 }
101 }
102 }
103
104 public synchronized void removeService(DiscoveryEvent event) {
105 Map details = event.getServiceDetails();
106 String url = MapHelper.getString(details, "connectURL");
107 if (url != null) {
108 try {
109 List uris = parseURIs(new URI(url));
110 for (Iterator uter = uris.iterator(); uter.hasNext();) {
111 URI uri = (URI) uter.next();
112 removeURI(uri);
113 }
114 }
115 catch (URISyntaxException e) {
116 log.warn("Could not remove remote URI: " + url + " due to bad URI syntax: " + e, e);
117 }
118 }
119 }
120
121 protected void addURI(URI uri, Map details) {
122 List urlList = getUris();
123 if (!urlList.contains(uri)) {
124 log.info("Adding new broker connection URL: " + uri + " with details: " + details);
125
126 urlList.add(uri);
127 }
128 }
129
130 protected void removeURI(URI uri) {
131 synchronized (this) {
132 List urlList = getUris();
133 if (urlList.remove(uri)) {
134 log.info("Removing broker connection URL: " + uri);
135 }
136 }
137 }
138
139 protected List parseURIs(URI uri) {
140 List answer = new ArrayList();
141 try {
142 CompositeTransportChannelFactory.parseURIs(answer, uri);
143 }
144 catch (URISyntaxException e) {
145 log.warn("Failed to parse URI: " + uri, e);
146 answer.add(uri);
147 }
148 return answer;
149 }
150
151 // Properties
152 //-------------------------------------------------------------------------
153 public DiscoveryAgent getDiscoveryAgent() {
154 return discoveryAgent;
155 }
156
157 public void setDiscoveryAgent(DiscoveryAgent discoveryAgent) {
158 this.discoveryAgent = discoveryAgent;
159 }
160
161
162 public String getRemotePassword() {
163 return remotePassword;
164 }
165
166 public void setRemotePassword(String remotePassword) {
167 this.remotePassword = remotePassword;
168 }
169
170 public String getRemoteUserName() {
171 return remoteUserName;
172 }
173
174 public void setRemoteUserName(String remoteUserName) {
175 this.remoteUserName = remoteUserName;
176 }
177
178 }