diff options
6 files changed, 157 insertions, 18 deletions
diff --git a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs index 15d2ec557..be242e5a9 100644 --- a/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs +++ b/bundles/org.eclipse.osgi/.settings/org.eclipse.jdt.core.prefs @@ -9,10 +9,14 @@ org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.7 @@ -38,7 +42,7 @@ org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled org.eclipse.jdt.core.compiler.problem.fieldHiding=warning org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning -org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning @@ -71,12 +75,14 @@ org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error org.eclipse.jdt.core.compiler.problem.nullReference=warning org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java index 90c98c0ec..c267a95e7 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/EquinoxFactoryManager.java @@ -92,7 +92,7 @@ public class EquinoxFactoryManager { Object lock; try { Field streamHandlerLockField = URL.class.getDeclaredField("streamHandlerLock"); //$NON-NLS-1$ - streamHandlerLockField.setAccessible(true); + MultiplexingFactory.setAccessible(streamHandlerLockField); lock = streamHandlerLockField.get(null); } catch (NoSuchFieldException noField) { // could not find the lock, lets sync on the class object @@ -229,7 +229,7 @@ public class EquinoxFactoryManager { for (int i = 0; i < fields.length; i++) { boolean isStatic = Modifier.isStatic(fields[i].getModifiers()); if (instance != isStatic && fields[i].getType().equals(type)) { - fields[i].setAccessible(true); + MultiplexingFactory.setAccessible(fields[i]); return fields[i]; } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java index edccf78a3..c78748c44 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingFactory.java @@ -8,12 +8,13 @@ *******************************************************************************/ package org.eclipse.osgi.internal.url; -import java.lang.reflect.Method; -import java.util.LinkedList; -import java.util.List; +import java.lang.reflect.*; +import java.net.URL; +import java.util.*; import org.eclipse.osgi.framework.log.FrameworkLogEntry; import org.eclipse.osgi.internal.framework.EquinoxBundle; import org.eclipse.osgi.internal.framework.EquinoxContainer; +import org.eclipse.osgi.storage.StorageUtil; import org.osgi.framework.*; /* @@ -21,6 +22,47 @@ import org.osgi.framework.*; * handle environments running multiple osgi frameworks with the same VM. */ public abstract class MultiplexingFactory { + /** + * As a short-term (hopefully) solution we use a special class which is defined + * using the Unsafe class from the VM. This class is an implementation of + * Collection<AccessibleObject> simply to provide a method add(AccessibleObject) + * which turns around and calls AccessibleObject.setAccessible(true). + * <p> + * The reason this is needed is to hack into the VM to get deep reflective access to + * the java.net package for the various hacks we have to do to multiplex the + * URL and Content handlers. Note that on Java 9 deep reflection is not possible + * by default on the java.net package. + * <p> + * The setAccessible class will be defined in the java.base module which grants + * it the ability to call setAccessible(true) on other types from the java.base module + */ + static final Collection<AccessibleObject> setAccessible; + static { + Collection<AccessibleObject> result = null; + 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 SetAccessible bytes stored in a resource to avoid real loading of it (see SetAccessible.java.src for source). + String tResource = "SetAccessible.bytes"; //$NON-NLS-1$ + + byte[] bytes = StorageUtil.getBytes(MultiplexingFactory.class.getResource(tResource).openStream(), -1, 4000); + @SuppressWarnings("unchecked") + Class<Collection<AccessibleObject>> clazz = (Class<Collection<AccessibleObject>>) defineAnonymousClass.invoke(unsafe, URL.class, bytes, (Object[]) null); + result = clazz.getConstructor().newInstance(); + } catch (Throwable t) { + t.printStackTrace(); + // ingore as if there is no Unsafe + } + setAccessible = result; + } protected EquinoxContainer container; protected BundleContext context; private List<Object> factories; // list of multiplexed factories @@ -167,4 +209,12 @@ public abstract class MultiplexingFactory { updated.remove(factory); factories = updated.isEmpty() ? null : updated; } + + static void setAccessible(AccessibleObject o) { + if (setAccessible != null) { + setAccessible.add(o); + } else { + o.setAccessible(true); + } + } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java index c82ab15ed..19f25b771 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/MultiplexingURLStreamHandler.java @@ -38,37 +38,37 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler { return; try { openConnectionMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", new Class[] {URL.class}); //$NON-NLS-1$ - openConnectionMethod.setAccessible(true); + MultiplexingFactory.setAccessible(openConnectionMethod); openConnectionProxyMethod = URLStreamHandler.class.getDeclaredMethod("openConnection", new Class[] {URL.class, Proxy.class}); //$NON-NLS-1$ - openConnectionProxyMethod.setAccessible(true); + MultiplexingFactory.setAccessible(openConnectionProxyMethod); equalsMethod = URLStreamHandler.class.getDeclaredMethod("equals", new Class[] {URL.class, URL.class}); //$NON-NLS-1$ - equalsMethod.setAccessible(true); + MultiplexingFactory.setAccessible(equalsMethod); getDefaultPortMethod = URLStreamHandler.class.getDeclaredMethod("getDefaultPort", (Class[]) null); //$NON-NLS-1$ - getDefaultPortMethod.setAccessible(true); + MultiplexingFactory.setAccessible(getDefaultPortMethod); getHostAddressMethod = URLStreamHandler.class.getDeclaredMethod("getHostAddress", new Class[] {URL.class}); //$NON-NLS-1$ - getHostAddressMethod.setAccessible(true); + MultiplexingFactory.setAccessible(getHostAddressMethod); hashCodeMethod = URLStreamHandler.class.getDeclaredMethod("hashCode", new Class[] {URL.class}); //$NON-NLS-1$ - hashCodeMethod.setAccessible(true); + MultiplexingFactory.setAccessible(hashCodeMethod); hostsEqualMethod = URLStreamHandler.class.getDeclaredMethod("hostsEqual", new Class[] {URL.class, URL.class}); //$NON-NLS-1$ - hostsEqualMethod.setAccessible(true); + MultiplexingFactory.setAccessible(hostsEqualMethod); parseURLMethod = URLStreamHandler.class.getDeclaredMethod("parseURL", new Class[] {URL.class, String.class, Integer.TYPE, Integer.TYPE}); //$NON-NLS-1$ - parseURLMethod.setAccessible(true); + MultiplexingFactory.setAccessible(parseURLMethod); sameFileMethod = URLStreamHandler.class.getDeclaredMethod("sameFile", new Class[] {URL.class, URL.class}); //$NON-NLS-1$ - sameFileMethod.setAccessible(true); + MultiplexingFactory.setAccessible(sameFileMethod); setURLMethod = URLStreamHandler.class.getDeclaredMethod("setURL", new Class[] {URL.class, String.class, String.class, Integer.TYPE, String.class, String.class, String.class, String.class, String.class}); //$NON-NLS-1$ - setURLMethod.setAccessible(true); + MultiplexingFactory.setAccessible(setURLMethod); toExternalFormMethod = URLStreamHandler.class.getDeclaredMethod("toExternalForm", new Class[] {URL.class}); //$NON-NLS-1$ - toExternalFormMethod.setAccessible(true); + MultiplexingFactory.setAccessible(toExternalFormMethod); try { handlerField = URL.class.getDeclaredField("handler"); //$NON-NLS-1$ @@ -77,7 +77,7 @@ public class MultiplexingURLStreamHandler extends URLStreamHandler { if (handlerField == null) throw e; } - handlerField.setAccessible(true); + MultiplexingFactory.setAccessible(handlerField); } catch (Exception e) { factory.container.getLogServices().log(MultiplexingURLStreamHandler.class.getName(), FrameworkLogEntry.ERROR, "initializeMethods", e); //$NON-NLS-1$ throw new RuntimeException(e.getMessage(), e); diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.bytes b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.bytes Binary files differnew file mode 100644 index 000000000..5752a1bee --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.bytes diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.java.src b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.java.src new file mode 100644 index 000000000..0dbd62421 --- /dev/null +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/url/SetAccessible.java.src @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2016 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + *******************************************************************************/ +package java.net; + +import java.lang.reflect.AccessibleObject; +import java.util.Collection; +import java.util.Iterator; + +public class SetAccessible implements Collection<AccessibleObject> { + // playing tricks to get around reflecting in java.net package on java 9 + @Override + public boolean add(AccessibleObject e) { + e.setAccessible(true); + return true; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public boolean contains(Object o) { + return false; + } + + @Override + public Iterator<AccessibleObject> iterator() { + return null; + } + + @Override + public Object[] toArray() { + return null; + } + + @Override + public <T> T[] toArray(T[] a) { + return null; + } + + @Override + public boolean remove(Object o) { + return false; + } + + @Override + public boolean containsAll(Collection<?> c) { + return false; + } + + @Override + public boolean addAll(Collection<? extends AccessibleObject> c) { + return false; + } + + @Override + public boolean removeAll(Collection<?> c) { + return false; + } + + @Override + public boolean retainAll(Collection<?> c) { + return false; + } + + @Override + public void clear() { + // nothing + } + +} |