diff options
author | Thomas Watson | 2011-11-01 20:13:00 +0000 |
---|---|---|
committer | Thomas Watson | 2011-11-01 20:29:56 +0000 |
commit | 609c7b5ae81f664920ccfe09d0b8d59cab098791 (patch) | |
tree | 36b8bd1b64dbf4c5cde9e2b35d14a7d34c6957ba | |
parent | ce9ce834452337419becbdc1f895b70a34ea2c5c (diff) | |
download | rt.equinox.framework-609c7b5ae81f664920ccfe09d0b8d59cab098791.tar.gz rt.equinox.framework-609c7b5ae81f664920ccfe09d0b8d59cab098791.tar.xz rt.equinox.framework-609c7b5ae81f664920ccfe09d0b8d59cab098791.zip |
Bug 361390 - Framework should ensure weaving hooks are presented
with byte code in a class cache environment
4 files changed, 84 insertions, 54 deletions
diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java index 860bb9a1a..b9d48f3ae 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/baseadaptor/bundlefile/BundleEntry.java @@ -11,9 +11,11 @@ package org.eclipse.osgi.baseadaptor.bundlefile; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; import org.eclipse.osgi.framework.debug.Debug; +import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil; /** * A BundleEntry represents one entry of a BundleFile. @@ -89,47 +91,8 @@ public abstract class BundleEntry { public byte[] getBytes() throws IOException { InputStream in = getInputStream(); int length = (int) getSize(); - byte[] classbytes; - int bytesread = 0; - int readcount; if (Debug.DEBUG_LOADER) Debug.println(" about to read " + length + " bytes from " + getName()); //$NON-NLS-1$ //$NON-NLS-2$ - - try { - if (length > 0) { - classbytes = new byte[length]; - for (; bytesread < length; bytesread += readcount) { - readcount = in.read(classbytes, bytesread, length - bytesread); - if (readcount <= 0) /* if we didn't read anything */ - break; /* leave the loop */ - } - } else /* BundleEntry does not know its own length! */{ - length = BUF_SIZE; - classbytes = new byte[length]; - readloop: while (true) { - for (; bytesread < length; bytesread += readcount) { - readcount = in.read(classbytes, bytesread, length - bytesread); - if (readcount <= 0) /* if we didn't read anything */ - break readloop; /* leave the loop */ - } - byte[] oldbytes = classbytes; - length += BUF_SIZE; - classbytes = new byte[length]; - System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); - } - } - if (classbytes.length > bytesread) { - byte[] oldbytes = classbytes; - classbytes = new byte[bytesread]; - System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); - } - } finally { - try { - in.close(); - } catch (IOException ee) { - // nothing to do here - } - } - return classbytes; + return AdaptorUtil.getBytes(in, length, BUF_SIZE); } } diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java index 419850cb9..3ff383ca4 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/AdaptorUtil.java @@ -235,4 +235,46 @@ public class AdaptorUtil { // TODO should we do this by hand ourselves? return file.toURL(); } + + public static byte[] getBytes(InputStream in, int length, int BUF_SIZE) throws IOException { + byte[] classbytes; + int bytesread = 0; + int readcount; + try { + if (length > 0) { + classbytes = new byte[length]; + for (; bytesread < length; bytesread += readcount) { + readcount = in.read(classbytes, bytesread, length - bytesread); + if (readcount <= 0) /* if we didn't read anything */ + break; /* leave the loop */ + } + } else /* does not know its own length! */{ + length = BUF_SIZE; + classbytes = new byte[length]; + readloop: while (true) { + for (; bytesread < length; bytesread += readcount) { + readcount = in.read(classbytes, bytesread, length - bytesread); + if (readcount <= 0) /* if we didn't read anything */ + break readloop; /* leave the loop */ + } + byte[] oldbytes = classbytes; + length += BUF_SIZE; + classbytes = new byte[length]; + System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); + } + } + if (classbytes.length > bytesread) { + byte[] oldbytes = classbytes; + classbytes = new byte[bytesread]; + System.arraycopy(oldbytes, 0, classbytes, 0, bytesread); + } + } finally { + try { + in.close(); + } catch (IOException ee) { + // nothing to do here + } + } + return classbytes; + } } diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java index 43aec13e2..9f43d0ec4 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java @@ -56,7 +56,7 @@ public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHo return null; } // create a woven class object and add it to the thread local stack - WovenClassImpl wovenClass = new WovenClassImpl(name, classbytes, classpathEntry.getDomain(), loader, registry, blackList); + WovenClassImpl wovenClass = new WovenClassImpl(name, classbytes, entry, classpathEntry.getDomain(), loader, registry, blackList); List<WovenClassImpl> wovenClasses = wovenClassStack.get(); if (wovenClasses == null) { wovenClasses = new ArrayList<WovenClassImpl>(6); diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java index 270f70593..e7e27a37c 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java @@ -12,6 +12,8 @@ package org.eclipse.osgi.internal.baseadaptor.weaving; import java.security.*; import java.util.*; +import org.eclipse.osgi.baseadaptor.bundlefile.BundleEntry; +import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil; import org.eclipse.osgi.internal.loader.BundleLoader; import org.eclipse.osgi.internal.serviceregistry.HookContext; import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry; @@ -26,21 +28,24 @@ public final class WovenClassImpl implements WovenClass, HookContext { private final static byte FLAG_WEAVINGCOMPLETE = 0x04; private final static String weavingHookName = WeavingHook.class.getName(); private final String className; + private final BundleEntry entry; private final List<String> dynamicImports; private final ProtectionDomain domain; private final BundleLoader loader; final ServiceRegistry registry; private final Map<ServiceRegistration<?>, Boolean> blackList; - private byte[] bytes; + private byte[] validBytes; + private byte[] resultBytes; private byte hookFlags = 0; private Throwable error; private ServiceRegistration<?> errorHook; private Class<?> clazz; - public WovenClassImpl(String className, byte[] bytes, ProtectionDomain domain, BundleLoader loader, ServiceRegistry registry, Map<ServiceRegistration<?>, Boolean> blacklist) { + public WovenClassImpl(String className, byte[] bytes, BundleEntry entry, ProtectionDomain domain, BundleLoader loader, ServiceRegistry registry, Map<ServiceRegistration<?>, Boolean> blacklist) { super(); this.className = className; - this.bytes = bytes; + this.validBytes = this.resultBytes = bytes; + this.entry = entry; this.dynamicImports = new DynamicImportList(this); this.domain = domain; this.loader = loader; @@ -51,13 +56,13 @@ public final class WovenClassImpl implements WovenClass, HookContext { public byte[] getBytes() { if ((hookFlags & FLAG_HOOKSCOMPLETE) == 0) { checkPermission(); - return bytes; // return raw bytes until complete + return validBytes; // return raw bytes until complete } // we have called all hooks; someone is calling outside of weave call // need to be safe and copy the bytes. - byte[] current = bytes; + byte[] current = validBytes; byte[] results = new byte[current.length]; - System.arraycopy(bytes, 0, results, 0, current.length); + System.arraycopy(current, 0, results, 0, current.length); return results; } @@ -68,7 +73,7 @@ public final class WovenClassImpl implements WovenClass, HookContext { if ((hookFlags & FLAG_HOOKSCOMPLETE) != 0) // someone is calling this outside of weave throw new IllegalStateException("Weaving has completed already."); //$NON-NLS-1$ - this.bytes = newBytes; + this.resultBytes = this.validBytes = newBytes; } void checkPermission() { @@ -90,9 +95,9 @@ public final class WovenClassImpl implements WovenClass, HookContext { private void setHooksComplete() { // create a copy of the bytes array that noone has a reference to - byte[] original = bytes; - bytes = new byte[bytes.length]; - System.arraycopy(original, 0, bytes, 0, original.length); + byte[] original = validBytes; + validBytes = new byte[original.length]; + System.arraycopy(original, 0, validBytes, 0, original.length); hookFlags |= FLAG_HOOKSCOMPLETE; } @@ -124,7 +129,13 @@ public final class WovenClassImpl implements WovenClass, HookContext { if (hook instanceof WeavingHook) { if (blackList.containsKey(hookRegistration)) return; // black listed hook - hookFlags |= FLAG_HOOKCALLED; + if ((hookFlags & FLAG_HOOKCALLED) == 0) { + hookFlags |= FLAG_HOOKCALLED; + // only do this check on the first weaving hook call + if (!validBytes(validBytes)) { + validBytes = AdaptorUtil.getBytes(entry.getInputStream(), (int) entry.getSize(), 8 * 1024); + } + } try { ((WeavingHook) hook).weave(this); } catch (WeavingException e) { @@ -140,6 +151,20 @@ public final class WovenClassImpl implements WovenClass, HookContext { } } + private boolean validBytes(byte[] checkBytes) { + if (checkBytes == null || checkBytes.length < 4) + return false; + if ((checkBytes[0] & 0xCA) != 0xCA) + return false; + if ((checkBytes[1] & 0xFE) != 0xFE) + return false; + if ((checkBytes[2] & 0xBA) != 0xBA) + return false; + if ((checkBytes[3] & 0xBE) != 0xBE) + return false; + return true; + } + public String getHookMethodName() { return "weave"; //$NON-NLS-1$ } @@ -169,7 +194,7 @@ public final class WovenClassImpl implements WovenClass, HookContext { } } finally { if ((hookFlags & FLAG_HOOKCALLED) != 0) { - wovenBytes = bytes; + wovenBytes = resultBytes; newImports = dynamicImports; setHooksComplete(); } |