You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2016/05/13 14:02:04 UTC
svn commit: r1743676 - in /sling/trunk/testing/http/clients: ./
src/main/java/org/apache/sling/testing/clients/osgi/
src/main/java/org/apache/sling/testing/clients/util/poller/
Author: bdelacretaz
Date: Fri May 13 14:02:03 2016
New Revision: 1743676
URL: http://svn.apache.org/viewvc?rev=1743676&view=rev
Log:
SLING-5725 - Remove o.a.s.testing.tools dependency in o.a.s.testing.clients and merge OSGi console clients - contribued by Andrei Dulvac, thanks!
Added:
sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java
Removed:
sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/WebconsoleClient.java
Modified:
sling/trunk/testing/http/clients/pom.xml
sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/BundlesInstaller.java
sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/OsgiConsoleClient.java
Modified: sling/trunk/testing/http/clients/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/testing/http/clients/pom.xml?rev=1743676&r1=1743675&r2=1743676&view=diff
==============================================================================
--- sling/trunk/testing/http/clients/pom.xml (original)
+++ sling/trunk/testing/http/clients/pom.xml Fri May 13 14:02:03 2016
@@ -69,17 +69,6 @@
<dependencies>
<dependency>
- <groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.testing.tools</artifactId>
- <version>1.0.12</version>
- <exclusions>
- <exclusion>
- <groupId>org.apache.httpcomponents</groupId>
- <artifactId>httpcore</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
</dependency>
@@ -144,5 +133,18 @@
<artifactId>org.apache.sling.xss</artifactId>
<version>1.0.4</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.json</artifactId>
+ <version>2.0.16</version>
+ </dependency>
+
+ <!-- For tests -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/BundlesInstaller.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/BundlesInstaller.java?rev=1743676&r1=1743675&r2=1743676&view=diff
==============================================================================
--- sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/BundlesInstaller.java (original)
+++ sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/BundlesInstaller.java Fri May 13 14:02:03 2016
@@ -16,171 +16,202 @@
*/
package org.apache.sling.testing.clients.osgi;
-import org.osgi.framework.Constants;
+import org.apache.sling.testing.clients.ClientException;
+import org.apache.sling.testing.clients.util.poller.AbstractPoller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.util.LinkedList;
import java.util.List;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-/** Utility that installs and starts additional bundles for testing */
+/**
+ * Utility for installing and starting additional bundles for testing
+ */
public class BundlesInstaller {
private final Logger log = LoggerFactory.getLogger(getClass());
- private final WebconsoleClient webconsoleClient;
+ private final OsgiConsoleClient osgiConsoleClient;
public static final String ACTIVE_STATE = "active";
-
- public BundlesInstaller(WebconsoleClient wcc) {
- webconsoleClient = wcc;
- }
-
- public boolean isInstalled(File bundleFile) throws Exception {
- final String bundleSymbolicName = getBundleSymbolicName(bundleFile);
- try{
- log.debug("Checking if installed: "+bundleSymbolicName);
- webconsoleClient.checkBundleInstalled(bundleSymbolicName, 1);
- // if this succeeds, then there's no need to install again
- log.debug("Already installed: "+bundleSymbolicName);
+
+ public BundlesInstaller(OsgiConsoleClient cc) {
+ osgiConsoleClient = cc;
+ }
+
+ /**
+ * Checks if a bundle is installed or not. Does not retry.
+ * @param bundleFile
+ * @return
+ * @throws ClientException
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public boolean isInstalled(File bundleFile) throws ClientException, InterruptedException, IOException {
+ final String bundleSymbolicName = OsgiConsoleClient.getBundleSymbolicName(bundleFile);
+ log.debug("Checking if installed: " + bundleSymbolicName);
+ boolean installed = osgiConsoleClient.checkBundleInstalled(bundleSymbolicName, 1000, 1);
+ // if this succeeds, then there's no need to install again
+ if (installed) {
+ log.debug("Already installed: " + bundleSymbolicName);
return true;
- } catch(AssertionError e) {
- log.debug("Not yet installed: "+bundleSymbolicName);
+ } else {
+ log.debug("Not yet installed: " + bundleSymbolicName);
return false;
}
-
}
-
- /** Check if the installed version matches the one of the bundle (file) **/
- public boolean isInstalledWithSameVersion(File bundleFile) throws Exception {
- final String bundleSymbolicName = getBundleSymbolicName(bundleFile);
- final String versionOnServer = webconsoleClient.getBundleVersion(bundleSymbolicName);
- final String versionInBundle = getBundleVersion(bundleFile);
+
+ /**
+ * Check if the installed version matches the one of the bundle (file)
+ * @param bundleFile
+ * @return
+ * @throws Exception
+ */
+ public boolean isInstalledWithSameVersion(File bundleFile) throws ClientException, IOException {
+ final String bundleSymbolicName = OsgiConsoleClient.getBundleSymbolicName(bundleFile);
+ final String versionOnServer = osgiConsoleClient.getBundleVersion(bundleSymbolicName);
+ final String versionInBundle = OsgiConsoleClient.getBundleVersionFromFile(bundleFile);
if (versionOnServer.equals(versionInBundle)) {
return true;
} else {
- log.info("Bundle installed doesn't match: "+bundleSymbolicName+
- ", versionOnServer="+versionOnServer+", versionInBundle="+versionInBundle);
+ log.warn("Installed bundle doesn't match: {}, versionOnServer={}, versionInBundle={}",
+ bundleSymbolicName, versionOnServer, versionInBundle);
return false;
}
}
-
- /** Install a list of bundles supplied as Files */
- public void installBundles(List<File> toInstall, boolean startBundles) throws Exception {
+
+ /**
+ * Install a list of bundles supplied as Files
+ * @param toInstall
+ * @param startBundles
+ * @throws Exception
+ */
+ public void installBundles(List<File> toInstall, boolean startBundles) throws ClientException, IOException, InterruptedException {
for(File f : toInstall) {
- final String bundleSymbolicName = getBundleSymbolicName(f);
+ final String bundleSymbolicName = OsgiConsoleClient.getBundleSymbolicName(f);
if (isInstalled(f)) {
if (f.getName().contains("SNAPSHOT")) {
log.info("Reinstalling (due to SNAPSHOT version): {}", bundleSymbolicName);
- webconsoleClient.uninstallBundle(bundleSymbolicName, f);
+ osgiConsoleClient.uninstallBundle(bundleSymbolicName);
} else if (!isInstalledWithSameVersion(f)) {
log.info("Reinstalling (due to version mismatch): {}", bundleSymbolicName);
- webconsoleClient.uninstallBundle(bundleSymbolicName, f);
+ osgiConsoleClient.uninstallBundle(bundleSymbolicName);
} else {
log.info("Not reinstalling: {}", bundleSymbolicName);
continue;
}
}
- webconsoleClient.installBundle(f, startBundles);
+ osgiConsoleClient.installBundle(f, startBundles);
log.info("Installed: {}", bundleSymbolicName);
}
-
+
// ensure that bundles are re-wired esp. if an existing bundle was updated
- webconsoleClient.refreshPackages();
+ osgiConsoleClient.refreshPackages();
log.info("{} additional bundles installed", toInstall.size());
}
-
- /** Uninstall a list of bundles supplied as Files */
- public void uninstallBundles(List<File> toUninstall) throws Exception {
+
+ /**
+ * Uninstall a list of bundles supplied as Files
+ * @param toUninstall
+ * @throws ClientException
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public void uninstallBundles(List<File> toUninstall) throws ClientException, IOException, InterruptedException {
for(File f : toUninstall) {
- final String bundleSymbolicName = getBundleSymbolicName(f);
+ final String bundleSymbolicName = OsgiConsoleClient.getBundleSymbolicName(f);
if (isInstalled(f)) {
log.info("Uninstalling bundle: {}", bundleSymbolicName);
- webconsoleClient.uninstallBundle(bundleSymbolicName, f);
+ osgiConsoleClient.uninstallBundle(bundleSymbolicName);
} else {
log.info("Could not uninstall: {} as it never was installed", bundleSymbolicName);
}
}
-
+
// ensure that bundles are re-wired esp. if an existing bundle was updated
- webconsoleClient.refreshPackages();
+ osgiConsoleClient.refreshPackages();
log.info("{} additional bundles uninstalled", toUninstall.size());
}
-
- /** Wait for all bundles specified in symbolicNames list to be installed in the
- * remote web console.
- */
- public void waitForBundlesInstalled(List<String> symbolicNames, int timeoutSeconds) throws Exception {
- log.info("Checking that bundles are installed (timeout {} seconds): {}", timeoutSeconds, symbolicNames);
- for(String symbolicName : symbolicNames) {
- webconsoleClient.checkBundleInstalled(symbolicName, timeoutSeconds);
- }
+
+
+ /**
+ * Wait for all bundles specified in symbolicNames list to be installed in the OSGi web console.
+ * @param symbolicNames the list of names for the bundles
+ * @param timeoutSeconds how many seconds to wait
+ * @return
+ * @throws Exception
+ */
+ public boolean waitForBundlesInstalled(List<String> symbolicNames, int timeoutSeconds) throws ClientException, InterruptedException {
+ log.info("Checking that the following bundles are installed (timeout {} seconds): {}", timeoutSeconds, symbolicNames);
+ for (String symbolicName : symbolicNames) {
+ boolean started = osgiConsoleClient.checkBundleInstalled(symbolicName, 500, 2 * timeoutSeconds);
+ if (!started) return false;
+ }
+ return true;
}
-
- public void startAllBundles(List<String> symbolicNames, int timeoutSeconds) throws Exception {
+
+ /**
+ * Start all the bundles in a {{List}}
+ * @param symbolicNames the list of bundles to start
+ * @param timeoutSeconds number of seconds until it times out
+ * @throws ClientException
+ * @throws InterruptedException
+ */
+ public void startAllBundles(final List<String> symbolicNames, int timeoutSeconds) throws ClientException, InterruptedException {
log.info("Starting bundles (timeout {} seconds): {}", timeoutSeconds, symbolicNames);
-
- final long timeout = System.currentTimeMillis() + timeoutSeconds * 1000L;
- final List<String> toStart = new LinkedList<String>();
- while(System.currentTimeMillis() < timeout) {
- toStart.clear();
- for(String name : symbolicNames) {
- final String state = webconsoleClient.getBundleState(name);
- if(!state.equalsIgnoreCase(ACTIVE_STATE)) {
- toStart.add(name);
- break;
+ class StartAllBundlesPoller extends AbstractPoller {
+ private ClientException exception;
+ public StartAllBundlesPoller(List<String> symbolicNames, long waitInterval, long waitCount) {
+ super(waitInterval, waitCount);
+ }
+
+ @Override
+ public boolean call() {
+ for (String bundle : symbolicNames) {
+ final String state;
+ try {
+ state = osgiConsoleClient.getBundleState(bundle);
+ if (!state.equalsIgnoreCase(ACTIVE_STATE)) {
+ osgiConsoleClient.startBundle(bundle);
+ }
+ } catch (ClientException e) {
+ this.exception = e;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean condition() {
+ for (String bundle : symbolicNames) {
+ final String state;
+ try {
+ state = osgiConsoleClient.getBundleState(bundle);
+ if (!state.equalsIgnoreCase(ACTIVE_STATE)) {
+ return false;
+ }
+ } catch (ClientException e) {
+ this.exception = e;
+ return false;
+ }
}
+ return true;
+ }
+
+ public ClientException getException() {
+ return exception;
}
-
- if(toStart.isEmpty()) {
- log.info("Ok - all bundles are in the {} state", ACTIVE_STATE);
- break;
- }
-
- for(String name : toStart) {
- webconsoleClient.startBundle(name);
- }
-
- Thread.sleep(500L);
- }
-
- if(!toStart.isEmpty()) {
- throw new Exception("Some bundles did not start: " + toStart);
- }
- }
-
- public String getBundleSymbolicName(File bundleFile) throws IOException {
- String name = null;
- final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
- try {
- final Manifest m = jis.getManifest();
- if (m == null) {
- throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
- }
- name = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
- } finally {
- jis.close();
- }
- return name;
- }
-
- public String getBundleVersion(File bundleFile) throws IOException {
- String version = null;
- final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
- try {
- final Manifest m = jis.getManifest();
- if(m == null) {
- throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
- }
- version = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
- } finally {
- jis.close();
}
- return version;
+ StartAllBundlesPoller poller = new StartAllBundlesPoller(symbolicNames, 1000, timeoutSeconds);
+ if (!poller.callUntilCondition()) {
+ throw new ClientException("Some bundles did not start or timed out", poller.getException());
+ }
+
}
+
+
+
+
}
\ No newline at end of file
Modified: sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/OsgiConsoleClient.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/OsgiConsoleClient.java?rev=1743676&r1=1743675&r2=1743676&view=diff
==============================================================================
--- sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/OsgiConsoleClient.java (original)
+++ sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/osgi/OsgiConsoleClient.java Fri May 13 14:02:03 2016
@@ -18,7 +18,11 @@
package org.apache.sling.testing.clients.osgi;
import org.apache.http.Header;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.sling.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
import org.apache.sling.testing.clients.ClientException;
import org.apache.sling.testing.clients.SlingHttpResponse;
import org.apache.sling.testing.clients.util.JsonUtils;
@@ -27,18 +31,27 @@ import org.apache.sling.testing.clients.
import org.apache.sling.testing.clients.SlingClientConfig;
import org.apache.sling.testing.clients.util.FormEntityBuilder;
import org.apache.sling.testing.clients.util.HttpUtils;
+import org.apache.sling.testing.clients.util.poller.PathPoller;
import org.codehaus.jackson.JsonNode;
+import org.osgi.framework.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
import java.net.URI;
import java.util.*;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
import static org.apache.http.HttpStatus.SC_MOVED_TEMPORARILY;
import static org.apache.http.HttpStatus.SC_OK;
/**
* A client that wraps the Felix OSGi Web Console REST API calls.
+ * @see <a href=http://felix.apache.org/documentation/subprojects/apache-felix-web-console/web-console-restful-api.html>
+ * Web Console RESTful API</a>
*/
public class OsgiConsoleClient extends SlingClient {
@@ -63,6 +76,12 @@ public class OsgiConsoleClient extends S
*/
private final String URL_COMPONENTS = CONSOLE_ROOT_URL + "/components";
+
+ public static final String JSON_KEY_ID = "id";
+ public static final String JSON_KEY_VERSION = "version";
+ public static final String JSON_KEY_DATA = "data";
+ public static final String JSON_KEY_STATE = "state";
+
/**
* Default constructor. Simply calls {@link SlingClient#SlingClient(URI, String, String)}
*
@@ -141,6 +160,10 @@ public class OsgiConsoleClient extends S
return new ComponentInfo(JsonUtils.getJsonNodeFromString(resp.getContent()));
}
+ //
+ // OSGi configurations
+ //
+
/**
* Returns a map of all properties set for the config referenced by the PID, where the map keys
* are the property names.
@@ -276,16 +299,282 @@ public class OsgiConsoleClient extends S
*
* @param pid pid
* @param expectedStatus expected response status
+ * @return the sling response
* @throws ClientException if the response status does not match any of the expectedStatus
*/
- public void deleteConfiguration(String pid, int... expectedStatus) throws ClientException {
+ public SlingHttpResponse deleteConfiguration(String pid, int... expectedStatus) throws ClientException {
FormEntityBuilder builder = FormEntityBuilder.create();
builder.addParameter("apply", "1");
builder.addParameter("delete", "1");
// make the request
SlingHttpResponse resp = this.doPost(URL_CONFIGURATION + "/" + pid, builder.build());
- // check the returned status
+ // check the returned status
HttpUtils.verifyHttpStatus(resp, HttpUtils.getExpectedStatus(200, expectedStatus));
+ return resp;
+ }
+
+ //
+ // Bundles
+ //
+
+ /**
+ * Uninstall a bundle
+ * @param symbolicName
+ * @return the sling response
+ * @throws ClientException
+ */
+ public SlingHttpResponse uninstallBundle(String symbolicName) throws ClientException {
+ final long bundleId = getBundleId(symbolicName);
+ LOG.info("Uninstalling bundle {} with bundleId {}", symbolicName, bundleId);
+ FormEntityBuilder builder = FormEntityBuilder.create();
+ builder.addParameter("action", "uninstall");
+ return this.doPost(getBundlePath(symbolicName), builder.build(), 200);
+ }
+
+ /**
+ * Install a bundle using the Felix webconsole HTTP interface
+ * @param f the bundle file
+ * @param startBundle whether to start the bundle or not
+ * @return the sling response
+ * @throws ClientException
+ */
+ public SlingHttpResponse installBundle(File f, boolean startBundle) throws ClientException {
+ return installBundle(f, startBundle, 0);
+ }
+
+ /**
+ * Install a bundle using the Felix webconsole HTTP interface, with a specific start level
+ * @param f
+ * @param startBundle
+ * @param startLevel
+ * @return the sling response
+ * @throws ClientException
+ */
+ public SlingHttpResponse installBundle(File f, boolean startBundle, int startLevel) throws ClientException {
+ // Setup request for Felix Webconsole bundle install
+ MultipartEntityBuilder builder = MultipartEntityBuilder.create()
+ .addTextBody("action", "install")
+ .addBinaryBody("bundlefile", f);
+ if (startBundle) {
+ builder.addTextBody("bundlestart", "true");
+ }
+ if (startLevel > 0) {
+ builder.addTextBody("bundlestartlevel", String.valueOf(startLevel));
+ LOG.info("Installing bundle {} at start level {}", f.getName(), startLevel);
+ } else {
+ LOG.info("Installing bundle {} at default start level", f.getName());
+ }
+
+ return this.doPost(URL_BUNDLES, builder.build(), 302);
+
+ }
+
+ /**
+ * Install a bundle using the Felix webconsole HTTP interface and wait for it to be installed
+ * @param f the bundle file
+ * @param startBundle whether to start the bundle or not
+ * @param startLevel the start level of the bundle. negative values mean default start level
+ * @param waitTime how long to wait between retries of checking the bundle
+ * @param retries how many times to check for the bundle to be installed, until giving up
+ * @return true if the bundle was successfully installed, false otherwise
+ * @throws ClientException
+ */
+ public boolean installBundleWithRetry(File f, boolean startBundle, int startLevel, int waitTime, int retries)
+ throws ClientException, InterruptedException {
+ installBundle(f, startBundle, startLevel);
+ try {
+ return this.checkBundleInstalled(OsgiConsoleClient.getBundleSymbolicName(f), waitTime, retries);
+ } catch (IOException e) {
+ throw new ClientException("Cannot get bundle symbolic name", e);
+ }
+ }
+
+ /**
+ * Check that specified bundle is installed and retries every {{waitTime}} milliseconds, until the
+ * bundle is installed or the number of retries was reached
+ * @param symbolicName the name of the bundle
+ * @param waitTime How many milliseconds to wait between retries
+ * @param retries the number of retries
+ * @return true if the bundle was installed until the retries stop, false otherwise
+ * @throws InterruptedException
+ */
+ public boolean checkBundleInstalled(String symbolicName, int waitTime, int retries) throws InterruptedException {
+ final String path = getBundlePath(symbolicName, ".json");
+ return new PathPoller(this, path, waitTime, retries).callAndWait();
+ }
+
+ /**
+ * Get the id of the bundle
+ * @param symbolicName
+ * @return
+ * @throws Exception
+ */
+ public long getBundleId(String symbolicName) throws ClientException {
+ final JSONObject bundle = getBundleData(symbolicName);
+ try {
+ return bundle.getLong(JSON_KEY_ID);
+ } catch (JSONException e) {
+ throw new ClientException("Cannot get id from json", e);
+ }
+ }
+
+ /**
+ * Get the version of the bundle
+ * @param symbolicName
+ * @return
+ * @throws ClientException
+ */
+ public String getBundleVersion(String symbolicName) throws ClientException {
+ final JSONObject bundle = getBundleData(symbolicName);
+ try {
+ return bundle.getString(JSON_KEY_VERSION);
+ } catch (JSONException e) {
+ throw new ClientException("Cannot get version from json", e);
+ }
+ }
+
+ /**
+ * Get the state of the bundle
+ * @param symbolicName
+ * @return
+ * @throws Exception
+ */
+ public String getBundleState(String symbolicName) throws ClientException {
+ final JSONObject bundle = getBundleData(symbolicName);
+ try {
+ return bundle.getString(JSON_KEY_STATE);
+ } catch (JSONException e) {
+ throw new ClientException("Cannot get state from json", e);
+ }
+ }
+
+ /**
+ * Starts a bundle
+ * @param symbolicName the name of the bundle
+ * @throws ClientException
+ */
+ public void startBundle(String symbolicName) throws ClientException {
+ // To start the bundle we POST action=start to its URL
+ final String path = getBundlePath(symbolicName);
+ LOG.info("Starting bundle {} via {}", symbolicName, path);
+ this.doPost(path, FormEntityBuilder.create().addParameter("action", "start").build(), SC_OK);
+ }
+
+ /**
+ * Starts a bundle and waits for it to be started
+ * @param symbolicName the name of the bundle
+ * @param waitTime How many milliseconds to wait between retries
+ * @param retries the number of retries
+ * @throws ClientException, InterruptedException
+ */
+ public void startBundlewithWait(String symbolicName, int waitTime, int retries)
+ throws ClientException, InterruptedException {
+ // start a bundle
+ startBundle(symbolicName);
+ // wait for it to be in the started state
+ checkBundleInstalled(symbolicName, waitTime, retries);
+ }
+
+ /**
+ * Calls PackageAdmin.refreshPackages to force re-wiring of all the bundles.
+ * @throws ClientException
+ */
+ public void refreshPackages() throws ClientException {
+ LOG.info("Refreshing packages.");
+ FormEntityBuilder builder = FormEntityBuilder.create();
+ builder.addParameter("action", "refreshPackages");
+ this.doPost(URL_BUNDLES, builder.build(), 200);
+ }
+
+
+ //
+ // private methods
+ //
+
+ private String getBundlePath(String symbolicName, String extension) {
+ return getBundlePath(symbolicName) + extension;
+ }
+
+ private String getBundlePath(String symbolicName) {
+ return URL_BUNDLES + "/" + symbolicName;
+ }
+
+ private JSONObject getBundleData(String symbolicName) throws ClientException {
+ // This returns a data structure like
+ // {"status":"Bundle information: 173 bundles in total - all 173 bundles active.","s":[173,171,2,0,0],"data":
+ // [
+ // {"id":0,"name":"System Bundle","fragment":false,"stateRaw":32,"state":"Active","version":"3.0.7","symbolicName":"org.apache.felix.framework","category":""},
+ // ]}
+ final String path = getBundlePath(symbolicName, ".json");
+ final String content = this.doGet(path, SC_OK).getContent();
+
+ try {
+ final JSONObject root = new JSONObject(content);
+
+ if (!root.has(JSON_KEY_DATA)) {
+ throw new ClientException(path + " does not provide '" + JSON_KEY_DATA + "' element, JSON content=" + content);
+ }
+
+ final JSONArray data = root.getJSONArray(JSON_KEY_DATA);
+ if (data.length() < 1) {
+ throw new ClientException(path + "." + JSON_KEY_DATA + " is empty, JSON content=" + content);
+ }
+
+ final JSONObject bundle = data.getJSONObject(0);
+ if (!bundle.has(JSON_KEY_STATE)) {
+ throw new ClientException(path + ".data[0].state missing, JSON content=" + content);
+ }
+
+ return bundle;
+ } catch (JSONException e) {
+ throw new ClientException("Cannot get json", e);
+ }
+ }
+
+ //
+ // static methods
+ //
+
+ /**
+ * Get the symbolic name from a bundle file
+ * @param bundleFile
+ * @return
+ * @throws IOException
+ */
+ public static String getBundleSymbolicName(File bundleFile) throws IOException {
+ String name = null;
+ final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
+ try {
+ final Manifest m = jis.getManifest();
+ if (m == null) {
+ throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
+ }
+ name = m.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME);
+ } finally {
+ jis.close();
+ }
+ return name;
+ }
+
+ /**
+ * Get the version form a bundle file
+ * @param bundleFile
+ * @return
+ * @throws IOException
+ */
+ public static String getBundleVersionFromFile(File bundleFile) throws IOException {
+ String version = null;
+ final JarInputStream jis = new JarInputStream(new FileInputStream(bundleFile));
+ try {
+ final Manifest m = jis.getManifest();
+ if(m == null) {
+ throw new IOException("Manifest is null in " + bundleFile.getAbsolutePath());
+ }
+ version = m.getMainAttributes().getValue(Constants.BUNDLE_VERSION);
+ } finally {
+ jis.close();
+ }
+ return version;
}
Added: sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java
URL: http://svn.apache.org/viewvc/sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java?rev=1743676&view=auto
==============================================================================
--- sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java (added)
+++ sling/trunk/testing/http/clients/src/main/java/org/apache/sling/testing/clients/util/poller/PathPoller.java Fri May 13 14:02:03 2016
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.testing.clients.util.poller;
+
+import org.apache.sling.testing.clients.AbstractSlingClient;
+import org.apache.sling.testing.clients.ClientException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Allows polling for a resource
+ */
+public class PathPoller extends AbstractPoller {
+ private static final Logger LOG = LoggerFactory.getLogger(PathPoller.class);
+ private final AbstractSlingClient client;
+ private final String path;
+ private final int[] expectedStatus;
+ private Exception exception;
+
+ public PathPoller(AbstractSlingClient client, String path, long waitInterval, long waitCount, int... expectedStatus) {
+ super(waitInterval, waitCount);
+ this.client = client;
+ this.path = path;
+ this.expectedStatus = expectedStatus;
+ }
+
+
+ @Override
+ public boolean call() {
+ return true;
+ }
+
+ @Override
+ public boolean condition() {
+ try {
+ client.doGet(path, expectedStatus);
+ } catch (ClientException e) {
+ LOG.warn("Get on {} failed: {}", path, e);
+ this.exception = e;
+ return false;
+ }
+ return true;
+ }
+
+ public Exception getException() {
+ return exception;
+ }
+}