You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wink.apache.org by ro...@apache.org on 2009/11/09 20:30:45 UTC

svn commit: r834183 - in /incubator/wink/trunk: wink-common/src/main/java/org/apache/wink/common/internal/application/ wink-common/src/main/java/org/apache/wink/common/internal/utils/ wink-server/src/main/java/org/apache/wink/server/internal/servlet/

Author: rott
Date: Mon Nov  9 19:30:44 2009
New Revision: 834183

URL: http://svn.apache.org/viewvc?rev=834183&view=rev
Log:
WINK-227: use thread context classloader over system classloader in J2EE environments

Added:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/ClassUtils.java
Modified:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationFileLoader.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/FileLoader.java
    incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationFileLoader.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationFileLoader.java?rev=834183&r1=834182&r2=834183&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationFileLoader.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/application/ApplicationFileLoader.java Mon Nov  9 19:30:44 2009
@@ -36,6 +36,7 @@
 import org.apache.wink.common.internal.i18n.Messages;
 import org.apache.wink.common.internal.registry.metadata.ProviderMetadataCollector;
 import org.apache.wink.common.internal.registry.metadata.ResourceMetadataCollector;
+import org.apache.wink.common.internal.utils.ClassUtils;
 import org.apache.wink.common.internal.utils.FileLoader;
 
 /**
@@ -119,7 +120,8 @@
 
                 Class<?> cls = null;
                 try {
-                    cls = Class.forName(line);
+                    // use ClassUtils.loadClass instead of Class.forName so we have classloader visibility into the Web module in J2EE environments
+                    cls = ClassUtils.loadClass(line);
                     if (ResourceMetadataCollector.isStaticResource(cls) || ProviderMetadataCollector
                         .isProvider(cls)) {
                         logger.debug(Messages.getMessage("loadingClassToApplication"), line);

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/ClassUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/ClassUtils.java?rev=834183&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/ClassUtils.java (added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/ClassUtils.java Mon Nov  9 19:30:44 2009
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.apache.wink.common.internal.utils;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClassUtils {
+    
+    private static final Logger logger = LoggerFactory.getLogger(ClassUtils.class);
+
+    // Class.forName does not support primitives, so we have to account for that
+    private static HashMap<String, Class<?>> loadClassMap = new HashMap<String, Class<?>>();
+    static {
+        loadClassMap.put("byte", byte.class);
+        loadClassMap.put("int", int.class);
+        loadClassMap.put("short", short.class);
+        loadClassMap.put("long", long.class);
+        loadClassMap.put("float", float.class);
+        loadClassMap.put("double", double.class);
+        loadClassMap.put("boolean", boolean.class);
+        loadClassMap.put("char", char.class);
+        loadClassMap.put("void", void.class);
+    }
+    
+    /**
+     * Use of ClassUtils.loadClass may be necessary in J2EE environments to load classes dynamically
+     * due to Classloader hierarchies configured by the specific J2EE runtime.  In such environments,
+     * the thread context class loader is prioritized over the system classloader.  For example, when
+     * loading a JAX-RS Application subclass, and WINK is running as a shared library, WINK runtime may
+     * not have classloader visibility into the J2EE application.  Prioritizing the thread context
+     * classloader restores visibility.
+     *
+     * @param _className Class name
+     * @return java class
+     * @throws ClassNotFoundException if the class is not found
+     */
+    public static Class loadClass(final String _className)
+            throws ClassNotFoundException {
+
+        final String className = _className;
+        Object ret = null;
+        try { 
+            // use doPrivileged to handle java2security
+            ret = AccessController.doPrivileged(
+                    new PrivilegedAction<Object>() {
+                        public Object run() {
+
+                            try {
+                                // try context class loader first
+                                logger.debug("Loading class {} using thread context classloader.", className);
+                                return Class.forName(className,
+                                        true,
+                                        Thread.currentThread().getContextClassLoader());
+                            } catch (ClassNotFoundException cnfe) {
+                                try {
+                                    // fallback to current classloader
+                                    logger.debug("Loading class {} using current classloader.", className);
+                                    return Class.forName(className,
+                                                         true,
+                                                         ClassUtils.class.getClassLoader());
+                                } catch (ClassNotFoundException cnfe2) {
+                                    // fallback to system classloader
+                                    logger.debug("Loading class {} using system classloader.", className);
+                                    try {
+                                        return Class.forName(className);
+                                    } catch (ClassNotFoundException cnfe3) {
+                                        return cnfe3;
+                                    }
+                                }
+                            } 
+                        }
+                    });
+        }
+        catch (SecurityException se) {
+            // SecurityException means java2security did not allow visibility to className
+            throw new ClassNotFoundException(className);
+        }
+
+        // class was located, return it
+        if (ret instanceof Class) {
+            return (Class) ret;
+        } else if (ret instanceof ClassNotFoundException) {
+            // Class.forName does not support primitives, so do a last check:
+            Class cls = (Class) loadClassMap.get(className);
+            if (cls != null) {
+                logger.debug("Returning class {}", className);
+                return cls;
+            }
+            throw (ClassNotFoundException) ret;
+        }
+        throw new ClassNotFoundException(className);
+
+    }
+    
+}

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/FileLoader.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/FileLoader.java?rev=834183&r1=834182&r2=834183&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/FileLoader.java (original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/utils/FileLoader.java Mon Nov  9 19:30:44 2009
@@ -117,6 +117,11 @@
      * @throws IOException
      */
     public static Enumeration<URL> loadFileUsingClassLoaders(String filename) throws IOException {
+        
+        /*
+         * TODO: perhaps desirable to move this code to org.apache.wink.common.internal.utils.ClassUtils?
+         */
+        
         logger.debug("Searching for {} using thread context classloader.", filename);
         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         Enumeration<URL> resources = loadFileUsingClassLoader(classLoader, filename);

Modified: incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java?rev=834183&r1=834182&r2=834183&view=diff
==============================================================================
--- incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java (original)
+++ incubator/wink/trunk/wink-server/src/main/java/org/apache/wink/server/internal/servlet/RestServlet.java Mon Nov  9 19:30:44 2009
@@ -29,10 +29,10 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.ws.rs.core.Application;
 
-import org.apache.commons.lang.ClassUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.wink.common.internal.i18n.Messages;
+import org.apache.wink.common.internal.utils.ClassUtils;
 import org.apache.wink.server.internal.DeploymentConfiguration;
 import org.apache.wink.server.internal.RequestProcessor;
 import org.apache.wink.server.internal.application.ServletWinkApplication;
@@ -146,8 +146,8 @@
             logger.info(Messages.getMessage("restServletUseDeploymentConfigurationParam"),
                         initParameter,
                         DEPLYMENT_CONF_PARAM);
-            // use ClassUtils.getClass instead of Class.forName so we have classloader visibility into the Web module in J2EE environments
-            Class<?> confClass = ClassUtils.getClass(initParameter);
+            // use ClassUtils.loadClass instead of Class.forName so we have classloader visibility into the Web module in J2EE environments
+            Class<?> confClass = ClassUtils.loadClass(initParameter);
             return (DeploymentConfiguration)confClass.newInstance();
         }
         return new DeploymentConfiguration();
@@ -162,8 +162,8 @@
             logger.info(Messages.getMessage("restServletJAXRSApplicationInitParam"),
                         initParameter,
                         APPLICATION_INIT_PARAM);
-            // use ClassUtils.getClass instead of Class.forName so we have classloader visibility into the Web module in J2EE environments
-            appClass = (Class<Application>)ClassUtils.getClass(initParameter);
+            // use ClassUtils.loadClass instead of Class.forName so we have classloader visibility into the Web module in J2EE environments
+            appClass = (Class<? extends Application>)ClassUtils.loadClass(initParameter);
             return appClass.newInstance();
         }
         String appLocationParameter = getInitParameter(APP_LOCATION_PARAM);