1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.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 import org.apache.logging.log4j.Logger;
26 import org.apache.logging.log4j.core.config.plugins.Plugin;
27 import org.apache.logging.log4j.status.StatusLogger;
28
29
30
31
32
33
34
35
36 @Plugin(name = "multicastdns", category = "Core", elementType = "advertiser", printObject = false)
37 public class MulticastDNSAdvertiser implements Advertiser {
38 protected static final Logger LOGGER = StatusLogger.getLogger();
39 private static Object jmDNS = initializeJMDNS();
40
41 private static Class<?> jmDNSClass;
42 private static Class<?> serviceInfoClass;
43
44 public MulticastDNSAdvertiser()
45 {
46
47 }
48
49
50
51
52
53
54
55
56
57
58
59
60
61 @Override
62 public Object advertise(Map<String, String> properties) {
63
64 Map<String, String> truncatedProperties = new HashMap<String, String>();
65 for (Map.Entry<String, String> entry:properties.entrySet())
66 {
67 if (entry.getKey().length() <= 255 && entry.getValue().length() <= 255)
68 {
69 truncatedProperties.put(entry.getKey(), entry.getValue());
70 }
71 }
72 String protocol = truncatedProperties.get("protocol");
73 String zone = "._log4j._"+(protocol != null ? protocol : "tcp") + ".local.";
74
75 String portString = truncatedProperties.get("port");
76 int port = (portString != null ? Integer.parseInt(portString) : 4555);
77
78 String name = truncatedProperties.get("name");
79
80
81 if (jmDNS != null)
82 {
83 boolean isVersion3 = false;
84 try {
85
86 jmDNSClass.getMethod("create", (Class[])null);
87 isVersion3 = true;
88 } catch (NoSuchMethodException e) {
89
90 }
91 Object serviceInfo;
92 if (isVersion3) {
93 serviceInfo = buildServiceInfoVersion3(zone, port, name, truncatedProperties);
94 } else {
95 serviceInfo = buildServiceInfoVersion1(zone, port, name, truncatedProperties);
96 }
97
98 try {
99 Method method = jmDNSClass.getMethod("registerService", new Class[]{serviceInfoClass});
100 method.invoke(jmDNS, serviceInfo);
101 } catch(IllegalAccessException e) {
102 LOGGER.warn("Unable to invoke registerService method", e);
103 } catch(NoSuchMethodException e) {
104 LOGGER.warn("No registerService method", e);
105 } catch(InvocationTargetException e) {
106 LOGGER.warn("Unable to invoke registerService method", e);
107 }
108 return serviceInfo;
109 }
110 else
111 {
112 LOGGER.warn("JMDNS not available - will not advertise ZeroConf support");
113 return null;
114 }
115 }
116
117
118
119
120
121 @Override
122 public void unadvertise(Object serviceInfo) {
123 if (jmDNS != null) {
124 try {
125 Method method = jmDNSClass.getMethod("unregisterService", new Class[]{serviceInfoClass});
126 method.invoke(jmDNS, serviceInfo);
127 } catch(IllegalAccessException e) {
128 LOGGER.warn("Unable to invoke unregisterService method", e);
129 } catch(NoSuchMethodException e) {
130 LOGGER.warn("No unregisterService method", e);
131 } catch(InvocationTargetException e) {
132 LOGGER.warn("Unable to invoke unregisterService method", e);
133 }
134 }
135 }
136
137 private static Object createJmDNSVersion1()
138 {
139 try {
140 return jmDNSClass.newInstance();
141 } catch (InstantiationException e) {
142 LOGGER.warn("Unable to instantiate JMDNS", e);
143 } catch (IllegalAccessException e) {
144 LOGGER.warn("Unable to instantiate JMDNS", e);
145 }
146 return null;
147 }
148
149 private static Object createJmDNSVersion3()
150 {
151 try {
152 Method jmDNSCreateMethod = jmDNSClass.getMethod("create", (Class[])null);
153 return jmDNSCreateMethod.invoke(null, (Object[])null);
154 } catch (IllegalAccessException e) {
155 LOGGER.warn("Unable to instantiate jmdns class", e);
156 } catch (NoSuchMethodException e) {
157 LOGGER.warn("Unable to access constructor", e);
158 } catch (InvocationTargetException e) {
159 LOGGER.warn("Unable to call constructor", e);
160 }
161 return null;
162 }
163
164 private Object buildServiceInfoVersion1(String zone, int port, String name, Map<String, String> properties) {
165
166 Hashtable<String, String> hashtableProperties = new Hashtable<String, String>(properties);
167 try {
168 Class[] args = new Class[6];
169 args[0] = String.class;
170 args[1] = String.class;
171 args[2] = int.class;
172 args[3] = int.class;
173 args[4] = int.class;
174 args[5] = Hashtable.class;
175 Constructor<?> constructor = serviceInfoClass.getConstructor(args);
176 Object[] values = new Object[6];
177 values[0] = zone;
178 values[1] = name;
179 values[2] = port;
180 values[3] = 0;
181 values[4] = 0;
182 values[5] = hashtableProperties;
183 return constructor.newInstance(values);
184 } catch (IllegalAccessException e) {
185 LOGGER.warn("Unable to construct ServiceInfo instance", e);
186 } catch (NoSuchMethodException e) {
187 LOGGER.warn("Unable to get ServiceInfo constructor", e);
188 } catch (InstantiationException e) {
189 LOGGER.warn("Unable to construct ServiceInfo instance", e);
190 } catch (InvocationTargetException e) {
191 LOGGER.warn("Unable to construct ServiceInfo instance", e);
192 }
193 return null;
194 }
195
196 private Object buildServiceInfoVersion3(String zone, int port, String name, Map<String, String> properties) {
197 try {
198 Class[] args = new Class[6];
199 args[0] = String.class;
200 args[1] = String.class;
201 args[2] = int.class;
202 args[3] = int.class;
203 args[4] = int.class;
204 args[5] = Map.class;
205 Method serviceInfoCreateMethod = serviceInfoClass.getMethod("create", args);
206 Object[] values = new Object[6];
207 values[0] = zone;
208 values[1] = name;
209 values[2] = port;
210 values[3] = 0;
211 values[4] = 0;
212 values[5] = properties;
213 return serviceInfoCreateMethod.invoke(null, values);
214 } catch (IllegalAccessException e) {
215 LOGGER.warn("Unable to invoke create method", e);
216 } catch (NoSuchMethodException e) {
217 LOGGER.warn("Unable to find create method", e);
218 } catch (InvocationTargetException e) {
219 LOGGER.warn("Unable to invoke create method", e);
220 }
221 return null;
222 }
223
224 private static Object initializeJMDNS() {
225 try {
226 jmDNSClass = Class.forName("javax.jmdns.JmDNS");
227 serviceInfoClass = Class.forName("javax.jmdns.ServiceInfo");
228
229 boolean isVersion3 = false;
230 try {
231
232 jmDNSClass.getMethod("create", (Class[])null);
233 isVersion3 = true;
234 } catch (NoSuchMethodException e) {
235
236 }
237
238 if (isVersion3) {
239 return createJmDNSVersion3();
240 } else {
241 return createJmDNSVersion1();
242 }
243 } catch (ClassNotFoundException e) {
244 LOGGER.warn("JmDNS or serviceInfo class not found", e);
245 } catch (ExceptionInInitializerError e2) {
246 LOGGER.warn("JmDNS or serviceInfo class not found", e2);
247 }
248 return null;
249 }
250 }