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-installer-console.git
The following commit(s) were added to refs/heads/master by this push:
new 02265a4 SLING-13166 Update to Parent 66 and apply spotless formatting
(#5)
02265a4 is described below
commit 02265a4b8dd20281816703d37ae1a1cae43836c8
Author: Eric Norman <[email protected]>
AuthorDate: Tue Apr 14 14:59:31 2026 -0700
SLING-13166 Update to Parent 66 and apply spotless formatting (#5)
---
.sling-module.json | 8 +
pom.xml | 68 +++-
.../impl/console/AbstractWebConsolePlugin.java | 27 +-
.../console/OsgiInstallerWebConsolePlugin.java | 206 +++++------
.../impl/console/AbstractWebConsolePluginTest.java | 82 +++++
.../console/OsgiInstallerWebConsolePluginTest.java | 391 +++++++++++++++++++++
.../core/impl/console/ReflectionTools.java | 71 ++++
7 files changed, 725 insertions(+), 128 deletions(-)
diff --git a/.sling-module.json b/.sling-module.json
new file mode 100644
index 0000000..d4268ec
--- /dev/null
+++ b/.sling-module.json
@@ -0,0 +1,8 @@
+{
+ "jenkins": {
+ "jdks": [
+ 17,
+ 21
+ ]
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index d876adb..4c146ad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,31 +23,35 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling-bundle-parent</artifactId>
- <version>49</version>
+ <version>66</version>
<relativePath />
</parent>
<artifactId>org.apache.sling.installer.console</artifactId>
- <version>1.1.3-SNAPSHOT</version>
+ <version>2.0.0-SNAPSHOT</version>
<name>Apache Sling Installer Web Console Plugin</name>
- <description>
- Provides a web console plugin for the OSGi installer
- </description>
-
- <properties>
- <sling.java.version>8</sling.java.version>
-
<project.build.outputTimestamp>2023-05-15T10:56:39Z</project.build.outputTimestamp>
- </properties>
+ <description>Provides a web console plugin for the OSGi
installer</description>
<scm>
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-console.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-console.git</developerConnection>
-
<url>https://github.com/apache/sling-org-apache-sling-installer-console.git</url>
- <tag>HEAD</tag>
- </scm>
+ <tag>HEAD</tag>
+
<url>https://github.com/apache/sling-org-apache-sling-installer-console/tree/${project.scm.tag}</url>
+ </scm>
+
+ <properties>
+ <sling.java.version>17</sling.java.version>
+
<project.build.outputTimestamp>2023-05-15T10:56:39Z</project.build.outputTimestamp>
+ </properties>
<dependencies>
+ <!-- JetBrains annotations for null-analysis (SLING-7798) -->
+ <dependency>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.framework</artifactId>
@@ -73,11 +77,49 @@
<artifactId>org.apache.sling.installer.core</artifactId>
<version>3.10.0</version>
<scope>provided</scope>
+ <exclusions>
+ <!-- workaround to exclude the older artifact that is
incomatible with current sling-mock -->
+ <exclusion>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.osgi</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-engine</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.sling-mock.junit5</artifactId>
+ <version>3.6.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java
b/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java
index a9e8895..b06bcc3 100644
---
a/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java
+++
b/src/main/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePlugin.java
@@ -18,15 +18,15 @@
*/
package org.apache.sling.installer.core.impl.console;
-import java.net.URL;
-
import javax.servlet.GenericServlet;
+import java.net.URL;
+
@SuppressWarnings("serial")
abstract class AbstractWebConsolePlugin extends GenericServlet {
/**
- *
+ *
* @return the prefix under which resources are requested (must not start
with "/", must end with "/")
*/
abstract String getRelativeResourcePrefix();
@@ -38,11 +38,8 @@ abstract class AbstractWebConsolePlugin extends
GenericServlet {
private URL getResource(final String path) {
if (path.startsWith("/" + getRelativeResourcePrefix())) {
// strip label
- int index = path.indexOf('/', 1);
- if (index <= 0) {
- throw new IllegalStateException("The relativeResourcePrefix
must contain at least one '/'");
- }
- return this.getClass().getResource(path.substring(index));
+ String resPath = path.substring(path.indexOf('/', 1));
+ return this.getClass().getResource(resPath);
}
return null;
}
@@ -57,19 +54,19 @@ abstract class AbstractWebConsolePlugin extends
GenericServlet {
if (input == null) {
return null;
}
-
+
final StringBuilder b = new StringBuilder(input.length());
- for(int i = 0;i < input.length(); i++) {
+ for (int i = 0; i < input.length(); i++) {
final char c = input.charAt(i);
- if(c == '&') {
+ if (c == '&') {
b.append("&");
- } else if(c == '<') {
+ } else if (c == '<') {
b.append("<");
- } else if(c == '>') {
+ } else if (c == '>') {
b.append(">");
- } else if(c == '"') {
+ } else if (c == '"') {
b.append(""");
- } else if(c == '\'') {
+ } else if (c == '\'') {
b.append("'");
} else {
b.append(c);
diff --git
a/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java
b/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java
index 97bc12d..5862bc2 100644
---
a/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java
+++
b/src/main/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePlugin.java
@@ -18,6 +18,9 @@
*/
package org.apache.sling.installer.core.impl.console;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -27,9 +30,6 @@ import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.info.InfoProvider;
import org.apache.sling.installer.api.info.InstallationState;
@@ -43,37 +43,36 @@ import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferencePolicyOption;
-
-@Component(service=javax.servlet.Servlet.class,
- property = {
- Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
- Constants.SERVICE_DESCRIPTION + "=Apache Sling OSGi Installer Web
Console Plugin",
- "felix.webconsole.label=" + OsgiInstallerWebConsolePlugin.LABEL,
- "felix.webconsole.title=OSGi Installer",
- "felix.webconsole.category=OSGi",
- "felix.webconsole.configprinter.modes=zip",
- "felix.webconsole.configprinter.modes=txt",
- "felix.webconsole.css=" + OsgiInstallerWebConsolePlugin.RES_LOC +
"list.css"
- })
+@Component(
+ service = javax.servlet.Servlet.class,
+ property = {
+ Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+ Constants.SERVICE_DESCRIPTION + "=Apache Sling OSGi Installer Web
Console Plugin",
+ "felix.webconsole.label=" + OsgiInstallerWebConsolePlugin.LABEL,
+ "felix.webconsole.title=OSGi Installer",
+ "felix.webconsole.category=OSGi",
+ "felix.webconsole.configprinter.modes=zip",
+ "felix.webconsole.configprinter.modes=txt",
+ "felix.webconsole.css=" + OsgiInstallerWebConsolePlugin.RES_LOC +
"list.css"
+ })
@SuppressWarnings("serial")
public class OsgiInstallerWebConsolePlugin extends AbstractWebConsolePlugin {
public static final String LABEL = "osgi-installer";
protected static final String RES_LOC = LABEL + "/res/ui/";
-
- @Reference(policyOption=ReferencePolicyOption.GREEDY)
- private InfoProvider installer;
+ @Reference(policyOption = ReferencePolicyOption.GREEDY)
+ private transient InfoProvider installer;
private String getType(final RegisteredResource rsrc) {
final String type = rsrc.getType();
- if ( type.equals(InstallableResource.TYPE_BUNDLE) ) {
+ if (type.equals(InstallableResource.TYPE_BUNDLE)) {
return "Bundles";
- } else if ( type.equals(InstallableResource.TYPE_CONFIG) ) {
+ } else if (type.equals(InstallableResource.TYPE_CONFIG)) {
return "Configurations";
- } else if ( type.equals(InstallableResource.TYPE_FILE) ) {
+ } else if (type.equals(InstallableResource.TYPE_FILE)) {
return "Files";
- } else if ( type.equals(InstallableResource.TYPE_PROPERTIES) ) {
+ } else if (type.equals(InstallableResource.TYPE_PROPERTIES)) {
return "Properties";
}
return type;
@@ -82,14 +81,14 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
private String getEntityId(final RegisteredResource rsrc, String alias) {
String id = rsrc.getEntityId();
final int pos = id.indexOf(':');
- if ( pos != -1 ) {
+ if (pos != -1) {
id = id.substring(pos + 1);
}
return (alias == null ? id : id + '\n' + alias);
}
private String getURL(final Resource rsrc) {
- if ( rsrc.getVersion() != null ) {
+ if (rsrc.getVersion() != null) {
return rsrc.getURL() + " (" + rsrc.getVersion() + ")";
}
return rsrc.getURL();
@@ -98,8 +97,8 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
private String getState(final Resource rsrc) {
String stateInfo = rsrc.getState().toString();
// INSTALLED state has some variants
- if ( rsrc.getState() == ResourceState.INSTALLED) {
- if (rsrc.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) != null
) {
+ if (rsrc.getState() == ResourceState.INSTALLED) {
+ if (rsrc.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) != null)
{
stateInfo = "EXCLUDED";
}
if (rsrc.getAttribute(TaskResource.ATTR_INSTALL_INFO) != null) {
@@ -125,55 +124,58 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
* Format a date
*/
private synchronized String formatDate(final long time) {
- if ( time == -1 ) {
- return "-";
- }
final Date d = new Date(time);
return dateFormat.format(d);
}
@Override
- public void service(final ServletRequest req, final ServletResponse res)
- throws IOException {
+ public void service(final ServletRequest req, final ServletResponse res)
throws IOException {
StringWriter bufferedWriter = new StringWriter();
final PrintWriter bufferedPw = new PrintWriter(bufferedWriter);
PrintWriter pw = res.getWriter();
final InstallationState state = this.installer.getInstallationState();
pw.print("<p class='statline ui-state-highlight'>Apache Sling OSGi
Installer");
- if ( state.getActiveResources().size() == 0 &&
state.getInstalledResources().size() == 0 &&
state.getUntransformedResources().size() == 0 ) {
+ if (state.getActiveResources().isEmpty()
+ && state.getInstalledResources().isEmpty()
+ && state.getUntransformedResources().isEmpty()) {
pw.print(" - no resources registered.");
}
-
+
pw.print("</p>");
pw.println("<ul class=list>");
pw.println("<li>Active Resources");
pw.println("<ul>");
-
+
String rt = null;
for (final ResourceGroup group : state.getActiveResources()) {
final Resource toActivate = group.getResources().get(0);
- if ( !toActivate.getType().equals(rt) ) {
- if ( rt != null ) {
+ if (!toActivate.getType().equals(rt)) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
}
String anchor = "active-" + escapeXml(getType(toActivate));
pw.println("<li><a href='#" + anchor + "'>" +
escapeXml(getType(toActivate)) + "</a></li>");
- bufferedPw.println("<div id='" + anchor + "'
class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
- bufferedPw.printf("<span style='float: left; margin-left:
1em;'>Active Resources - %s</span>", getType(toActivate));
+ bufferedPw.println("<div id='" + anchor
+ + "' class='ui-widget-header ui-corner-top
buttonGroup' style='height: 15px;'>");
+ bufferedPw.printf(
+ "<span style='float: left; margin-left: 1em;'>Active
Resources - %s</span>",
+ getType(toActivate));
bufferedPw.println("</div>");
bufferedPw.println("<table class='nicetable'><tbody>");
- bufferedPw.printf("<tr><th>Entity
ID</th><th>Digest/Priority</th><th>URL
(Version)</th><th>State</th><th>Error</th></tr>");
+ bufferedPw.printf(
+ "<tr><th>Entity ID</th><th>Digest/Priority</th><th>URL
(Version)</th><th>State</th><th>Error</th></tr>");
rt = toActivate.getType();
}
-
bufferedPw.printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
+ bufferedPw.printf(
+
"<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
escapeXml(getEntityId(toActivate, group.getAlias())),
escapeXml(getInfo(toActivate)),
escapeXml(getURL(toActivate)),
escapeXml(toActivate.getState().toString()),
escapeXml(getError(toActivate)));
}
- if ( rt != null ) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
} else {
pw.println("<li>none</li>");
@@ -183,24 +185,28 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
pw.println("</ul></li>");
pw.println("<li>Processed Resources");
pw.println("<ul>");
-
- for(final ResourceGroup group : state.getInstalledResources()) {
+
+ for (final ResourceGroup group : state.getInstalledResources()) {
final Collection<Resource> resources = group.getResources();
- if (resources.size() > 0) {
+ if (!resources.isEmpty()) {
final Iterator<Resource> iter = resources.iterator();
final Resource first = iter.next();
- if ( !first.getType().equals(rt) ) {
- if ( rt != null ) {
+ if (!first.getType().equals(rt)) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
}
String anchor = "processed-" + escapeXml(getType(first));
pw.println("<li><a href='#" + anchor + "'>" +
escapeXml(getType(first)) + "</a></li>");
-
- bufferedPw.println("<div id='" + anchor + "'
class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
- bufferedPw.printf("<span style='float: left; margin-left:
1em;'>Processed Resources - %s</span>", getType(first));
+
+ bufferedPw.println("<div id='" + anchor
+ + "' class='ui-widget-header ui-corner-top
buttonGroup' style='height: 15px;'>");
+ bufferedPw.printf(
+ "<span style='float: left; margin-left:
1em;'>Processed Resources - %s</span>",
+ getType(first));
bufferedPw.println("</div>");
bufferedPw.println("<table class='nicetable'><tbody>");
- bufferedPw.printf("<tr><th>Entity
ID</th><th>Digest/Priority</th><th>URL
(Version)</th><th>State</th><th>Error</th></tr>");
+ bufferedPw.printf(
+ "<tr><th>Entity
ID</th><th>Digest/Priority</th><th>URL
(Version)</th><th>State</th><th>Error</th></tr>");
rt = first.getType();
}
bufferedPw.print("<tr><td>");
@@ -211,9 +217,9 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
bufferedPw.print(escapeXml(getURL(first)));
bufferedPw.print("</td><td>");
bufferedPw.print(escapeXml(getState(first)));
- if ( first.getState() == ResourceState.INSTALLED ) {
+ if (first.getState() == ResourceState.INSTALLED) {
final long lastChange = first.getLastChange();
- if ( lastChange > 0 ) {
+ if (lastChange > 0) {
bufferedPw.print("<br/>");
bufferedPw.print(formatDate(lastChange));
}
@@ -221,18 +227,22 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
bufferedPw.print("</td><td>");
bufferedPw.print(escapeXml(getError(first)));
bufferedPw.print("</td></tr>");
- if ( first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) !=
null ) {
- bufferedPw.printf("<tr><td></td><td
colspan='2'>%s</td><td></td><td></td></tr>",
-
escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED).toString()));
+ if (first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) !=
null) {
+ bufferedPw.printf(
+ "<tr><td></td><td
colspan='2'>%s</td><td></td><td></td></tr>",
+
escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED)
+ .toString()));
}
- if ( first.getAttribute(TaskResource.ATTR_INSTALL_INFO) !=
null ) {
- bufferedPw.printf("<tr><td></td><td
colspan='2'>%s</td><td></td><td></td></tr>",
-
escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_INFO).toString()));
-
+ if (first.getAttribute(TaskResource.ATTR_INSTALL_INFO) !=
null) {
+ bufferedPw.printf(
+ "<tr><td></td><td
colspan='2'>%s</td><td></td><td></td></tr>",
+
escapeXml(first.getAttribute(TaskResource.ATTR_INSTALL_INFO)
+ .toString()));
}
- while ( iter.hasNext() ) {
+ while (iter.hasNext()) {
final Resource resource = iter.next();
-
bufferedPw.printf("<tr><td></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
+ bufferedPw.printf(
+
"<tr><td></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
escapeXml(getInfo(resource)),
escapeXml(getURL(resource)),
escapeXml(resource.getState().toString()),
@@ -240,7 +250,7 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
}
}
}
- if ( rt != null ) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
} else {
pw.println("<li>none</li>");
@@ -251,27 +261,30 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
pw.println("<ul>");
rt = null;
- for(final RegisteredResource registeredResource :
state.getUntransformedResources()) {
- if ( !registeredResource.getType().equals(rt) ) {
- if ( rt != null ) {
+ for (final RegisteredResource registeredResource :
state.getUntransformedResources()) {
+ if (!registeredResource.getType().equals(rt)) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
}
String anchor = "untransformed-" +
escapeXml(getType(registeredResource));
pw.println("<li><a href='#" + anchor + "'>" +
escapeXml(getType(registeredResource)) + "</a></li>");
-
- bufferedPw.println("<div id='" + anchor + "'
class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px;'>");
- bufferedPw.printf("<span style='float: left; margin-left:
1em;'>Untransformed Resources - %s</span>", getType(registeredResource));
+
+ bufferedPw.println("<div id='" + anchor
+ + "' class='ui-widget-header ui-corner-top
buttonGroup' style='height: 15px;'>");
+ bufferedPw.printf(
+ "<span style='float: left; margin-left:
1em;'>Untransformed Resources - %s</span>",
+ getType(registeredResource));
bufferedPw.println("</div>");
bufferedPw.println("<table class='nicetable'><tbody>");
bufferedPw.printf("<tr><th>Digest/Priority</th><th>URL</th></tr>");
rt = registeredResource.getType();
}
- bufferedPw.printf("<tr><td>%s</td><td>%s</td></tr>",
- escapeXml(getInfo(registeredResource)),
- escapeXml(registeredResource.getURL()));
+ bufferedPw.printf(
+ "<tr><td>%s</td><td>%s</td></tr>",
+ escapeXml(getInfo(registeredResource)),
escapeXml(registeredResource.getURL()));
}
- if ( rt != null ) {
+ if (rt != null) {
bufferedPw.println("</tbody></table>");
} else {
pw.println("<li>none</li>");
@@ -286,7 +299,7 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
* Method for the configuration printer.
*/
public void printConfiguration(final PrintWriter pw, final String mode) {
- if ( !"zip".equals(mode) && !"txt".equals(mode) ) {
+ if (!"zip".equals(mode) && !"txt".equals(mode)) {
return;
}
pw.println("Apache Sling OSGi Installer");
@@ -295,13 +308,14 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
pw.println("Active Resources");
pw.println("----------------");
String rt = null;
- for(final ResourceGroup group : state.getActiveResources()) {
+ for (final ResourceGroup group : state.getActiveResources()) {
final Resource toActivate = group.getResources().get(0);
- if ( !toActivate.getType().equals(rt) ) {
+ if (!toActivate.getType().equals(rt)) {
pw.printf("%s:%n", getType(toActivate));
rt = toActivate.getType();
}
- pw.printf("- %s: %s, %s, %s, %s%n",
+ pw.printf(
+ "- %s: %s, %s, %s, %s%n",
getEntityId(toActivate, group.getAlias()),
getInfo(toActivate),
getURL(toActivate),
@@ -313,37 +327,33 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
pw.println("Processed Resources");
pw.println("-------------------");
rt = null;
- for(final ResourceGroup group : state.getInstalledResources()) {
+ for (final ResourceGroup group : state.getInstalledResources()) {
final Collection<Resource> resources = group.getResources();
- if (resources.size() > 0) {
+ if (!resources.isEmpty()) {
final Iterator<Resource> iter = resources.iterator();
final Resource first = iter.next();
- if ( !first.getType().equals(rt) ) {
+ if (!first.getType().equals(rt)) {
pw.printf("%s:%n", getType(first));
rt = first.getType();
}
- pw.printf("* %s: %s, %s, %s, %s%n",
+ pw.printf(
+ "* %s: %s, %s, %s, %s%n",
getEntityId(first, group.getAlias()),
getInfo(first),
getURL(first),
getState(first),
getError(first));
- if ( first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) !=
null ) {
- pw.printf(" : %s",
-
first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED));
+ if (first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED) !=
null) {
+ pw.printf(" : %s",
first.getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED));
}
- if ( first.getAttribute(TaskResource.ATTR_INSTALL_INFO) !=
null ) {
- pw.printf(" : %s",
-
first.getAttribute(TaskResource.ATTR_INSTALL_INFO));
-
+ if (first.getAttribute(TaskResource.ATTR_INSTALL_INFO) !=
null) {
+ pw.printf(" : %s",
first.getAttribute(TaskResource.ATTR_INSTALL_INFO));
}
- while ( iter.hasNext() ) {
+ while (iter.hasNext()) {
final Resource resource = iter.next();
- pw.printf(" - %s, %s, %s, %s%n",
- getInfo(resource),
- getURL(resource),
- resource.getState(),
- getError(resource));
+ pw.printf(
+ " - %s, %s, %s, %s%n",
+ getInfo(resource), getURL(resource),
resource.getState(), getError(resource));
}
}
}
@@ -352,14 +362,12 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
pw.println("Untransformed Resources");
pw.println("-----------------------");
rt = null;
- for(final RegisteredResource registeredResource :
state.getUntransformedResources()) {
- if ( !registeredResource.getType().equals(rt) ) {
+ for (final RegisteredResource registeredResource :
state.getUntransformedResources()) {
+ if (!registeredResource.getType().equals(rt)) {
pw.printf("%s:%n", getType(registeredResource));
rt = registeredResource.getType();
}
- pw.printf("- %s, %s%n",
- getInfo(registeredResource),
- registeredResource.getURL());
+ pw.printf("- %s, %s%n", getInfo(registeredResource),
registeredResource.getURL());
}
}
@@ -367,6 +375,4 @@ public class OsgiInstallerWebConsolePlugin extends
AbstractWebConsolePlugin {
String getRelativeResourcePrefix() {
return RES_LOC;
}
-
-
}
diff --git
a/src/test/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePluginTest.java
b/src/test/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePluginTest.java
new file mode 100644
index 0000000..22d7306
--- /dev/null
+++
b/src/test/java/org/apache/sling/installer/core/impl/console/AbstractWebConsolePluginTest.java
@@ -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.
+ */
+package org.apache.sling.installer.core.impl.console;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import java.io.IOException;
+import java.net.URL;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ *
+ */
+class AbstractWebConsolePluginTest {
+ private AbstractWebConsolePlugin plugin = new AbstractWebConsolePlugin() {
+
+ @Override
+ public void service(ServletRequest req, ServletResponse res) throws
ServletException, IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ String getRelativeResourcePrefix() {
+ return "osgi-installer/res/ui/";
+ }
+ };
+
+ /**
+ * Test method for {@link
org.apache.sling.installer.core.impl.console.AbstractWebConsolePlugin#escapeXml(java.lang.String)}.
+ */
+ @Test
+ void testEscapeXml() {
+ assertNull(plugin.escapeXml(null));
+ assertEquals("", plugin.escapeXml(""));
+ assertEquals("<hello/>", plugin.escapeXml("<hello/>"));
+ assertEquals(""dog's & cat"",
plugin.escapeXml("\"dog's & cat\""));
+ }
+
+ /**
+ * Test method for {@link
+ *
org.apache.sling.installer.factories.configuration.impl.ConfigurationSerializerWebConsolePlugin#getResource(java.lang.String)}.
+ */
+ @Test
+ void testGetResource() throws SecurityException, IllegalArgumentException {
+ final URL value1 = ReflectionTools.invokeMethodWithReflection(
+ plugin, "getResource", new Class[] {String.class}, URL.class,
new Object[] {"/invalid"});
+ assertNull(value1);
+
+ final URL value2 = ReflectionTools.invokeMethodWithReflection(
+ plugin, "getResource", new Class[] {String.class}, URL.class,
new Object[] {
+ "/osgi-installer/res/ui/list.css"
+ });
+ assertNotNull(value2);
+
+ final URL value3 = ReflectionTools.invokeMethodWithReflection(
+ plugin, "getResource", new Class[] {String.class}, URL.class,
new Object[] {
+ "/osgi-installer/res/ui/invalid.css"
+ });
+ assertNull(value3);
+ }
+}
diff --git
a/src/test/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePluginTest.java
b/src/test/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePluginTest.java
new file mode 100644
index 0000000..ce789e8
--- /dev/null
+++
b/src/test/java/org/apache/sling/installer/core/impl/console/OsgiInstallerWebConsolePluginTest.java
@@ -0,0 +1,391 @@
+/*
+ * 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.installer.core.impl.console;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.installer.api.InstallableResource;
+import org.apache.sling.installer.api.info.InfoProvider;
+import org.apache.sling.installer.api.info.InstallationState;
+import org.apache.sling.installer.api.info.Resource;
+import org.apache.sling.installer.api.info.ResourceGroup;
+import org.apache.sling.installer.api.tasks.RegisteredResource;
+import org.apache.sling.installer.api.tasks.ResourceState;
+import org.apache.sling.installer.api.tasks.TaskResource;
+import org.apache.sling.testing.mock.sling.junit5.SlingContext;
+import org.apache.sling.testing.mock.sling.junit5.SlingContextExtension;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
+import
org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletResponse;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.Mockito;
+import org.osgi.framework.Version;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ *
+ */
+@ExtendWith(SlingContextExtension.class)
+class OsgiInstallerWebConsolePluginTest {
+ public final SlingContext context = new SlingContext();
+
+ private OsgiInstallerWebConsolePlugin plugin;
+
+ private InfoProvider mockInfoProvider;
+
+ @BeforeEach
+ void beforeEach() {
+ mockInfoProvider = context.registerService(InfoProvider.class,
Mockito.mock(InfoProvider.class));
+
+ plugin =
context.registerInjectActivateService(OsgiInstallerWebConsolePlugin.class);
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.installer.core.impl.console.OsgiInstallerWebConsolePlugin#getRelativeResourcePrefix()}.
+ */
+ @Test
+ void testGetRelativeResourcePrefix() {
+ assertNotNull(plugin.getRelativeResourcePrefix());
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.installer.core.impl.console.OsgiInstallerWebConsolePlugin#service(jakarta.servlet.ServletRequest,
jakarta.servlet.ServletResponse)}.
+ */
+ @Test
+ void testServiceWithNoResources() throws IOException {
+ // mock InfoProvider
+ mockInstallationState();
+
+ final @NotNull MockSlingHttpServletRequest req = context.request();
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ plugin.service(req, resp);
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertTrue(outputAsString.contains("no resources registered"));
+ }
+
+ @Test
+ void testServiceWithActiveResources() throws IOException {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicActiveResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletRequest req = context.request();
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ plugin.service(req, resp);
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertFalse(outputAsString.contains("no resources registered"));
+ }
+
+ @Test
+ void testServiceWithInstalledResources() throws IOException {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicInstalledResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletRequest req = context.request();
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ plugin.service(req, resp);
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertFalse(outputAsString.contains("no resources registered"));
+ }
+
+ @Test
+ void testServiceWithUntransformedResources() throws IOException {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicUntransformedResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletRequest req = context.request();
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ plugin.service(req, resp);
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertFalse(outputAsString.contains("no resources registered"));
+ }
+
+ /**
+ * Test method for {@link
org.apache.sling.installer.core.impl.console.OsgiInstallerWebConsolePlugin#printConfiguration(java.io.PrintWriter,
java.lang.String)}.
+ */
+ @ParameterizedTest
+ @ValueSource(strings = {"zip", "txt"})
+ void testPrintConfigurationWithActiveResources(String mode) {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicActiveResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ final PrintWriter pw = resp.getWriter();
+ plugin.printConfiguration(pw, mode);
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertTrue(outputAsString.contains("Apache Sling OSGi Installer"));
+ }
+
+ @Test
+ void testPrintConfigurationWithInstalledResources() {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicInstalledResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ final PrintWriter pw = resp.getWriter();
+ plugin.printConfiguration(pw, "txt");
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertTrue(outputAsString.contains("Apache Sling OSGi Installer"));
+ }
+
+ @Test
+ void testPrintConfigurationWithUntransformedResources() {
+ // mock InfoProvider
+ final InstallationState mockInstallationState =
mockInstallationState();
+ mockBasicUntransformedResources(mockInstallationState);
+
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ final PrintWriter pw = resp.getWriter();
+ plugin.printConfiguration(pw, "zip");
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertTrue(outputAsString.contains("Apache Sling OSGi Installer"));
+ }
+
+ @Test
+ void testPrintConfigurationForInvalidMode() {
+ final @NotNull MockSlingHttpServletResponse resp = context.response();
+ final PrintWriter pw = resp.getWriter();
+ plugin.printConfiguration(pw, "invalid");
+ final String outputAsString = resp.getOutputAsString();
+ assertNotNull(outputAsString);
+ assertTrue(outputAsString.isEmpty());
+ }
+
+ private InstallationState mockInstallationState() {
+ InstallationState mockInstallationState =
Mockito.mock(InstallationState.class);
+
Mockito.doReturn(mockInstallationState).when(mockInfoProvider).getInstallationState();
+ return mockInstallationState;
+ }
+
+ private RegisteredResource mockInstallRegisteredResource(
+ String type, String entityId, String scheme, Map<String, Object>
dictionary) {
+ RegisteredResource mockInstalledResource =
Mockito.mock(RegisteredResource.class);
+ Mockito.doReturn(type).when(mockInstalledResource).getType();
+ Mockito.doReturn(entityId).when(mockInstalledResource).getEntityId();
+ Mockito.doReturn(scheme).when(mockInstalledResource).getScheme();
+ Mockito.doReturn(new Hashtable<>(dictionary))
+ .when(mockInstalledResource)
+ .getDictionary();
+ return mockInstalledResource;
+ }
+
+ private Resource mockInstallResoure(
+ String type,
+ ResourceState state,
+ String entityId,
+ String scheme,
+ Map<String, Object> dictionary,
+ String error,
+ String url,
+ Version version) {
+ Resource mockInstalledResource = Mockito.mock(Resource.class);
+ Mockito.doReturn(type).when(mockInstalledResource).getType();
+ Mockito.doReturn(state).when(mockInstalledResource).getState();
+ Mockito.doReturn(entityId).when(mockInstalledResource).getEntityId();
+ Mockito.doReturn(scheme).when(mockInstalledResource).getScheme();
+ Mockito.doReturn(new Hashtable<>(dictionary))
+ .when(mockInstalledResource)
+ .getDictionary();
+ Mockito.doReturn(error).when(mockInstalledResource).getError();
+ Mockito.doReturn(url).when(mockInstalledResource).getURL();
+ Mockito.doReturn(version).when(mockInstalledResource).getVersion();
+ return mockInstalledResource;
+ }
+
+ private void mockBasicUntransformedResources(final InstallationState
mockInstallationState) {
+ // mock untransformed resources
+ final RegisteredResource mockUntransformedResource1 =
mockInstallRegisteredResource(
+ InstallableResource.TYPE_CONFIG, "test1", "launchpad",
Map.of("key1", "value1"));
+
+ // and a second for code coverage
+ final RegisteredResource mockUntransformedResource2 =
mockInstallRegisteredResource(
+ InstallableResource.TYPE_CONFIG, "test2", "launchpad",
Map.of("key2", "value2"));
+
+ // and a third for code coverage
+ final RegisteredResource mockUntransformedResource3 =
mockInstallRegisteredResource(
+ InstallableResource.TYPE_PROPERTIES, "test3", "launchpad",
Map.of("key3", "value3"));
+
+ Mockito.doReturn(List.of(mockUntransformedResource1,
mockUntransformedResource2, mockUntransformedResource3))
+ .when(mockInstallationState)
+ .getUntransformedResources();
+ }
+
+ private void mockBasicInstalledResources(final InstallationState
mockInstallationState) {
+ // mock installed resources
+ ResourceGroup mockInstalledRG1 = Mockito.mock(ResourceGroup.class);
+ Mockito.doReturn("alias1").when(mockInstalledRG1).getAlias();
+
+ Resource mockInstalledResource1 = mockInstallResoure(
+ InstallableResource.TYPE_CONFIG,
+ ResourceState.INSTALLED,
+ "config:factory1~test1",
+ "launchpad",
+ Map.of("key1", "value1", "key2", "value2"),
+ "error1",
+ "url1",
+ new Version(1, 0, 0));
+ // mock a last change timestamp for code coverage
+ Mockito.doReturn(System.currentTimeMillis())
+ .when(mockInstalledResource1)
+ .getLastChange();
+ // add mock attributes for code coverage
+
Mockito.doReturn("excluded1").when(mockInstalledResource1).getAttribute(TaskResource.ATTR_INSTALL_EXCLUDED);
+
Mockito.doReturn("info1").when(mockInstalledResource1).getAttribute(TaskResource.ATTR_INSTALL_INFO);
+
+ Resource mockInstalledResource2 = mockInstallResoure(
+ InstallableResource.TYPE_CONFIG,
+ ResourceState.INSTALLED,
+ "test2",
+ "launchpad",
+ Map.of("key2", "value2"),
+ null,
+ "url2",
+ null);
+ Mockito.doReturn(List.of(mockInstalledResource1,
mockInstalledResource2))
+ .when(mockInstalledRG1)
+ .getResources();
+
+ // and a second group for code coverage
+ ResourceGroup mockInstalledRG2 = Mockito.mock(ResourceGroup.class);
+
+ Resource mockInstalledResource3 = mockInstallResoure(
+ InstallableResource.TYPE_CONFIG,
+ ResourceState.INSTALLED,
+ "test3",
+ "launchpad",
+ Map.of("key3", "value3"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockInstalledResource3)).when(mockInstalledRG2).getResources();
+
+ // and a third group for code coverage
+ ResourceGroup mockInstalledRG3 = Mockito.mock(ResourceGroup.class);
+
+ Resource mockInstalledResource4 = mockInstallResoure(
+ InstallableResource.TYPE_BUNDLE,
+ ResourceState.INSTALLED,
+ "test4",
+ "launchpad",
+ Map.of("key4", "value4"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockInstalledResource4)).when(mockInstalledRG3).getResources();
+
+ // and a fourth group for code coverage
+ ResourceGroup mockInstalledRG4 = Mockito.mock(ResourceGroup.class);
+
+ Resource mockInstalledResource5 = mockInstallResoure(
+ InstallableResource.TYPE_FILE,
+ ResourceState.UNINSTALLED,
+ "test5",
+ "launchpad",
+ Map.of("key5", "value5"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockInstalledResource5)).when(mockInstalledRG4).getResources();
+
+ // and a fifth group for code coverage
+ ResourceGroup mockInstalledRG5 = Mockito.mock(ResourceGroup.class);
+
+ Resource mockInstalledResource6 = mockInstallResoure(
+ "invalid", ResourceState.INSTALLED, "test6", "launchpad",
Map.of("key6", "value6"), null, null, null);
+
Mockito.doReturn(List.of(mockInstalledResource6)).when(mockInstalledRG5).getResources();
+
+ // and a sixth (empty) group for code coverage
+ ResourceGroup mockInstalledRG6 = Mockito.mock(ResourceGroup.class);
+ Mockito.doReturn(List.of()).when(mockInstalledRG6).getResources();
+
+ Mockito.doReturn(List.of(
+ mockInstalledRG1,
+ mockInstalledRG2,
+ mockInstalledRG3,
+ mockInstalledRG4,
+ mockInstalledRG5,
+ mockInstalledRG6))
+ .when(mockInstallationState)
+ .getInstalledResources();
+ }
+
+ private void mockBasicActiveResources(final InstallationState
mockInstallationState) {
+ // mock active resources
+ ResourceGroup mockActiveRG1 = Mockito.mock(ResourceGroup.class);
+ Resource mockActiveResource1 = mockInstallResoure(
+ InstallableResource.TYPE_CONFIG,
+ ResourceState.INSTALLED,
+ "config:factory1~test1",
+ "launchpad",
+ Map.of("key1", "value1", "key2", "value2"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockActiveResource1)).when(mockActiveRG1).getResources();
+
+ // and a second group for code coverage
+ ResourceGroup mockActiveRG2 = Mockito.mock(ResourceGroup.class);
+ Resource mockActiveResource2 = mockInstallResoure(
+ InstallableResource.TYPE_CONFIG,
+ ResourceState.INSTALLED,
+ "test2",
+ "launchpad",
+ Map.of("key2", "value2"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockActiveResource2)).when(mockActiveRG2).getResources();
+
+ // and a third group for code coverage
+ ResourceGroup mockActiveRG3 = Mockito.mock(ResourceGroup.class);
+ Resource mockActiveResource3 = mockInstallResoure(
+ InstallableResource.TYPE_PROPERTIES,
+ ResourceState.INSTALLED,
+ "test3",
+ "launchpad",
+ Map.of("key3", "value3"),
+ null,
+ null,
+ null);
+
Mockito.doReturn(List.of(mockActiveResource3)).when(mockActiveRG3).getResources();
+ Mockito.doReturn(List.of(mockActiveRG1, mockActiveRG2, mockActiveRG3))
+ .when(mockInstallationState)
+ .getActiveResources();
+ }
+}
diff --git
a/src/test/java/org/apache/sling/installer/core/impl/console/ReflectionTools.java
b/src/test/java/org/apache/sling/installer/core/impl/console/ReflectionTools.java
new file mode 100644
index 0000000..69cde7d
--- /dev/null
+++
b/src/test/java/org/apache/sling/installer/core/impl/console/ReflectionTools.java
@@ -0,0 +1,71 @@
+/*
+ * 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.installer.core.impl.console;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+/**
+ * Reflection utilities to facilitate testing
+ */
+public class ReflectionTools {
+
+ private ReflectionTools() {
+ // hide the public constructor
+ }
+
+ public static <T> T invokeMethodWithReflection(
+ Object obj, String methodName, Class<?>[] parameterTypes, Class<T>
expectedType, Object[] methodArgs) {
+ Object result = null;
+ try {
+ Class<?> clazz = obj.getClass();
+ Method method = null;
+ do {
+ try { // NOSONAR
+ method = clazz.getDeclaredMethod(methodName,
parameterTypes);
+ } catch (NoSuchMethodException nsfe) {
+ clazz = clazz.getSuperclass();
+ }
+ } while (method == null && clazz != null);
+ if (method != null) {
+ if (Modifier.isStatic(method.getModifiers())) {
+ if (!method.canAccess(null)) {
+ method.setAccessible(true);
+ }
+ result = method.invoke(null, methodArgs);
+ } else {
+ if (!method.canAccess(obj)) {
+ method.setAccessible(true);
+ }
+ result = method.invoke(obj, methodArgs);
+ }
+ } else {
+ fail("Failed to find method via reflection: " + methodName);
+ }
+ } catch (IllegalArgumentException | IllegalAccessException |
SecurityException e) {
+ fail("Failed to get method via reflection. Reason: " +
e.getMessage());
+ } catch (InvocationTargetException e) {
+ fail("Failed to invoke method via reflection. Reason: " +
e.getMessage());
+ }
+ return expectedType == null ? null : expectedType.cast(result);
+ }
+}