[jboss-svn-commits] JBoss Common SVN: r3266 - jboss-logmanager/trunk/src/main/java/org/jboss/logmanager.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Tue Jun 16 22:14:42 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-06-16 22:14:42 -0400 (Tue, 16 Jun 2009)
New Revision: 3266

Added:
   jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassLoaderLogContextSelector.java
Log:
Provide support for locating the log context based on the caller classloader

Added: jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassLoaderLogContextSelector.java
===================================================================
--- jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassLoaderLogContextSelector.java	                        (rev 0)
+++ jboss-logmanager/trunk/src/main/java/org/jboss/logmanager/ClassLoaderLogContextSelector.java	2009-06-17 02:14:42 UTC (rev 3266)
@@ -0,0 +1,121 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.logmanager;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.Permission;
+import java.util.concurrent.ConcurrentMap;
+import java.util.EnumSet;
+import static org.jboss.logmanager.ConcurrentReferenceHashMap.Option.IDENTITY_COMPARISONS;
+import static org.jboss.logmanager.ConcurrentReferenceHashMap.ReferenceType.WEAK;
+import static org.jboss.logmanager.ConcurrentReferenceHashMap.DEFAULT_CONCURRENCY_LEVEL;
+import static org.jboss.logmanager.ConcurrentReferenceHashMap.DEFAULT_LOAD_FACTOR;
+import static org.jboss.logmanager.ConcurrentReferenceHashMap.DEFAULT_INITIAL_CAPACITY;
+
+/**
+ * A log context selector which chooses a log context based on the caller's classloader.  This selector maintains
+ * weak references to the classloader as well as the log context; if either is collected, the association is
+ * broken.  Therefore, strong references must be kept external to this class.
+ */
+public final class ClassLoaderLogContextSelector implements LogContextSelector {
+
+    private static final Permission REGISTER_LOG_CONTEXT_PERMISSION = new RuntimePermission("registerLogContext", null);
+    private static final Permission UNREGISTER_LOG_CONTEXT_PERMISSION = new RuntimePermission("unregisterLogContext", null);
+
+    /**
+     * Construct a new instance.  If no matching log context is found, the provided default selector is consulted.
+     *
+     * @param defaultSelector the selector to consult if no matching log context is found
+     */
+    public ClassLoaderLogContextSelector(final LogContextSelector defaultSelector) {
+        this.defaultSelector = defaultSelector;
+    }
+
+    private static final class Gateway extends SecurityManager {
+        protected Class[] getClassContext() {
+            return super.getClassContext();
+        }
+    }
+
+    private static final Gateway GATEWAY;
+
+    static {
+        GATEWAY = AccessController.doPrivileged(new PrivilegedAction<Gateway>() {
+            public Gateway run() {
+                return new Gateway();
+            }
+        });
+    }
+
+    private final LogContextSelector defaultSelector;
+
+    private final ConcurrentMap<ClassLoader, LogContext> contextMap =
+            new ConcurrentReferenceHashMap<ClassLoader, LogContext>(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, WEAK, WEAK, EnumSet.of(IDENTITY_COMPARISONS));
+
+    /**
+     * {@inheritDoc}  This instance will consult the call stack to see if any calling classloader is associated
+     * with any log context.
+     */
+    public LogContext getLogContext() {
+        for (Class caller : GATEWAY.getClassContext()) {
+            final LogContext context = contextMap.get(caller.getClassLoader());
+            if (context != null) {
+                return context;
+            }
+        }
+        return defaultSelector.getLogContext();
+    }
+
+    /**
+     * Register a class loader with a log context.  This method requires the {@code registerLogContext} {@link RuntimePermission}.
+     *
+     * @param classLoader the classloader
+     * @param logContext the log context
+     * @throws IllegalArgumentException if the classloader is already associated with a log context
+     */
+    public void registerLogContext(ClassLoader classLoader, LogContext logContext) throws IllegalArgumentException {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(REGISTER_LOG_CONTEXT_PERMISSION);
+        }
+        if (contextMap.putIfAbsent(classLoader, logContext) != null) {
+            throw new IllegalArgumentException("ClassLoader instance is already registered to a log context (" + classLoader + ")");
+        }
+    }
+
+    /**
+     * Unregister a class loader/log context association.  This method requires the {@code unregisterLogContext} {@link RuntimePermission}.
+     *
+     * @param classLoader the classloader
+     * @param logContext the log context
+     * @return {@code true} if the association exists and was removed, {@code false} otherwise
+     */
+    public boolean unregisterLogContext(ClassLoader classLoader, LogContext logContext) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(UNREGISTER_LOG_CONTEXT_PERMISSION);
+        }
+        return contextMap.remove(classLoader, logContext);
+    }
+}




More information about the jboss-svn-commits mailing list