You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by pa...@apache.org on 2009/10/20 23:28:10 UTC
svn commit: r827806 - in
/felix/trunk/framework/src/main/java/org/apache/felix/framework:
ExtensionManager.java ModuleImpl.java URLHandlers.java
URLHandlersStreamHandlerProxy.java util/SecureAction.java
Author: pauls
Date: Tue Oct 20 21:28:10 2009
New Revision: 827806
URL: http://svn.apache.org/viewvc?rev=827806&view=rev
Log:
Fix various error during start-up on gnu/classpath based VMs (jamvm, kaffe, cacao) and mika (FELIX-1782). Mainly, catch throwable instead of exceptions when we look for dalvik specific classes and add a couple of workarounds to URLHandlers.
Modified:
felix/trunk/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java?rev=827806&r1=827805&r2=827806&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java Tue Oct 20 21:28:10 2009
@@ -88,9 +88,19 @@
static
{
+ // pre-init the url sub-system as otherwise we don't work on gnu/classpath
+ ExtensionManager extensionManager = new ExtensionManager();
+ try
+ {
+ (new URL("http://felix.extensions:9/")).openConnection();
+ }
+ catch (Throwable t)
+ {
+ // This doesn't matter much - we only need the above to init the url subsystem
+ }
+
// We use the secure action of Felix to add a new instance to the parent
// classloader.
- ExtensionManager extensionManager = new ExtensionManager();
try
{
Felix.m_secureAction.addURLToURLClassLoader(Felix.m_secureAction.createURL(
@@ -98,7 +108,7 @@
"http://felix.extensions:9/", extensionManager),
Felix.class.getClassLoader());
}
- catch (Exception ex)
+ catch (Throwable ex)
{
// extension bundles will not be supported.
extensionManager = null;
@@ -375,7 +385,6 @@
}
catch (Throwable ex)
{
- ex.printStackTrace();
m_logger.log(Logger.LOG_WARNING,
"Unable to start Felix Extension Activator", ex);
}
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java?rev=827806&r1=827805&r2=827806&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/ModuleImpl.java Tue Oct 20 21:28:10 2009
@@ -112,7 +112,7 @@
m_secureAction.setAccesssible(ctor);
cl = (ClassLoader) m_secureAction.invoke(ctor, new Object[] { null });
}
- catch (Exception ex)
+ catch (Throwable ex)
{
// On Android we get an exception if we set the parent class loader
// to null, so we will work around that case by setting the parent
@@ -1602,7 +1602,7 @@
dexFileClassLoadClass = dexFileClass.getMethod("loadClass",
new Class[] { String.class, ClassLoader.class });
}
- catch (Exception ex)
+ catch (Throwable ex)
{
dexFileClassConstructor = null;
dexFileClassLoadDex = null;
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java?rev=827806&r1=827805&r2=827806&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlers.java Tue Oct 20 21:28:10 2009
@@ -125,7 +125,6 @@
}
catch (Throwable ex)
{
- ex.printStackTrace();
// Ignore, this is a best effort (maybe log it or something).
}
}
@@ -150,7 +149,6 @@
}
catch (Throwable ex)
{
- ex.printStackTrace();
// Ignore, this is a best effort (maybe log it or something)
}
m_sm = new SecurityManagerEx();
@@ -161,6 +159,15 @@
URL.setURLStreamHandlerFactory(this);
m_streamHandlerFactory = this;
m_rootURLHandlers = this;
+ // try to flush the cache (gnu/classpath doesn't do it itself)
+ try
+ {
+ m_secureAction.flush(URL.class, URL.class);
+ }
+ catch (Throwable t)
+ {
+ // Not much we can do
+ }
}
catch (Error err)
{
@@ -208,6 +215,15 @@
{
URLConnection.setContentHandlerFactory(this);
m_contentHandlerFactory = this;
+ // try to flush the cache (gnu/classpath doesn't do it itself)
+ try
+ {
+ m_secureAction.flush(URLConnection.class, URLConnection.class);
+ }
+ catch (Throwable t)
+ {
+ // Not much we can do
+ }
}
catch (Error err)
{
@@ -341,7 +357,7 @@
(URLStreamHandler) handler.newInstance());
}
}
- catch (Exception ex)
+ catch (Throwable ex)
{
// This could be a class not found exception or an
// instantiation exception, not much we can do in either
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java?rev=827806&r1=827805&r2=827806&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/URLHandlersStreamHandlerProxy.java Tue Oct 20 21:28:10 2009
@@ -28,8 +28,6 @@
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
-import java.util.Collections;
-import java.util.Arrays;
import org.apache.felix.framework.util.SecureAction;
import org.osgi.service.url.URLStreamHandlerService;
@@ -360,6 +358,10 @@
}
}
+ // We use this thread local to detect whether we have a reentrant entry to the parseURL
+ // method. This can happen do to some difference between gnu/classpath and sun jvms
+ // For more see inside the method.
+ private static final ThreadLocal m_loopCheck = new ThreadLocal();
protected void parseURL(URL url, String spec, int start, int limit)
{
Object svc = getStreamHandlerService();
@@ -377,17 +379,50 @@
try
{
URL test = null;
+ // In order to cater for built-in urls being over-writable we need to use a
+ // somewhat strange hack. We use a hidden feature inside the jdk which passes
+ // the handler of the url given as a context to a new URL to that URL as its
+ // handler. This way, we can create a new URL which will use the given built-in
+ // handler to parse the url. Subsequently, we can use the information from that
+ // URL to call set with the correct values.
if (m_builtInURL != null)
{
- test = new URL(new URL(m_builtInURL, url.toExternalForm()), spec);
+ // However, if we are on gnu/classpath we have to pass the handler directly
+ // because the hidden feature is not there. Funnily, the workaround to pass
+ // pass the handler directly doesn't work on sun as their handler detects
+ // that it is not the same as the one inside the url and throws an exception
+ // Luckily it doesn't do that on gnu/classpath. We detect that we need to
+ // pass the handler directly by using the m_loopCheck thread local to detect
+ // that we parseURL has been called inside a call to parseURL.
+ if (m_loopCheck.get() != null)
+ {
+ test = new URL(new URL(m_builtInURL, url.toExternalForm()), spec, (URLStreamHandler) svc);
+ }
+ else
+ {
+ // Set-up the thread local as we don't expect to be called again until we are
+ // done. Otherwise, we are on gnu/classpath
+ m_loopCheck.set(Thread.currentThread());
+ try
+ {
+ test = new URL(new URL(m_builtInURL, url.toExternalForm()), spec);
+ }
+ finally
+ {
+ m_loopCheck.set(null);
+ }
+ }
}
else
{
+ // We don't have a url with a built-in handler for this but still want to create
+ // the url with the buil-in handler as we could find one now. This might not
+ // work for all handlers on sun but it is better then doing nothing.
test = m_action.createURL(url, spec, (URLStreamHandler) svc);
}
-
+
super.setURL(url, test.getProtocol(), test.getHost(), test.getPort(),test.getAuthority(),
- test.getUserInfo(), test.getPath(), test.getQuery(), test.getRef());
+ test.getUserInfo(), test.getPath(), test.getQuery(), test.getRef());
}
catch (Exception ex)
{
@@ -452,8 +487,17 @@
{
try
{
- return (String) TO_EXTERNAL_FORM.invoke(
+ String result = (String) TO_EXTERNAL_FORM.invoke(
svc, new Object[]{url});
+
+ // mika does return an invalid format if we have a url with the
+ // protocol only (<proto>://null) - we catch this case now
+ if ((result != null) && (result.equals(url.getProtocol() + "://null")))
+ {
+ result = url.getProtocol() + ":";
+ }
+
+ return result;
}
catch (InvocationTargetException ex)
{
@@ -484,7 +528,7 @@
answer.append(url.getProtocol());
answer.append(':');
String authority = url.getAuthority();
- if (authority != null && authority.length() > 0)
+ if ((authority != null) && (authority.length() > 0))
{
answer.append("//"); //$NON-NLS-1$
answer.append(url.getAuthority());
@@ -563,6 +607,13 @@
}
catch (Throwable t)
{
+ // In case that we are inside tomcat - the problem is that the webapp classloader
+ // creates a new url to load a class. This gets us to this method. Now, if we
+ // trigger a classload while executing tomcat is creating a new url and we end-up with
+ // a loop which is cut short after two iterations (because of a circularclassload).
+ // We catch this exception (and all others) and just return the built-in handler
+ // (if we have any) as this way we at least eventually get started (this just means
+ // that we don't use the potentially provided built-in handler overwrite).
return m_builtIn;
}
}
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java
URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java?rev=827806&r1=827805&r2=827806&view=diff
==============================================================================
--- felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java (original)
+++ felix/trunk/framework/src/main/java/org/apache/felix/framework/util/SecureAction.java Tue Oct 20 21:28:10 2009
@@ -22,6 +22,7 @@
import java.lang.reflect.*;
import java.net.*;
import java.security.*;
+import java.util.HashMap;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
@@ -996,6 +997,60 @@
return null;
}
+ public void flush(Class targetClazz, Object lock) throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.FLUSH_FIELD_ACTION, targetClazz, lock);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ _flush(targetClazz, lock);
+ }
+ }
+
+ private static void _flush(Class targetClazz, Object lock) throws Exception
+ {
+ synchronized (lock)
+ {
+ Field[] fields = targetClazz.getDeclaredFields();
+ // reset cache
+ for (int i = 0; i < fields.length; i++)
+ {
+ if (Modifier.isStatic(fields[i].getModifiers()) &&
+ ((fields[i].getType() == Hashtable.class) || (fields[i].getType() == HashMap.class)))
+ {
+ fields[i].setAccessible(true);
+ if (fields[i].getType() == Hashtable.class)
+ {
+ Hashtable cache = (Hashtable) fields[i].get(null);
+ if (cache != null)
+ {
+ cache.clear();
+ }
+ }
+ else
+ {
+ HashMap cache = (HashMap) fields[i].get(null);
+ if (cache != null)
+ {
+ cache.clear();
+ }
+ }
+ }
+ }
+ }
+ }
+
private static class Actions implements PrivilegedExceptionAction
{
public static final int INITIALIZE_CONTEXT = 0;
@@ -1038,6 +1093,7 @@
public static final int STOP_ACTIVATOR_ACTION = 37;
public static final int SWAP_FIELD_ACTION = 38;
public static final int SYSTEM_EXIT_ACTION = 39;
+ public static final int FLUSH_FIELD_ACTION = 40;
private int m_action = -1;
private Object m_arg1 = null;
@@ -1280,6 +1336,10 @@
{
((AccessibleObject) arg1).setAccessible(true);
}
+ else if (action == FLUSH_FIELD_ACTION)
+ {
+ _flush(((Class) arg1), arg2);
+ }
return null;
}