/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.googlecode.perftrace.log4j.net;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.googlecode.perftrace.log4j.helpers.LogLog;
public class ZeroConfSupport {
private static Object jmDNS = initializeJMDNS();
Object serviceInfo;
private static Class jmDNSClass;
private static Class serviceInfoClass;
public ZeroConfSupport(String zone, int port, String name, Map properties) {
//if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
boolean isVersion3 = false;
try {
//create method is in version 3, not version 1
jmDNSClass.getMethod("create", null);
isVersion3 = true;
} catch (NoSuchMethodException e) {
//no-op
}
if (isVersion3) {
LogLog.debug("using JmDNS version 3 to construct serviceInfo instance");
serviceInfo = buildServiceInfoVersion3(zone, port, name, properties);
} else {
LogLog.debug("using JmDNS version 1.0 to construct serviceInfo instance");
serviceInfo = buildServiceInfoVersion1(zone, port, name, properties);
}
}
public ZeroConfSupport(String zone, int port, String name) {
this(zone, port, name, new HashMap());
}
private static Object createJmDNSVersion1()
{
try {
return jmDNSClass.newInstance();
} catch (InstantiationException e) {
LogLog.warn("Unable to instantiate JMDNS", e);
} catch (IllegalAccessException e) {
LogLog.warn("Unable to instantiate JMDNS", e);
}
return null;
}
private static Object createJmDNSVersion3()
{
try {
Method jmDNSCreateMethod = jmDNSClass.getMethod("create", null);
return jmDNSCreateMethod.invoke(null, null);
} catch (IllegalAccessException e) {
LogLog.warn("Unable to instantiate jmdns class", e);
} catch (NoSuchMethodException e) {
LogLog.warn("Unable to access constructor", e);
} catch (InvocationTargetException e) {
LogLog.warn("Unable to call constructor", e);
}
return null;
}
private Object buildServiceInfoVersion1(String zone, int port, String name, Map properties) {
//version 1 uses a hashtable
Hashtable hashtableProperties = new Hashtable(properties);
try {
Class[] args = new Class[6];
args[0] = String.class;
args[1] = String.class;
args[2] = int.class;
args[3] = int.class; //weight (0)
args[4] = int.class; //priority (0)
args[5] = Hashtable.class;
Constructor constructor = serviceInfoClass.getConstructor(args);
Object[] values = new Object[6];
values[0] = zone;
values[1] = name;
values[2] = new Integer(port);
values[3] = new Integer(0);
values[4] = new Integer(0);
values[5] = hashtableProperties;
Object result = constructor.newInstance(values);
LogLog.debug("created serviceinfo: " + result);
return result;
} catch (IllegalAccessException e) {
LogLog.warn("Unable to construct ServiceInfo instance", e);
} catch (NoSuchMethodException e) {
LogLog.warn("Unable to get ServiceInfo constructor", e);
} catch (InstantiationException e) {
LogLog.warn("Unable to construct ServiceInfo instance", e);
} catch (InvocationTargetException e) {
LogLog.warn("Unable to construct ServiceInfo instance", e);
}
return null;
}
private Object buildServiceInfoVersion3(String zone, int port, String name, Map properties) {
try {
Class[] args = new Class[6];
args[0] = String.class; //zone/type
args[1] = String.class; //display name
args[2] = int.class; //port
args[3] = int.class; //weight (0)
args[4] = int.class; //priority (0)
args[5] = Map.class;
Method serviceInfoCreateMethod = serviceInfoClass.getMethod("create", args);
Object[] values = new Object[6];
values[0] = zone;
values[1] = name;
values[2] = new Integer(port);
values[3] = new Integer(0);
values[4] = new Integer(0);
values[5] = properties;
Object result = serviceInfoCreateMethod.invoke(null, values);
LogLog.debug("created serviceinfo: " + result);
return result;
} catch (IllegalAccessException e) {
LogLog.warn("Unable to invoke create method", e);
} catch (NoSuchMethodException e) {
LogLog.warn("Unable to find create method", e);
} catch (InvocationTargetException e) {
LogLog.warn("Unable to invoke create method", e);
}
return null;
}
public void advertise() {
try {
Method method = jmDNSClass.getMethod("registerService", new Class[]{serviceInfoClass});
method.invoke(jmDNS, new Object[]{serviceInfo});
LogLog.debug("registered serviceInfo: " + serviceInfo);
} catch(IllegalAccessException e) {
LogLog.warn("Unable to invoke registerService method", e);
} catch(NoSuchMethodException e) {
LogLog.warn("No registerService method", e);
} catch(InvocationTargetException e) {
LogLog.warn("Unable to invoke registerService method", e);
}
}
public void unadvertise() {
try {
Method method = jmDNSClass.getMethod("unregisterService", new Class[]{serviceInfoClass});
method.invoke(jmDNS, new Object[]{serviceInfo});
LogLog.debug("unregistered serviceInfo: " + serviceInfo);
} catch(IllegalAccessException e) {
LogLog.warn("Unable to invoke unregisterService method", e);
} catch(NoSuchMethodException e) {
LogLog.warn("No unregisterService method", e);
} catch(InvocationTargetException e) {
LogLog.warn("Unable to invoke unregisterService method", e);
}
}
private static Object initializeJMDNS() {
try {
jmDNSClass = Class.forName("javax.jmdns.JmDNS");
serviceInfoClass = Class.forName("javax.jmdns.ServiceInfo");
} catch (ClassNotFoundException e) {
LogLog.warn("JmDNS or serviceInfo class not found", e);
}
//if version 3 is available, use it to constuct a serviceInfo instance, otherwise support the version1 API
boolean isVersion3 = false;
try {
//create method is in version 3, not version 1
jmDNSClass.getMethod("create", null);
isVersion3 = true;
} catch (NoSuchMethodException e) {
//no-op
}
if (isVersion3) {
return createJmDNSVersion3();
} else {
return createJmDNSVersion1();
}
}
public static Object getJMDNSInstance() {
return jmDNS;
}
}