diff --git a/pom.xml b/pom.xml
index 69b0fb1..6e04c00 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,6 +21,7 @@
rome-fetcher
rome-modules
rome-opml
+ rome-osgi-test
rome-propono
rome-utils
@@ -133,6 +134,19 @@
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+ 2.19.1
+
+
+
+ integration-test
+ verify
+
+
+
+
diff --git a/rome-osgi-test/pom.xml b/rome-osgi-test/pom.xml
new file mode 100644
index 0000000..7926352
--- /dev/null
+++ b/rome-osgi-test/pom.xml
@@ -0,0 +1,101 @@
+
+
+ 4.0.0
+
+
+ com.rometools
+ rome-parent
+ 1.6.0-SNAPSHOT
+
+
+ rome-osgi-test
+
+
+
+ com.rometools
+ rome
+ test
+
+
+ com.rometools
+ rome-modules
+ test
+
+
+ com.rometools
+ rome-fetcher
+ test
+
+
+ junit
+ junit
+ test
+
+
+ org.apache.felix
+ org.apache.felix.framework
+ 5.4.0
+ test
+
+
+ org.ops4j.pax.exam
+ pax-exam-container-native
+ 4.8.0
+ test
+
+
+ org.ops4j.pax.exam
+ pax-exam-junit4
+ 4.8.0
+ test
+
+
+ org.ops4j.pax.exam
+ pax-exam-link-mvn
+ 4.8.0
+ test
+
+
+ org.ops4j.pax.url
+ pax-url-wrap
+ 2.4.5
+ test
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-deploy-plugin
+
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 2.10
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+ ${project.build.directory}/lib
+ true
+
+
+
+
+
+
+
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreIT.java
new file mode 100644
index 0000000..486bbce
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreIT.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import static org.junit.Assert.assertEquals;
+
+import com.rometools.rome.feed.synd.SyndFeed;
+import com.rometools.rome.io.SyndFeedInput;
+import com.rometools.rome.io.XmlReader;
+
+import org.junit.Test;
+
+public class CoreIT {
+
+ @Test
+ public void test() throws Exception {
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("core.xml"));
+ final SyndFeed feed = new SyndFeedInput().build(reader);
+ assertEquals("test-title", feed.getTitle());
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreOsgiIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreOsgiIT.java
new file mode 100644
index 0000000..0e0c90d
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CoreOsgiIT.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+@RunWith(PaxExam.class)
+public class CoreOsgiIT extends CoreIT {
+
+ @Configuration
+ public Option[] configuration() throws IOException, URISyntaxException {
+ return CoreOptions.options(
+ CoreOptions.junitBundles(),
+ CoreOptions.wrappedBundle("file:target/lib/jdom2.jar"),
+ CoreOptions.bundle("file:target/lib/rome.jar"));
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModule.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModule.java
new file mode 100644
index 0000000..8d1826a
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModule.java
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import com.rometools.rome.feed.CopyFrom;
+import com.rometools.rome.feed.module.Module;
+import com.rometools.rome.io.ModuleParser;
+
+import org.jdom2.Element;
+import org.jdom2.Namespace;
+
+import java.util.Locale;
+
+public class CustomModule implements Module {
+
+ public static final String URI = "http://example.org";
+
+ private String title;
+
+ public CustomModule(String title) {
+ this.title = title;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
+ public String getUri() {
+ return URI;
+ }
+
+ @Override
+ public Class extends CopyFrom> getInterface() {
+ return getClass();
+ }
+
+ @Override
+ public void copyFrom(CopyFrom obj) {
+ title = ((CustomModule) obj).title;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
+ public static class Parser implements ModuleParser {
+
+ public String getNamespaceUri() {
+ return URI;
+ }
+
+ public Module parse(Element element, Locale locale) {
+ return new CustomModule(element.getChildText("title", Namespace.getNamespace(getNamespaceUri())));
+ }
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleIT.java
new file mode 100644
index 0000000..c5baf02
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleIT.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.rometools.rome.feed.synd.SyndFeed;
+import com.rometools.rome.io.SyndFeedInput;
+import com.rometools.rome.io.XmlReader;
+
+import org.junit.Test;
+
+public class CustomModuleIT {
+
+ @Test
+ public void testCustomModule() throws Exception {
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("custom-module.xml"));
+ final SyndFeed feed = new SyndFeedInput().build(reader);
+
+ final CustomModule customModule = (CustomModule) feed.getModule(CustomModule.URI);
+
+ assertNotNull(customModule);
+ assertEquals("test-title", customModule.getTitle());
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleOsgiIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleOsgiIT.java
new file mode 100644
index 0000000..03fd068
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/CustomModuleOsgiIT.java
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.rometools.rome.feed.impl.ConfigurableClassLoader;
+import com.rometools.rome.feed.synd.SyndFeed;
+import com.rometools.rome.io.SyndFeedInput;
+import com.rometools.rome.io.XmlReader;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+
+@RunWith(PaxExam.class)
+public class CustomModuleOsgiIT {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Configuration
+ public Option[] configuration() throws IOException, URISyntaxException {
+ return CoreOptions.options(
+ CoreOptions.junitBundles(),
+ CoreOptions.wrappedBundle("file:target/lib/jdom2.jar"),
+ CoreOptions.bundle("file:target/lib/rome.jar"));
+ }
+
+ @Test
+ public void testDefaultClassLoader() throws Exception {
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("custom-module.xml"));
+ final SyndFeed feed = new SyndFeedInput().build(reader);
+
+ final CustomModule customModule = (CustomModule) feed.getModule(CustomModule.URI);
+
+ assertNull(customModule);
+ }
+
+ @Test
+ public void testConfigurableClassLoader() throws Exception {
+ ConfigurableClassLoader.INSTANCE.setClassLoader(getClass().getClassLoader());
+
+ expectedException.expect(ExceptionInInitializerError.class);
+
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("custom-module.xml"));
+ new SyndFeedInput().build(reader);
+ }
+
+ @Test
+ public void testConfigurableCompositeClassLoader() throws Exception {
+ final ClassLoader thisClassLoader = getClass().getClassLoader();
+ final ClassLoader romeClassLoader = ConfigurableClassLoader.INSTANCE.getClassLoader();
+ ConfigurableClassLoader.INSTANCE.setClassLoader(new CompositeClassLoader(thisClassLoader, romeClassLoader));
+
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("custom-module.xml"));
+ final SyndFeed feed = new SyndFeedInput().build(reader);
+
+ final CustomModule customModule = (CustomModule) feed.getModule(CustomModule.URI);
+
+ assertNotNull(customModule);
+ assertEquals("test-title", customModule.getTitle());
+ }
+
+ public static class CompositeClassLoader extends ClassLoader {
+
+ private ClassLoader delegate;
+
+ public CompositeClassLoader(ClassLoader delegate, ClassLoader parent) {
+ super(parent);
+ this.delegate = delegate;
+ }
+
+ @Override
+ protected final Class> findClass(String name) throws ClassNotFoundException {
+ return delegate.loadClass(name);
+ }
+
+ @Override
+ protected final URL findResource(String name) {
+ return delegate.getResource(name);
+ }
+
+ @Override
+ protected final Enumeration findResources(String name) throws IOException {
+ return delegate.getResources(name);
+ }
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherIT.java
new file mode 100644
index 0000000..3f01375
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherIT.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import static org.junit.Assert.assertEquals;
+
+import com.rometools.fetcher.FeedFetcher;
+import com.rometools.fetcher.impl.FeedFetcherCache;
+import com.rometools.fetcher.impl.HashMapFeedInfoCache;
+import com.rometools.fetcher.impl.HttpURLFeedFetcher;
+import com.rometools.rome.feed.synd.SyndFeed;
+
+import org.junit.Test;
+
+import java.net.URL;
+
+public class FetcherIT {
+
+ @Test
+ public void test() throws Exception {
+ FeedFetcherCache cache = HashMapFeedInfoCache.getInstance();
+ FeedFetcher fetcher = new HttpURLFeedFetcher(cache);
+ SyndFeed feed = fetcher.retrieveFeed(new URL("http://www.w3.org/blog/news/feed/atom"));
+
+ assertEquals("W3C News", feed.getTitle());
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherOsgiIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherOsgiIT.java
new file mode 100644
index 0000000..95f1ead
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/FetcherOsgiIT.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+@RunWith(PaxExam.class)
+public class FetcherOsgiIT extends FetcherIT {
+
+ @Configuration
+ public Option[] configuration() throws IOException, URISyntaxException {
+ return CoreOptions.options(
+ CoreOptions.junitBundles(),
+ CoreOptions.wrappedBundle("file:target/lib/jdom2.jar"),
+ CoreOptions.bundle("file:target/lib/rome.jar"),
+ CoreOptions.bundle("file:target/lib/rome-fetcher.jar"));
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesIT.java
new file mode 100644
index 0000000..40cff56
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesIT.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.rometools.modules.itunes.FeedInformation;
+import com.rometools.modules.itunes.ITunes;
+import com.rometools.rome.feed.synd.SyndFeed;
+import com.rometools.rome.io.SyndFeedInput;
+import com.rometools.rome.io.XmlReader;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+public class ModulesIT {
+
+ @Test
+ public void test() throws Exception {
+ final XmlReader reader = new XmlReader(getClass().getResourceAsStream("modules.xml"));
+ final SyndFeed feed = new SyndFeedInput().build(reader);
+ final FeedInformation itunes = (FeedInformation) feed.getModule(ITunes.URI);
+
+ assertNotNull(itunes);
+ assertEquals("test-author", itunes.getAuthor());
+ }
+}
diff --git a/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesOsgiIT.java b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesOsgiIT.java
new file mode 100644
index 0000000..ab2f1ed
--- /dev/null
+++ b/rome-osgi-test/src/test/java/com/rometools/rome/osgi/ModulesOsgiIT.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package com.rometools.rome.osgi;
+
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+@RunWith(PaxExam.class)
+public class ModulesOsgiIT extends ModulesIT {
+
+ @Configuration
+ public Option[] configuration() throws IOException, URISyntaxException {
+ return CoreOptions.options(
+ CoreOptions.junitBundles(),
+ CoreOptions.wrappedBundle("file:target/lib/jdom2.jar"),
+ CoreOptions.bundle("file:target/lib/rome-modules.jar"));
+ }
+}
diff --git a/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/core.xml b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/core.xml
new file mode 100644
index 0000000..472e57a
--- /dev/null
+++ b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/core.xml
@@ -0,0 +1,6 @@
+
+
+
+ test-title
+
+
diff --git a/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/custom-module.xml b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/custom-module.xml
new file mode 100644
index 0000000..350dadf
--- /dev/null
+++ b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/custom-module.xml
@@ -0,0 +1,6 @@
+
+
+
+ test-title
+
+
diff --git a/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/modules.xml b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/modules.xml
new file mode 100644
index 0000000..f9a234b
--- /dev/null
+++ b/rome-osgi-test/src/test/resources/com/rometools/rome/osgi/modules.xml
@@ -0,0 +1,6 @@
+
+
+
+ test-author
+
+
diff --git a/rome-osgi-test/src/test/resources/rome.properties b/rome-osgi-test/src/test/resources/rome.properties
new file mode 100644
index 0000000..f132a71
--- /dev/null
+++ b/rome-osgi-test/src/test/resources/rome.properties
@@ -0,0 +1 @@
+rss_2.0.feed.ModuleParser.classes=com.rometools.rome.osgi.CustomModule$Parser