Commit the new iPOJO version (0.7.6).
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@642265 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/examples/junit4osgi/felix-command/metadata.xml b/ipojo/examples/junit4osgi/felix-command/metadata.xml
new file mode 100644
index 0000000..87f7db1
--- /dev/null
+++ b/ipojo/examples/junit4osgi/felix-command/metadata.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component
+ className="org.apache.felix.ipojo.junit4osgi.command.JunitCommand"
+ factory="false">
+ <requires field="runner" />
+ <provides />
+ </component>
+ <instance
+ component="org.apache.felix.ipojo.junit4osgi.command.JunitCommand" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/junit4osgi/felix-command/pom.xml b/ipojo/examples/junit4osgi/felix-command/pom.xml
new file mode 100644
index 0000000..f810d59
--- /dev/null
+++ b/ipojo/examples/junit4osgi/felix-command/pom.xml
@@ -0,0 +1,95 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>Junit4Osgi</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Junit4Osgi-Felix-Command</name>
+ <artifactId>
+ org.apache.felix.ipojo.junit4osgi.felix-command
+ </artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.ipojo.junit4osgi</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.shell</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>
+ iPOJO OSGi Junit Runner - Felix Command
+ </Bundle-Name>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.ipojo.junit4osgi.command
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/junit4osgi/felix-command/src/main/java/org/apache/felix/ipojo/junit4osgi/command/JunitCommand.java b/ipojo/examples/junit4osgi/felix-command/src/main/java/org/apache/felix/ipojo/junit4osgi/command/JunitCommand.java
new file mode 100644
index 0000000..a217a9e
--- /dev/null
+++ b/ipojo/examples/junit4osgi/felix-command/src/main/java/org/apache/felix/ipojo/junit4osgi/command/JunitCommand.java
@@ -0,0 +1,111 @@
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestFailure;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiJunitRunner;
+import org.apache.felix.shell.Command;
+
+/**
+ * Felix shell command. Allow to run tests.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class JunitCommand implements Command {
+
+ private OSGiJunitRunner runner;
+
+ private List<String> getNamesFromTests(List<Test> list) {
+ List<String> names = new ArrayList<String>(list.size());
+ for (int i = 0; i < list.size(); i++) {
+ if (list.get(i) instanceof TestCase) {
+ names.add(((TestCase) list.get(i)).getName());
+ }
+ if (list.get(i) instanceof TestSuite) {
+ String name = ((TestSuite) list.get(i)).getName();
+ if (name == null) {
+ name = ((TestSuite) list.get(i)).toString();
+ }
+ names.add(name);
+ }
+ }
+ return names;
+ }
+
+ public void execute(String line, PrintStream out, PrintStream err) {
+ line = line.substring(getName().length()).trim();
+ List<TestResult> tr = null;
+ if (line.equals("all")) {
+ if (runner.getTests() == null) {
+ err.println("No tests to execute");
+ return;
+ } else {
+ out.println("Executing " + getNamesFromTests(runner.getTests()));
+ tr = runner.run();
+ }
+ } else {
+ try {
+ Long bundleId = new Long(line);
+ if (runner.getTests(bundleId) == null) {
+ err.println("No tests to execute");
+ return;
+ } else {
+ out.println("Executing " + getNamesFromTests(runner.getTests(bundleId)));
+ tr = runner.run(bundleId);
+ }
+ } catch (NumberFormatException e) {
+ err.println("Unable to parse id " + line);
+ return;
+ }
+ }
+
+ ListIterator<TestResult> it = tr.listIterator();
+ while (it.hasNext()) {
+ TestResult result = it.next();
+ if (result.failureCount() != 0) {
+ TestFailure fail = (TestFailure) result.failures().nextElement();
+ out.println(fail.trace());
+ return;
+ }
+ }
+
+ }
+
+ public String getName() {
+ return "junit";
+ }
+
+ public String getShortDescription() {
+ return "launch junit tests";
+ }
+
+ public String getUsage() {
+ return "junit";
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/immediate-launcher/metadata.xml b/ipojo/examples/junit4osgi/immediate-launcher/metadata.xml
new file mode 100644
index 0000000..648ab67
--- /dev/null
+++ b/ipojo/examples/junit4osgi/immediate-launcher/metadata.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component
+ className="org.apache.felix.ipojo.junit4osgi.command.ImmediateRunner"
+ factory="false">
+ <requires field="runner" />
+ <callback method="start" transition="validate" />
+ </component>
+ <instance
+ component="org.apache.felix.ipojo.junit4osgi.command.ImmediateRunner"
+ name="immediate-runner" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/junit4osgi/immediate-launcher/pom.xml b/ipojo/examples/junit4osgi/immediate-launcher/pom.xml
new file mode 100644
index 0000000..18cfb31
--- /dev/null
+++ b/ipojo/examples/junit4osgi/immediate-launcher/pom.xml
@@ -0,0 +1,95 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>Junit4Osgi</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Junit4Osgi-Immediate-Runner</name>
+ <artifactId>
+ org.apache.felix.ipojo.junit4osgi.immediate-runner
+ </artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.ipojo.junit4osgi</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.shell</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>
+ iPOJO OSGi Junit Runner - Immediate Runner
+ </Bundle-Name>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.ipojo.junit4osgi.command
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/junit4osgi/immediate-launcher/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ImmediateRunner.java b/ipojo/examples/junit4osgi/immediate-launcher/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ImmediateRunner.java
new file mode 100644
index 0000000..199cdf6
--- /dev/null
+++ b/ipojo/examples/junit4osgi/immediate-launcher/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ImmediateRunner.java
@@ -0,0 +1,35 @@
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiJunitRunner;
+
+/**
+ * Felix shell command. Allow to run tests.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ImmediateRunner {
+
+ private OSGiJunitRunner runner;
+
+ public void start() {
+ runner.run();
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/metadata.xml b/ipojo/examples/junit4osgi/junit4osgi/metadata.xml
new file mode 100644
index 0000000..83d84d3
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/metadata.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO xmlns:extender="org.apache.felix.ipojo.extender">
+ <Component
+ className="org.apache.felix.ipojo.junit4osgi.impl.JunitExtender">
+ <extender:extender extension="Test-Suite"
+ onArrival="onBundleArrival" onDeparture="onBundleDeparture" />
+ <callback transition="invalidate" method="stopping" />
+ <callback transition="validate" method="starting" />
+ <provides />
+ </Component>
+ <instance
+ component="org.apache.felix.ipojo.junit4osgi.impl.JunitExtender" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/junit4osgi/junit4osgi/pom.xml b/ipojo/examples/junit4osgi/junit4osgi/pom.xml
new file mode 100644
index 0000000..e4ffbf4
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/pom.xml
@@ -0,0 +1,103 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>Junit4Osgi</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Junit4Osgi</name>
+ <artifactId>org.apache.felix.ipojo.junit4osgi</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.metadata</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>
+ iPOJO OSGi Junit Runner
+ </Bundle-Name>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.ipojo.junit4osgi.impl,
+ org.apache.felix.ipojo.junit4osgi.test
+ </Private-Package>
+ <Export-Package>
+ org.apache.felix.ipojo.junit4osgi, junit.*
+ </Export-Package>
+ <Test-Suite>
+ org.apache.felix.ipojo.junit4osgi.test.TestTestCase,
+ org.apache.felix.ipojo.junit4osgi.test.TestOSGiTestCase,
+ org.apache.felix.ipojo.junit4osgi.test.TestTestSuite,
+ org.apache.felix.ipojo.junit4osgi.test.TestOSGiTestSuite
+ </Test-Suite>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiJunitRunner.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiJunitRunner.java
new file mode 100644
index 0000000..57a67d6
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiJunitRunner.java
@@ -0,0 +1,72 @@
+/*
+ * 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.felix.ipojo.junit4osgi;
+
+import java.io.PrintStream;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+/**
+ * OSGi Junit Runner.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface OSGiJunitRunner {
+
+ /**
+ * Set the output stream of the runner.
+ * @param ps : print stream.
+ */
+ void setResultPrinter(PrintStream ps);
+
+ /**
+ * Run the tests.
+ * @return the list of TestResult.
+ */
+ List<TestResult> run();
+
+ /**
+ * Run the tests from the given bundle.
+ * @param bundleId : bundle containing the tests.
+ * @return the list of the results.
+ */
+ List<TestResult> run(long bundleId);
+
+ /**
+ * Get the list of available test suites.
+ * @return the list of test suites.
+ */
+ List<Test> getTests();
+
+ /**
+ * Get the tests from the given bundle.
+ * @param bundleId : bundle id.
+ * @return the list of test suites contained in the given bundle.
+ */
+ List<Test> getTests(long bundleId);
+
+ /**
+ * Run the given test.
+ * @param test : test to execute.
+ * @return the result.
+ */
+ public TestResult run(Test test);
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestCase.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestCase.java
new file mode 100644
index 0000000..e10ad04
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestCase.java
@@ -0,0 +1,187 @@
+/*
+ * 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.felix.ipojo.junit4osgi;
+
+import junit.framework.TestCase;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * OSGi Test Case. Allow the injection of the bundle context.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class OSGiTestCase extends TestCase {
+
+ protected BundleContext context;
+
+ public void setBundleContext(BundleContext bc) {
+ context = bc;
+ }
+
+ /**
+ * Asserts that two doubles are equal. If they are not an AssertionFailedError is thrown with the given message.
+ */
+ static public void assertEquals(String message, double expected, double actual) {
+ if (Double.compare(expected, actual) != 0) {
+ fail(formatEqualsMessage(message, expected, actual));
+ }
+ }
+
+ static String formatEqualsMessage(String message, Object expected, Object actual) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ return formatted + "expected:<" + expected + "> but was:<" + actual + ">";
+ }
+
+ static String formatNotEqualsMessage(String message, Object o1, Object o2) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+ return formatted + "o1:<" + o1 + "> is equals to o2:<" + o2 + ">";
+ }
+
+ static String formatContainsMessage(String message, Object[] array, Object txt) {
+ String formatted = "";
+ if (message != null) {
+ formatted = message + " ";
+ }
+
+ String arr = null;
+ for (int i = 0; i < array.length; i++) {
+ if (arr == null) {
+ arr = "[" + array[i];
+ } else {
+ arr += "," + array[i];
+ }
+ }
+ arr += "]";
+
+ return formatted + "array:" + arr + " does not contains:<" + txt + ">";
+ }
+
+ static public void assertNotEquals(String message, Object o1, Object o2) {
+ if (o1.equals(o2)) {
+ fail(formatNotEqualsMessage(message, o1, o2));
+ }
+ }
+
+ static public void assertContains(String message, String[] array, String txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i].equals(txt)) {
+ return;
+ }
+ }
+ fail(formatContainsMessage(message, array, txt));
+ }
+
+ static public void assertContains(String message, byte[] array, int txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Byte[] bytes = new Byte[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Byte(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, short[] array, int txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Short[] bytes = new Short[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Short(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, int[] array, int txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Integer[] bytes = new Integer[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Integer(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, long[] array, long txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Long[] bytes = new Long[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Long(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, float[] array, float txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Float[] bytes = new Float[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Float(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, double[] array, double txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Double[] bytes = new Double[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Double(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+ static public void assertContains(String message, char[] array, char txt) {
+ for (int i = 0; i < array.length; i++) {
+ if (array[i] == txt) {
+ return;
+ }
+ }
+ Character[] bytes = new Character[array.length];
+ for (int i = 0; i < array.length; i++) {
+ bytes[i] = new Character(array[i]);
+ }
+ fail(formatContainsMessage(message, bytes, txt));
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestSuite.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestSuite.java
new file mode 100644
index 0000000..8e7795a
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/OSGiTestSuite.java
@@ -0,0 +1,87 @@
+/*
+ * 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.felix.ipojo.junit4osgi;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * OSGi Test Suite.
+ * Allow the injection of the bundle context.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class OSGiTestSuite extends TestSuite {
+
+ protected BundleContext context;
+
+ public OSGiTestSuite(Class clazz, BundleContext bc) {
+ super(clazz);
+ context = bc;
+ }
+
+ public OSGiTestSuite(BundleContext bc) {
+ super();
+ context = bc;
+ }
+
+ public OSGiTestSuite(String name, BundleContext bc) {
+ super(name);
+ context = bc;
+ }
+
+ public OSGiTestSuite(Class clazz, String name, BundleContext bc) {
+ super(clazz, name);
+ context = bc;
+ }
+
+ public void setBundleContext(BundleContext bc) {
+ context = bc;
+ }
+
+ /**
+ * Adds the tests from the given class to the suite
+ */
+ public void addTestSuite(Class testClass) {
+ if (OSGiTestCase.class.isAssignableFrom(testClass)) {
+ addTest(new OSGiTestSuite(testClass, context));
+ } else if (TestCase.class.isAssignableFrom(testClass)) {
+ addTest(new TestSuite(testClass));
+ } else {
+ System.out.println("Error : the " + testClass + " is not a valid test class");
+ }
+ }
+
+ public void runTest(Test test, TestResult result) {
+ if (test instanceof OSGiTestSuite) {
+ ((OSGiTestSuite) test).context = context;
+ test.run(result);
+ } else if (test instanceof OSGiTestCase) {
+ ((OSGiTestCase) test).context = context;
+ test.run(result);
+ } else {
+ test.run(result);
+ }
+
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/JunitExtender.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/JunitExtender.java
new file mode 100644
index 0000000..34f0382
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/JunitExtender.java
@@ -0,0 +1,302 @@
+/*
+ * 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.felix.ipojo.junit4osgi.impl;
+
+import java.io.PrintStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiJunitRunner;
+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;
+import org.apache.felix.ipojo.junit4osgi.OSGiTestSuite;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Detect test suite from installed bundles.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class JunitExtender implements OSGiJunitRunner {
+
+ public static final String SUITE_METHODNAME = "suite";
+
+ private Map<Bundle, List<Class>> m_suites = new HashMap<Bundle, List<Class>>();
+
+ private ResultPrinter m_printer = new ResultPrinter(System.out);
+
+ void onBundleArrival(Bundle bundle, String header) {
+ String[] tss = header.split(",");
+ for (int i = 0; i < tss.length; i++) {
+ try {
+ if (tss[i].length() != 0) {
+ System.out.println("Loading " + tss[i]);
+ Class<? extends Test> clazz = bundle.loadClass(tss[i].trim());
+ addTestSuite(bundle, clazz);
+ }
+ } catch (ClassNotFoundException e) {
+ System.err.println("The test suite " + tss[i] + " is not in the bundle " + bundle.getBundleId() + " : " + e.getMessage());
+ }
+ }
+ }
+
+ private synchronized void addTestSuite(Bundle bundle, Class<? extends Test> test) {
+ List<Class> list = m_suites.get(bundle);
+ if (list == null) {
+ list = new ArrayList<Class>();
+ list.add(test);
+ m_suites.put(bundle, list);
+ } else {
+ list.add(test);
+ }
+ }
+
+ private synchronized void removeTestSuites(Bundle bundle) {
+ m_suites.remove(bundle);
+ }
+
+ void onBundleDeparture(Bundle bundle) {
+ removeTestSuites(bundle);
+ }
+
+ public void setResultPrinter(PrintStream pw) {
+ m_printer = new ResultPrinter(pw);
+ }
+
+ public synchronized List<TestResult> run() {
+ List<TestResult> results = new ArrayList<TestResult>(m_suites.size());
+ Iterator<Entry<Bundle, List<Class>>> it = m_suites.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<Bundle, List<Class>> entry = it.next();
+ Bundle bundle = entry.getKey();
+ List<Class> list = m_suites.get(bundle);
+ for (int i = 0; i < list.size(); i++) {
+ Test test = createTestFromClass(list.get(i), bundle);
+ TestResult tr = doRun(test);
+ results.add(tr);
+ }
+ }
+ return results;
+ }
+
+ private TestResult doRun(Test test) {
+ TestResult result = new TestResult();
+ result.addListener(m_printer);
+ long startTime = System.currentTimeMillis();
+
+ test.run(result);
+
+ long endTime = System.currentTimeMillis();
+ long runTime = endTime - startTime;
+ m_printer.print(result, runTime);
+
+ return result;
+ }
+
+ private Test createTestFromClass(Class<?> clazz, Bundle bundle) {
+ Method suiteMethod = null;
+ boolean bc = false;
+ try {
+ suiteMethod = clazz.getMethod(SUITE_METHODNAME, new Class[0]);
+ } catch (Exception e) {
+ // try to use a suite method receiving a bundle context
+ try {
+ suiteMethod = clazz.getMethod(SUITE_METHODNAME, new Class[] { BundleContext.class });
+ bc = true;
+ } catch (Exception e2) {
+ // try to extract a test suite automatically
+ if (OSGiTestSuite.class.isAssignableFrom(clazz)) {
+ OSGiTestSuite ts = new OSGiTestSuite(clazz, getBundleContext(bundle));
+ return ts;
+ } else if (OSGiTestCase.class.isAssignableFrom(clazz)) {
+ OSGiTestSuite ts = new OSGiTestSuite(clazz, getBundleContext(bundle));
+ return ts;
+ } else {
+ return new TestSuite(clazz);
+ }
+ }
+ }
+
+ if (!Modifier.isStatic(suiteMethod.getModifiers())) {
+ System.err.println("Suite() method must be static");
+ return null;
+ }
+ Test test = null;
+ try {
+ if (bc) {
+ test = (Test) suiteMethod.invoke(null, new Object[] { getBundleContext(bundle) }); // static method injection the bundle context
+ } else {
+ test = (Test) suiteMethod.invoke(null, (Object[]) new Class[0]); // static method
+ }
+ } catch (InvocationTargetException e) {
+ System.err.println("Failed to invoke suite():" + e.getTargetException().toString());
+ return null;
+ } catch (IllegalAccessException e) {
+ System.err.println("Failed to invoke suite():" + e.toString());
+ return null;
+ }
+
+ return test;
+ }
+
+ public synchronized List<Test> getTests() {
+ List<Test> results = new ArrayList<Test>();
+ Iterator<Entry<Bundle, List<Class>>> it = m_suites.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<Bundle, List<Class>> entry = it.next();
+ Bundle bundle = entry.getKey();
+ List<Class> list = m_suites.get(bundle);
+ for (int i = 0; i < list.size(); i++) {
+ Test test = createTestFromClass(list.get(i), bundle);
+ results.add(test);
+ }
+ }
+ return results;
+ }
+
+ public TestResult run(Test test) {
+ return doRun(test);
+ }
+
+ public synchronized List<Test> getTests(long bundleId) {
+ Iterator<Entry<Bundle, List<Class>>> it = m_suites.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<Bundle, List<Class>> entry = it.next();
+ Bundle bundle = entry.getKey();
+ if (bundle.getBundleId() == bundleId) {
+ List<Test> results = new ArrayList<Test>();
+ List<Class> list = m_suites.get(bundle);
+ for (int i = 0; i < list.size(); i++) {
+ Test test = createTestFromClass(list.get(i), bundle);
+ results.add(test);
+ }
+ return results;
+ }
+ }
+ return null;
+ }
+
+ public synchronized List<TestResult> run(long bundleId) {
+ Iterator<Entry<Bundle, List<Class>>> it = m_suites.entrySet().iterator();
+ while (it.hasNext()) {
+ Entry<Bundle, List<Class>> entry = it.next();
+ Bundle bundle = entry.getKey();
+ if (bundle.getBundleId() == bundleId) {
+ List<TestResult> results = new ArrayList<TestResult>();
+ List<Class> list = m_suites.get(bundle);
+ for (int i = 0; i < list.size(); i++) {
+ Test test = createTestFromClass(list.get(i), bundle);
+ TestResult tr = doRun(test);
+ results.add(tr);
+ }
+ return results;
+ }
+ }
+ return null;
+ }
+
+ public synchronized void stopping() {
+ System.out.println("Cleaning test suites ...");
+ m_suites.clear();
+ }
+
+ public void starting() {
+ System.out.println("Junit Extender starting ...");
+ }
+
+ private BundleContext getBundleContext(Bundle bundle) {
+ if (bundle == null) { return null; }
+
+ // getBundleContext (OSGi 4.1)
+ Method meth = null;
+ try {
+ meth = bundle.getClass().getMethod("getBundleContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try the Equinox method
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try the Equinox method
+ }
+
+ // try Equinox getContext if not found.
+ if (meth == null) {
+ try {
+ meth = bundle.getClass().getMethod("getContext", new Class[0]);
+ } catch (SecurityException e) {
+ // Nothing do to, will try field inspection
+ } catch (NoSuchMethodException e) {
+ // Nothing do to, will try field inspection
+ }
+ }
+
+ if (meth != null) {
+ if (! meth.isAccessible()) {
+ meth.setAccessible(true);
+ }
+ try {
+ return (BundleContext) meth.invoke(bundle, new Object[0]);
+ } catch (IllegalArgumentException e) {
+ err("Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ err("Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (InvocationTargetException e) {
+ err("Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ }
+ }
+
+ // Else : Field inspection (KF and Prosyst)
+ Field[] fields = bundle.getClass().getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (BundleContext.class.isAssignableFrom(fields[i].getType())) {
+ if (! fields[i].isAccessible()) {
+ fields[i].setAccessible(true);
+ }
+ try {
+ return (BundleContext) fields[i].get(bundle);
+ } catch (IllegalArgumentException e) {
+ err("Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ } catch (IllegalAccessException e) {
+ err("Cannot get the BundleContext by invoking " + meth.getName(), e);
+ return null;
+ }
+ }
+ }
+ err("Cannot find the BundleContext for " + bundle.getSymbolicName(), null);
+ return null;
+ }
+
+ private void err(String s, Throwable e) {
+ System.err.println(s + " : " + e.getMessage());
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/ResultPrinter.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/ResultPrinter.java
new file mode 100644
index 0000000..4eb4e96
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/impl/ResultPrinter.java
@@ -0,0 +1,161 @@
+/*
+ * 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.felix.ipojo.junit4osgi.impl;
+
+import java.io.PrintStream;
+import java.text.NumberFormat;
+import java.util.Enumeration;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestFailure;
+import junit.framework.TestListener;
+import junit.framework.TestResult;
+import junit.runner.BaseTestRunner;
+
+/**
+ * Result Printer.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResultPrinter implements TestListener {
+ PrintStream fWriter;
+
+ int fColumn = 0;
+
+ public ResultPrinter(PrintStream writer) {
+ fWriter = writer;
+ }
+
+ /*
+ * API for use by textui.TestRunner
+ */
+
+ synchronized void print(TestResult result, long runTime) {
+ printHeader(runTime);
+ printErrors(result);
+ printFailures(result);
+ printFooter(result);
+ }
+
+ void printWaitPrompt() {
+ getWriter().println();
+ getWriter().println("<RETURN> to continue");
+ }
+
+ /*
+ * Internal methods
+ */
+
+ protected void printHeader(long runTime) {
+ getWriter().println();
+ getWriter().println("Time: " + elapsedTimeAsString(runTime));
+ }
+
+ protected void printErrors(TestResult result) {
+ printDefects(result.errors(), result.errorCount(), "error");
+ }
+
+ protected void printFailures(TestResult result) {
+ printDefects(result.failures(), result.failureCount(), "failure");
+ }
+
+ protected void printDefects(Enumeration<TestFailure> booBoos, int count, String type) {
+ if (count == 0)
+ return;
+ if (count == 1)
+ getWriter().println("There was " + count + " " + type + ":");
+ else
+ getWriter().println("There were " + count + " " + type + "s:");
+ for (int i = 1; booBoos.hasMoreElements(); i++) {
+ printDefect(booBoos.nextElement(), i);
+ }
+ }
+
+ public void printDefect(TestFailure booBoo, int count) { // only public for testing purposes
+ printDefectHeader(booBoo, count);
+ printDefectTrace(booBoo);
+ }
+
+ protected void printDefectHeader(TestFailure booBoo, int count) {
+ // I feel like making this a println, then adding a line giving the throwable a chance to print something
+ // before we get to the stack trace.
+ getWriter().print(count + ") " + booBoo.failedTest());
+ }
+
+ protected void printDefectTrace(TestFailure booBoo) {
+ getWriter().print(BaseTestRunner.getFilteredTrace(booBoo.trace()));
+ }
+
+ protected void printFooter(TestResult result) {
+ if (result.wasSuccessful()) {
+ getWriter().println();
+ getWriter().print("OK");
+ getWriter().println(" (" + result.runCount() + " test" + (result.runCount() == 1 ? "" : "s") + ")");
+
+ } else {
+ getWriter().println();
+ getWriter().println("FAILURES!!!");
+ getWriter().println("Tests run: " + result.runCount() + ", Failures: " + result.failureCount() + ", Errors: " + result.errorCount());
+ }
+ getWriter().println();
+ }
+
+ /**
+ * Returns the formatted string of the elapsed time. Duplicated from BaseTestRunner. Fix it.
+ */
+ protected String elapsedTimeAsString(long runTime) {
+ return NumberFormat.getInstance().format((double) runTime / 1000);
+ }
+
+ public PrintStream getWriter() {
+ return fWriter;
+ }
+
+ /**
+ * @see junit.framework.TestListener#addError(Test, Throwable)
+ */
+ public void addError(Test test, Throwable t) {
+ getWriter().print("E");
+ }
+
+ /**
+ * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
+ */
+ public void addFailure(Test test, AssertionFailedError t) {
+ getWriter().print("F");
+ }
+
+ /**
+ * @see junit.framework.TestListener#endTest(Test)
+ */
+ public void endTest(Test test) {
+ }
+
+ /**
+ * @see junit.framework.TestListener#startTest(Test)
+ */
+ public void startTest(Test test) {
+ getWriter().print(".");
+ if (fColumn++ >= 40) {
+ getWriter().println();
+ fColumn = 0;
+ }
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestCase.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestCase.java
new file mode 100644
index 0000000..2ee139e
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestCase.java
@@ -0,0 +1,34 @@
+/*
+ * 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.felix.ipojo.junit4osgi.test;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;
+
+/**
+ * Simple OSGi Test Case.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TestOSGiTestCase extends OSGiTestCase {
+
+ public void test1() {
+ System.out.println("Test BC");
+ assertNotNull("Test bundle context", context);
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestSuite.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestSuite.java
new file mode 100644
index 0000000..c68f37c
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestOSGiTestSuite.java
@@ -0,0 +1,43 @@
+/*
+ * 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.felix.ipojo.junit4osgi.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiTestSuite;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Simple OSGi Test suite.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TestOSGiTestSuite extends TestSuite {
+
+ public static Test suite(BundleContext bc) {
+ TestSuite ts = new TestSuite();
+ ts.setName("Test OSGi suite() method");
+ ts.addTestSuite(TestTestCase.class);
+ OSGiTestSuite ots = new OSGiTestSuite(TestOSGiTestCase.class, bc);
+ ots.setBundleContext(bc);
+ ts.addTest(ots);
+ return ts;
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestCase.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestCase.java
new file mode 100644
index 0000000..0e1527b
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestCase.java
@@ -0,0 +1,37 @@
+/*
+ * 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.felix.ipojo.junit4osgi.test;
+
+import junit.framework.TestCase;
+
+/**
+ * Simple Test Case.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TestTestCase extends TestCase {
+
+ public void test1() { }
+
+ public void test2() { }
+
+ public void test3() { }
+
+ public void test4() { }
+
+}
diff --git a/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestSuite.java b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestSuite.java
new file mode 100644
index 0000000..6bd1bf1
--- /dev/null
+++ b/ipojo/examples/junit4osgi/junit4osgi/src/main/java/org/apache/felix/ipojo/junit4osgi/test/TestTestSuite.java
@@ -0,0 +1,37 @@
+/*
+ * 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.felix.ipojo.junit4osgi.test;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Simple OSGi Test Suite.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TestTestSuite extends TestSuite {
+
+ public static Test suite() {
+ TestSuite ts = new TestSuite();
+ ts.setName("Test suite() method");
+ ts.addTestSuite(TestTestCase.class);
+ return ts;
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/metadata.xml b/ipojo/examples/junit4osgi/metadata.xml
new file mode 100644
index 0000000..29be5f3
--- /dev/null
+++ b/ipojo/examples/junit4osgi/metadata.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO xmlns:extender="org.apache.felix.ipojo.extender">
+ <Component className="org.apache.felix.ipojo.junit4osgi.impl.JunitExtender">
+ <extender:extender extension="Test-Suite" onArrival="onBundleArrival" onDeparture="onBundleDeparture"/>
+ <callback transition="invalidate" method="stopping"/>
+ <provides/>
+ </Component>
+ <instance component="org.apache.felix.ipojo.junit4osgi.impl.JunitExtender"/>
+
+ <component className="org.apache.felix.ipojo.junit4osgi.command.JunitCommand" factory="false">
+ <requires field="runner"/>
+ <provides/>
+ </component>
+ <instance component="org.apache.felix.ipojo.junit4osgi.command.JunitCommand"/>
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/junit4osgi/pom.xml b/ipojo/examples/junit4osgi/pom.xml
new file mode 100644
index 0000000..4e5a05e
--- /dev/null
+++ b/ipojo/examples/junit4osgi/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>Junit4Osgi</artifactId>
+ <name>Apache Felix iPOJO Junit4OSGi</name>
+ <packaging>pom</packaging>
+
+ <profiles>
+ <profile>
+ <id>java5</id>
+ <activation>
+ <jdk>1.5</jdk>
+ </activation>
+ <modules>
+ <module>junit4osgi</module>
+ <module>felix-command</module>
+ <module>swing-runner</module>
+ <module>immediate-launcher</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>java6</id>
+ <activation>
+ <jdk>1.6</jdk>
+ </activation>
+ <modules>
+ <module>junit4osgi</module>
+ <module>felix-command</module>
+ <module>swing-runner</module>
+ <module>immediate-launcher</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
diff --git a/ipojo/examples/junit4osgi/swing-runner/metadata.xml b/ipojo/examples/junit4osgi/swing-runner/metadata.xml
new file mode 100644
index 0000000..9251b6f
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/metadata.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component
+ classname="org.apache.felix.ipojo.junit4osgi.command.SwingRunner">
+ <requires field="m_runner" />
+ <callback method="stop" transition="invalidate" />
+ <callback method="start" transition="validate" />
+ </component>
+ <instance
+ component="org.apache.felix.ipojo.junit4osgi.command.SwingRunner" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/junit4osgi/swing-runner/pom.xml b/ipojo/examples/junit4osgi/swing-runner/pom.xml
new file mode 100644
index 0000000..da9bae5
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/pom.xml
@@ -0,0 +1,105 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>Junit4Osgi</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Junit4Osgi-Swing-GUI</name>
+ <artifactId>org.apache.felix.ipojo.junit4osgi.swing-gui</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.ipojo.junit4osgi</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.shell</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>
+ iPOJO OSGi Junit Runner - Swing Gui
+ </Bundle-Name>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ org.apache.felix.ipojo.junit4osgi.command
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <repositories>
+ <repository>
+ <id>unknown-jars-temp-repo</id>
+ <name>
+ A temporary repository created by NetBeans for libraries
+ and jars it could not identify. Please replace the
+ dependencies in this repository with correct ones and
+ delete this repository.
+ </name>
+ <url>file:${project.basedir}/lib</url>
+ </repository>
+ </repositories>
+</project>
diff --git a/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultCellRenderer.java b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultCellRenderer.java
new file mode 100644
index 0000000..680ad32
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultCellRenderer.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2008 clement.
+ *
+ * Licensed 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.
+ * under the License.
+ */
+
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import java.awt.Color;
+import java.awt.Component;
+
+import javax.swing.JTable;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ * Test result renderer.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResultCellRenderer extends DefaultTableCellRenderer {
+
+ /**
+ * UUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+ ResultTableModel results = (ResultTableModel) table.getModel();
+ String status = (String) results.getValueAt(row, column);
+ if (status.equals(ResultTableModel.SUCESS)) {
+ c.setForeground(Color.GREEN);
+ setToolTipText(results.getMessage(row, column));
+ }
+ if (status.equals(ResultTableModel.FAILURE)) {
+ c.setForeground(Color.ORANGE);
+ setToolTipText(results.getMessage(row, column));
+ }
+ if (status.equals(ResultTableModel.ERROR)) {
+ c.setForeground(Color.RED);
+ setToolTipText(results.getMessage(row, column));
+ }
+
+ return c;
+ }
+}
diff --git a/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultTableModel.java b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultTableModel.java
new file mode 100644
index 0000000..491f223
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/ResultTableModel.java
@@ -0,0 +1,183 @@
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.table.AbstractTableModel;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+
+/**
+ * Result Table Model.
+ * Store the results of executed tests.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ResultTableModel extends AbstractTableModel {
+
+ public static final String SUCESS = "success";
+
+ public static final String FAILURE = "failure";
+
+ public static final String ERROR = "error";
+
+ private static final long serialVersionUID = 1L;
+
+ private List<TestRecord> results = new ArrayList<TestRecord>();
+
+ public int getRowCount() {
+ return results.size();
+ }
+
+ public int getColumnCount() {
+ return 2;
+ }
+
+ public void addTest(Test t, AssertionFailedError e) {
+ TestRecord rec = new TestRecord(t, e);
+ results.add(rec);
+ fireTableDataChanged();
+ }
+
+ public void addTest(Test t, Throwable e) {
+ TestRecord rec = new TestRecord(t, e);
+ results.add(rec);
+ fireTableDataChanged();
+ }
+
+ public void addTest(Test t) {
+ if (!contains(t)) {
+ TestRecord rec = new TestRecord(t);
+ results.add(rec);
+ fireTableDataChanged();
+ }
+ }
+
+ public int getTestCount() {
+ return results.size();
+ }
+
+ public int getSucess() {
+ int count = 0;
+ for (TestRecord test : results) {
+ if (test.m_wasSucessFull) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ public int getErrors() {
+ int count = 0;
+ for (TestRecord test : results) {
+ if (test.m_error != null) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ public int getFailures() {
+ int count = 0;
+ for (TestRecord test : results) {
+ if (test.m_failure != null) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private boolean contains(Test t) {
+ for (TestRecord test : results) {
+ if (test.m_test.equals(t)) { return true; }
+ }
+ return false;
+ }
+
+ public void clear() {
+ results.clear();
+ fireTableDataChanged();
+ }
+
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (columnIndex == 0) { return results.get(rowIndex).m_test; }
+ if (columnIndex == 1) {
+ TestRecord tr = results.get(rowIndex);
+ if (tr.m_wasSucessFull) { return SUCESS; }
+ if (tr.m_failure != null) { return FAILURE; }
+ if (tr.m_error != null) { return ERROR; }
+ }
+ return null;
+ }
+
+ public String getColumnName(int column) {
+ if (column == 0) { return "Test"; }
+
+ if (column == 1) { return "Status"; }
+
+ return null;
+ }
+
+ public String getMessage(int row, int column) {
+ if (row == -1) { return null; }
+ TestRecord rec = results.get(row);
+ if (rec.m_wasSucessFull) { return "The test " + rec.m_test + " was executed sucessfully."; }
+ if (rec.m_failure != null) { return "The test " + rec.m_test + " has failed : \n" + rec.m_failure.getMessage(); }
+ if (rec.m_error != null) {
+ String message = "The test " + rec.m_test + " has thrown an error : \n" + rec.m_error.getMessage();
+ StringWriter sw = new StringWriter();
+ rec.m_error.printStackTrace(new PrintWriter(sw));
+ message += "\n" + sw.toString();
+ return message;
+ }
+ return "";
+ }
+
+ private class TestRecord {
+ private boolean m_wasSucessFull;
+
+ private Test m_test;
+
+ private AssertionFailedError m_failure;
+
+ private Throwable m_error;
+
+ public TestRecord(Test t, AssertionFailedError e) {
+ m_test = t;
+ m_wasSucessFull = false;
+ m_failure = e;
+ }
+
+ public TestRecord(Test t, Throwable e) {
+ m_test = t;
+ m_wasSucessFull = false;
+ m_error = e;
+ }
+
+ public TestRecord(Test t) {
+ m_test = t;
+ m_wasSucessFull = true;
+ }
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.form b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.form
new file mode 100644
index 0000000..55cf564
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.form
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.5" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+ <NonVisualComponents>
+ <Container class="javax.swing.JDialog" name="m_resultDialog">
+ <Properties>
+ <Property name="defaultCloseOperation" type="int" value="0"/>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[320, 250]"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="windowClosed" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="onDialogClosed"/>
+ <EventHandler event="windowClosing" listener="java.awt.event.WindowListener" parameters="java.awt.event.WindowEvent" handler="onDialogClosed"/>
+ </Events>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JScrollPane" name="m_message">
+ <Properties>
+ <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
+ <Border info="null"/>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[300, 202]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[300, 202]"/>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+ </AuxValues>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="Center"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JTextArea" name="m_messageArea">
+ <Properties>
+ <Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
+ <Color blue="f0" green="f0" id="Panel.background" palette="3" red="f0" type="palette"/>
+ </Property>
+ <Property name="columns" type="int" value="20"/>
+ <Property name="editable" type="boolean" value="false"/>
+ <Property name="lineWrap" type="boolean" value="true"/>
+ <Property name="rows" type="int" value="5"/>
+ <Property name="wrapStyleWord" type="boolean" value="true"/>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[300, 250]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[250, 200]"/>
+ </Property>
+ </Properties>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JButton" name="m_ok">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Ok"/>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[120, 23]"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="m_okActionPerformed"/>
+ </Events>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
+ <BorderConstraints direction="South"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ </SubComponents>
+ </Container>
+ </NonVisualComponents>
+ <Properties>
+ <Property name="defaultCloseOperation" type="int" value="2"/>
+ <Property name="title" type="java.lang.String" value="Junit Runner"/>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[580, 580]"/>
+ </Property>
+ </Properties>
+ <SyntheticProperties>
+ <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+ </SyntheticProperties>
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,84,0,0,2,98"/>
+ </AuxValues>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JPanel" name="m_panel">
+ <Properties>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[580, 560]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[580, 566]"/>
+ </Property>
+ </Properties>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="2" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
+ <SubComponents>
+ <Container class="javax.swing.JScrollPane" name="m_suiteScroll">
+ <Properties>
+ <Property name="autoscrolls" type="boolean" value="true"/>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[400, 147]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[400, 147]"/>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+ </AuxValues>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="0" gridWidth="4" gridHeight="2" fill="1" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JList" name="m_suiteList">
+ <Properties>
+ <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+ <Connection code="new TestListModel()" type="code"/>
+ </Property>
+ <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[250, 147]"/>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[250, 147]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[250, 147]"/>
+ </Property>
+ </Properties>
+ </Component>
+ </SubComponents>
+ </Container>
+ <Component class="javax.swing.JButton" name="m_allButton">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Select All"/>
+ <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="m_allButtonActionPerformed"/>
+ </Events>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="4" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="3" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ <Component class="javax.swing.JButton" name="m_executeButton">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="Execute"/>
+ <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[90, 23]"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="m_executeButtonActionPerformed"/>
+ </Events>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="4" gridY="1" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+ </Component>
+ <Container class="javax.swing.JScrollPane" name="m_resultScroll">
+ <Properties>
+ <Property name="verticalScrollBarPolicy" type="int" value="22"/>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[452, 402]"/>
+ </Property>
+ </Properties>
+ <AuxValues>
+ <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+ </AuxValues>
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="2" gridWidth="5" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="3" insetsBottom="3" insetsRight="3" anchor="10" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JTable" name="m_resultTable">
+ <Properties>
+ <Property name="autoCreateRowSorter" type="boolean" value="true"/>
+ <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+ <Font name="Tahoma" size="10" style="0"/>
+ </Property>
+ <Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
+ <Connection code="new ResultTableModel()" type="code"/>
+ </Property>
+ <Property name="autoResizeMode" type="int" value="4"/>
+ <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[300, 400]"/>
+ </Property>
+ <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="[300, 400]"/>
+ </Property>
+ <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+ <Dimension value="null"/>
+ </Property>
+ </Properties>
+ <Events>
+ <EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="m_resultTableMouseClicked"/>
+ </Events>
+ </Component>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+ </Container>
+ <Container class="javax.swing.JPanel" name="m_statusBar">
+ <Constraints>
+ <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
+ <GridBagConstraints gridX="0" gridY="2" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
+ </Constraint>
+ </Constraints>
+
+ <Layout class="org.netbeans.modules.form.compat2.layouts.DesignBoxLayout"/>
+ <SubComponents>
+ <Component class="javax.swing.JProgressBar" name="m_progress">
+ <Properties>
+ <Property name="indeterminate" type="boolean" value="true"/>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JLabel" name="m_executedResults">
+ <Properties>
+ <Property name="text" type="java.lang.String" value="aaaaaaaaaaaaaaa"/>
+ </Properties>
+ </Component>
+ </SubComponents>
+ </Container>
+ </SubComponents>
+</Form>
diff --git a/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.java b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.java
new file mode 100644
index 0000000..82c4366
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/SwingRunner.java
@@ -0,0 +1,475 @@
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import java.awt.Cursor;
+import java.awt.Point;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JScrollBar;
+
+import javax.swing.table.TableColumn;
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import org.apache.felix.ipojo.junit4osgi.OSGiJunitRunner;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+
+/**
+ * Swing Runner for Junit4Osgi.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class SwingRunner extends javax.swing.JFrame implements BundleListener {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Bundle context (to register the bundle listener).
+ */
+ private BundleContext m_context;
+
+ /**
+ * OSGi Junit Runner Service.
+ */
+ private OSGiJunitRunner m_runner;
+
+ /**
+ * State variable describing if we are executing tests.
+ */
+ private boolean m_running = false;
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JButton m_allButton;
+ private javax.swing.JButton m_executeButton;
+ private javax.swing.JLabel m_executedResults;
+ private javax.swing.JScrollPane m_message;
+ private javax.swing.JTextArea m_messageArea;
+ private javax.swing.JButton m_ok;
+ private javax.swing.JPanel m_panel;
+ private javax.swing.JProgressBar m_progress;
+ private javax.swing.JDialog m_resultDialog;
+ private javax.swing.JScrollPane m_resultScroll;
+ private javax.swing.JTable m_resultTable;
+ private javax.swing.JPanel m_statusBar;
+ private javax.swing.JList m_suiteList;
+ private javax.swing.JScrollPane m_suiteScroll;
+ // End of variables declaration//GEN-END:variables
+
+ /**
+ * Constructor.
+ * @param bc : bundle context.
+ */
+ public SwingRunner(BundleContext bc) {
+ m_context = bc;
+ }
+
+ /**
+ * Start method.
+ */
+ public void start() {
+ initComponents();
+ setVisible(true);
+ m_resultDialog.setVisible(false);
+ refreshSuites();
+ m_context.addBundleListener(this);
+ m_executedResults.setText(" \t No executed tests");
+ m_progress.setIndeterminate(false);
+ m_progress.setMaximum(100);
+ m_progress.setValue(100);
+
+ TableColumn column = null;
+ for (int i = 0; i < m_resultTable.getColumnCount(); i++) {
+ column = m_resultTable.getColumnModel().getColumn(i);
+ if (i == 0) {
+ column.setPreferredWidth(350); //first column is bigger
+ } else {
+ column.setPreferredWidth(50);
+ column.setCellRenderer(new ResultCellRenderer());
+ }
+}
+ }
+
+ /**
+ * Stop method.
+ */
+ public void stop() {
+ m_context.removeBundleListener(this);
+ dispose();
+ }
+
+ /**
+ * Refresh the list of available test suites.
+ */
+ private void refreshSuites() {
+ List<Test> list = m_runner.getTests();
+ TestListModel lm = (TestListModel) m_suiteList.getModel();
+ lm.clear();
+ for (Test t : list) {
+ lm.addTest(t);
+ }
+ }
+
+ /** This method is called from within the constructor to
+ * initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is
+ * always regenerated by the Form Editor.
+ */
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+ java.awt.GridBagConstraints gridBagConstraints;
+
+ m_resultDialog = new javax.swing.JDialog();
+ m_message = new javax.swing.JScrollPane();
+ m_messageArea = new javax.swing.JTextArea();
+ m_ok = new javax.swing.JButton();
+ m_panel = new javax.swing.JPanel();
+ m_suiteScroll = new javax.swing.JScrollPane();
+ m_suiteList = new javax.swing.JList();
+ m_allButton = new javax.swing.JButton();
+ m_executeButton = new javax.swing.JButton();
+ m_resultScroll = new javax.swing.JScrollPane();
+ m_resultTable = new javax.swing.JTable();
+ m_statusBar = new javax.swing.JPanel();
+ m_progress = new javax.swing.JProgressBar();
+ m_executedResults = new javax.swing.JLabel();
+
+ m_resultDialog.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
+ m_resultDialog.setMinimumSize(new java.awt.Dimension(320, 250));
+ m_resultDialog.addWindowListener(new java.awt.event.WindowAdapter() {
+ public void windowClosed(java.awt.event.WindowEvent evt) {
+ onDialogClosed(evt);
+ }
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ onDialogClosed(evt);
+ }
+ });
+
+ m_message.setBorder(null);
+ m_message.setMinimumSize(new java.awt.Dimension(300, 202));
+ m_message.setPreferredSize(new java.awt.Dimension(300, 202));
+
+ m_messageArea.setBackground(javax.swing.UIManager.getDefaults().getColor("Panel.background"));
+ m_messageArea.setColumns(20);
+ m_messageArea.setEditable(false);
+ m_messageArea.setLineWrap(true);
+ m_messageArea.setRows(5);
+ m_messageArea.setWrapStyleWord(true);
+ m_messageArea.setMinimumSize(new java.awt.Dimension(300, 250));
+ m_messageArea.setPreferredSize(new java.awt.Dimension(250, 200));
+ m_message.setViewportView(m_messageArea);
+
+ m_resultDialog.getContentPane().add(m_message, java.awt.BorderLayout.CENTER);
+
+ m_ok.setText("Ok");
+ m_ok.setPreferredSize(new java.awt.Dimension(120, 23));
+ m_ok.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ okActionPerformed(evt);
+ }
+ });
+ m_resultDialog.getContentPane().add(m_ok, java.awt.BorderLayout.SOUTH);
+
+ setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
+ setTitle("Junit Runner");
+ setMinimumSize(new java.awt.Dimension(580, 580));
+ getContentPane().setLayout(new java.awt.GridBagLayout());
+
+ m_panel.setMinimumSize(new java.awt.Dimension(580, 560));
+ m_panel.setPreferredSize(new java.awt.Dimension(580, 566));
+ m_panel.setLayout(new java.awt.GridBagLayout());
+
+ m_suiteScroll.setAutoscrolls(true);
+ m_suiteScroll.setMinimumSize(new java.awt.Dimension(400, 147));
+ m_suiteScroll.setPreferredSize(new java.awt.Dimension(400, 147));
+
+ m_suiteList.setModel(new TestListModel());
+ m_suiteList.setMaximumSize(new java.awt.Dimension(250, 147));
+ m_suiteList.setMinimumSize(new java.awt.Dimension(250, 147));
+ m_suiteList.setPreferredSize(new java.awt.Dimension(250, 147));
+ m_suiteScroll.setViewportView(m_suiteList);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridwidth = 4;
+ gridBagConstraints.gridheight = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
+ m_panel.add(m_suiteScroll, gridBagConstraints);
+
+ m_allButton.setText("Select All");
+ m_allButton.setMaximumSize(new java.awt.Dimension(90, 23));
+ m_allButton.setMinimumSize(new java.awt.Dimension(90, 23));
+ m_allButton.setPreferredSize(new java.awt.Dimension(90, 23));
+ m_allButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ allButtonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 4;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
+ gridBagConstraints.insets = new java.awt.Insets(3, 0, 0, 0);
+ m_panel.add(m_allButton, gridBagConstraints);
+
+ m_executeButton.setText("Execute");
+ m_executeButton.setMaximumSize(new java.awt.Dimension(90, 23));
+ m_executeButton.setMinimumSize(new java.awt.Dimension(90, 23));
+ m_executeButton.setPreferredSize(new java.awt.Dimension(90, 23));
+ m_executeButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ executeButtonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 4;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
+ gridBagConstraints.insets = new java.awt.Insets(2, 0, 0, 0);
+ m_panel.add(m_executeButton, gridBagConstraints);
+
+ m_resultScroll.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+ m_resultScroll.setMinimumSize(new java.awt.Dimension(452, 402));
+
+ m_resultTable.setFont(new java.awt.Font("Tahoma", 0, 10));
+ m_resultTable.setModel(new ResultTableModel());
+ m_resultTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
+ m_resultTable.setMaximumSize(new java.awt.Dimension(300, 400));
+ m_resultTable.setMinimumSize(new java.awt.Dimension(300, 400));
+ m_resultTable.setPreferredSize(null);
+ m_resultTable.addMouseListener(new java.awt.event.MouseAdapter() {
+ public void mouseClicked(java.awt.event.MouseEvent evt) {
+ resultTableMouseClicked(evt);
+ }
+ });
+ m_resultScroll.setViewportView(m_resultTable);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridwidth = 5;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ gridBagConstraints.insets = new java.awt.Insets(2, 3, 3, 3);
+ m_panel.add(m_resultScroll, gridBagConstraints);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 0;
+ gridBagConstraints.gridheight = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
+ gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
+ getContentPane().add(m_panel, gridBagConstraints);
+
+ m_statusBar.setLayout(new javax.swing.BoxLayout(m_statusBar, javax.swing.BoxLayout.LINE_AXIS));
+
+ m_progress.setIndeterminate(true);
+ m_statusBar.add(m_progress);
+
+ m_executedResults.setText("aaaaaaaaaaaaaaa");
+ m_statusBar.add(m_executedResults);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ getContentPane().add(m_statusBar, gridBagConstraints);
+
+ pack();
+ }// </editor-fold>//GEN-END:initComponents
+
+ /**
+ * Execute button action.
+ * @param evt : event.
+ */
+ private void executeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_executeButtonActionPerformed
+ if (m_running) { return; }
+ // Collect selected test.
+ int[] indices = m_suiteList.getSelectedIndices();
+ List<Test> list = new ArrayList<Test>(indices.length);
+ TestListModel model = (TestListModel) m_suiteList.getModel();
+ for (int i = 0; i < indices.length; i++) {
+ list.add(model.getTestElementAt(indices[i]));
+ }
+ setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ executeTest(list);
+ }//GEN-LAST:event_m_executeButtonActionPerformed
+
+ /**
+ * All button action.
+ * @param evt : event.
+ */
+ private void allButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_allButtonActionPerformed
+ int max = m_suiteList.getModel().getSize();
+ int[] indices = new int[max];
+ for (int i = 0; i < max; i++) {
+ indices[i] = i;
+ }
+ m_suiteList.setSelectedIndices(indices);
+ }//GEN-LAST:event_m_allButtonActionPerformed
+
+ /**
+ * Listener on table click.
+ * @param evt : event.
+ */
+ private void resultTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_m_resultTableMouseClicked
+ Point p = evt.getPoint();
+ int row = m_resultTable.rowAtPoint(p);
+ int col = m_resultTable.columnAtPoint(p);
+ ResultTableModel model = (ResultTableModel) m_resultTable.getModel();
+ String message = model.getMessage(row, col);
+ if (message != null) {
+ setEnabled(false);
+ m_resultDialog.setTitle("Test Report");
+ m_messageArea.setText(message);
+ m_resultDialog.setVisible(true);
+ }
+ }//GEN-LAST:event_m_resultTableMouseClicked
+
+ /**
+ * Ok button action.
+ * @param evt : event.
+ */
+ private void okActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_m_okActionPerformed
+ m_resultDialog.setVisible(false);
+ setEnabled(true);
+ }//GEN-LAST:event_m_okActionPerformed
+
+ /**
+ * Listener when the test report is closed.
+ * @param evt : event.
+ */
+ private void onDialogClosed(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_onDialogClosed
+ m_resultDialog.setVisible(false);
+ setEnabled(true);
+ }//GEN-LAST:event_onDialogClosed
+
+ /**
+ * Execute method.
+ * @param list : list of test to execute.
+ */
+ private void executeTest(final List<Test> list) {
+ Runnable thread = new Runnable() {
+ public void run() {
+ ResultTableModel model = (ResultTableModel) m_resultTable.getModel();
+ m_running = true;
+ m_executeButton.setText("Running...");
+ m_progress.setIndeterminate(true);
+ model.clear();
+ for (int i = 0; i < list.size(); i++) {
+ TestResult tr = new TestResult();
+ tr.addListener(new MyTestListener());
+ list.get(i).run(tr);
+ }
+ m_running = false;
+ m_progress.setIndeterminate(false);
+ m_progress.setMaximum(100);
+ m_progress.setValue(100);
+ m_executeButton.setText("Execute");
+ computeExecutedTest();
+ setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ }
+
+ };
+ new Thread(thread).start();
+ }
+
+ private void computeExecutedTest() {
+ ResultTableModel results = (ResultTableModel) m_resultTable.getModel();
+ String m = " \t ";
+ m+= results.getTestCount() + " tests executed / ";
+ m+= results.getSucess() + " sucess / ";
+ m+= results.getFailures() + " failures / ";
+ m+= results.getErrors() + " errors ";
+ m_executedResults.setText(m);
+ }
+
+ private class MyTestListener implements junit.framework.TestListener {
+ /**
+ * Table model.
+ */
+ ResultTableModel m_model = (ResultTableModel) m_resultTable.getModel();
+
+ /**
+ * Add an error.
+ * @param arg0 : test which throws an error.
+ * @param arg1 : thrown exception.
+ * @see junit.framework.TestListener#addError(junit.framework.Test, java.lang.Throwable)
+ */
+ public void addError(Test arg0, Throwable arg1) {
+ m_model.addTest(arg0, arg1);
+ adjustScroll();
+ }
+
+ /**
+ * Add a failure.
+ * @param arg0 : failing test.
+ * @param arg1 : thrown failure.
+ * @see junit.framework.TestListener#addError(junit.framework.Test, java.lang.Throwable)
+ */
+ public void addFailure(Test arg0, AssertionFailedError arg1) {
+ m_model.addTest(arg0, arg1);
+ adjustScroll();
+ }
+
+ /**
+ * End of a test.
+ * @param arg0 : test.
+ * @see junit.framework.TestListener#endTest(junit.framework.Test)
+ */
+ public void endTest(Test arg0) {
+ m_model.addTest(arg0);
+ adjustScroll();
+ }
+
+ /**
+ * Start of a test.
+ * @param arg0 : test.
+ * @see junit.framework.TestListener#startTest(junit.framework.Test)
+ */
+ public void startTest(Test arg0) {
+ // Nothing to do here.
+ }
+
+ /**
+ * Adjust the scrolling bar of the result table.
+ */
+ private void adjustScroll() {
+ JScrollBar bar = m_resultScroll.getVerticalScrollBar();
+ if ((bar != null) && (bar.isVisible())) {
+ bar.setValue(Integer.MAX_VALUE);
+ }
+ }
+
+ }
+
+ /**
+ * Bundle Changed callback method.
+ * @param arg0 : bundle event.
+ * @see org.osgi.framework.BundleListener#bundleChanged(org.osgi.framework.BundleEvent)
+ */
+ public void bundleChanged(BundleEvent arg0) {
+ refreshSuites();
+ }
+
+}
diff --git a/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/TestListModel.java b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/TestListModel.java
new file mode 100644
index 0000000..4811c5e
--- /dev/null
+++ b/ipojo/examples/junit4osgi/swing-runner/src/main/java/org/apache/felix/ipojo/junit4osgi/command/TestListModel.java
@@ -0,0 +1,89 @@
+/*
+ * 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.felix.ipojo.junit4osgi.command;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.swing.AbstractListModel;
+import junit.framework.Test;
+
+/**
+ * Test Suite list model.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TestListModel extends AbstractListModel {
+
+ private static final long serialVersionUID = 1L;
+
+ private List<TestRecord> list = new ArrayList<TestRecord>();
+
+ public Object getElementAt(int index) {
+ if (index >= list.size()) {
+ return null;
+ } else {
+ return list.get(index).name;
+ }
+ }
+
+ public Test getTestElementAt(int index) {
+ return list.get(index).test;
+ }
+
+ public void addTest(Test test) {
+ synchronized(this) {
+ TestRecord tr = new TestRecord();
+ tr.test = test;
+ tr.name = test.toString();
+ list.add(tr);
+ }
+ fireContentsChanged(this, list.size() - 1, list.size() - 1);
+ }
+
+ public void removeTest(Test test) {
+ int index = 1;
+ synchronized(this) {
+ for (TestRecord t : list) {
+ if (t.test.equals(test)) {
+ index = list.indexOf(t);
+ list.remove(t);
+ return;
+ }
+ }
+ }
+
+ if (index != -1) {
+ fireContentsChanged(this, index, index);
+ }
+ }
+
+ public void clear() {
+ list.clear();
+ }
+
+ private class TestRecord {
+ public Test test;
+
+ public String name;
+ }
+
+ public int getSize() {
+ return list.size();
+ }
+
+}
diff --git a/ipojo/examples/pom.xml b/ipojo/examples/pom.xml
new file mode 100644
index 0000000..0aef7eb
--- /dev/null
+++ b/ipojo/examples/pom.xml
@@ -0,0 +1,40 @@
+<project>
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>iPOJO</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples</artifactId>
+ <name>Apache Felix iPOJO Examples</name>
+ <packaging>pom</packaging>
+ <modules>
+ <module>tutorial-maven</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>java5</id>
+ <activation>
+ <jdk>1.5</jdk>
+ </activation>
+ <modules>
+ <module>junit4osgi</module>
+ <module>property-handler</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>java6</id>
+ <activation>
+ <jdk>1.6</jdk>
+ </activation>
+ <modules>
+ <module>junit4osgi</module>
+ <module>property-handler</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
diff --git a/ipojo/examples/property-handler/PropertyHandler/metadata.xml b/ipojo/examples/property-handler/PropertyHandler/metadata.xml
new file mode 100644
index 0000000..48d7bef
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandler/metadata.xml
@@ -0,0 +1,9 @@
+<ipojo xmlns:props="example.handler.properties">
+
+ <!-- Declare the handler -->
+ <handler name="properties" namespace="example.handler.properties"
+ classname="org.apache.felix.ipojo.handler.properties.PropertiesHandler">
+ <!-- the properties handler does not use any other handler -->
+ </handler>
+
+</ipojo>
diff --git a/ipojo/examples/property-handler/PropertyHandler/pom.xml b/ipojo/examples/property-handler/PropertyHandler/pom.xml
new file mode 100644
index 0000000..d806ab9
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandler/pom.xml
@@ -0,0 +1,85 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples.property.handler</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Apache Felix iPOJO Property Handler</name>
+ <artifactId>
+ org.apache.felix.ipojo.example.handler.property
+ </artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.metadata</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Private-Package>
+ org.apache.felix.ipojo.handler.properties,
+ example.handler.properties
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ <configuration>
+ <ignoreAnnotations>true</ignoreAnnotations>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/property-handler/PropertyHandler/src/main/java/example/handler/properties/Properties.java b/ipojo/examples/property-handler/PropertyHandler/src/main/java/example/handler/properties/Properties.java
new file mode 100644
index 0000000..9144bb8
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandler/src/main/java/example/handler/properties/Properties.java
@@ -0,0 +1,33 @@
+/*
+ * 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 example.handler.properties;
+
+/**
+ * The Properties annotation.
+ * This annotation may be used in POJO class to used the Property handler.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public @interface Properties {
+
+ /**
+ * Returns the property file used by the handler.
+ */
+ String file();
+
+}
diff --git a/ipojo/examples/property-handler/PropertyHandler/src/main/java/org/apache/felix/ipojo/handler/properties/PropertiesHandler.java b/ipojo/examples/property-handler/PropertyHandler/src/main/java/org/apache/felix/ipojo/handler/properties/PropertiesHandler.java
new file mode 100644
index 0000000..abd3583
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandler/src/main/java/org/apache/felix/ipojo/handler/properties/PropertiesHandler.java
@@ -0,0 +1,283 @@
+/*
+ * 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.felix.ipojo.handler.properties;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.PrimitiveHandler;
+import org.apache.felix.ipojo.architecture.HandlerDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.parser.FieldMetadata;
+import org.apache.felix.ipojo.parser.PojoMetadata;
+
+/**
+ * This handler load a properties file containing property value. The handler injects this values inside fields. When stopping the handler stores
+ * updated value inside the file. The properties file contains [field-name: field-value] (field-value are strings) Metadata :
+ * <example.handler.properties:properties file="file-path"> Instances can override file locations by setting the properties.file property.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PropertiesHandler extends PrimitiveHandler {
+
+ /** The Handler NAMESPACE. */
+ private final String NAMESPACE = "example.handler.properties";
+
+ /** Properties file. */
+ private Properties m_properties = new Properties();
+
+ /** File location. */
+ private String m_file;
+
+ /**
+ * This method is the first to be invoked. This method aims to configure the handler. It receives the component type metadata and the instance
+ * description. The method parses given metadata and register field to listen. Step 3 : when the instance configuration contains the
+ * properties.file property, it overrides the properties file location.
+ * @param metadata : component type metadata
+ * @param configuration : instance description
+ * @throws ConfigurationException : the configuration of the handler has failed.
+ * @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.metadata.Element, java.util.Dictionary)
+ */
+ @SuppressWarnings("unchecked")
+ public void configure(Element metadata, Dictionary configuration) throws ConfigurationException {
+ // Parse metadata to get <properties file="$file"/>
+
+ Element[] elem = metadata.getElements("properties", NAMESPACE); // Get all example.handler.properties:properties element
+
+ switch (elem.length) {
+ case 0:
+ // No matching element in metadata, throw a configuration error.
+ throw new ConfigurationException("No properties found");
+ case 1:
+ // One 'properties' found, get attributes.
+ m_file = elem[0].getAttribute("file");
+ if (m_file == null) {
+ // if file is null, throw a configuration error.
+ throw new ConfigurationException("Malformed properties element : file attribute must be set");
+ }
+ break;
+ default:
+ // To simplify we handle only one properties element.
+ throw new ConfigurationException("Only one properties element is supported");
+ }
+
+ // Look if the instance overrides file location :
+ String instanceFile = (String) configuration.get("properties.file");
+ if (instanceFile != null) {
+ m_file = instanceFile;
+ }
+
+ // Load properties
+ try {
+ loadProperties();
+ } catch (IOException e) {
+ throw new ConfigurationException("Error when reading the " + m_file + " file : " + e.getMessage());
+ }
+
+ // Register fields
+ // By convention, properties file entry are field name, so look for each property to get field list.
+
+ //First get Pojo Metadata metadata :
+ PojoMetadata pojoMeta = getPojoMetadata();
+ Enumeration e = m_properties.keys();
+ while (e.hasMoreElements()) {
+ String field = (String) e.nextElement();
+ FieldMetadata fm = pojoMeta.getField(field);
+
+ if (fm == null) { // The field does not exist
+ throw new ConfigurationException("The field " + field + " is declared in the properties file but does not exist in the pojo");
+ }
+
+ // Then check that the field is a String field
+ if (!fm.getFieldType().equals(String.class.getName())) {
+ throw new ConfigurationException("The field " + field + " exists in the pojo, but is not a String");
+ }
+
+ // All checks are ok, register the interceptor.
+ getInstanceManager().register(fm, this);
+ }
+
+ // Finally register the field to listen
+ }
+
+ /**
+ * This method is called when the instance start (after the configure method). We just print stored properties.
+ * @see org.apache.felix.ipojo.Handler#start()
+ */
+ public void start() {
+ // The properties are already loaded (in the configure method), just print values.
+ m_properties.list(System.out);
+ }
+
+ /**
+ * This method is called when the instance stops. We save the properties to not lost the instance state and clear the stored properties.
+ * @see org.apache.felix.ipojo.Handler#stop()
+ */
+ public void stop() {
+ try {
+ saveProperties();
+ } catch (IOException e) {
+ error("Cannot read the file : " + m_file, e); // Log an error message by using the iPOJO logger
+ }
+ m_properties = null;
+ }
+
+ /**
+ * This method is called at each time the pojo 'get' a listened field. The method return the stored value.
+ * @param pojo : pojo object getting the field
+ * @param field : field name.
+ * @param o : previous value.
+ * @return the stored value.
+ * @see org.apache.felix.ipojo.PrimitiveHandler#getterCallback(java.lang.String, java.lang.Object)
+ */
+ public Object onGet(Object pojo, String field, Object o) {
+ // When the pojo requires a value for a managed field, this method is invoked.
+ // So, we have just to return the stored value.
+ return m_properties.get(field);
+ }
+
+ /**
+ * This method is called at each time the pojo 'set' a listened field. This method updates the local properties.
+ * @param pojo : pojo object setting the field
+ * @param field : field name
+ * @param newvalue : new value
+ * @see org.apache.felix.ipojo.PrimitiveHandler#setterCallback(java.lang.String, java.lang.Object)
+ */
+ public void onSet(Object pojo, String field, Object newvalue) {
+ // When the pojo set a value to a managed field, this method is invoked.
+ // So, we update the stored value.
+ m_properties.put(field, newvalue);
+ }
+
+ /**
+ * Step 2 : state properties when the instance becomes invalid.
+ * @param newState : the instance state
+ * @see org.apache.felix.ipojo.Handler#stateChanged(int)
+ */
+ public void stateChanged(int newState) {
+ // This method is invoked each times that the instance state changed.
+
+ // If the new state is invalid, save the properties.
+ if (newState == ComponentInstance.INVALID) {
+ // Reload properties
+ try {
+ saveProperties();
+ } catch (IOException e) {
+ error("Cannot read the file : " + m_file, e); // Log an error message by using the iPOJO logger
+ }
+ return;
+ }
+ }
+
+ /**
+ * Step 5 : dynamic reconfiguration. This method is call when the instance is reconfigured externally. The given property contains property value.
+ * @param dict : new properties
+ * @see org.apache.felix.ipojo.Handler#reconfigure(java.util.Dictionary)
+ */
+ @SuppressWarnings("unchecked")
+ public synchronized void reconfigure(Dictionary dict) {
+ // For each property, look if a new value is contained in the new configuration.
+ Enumeration e = m_properties.keys();
+ while (e.hasMoreElements()) {
+ String field = (String) e.nextElement();
+ String value = (String) dict.get(field);
+ // If the dictionary contains a value, update the stored value.
+ if (value != null) {
+ m_properties.put(field, value);
+ }
+ }
+ }
+
+ /**
+ * Returns handler description.
+ * @return the handler description.
+ * @see org.apache.felix.ipojo.Handler#getDescription()
+ */
+ public HandlerDescription getDescription() {
+ return new Description(this);
+ }
+
+ /**
+ * Helper method just loading the properties.
+ * @throws IOException : the file cannot be read.
+ */
+ private void loadProperties() throws IOException {
+ // Load the properties file from file system
+ File file = new File(m_file);
+ InputStream is = new FileInputStream(file);
+ m_properties.load(is);
+ }
+
+ /**
+ * Helper method writing properties.
+ * @throws IOException : the file cannot be written.
+ */
+ private void saveProperties() throws IOException {
+ // Store the file, modified the last modification date.
+ File file = new File(m_file);
+ OutputStream os = new FileOutputStream(file);
+ m_properties.store(os, "");
+ }
+
+ /**
+ * Step 3 : The handler will participate to the instance architecture.
+ * This class describing the handler.
+ */
+ private class Description extends HandlerDescription {
+
+ /**
+ * Instantiates a new description.
+ * @param h the h
+ */
+ public Description(PrimitiveHandler h) {
+ super(h);
+ }
+
+ /**
+ * This method must return the Element describing the handler. The description of this handler contains the list of properties with attached
+ * value.
+ * @return the description of the handler.
+ * @see org.apache.felix.ipojo.architecture.HandlerDescription#getHandlerInfo()
+ */
+ @SuppressWarnings("unchecked")
+ public Element getHandlerInfo() {
+ Element elem = super.getHandlerInfo(); // This method must be called to get the root description element.
+ Enumeration e = m_properties.keys();
+ while (e.hasMoreElements()) {
+ String field = (String) e.nextElement();
+ Element prop = new Element("property", ""); // Create an element for the actual property.
+ // Add two attribute (the field and the value).
+ prop.addAttribute(new Attribute("field", field));
+ prop.addAttribute(new Attribute("value", (String) m_properties.get(field)));
+ elem.addElement(prop); // Attach the current element to the root element.
+ }
+ return elem;
+ }
+
+ }
+}
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/metadata.xml b/ipojo/examples/property-handler/PropertyHandlerTest/metadata.xml
new file mode 100644
index 0000000..dcc9c16
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/metadata.xml
@@ -0,0 +1,21 @@
+<ipojo xmlns:props="example.handler.properties">
+
+ <!-- Declare a component using your handler -->
+ <component
+ classname="org.apache.felix.ipojo.handler.properties.example.PropertiesTester">
+ <callback transition="validate" method="start" />
+ <callback transition="invalidate" method="stop" />
+ <!-- declare our handler -->
+ <props:properties file="props\properties.txt" />
+ </component>
+
+ <!-- Declare an instance -->
+ <instance component="annotationTester" />
+ <instance
+ component="org.apache.felix.ipojo.handler.properties.example.PropertiesTester"
+ name="i1">
+ <property name="properties.file"
+ value="props\properties-i1.txt" />
+ </instance>
+
+</ipojo>
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/pom.xml b/ipojo/examples/property-handler/PropertyHandlerTest/pom.xml
new file mode 100644
index 0000000..dc28218
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/pom.xml
@@ -0,0 +1,83 @@
+<!--
+ 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.
+-->
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples.property.handler</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <name>Apache Felix iPOJO Property Handler Test</name>
+ <artifactId>
+ org.apache.felix.ipojo.example.handler.property.test
+ </artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>
+ org.apache.felix.ipojo.example.handler.property
+ </artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Private-Package>
+ org.apache.felix.ipojo.handler.properties.example
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>${pom.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/props/properties-i1.txt b/ipojo/examples/property-handler/PropertyHandlerTest/props/properties-i1.txt
new file mode 100644
index 0000000..7d688d2
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/props/properties-i1.txt
@@ -0,0 +1,4 @@
+#
+#Sun Nov 18 20:33:54 CET 2007
+m_property2=foo - 18 nov. 2007 20\:32\:55 - 18 nov. 2007 20\:33\:51
+m_property1=bar - 18 nov. 2007 20\:32\:55 - 18 nov. 2007 20\:33\:51
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/props/properties.txt b/ipojo/examples/property-handler/PropertyHandlerTest/props/properties.txt
new file mode 100644
index 0000000..2d46de8
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/props/properties.txt
@@ -0,0 +1,4 @@
+#
+#Sun Nov 18 20:33:54 CET 2007
+m_property2=prop2 - 18 nov. 2007 20\:32\:55 - 18 nov. 2007 20\:33\:51
+m_property1=prop1 - 18 nov. 2007 20\:32\:55 - 18 nov. 2007 20\:33\:51
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/AnnotationPropertiesTester.java b/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/AnnotationPropertiesTester.java
new file mode 100644
index 0000000..0f3df8d
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/AnnotationPropertiesTester.java
@@ -0,0 +1,83 @@
+/*
+ * 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.felix.ipojo.handler.properties.example;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Invalidate;
+import org.apache.felix.ipojo.annotations.Validate;
+
+import example.handler.properties.Properties;
+
+/**
+ * A simple component implementation using the property handler.
+ *@author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Component(name = "annotationTester")
+@Properties(file = "props\\properties.txt")
+public class AnnotationPropertiesTester {
+
+ /**
+ * Property 1 : injected.
+ */
+ private String m_property1;
+
+ /**
+ * Property 1 : injected.
+ */
+ private String m_property2;
+
+ /**
+ * Start method :
+ * displays loaded & injected properties before modifying them.
+ */
+ @Validate
+ public void start() {
+ System.out.println("AnnotationPropertiesTester is starting ...");
+ System.out.println("Property 1 : " + m_property1);
+ System.out.println("Property 2 : " + m_property2);
+
+ updateProperties();
+ }
+
+ /**
+ * Stop method :
+ * displays properties values.
+ */
+ @Invalidate
+ public void stop() {
+ System.out.println("AnnotationPropertiesTester is stopping ...");
+ System.out.println("Property 1 : " + m_property1);
+ System.out.println("Property 2 : " + m_property2);
+ }
+
+ /**
+ * Update property value.
+ */
+ private void updateProperties() {
+ System.out.println("Update properties");
+ Date date = new Date();
+ DateFormat df = DateFormat.getDateTimeInstance();
+ m_property1 = m_property1 + " - " + df.format(date);
+ m_property2 = m_property2 + " - " + df.format(date);
+
+ }
+}
diff --git a/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/PropertiesTester.java b/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/PropertiesTester.java
new file mode 100644
index 0000000..37872db
--- /dev/null
+++ b/ipojo/examples/property-handler/PropertyHandlerTest/src/main/java/org/apache/felix/ipojo/handler/properties/example/PropertiesTester.java
@@ -0,0 +1,68 @@
+/*
+ * 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.felix.ipojo.handler.properties.example;
+
+import java.text.DateFormat;
+import java.util.Date;
+
+public class PropertiesTester {
+
+ // These two fields will be injected.
+ private String property1;
+ private String property2;
+
+ /**
+ * Starting method.
+ * This method will be called when the instance starts.
+ */
+ public void start() {
+ System.out.println("PropertiesTester is starting ...");
+ // Read the injected properties.
+ System.out.println("Property 1 : " + property1);
+ System.out.println("Property 2 : " + property2);
+
+ // Update the properties.
+ updateProperties();
+ }
+
+ /**
+ * Stopping method.
+ * This method will be called when the instance stops.
+ */
+ public void stop() {
+ System.out.println("PropertiesTester is stopping ...");
+ System.out.println("Property 1 : " + property1);
+ System.out.println("Property 2 : " + property2);
+ }
+
+ /**
+ * This method just updates managed properties.
+ * It appends the current date to the actual property value.
+ */
+ private void updateProperties() {
+ System.out.println("Update properties");
+ Date date = new Date();
+ DateFormat df = DateFormat.getDateTimeInstance();
+ // The properties will be updated in the property file
+ property1 = property1 + " - " + df.format(date);
+ property2 = property2 + " - " + df.format(date);
+
+ }
+
+}
diff --git a/ipojo/examples/property-handler/pom.xml b/ipojo/examples/property-handler/pom.xml
new file mode 100644
index 0000000..2b9f2df
--- /dev/null
+++ b/ipojo/examples/property-handler/pom.xml
@@ -0,0 +1,36 @@
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>ipojo.examples.property.handler</artifactId>
+ <name>Apache Felix iPOJO Property Handler</name>
+ <packaging>pom</packaging>
+
+ <profiles>
+ <profile>
+ <id>java5</id>
+ <activation>
+ <jdk>1.5</jdk>
+ </activation>
+ <modules>
+ <module>PropertyHandler</module>
+ <module>PropertyHandlerTest</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>java6</id>
+ <activation>
+ <jdk>1.6</jdk>
+ </activation>
+ <modules>
+ <module>PropertyHandler</module>
+ <module>PropertyHandlerTest</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.client.annotation/metadata.xml b/ipojo/examples/tutorial-maven/hello.client.annotation/metadata.xml
new file mode 100644
index 0000000..134250d
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client.annotation/metadata.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <instance component="AnnotatedHelloClient" name="HelloClient"/>
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.client.annotation/pom.xml b/ipojo/examples/tutorial-maven/hello.client.annotation/pom.xml
new file mode 100644
index 0000000..eee6444
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client.annotation/pom.xml
@@ -0,0 +1,66 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.client.annotation</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <name>Hello Service Client using Annotations</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.service</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>apache.snapshots</id>
+ <name>snapshot plugins</name>
+ <url>
+ http://people.apache.org/repo/m2-snapshot-repository
+ </url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
+ <Private-Package>ipojo.example.hello.client</Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/hello/client/HelloClient.java b/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/hello/client/HelloClient.java
new file mode 100644
index 0000000..2c3697c
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/hello/client/HelloClient.java
@@ -0,0 +1,90 @@
+/*
+ * 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 ipojo.example.hello.client;
+
+import ipojo.example.hello.Hello;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Invalidate;
+import org.apache.felix.ipojo.annotations.Requires;
+import org.apache.felix.ipojo.annotations.Validate;
+
+/**
+ * A simple Hello service client. This client use annotation instead of XML metadata.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Component(name = "AnnotatedHelloClient", architecture = true)
+public class HelloClient implements Runnable {
+
+ /** Delay between two invocations. */
+ private static final int DELAY = 10000;
+
+ /**
+ * Hello services. Injected by the container.
+ */
+ @Requires
+ private Hello[] m_hello;
+
+ /**
+ * End flag.
+ */
+ private boolean m_end;
+
+ /**
+ * Run method.
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ while (!m_end) {
+ try {
+ invokeHelloServices();
+ Thread.sleep(DELAY);
+ } catch (InterruptedException ie) {
+ /* will recheck end */
+ }
+ }
+ }
+
+ /**
+ * Invoke hello services.
+ */
+ public void invokeHelloServices() {
+ for (int i = 0; i < m_hello.length; i++) {
+ System.out.println(i + " :" + m_hello[i].sayHello("Clement"));
+ }
+ }
+
+ /**
+ * Starting.
+ */
+ @Validate
+ public void starting() {
+ Thread thread = new Thread(this);
+ m_end = false;
+ thread.start();
+ }
+
+ /**
+ * Stopping.
+ */
+ @Invalidate
+ public void stopping() {
+ m_end = true;
+ }
+}
diff --git a/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/source.txt b/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/source.txt
new file mode 100644
index 0000000..0198756
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client.annotation/src/main/java/ipojo/example/source.txt
@@ -0,0 +1 @@
+PUT YOUR SOURCE FILES HERE
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.client/metadata.xml b/ipojo/examples/tutorial-maven/hello.client/metadata.xml
new file mode 100644
index 0000000..4141c34
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client/metadata.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component className="ipojo.example.hello.client.HelloClient"
+ architecture="true">
+ <requires field="m_hello" />
+ <callback transition="validate" method="starting" />
+ <callback transition="invalidate" method="stopping" />
+ <properties>
+ <property field="m_name" name="name" />
+ </properties>
+ </component>
+ <instance component="ipojo.example.hello.client.HelloClient">
+ <property name="name" value="clement" />
+ </instance>
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.client/pom.xml b/ipojo/examples/tutorial-maven/hello.client/pom.xml
new file mode 100644
index 0000000..91cbe69
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client/pom.xml
@@ -0,0 +1,82 @@
+<!--
+ 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging><!-- Use the BND Maven plug-in -->
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.client</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <name>Hello Service Client</name>
+ <dependencies>
+ <dependency>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.service</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>apache.snapshots</id>
+ <name>snapshot plugins</name>
+ <url>
+ http://people.apache.org/repo/m2-snapshot-repository
+ </url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <version>1.4.0</version>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ ipojo.example.hello.client
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/hello/client/HelloClient.java b/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/hello/client/HelloClient.java
new file mode 100644
index 0000000..023db3f
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/hello/client/HelloClient.java
@@ -0,0 +1,90 @@
+/*
+ * 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 ipojo.example.hello.client;
+
+import ipojo.example.hello.Hello;
+
+/**
+ * Hello Service simple client.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class HelloClient implements Runnable {
+
+ /**
+ * Delay between two invocations.
+ */
+ private static final int DELAY = 10000;
+
+ /**
+ * Hello services.
+ * Injected by the container.
+ * */
+ private Hello[] m_hello; // Service Requirement
+
+ /**
+ * End flag.
+ * */
+ private boolean m_end;
+
+ /**
+ * Name property.
+ * Injected by the container.
+ * */
+ private String m_name;
+
+ /**
+ * Run method.
+ * @see java.lang.Runnable#run()
+ */
+ public void run() {
+ while (!m_end) {
+ try {
+ invokeHelloServices();
+ Thread.sleep(DELAY);
+ } catch (InterruptedException ie) {
+ /* will recheck end */
+ }
+ }
+ }
+
+ /**
+ * Invoke hello services.
+ */
+ public void invokeHelloServices() {
+ for (int i = 0; i < m_hello.length; i++) {
+ System.out.println(m_hello[i].sayHello(m_name));
+ }
+ }
+
+ /**
+ * Starting.
+ */
+ public void starting() {
+ Thread thread = new Thread(this);
+ m_end = false;
+ thread.start();
+ }
+
+ /**
+ * Stopping.
+ */
+ public void stopping() {
+ m_end = true;
+ }
+}
diff --git a/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/source.txt b/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/source.txt
new file mode 100644
index 0000000..0198756
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.client/src/main/java/ipojo/example/source.txt
@@ -0,0 +1 @@
+PUT YOUR SOURCE FILES HERE
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.impl.annotation/pom.xml b/ipojo/examples/tutorial-maven/hello.impl.annotation/pom.xml
new file mode 100644
index 0000000..2281a57
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl.annotation/pom.xml
@@ -0,0 +1,88 @@
+<!--
+ 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.impl.annotation</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <name>Hello Service Provider using Annotations</name>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>apache.snapshots</id>
+ <name>snapshot plugins</name>
+ <url>
+ http://people.apache.org/repo/m2-snapshot-repository
+ </url>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.service</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.annotations</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ ipojo.example.hello.impl
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/HelloImpl.java b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/HelloImpl.java
new file mode 100644
index 0000000..8b37c2f
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/HelloImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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 ipojo.example.hello.impl;
+
+import ipojo.example.hello.Hello;
+
+import org.apache.felix.ipojo.annotations.Component;
+import org.apache.felix.ipojo.annotations.Provides;
+
+/**
+ * Component implementing the Hello service.
+ * This class used annotations to describe the component type.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@Component
+@Provides
+public class HelloImpl implements Hello {
+
+ /**
+ * Returns an 'Hello' message.
+ * @param name : name
+ * @return Hello message
+ * @see ipojo.example.hello.Hello#sayHello(java.lang.String)
+ */
+ public String sayHello(String name) { return "hello " + name + " @"; }
+}
diff --git a/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/source.txt b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/source.txt
new file mode 100644
index 0000000..0198756
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/java/ipojo/example/hello/impl/source.txt
@@ -0,0 +1 @@
+PUT YOUR SOURCE FILES HERE
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/resources/metadata.xml b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/resources/metadata.xml
new file mode 100644
index 0000000..559b556
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl.annotation/src/main/resources/metadata.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <instance component="ipojo.example.hello.impl.HelloImpl"
+ name="HelloService2" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.impl/metadata.xml b/ipojo/examples/tutorial-maven/hello.impl/metadata.xml
new file mode 100644
index 0000000..59d9666
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl/metadata.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component className="ipojo.example.hello.impl.HelloImpl"
+ name="HelloProvider" architecture="true">
+ <provides />
+ </component>
+ <instance component="HelloProvider" name="HelloService" />
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.impl/pom.xml b/ipojo/examples/tutorial-maven/hello.impl/pom.xml
new file mode 100644
index 0000000..3cf4551
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl/pom.xml
@@ -0,0 +1,65 @@
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.impl</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <name>Hello Service Provider</name>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>apache.snapshots</id>
+ <name>snapshot plugins</name>
+ <url>
+ http://people.apache.org/repo/m2-snapshot-repository
+ </url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <dependencies>
+ <dependency>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.service</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Private-Package>
+ ipojo.example.hello.impl
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-ipojo-plugin</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>ipojo-bundle</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/HelloImpl.java b/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/HelloImpl.java
new file mode 100644
index 0000000..8008fa9
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/HelloImpl.java
@@ -0,0 +1,36 @@
+/*
+ * 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 ipojo.example.hello.impl;
+
+import ipojo.example.hello.Hello;
+
+/**
+ * Component implementing the Hello service.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class HelloImpl implements Hello {
+
+ /**
+ * Returns an 'Hello' message.
+ * @param name : name
+ * @return Hello message
+ * @see ipojo.example.hello.Hello#sayHello(java.lang.String)
+ */
+ public String sayHello(String name) { return "hello " + name; }
+}
diff --git a/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/source.txt b/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/source.txt
new file mode 100644
index 0000000..0198756
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.impl/src/main/java/ipojo/example/hello/impl/source.txt
@@ -0,0 +1 @@
+PUT YOUR SOURCE FILES HERE
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.service/metadata.xml b/ipojo/examples/tutorial-maven/hello.service/metadata.xml
new file mode 100644
index 0000000..89547bc
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.service/metadata.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<iPOJO>
+ <component className="ipojo.example.hello.impl.HelloImpl" name="HelloProvider" architecture="true">
+ <provides/>
+ </component>
+ <instance component="HelloProvider" name="HelloService"/>
+</iPOJO>
\ No newline at end of file
diff --git a/ipojo/examples/tutorial-maven/hello.service/pom.xml b/ipojo/examples/tutorial-maven/hello.service/pom.xml
new file mode 100644
index 0000000..084989d
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.service/pom.xml
@@ -0,0 +1,63 @@
+<!--
+ 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.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>hello.service</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <name>Hello Service</name>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>apache.snapshots</id>
+ <name>snapshot plugins</name>
+ <url>
+ http://people.apache.org/repo/m2-snapshot-repository
+ </url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.0</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>
+ ${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Export-Package>
+ ipojo.example.hello
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/ipojo/examples/tutorial-maven/hello.service/src/main/java/ipojo/example/hello/Hello.java b/ipojo/examples/tutorial-maven/hello.service/src/main/java/ipojo/example/hello/Hello.java
new file mode 100644
index 0000000..e0c25da
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/hello.service/src/main/java/ipojo/example/hello/Hello.java
@@ -0,0 +1,33 @@
+/*
+ * 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 ipojo.example.hello;
+
+/**
+ * Hello Interface.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public interface Hello {
+
+ /**
+ * Returns a message like: "Hello $user_name".
+ * @param name the name
+ * @return the hello message
+ */
+ String sayHello(String name);
+}
diff --git a/ipojo/examples/tutorial-maven/pom.xml b/ipojo/examples/tutorial-maven/pom.xml
new file mode 100644
index 0000000..99d12ac
--- /dev/null
+++ b/ipojo/examples/tutorial-maven/pom.xml
@@ -0,0 +1,40 @@
+<project>
+ <parent>
+ <groupId>ipojo.examples</groupId>
+ <artifactId>ipojo.examples</artifactId>
+ <version>0.7.6-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>ipojo.tutorial</artifactId>
+ <name>Apache Felix iPOJO Tutorial</name>
+ <packaging>pom</packaging>
+ <modules>
+ <module>hello.service</module>
+ <module>hello.impl</module>
+ <module>hello.client</module>
+ </modules>
+
+ <profiles>
+ <profile>
+ <id>java5</id>
+ <activation>
+ <jdk>1.5</jdk>
+ </activation>
+ <modules>
+ <module>hello.impl.annotation</module>
+ <module>hello.client.annotation</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>java6</id>
+ <activation>
+ <jdk>1.6</jdk>
+ </activation>
+ <modules>
+ <module>hello.impl.annotation</module>
+ <module>hello.client.annotation</module>
+ </modules>
+ </profile>
+ </profiles>
+</project>
\ No newline at end of file