You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2022/11/15 13:22:10 UTC
[sling-org-apache-sling-tooling-support-source] branch master updated: SLING-11676 Migrate to OSGi Whiteboard (#3)
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tooling-support-source.git
The following commit(s) were added to refs/heads/master by this push:
new 21ca1c3 SLING-11676 Migrate to OSGi Whiteboard (#3)
21ca1c3 is described below
commit 21ca1c323fefe6b708638737b861e2f336923d81
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Tue Nov 15 14:22:05 2022 +0100
SLING-11676 Migrate to OSGi Whiteboard (#3)
Add tests
Update dependencies
No longer refresh packages by default
---
pom.xml | 57 ++++++--
.../impl/FelixJettySourceReferenceFinder.java | 37 ++---
.../source/impl/SourceReferencesServlet.java | 151 ++++++++++-----------
.../support/source/impl/PomHandlerTest.java | 15 +-
.../source/impl/SourceReferencesServletTest.java | 77 +++++++++++
.../support/source/impl/expectedBundleSource.json | 1 +
.../tooling/support/source/impl/pom.properties | 3 +
7 files changed, 222 insertions(+), 119 deletions(-)
diff --git a/pom.xml b/pom.xml
index abc448f..708ef0c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,14 +23,14 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling-bundle-parent</artifactId>
- <version>48</version>
+ <version>49</version>
</parent>
<artifactId>org.apache.sling.tooling.support.source</artifactId>
<version>1.0.5-SNAPSHOT</version>
<name>Apache Sling Tooling Support Source</name>
-
+ <description>Outputs source information about bundles running in a Sling instance</description>
<scm>
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tooling-support-source.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tooling-support-source.git</developerConnection>
@@ -40,7 +40,12 @@
<dependencies>
<dependency>
<groupId>org.osgi</groupId>
- <artifactId>osgi.core</artifactId>
+ <artifactId>org.osgi.framework</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.resource</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
@@ -48,15 +53,21 @@
<artifactId>org.osgi.service.component.annotations</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.service.http.whiteboard</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.utils</artifactId>
- <version>1.9.0</version>
+ <version>1.11.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
@@ -64,15 +75,41 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <version>5.9.1</version>
<scope>test</scope>
</dependency>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>2.4</version>
- <scope>provided</scope>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>4.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-junit-jupiter</artifactId>
+ <version>4.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes combine.children="append">
+ <exclude>src/test/resources/**/*.properties</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/src/main/java/org/apache/sling/tooling/support/source/impl/FelixJettySourceReferenceFinder.java b/src/main/java/org/apache/sling/tooling/support/source/impl/FelixJettySourceReferenceFinder.java
index e9be471..46c9865 100644
--- a/src/main/java/org/apache/sling/tooling/support/source/impl/FelixJettySourceReferenceFinder.java
+++ b/src/main/java/org/apache/sling/tooling/support/source/impl/FelixJettySourceReferenceFinder.java
@@ -27,7 +27,6 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
-import org.apache.commons.io.IOUtils;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,12 +36,16 @@ import org.xml.sax.SAXException;
public class FelixJettySourceReferenceFinder implements SourceReferenceFinder {
private final Logger log = LoggerFactory.getLogger(getClass());
-
+ private final SAXParserFactory parserFactory;
+
+ public FelixJettySourceReferenceFinder() {
+ parserFactory = SAXParserFactory.newInstance();
+ }
@Override
public List<SourceReference> findSourceReferences(Bundle bundle) throws SourceReferenceException {
// the org.apache.felix.http.jetty bundle does not retain references to the source bundles
// so infer them from the X-Jetty-Version header
- if ( !bundle.getSymbolicName().equals("org.apache.felix.http.jetty")) {
+ if (!"org.apache.felix.http.jetty".equals(bundle.getSymbolicName())) {
return Collections.emptyList();
}
@@ -54,30 +57,14 @@ public class FelixJettySourceReferenceFinder implements SourceReferenceFinder {
Enumeration<URL> entries = bundle.findEntries("META-INF/maven", "pom.xml", true);
if (entries != null && entries.hasMoreElements()) {
URL entry = entries.nextElement();
- InputStream pom = null;
- try {
- pom = entry.openStream();
-
- try {
- SAXParserFactory parserFactory = SAXParserFactory.newInstance();
- SAXParser parser = parserFactory.newSAXParser();
- PomHandler handler = new PomHandler((String) jettyVersion);
- parser.parse(new InputSource(pom), handler);
-
- return handler.getReferences();
- } catch (SAXException e) {
- throw new SourceReferenceException(e);
- } catch (ParserConfigurationException e) {
- throw new SourceReferenceException(e);
- } finally {
- IOUtils.closeQuietly(pom);
- }
- } catch (IOException e) {
+ try (InputStream pom = entry.openStream()) {
+ SAXParser parser = parserFactory.newSAXParser();
+ PomHandler handler = new PomHandler((String) jettyVersion);
+ parser.parse(new InputSource(pom), handler);
+ return handler.getReferences();
+ } catch (SAXException|ParserConfigurationException|IOException e) {
throw new SourceReferenceException(e);
- } finally {
- IOUtils.closeQuietly(pom);
}
-
} else {
log.warn("Could not find a pom.xml in bundle '{}'!", bundle);
return Collections.emptyList();
diff --git a/src/main/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServlet.java b/src/main/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServlet.java
index bf9d570..92626ef 100644
--- a/src/main/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServlet.java
+++ b/src/main/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServlet.java
@@ -18,6 +18,7 @@ package org.apache.sling.tooling.support.source.impl;
import java.io.IOException;
import java.io.InputStream;
+import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -33,29 +34,27 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.apache.commons.io.IOUtils;
import org.apache.felix.utils.json.JSONWriter;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
+import org.osgi.service.http.whiteboard.propertytypes.HttpWhiteboardServletPattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The <tt>SourceReferencesServlet</tt> infers and outputs source information about bundles running a Sling instance
*/
-@Component(service = Servlet.class,
- property = {
- Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
- "alias=/system/sling/tooling/sourceReferences.json"
- })
+@Component(service = Servlet.class)
+@HttpWhiteboardServletPattern("/system/sling/tooling/sourceReferences.json")
public class SourceReferencesServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
- private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final Logger log = LoggerFactory.getLogger(SourceReferencesServlet.class);
private static final String KEY_TYPE = "__type__";
private static final String KEY_GROUP_ID = "groupId";
@@ -67,10 +66,11 @@ public class SourceReferencesServlet extends HttpServlet {
private static final String FELIX_FW_GROUP_ID = "org.apache.felix";
private static final String FELIX_FW_ARTIFACT_ID = "org.apache.felix.framework";
- private ComponentContext ctx;
- private List<SourceReferenceFinder> finders;
+ private final BundleContext ctx;
+ private final List<SourceReferenceFinder> finders;
- protected void activate(ComponentContext ctx) {
+ @Activate
+ public SourceReferencesServlet(BundleContext ctx) {
this.ctx = ctx;
finders = new ArrayList<>();
@@ -81,87 +81,87 @@ public class SourceReferencesServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
response.setContentType("application/json");
+ writeBundleSourceJson(response.getWriter(), ctx.getBundles());
+ } catch (IOException e) {
+ throw new ServletException(e);
+ }
+ }
- final JSONWriter w = new JSONWriter(response.getWriter());
- w.array();
+ void writeBundleSourceJson(Writer writer, Bundle... bundles) throws IOException {
+ final JSONWriter w = new JSONWriter(writer);
+ w.array();
- for ( Bundle bundle : ctx.getBundleContext().getBundles() ) {
+ for (Bundle bundle : bundles) {
- // skip bundle if it is a fragment (http://stackoverflow.com/questions/11655295/using-the-osgi-api-how-do-i-find-out-if-a-given-bundle-is-a-fragment)
- if ((bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
- log.debug("Skip bundle '{}' because it is a fragment", bundle);
- // source references should only be listed with the host bundle
- continue;
- }
- Object bundleVersion = bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+ // skip bundle if it is a fragment (http://stackoverflow.com/questions/11655295/using-the-osgi-api-how-do-i-find-out-if-a-given-bundle-is-a-fragment)
+ if ((bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) {
+ log.debug("Skip bundle '{}' because it is a fragment", bundle);
+ // source references should only be listed with the host bundle
+ continue;
+ }
+ Object bundleVersion = bundle.getVersion();
- w.object();
- w.key(Constants.BUNDLE_SYMBOLICNAME);
- w.value(bundle.getSymbolicName());
- w.key(Constants.BUNDLE_VERSION);
- w.value(bundleVersion);
+ w.object();
+ w.key(Constants.BUNDLE_SYMBOLICNAME);
+ w.value(bundle.getSymbolicName());
+ w.key(Constants.BUNDLE_VERSION);
+ w.value(bundleVersion);
- w.key("sourceReferences");
- w.array();
+ w.key("sourceReferences");
+ w.array();
- // the system bundle is embedded by the launchpad jar so we need special handling
- // since the pom.properties file is not located in the bundle
- if ( bundle.getBundleId() == 0 && bundle.getSymbolicName().equals(FELIX_FW_ARTIFACT_ID) ) {
- writeMavenGav(w, FELIX_FW_GROUP_ID, FELIX_FW_ARTIFACT_ID, (String) bundleVersion);
- }
+ // the system bundle is embedded by the launchpad jar so we need special handling
+ // since the pom.properties file is not located in the bundle
+ if ( bundle.getBundleId() == Constants.SYSTEM_BUNDLE_ID && FELIX_FW_ARTIFACT_ID.equals(bundle.getSymbolicName()) ) {
+ writeMavenGav(w, FELIX_FW_GROUP_ID, FELIX_FW_ARTIFACT_ID, (String) bundleVersion);
+ }
- // look for pom.properties in the bundle ( the original bundle, fragments )
- collectMavenSourceReferences(w, bundle);
+ // look for pom.properties in the bundle ( the original bundle, fragments )
+ collectMavenSourceReferences(w, bundle);
- // look for pom.properties in jars embedded in the bundle
- for ( String jar : getEmbeddedJars(bundle)) {
- URL entry = bundle.getEntry(jar);
- // incorrect or inaccessible entry
- if ( entry == null ) {
- continue;
- }
- collectMavenSourceRerefences(w, entry);
+ // look for pom.properties in jars embedded in the bundle
+ for ( String jar : getEmbeddedJars(bundle)) {
+ URL entry = bundle.getEntry(jar);
+ // incorrect or inaccessible entry
+ if ( entry == null ) {
+ continue;
}
+ collectMavenSourceReferences(w, entry);
+ }
- // query custom finders for source references
- for ( SourceReferenceFinder finder : finders ) {
- try {
- for ( SourceReference reference : finder.findSourceReferences(bundle)) {
- log.debug("{} found reference {}:{}:{} in {}", new Object[] { finder, reference.getGroupId(), reference.getArtifactId(), reference.getVersion(), bundle});
- writeMavenGav(w, reference.getGroupId(), reference.getArtifactId(), reference.getVersion());
- }
- } catch (SourceReferenceException e) {
- log.warn(finder + " execution did not complete normally for " + bundle, e);
+ // query custom finders for source references
+ for ( SourceReferenceFinder finder : finders ) {
+ try {
+ for ( SourceReference reference : finder.findSourceReferences(bundle)) {
+ log.debug("{} found reference {}:{}:{} in {}", new Object[] { finder, reference.getGroupId(), reference.getArtifactId(), reference.getVersion(), bundle});
+ writeMavenGav(w, reference.getGroupId(), reference.getArtifactId(), reference.getVersion());
}
+ } catch (SourceReferenceException e) {
+ log.warn(finder + " execution did not complete normally for " + bundle, e);
}
-
- w.endArray();
- w.endObject();
}
w.endArray();
- } catch (IOException e) {
- throw new ServletException(e);
+ w.endObject();
}
+
+ w.endArray();
}
- private void collectMavenSourceReferences(JSONWriter w, Bundle bundle) throws IOException {
+ private static void collectMavenSourceReferences(JSONWriter w, Bundle bundle) throws IOException {
Enumeration<?> entries = bundle.findEntries("/META-INF/maven", "pom.properties", true);
while ( entries != null && entries.hasMoreElements()) {
URL entry = (URL) entries.nextElement();
- InputStream in = entry.openStream();
- try {
+ try (InputStream in = entry.openStream()) {
writeMavenGav(w, in);
- } finally {
- IOUtils.closeQuietly(in);
}
}
}
- private void writeMavenGav(JSONWriter w, String groupId, String artifactId, String version) throws IOException {
+ private static void writeMavenGav(JSONWriter w, String groupId, String artifactId, String version) throws IOException {
w.object();
w.key(KEY_TYPE).value(VALUE_TYPE_MAVEN);
@@ -171,7 +171,7 @@ public class SourceReferencesServlet extends HttpServlet {
w.endObject();
}
- private void writeMavenGav(JSONWriter w, InputStream in) throws IOException {
+ private static void writeMavenGav(JSONWriter w, InputStream in) throws IOException {
Properties p = new Properties();
p.load(in);
@@ -183,18 +183,18 @@ public class SourceReferencesServlet extends HttpServlet {
w.endObject();
}
- private List<String> getEmbeddedJars(Bundle bundle) {
+ private static List<String> getEmbeddedJars(Bundle bundle) {
- String classPath = (String) bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
- if ( classPath == null ) {
+ String classPath = bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
+ if (classPath == null) {
return Collections.emptyList();
}
List<String> embeddedJars = new ArrayList<>();
String[] classPathEntryNames = classPath.split("\\,");
- for ( String classPathEntry : classPathEntryNames ) {
- if ( classPathEntry.endsWith(".jar")) {
+ for (String classPathEntry : classPathEntryNames) {
+ if (classPathEntry.endsWith(".jar")) {
embeddedJars.add(classPathEntry);
}
}
@@ -202,20 +202,17 @@ public class SourceReferencesServlet extends HttpServlet {
return embeddedJars;
}
- private void collectMavenSourceRerefences(JSONWriter w, URL entry) throws IOException {
+ private static void collectMavenSourceReferences(JSONWriter w, URL entry) throws IOException {
- InputStream wrappedIn = entry.openStream();
- try {
- JarInputStream jarIs = new JarInputStream(wrappedIn);
+ try (InputStream wrappedIn = entry.openStream();
+ JarInputStream jarIs = new JarInputStream(wrappedIn)) {
JarEntry jarEntry;
- while ( ( jarEntry = jarIs.getNextJarEntry()) != null ) {
+ while ((jarEntry = jarIs.getNextJarEntry()) != null) {
String entryName = jarEntry.getName();
- if ( entryName.startsWith("META-INF/maven/") && entryName.endsWith("/pom.properties")) {
+ if (entryName.startsWith("META-INF/maven/") && entryName.endsWith("/pom.properties")) {
writeMavenGav(w, jarIs);
}
}
- } finally {
- IOUtils.closeQuietly(wrappedIn);
}
}
diff --git a/src/test/java/org/apache/sling/tooling/support/source/impl/PomHandlerTest.java b/src/test/java/org/apache/sling/tooling/support/source/impl/PomHandlerTest.java
index 15b73e0..11b553b 100644
--- a/src/test/java/org/apache/sling/tooling/support/source/impl/PomHandlerTest.java
+++ b/src/test/java/org/apache/sling/tooling/support/source/impl/PomHandlerTest.java
@@ -16,26 +16,27 @@
*/
package org.apache.sling.tooling.support.source.impl;
-import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
+import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
import org.xml.sax.SAXException;
-public class PomHandlerTest {
+class PomHandlerTest {
@Test
- public void parseJettyPom() throws SAXException, IOException, ParserConfigurationException {
+ void parseJettyPom() throws SAXException, IOException, ParserConfigurationException {
PomHandler handler = new PomHandler("9.2.4");
-
- SAXParserFactory.newInstance().newSAXParser().parse(getClass().getResourceAsStream("felix-pom.xml"), handler);
-
+ try (InputStream input = getClass().getResourceAsStream("felix-pom.xml")) {
+ SAXParserFactory.newInstance().newSAXParser().parse(input, handler);
+ }
List<SourceReference> references = handler.getReferences();
assertEquals(10, references.size());
diff --git a/src/test/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServletTest.java b/src/test/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServletTest.java
new file mode 100644
index 0000000..40da3b4
--- /dev/null
+++ b/src/test/java/org/apache/sling/tooling/support/source/impl/SourceReferencesServletTest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tooling.support.source.impl;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleRevision;
+
+@ExtendWith(MockitoExtension.class)
+class SourceReferencesServletTest {
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void testWriteBundleSourceJson() throws IOException {
+ Bundle bundle1 = Mockito.mock(Bundle.class);
+ BundleRevision bundleRevision = Mockito.mock(BundleRevision.class);
+ Mockito.when(bundle1.adapt(BundleRevision.class)).thenReturn(bundleRevision);
+ Dictionary<String, String> dictionary = Mockito.mock(Dictionary.class);
+ Mockito.when(bundle1.getHeaders()).thenReturn(dictionary);
+ BundleContext ctx = Mockito.mock(BundleContext.class);
+ URLConnection mockUrlConnection = Mockito.mock(URLConnection.class);
+ URLStreamHandler stubUrlHandler = new URLStreamHandler() {
+ @Override
+ protected URLConnection openConnection(URL u) throws IOException {
+ return mockUrlConnection;
+ }
+ };
+ URL url = new URL("foo", "bar", 99, "/foobar", stubUrlHandler);
+ Mockito.when(mockUrlConnection.getInputStream()).thenReturn(this.getClass().getResourceAsStream("pom.properties"));
+ Mockito.when(bundle1.findEntries("/META-INF/maven", "pom.properties", true)).thenReturn(Collections.enumeration(Collections.singleton(url)));
+
+ SourceReferencesServlet servlet = new SourceReferencesServlet(ctx);
+ StringWriter writer = new StringWriter();
+ servlet.writeBundleSourceJson(writer, bundle1);
+ String expectedOutput;
+ try (InputStream input = this.getClass().getResourceAsStream("expectedBundleSource.json");
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8))) {
+ // normalize line separators to system default
+ expectedOutput = reader.lines().collect(Collectors.joining(System.lineSeparator()));
+ }
+ assertEquals(expectedOutput, writer.toString());
+ }
+
+}
diff --git a/src/test/resources/org/apache/sling/tooling/support/source/impl/expectedBundleSource.json b/src/test/resources/org/apache/sling/tooling/support/source/impl/expectedBundleSource.json
new file mode 100644
index 0000000..ca01f19
--- /dev/null
+++ b/src/test/resources/org/apache/sling/tooling/support/source/impl/expectedBundleSource.json
@@ -0,0 +1 @@
+[{"Bundle-SymbolicName":null,"Bundle-Version":null,"sourceReferences":[{"__type__":"maven","groupId":"com.example.myGroupId","artifactId":"myArtifactId","version":"1.0.0"}]}]
\ No newline at end of file
diff --git a/src/test/resources/org/apache/sling/tooling/support/source/impl/pom.properties b/src/test/resources/org/apache/sling/tooling/support/source/impl/pom.properties
new file mode 100644
index 0000000..8377447
--- /dev/null
+++ b/src/test/resources/org/apache/sling/tooling/support/source/impl/pom.properties
@@ -0,0 +1,3 @@
+groupId=com.example.myGroupId
+artifactId=myArtifactId
+version=1.0.0
\ No newline at end of file