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 2020/01/28 00:46:47 UTC
svn commit: r1873234 - in /felix/sandbox/pauls/connect: ./
src/main/java/org/apache/felix/framework/ext/
src/main/java/org/apache/felix/framework/util/
src/main/resources/org/apache/felix/framework/util/
Author: pauls
Date: Tue Jan 28 00:46:47 2020
New Revision: 1873234
URL: http://svn.apache.org/viewvc?rev=1873234&view=rev
Log:
Use unsave to work around reflection restrictions.
Added:
felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/
felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.bytes (with props)
felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.src
Modified:
felix/sandbox/pauls/connect/pom.xml
felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/ext/ClassPathExtenderFactory.java
felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/util/SecureAction.java
Modified: felix/sandbox/pauls/connect/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/pauls/connect/pom.xml?rev=1873234&r1=1873233&r2=1873234&view=diff
==============================================================================
--- felix/sandbox/pauls/connect/pom.xml (original)
+++ felix/sandbox/pauls/connect/pom.xml Tue Jan 28 00:46:47 2020
@@ -118,6 +118,16 @@
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
+ <excludes>
+ <exclude>**/*.bytes</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>**/*.bytes</include>
+ </includes>
</resource>
</resources>
</build>
Modified: felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/ext/ClassPathExtenderFactory.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/ext/ClassPathExtenderFactory.java?rev=1873234&r1=1873233&r2=1873234&view=diff
==============================================================================
--- felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/ext/ClassPathExtenderFactory.java (original)
+++ felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/ext/ClassPathExtenderFactory.java Tue Jan 28 00:46:47 2020
@@ -23,6 +23,8 @@ import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
+import org.apache.felix.framework.util.SecureAction;
+
public interface ClassPathExtenderFactory
{
interface ClassPathExtender
@@ -50,7 +52,7 @@ public interface ClassPathExtenderFactor
try
{
append = app.getClass().getDeclaredMethod("appendToClassPathForInstrumentation", String.class);
- append.setAccessible(true);
+ new SecureAction().setAccesssible(append);
break;
}
catch (Exception e)
@@ -74,7 +76,7 @@ public interface ClassPathExtenderFactor
try
{
addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
- addURL.setAccessible(true);
+ new SecureAction().setAccesssible(addURL);
}
catch (Exception e)
{
Modified: felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/util/SecureAction.java
URL: http://svn.apache.org/viewvc/felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/util/SecureAction.java?rev=1873234&r1=1873233&r2=1873234&view=diff
==============================================================================
--- felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/util/SecureAction.java (original)
+++ felix/sandbox/pauls/connect/src/main/java/org/apache/felix/framework/util/SecureAction.java Tue Jan 28 00:46:47 2020
@@ -23,11 +23,15 @@ import java.lang.reflect.*;
import java.lang.reflect.Proxy;
import java.net.*;
import java.security.*;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
import java.util.jar.JarFile;
+import java.util.stream.Stream;
import java.util.zip.ZipFile;
import org.osgi.framework.Bundle;
@@ -56,6 +60,29 @@ import org.osgi.framework.wiring.BundleR
**/
public class SecureAction
{
+ private static final byte[] accessor;
+
+ static {
+ byte[] result;
+
+ try (ByteArrayOutputStream output = new ByteArrayOutputStream();
+ InputStream input = SecureAction.class.getResourceAsStream("accessor.bytes"))
+ {
+
+ byte[] buffer = new byte[input.available() > 0 ? input.available() : 1024];
+ for (int i = input.read(buffer); i != -1; i = input.read(buffer))
+ {
+ output.write(buffer, 0, i);
+ }
+ result = output.toByteArray();
+ }
+ catch (Throwable t) {
+ t.printStackTrace();
+ result = new byte[0];
+ }
+ accessor = result;
+ }
+
private static final ThreadLocal m_actions = new ThreadLocal()
{
public Object initialValue()
@@ -762,7 +789,7 @@ public class SecureAction
Method addURL =
URLClassLoader.class.getDeclaredMethod("addURL",
new Class[] {URL.class});
- addURL.setAccessible(true);
+ getAccessor(URLClassLoader.class).accept(new AccessibleObject[]{addURL});
addURL.invoke(loader, new Object[]{extension});
}
}
@@ -851,7 +878,7 @@ public class SecureAction
}
}
- public void setAccesssible(AccessibleObject ao)
+ public void setAccesssible(Executable ao)
{
if (System.getSecurityManager() != null)
{
@@ -868,7 +895,7 @@ public class SecureAction
}
else
{
- ao.setAccessible(true);
+ getAccessor(ao.getDeclaringClass()).accept(new AccessibleObject[]{ao});
}
}
@@ -889,7 +916,8 @@ public class SecureAction
}
else
{
- method.setAccessible(true);
+ getAccessor(method.getDeclaringClass()).accept(new AccessibleObject[]{method});
+
return method.invoke(target, params);
}
}
@@ -955,8 +983,7 @@ public class SecureAction
else
{
Field field = targetClass.getDeclaredField(name);
- field.setAccessible(true);
-
+ getAccessor(targetClass).accept(new AccessibleObject[]{field});
return field.get(target);
}
}
@@ -985,9 +1012,49 @@ public class SecureAction
}
}
+ private static ConcurrentHashMap<Class, Object> m_accessorCache = new ConcurrentHashMap<>();
+
+ @SuppressWarnings("unchecked")
+ private static Consumer<AccessibleObject[]> getAccessor(Class clazz) {
+ String packageName = clazz.getPackage().getName();
+ if ("java.net".equals(packageName) || "jdk.internal.loader".equals(packageName))
+ {
+ return (Consumer<AccessibleObject[]>) m_accessorCache.computeIfAbsent(clazz, target ->
+ {
+ try
+ {
+ // Use reflection on Unsafe to avoid having to compile against it
+ Class<?> unsafeClass = Class.forName("sun.misc.Unsafe"); //$NON-NLS-1$
+ Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe"); //$NON-NLS-1$
+ // NOTE: deep reflection is allowed on sun.misc package for java 9.
+ theUnsafe.setAccessible(true);
+ Object unsafe = theUnsafe.get(null);
+ // using defineAnonymousClass here because it seems more simple to get what we need
+ Method defineAnonymousClass = unsafeClass.getMethod("defineAnonymousClass", Class.class, byte[].class, Object[].class); //$NON-NLS-1$
+ // The bytes stored in a resource to avoid real loading of it (see accessible.src for source).
+
+ Class<Consumer<AccessibleObject[]>> result =
+ (Class<Consumer<AccessibleObject[]>>)
+ defineAnonymousClass.invoke(unsafe, packageName.equals("java.net") ? clazz : URL.class, accessor , null);
+ return result.getConstructor().newInstance();
+
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ return (Consumer<AccessibleObject[]>) objects -> AccessibleObject.setAccessible(objects, true);
+ }
+ });
+ }
+ else {
+ return objects -> AccessibleObject.setAccessible(objects, true);
+ }
+ }
+
private static Object _swapStaticFieldIfNotClass(Class targetClazz,
Class targetType, Class condition, String lockName) throws Exception
{
+
Object lock = null;
if (lockName != null)
{
@@ -995,7 +1062,7 @@ public class SecureAction
{
Field lockField =
targetClazz.getDeclaredField(lockName);
- lockField.setAccessible(true);
+ getAccessor(targetClazz).accept(new AccessibleObject[]{lockField});
lock = lockField.get(null);
}
catch (NoSuchFieldException ex)
@@ -1010,14 +1077,14 @@ public class SecureAction
{
Field[] fields = targetClazz.getDeclaredFields();
+ getAccessor(targetClazz).accept(fields);
+
Object result = null;
for (int i = 0; (i < fields.length) && (result == null); i++)
{
if (Modifier.isStatic(fields[i].getModifiers()) &&
(fields[i].getType() == targetType))
{
- fields[i].setAccessible(true);
-
result = fields[i].get(null);
if (result != null)
@@ -1040,7 +1107,6 @@ public class SecureAction
if (Modifier.isStatic(fields[i].getModifiers()) &&
(fields[i].getType() == Hashtable.class))
{
- fields[i].setAccessible(true);
Hashtable cache = (Hashtable) fields[i].get(null);
if (cache != null)
{
@@ -1081,13 +1147,13 @@ public class SecureAction
synchronized (lock)
{
Field[] fields = targetClazz.getDeclaredFields();
+ getAccessor(targetClazz).accept(fields);
// 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);
@@ -1708,7 +1774,7 @@ public class SecureAction
Method addURL =
URLClassLoader.class.getDeclaredMethod("addURL",
new Class[] {URL.class});
- addURL.setAccessible(true);
+ getAccessor(URLClassLoader.class).accept(new AccessibleObject[]{addURL});
addURL.invoke(arg2, new Object[]{arg1});
return null;
case CREATE_TMPFILE_ACTION:
@@ -1740,7 +1806,7 @@ public class SecureAction
return ((Class) arg1).getDeclaredMethod((String) arg2, (Class[]) arg3);
case GET_FIELD_ACTION:
Field field = ((Class) arg1).getDeclaredField((String) arg2);
- field.setAccessible(true);
+ getAccessor((Class) arg1).accept(new AccessibleObject[]{field});
return field.get(arg3);
case GET_FILE_INPUT_ACTION:
return new FileInputStream((File) arg1);
@@ -1765,7 +1831,7 @@ public class SecureAction
case INVOKE_DIRECTMETHOD_ACTION:
return ((Method) arg1).invoke(arg2, (Object[]) arg3);
case INVOKE_METHOD_ACTION:
- ((Method) arg1).setAccessible(true);
+ getAccessor(((Method) arg1).getDeclaringClass()).accept(new AccessibleObject[]{(Method) arg1});
return ((Method) arg1).invoke(arg2, (Object[]) arg3);
case LIST_DIRECTORY_ACTION:
return ((File) arg1).listFiles();
@@ -1780,7 +1846,7 @@ public class SecureAction
case RENAME_FILE_ACTION:
return ((File) arg1).renameTo((File) arg2) ? Boolean.TRUE : Boolean.FALSE;
case SET_ACCESSIBLE_ACTION:
- ((AccessibleObject) arg1).setAccessible(true);
+ getAccessor(((Executable) arg1).getDeclaringClass()).accept(new AccessibleObject[]{(Executable) arg1});
return null;
case START_ACTIVATOR_ACTION:
((BundleActivator) arg1).start((BundleContext) arg2);
Added: felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.bytes
URL: http://svn.apache.org/viewvc/felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.bytes?rev=1873234&view=auto
==============================================================================
Binary file - no diff available.
Propchange: felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.bytes
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.src
URL: http://svn.apache.org/viewvc/felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.src?rev=1873234&view=auto
==============================================================================
--- felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.src (added)
+++ felix/sandbox/pauls/connect/src/main/resources/org/apache/felix/framework/util/accessor.src Tue Jan 28 00:46:47 2020
@@ -0,0 +1,31 @@
+/*
+ * 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 java.net;
+
+import java.lang.reflect.AccessibleObject;
+import java.util.function.Consumer;
+
+public class Accessor implements Consumer<AccessibleObject[]>
+{
+ @Override
+ public void accept(AccessibleObject[] accessibleObjectStream)
+ {
+ AccessibleObject.setAccessible(accessibleObjectStream, true);
+ }
+}