View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  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  package org.apache.log4j.net;
18  
19  import java.lang.reflect.Constructor;
20  import java.lang.reflect.InvocationTargetException;
21  import java.lang.reflect.Method;
22  import java.util.HashMap;
23  import java.util.Hashtable;
24  import java.util.Map;
25  
26  import org.apache.log4j.helpers.LogLog;
27  
28  public class ZeroConfSupport {
29      private static Object jmDNS = initializeJMDNS();
30  
31      Object serviceInfo;
32      private static Class jmDNSClass;
33      private static Class serviceInfoClass;
34  
35      public ZeroConfSupport(String zone, int port, String name, Map properties) {
36          //if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
37          boolean isVersion3 = false;
38          try {
39              //create method is in version 3, not version 1
40              jmDNSClass.getMethod("create", null);
41              isVersion3 = true;
42          } catch (NoSuchMethodException e) {
43              //no-op
44          }
45  
46          if (isVersion3) {
47              LogLog.debug("using JmDNS version 3 to construct serviceInfo instance");
48              serviceInfo = buildServiceInfoVersion3(zone, port, name, properties);
49          } else {
50              LogLog.debug("using JmDNS version 1.0 to construct serviceInfo instance");
51              serviceInfo = buildServiceInfoVersion1(zone, port, name, properties);
52          }
53      }
54  
55      public ZeroConfSupport(String zone, int port, String name) {
56          this(zone, port, name, new HashMap());
57      }
58  
59      private static Object createJmDNSVersion1()
60      {
61          try {
62              return jmDNSClass.newInstance();
63          } catch (InstantiationException e) {
64              LogLog.warn("Unable to instantiate JMDNS", e);
65          } catch (IllegalAccessException e) {
66              LogLog.warn("Unable to instantiate JMDNS", e);
67          }
68          return null;
69      }
70  
71      private static Object createJmDNSVersion3()
72      {
73          try {
74              Method jmDNSCreateMethod = jmDNSClass.getMethod("create", null);
75              return jmDNSCreateMethod.invoke(null, null);
76          } catch (IllegalAccessException e) {
77              LogLog.warn("Unable to instantiate jmdns class", e);
78          } catch (NoSuchMethodException e) {
79              LogLog.warn("Unable to access constructor", e);
80          } catch (InvocationTargetException e) {
81                  LogLog.warn("Unable to call constructor", e);
82          }
83          return null;
84      }
85  
86      private Object buildServiceInfoVersion1(String zone, int port, String name, Map properties) {
87          //version 1 uses a hashtable
88          Hashtable hashtableProperties = new Hashtable(properties);
89          try {
90              Class[] args = new Class[6];
91              args[0] = String.class;
92              args[1] = String.class;
93              args[2] = int.class;
94              args[3] = int.class; //weight (0)
95              args[4] = int.class; //priority (0)
96              args[5] = Hashtable.class;
97              Constructor constructor  = serviceInfoClass.getConstructor(args);
98              Object[] values = new Object[6];
99              values[0] = zone;
100             values[1] = name;
101             values[2] = new Integer(port);
102             values[3] = new Integer(0);
103             values[4] = new Integer(0);
104             values[5] = hashtableProperties;
105             Object result = constructor.newInstance(values);
106             LogLog.debug("created serviceinfo: " + result);
107             return result;
108         } catch (IllegalAccessException e) {
109             LogLog.warn("Unable to construct ServiceInfo instance", e);
110         } catch (NoSuchMethodException e) {
111             LogLog.warn("Unable to get ServiceInfo constructor", e);
112         } catch (InstantiationException e) {
113             LogLog.warn("Unable to construct ServiceInfo instance", e);
114         } catch (InvocationTargetException e) {
115             LogLog.warn("Unable to construct ServiceInfo instance", e);
116         }
117         return null;
118     }
119 
120     private Object buildServiceInfoVersion3(String zone, int port, String name, Map properties) {
121         try {
122             Class[] args = new Class[6];
123             args[0] = String.class; //zone/type
124             args[1] = String.class; //display name
125             args[2] = int.class; //port
126             args[3] = int.class; //weight (0)
127             args[4] = int.class; //priority (0)
128             args[5] = Map.class;
129             Method serviceInfoCreateMethod = serviceInfoClass.getMethod("create", args);
130             Object[] values = new Object[6];
131             values[0] = zone;
132             values[1] = name;
133             values[2] = new Integer(port);
134             values[3] = new Integer(0);
135             values[4] = new Integer(0);
136             values[5] = properties;
137             Object result = serviceInfoCreateMethod.invoke(null, values);
138             LogLog.debug("created serviceinfo: " + result);
139             return result;
140         } catch (IllegalAccessException e) {
141             LogLog.warn("Unable to invoke create method", e);
142         } catch (NoSuchMethodException e) {
143             LogLog.warn("Unable to find create method", e);
144         } catch (InvocationTargetException e) {
145                 LogLog.warn("Unable to invoke create method", e);
146         }
147         return null;
148     }
149 
150     public void advertise() {
151         try {
152             Method method = jmDNSClass.getMethod("registerService", new Class[]{serviceInfoClass});
153             method.invoke(jmDNS, new Object[]{serviceInfo});
154             LogLog.debug("registered serviceInfo: " + serviceInfo);
155         } catch(IllegalAccessException e) {
156             LogLog.warn("Unable to invoke registerService method", e);
157         } catch(NoSuchMethodException e) {
158             LogLog.warn("No registerService method", e);
159         } catch(InvocationTargetException e) {
160             LogLog.warn("Unable to invoke registerService method", e);
161         }
162     }
163 
164     public void unadvertise() {
165         try {
166             Method method = jmDNSClass.getMethod("unregisterService", new Class[]{serviceInfoClass});
167             method.invoke(jmDNS, new Object[]{serviceInfo});
168             LogLog.debug("unregistered serviceInfo: " + serviceInfo);
169         } catch(IllegalAccessException e) {
170             LogLog.warn("Unable to invoke unregisterService method", e);
171         } catch(NoSuchMethodException e) {
172             LogLog.warn("No unregisterService method", e);
173         } catch(InvocationTargetException e) {
174             LogLog.warn("Unable to invoke unregisterService method", e);
175        }
176     }
177 
178     private static Object initializeJMDNS() {
179         try {
180             jmDNSClass = Class.forName("javax.jmdns.JmDNS");
181             serviceInfoClass = Class.forName("javax.jmdns.ServiceInfo");
182         } catch (ClassNotFoundException e) {
183             LogLog.warn("JmDNS or serviceInfo class not found", e);
184         }
185 
186         //if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
187         boolean isVersion3 = false;
188         try {
189             //create method is in version 3, not version 1
190             jmDNSClass.getMethod("create", null);
191             isVersion3 = true;
192         } catch (NoSuchMethodException e) {
193             //no-op
194         }
195 
196         if (isVersion3) {
197             return createJmDNSVersion3();
198         } else {
199             return createJmDNSVersion1();
200         }
201     }
202 
203     public static Object getJMDNSInstance() {
204         return jmDNS;
205     }
206 }