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.io.IOException;
20  import java.lang.reflect.Method;
21  
22  import javax.jmdns.JmDNS;
23  import javax.jmdns.ServiceInfo;
24  
25  import org.apache.log4j.Level;
26  
27  
28  /***
29   * A sub-class of SocketHubAppender that broadcasts its configuration via Zeroconf.
30   * 
31   * This allows Zeroconf aware applications such as Chainsaw to be able to detect them, and automatically configure
32   * themselves to be able to connect to them.
33   * 
34   * @author psmith
35   *
36   */
37  public class ZeroConfSocketHubAppender extends SocketHubAppender {
38  
39      public static final String DEFAULT_ZEROCONF_ZONE="_log4j._tcp.local.";
40      private String zeroConfZone = DEFAULT_ZEROCONF_ZONE;
41      
42      private Object logger;
43      private Method logInfoMethod;
44      private Method logErrorMethod;
45      
46      public ZeroConfSocketHubAppender() {
47          setName("SocketHubAppender");
48          try {
49              Method getLoggerMethod = this.getClass().getMethod("getLogger", new Class[0]);
50              logger = getLoggerMethod.invoke(this, new Object[0]);
51              logInfoMethod = logger.getClass().getMethod("info", new Class[] {Object.class});
52              logErrorMethod = logger.getClass().getMethod("error", new Class[] {Object.class});
53          }catch(Exception e) {
54              // we're not in log4j1.3 land
55          }
56      }
57      public void activateOptions() {
58          super.activateOptions();
59          
60          try {
61              JmDNS jmDNS = Zeroconf4log4j.getInstance();
62              ServiceInfo info = buildServiceInfo();
63              logWithlog4j12Compatibility(Level.INFO,"Registering this SocketHubAppender as :" + info);
64              jmDNS.registerService(info);
65          } catch (IOException e) {
66              logWithlog4j12Compatibility(Level.ERROR,"Failed to instantiate JmDNS to broadcast via ZeroConf, will now operate in simple SocketHubAppender mode");
67          }
68      }
69      private ServiceInfo buildServiceInfo() {
70          return new ServiceInfo(zeroConfZone, getName(), getPort(), "SocketHubAppender on port " + getPort() );
71      }
72      
73      private void logWithlog4j12Compatibility(Level level, String message) {
74          if(logger!=null && logInfoMethod!=null & logErrorMethod!=null) {
75              try {
76                  switch (level.toInt()) {
77                  case Level.INFO_INT:
78                      logInfoMethod.invoke(logger, new Object[] { message });
79                      break;
80                  case Level.ERROR_INT:
81                      logInfoMethod.invoke(logger, new Object[] { message });
82                      break;
83                  }
84              } catch (Exception e) {
85                  e.printStackTrace();
86              }
87          }
88      }
89  
90      /***
91       * Returns the ZeroConf domain that will be used to register this 'device'.
92       * 
93       * @return String ZeroConf zone
94       */
95      public String getZeroConfZone() {
96          return zeroConfZone;
97      }
98  
99  
100     /***
101      * Sets the ZeroConf zone to register this device under, BE CAREFUL with this value
102      * as ZeroConf has some weird naming conventions, it should start with an "_" and end in a ".",
103      * if you're not sure about this value might I suggest that you leave it at the default value
104      * which is specified in {@link #DEFAULT_ZEROCONF_ZONE }.
105      * 
106      * This method does NO(0, zero, pun not intended) checks on this value.
107      * 
108      * @param zeroConfZone
109      */
110     public void setZeroConfZone(String zeroConfZone) {
111 //        TODO work out a sane checking mechanism that verifies the value is a correct ZeroConf zone
112         this.zeroConfZone = zeroConfZone;
113     }
114     public synchronized void close() {
115         super.close();
116         try {
117             JmDNS jmDNS = Zeroconf4log4j.getInstance();
118             ServiceInfo info = buildServiceInfo();
119             logWithlog4j12Compatibility(Level.INFO,"Deregistering this SocketHubAppender (" + info + ")");
120             jmDNS.unregisterService(info);
121         } catch (Exception e) {
122             logWithlog4j12Compatibility(Level.ERROR,"Failed to instantiate JmDNS to broadcast via ZeroConf, will now operate in simple SocketHubAppender mode");
123         }
124     }
125     
126     
127 }