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 }