blob: b3317f65d197607c28c42e038ed004bbcc485e6a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* 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
*
* Contributors:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.kernel.userregion.internal.equinox;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import java.io.File;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.virgo.kernel.userregion.internal.equinox.KernelBundleClassLoader;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.Bundle;
/**
*/
public class LoadTimeWeavingTests extends AbstractOsgiFrameworkLaunchingTests {
private static final String DOMAIN_TYPE_NAME = "ltw.domain.DomainType";
private static final String A_TYPE_NAME = "app.a.A";
private static final String B_TYPE_NAME = "app.b.B";
private Bundle emBundle;
private Bundle includeBundle;
@Override
protected String getRepositoryConfigDirectory() {
return new File("src/test/resources/config/LoadTimeWeavingTests").getAbsolutePath();
}
@Before
public void setUp() throws Exception {
super.setUp();
this.framework.getBundleContext().installBundle(new File("src/test/resources/ltw/ltw-domain.jar").toURI().toString());
this.includeBundle = this.framework.getBundleContext().installBundle(new File("src/test/resources/ltw/ltw-include.jar").toURI().toString());
this.emBundle = this.framework.getBundleContext().installBundle(new File("src/test/resources/ltw/ltw-em.jar").toURI().toString());
this.emBundle.start();
}
@Test public void instrumentPackageIncludes() throws ClassNotFoundException {
KernelBundleClassLoader incClassLoader = (KernelBundleClassLoader) this.framework.getBundleClassLoader(this.includeBundle);
assertNotNull(incClassLoader);
ClassLoader throwAway = incClassLoader.createThrowAway();
assertEquals(throwAway, throwAway.loadClass(A_TYPE_NAME).getClassLoader());
assertEquals(incClassLoader, throwAway.loadClass(B_TYPE_NAME).getClassLoader());
}
@Test public void throwawayAcrossBundles() throws ClassNotFoundException {
KernelBundleClassLoader emClassLoader = (KernelBundleClassLoader) this.framework.getBundleClassLoader(this.emBundle);
assertNotNull(emClassLoader);
ClassLoader throwAway = emClassLoader.createThrowAway();
Class<?> domainTypeClass = throwAway.loadClass(DOMAIN_TYPE_NAME);
assertNotNull(domainTypeClass);
assertNotSame(emClassLoader.loadClass(DOMAIN_TYPE_NAME), domainTypeClass);
assertSame(domainTypeClass, throwAway.loadClass(DOMAIN_TYPE_NAME));
}
@Test public void weaveAcrossBundles() throws ClassNotFoundException {
KernelBundleClassLoader emClassLoader = (KernelBundleClassLoader) this.framework.getBundleClassLoader(this.emBundle);
assertNotNull(emClassLoader);
final AtomicInteger counter = new AtomicInteger(0);
emClassLoader.addClassFileTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
counter.incrementAndGet();
return null;
}
});
Class<?> domainTypeClass = emClassLoader.loadClass(DOMAIN_TYPE_NAME);
assertNotNull(domainTypeClass);
assertEquals(1, counter.get());
}
@Test public void testRefreshWithNoPropagation() throws Exception {
Class<?> before = this.emBundle.loadClass(DOMAIN_TYPE_NAME);
this.framework.refresh(this.emBundle);
waitUntilResolved(3000);
assertSame(this.emBundle.loadClass(DOMAIN_TYPE_NAME), before);
}
@Test public void testRefreshWithPropagation() throws Exception {
KernelBundleClassLoader emClassLoader = (KernelBundleClassLoader) this.framework.getBundleClassLoader(this.emBundle);
emClassLoader.addClassFileTransformer(new ClassFileTransformer() {
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
byte[] classfileBuffer) throws IllegalClassFormatException {
return null;
}
});
Class<?> before = this.emBundle.loadClass(DOMAIN_TYPE_NAME);
this.framework.refresh(this.emBundle);
waitUntilResolved(3000);
assertNotSame(this.emBundle.loadClass(DOMAIN_TYPE_NAME), before);
}
private void waitUntilResolved(int maxWaitInMillis) {
boolean resolved = this.emBundle.getState() == Bundle.RESOLVED;
while (!resolved && maxWaitInMillis>0) {
try {
Thread.sleep(50); maxWaitInMillis-=50;
} catch (InterruptedException e) {
continue;
}
resolved = this.emBundle.getState() == Bundle.RESOLVED;
}
}
}