This is an automated email from the ASF dual-hosted git repository.
enorman pushed a commit to branch master
in repository
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-bundleresource-impl.git
The following commit(s) were added to refs/heads/master by this push:
new b0ec7d4 SLING-13028 Resolve various sonar warnings (#9)
b0ec7d4 is described below
commit b0ec7d436ea33dad6ec5b92457771b39239bdccb
Author: Eric Norman <[email protected]>
AuthorDate: Thu Jan 29 15:18:24 2026 -0800
SLING-13028 Resolve various sonar warnings (#9)
---
.../sling/bundleresource/impl/Activator.java | 29 ++---
.../sling/bundleresource/impl/BundleResource.java | 26 +++--
.../bundleresource/impl/BundleResourceCache.java | 24 +++-
.../impl/BundleResourceProvider.java | 24 ++--
.../impl/BundleResourceURLConnection.java | 4 +
.../impl/BundleResourceWebConsolePlugin.java | 90 +++++++--------
.../sling/bundleresource/impl/PathMapping.java | 12 +-
.../sling/bundleresource/impl/ActivatorTest.java | 70 ++++++++++++
.../bundleresource/impl/BundleResourceMapTest.java | 124 +++++++++++++++++++++
.../impl/BundleResourceProviderTest.java | 20 ++--
.../bundleresource/impl/BundleResourceTest.java | 12 +-
.../impl/BundleResourceWebConsolePluginTest.java | 20 ++++
.../bundleresource/impl/NoBundleContextTest.java | 11 +-
.../sling/bundleresource/impl/PathMappingTest.java | 6 +-
14 files changed, 355 insertions(+), 117 deletions(-)
diff --git a/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
b/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
index 58f614d..67c5bc2 100644
--- a/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
+++ b/src/main/java/org/apache/sling/bundleresource/impl/Activator.java
@@ -93,16 +93,13 @@ public class Activator implements BundleActivator,
BundleListener {
*/
@Override
public void bundleChanged(final BundleEvent event) {
- switch (event.getType()) {
- case BundleEvent.STARTED:
- // register resource provider for the started bundle
- addBundleResourceProvider(event.getBundle());
- break;
-
- case BundleEvent.STOPPED:
- // remove resource provider after the bundle has stopped
- removeBundleResourceProvider(event.getBundle());
- break;
+ final int type = event.getType();
+ if (BundleEvent.STARTED == type) {
+ // register resource provider for the started bundle
+ addBundleResourceProvider(event.getBundle());
+ } else if (BundleEvent.STOPPED == type) {
+ // remove resource provider after the bundle has stopped
+ removeBundleResourceProvider(event.getBundle());
}
}
@@ -120,8 +117,10 @@ public class Activator implements BundleActivator,
BundleListener {
if (prefixes != null) {
log.debug(
"addBundleResourceProvider: Registering resources
'{}' for bundle {}:{} ({}) as service ",
- new Object[] {prefixes, bundle.getSymbolicName(),
bundle.getVersion(), bundle.getBundleId()
- });
+ prefixes,
+ bundle.getSymbolicName(),
+ bundle.getVersion(),
+ bundle.getBundleId());
final PathMapping[] roots = PathMapping.getRoots(prefixes);
providers = new BundleResourceProvider[roots.length];
@@ -143,7 +142,7 @@ public class Activator implements BundleActivator,
BundleListener {
log.debug("addBundleResourceProvider: Service ID = {}",
id);
}
}
- } catch (final Throwable t) {
+ } catch (final Throwable t) { // NOSONAR
log.error(
"activate: Problem while registering bundle resources for
bundle " + bundle.getSymbolicName() + ":"
+ bundle.getVersion() + " (" +
bundle.getBundleId() + ")",
@@ -159,7 +158,9 @@ public class Activator implements BundleActivator,
BundleListener {
if (brp != null) {
log.debug(
"removeBundleResourceProvider: Unregistering resources for
bundle {}:{} ({})",
- new Object[] {bundle.getSymbolicName(),
bundle.getVersion(), bundle.getBundleId()});
+ bundle.getSymbolicName(),
+ bundle.getVersion(),
+ bundle.getBundleId());
for (final BundleResourceProvider provider : brp) {
try {
provider.unregisterService();
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java
index 1c69e03..f1fae21 100644
--- a/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java
+++ b/src/main/java/org/apache/sling/bundleresource/impl/BundleResource.java
@@ -32,6 +32,7 @@ import jakarta.json.Json;
import jakarta.json.JsonArray;
import jakarta.json.JsonNumber;
import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
import jakarta.json.JsonString;
import jakarta.json.JsonValue;
import org.apache.sling.api.resource.AbstractResource;
@@ -141,10 +142,12 @@ public class BundleResource extends AbstractResource {
try {
final URL url = this.cache.getEntry(propsPath);
if (url != null) {
- final JsonObject obj =
-
Json.createReader(url.openStream()).readObject();
+ final JsonObject obj;
+ try (JsonReader reader =
Json.createReader(url.openStream())) {
+ obj = reader.readObject();
+ }
for (final Map.Entry<String, JsonValue> entry :
obj.entrySet()) {
- final Object value = getValue(entry.getValue(),
true);
+ final Object value = getValue(entry.getValue());
if (value != null) {
if (value instanceof Map) {
if (children == null) {
@@ -184,17 +187,18 @@ public class BundleResource extends AbstractResource {
resources = ((BundleResource) result).subResources;
} else {
result = null;
- break;
}
} else {
result = null;
+ }
+ if (result == null) {
break;
}
}
return result;
}
- private static Object getValue(final JsonValue value, final boolean
topLevel) {
+ private static Object getValue(final JsonValue value) {
switch (value.getValueType()) {
// type NULL -> return null
case NULL:
@@ -218,7 +222,7 @@ public class BundleResource extends AbstractResource {
case ARRAY:
final List<Object> array = new ArrayList<>();
for (final JsonValue x : ((JsonArray) value)) {
- array.add(getValue(x, false));
+ array.add(getValue(x));
}
return array;
// type OBJECT -> return map
@@ -226,7 +230,7 @@ public class BundleResource extends AbstractResource {
final Map<String, Object> map = new HashMap<>();
final JsonObject obj = (JsonObject) value;
for (final Map.Entry<String, JsonValue> entry :
obj.entrySet()) {
- map.put(entry.getKey(), getValue(entry.getValue(), false));
+ map.put(entry.getKey(), getValue(entry.getValue()));
}
return map;
}
@@ -264,13 +268,13 @@ public class BundleResource extends AbstractResource {
@Override
@SuppressWarnings("unchecked")
- public <Type> Type adaptTo(Class<Type> type) {
+ public <T> T adaptTo(Class<T> type) {
if (type == InputStream.class) {
- return (Type) getInputStream(); // unchecked cast
+ return (T) getInputStream(); // unchecked cast
} else if (type == URL.class) {
- return (Type) getURL(); // unchecked cast
+ return (T) getURL(); // unchecked cast
} else if (type == ValueMap.class) {
- return (Type) valueMap; // unchecked cast
+ return (T) valueMap; // unchecked cast
}
// fall back to adapter factories
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceCache.java
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceCache.java
index 11e0bd3..66933f5 100644
---
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceCache.java
+++
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceCache.java
@@ -225,7 +225,7 @@ class BundleResourceCache {
* {@link #removeEldestEntry(Entry)} method to implement the size limit,
* which is set in the constructor.
*/
- private static class BundleResourceMap<K, V> extends LinkedHashMap<String,
V> {
+ private static class BundleResourceMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = 7455098291380945276L;
@@ -251,7 +251,7 @@ class BundleResourceCache {
// we need the access-order to implement the LRU mechanism
super(8, 0.75f, true);
- // normalize size to a possitive number
+ // normalize size to a positive number
if (limit <= 0) {
limit = DEFAULT_LIMIT;
}
@@ -264,8 +264,26 @@ class BundleResourceCache {
* map exceeds the configured limit.
*/
@Override
- protected boolean removeEldestEntry(Entry<String, V> eldest) {
+ protected boolean removeEldestEntry(Entry<K, V> eldest) {
return size() > limit;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + limit;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!super.equals(obj)) return false;
+ if (getClass() != obj.getClass()) return false;
+ @SuppressWarnings("rawtypes")
+ BundleResourceMap other = (BundleResourceMap) obj;
+ return limit == other.limit;
+ }
}
}
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
index 5fae749..b988fef 100644
---
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
+++
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceProvider.java
@@ -44,7 +44,7 @@ public class BundleResourceProvider extends
ResourceProvider<Object> {
private final PathMapping root;
@SuppressWarnings("rawtypes")
- private volatile ServiceRegistration<ResourceProvider> serviceRegistration;
+ private ServiceRegistration<ResourceProvider> serviceRegistration;
/**
* Creates Bundle resource provider accessing entries in the given Bundle
an
@@ -60,10 +60,10 @@ public class BundleResourceProvider extends
ResourceProvider<Object> {
long registerService() {
final Bundle bundle = this.cache.getBundle();
- final Dictionary<String, Object> props = new Hashtable<>();
+ final Dictionary<String, Object> props = new Hashtable<>(); // NOSONAR
props.put(
Constants.SERVICE_DESCRIPTION,
- "Provider of bundle based resources from bundle " +
String.valueOf(bundle.getBundleId()));
+ "Provider of bundle based resources from bundle " +
bundle.getBundleId());
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
props.put(ResourceProvider.PROPERTY_ROOT, this.root.getResourceRoot());
props.put(PROP_BUNDLE, bundle.getBundleId());
@@ -125,15 +125,13 @@ public class BundleResourceProvider extends
ResourceProvider<Object> {
// here we either have a folder for which no same-named item exists
// or a bundle file
- if (entry != null) {
- // check if a JSON props file is directly requested
- // if so, we deny the access
- if (this.root.getJSONPropertiesExtension() == null
- ||
!entryPath.endsWith(this.root.getJSONPropertiesExtension())) {
-
- return new BundleResource(
- ctx.getResourceResolver(), cache, mappedPath,
resourcePath, null, isFolder);
- }
+ // check if a JSON props file is directly requested
+ // if so, we deny the access
+ if (entry != null
+ && (this.root.getJSONPropertiesExtension() == null
+ ||
!entryPath.endsWith(this.root.getJSONPropertiesExtension()))) {
+
+ return new BundleResource(ctx.getResourceResolver(), cache,
mappedPath, resourcePath, null, isFolder);
}
// the bundle does not contain the path
@@ -162,7 +160,7 @@ public class BundleResourceProvider extends
ResourceProvider<Object> {
@Override
public Iterator<Resource> listChildren(final ResolveContext<Object> ctx,
final Resource parent) {
- if (parent instanceof BundleResource && ((BundleResource)
parent).getBundle() == this.cache) {
+ if (parent instanceof BundleResource br && br.getBundle() ==
this.cache) {
// bundle resources can handle this request directly when the
parent
// resource is in the same bundle as this provider.
return new BundleResourceIterator((BundleResource) parent);
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceURLConnection.java
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceURLConnection.java
index 190f435..9601134 100644
---
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceURLConnection.java
+++
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceURLConnection.java
@@ -66,6 +66,7 @@ public class BundleResourceURLConnection extends
URLConnection {
}
/** Returns the input stream of the Bundle provided URLConnection */
+ @Override
public InputStream getInputStream() throws IOException {
connect();
@@ -73,6 +74,7 @@ public class BundleResourceURLConnection extends
URLConnection {
}
/** Returns the content length of the Bundle provided URLConnection */
+ @Override
public int getContentLength() {
try {
connect();
@@ -87,6 +89,7 @@ public class BundleResourceURLConnection extends
URLConnection {
* Returns the last modification time of the underlying bundle, which is
the
* last time the bundle was installed or updated
*/
+ @Override
public long getLastModified() {
try {
connect();
@@ -98,6 +101,7 @@ public class BundleResourceURLConnection extends
URLConnection {
}
/** Returns the content type of the Bundle provided URLConnection */
+ @Override
public String getContentType() {
try {
connect();
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
index 5a4ed20..9d18c16 100644
---
a/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
+++
b/src/main/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePlugin.java
@@ -83,67 +83,69 @@ class BundleResourceWebConsolePlugin extends HttpServlet {
@Override
protected void doGet(final HttpServletRequest req, final
HttpServletResponse res)
throws ServletException, IOException {
- PrintWriter pw = res.getWriter();
+ try (PrintWriter pw = res.getWriter()) {
+ pw.println("<table class='content' cellpadding='0' cellspacing='0'
width='100%'>");
- pw.println("<table class='content' cellpadding='0' cellspacing='0'
width='100%'>");
+ pw.println("<tr class='content'>"); // NOSONAR
+ pw.println("<th colspan='2' class='content container'>Bundle
Resource Provider</th>");
+ pw.println("</tr>"); // NOSONAR
- pw.println("<tr class='content'>");
- pw.println("<th colspan='2' class='content container'>Bundle Resource
Provider</th>");
- pw.println("</tr>");
+ BundleResourceProvider[] brp = provider.toArray(new
BundleResourceProvider[provider.size()]);
+ for (BundleResourceProvider bundleResourceProvider : brp) {
- BundleResourceProvider[] brp = provider.toArray(new
BundleResourceProvider[provider.size()]);
- for (BundleResourceProvider bundleResourceProvider : brp) {
+ BundleResourceCache cache =
bundleResourceProvider.getBundleResourceCache();
+ PathMapping path = bundleResourceProvider.getMappedPath();
- BundleResourceCache cache =
bundleResourceProvider.getBundleResourceCache();
- PathMapping path = bundleResourceProvider.getMappedPath();
+ pw.println("<tr class='content'>");
- pw.println("<tr class='content'>");
+ pw.println("<td class='content'>"); // NOSONAR
+ pw.println(cache.getBundle().getBundleId());
+ pw.println("</td>"); // NOSONAR
- pw.println("<td class='content'>");
- pw.println(cache.getBundle().getBundleId());
- pw.println("</td>");
+ pw.println("<td class='content'>");
+ pw.println(getName(cache.getBundle()));
+ pw.println("</td>");
- pw.println("<td class='content'>");
- pw.println(getName(cache.getBundle()));
- pw.println("</td>");
+ pw.println("</tr>");
- pw.println("</tr>");
+ pw.println("<tr class='content'>");
+ pw.println("<td class='content'> </td>");
- pw.println("<tr class='content'>");
- pw.println("<td class='content'> </td>");
+ pw.println("<td class='content'>");
- pw.println("<td class='content'>");
+ pw.println("<table>");
- pw.println("<table>");
+ pw.println("<tr>");
+ pw.println("<td>Mapping</td>");
+ pw.println("<td>");
+ pw.print(path.getResourceRoot());
+ if (path.getEntryRoot() != null) {
+ pw.print(" ==> ");
+ pw.print(path.getEntryRoot());
+ }
+ pw.println("</td>");
+ pw.println("</tr>");
- pw.println("<tr>");
- pw.println("<td>Mapping</td>");
- pw.println("<td>");
- pw.print(path.getResourceRoot());
- if (path.getEntryRoot() != null) {
- pw.print(" ==> ");
- pw.print(path.getEntryRoot());
- }
- pw.println("</td>");
- pw.println("</tr>");
+ pw.println("<tr>");
+ pw.println("<td>Entry Cache</td>");
+ pw.printf("<td>Size: %d, Limit: %d</td>%n",
cache.getEntryCacheSize(), cache.getEntryCacheMaxSize());
+ pw.println("</tr>");
- pw.println("<tr>");
- pw.println("<td>Entry Cache</td>");
- pw.printf("<td>Size: %d, Limit: %d</td>%n",
cache.getEntryCacheSize(), cache.getEntryCacheMaxSize());
- pw.println("</tr>");
+ pw.println("<tr>");
+ pw.println("<td>List Cache</td>");
+ pw.printf("<td>Size: %d, Limit: %d</td>%n",
cache.getListCacheSize(), cache.getListCacheMaxSize());
+ pw.println("</tr>");
- pw.println("<tr>");
- pw.println("<td>List Cache</td>");
- pw.printf("<td>Size: %d, Limit: %d</td>%n",
cache.getListCacheSize(), cache.getListCacheMaxSize());
- pw.println("</tr>");
+ pw.println("</table>");
- pw.println("</table>");
+ pw.println("</td>");
+ pw.println("</tr>");
+ }
- pw.println("</td>");
- pw.println("</tr>");
+ pw.println("</table>");
+ } catch (IOException ioe) {
+ log("Failed to write response: " + ioe.getMessage(), ioe);
}
-
- pw.println("</table>");
}
@SuppressWarnings("rawtypes")
diff --git
a/src/main/java/org/apache/sling/bundleresource/impl/PathMapping.java
b/src/main/java/org/apache/sling/bundleresource/impl/PathMapping.java
index e1ee6ff..6623a37 100644
--- a/src/main/java/org/apache/sling/bundleresource/impl/PathMapping.java
+++ b/src/main/java/org/apache/sling/bundleresource/impl/PathMapping.java
@@ -28,7 +28,7 @@ class PathMapping {
public static final String DIR_PATH = "path";
public static final String DIR_JSON = "propsJSON";
- private static final char prefixSeparatorChar = '!';
+ private static final char PREFIX_SEPARATOR_CHAR = '!';
private final String resourceRoot;
private final String resourceRootPrefix;
private final String entryRoot;
@@ -56,7 +56,7 @@ class PathMapping {
static PathMapping create(final String configPath, final String
expandDirective) {
String resourceRoot;
String entryRoot;
- int prefixSep = configPath.indexOf(prefixSeparatorChar);
+ int prefixSep = configPath.indexOf(PREFIX_SEPARATOR_CHAR);
if (prefixSep >= 0) {
entryRoot = configPath.substring(prefixSep + 1);
resourceRoot = configPath.substring(0,
prefixSep).concat(entryRoot);
@@ -126,7 +126,7 @@ class PathMapping {
}
private static String ensureLeadingDot(final String path) {
- if (path == null || path.length() == 0) {
+ if (path == null || path.isEmpty()) {
return null;
}
@@ -138,7 +138,7 @@ class PathMapping {
}
private static String ensureNoTrailingSlash(final String path) {
- if (path == null || path.length() == 0) {
+ if (path == null || path.isEmpty()) {
return null;
}
@@ -150,7 +150,7 @@ class PathMapping {
}
private static String ensureTrailingSlash(final String path) {
- if (path == null || path.length() == 0) {
+ if (path == null || path.isEmpty()) {
return null;
}
@@ -162,7 +162,7 @@ class PathMapping {
}
private static String ensureLeadingSlash(final String path) {
- if (path == null || path.length() == 0) {
+ if (path == null || path.isEmpty()) {
return null;
}
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/ActivatorTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/ActivatorTest.java
new file mode 100644
index 0000000..8d306ab
--- /dev/null
+++ b/src/test/java/org/apache/sling/bundleresource/impl/ActivatorTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.bundleresource.impl;
+
+import java.util.Hashtable;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ActivatorTest {
+
+ private Bundle bundle;
+
+ @BeforeEach
+ void setUp() {
+ bundle = mock(Bundle.class);
+ // Return an empty headers dictionary so that addBundleResourceProvider
+ // finds no prefixes and returns early without performing
registrations.
+ when(bundle.getHeaders()).thenReturn(new Hashtable<>());
+ }
+
+ @Test
+ void bundleChanged_handlesStartedEventWithoutThrowing() {
+ final Activator activator = new Activator();
+ final BundleEvent startedEvent = new BundleEvent(BundleEvent.STARTED,
bundle);
+
+ // Verify the STARTED branch runs (and does not throw).
+ assertDoesNotThrow(() -> activator.bundleChanged(startedEvent));
+ }
+
+ @Test
+ void bundleChanged_handlesStoppedEventWithoutThrowing() {
+ final Activator activator = new Activator();
+ final BundleEvent stoppedEvent = new BundleEvent(BundleEvent.STOPPED,
bundle);
+
+ // Verify the STOPPED branch runs (and does not throw).
+ assertDoesNotThrow(() -> activator.bundleChanged(stoppedEvent));
+ }
+
+ @Test
+ void bundleChanged_handlesOtherEventWithoutThrowing() {
+ final Activator activator = new Activator();
+ final BundleEvent stoppedEvent = new BundleEvent(BundleEvent.RESOLVED,
bundle);
+
+ // Verify nothing happens (and does not throw).
+ assertDoesNotThrow(() -> activator.bundleChanged(stoppedEvent));
+ }
+}
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceMapTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceMapTest.java
new file mode 100644
index 0000000..021e87f
--- /dev/null
+++
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceMapTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.bundleresource.impl;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Tests for the private static inner class BundleResourceMap inside
+ * BundleResourceCache. The class is private, so we access it via reflection
+ * and treat instances as plain Maps to exercise equals() and hashCode().
+ */
+class BundleResourceMapTest {
+
+ /**
+ * Create an instance of the private inner class BundleResourceMap using
+ * reflection. The constructor used takes a single int parameter (limit).
+ */
+ @SuppressWarnings("unchecked")
+ private <K, V> Map<K, V> createMap(int limit) throws Exception {
+ Class<?> outer = BundleResourceCache.class;
+ Class<?> target = null;
+ for (Class<?> c : outer.getDeclaredClasses()) {
+ if ("BundleResourceMap".equals(c.getSimpleName())) { // NOSONAR
+ target = c;
+ break;
+ }
+ }
+ if (target == null) {
+ throw new IllegalStateException("BundleResourceMap inner class not
found");
+ }
+
+ Constructor<?> ctor = target.getDeclaredConstructor(int.class);
+ ctor.setAccessible(true);
+ Object instance = ctor.newInstance(limit);
+ return (Map<K, V>) instance;
+ }
+
+ @Test
+ void equalsAndHashCode_sameLimitAndContent() throws Exception {
+ Map<String, String> m1 = createMap(10);
+ Map<String, String> m2 = createMap(10);
+
+ // same content
+ m1.put("a", "1");
+ m1.put("b", "2");
+
+ m2.put("a", "1");
+ m2.put("b", "2");
+
+ // equals should be true and hashCodes equal
+ assertTrue(m1.equals(m2), "Maps with same limit and same entries
should be equal"); // NOSONAR
+ assertTrue(m2.equals(m1), "Equality should be symmetric"); // NOSONAR
+ assertEquals(m1.hashCode(), m2.hashCode(), "hashCode must be equal for
equal maps");
+
+ // same instance equals itself
+ assertTrue(m1.equals(m1)); // NOSONAR
+ }
+
+ @Test
+ void equals_differentLimits() throws Exception {
+ Map<String, String> m1 = createMap(5);
+ Map<String, String> m2 = createMap(10);
+
+ // same content
+ m1.put("k", "v");
+ m2.put("k", "v");
+
+ // equals should be false because limits differ even though content
equals
+ assertFalse(m1.equals(m2), "Maps with same entries but different
limits should NOT be equal"); // NOSONAR
+ assertFalse(m2.equals(m1), "Symmetry for inequality"); // NOSONAR
+
+ // hashCodes are very likely different; at least they shouldn't be
required to be equal
+ // but we can assert that when equals is false, hashCodes may differ
(not a strict requirement),
+ // so we don't assert anything about hashCode here beyond that calling
it doesn't throw.
+ m1.hashCode();
+ m2.hashCode();
+ }
+
+ @Test
+ void equals_differentContent() throws Exception {
+ Map<String, String> m1 = createMap(7);
+ Map<String, String> m2 = createMap(7);
+
+ m1.put("x", "1");
+ m2.put("y", "2");
+
+ assertFalse(m1.equals(m2), "Maps with same limit but different content
should NOT be equal"); // NOSONAR
+ }
+
+ @Test
+ void equals_againstOtherTypesAndNull() throws Exception {
+ Map<String, String> m1 = createMap(3);
+ m1.put("foo", "bar");
+
+ assertFalse(m1.equals(null), "Should not be equal to null"); // NOSONAR
+ final HashMap<Object, Object> otherMap = new HashMap<>();
+ otherMap.put("foo", "bar");
+ assertFalse(m1.equals(otherMap), "Should not be equal to an unrelated
object"); // NOSONAR
+ }
+}
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceProviderTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceProviderTest.java
index 56454bd..ab73539 100644
---
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceProviderTest.java
+++
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceProviderTest.java
@@ -45,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class BundleResourceProviderTest {
+class BundleResourceProviderTest {
Bundle getBundle() {
Bundle bundle = mock(Bundle.class);
@@ -104,18 +104,18 @@ public class BundleResourceProviderTest {
}
@BeforeEach
- public void setup() {
+ void setup() {
ResourceURLStreamHandlerFactory.init();
}
@AfterEach
- public void finish() {
+ void finish() {
ResourceURLStreamHandler.reset();
}
@SuppressWarnings("unchecked")
@Test
- public void testFileResource() throws IOException {
+ void testFileResource() throws IOException {
final Bundle bundle = getBundle();
addContent(bundle, "/libs/foo/test.json", "HELLOWORLD");
@@ -130,7 +130,7 @@ public class BundleResourceProviderTest {
@SuppressWarnings("unchecked")
@Test
- public void testJSONResource() throws IOException {
+ void testJSONResource() throws IOException {
final Bundle bundle = getBundle();
addContent(bundle, "/libs/foo/test.json",
Collections.singletonMap("test", (Object) "foo"));
@@ -150,7 +150,7 @@ public class BundleResourceProviderTest {
@SuppressWarnings("unchecked")
@Test
- public void testFileAndJSONResource() throws IOException {
+ void testFileAndJSONResource() throws IOException {
final Bundle bundle = getBundle();
addContent(bundle, "/libs/foo/test", "HELLOWORLD");
addContent(bundle, "/libs/foo/test.json",
Collections.singletonMap("test", (Object) "foo"));
@@ -171,7 +171,7 @@ public class BundleResourceProviderTest {
}
@Test
- public void testTreeWithoutDeepJSON() throws IOException {
+ void testTreeWithoutDeepJSON() throws IOException {
testTreeWithoutDeepJSON("");
testTreeWithoutDeepJSON("/SLING-INF");
}
@@ -194,7 +194,7 @@ public class BundleResourceProviderTest {
finishContent(bundle);
final PathMapping path;
- if (prefix.length() == 0) {
+ if (prefix.isEmpty()) {
path = new PathMapping("/libs/foo", null, "json");
} else {
path = new PathMapping("/libs/foo", prefix + "/libs/foo", "json");
@@ -230,7 +230,7 @@ public class BundleResourceProviderTest {
}
@Test
- public void testTreeWithDeepJSON() throws IOException {
+ void testTreeWithDeepJSON() throws IOException {
testTreeWithDeepJSON("");
testTreeWithDeepJSON("/SLING-INF");
}
@@ -292,7 +292,7 @@ public class BundleResourceProviderTest {
finishContent(bundle);
final PathMapping path;
- if (prefix.length() == 0) {
+ if (prefix.isEmpty()) {
path = new PathMapping("/libs/foo", null, "json");
} else {
path = new PathMapping("/libs/foo", prefix + "/libs/foo", "json");
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceTest.java
index 8300df8..a006ba5 100644
--- a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceTest.java
+++ b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceTest.java
@@ -39,7 +39,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class BundleResourceTest {
+class BundleResourceTest {
BundleResourceCache getBundleResourceCache() {
Bundle bundle = mock(Bundle.class);
@@ -52,12 +52,12 @@ public class BundleResourceTest {
}
@BeforeEach
- public void setup() {
+ void setup() {
ResourceURLStreamHandlerFactory.init();
}
@AfterEach
- public void finish() {
+ void finish() {
ResourceURLStreamHandler.reset();
}
@@ -76,7 +76,7 @@ public class BundleResourceTest {
}
@Test
- public void testFileResource() throws MalformedURLException {
+ void testFileResource() throws MalformedURLException {
final BundleResourceCache cache = getBundleResourceCache();
when(cache.getEntry("/libs/foo/test.json")).thenReturn(new
URL("file:/libs/foo/test.json"));
final BundleResource rsrc = new BundleResource(
@@ -88,7 +88,7 @@ public class BundleResourceTest {
}
@Test
- public void testJSONResource() throws IOException {
+ void testJSONResource() throws IOException {
final BundleResourceCache cache = getBundleResourceCache();
addContent(cache, "/libs/foo/test.json",
Collections.singletonMap("test", (Object) "foo"));
final BundleResource rsrc = new BundleResource(
@@ -105,7 +105,7 @@ public class BundleResourceTest {
* JSONPropertiesExtension is loaded
*/
@Test
- public void testJSONResourceForMappedFile() throws IOException {
+ void testJSONResourceForMappedFile() throws IOException {
final BundleResourceCache cache = getBundleResourceCache();
addContent(cache, "/SLING_INF/libs/foo/test.txt", "Hello Text");
addContent(cache, "/SLING-INF/libs/foo/test.txt.json",
Collections.singletonMap("test", (Object) "foo"));
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePluginTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePluginTest.java
index 8c9dd23..0af0d60 100644
---
a/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePluginTest.java
+++
b/src/test/java/org/apache/sling/bundleresource/impl/BundleResourceWebConsolePluginTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.sling.bundleresource.impl;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
@@ -43,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -59,6 +61,24 @@ import static org.mockito.Mockito.when;
*/
class BundleResourceWebConsolePluginTest {
+ @Test
+ void testDoGetWithCaughtIOException() throws Exception {
+ testPlugin((ctx, reg, plugin) -> {
+ plugin = Mockito.spy(plugin);
+ Mockito.doNothing().when(plugin).log(anyString(),
any(Exception.class));
+
+ // Prepare mocks for servlet invocation and capture output
+ HttpServletRequest req = mock(HttpServletRequest.class);
+ HttpServletResponse resp = mock(HttpServletResponse.class);
+ Mockito.doThrow(IOException.class).when(resp).getWriter();
+
+ plugin.doGet(req, resp);
+
+ // verify the error log message was invoked
+ verify(plugin, times(1)).log(anyString(), any(Exception.class));
+ });
+ }
+
@Test
void testActivateDoGetDeactivate() throws Exception {
testPlugin((ctx, reg, plugin) -> {
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/NoBundleContextTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/NoBundleContextTest.java
index 5abf2c7..d8bab2b 100644
---
a/src/test/java/org/apache/sling/bundleresource/impl/NoBundleContextTest.java
+++
b/src/test/java/org/apache/sling/bundleresource/impl/NoBundleContextTest.java
@@ -18,7 +18,6 @@
*/
package org.apache.sling.bundleresource.impl;
-import java.io.IOException;
import java.util.Dictionary;
import org.apache.sling.spi.resource.provider.ResourceProvider;
@@ -38,24 +37,22 @@ import static org.mockito.Mockito.when;
/**
* SLING-11649 - verify check for null BundleContext while registering bundle
resources
*/
-public class NoBundleContextTest {
+class NoBundleContextTest {
@Test
- public void verifyIllegalStateExceptionWhenNoBundleContextIsAvailable()
throws IOException {
+ void verifyIllegalStateExceptionWhenNoBundleContextIsAvailable() {
final Bundle bundle = mock(Bundle.class);
when(bundle.getBundleContext()).thenReturn(null);
final PathMapping path = new PathMapping("/libs/foo", null, null);
final BundleResourceProvider provider = new BundleResourceProvider(new
BundleResourceCache(bundle), path);
- Exception exception = assertThrows(IllegalStateException.class, () -> {
- provider.registerService();
- });
+ Exception exception = assertThrows(IllegalStateException.class,
provider::registerService);
assertTrue(exception.getMessage().contains("No BundleContext was
found"));
}
@SuppressWarnings("unchecked")
@Test
- public void verifyNoIllegalStateExceptionWhenBundleContextIsAvailable()
throws IOException {
+ void verifyNoIllegalStateExceptionWhenBundleContextIsAvailable() {
final Bundle bundle = mock(Bundle.class);
final BundleContext bc = mock(BundleContext.class);
when(bundle.getBundleContext()).thenReturn(bc);
diff --git
a/src/test/java/org/apache/sling/bundleresource/impl/PathMappingTest.java
b/src/test/java/org/apache/sling/bundleresource/impl/PathMappingTest.java
index 1124025..6ce7b3c 100644
--- a/src/test/java/org/apache/sling/bundleresource/impl/PathMappingTest.java
+++ b/src/test/java/org/apache/sling/bundleresource/impl/PathMappingTest.java
@@ -23,10 +23,10 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
-public class PathMappingTest {
+class PathMappingTest {
@Test
- public void testSimpleRoot() {
+ void testSimpleRoot() {
final PathMapping[] paths = PathMapping.getRoots("/libs/foo");
assertEquals(1, paths.length);
assertNull(paths[0].getEntryRoot());
@@ -37,7 +37,7 @@ public class PathMappingTest {
}
@Test
- public void testSimpleRootWithJSON() {
+ void testSimpleRootWithJSON() {
final PathMapping[] paths = PathMapping.getRoots("/libs/foo;" +
PathMapping.DIR_JSON + ":=json");
assertEquals(1, paths.length);
assertNull(paths[0].getEntryRoot());