View Javadoc
1   /*
2    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
3    * The software in this package is published under the terms of the CPAL v1.0
4    * license, a copy of which has been included with this distribution in the
5    * LICENSE.txt file.
6    */
7   package org.mule.module.logging;
8   
9   import java.lang.ref.PhantomReference;
10  import java.lang.ref.ReferenceQueue;
11  import java.util.HashMap;
12  import java.util.Map;
13  import java.util.concurrent.ConcurrentHashMap;
14  import java.util.concurrent.ConcurrentMap;
15  
16  import org.apache.commons.logging.Log;
17  import org.apache.commons.logging.LogConfigurationException;
18  import org.apache.commons.logging.impl.MuleLocationAwareLog;
19  import org.apache.commons.logging.impl.MuleLog;
20  import org.apache.commons.logging.impl.SLF4JLogFactory;
21  import org.slf4j.Logger;
22  import org.slf4j.LoggerFactory;
23  import org.slf4j.spi.LocationAwareLogger;
24  
25  public class MuleLogFactory extends SLF4JLogFactory
26  {
27  
28      public static final String LOG_HANDLER_THREAD_NAME = "Mule.log.clogging.ref.handler";
29  
30      protected ConcurrentHashMap<Integer, ConcurrentMap<String, Log>> repository = new ConcurrentHashMap<Integer, ConcurrentMap<String, Log>>();
31  
32      protected static final Integer NO_CCL_CLASSLOADER = 0;
33  
34      protected ReferenceQueue<ClassLoader> referenceQueue = new ReferenceQueue<ClassLoader>();
35      // map ref back to the classloader hash for cleanup of repository map, as both Weak- and SoftReference's get() return null by this time
36      protected Map<PhantomReference<ClassLoader>, Integer> refs = new HashMap<PhantomReference<ClassLoader>, Integer>();
37  
38      public MuleLogFactory()
39      {
40          if (MuleUtils.isStandalone())
41          {
42              createLoggerReferenceHandler();
43          }
44      }
45  
46      protected void createLoggerReferenceHandler()
47      {
48          new LoggerReferenceHandler(LOG_HANDLER_THREAD_NAME, referenceQueue, refs, repository);
49      }
50  
51      public Log getInstance(String name) throws LogConfigurationException
52      {
53          final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
54          ConcurrentMap<String, Log> loggerMap = repository.get(ccl == null ? NO_CCL_CLASSLOADER : ccl.hashCode());
55  
56          if (loggerMap == null)
57          {
58              loggerMap = new ConcurrentHashMap<String, Log>();
59  
60              final ConcurrentMap<String, Log> previous = repository.putIfAbsent(ccl == null ? NO_CCL_CLASSLOADER : ccl.hashCode(), loggerMap);
61              if (previous != null)
62              {
63                  loggerMap = previous;
64              }
65  
66              if (ccl != null)
67              {
68                  // must save a strong ref to the PhantomReference in order for it to stay alive and work
69                  refs.put(new PhantomReference<ClassLoader>(ccl, referenceQueue), ccl.hashCode());
70              }
71  
72          }
73  
74          Log instance = loggerMap.get(name);
75  
76          if (instance == null)
77          {
78              Logger logger = LoggerFactory.getLogger(name);
79              if (logger instanceof LocationAwareLogger)
80              {
81                  instance = new MuleLocationAwareLog((LocationAwareLogger) logger);
82              }
83              else
84              {
85                  instance = new MuleLog(logger);
86              }
87              final Log previous = loggerMap.putIfAbsent(name, instance);
88              if (previous != null)
89              {
90                  // someone got there before us
91                  instance = previous;
92              }
93          }
94  
95          return instance;
96      }
97  }