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);