You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2012/08/17 14:45:08 UTC
svn commit: r1374227 - in /sling/trunk/launchpad/base: ./
src/main/java/org/apache/sling/launchpad/base/impl/
src/test/java/org/apache/sling/launchpad/base/impl/
src/test/java/org/apache/sling/launchpad/base/impl/t1/ src/test/resources/
Author: fmeschbe
Date: Fri Aug 17 12:45:08 2012
New Revision: 1374227
URL: http://svn.apache.org/viewvc?rev=1374227&view=rev
Log:
SLING-2554 Add SlingFelix.getBundle(Class) method and test case
Added:
sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/SlingFelixTest.java
sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/
sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/T1Activator.java
sling/trunk/launchpad/base/src/test/resources/test1.bnd
Modified:
sling/trunk/launchpad/base/pom.xml
sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/impl/SlingFelix.java
Modified: sling/trunk/launchpad/base/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/pom.xml?rev=1374227&r1=1374226&r2=1374227&view=diff
==============================================================================
--- sling/trunk/launchpad/base/pom.xml (original)
+++ sling/trunk/launchpad/base/pom.xml Fri Aug 17 12:45:08 2012
@@ -50,6 +50,36 @@
<build>
<plugins>
<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>testbundles</id>
+ <phase>process-test-classes</phase>
+ <configuration>
+ <target name="build">
+ <taskdef resource="aQute/bnd/ant/taskdef.properties"
+ classpathref="maven.plugin.classpath" />
+ <bnd classpath="${build.testOutputDirectory}" failok="false"
+ exceptions="true" files="src/test/resources/test1.bnd"
+ output="${build.testOutputDirectory}" />
+ </target>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>biz.aQute</groupId>
+ <artifactId>bnd</artifactId>
+ <version>0.0.384</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
Modified: sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/impl/SlingFelix.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/impl/SlingFelix.java?rev=1374227&r1=1374226&r2=1374227&view=diff
==============================================================================
--- sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/impl/SlingFelix.java (original)
+++ sling/trunk/launchpad/base/src/main/java/org/apache/sling/launchpad/base/impl/SlingFelix.java Fri Aug 17 12:45:08 2012
@@ -21,11 +21,14 @@ package org.apache.sling.launchpad.base.
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.Map;
import org.apache.felix.framework.Felix;
import org.apache.sling.launchpad.base.shared.Loader;
import org.apache.sling.launchpad.base.shared.Notifiable;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
@@ -35,6 +38,9 @@ public class SlingFelix extends Felix {
private Thread notifierThread;
+ // see getBundle(Class) below
+ private Method getBundleMethod;
+
public SlingFelix(final Notifiable notifiable, final Map<?, ?> props) throws Exception {
super(props);
this.notifiable = notifiable;
@@ -87,6 +93,49 @@ public class SlingFelix extends Felix {
}
}
+ /**
+ * Returns the bundle from which the given class has been loaded or
+ * <code>null</code> if the class has not been loaded through any
+ * of the bundles in this framework.
+ * <p>
+ * This method delegates to Felix.getBundle(Class) to support the
+ * URLHandlers service implementation. See SLING-2554 for details.
+ *
+ * @param clazz The class to check
+ *
+ * @return The Bundle or <code>null</code> if the class has not been
+ * loaded through any of the bundles in this framework.
+ */
+ public Bundle getBundle(Class<?> clazz) {
+ Method getBundleMethod = this.getBundleMethod;
+ if (getBundleMethod == null) {
+ Class<?> provider = Felix.class; // super class actually
+ try {
+ getBundleMethod = provider.getDeclaredMethod("getBundle", Class.class);
+ getBundleMethod.setAccessible(true);
+ this.getBundleMethod = getBundleMethod;
+ } catch (Exception e) {
+ throw new NoSuchMethodError("getBundle");
+ }
+ }
+
+ try {
+ return (Bundle) getBundleMethod.invoke(this, clazz);
+ } catch (IllegalArgumentException e) {
+ // we don't expect this, we checked everything
+ } catch (IllegalAccessException e) {
+ // we don't expect this, because we set the method accessible
+ } catch (InvocationTargetException e) {
+ // unpack and rethrow
+ Throwable t = e.getCause();
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ }
+ }
+
+ return null;
+ }
+
private class Notifier implements Runnable {
private final boolean restart;
Added: sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/SlingFelixTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/SlingFelixTest.java?rev=1374227&view=auto
==============================================================================
--- sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/SlingFelixTest.java (added)
+++ sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/SlingFelixTest.java Fri Aug 17 12:45:08 2012
@@ -0,0 +1,191 @@
+/*
+ * 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 org.apache.sling.launchpad.base.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.HashMap;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.TestCase;
+
+import org.apache.sling.launchpad.base.shared.Notifiable;
+import org.junit.After;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.launch.Framework;
+import org.osgi.service.packageadmin.PackageAdmin;
+
+public class SlingFelixTest {
+
+ private final TestNotifiable notifiable = new TestNotifiable();
+
+ private SlingFelix framework;
+
+ @After
+ public void tearDown() {
+ stopSling();
+ }
+
+ @Test
+ public void test_start_stop() {
+ SlingFelix sf = startSling();
+ TestCase.assertNotNull(sf);
+ TestCase.assertEquals(Bundle.ACTIVE, sf.getState());
+
+ stopSling();
+ TestCase.assertNull("Expect the framework field to be cleared", this.framework);
+
+ TestCase.assertTrue("Expect Notifiable.stopped to be called", this.notifiable.stoppedCalled);
+ TestCase.assertFalse("Expect Notifiable.updated to not be called", this.notifiable.updatedCalled);
+ TestCase.assertNull("Expect Notifiable.updated to not be called", this.notifiable.updatedCalledFile);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void test_Felix_getBundle_Class_from_PackageAdmin() {
+
+ /*
+ * Tests whether the Felix.getBundle(Class) call from PackageAdmin
+ * is possible. This test should always succeed regardless of the
+ * SLING-2554 implementation because it uses regular Java call
+ * methodology.
+ */
+
+ SlingFelix sf = startSling();
+
+ PackageAdmin pa = getService(sf, PackageAdmin.class);
+ TestCase.assertNotNull(pa);
+
+ TestCase.assertNull("Integer class provided by the VM not from a bundle", pa.getBundle(Integer.class));
+ TestCase.assertEquals("BundleContext class must come from the framework", sf.getBundle(),
+ pa.getBundle(BundleContext.class));
+ }
+
+ @Test
+ public void test_Felix_getBundle_Class_from_UrlStreamHandler() {
+
+ /*
+ * Tests whether the Felix.getBundle(Class) method can be called
+ * from the URLHandlers class. This call may fail if SLING-2554
+ * does not work because it uses reflection on the class of the
+ * framework instance, which happens to be SlingFelix instead of
+ * Felix
+ */
+
+ SlingFelix sf = startSling();
+ SlingFelix sf2 = doStartSling(new TestNotifiable());
+
+ try {
+ InputStream ins = getClass().getResourceAsStream("/test1.jar");
+ sf.getBundleContext().installBundle("test1", ins).start();
+
+ Runnable r = getService(sf, Runnable.class);
+ r.run();
+
+ } catch (Exception e) {
+ throw (AssertionFailedError) new AssertionFailedError(e.toString()).initCause(e);
+ } finally {
+ doStopSling(sf2);
+ }
+ }
+
+ private SlingFelix startSling() {
+ if (this.framework == null) {
+ this.framework = doStartSling(this.notifiable);
+ }
+
+ return this.framework;
+ }
+
+ private static SlingFelix doStartSling(final Notifiable notifiable) {
+ final String baseDir = System.getProperty("basedir");
+ if (baseDir == null) {
+ TestCase.fail("Need the basedir system property to locate the framework folder");
+ }
+ File fwDir = new File(baseDir + "/target/felix." + System.nanoTime());
+ fwDir.mkdirs();
+
+ HashMap<String, Object> props = new HashMap<String, Object>();
+ props.put(Constants.FRAMEWORK_STORAGE, fwDir.getAbsolutePath());
+ props.put(Constants.FRAMEWORK_STORAGE_CLEAN, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+ props.put(Constants.FRAMEWORK_BEGINNING_STARTLEVEL, "30");
+
+ try {
+ SlingFelix fw = new SlingFelix(notifiable, props);
+ fw.start();
+ return fw;
+ } catch (Exception e) {
+ TestCase.fail("Failed to start OSGi Framework: " + e);
+ return null; // to keep the compiler cool
+ }
+ }
+
+ private void stopSling() {
+ if (this.framework != null) {
+ try {
+ doStopSling(this.framework);
+ } finally {
+ this.framework = null;
+ }
+ }
+ }
+
+ private static void doStopSling(final SlingFelix framework) {
+ try {
+ framework.stop();
+ if (framework.waitForStop(10L).getType() == FrameworkEvent.WAIT_TIMEDOUT) {
+ TestCase.fail("Timed out waiting for framework to stop");
+ }
+ } catch (Exception e) {
+ TestCase.fail("Cannot stop OSGi Framework: " + e);
+ }
+ }
+
+ private <T> T getService(final Framework framework, Class<T> type) {
+ ServiceReference<T> ref = framework.getBundleContext().getServiceReference(type);
+ if (ref != null) {
+ return framework.getBundleContext().getService(ref);
+ }
+ return null;
+ }
+
+ private static class TestNotifiable implements Notifiable {
+
+ boolean stoppedCalled = false;
+
+ boolean updatedCalled = false;
+
+ File updatedCalledFile = null;
+
+ public void stopped() {
+ this.stoppedCalled = true;
+ }
+
+ public void updated(File tmpFile) {
+ this.updatedCalled = true;
+ this.updatedCalledFile = tmpFile;
+ }
+
+ }
+}
Added: sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/T1Activator.java
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/T1Activator.java?rev=1374227&view=auto
==============================================================================
--- sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/T1Activator.java (added)
+++ sling/trunk/launchpad/base/src/test/java/org/apache/sling/launchpad/base/impl/t1/T1Activator.java Fri Aug 17 12:45:08 2012
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.sling.launchpad.base.impl.t1;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The <code>T1Activator</code> uses the framework to connect to an URL
+ * which causes the Felix.getBundle(Class) method to be called to resolve
+ * the framework from the calling class.
+ *
+ * If SlingFelix does not overwrite the Felix.getBundle(Class) method
+ * the URLHandlers class cannot find the method and thus the
+ * {@link #run()} method throws an exception.
+ */
+public class T1Activator implements BundleActivator, Runnable {
+
+ private String url;
+
+ public void start(BundleContext context) throws Exception {
+ this.url = context.getBundle().getEntry("META-INF/MANIFEST.MF").toString();
+ context.registerService(Runnable.class.getName(), this, null);
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ }
+
+ public void run() {
+ try {
+ new URL(url).openConnection();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
Added: sling/trunk/launchpad/base/src/test/resources/test1.bnd
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/base/src/test/resources/test1.bnd?rev=1374227&view=auto
==============================================================================
--- sling/trunk/launchpad/base/src/test/resources/test1.bnd (added)
+++ sling/trunk/launchpad/base/src/test/resources/test1.bnd Fri Aug 17 12:45:08 2012
@@ -0,0 +1,24 @@
+# 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.
+
+# Descriptor for a test bundle for SlingFelixTest to ensure
+# SLING-2554
+
+Bundle-SymbolicName: test1
+Bundle-Version: 0.0.1
+Bundle-Activator: org.apache.sling.launchpad.base.impl.t1.T1Activator
+Export-Package: org.apache.sling.launchpad.base.impl.t1;provide:=true;version=1.0
\ No newline at end of file