View Javadoc

1   /***
2    * 
3    * Copyright 2004 Protique Ltd
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.codehaus.activemq.transport.zeroconf;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.codehaus.activemq.ConfigurationException;
23  import org.codehaus.activemq.NotStartedException;
24  import org.codehaus.activemq.transport.DiscoveryAgent;
25  import org.codehaus.activemq.transport.DiscoveryAgentSupport;
26  import org.codehaus.activemq.transport.DiscoveryEvent;
27  import org.codehaus.activemq.util.JMSExceptionHelper;
28  import org.codehaus.activemq.util.MapHelper;
29  
30  import javax.jmdns.JmDNS;
31  import javax.jmdns.ServiceInfo;
32  import javax.jmdns.ServiceListener;
33  import javax.jms.JMSException;
34  import java.io.IOException;
35  import java.net.InetAddress;
36  import java.net.UnknownHostException;
37  import java.util.Enumeration;
38  import java.util.HashMap;
39  import java.util.Hashtable;
40  import java.util.Map;
41  
42  /***
43   * A {@link DiscoveryAgent} using <a href="http://www.zeroconf.org/">Zeroconf</a>
44   * via the <a href="http://jmdns.sf.net/">jmDNS</a> library
45   *
46   * @version $Revision: 1.5 $
47   */
48  public class ZeroconfDiscoveryAgent extends DiscoveryAgentSupport implements ServiceListener {
49      private static final Log log = LogFactory.getLog(ZeroconfDiscoveryAgent.class);
50  
51      private JmDNS jmdns;
52      private InetAddress localAddress;
53      private String localhost;
54      private String type;
55      private int weight = 0;
56      private int priority = 0;
57  
58      // DiscoveryAgent interface
59      //-------------------------------------------------------------------------
60      public void start() throws JMSException {
61          if (type == null) {
62              throw new ConfigurationException("You must specify a type of service to discover");
63          }
64          if (!type.endsWith(".")) {
65              log.warn("The type '" + type + "' should end with '.' to be a valid Zeroconf type");
66              type += ".";
67          }
68          try {
69              if (jmdns == null) {
70                  jmdns = createJmDNS();
71              }
72              if (getDiscoveryListener() != null) {
73                  log.info("Discovering service of type: " + type);
74                  jmdns.addServiceListener(type, this);
75              }
76          }
77          catch (IOException e) {
78              JMSExceptionHelper.newJMSException("Failed to start JmDNS service: " + e, e);
79          }
80      }
81  
82      public void stop() throws JMSException {
83          jmdns.unregisterAllServices();
84          jmdns.close();
85      }
86  
87      public void registerService(String name, Map details) throws JMSException {
88          if (jmdns == null) {
89              throw new NotStartedException();
90          }
91          try {
92              jmdns.registerService(createServiceInfo(name, details));
93          }
94          catch (IOException e) {
95              JMSExceptionHelper.newJMSException("Could not register service: " + name + ". Reason: " + e, e);
96          }
97      }
98  
99  
100     // ServiceListener interface
101     //-------------------------------------------------------------------------
102     public void addService(JmDNS jmDNS, String type, String name) {
103         if (log.isDebugEnabled()) {
104             log.debug("addService with type: " + type + " name: " + name);
105         }
106         jmDNS.requestServiceInfo(type, name);
107     }
108 
109     public void removeService(JmDNS jmDNS, String type, String name) {
110         if (log.isDebugEnabled()) {
111             log.debug("removeService with type: " + type + " name: " + name);
112         }
113         DiscoveryEvent event = new DiscoveryEvent(this, name);
114         getDiscoveryListener().removeService(event);
115     }
116 
117     public void resolveService(JmDNS jmDNS, String type, String name, ServiceInfo serviceInfo) {
118         if (log.isDebugEnabled()) {
119             log.debug("removeService with type: " + type + " name: " + name + " info: " + serviceInfo);
120         }
121 
122         Map map = new HashMap();
123         if (serviceInfo != null) {
124             Enumeration iter = serviceInfo.getPropertyNames();
125             while (iter.hasMoreElements()) {
126                 String key = (String) iter.nextElement();
127                 String value = serviceInfo.getPropertyString(key);
128                 map.put(key, value);
129             }
130         }
131         DiscoveryEvent event = new DiscoveryEvent(this, name, map);
132         getDiscoveryListener().addService(event);
133     }
134 
135     public String getType() {
136         return type;
137     }
138 
139     public void setType(String type) {
140         this.type = type;
141     }
142 
143     public int getPriority() {
144         return priority;
145     }
146 
147     public void setPriority(int priority) {
148         this.priority = priority;
149     }
150 
151     public int getWeight() {
152         return weight;
153     }
154 
155     public void setWeight(int weight) {
156         this.weight = weight;
157     }
158 
159     public JmDNS getJmdns() {
160         return jmdns;
161     }
162 
163     public void setJmdns(JmDNS jmdns) {
164         this.jmdns = jmdns;
165     }
166 
167 
168     public InetAddress getLocalAddress() throws UnknownHostException {
169         if (localAddress == null) {
170             localAddress = createLocalAddress();
171         }
172         return localAddress;
173     }
174 
175     public void setLocalAddress(InetAddress localAddress) {
176         this.localAddress = localAddress;
177     }
178 
179     public String getLocalhost() {
180         return localhost;
181     }
182 
183     public void setLocalhost(String localhost) {
184         this.localhost = localhost;
185     }
186 
187     // Implementation methods
188     //-------------------------------------------------------------------------
189     protected ServiceInfo createServiceInfo(String name, Map map) {
190         name += "." + type;
191         int port = MapHelper.getInt(map, "port", 0);
192 
193         if (log.isDebugEnabled()) {
194             log.debug("Registering service type: " + type + " name: " + name + " details: " + map);
195         }
196         return new ServiceInfo(type, name, port, weight, priority, new Hashtable(map));
197     }
198 
199     protected JmDNS createJmDNS() throws IOException {
200         return new JmDNS(getLocalAddress());
201     }
202 
203     protected InetAddress createLocalAddress() throws UnknownHostException {
204         if (localhost != null) {
205             return InetAddress.getByName(localhost);
206         }
207         return InetAddress.getLocalHost();
208     }
209 }