You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2009/06/27 17:53:26 UTC
svn commit: r788992 [23/25] - in /incubator/ace/trunk: gateway/ gateway/src/
gateway/src/net/ gateway/src/net/luminis/ gateway/src/net/luminis/liq/
gateway/src/net/luminis/liq/bootstrap/
gateway/src/net/luminis/liq/bootstrap/multigateway/ gateway/src/n...
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,39 @@
+package net.luminis.liq.test.bundlestop;
+
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.service.log.LogService;
+
+/**
+ * This bundle stops the systembundle whenever the deploymentadmin is done deploying.
+ */
+public class Activator extends DependencyActivatorBase {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws Exception {
+ String[] topics = new String[] {EventConstants.EVENT_TOPIC, "org/osgi/service/deployment/COMPLETE"};
+ Dictionary properties = new Hashtable();
+ properties.put(EventConstants.EVENT_TOPIC, topics);
+
+ SystemBundleStopper stopper = new SystemBundleStopper();
+ context.addBundleListener(stopper);
+ manager.add(createService()
+ .setInterface(EventHandler.class.getName(), properties)
+ .setImplementation(stopper)
+ .add(createServiceDependency()
+ .setService(LogService.class)
+ .setRequired(false)));
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ }
+}
+
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/SystemBundleStopper.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/SystemBundleStopper.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/SystemBundleStopper.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/bundlestop/SystemBundleStopper.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,50 @@
+package net.luminis.liq.test.bundlestop;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.BundleListener;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+public class SystemBundleStopper implements EventHandler, BundleListener {
+
+ private BundleContext m_context;
+ private boolean m_deploymentPackageIsInstalled = false;
+ private boolean m_isFrameWorkStarted = false;
+
+ /**
+ * This service only listens for completed events. If it gets one,
+ * the systembundle should be stopped.
+ */
+ public synchronized void handleEvent(Event arg0) {
+ if (m_isFrameWorkStarted || (m_context.getBundle(0).getState() == Bundle.ACTIVE)) {
+ stopSystemBundle();
+ } else {
+ m_deploymentPackageIsInstalled = true;
+ }
+ }
+
+ public synchronized void bundleChanged(BundleEvent event) {
+ if ((event.getBundle().getBundleId() == 0) && (event.getType() == BundleEvent.STARTED)) {
+ if (m_deploymentPackageIsInstalled) {
+ stopSystemBundle();
+ } else {
+ m_isFrameWorkStarted = true;
+ }
+ }
+ }
+
+ public void stopSystemBundle() {
+ try {
+ m_context.getBundle(0).stop();
+ }
+ catch (BundleException e) {
+ System.err.println("Error stopping systembundle. Performing an un-clean exit now.");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,29 @@
+package net.luminis.liq.test.deployment;
+
+import net.luminis.test.osgi.dm.TestActivatorBase;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.http.HttpService;
+
+public class Activator extends TestActivatorBase {
+ @SuppressWarnings("unchecked")
+ private Class[] m_classes = new Class[] { DeploymentIntegrationTest.class };
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class[] getTestClasses() {
+ return m_classes;
+ }
+
+ @Override
+ protected void initServices(BundleContext context, DependencyManager manager) {
+ manager.add(createService()
+ .setImplementation(DeploymentIntegrationTest.class)
+ .add(createServiceDependency().setService(HttpService.class).setRequired(true))
+ .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(DeploymentAdmin.class).setRequired(true)));
+ }
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/DeploymentIntegrationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/DeploymentIntegrationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/DeploymentIntegrationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/deployment/DeploymentIntegrationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,361 @@
+package net.luminis.liq.test.deployment;
+
+import static net.luminis.liq.test.utils.TestUtils.INTEGRATION;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import net.luminis.liq.deployment.provider.ArtifactData;
+import net.luminis.liq.deployment.provider.impl.ArtifactDataImpl;
+import net.luminis.liq.discovery.property.constants.DiscoveryConstants;
+import net.luminis.liq.http.listener.constants.HttpConstants;
+import net.luminis.liq.identification.property.constants.IdentificationConstants;
+import net.luminis.liq.scheduler.constants.SchedulerConstants;
+import net.luminis.liq.test.utils.deployment.BundleStreamGenerator;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.deploymentadmin.DeploymentException;
+import org.osgi.service.deploymentadmin.DeploymentPackage;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+public class DeploymentIntegrationTest implements BundleListener, EventHandler {
+
+ public static final String HOST = "localhost";
+ public static final int PORT = 8080;
+ public static final String GWID = "gw-id";
+ public static final long POLL_INTERVAL = 1000;
+ private static Object instance;
+ private volatile ConfigurationAdmin m_config;
+ private volatile DeploymentAdmin m_deployment;
+ private volatile BundleContext m_context;
+ private volatile File m_tempDir;
+ private final Semaphore m_semaphore = new Semaphore(0);
+ Map<Integer, List<Bundle>> m_events = new HashMap<Integer, List<Bundle>>();
+ private ServiceRegistration m_deploymentAdminProxyRegistration;
+
+ public DeploymentIntegrationTest() throws IOException {
+ synchronized (DeploymentIntegrationTest.class) {
+ if (instance == null) {
+ instance = this;
+ }
+ }
+ }
+
+ @BeforeTest(alwaysRun = true)
+ public void setUp() throws IOException {
+ m_tempDir = File.createTempFile("test", "");
+ m_tempDir.delete();
+ m_tempDir.mkdir();
+ }
+
+ @AfterTest(alwaysRun = true)
+ public void tearDown() {
+ deleteDirOrFile(m_tempDir);
+ }
+
+ private void deleteDirOrFile(File root) {
+ if (root.isDirectory()) {
+ for (File file : root.listFiles()) {
+ deleteDirOrFile(file);
+ }
+ }
+ root.delete();
+ }
+
+ @Factory
+ public Object[] createInstance() {
+ synchronized (DeploymentIntegrationTest.class) {
+ return new Object[] { instance };
+ }
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void deployVersionSeries() throws Exception {
+ Bundle[] start = m_context.getBundles();
+
+ // Test deploy initial version 1.0.0 with 3 bundles in version 1.0.0
+ String[] versions = new String[] { "bundle1", "bundle2", "bundle3" };
+ generateBundles(createVersion("1.0.0"), versions, 0, versions.length, "1.0.0");
+ executeTest();
+ // start + versions bundles may be present
+ assertState(start, m_context.getBundles(), versions);
+ assert m_events.get(BundleEvent.STARTED).size() == versions.length : "Received unexpected amount of starting events.";
+ assert m_events.get(BundleEvent.STOPPED) == null : "Received unexpected amount of stopping events";
+ m_events.clear();
+
+ // Test correct presence of deployment packages in deployment admin
+ assert m_deployment.listDeploymentPackages().length == 1 : "Deployment admin reports unexpected number of deployment packages";
+ assert m_deployment.getDeploymentPackage(GWID) != null : "Deployment admin did not return the expected deployment package";
+ Bundle[] bundles = m_context.getBundles();
+ Bundle bundle = null;
+ for (int i = 0; i < bundles.length; i++) {
+ if("bundle1".equals(bundles[i].getSymbolicName())) {
+ bundle = bundles[i];
+ break;
+ }
+ }
+ assert m_deployment.getDeploymentPackage(bundle) != null : "Deployment admin did not return the expected deployment package";
+
+ // Test deploy a version 1.1.0 on top of the previous 1.0.0 with one new bundle and one updated to version 1.1.0 (i.e., two fix-package bundles)
+ versions = new String[] { "bundle1", "bundle2", "bundle3", "bundle4" };
+ File version = createVersion("1.1.0");
+ generateBundle(new File(version, "0.jar"), versions[0], "1.1.0");
+ generateBundles(version, versions, 1, versions.length, "1.0.0");
+ executeTest();
+ // start + versions bundles may be present
+ assertState(start, m_context.getBundles(), versions);
+ assert m_events.get(BundleEvent.UPDATED).size() == 1 : "Received unexpected amount of updated events.";
+ assert m_events.get(BundleEvent.UPDATED).get(0).getSymbolicName().equals(versions[0]) : "Received unexpected update event.";
+ assert m_events.get(BundleEvent.STOPPED).size() == versions.length - 1 : "Received unexpected amount of stopped events.";
+ assert m_events.get(BundleEvent.STARTED).size() == versions.length : "Received unexpected amount of started events: expected " + versions.length + ", received " + m_events.get(BundleEvent.STARTED).size() + ".";
+ m_events.clear();
+
+ // Test to deploy an empty version 2.0.0, but break the stream which should cancel the deployment
+ createVersion("2.0.0");
+ executeTestWithFailingStream();
+ m_events.clear();
+
+ // Test to deploy an empty version 2.0.0 which should remove all the previously installed bundles
+ executeTest();
+
+ // only start bundles may be present
+ assertState(start, m_context.getBundles(), new String[0]);
+ assert m_events.get(BundleEvent.INSTALLED) == null : "Received unexpected amount of installed events.";
+ assert m_events.get(BundleEvent.STARTED) == null : "Received unexpected amount of starting events.";
+ assert m_events.get(BundleEvent.UNINSTALLED).size() == versions.length : "Received unexpected amount of uninstalled events: " + m_events.get(BundleEvent.UNINSTALLED).size() + " instead of " + versions.length;
+ assert m_events.get(BundleEvent.STOPPED).size() == versions.length : "Received unexpected amount of stopped events: " + m_events.get(BundleEvent.STOPPED).size() + " instead of " + versions.length;
+ m_events.clear();
+
+ }
+
+ public void bundleChanged(BundleEvent event) {
+ synchronized (m_events) {
+ if (!m_events.containsKey(Integer.valueOf(event.getType()))) {
+ m_events.put(Integer.valueOf(event.getType()), new ArrayList<Bundle>());
+ }
+ m_events.get(Integer.valueOf(event.getType())).add(event.getBundle());
+ }
+ }
+
+ public void handleEvent(Event event) {
+ System.out.println("Event: " + event);
+ m_semaphore.release();
+ }
+
+ private void generateBundles(File dir, String[] versions, int off, int len, String version) throws Exception {
+ for (int i = off; i < len; i++) {
+ generateBundle(new File(dir, i + ".jar"), versions[i], version);
+ }
+ }
+
+ private void assertState(Bundle[] start, Bundle[] current, String[] versions) {
+ assert (start.length + versions.length) == current.length : "System has " + (((start.length + versions.length) < current.length) ? "more" : "less") + " bundes then expected: expected " + (start.length + versions.length) + ", found " + current.length;
+ for (int i = 0; i < start.length; i++) {
+ assert current[i].getSymbolicName().equals(start[i].getSymbolicName()) : "Bundle names do not match: " + current[i].getSymbolicName() + " v.s. " + start[i];
+ }
+ List<String> index = Arrays.asList(versions);
+ for (int i = start.length; i < current.length; i++) {
+ assert index.contains(current[i].getSymbolicName()) : "Bundle names do not match: " + current[i].getSymbolicName();
+ }
+ }
+
+ private File createVersion(String version) {
+ File versionFile = new File(new File(m_tempDir, GWID), version);
+ versionFile.mkdirs();
+ return versionFile;
+ }
+
+ @SuppressWarnings("serial")
+ private void executeTest() throws IOException, InterruptedException {
+ m_context.addBundleListener(this);
+ ServiceRegistration reg = m_context.registerService(EventHandler.class.getName(), this, new Properties() {
+ {
+ put(EventConstants.EVENT_TOPIC, "org/osgi/service/deployment/COMPLETE");
+ put(EventConstants.EVENT_FILTER, "(successful=true)");
+ }
+ });
+ configureGateway();
+ configureServer();
+ assert m_semaphore.tryAcquire(8, TimeUnit.SECONDS) : "Timed out while waiting for deployment to complete.";
+ unconfigureServer();
+ unconfigureGateway();
+ reg.unregister();
+ m_context.removeBundleListener(this);
+ }
+
+ private void executeTestWithFailingStream() throws IOException, InterruptedException {
+ m_context.addBundleListener(this);
+ registerDeploymentAdminProxy(new FailingDeploymentAdmin(m_deployment, 50));
+ configureGateway();
+ configureServer();
+ assert m_semaphore.tryAcquire(8, TimeUnit.SECONDS) : "Timed out while waiting for deployment to abort.";
+ unconfigureServer();
+ unconfigureGateway();
+ unregisterDeploymentAdminProxy();
+ m_context.removeBundleListener(this);
+ }
+
+ /**
+ * Input stream wrapper that creates an input stream that breaks after N bytes. When it
+ * breaks, it will throw an IO exception and sends a notification to the semaphore that
+ * allows the overall test to continue.
+ */
+ private class BrokenInputStream extends InputStream {
+ private final InputStream m_normalStream;
+ private int m_bytesUntilBreakdown;
+ private boolean m_isBroken;
+
+ public BrokenInputStream(InputStream normalStream, int bytesUntilBreakdown) {
+ m_normalStream = normalStream;
+ m_bytesUntilBreakdown = bytesUntilBreakdown;
+ }
+
+ private synchronized void breakStream() throws IOException {
+ if (!m_isBroken) {
+ m_isBroken = true;
+
+ // release the semaphore to continue the test
+ m_semaphore.release();
+ }
+ throw new IOException("Stream broken.");
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (m_bytesUntilBreakdown-- < 1) {
+ breakStream();
+ }
+ return m_normalStream.read();
+ }
+
+ @Override
+ public void close() throws IOException {
+ m_normalStream.close();
+ breakStream();
+ }
+
+ }
+
+ /**
+ * Wrapper around the deployment admin that will fail once, after N bytes.
+ */
+ private class FailingDeploymentAdmin implements DeploymentAdmin {
+ private final DeploymentAdmin m_deploymentAdmin;
+ private boolean m_wasBroken;
+ private final int m_failAfterBytes;
+
+ public FailingDeploymentAdmin(DeploymentAdmin deploymentAdmin, int failAfterBytes) {
+ m_deploymentAdmin = deploymentAdmin;
+ m_failAfterBytes = failAfterBytes;
+ }
+
+ public boolean cancel() {
+ return m_deploymentAdmin.cancel();
+ }
+
+ public DeploymentPackage getDeploymentPackage(String symbName) {
+ return m_deploymentAdmin.getDeploymentPackage(symbName);
+ }
+
+ public DeploymentPackage getDeploymentPackage(Bundle bundle) {
+ return m_deploymentAdmin.getDeploymentPackage(bundle);
+ }
+
+ public DeploymentPackage installDeploymentPackage(InputStream in) throws DeploymentException {
+ synchronized (this) {
+ if (!m_wasBroken) {
+ m_wasBroken = true;
+ in = new BrokenInputStream(in, m_failAfterBytes);
+ }
+ }
+ return m_deploymentAdmin.installDeploymentPackage(in);
+ }
+
+ public DeploymentPackage[] listDeploymentPackages() {
+ return m_deploymentAdmin.listDeploymentPackages();
+ }
+ }
+
+ private void configureGateway() throws IOException {
+ // configure discovery bundle
+ setProperty(DiscoveryConstants.DISCOVERY_PID, new Object[][] { { DiscoveryConstants.DISCOVERY_URL_KEY, "http://" + HOST + ":" + PORT } });
+ // configure identification bundle
+ setProperty(IdentificationConstants.IDENTIFICATION_PID, new Object[][] { { IdentificationConstants.IDENTIFICATION_GATEWAYID_KEY, GWID } });
+ // configure scheduler
+ setProperty(SchedulerConstants.SCHEDULER_PID, new Object[][] {
+ { "net.luminis.liq.gateway.auditlog.task.AuditLogSyncTask", POLL_INTERVAL },
+ { "net.luminis.liq.deployment.task.DeploymentUpdateTask", POLL_INTERVAL }
+ });
+ }
+
+ private void unconfigureGateway() throws IOException {
+ m_config.getConfiguration(DiscoveryConstants.DISCOVERY_PID, null).delete();
+ m_config.getConfiguration(IdentificationConstants.IDENTIFICATION_PID, null).delete();
+ m_config.getConfiguration(SchedulerConstants.SCHEDULER_PID, null).delete();
+ }
+
+ private void unconfigureServer() throws IOException {
+ m_config.getConfiguration("net.luminis.liq.deployment.servlet", null).delete();
+ m_config.getConfiguration("net.luminis.liq.deployment.provider.filebased", null).delete();
+ }
+
+ private void configureServer() throws IOException {
+ // configure data bundle
+ setProperty(net.luminis.liq.deployment.servlet.Activator.PID, new Object[][] { { HttpConstants.ENDPOINT, "/deployment" } });
+ // configure file based backend
+ setProperty(net.luminis.liq.deployment.provider.filebased.Activator.PID, new Object[][] { { "BaseDirectoryName", m_tempDir.getAbsolutePath() } });
+ }
+
+ @SuppressWarnings("unchecked")
+ private void setProperty(String pid, Object[][] props) throws IOException {
+ Configuration configuration = m_config.getConfiguration(pid, null);
+ Dictionary dictionary = configuration.getProperties();
+ if (dictionary == null) {
+ dictionary = new Hashtable();
+ }
+ for (Object[] pair : props) {
+ dictionary.put(pair[0], pair[1]);
+ }
+ configuration.update(dictionary);
+ }
+
+ private ArtifactData generateBundle(File file, String symbolicName, String version) throws Exception {
+ ArtifactData bundle = new ArtifactDataImpl(file.getName(), symbolicName, version, file.toURI().toURL(), false);
+ BundleStreamGenerator.generateBundle(bundle);
+ return bundle;
+ }
+
+ private void registerDeploymentAdminProxy(DeploymentAdmin proxy) {
+ Properties props = new Properties();
+ props.put(org.osgi.framework.Constants.SERVICE_RANKING, 1);
+ m_deploymentAdminProxyRegistration = m_context.registerService(DeploymentAdmin.class.getName(), proxy, props);
+ }
+
+ private void unregisterDeploymentAdminProxy() {
+ m_deploymentAdminProxyRegistration.unregister();
+ }
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,29 @@
+package net.luminis.liq.test.http.listener;
+
+import net.luminis.test.osgi.dm.TestActivatorBase;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+/**
+ * Activator for the integration test.
+ */
+public class Activator extends TestActivatorBase {
+
+ @Override
+ protected void initServices(BundleContext context, DependencyManager manager) {
+ manager.add(createService()
+ .setImplementation(new ServletConfiguratorIntegrationTest(manager))
+ .add(createServiceDependency()
+ .setService(LogService.class)
+ .setRequired(false)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class[] getTestClasses() {
+ return new Class[] { ServletConfiguratorIntegrationTest.class };
+ }
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/EchoServlet.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/EchoServlet.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/EchoServlet.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/EchoServlet.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,34 @@
+package net.luminis.liq.test.http.listener;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class EchoServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) {
+ ServletOutputStream output = null;
+ try {
+ output = response.getOutputStream();
+ output.println(request.getQueryString());
+ }
+ catch (IOException e) {
+ // not much we can do, the test will fail anyway
+ } finally {
+ if (output != null) {
+ try {
+ output.close();
+ }
+ catch (IOException e) {
+ // not much we can do, the test will fail anyway
+ }
+ }
+ }
+ }
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/MockHttpService.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/MockHttpService.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/MockHttpService.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/MockHttpService.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,43 @@
+package net.luminis.liq.test.http.listener;
+
+import java.util.Dictionary;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+public class MockHttpService implements HttpService {
+
+ private boolean m_registerCalled = false;
+ private boolean m_unregisterCalled = false;
+
+ public HttpContext createDefaultHttpContext() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void registerResources(String arg0, String arg1, HttpContext arg2) throws NamespaceException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void registerServlet(String arg0, Servlet arg1, Dictionary arg2, HttpContext arg3) throws ServletException, NamespaceException {
+ m_registerCalled = true;
+ }
+
+ public void unregister(String arg0) {
+ m_unregisterCalled = true;
+ }
+
+ public boolean isRegisterCalled() {
+ return m_registerCalled;
+ }
+
+ public boolean isUnregisterCalled() {
+ return m_unregisterCalled;
+ }
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/ServletConfiguratorIntegrationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/ServletConfiguratorIntegrationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/ServletConfiguratorIntegrationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/http/listener/ServletConfiguratorIntegrationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,231 @@
+package net.luminis.liq.test.http.listener;
+
+import static net.luminis.liq.test.utils.TestUtils.INTEGRATION;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.http.HttpServlet;
+
+import net.luminis.liq.http.listener.constants.HttpConstants;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.http.HttpService;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+/**
+ * A test for the ServletConfigurator.
+ */
+public class ServletConfiguratorIntegrationTest {
+
+ private static Object instance;
+
+ private BundleContext m_context;
+
+ private DependencyManager m_dependencyManager;
+
+ // the echo servlet
+ private HttpServlet m_echoServlet;
+ // echo servlet service-reference
+ private Service m_echoServletService;
+ // mock http service
+ private MockHttpService m_mockHttp;
+
+ //mock http service-reference
+ private Service m_mockHttpService;
+ // regular http service service-reference
+ private Bundle m_httpBundle;
+
+ public ServletConfiguratorIntegrationTest() {
+ if (instance == null) {
+ instance = this;
+ }
+ }
+
+ @Factory
+ public Object[] createInstances() {
+ return new Object[] { instance };
+ }
+
+ /**
+ * store the dependencymanager to publish our own test services
+ */
+ public ServletConfiguratorIntegrationTest(DependencyManager dependencyManager) {
+ if (instance == null) {
+ instance = this;
+ }
+ m_dependencyManager = dependencyManager;
+ // start will be called when the dependency manager is ready
+ }
+
+ public void start() {
+ m_echoServlet = new EchoServlet();
+ Dictionary<String, String> dictionary = new Hashtable<String, String>();
+ dictionary.put(HttpConstants.ENDPOINT, "/echoServlet");
+ m_echoServletService = m_dependencyManager.createService()
+ .setImplementation(m_echoServlet)
+ .setInterface(HttpServlet.class.getName(), dictionary);
+
+ m_mockHttp = new MockHttpService();
+ m_mockHttpService = m_dependencyManager.createService()
+ .setImplementation(m_mockHttp)
+ .setInterface(HttpService.class.getName(), null);
+ }
+
+ private void setUp() throws InvalidSyntaxException, BundleException {
+ if (m_httpBundle == null) {
+ m_httpBundle = m_context.getServiceReference(HttpService.class.getName()).getBundle();
+ }
+ }
+
+ private void tearDown() {
+ try {
+ m_dependencyManager.remove(m_echoServletService);
+ m_dependencyManager.remove(m_mockHttpService);
+ }
+ catch (IllegalStateException ise) {
+ // It is possible that our services has been removed by the tests themselves; no problem here.
+ }
+ }
+
+ /**
+ * Start the http service and then register a servlet and see if it works
+ * After that, try to unregister
+ */
+ @Test(groups = { INTEGRATION })
+ public void testRegisterServlet() throws Exception {
+ setUp();
+
+ assert m_httpBundle != null : "We need a (real) http service !";
+
+ // use normal http service
+ m_httpBundle.start();
+ m_dependencyManager.add(m_echoServletService);
+ assert waitForEchoServlet(true) : "TestValue not echo'd back";
+
+ m_dependencyManager.remove(m_echoServletService);
+ assert !waitForEchoServlet(false) : "The servlet should not be available anymore";
+
+ tearDown();
+ }
+
+ /**
+ * Register a servlet and then start the http service and see if it works
+ * After that, try to unregister
+ */
+ @Test(groups = { INTEGRATION })
+ public void testStartHttpService() throws Exception {
+ setUp();
+
+ assert m_httpBundle != null : "We need a (real) http service !";
+
+ // use normal http service
+ m_dependencyManager.add(m_echoServletService);
+ m_httpBundle.start();
+ assert waitForEchoServlet(true) : "TestValue not echo'd back";
+
+ m_dependencyManager.remove(m_echoServletService);
+ assert !waitForEchoServlet(false) : "The servlet should not be available anymore";
+
+ tearDown();
+ }
+
+ /**
+ * Register a servlet with 2 http services, try to unregister and see if it is removed from both
+ */
+ @Test(groups = { INTEGRATION })
+ public void testServletOnTwoHttpServices() throws Exception {
+ setUp();
+
+ assert m_httpBundle != null : "We need a (real) http service !";
+
+ // use normal http service
+ m_dependencyManager.add(m_echoServletService);
+ // also use the mock version
+ m_dependencyManager.add(m_mockHttpService);
+ m_httpBundle.start();
+ assert waitForEchoServlet(true) : "TestValue not echo'd back";
+ assert m_mockHttp.isRegisterCalled() : "Servlet not registered with the mock service";
+
+
+ m_dependencyManager.remove(m_echoServletService);
+ assert !waitForEchoServlet(false) : "The servlet should not be available anymore";
+ assert m_mockHttp.isUnregisterCalled() : "Servlet not unregistered with the mock service";
+
+ tearDown();
+
+ }
+
+
+
+ /**
+ * now the server should be made available at
+ * http://localhost:8080/echoservlet
+ * if it is not available after 2000 ms, the test is failed anyway
+ *
+ * The expectSuccess parameter indicated if this method should expect a working echoservlet or a non-working one.
+ *
+ * This method returns whether the expect result was met. So if you expect it to work (and it does), true will be returned.
+ * If you expect it to NOT work (and it doesn't), false will be returned.
+ */
+ private boolean waitForEchoServlet(boolean expectedResult) {
+ BufferedReader bufReader = null;
+
+ long startTimeMillis = System.currentTimeMillis();
+ // make sure we iterate at least once
+ boolean success = !expectedResult;
+ try {
+ while ((expectedResult != success) && (System.currentTimeMillis() < startTimeMillis + 30000)) {
+ URL echoServletUrl = new URL("http://localhost:8080/echoServlet?test");
+ String echoString = null;
+ try {
+ bufReader = new BufferedReader(new InputStreamReader(echoServletUrl.openStream()));
+ echoString = bufReader.readLine();
+ } catch (IOException ioe) {
+ // let's wait and try again.
+ }
+ boolean resultFromServlet = (echoString != null) && echoString.equals("test");
+ if (resultFromServlet == expectedResult) {
+ success = expectedResult;
+ }
+ if ((expectedResult != success)) {
+ Thread.sleep(100);
+ }
+ }
+ }catch (MalformedURLException e) {
+ e.printStackTrace();
+ assert false : "No MalformedURLException expected";
+ }
+ catch (InterruptedException e) {
+ e.printStackTrace();
+ assert false : "No interruptedException expected";
+ } catch (Throwable t) {
+ t.printStackTrace();
+ } finally {
+ if (bufReader != null) {
+ try {
+ bufReader.close();
+ }
+ catch (Exception ex) {
+ // not much we can do
+ }
+ }
+ }
+ return success;
+ }
+
+
+
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/log/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/log/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/log/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/log/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,124 @@
+package net.luminis.liq.test.log;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import net.luminis.liq.discovery.property.constants.DiscoveryConstants;
+import net.luminis.liq.http.listener.constants.HttpConstants;
+import net.luminis.liq.identification.property.constants.IdentificationConstants;
+import net.luminis.liq.log.Log;
+import net.luminis.liq.server.log.store.LogStore;
+import net.luminis.test.osgi.dm.TestActivatorBase;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+
+public class Activator extends TestActivatorBase {
+ private static final String AUDITLOG = "/auditlog";
+ private static final String DEPLOYMENT = "/deployment";
+
+ @SuppressWarnings("unchecked")
+ private Class[] m_classes = new Class[] { LogIntegrationTest.class };
+ public static final String HOST = "localhost";
+ public static final int PORT = 8080;
+ public static final String GWID = "gw-id";
+ public static final String POLL_INTERVAL = "2";
+ private volatile ConfigurationAdmin m_config;
+ private volatile LogService m_log;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class[] getTestClasses() {
+ return m_classes;
+ }
+
+ @Override
+ protected void initServices(BundleContext context, DependencyManager manager) {
+ // helper service that configures the system
+ manager.add(createService()
+ .setImplementation(this)
+ .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false))
+ );
+ // service containing the actual integration test
+ manager.add(createService()
+ .setImplementation(LogIntegrationTest.class)
+ .add(createServiceDependency().setService(Log.class, "(&("+Constants.OBJECTCLASS+"="+Log.class.getName()+")(name=auditlog))").setRequired(true))
+ .add(createServiceDependency().setService(LogStore.class, "(&("+Constants.OBJECTCLASS+"="+LogStore.class.getName()+")(name=auditlog))").setRequired(true))
+ .add(createServiceDependency().setService(Runnable.class, "(&("+Constants.OBJECTCLASS+"="+Runnable.class.getName()+")(taskName=auditlog))").setRequired(true))
+ );
+ }
+
+ public void start() {
+ try {
+ configureServer();
+ configureGateway();
+ }
+ catch (Exception e) {
+ m_log.log(LogService.LOG_ERROR, "Exception while starting", e);
+ }
+ }
+
+ public void stop() {
+ try {
+ unconfigureGateway();
+ unconfigureServer();
+ }
+ catch (IOException e) {
+ m_log.log(LogService.LOG_ERROR, "IO exception while stopping", e);
+ }
+ }
+
+ private void configureGateway() throws IOException {
+ setProperty(DiscoveryConstants.DISCOVERY_PID, new Object[][] { { DiscoveryConstants.DISCOVERY_URL_KEY, "http://" + HOST + ":" + PORT } });
+ setProperty(IdentificationConstants.IDENTIFICATION_PID, new Object[][] { { IdentificationConstants.IDENTIFICATION_GATEWAYID_KEY, GWID } });
+ createFactoryInstance("net.luminis.liq.gateway.log.store.factory", new Object[][] { {"name", "auditlog"} });
+ createFactoryInstance("net.luminis.liq.gateway.log.factory", new Object[][] { {"name", "auditlog"} });
+ }
+
+ private void unconfigureGateway() throws IOException {
+ m_config.getConfiguration(DiscoveryConstants.DISCOVERY_PID, null).delete();
+ m_config.getConfiguration(IdentificationConstants.IDENTIFICATION_PID, null).delete();
+ }
+
+ private void unconfigureServer() throws IOException {
+ m_config.getConfiguration("net.luminis.liq.deployment.servlet", null).delete();
+ m_config.getConfiguration("net.luminis.liq.deployment.provider.filebased", null).delete();
+ }
+
+ private void configureServer() throws Exception {
+ setProperty("net.luminis.liq.deployment.servlet", new Object[][] { { HttpConstants.ENDPOINT, DEPLOYMENT } });
+ createFactoryInstance("net.luminis.liq.server.log.servlet.factory", new Object[][] { {"name", "auditlog"}, { HttpConstants.ENDPOINT, AUDITLOG } });
+ createFactoryInstance("net.luminis.liq.server.log.store.factory", new Object[][] { {"name", "auditlog"} });
+ }
+
+ @SuppressWarnings("unchecked")
+ private void setProperty(String pid, Object[][] props) throws IOException {
+ Configuration configuration = m_config.getConfiguration(pid, null);
+ Dictionary dictionary = configuration.getProperties();
+ if (dictionary == null) {
+ dictionary = new Hashtable();
+ }
+ for (Object[] pair : props) {
+ dictionary.put(pair[0], pair[1]);
+ }
+ configuration.update(dictionary);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void createFactoryInstance(String factoryPid, Object[][] props) throws IOException {
+ Dictionary dict = new Properties();
+ for (Object[] pair : props) {
+ dict.put(pair[0], pair[1]);
+ }
+ Configuration config = m_config.createFactoryConfiguration(factoryPid, null);
+ config.update(dict);
+ }
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/log/LogIntegrationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/log/LogIntegrationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/log/LogIntegrationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/log/LogIntegrationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,150 @@
+package net.luminis.liq.test.log;
+
+import static net.luminis.liq.test.utils.TestUtils.INTEGRATION;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+import net.luminis.liq.log.LogEvent;
+import net.luminis.liq.log.Log;
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.server.log.store.LogStore;
+
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+/**
+ * Integration tests for the audit log. Both a server and a gateway are setup
+ * on the same machine. The audit log is run and we check if it is indeed
+ * replicated to the server.
+ */
+public class LogIntegrationTest {
+ private volatile Log m_auditLog;
+ private volatile LogStore m_serverStore;
+ private volatile Runnable m_auditLogSyncTask;
+ private static Object instance;
+
+ public LogIntegrationTest() {
+ synchronized (LogIntegrationTest.class) {
+ if (instance == null) {
+ instance = this;
+ }
+ }
+ }
+
+ @Factory
+ public Object[] createInstance() {
+ synchronized (LogIntegrationTest.class) {
+ return new Object[] { instance };
+ }
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void runTests() throws Exception {
+ startupAndTestReplication();
+ testServlet();
+ }
+
+ public void startupAndTestReplication() throws Exception {
+ // now log another event
+ Properties props = new Properties();
+ props.put("one", "value1");
+ props.put("two", "value2");
+ m_auditLog.log(12345, props);
+
+ boolean found = false;
+ long startTime = System.currentTimeMillis();
+ while ((!found) && (System.currentTimeMillis() - startTime < 2000)) {
+ // synchronize again
+ m_auditLogSyncTask.run();
+
+ // get and evaluate results (note that there is some concurrency that might interfere with this test)
+ List<LogDescriptor> ranges2 = m_serverStore.getDescriptors();
+ assert ranges2.size() == 1 : "We should still have audit log events for one gateway on the server, but found " + ranges2.size();
+ LogDescriptor range = ranges2.get(0);
+ List<LogEvent> events = m_serverStore.get(range);
+ assert events.size() > 1 : "We should have a couple of events, at least more than the one we added ourselves.";
+ for (LogEvent event : events) {
+ if (event.getType() == 12345) {
+ assert event.getProperties().get("two").equals("value2") : "We could not retrieve a property of our audit log event.";
+ found = true;
+ break;
+ }
+ }
+
+ // wait if we have not found anything yet
+ if (!found) {
+ try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException ie) {}
+ }
+ }
+ assert found : "We could not retrieve our audit log event (after 2 seconds).";
+ }
+
+ public void testServlet() throws Exception {
+ // prepare the store
+ List<LogEvent> events = new ArrayList<LogEvent>();
+ events.add(new LogEvent("42", 1, 1, 1, 1, new Properties()));
+ events.add(new LogEvent("47", 1, 1, 1, 1, new Properties()));
+ events.add(new LogEvent("47", 2, 1, 1, 1, new Properties()));
+ events.add(new LogEvent("47", 2, 2, 1, 1, new Properties()));
+ m_serverStore.put(events);
+
+ List<String> result = getResponse("http://localhost:8080/auditlog/query");
+ assert result.size() > 1 : "We expect at least two logs on the server.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=42");
+ assert result.size() == 1 : "Gateway 42 has a single audit log event.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=47");
+ assert result.size() == 3 : "Gateway 47 has 3 audit log events.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=47&logid=1");
+ assert result.size() == 1 : "Gateway 47, logid 1 has 1 audit log event.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=47&logid=2");
+ assert result.size() == 2 : "Gateway 47, logid 2 has 2 audit log events.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=47&logid=2&range=1");
+ assert result.size() == 1 : "Gateway 47, logid 2, range 1 has 1 audit log event.";
+
+ result = getResponse("http://localhost:8080/auditlog/receive?gwid=47&logid=2&range=3,5");
+ assert result.size() == 0 : "Gateway 47, logid 2, range 3,5 has 0 audit log event.";
+ }
+
+ private List<String> getResponse(String request) throws IOException {
+ List<String> result = new ArrayList<String>();
+ InputStream in = null;
+ try {
+ in = new URL(request).openConnection().getInputStream();
+ byte[] response = new byte[in.available()];
+ in.read(response);
+
+ StringBuilder element = new StringBuilder();
+ for (byte b : response) {
+ switch(b) {
+ case '\n' :
+ result.add(element.toString());
+ element = new StringBuilder();
+ break;
+ default :
+ element.append(b);
+ }
+ }
+ }
+ finally {
+ try {
+ in.close();
+ }
+ catch (Exception e) {
+ // no problem.
+ }
+ }
+ return result;
+ }
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,29 @@
+package net.luminis.liq.test.mockautoconf;
+
+import java.util.Properties;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessor;
+
+public class Activator extends DependencyActivatorBase {
+
+ private static final String PID = "org.osgi.deployment.rp.autoconf";
+
+ @Override
+ public void init(BundleContext context, DependencyManager manager) throws Exception {
+ MockAutoConf impl = new MockAutoConf();
+ Properties props = new Properties();
+ props.put(Constants.SERVICE_PID, PID);
+
+ manager.add(createService().setInterface(ResourceProcessor.class.getName(), props)
+ .setImplementation(impl));
+ }
+
+ @Override
+ public void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // do nothing
+ }
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/MockAutoConf.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/MockAutoConf.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/MockAutoConf.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/mockautoconf/MockAutoConf.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,76 @@
+package net.luminis.liq.test.mockautoconf;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.osgi.service.deploymentadmin.spi.DeploymentSession;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessor;
+import org.osgi.service.deploymentadmin.spi.ResourceProcessorException;
+
+public class MockAutoConf implements ResourceProcessor{
+
+ public void start() {
+ System.err.println("MockAutoConf started.");
+ }
+
+ public void stop() {
+ System.err.println("MockAutoConf stopped.");
+ }
+
+ public void begin(DeploymentSession session) {
+ System.err.println("Called begin(...)");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void cancel() {
+ System.err.println("Called cancel(...)");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void commit() {
+ System.err.println("Called commit()");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void dropAllResources() throws ResourceProcessorException {
+ System.err.println("Called dropAllResources()");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void dropped(String resource) throws ResourceProcessorException {
+ System.err.println("Called dropped(" + resource + ")");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void prepare() throws ResourceProcessorException {
+ System.err.println("Called prepare()");
+ // TODO Auto-generated method stub
+
+ }
+
+ public void process(String name, InputStream stream)
+ throws ResourceProcessorException {
+ System.err.println("Called process(...).\nAnd here's the resource, named '" + name + "':");
+ byte[] buf = new byte[1024];
+ try {
+ while (stream.read(buf) > 0) {
+ System.err.write(buf);
+ }
+ }
+ catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ System.err.println("That's it!");
+ }
+
+ public void rollback() {
+ System.err.println("Called rollback()");
+ }
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/repository/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/repository/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/repository/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/repository/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,32 @@
+package net.luminis.liq.test.repository;
+
+import net.luminis.test.osgi.dm.TestActivatorBase;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.PreferencesService;
+
+/**
+ * Activator for the integration test.
+ */
+public class Activator extends TestActivatorBase {
+
+ @Override
+ protected void initServices(BundleContext context, DependencyManager manager) {
+ manager.add(createService()
+ .setImplementation(RepositoryTest.class)
+ .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(PreferencesService.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false)));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class[] getTestClasses() {
+ return new Class[] { RepositoryTest.class };
+ }
+
+}
+
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/repository/RepositoryTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/repository/RepositoryTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/repository/RepositoryTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/repository/RepositoryTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,345 @@
+package net.luminis.liq.test.repository;
+
+import static net.luminis.liq.test.utils.TestUtils.INTEGRATION;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import net.luminis.liq.http.listener.constants.HttpConstants;
+import net.luminis.liq.repository.Repository;
+import net.luminis.liq.repository.impl.constants.RepositoryConstants;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+public class RepositoryTest {
+
+ private static Object m_instance;
+
+ private static final int COPY_BUFFER_SIZE = 4096;
+ private static final String MIME_APPLICATION_OCTET_STREAM = "application/octet-stream";
+ private static final String HOST = "http://localhost:8080";
+
+ private volatile ConfigurationAdmin m_configAdmin; // Injected by dependency manager
+ private volatile BundleContext m_context; // Injected by dependency manager
+
+ public RepositoryTest() {
+ synchronized (RepositoryTest.class) {
+ if (m_instance == null) {
+ m_instance = this;
+ }
+ }
+ }
+
+ @Factory
+ public Object[] createInstances() {
+ synchronized (RepositoryTest.class) {
+ return new Object[] { m_instance };
+ }
+ }
+
+ protected void start() throws IOException {
+ // configure the (replication)repository servlets
+ setProperty("net.luminis.liq.repository.servlet.RepositoryReplicationServlet", new Object[][] { { HttpConstants.ENDPOINT, "/replication" } });
+ setProperty("net.luminis.liq.repository.servlet.RepositoryServlet", new Object[][] { { HttpConstants.ENDPOINT, "/repository" } });
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception {
+ // remove all repositories, in case a test case does not reach it's cleanup section due to an exception
+ removeAllRepositories();
+ }
+
+ private void addRepository(String instanceName, String customer, String name, boolean isMaster) throws IOException, InterruptedException, InvalidSyntaxException {
+ addRepository(instanceName, customer, name, null, isMaster);
+ }
+
+ /* Configure a new repository instance */
+ private void addRepository(String instanceName, String customer, String name, String initial, boolean isMaster) throws IOException, InterruptedException, InvalidSyntaxException {
+ // Publish configuration for a repository instance
+ Properties props = new Properties();
+ props.put(RepositoryConstants.REPOSITORY_CUSTOMER, customer);
+ props.put(RepositoryConstants.REPOSITORY_NAME, name);
+ props.put(RepositoryConstants.REPOSITORY_MASTER, String.valueOf(isMaster));
+ if (initial != null) {
+ props.put(RepositoryConstants.REPOSITORY_INITIAL_CONTENT, initial);
+ }
+ props.put("factory.instance.pid", instanceName);
+ Configuration config = m_configAdmin.createFactoryConfiguration("net.luminis.liq.server.repository.factory", null);
+
+ ServiceTracker tracker = new ServiceTracker(m_context, m_context.createFilter("(factory.instance.pid=" + instanceName + ")"), null);
+ tracker.open();
+
+ config.update(props);
+
+ if (tracker.waitForService(1000) == null) {
+ throw new IOException("Did not get notified about new repository becoming available in time.");
+ }
+ tracker.close();
+ }
+
+ private void removeAllRepositories() throws IOException, InvalidSyntaxException, InterruptedException {
+ final Configuration[] configs = m_configAdmin.listConfigurations("(factory.instance.pid=*)");
+ if ((configs != null) && (configs.length > 0)) {
+ final Semaphore sem = new Semaphore(0);
+
+ ServiceTracker tracker = new ServiceTracker(m_context, m_context.createFilter("(" + Constants.OBJECTCLASS + "=" + Repository.class.getName() + ")"), null) {
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ super.removedService(reference, service);
+ // config.length times two because the service tracker also sees added events for each instance
+ if (size() == 0) {
+ sem.release();
+ }
+ }
+ };
+ tracker.open();
+
+ for (int i = 0; i < configs.length; i++) {
+ configs[i].delete();
+ }
+
+ if (!sem.tryAcquire(1, TimeUnit.SECONDS)) {
+ throw new IOException("Not all instances were removed in time.");
+ }
+ tracker.close();
+ }
+ }
+
+ private void removeRepository(String instanceName) throws IOException, InterruptedException, InvalidSyntaxException {
+ Configuration[] configs = null;
+ try {
+ configs = m_configAdmin.listConfigurations("(factory.instance.pid=" + instanceName + ")");
+ }
+ catch (InvalidSyntaxException e) {
+ // should not happen
+ }
+ if ((configs != null) && (configs.length > 0)) {
+ final Semaphore sem = new Semaphore(0);
+ ServiceTracker tracker = new ServiceTracker(m_context, m_context.createFilter("(factory.instance.pid=" + instanceName + ")"), null) {
+ @Override
+ public void removedService(ServiceReference reference, Object service) {
+ super.removedService(reference, service);
+ sem.release();
+ }
+ };
+ tracker.open();
+
+ configs[0].delete();
+
+ if (!sem.tryAcquire(1, TimeUnit.SECONDS)) {
+ throw new IOException("Instance did not get removed in time.");
+ }
+ }
+ }
+
+ /* Configure properties for the specified service PID */
+ @SuppressWarnings("unchecked")
+ private void setProperty(String pid, Object[][] props) throws IOException {
+ Configuration configuration = m_configAdmin.getConfiguration(pid, null);
+ Dictionary dictionary = configuration.getProperties();
+ if (dictionary == null) {
+ dictionary = new Hashtable();
+ }
+ for (Object[] pair : props) {
+ dictionary.put(pair[0], pair[1]);
+ }
+ configuration.update(dictionary);
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testCreation() throws Exception {
+ addRepository("testInstance", "luminis", "test", true);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int responseCode = query(HOST, "replication/query", null, null, out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+ assert "luminis,test,\n".equals(out.toString()) : "Expected one repository without any versions as query result instead of : " + out.toString();
+
+ addRepository("testInstance2", "luminis", "test2", true);
+
+ out.reset();
+ responseCode = query(HOST, "replication/query", null, null, out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+ assert "luminis,test,\nluminis,test2,\n".equals(out.toString()) ||
+ "luminis,test2,\nluminis,test,\n".equals(out.toString()) : "Expected two repositories without any versions as query result instead of : " + out.toString();
+
+ removeRepository("testInstance2");
+
+ out.reset();
+ responseCode = query(HOST, "replication/query", null, null, out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+ assert "luminis,test,\n".equals(out.toString()) : "Expected one repository without any versions as query result instead of : " + out.toString();
+
+ removeRepository("testInstance");
+
+ out.reset();
+ responseCode = query(HOST, "replication/query", null, null, out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+ assert "".equals(out.toString()) : "Expected one repository without any versions as query result instead of : " + out.toString();
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testGetAndPut() throws Exception {
+ addRepository("testInstance", "luminis", "test", true);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int responseCode = get(HOST, "replication/get", "luminis", "test", "1", out);
+ assert responseCode == HttpURLConnection.HTTP_NOT_FOUND : "Expected responsecode " + HttpURLConnection.HTTP_NOT_FOUND + " instead of " + responseCode;
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("test".getBytes());
+ responseCode = put("replication/put", HOST, "luminis", "test", "1", byteArrayInputStream);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+
+ out.reset();
+ responseCode = get(HOST, "replication/get", "luminis", "test", "1", out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+ assert "test".equals(out.toString()) : "Expected 'test' as a result of the get operation, not: " + out.toString();
+
+ removeRepository("testInstance");
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testCheckoutAndCommit() throws Exception {
+ addRepository("testInstance", "luminis", "test", true);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int responseCode = get(HOST, "repository/checkout", "luminis", "test", "1", out);
+ assert responseCode == HttpURLConnection.HTTP_NOT_FOUND : "Expected responsecode " + HttpURLConnection.HTTP_NOT_FOUND + " instead of " + responseCode;
+
+ ByteArrayInputStream input = new ByteArrayInputStream("test".getBytes());
+ responseCode = put("repository/commit", HOST, "luminis", "test", "1", input);
+ assert responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR : "Expected responsecode " + HttpURLConnection.HTTP_INTERNAL_ERROR + " instead of " + responseCode;
+
+ input.reset();
+ responseCode = put("repository/commit", HOST, "luminis", "test", "0", input);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+
+ out.reset();
+ responseCode = get(HOST, "repository/checkout", "luminis", "test", "1", out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+
+ removeRepository("testInstance");
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testMaster() throws Exception {
+ addRepository("testInstance", "luminis", "test", false);
+
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("test".getBytes());
+ int responseCode = put("replication/put", HOST, "luminis", "test", "1", byteArrayInputStream);
+ assert responseCode == HttpURLConnection.HTTP_OK;
+
+ byteArrayInputStream.reset();
+ responseCode = put("repository/commit", HOST, "luminis", "test", "0", byteArrayInputStream);
+ assert responseCode == HttpURLConnection.HTTP_INTERNAL_ERROR : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+
+ removeRepository("testInstance");
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testBadRequests() throws Exception {
+ addRepository("testInstance", "luminis", "test", false);
+
+ URL url = new URL(new URL(HOST), "replication/query?customer=luminis&name=test&filter=test");
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ int responseCode = connection.getResponseCode();
+ assert responseCode == HttpURLConnection.HTTP_BAD_REQUEST : "Expected responsecode " + HttpURLConnection.HTTP_BAD_REQUEST + " instead of " + responseCode;
+
+ url = new URL(new URL(HOST), "repository/query?customer=luminis&name=test&filter=test");
+ connection = (HttpURLConnection) url.openConnection();
+ responseCode = connection.getResponseCode();
+ assert responseCode == HttpURLConnection.HTTP_BAD_REQUEST : "Expected responsecode " + HttpURLConnection.HTTP_BAD_REQUEST + " instead of " + responseCode;
+
+ removeRepository("testInstance");
+ }
+
+ @Test(groups = { INTEGRATION })
+ public void testInitialContent() throws Exception {
+ addRepository("testInstance", "luminis", "test", "somecontent", true);
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int responseCode = get(HOST, "repository/checkout", "luminis", "test", "1", out);
+ assert responseCode == HttpURLConnection.HTTP_OK : "Expected responsecode " + HttpURLConnection.HTTP_OK + " instead of " + responseCode;
+
+ assert Arrays.equals(out.toByteArray(), "somecontent".getBytes());
+
+ removeRepository("testInstance");
+ }
+
+ private static int query(String host, String endpoint, String customer, String name, OutputStream out) throws MalformedURLException, IOException {
+ String f1 = (customer == null) ? null : "customer=" + customer;
+ String f2 = (name == null) ? null : "name=" + name;
+ String filter = ((f1 == null) ? "?" : "?" + f1 + "&") + ((f2 == null) ? "" : f2);
+ URL url = new URL(new URL(host), endpoint + filter);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ InputStream input = connection.getInputStream();
+ copy(input, out);
+ out.flush();
+ }
+ return responseCode;
+ }
+
+ private static int get(String host, String endpoint, String customer, String name, String version, OutputStream out) throws MalformedURLException, IOException, FileNotFoundException {
+ URL url = new URL(new URL(host), endpoint + "?customer=" + customer + "&name=" + name + "&version=" + version);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ InputStream input = connection.getInputStream();
+ copy(input, out);
+ out.flush();
+ }
+ return responseCode;
+ }
+
+ private static int put(String endpoint, String host, String customer, String name, String version, InputStream in) throws MalformedURLException, IOException, FileNotFoundException {
+ URL url = new URL(new URL(host), endpoint + "?customer=" + customer + "&name=" + name + "&version=" + version);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setDoOutput(true);
+ connection.setRequestProperty("Content-Type", MIME_APPLICATION_OCTET_STREAM);
+ OutputStream out = connection.getOutputStream();
+ copy(in, out);
+ out.flush();
+ int responseCode = connection.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ InputStream is = (InputStream) connection.getContent();
+ is.close();
+ }
+ return responseCode;
+ }
+
+ /* copy in to out */
+ private static void copy(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[COPY_BUFFER_SIZE];
+ int bytes = in.read(buffer);
+ while (bytes != -1) {
+ out.write(buffer, 0, bytes);
+ bytes = in.read(buffer);
+ }
+ }
+
+
+}
Added: incubator/ace/trunk/test/src/net/luminis/liq/test/repositoryadmin/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/test/repositoryadmin/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/test/repositoryadmin/Activator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/test/repositoryadmin/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,85 @@
+package net.luminis.liq.test.repositoryadmin;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import net.luminis.liq.client.repository.RepositoryAdmin;
+import net.luminis.liq.client.repository.RepositoryObject;
+import net.luminis.liq.client.repository.repository.Artifact2GroupAssociationRepository;
+import net.luminis.liq.client.repository.repository.ArtifactRepository;
+import net.luminis.liq.client.repository.repository.DeploymentVersionRepository;
+import net.luminis.liq.client.repository.repository.GatewayRepository;
+import net.luminis.liq.client.repository.repository.Group2LicenseAssociationRepository;
+import net.luminis.liq.client.repository.repository.GroupRepository;
+import net.luminis.liq.client.repository.repository.License2GatewayAssociationRepository;
+import net.luminis.liq.client.repository.repository.LicenseRepository;
+import net.luminis.liq.client.repository.stateful.StatefulGatewayObject;
+import net.luminis.liq.client.repository.stateful.StatefulGatewayRepository;
+import net.luminis.liq.server.log.store.LogStore;
+import net.luminis.liq.test.utils.TestUtils;
+import net.luminis.test.osgi.dm.TestActivatorBase;
+
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+
+/**
+ * Activator for the integration test.
+ */
+public class Activator extends TestActivatorBase {
+
+ private ConfigurationAdmin m_configAdmin;
+
+ @Override
+ protected void initServices(BundleContext context, DependencyManager manager) {
+ manager.add(createService()
+ .setImplementation(this)
+ .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true)));
+ RepositoryAdminTest test = new RepositoryAdminTest();
+ manager.add(createService()
+ .setImplementation(test)
+ .add(createServiceDependency().setService(RepositoryAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(ArtifactRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(Artifact2GroupAssociationRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(GroupRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(Group2LicenseAssociationRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(LicenseRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(License2GatewayAssociationRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(GatewayRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(DeploymentVersionRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(StatefulGatewayRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(LogStore.class, "(&("+Constants.OBJECTCLASS+"="+LogStore.class.getName()+")(name=auditlog))").setRequired(true))
+ .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true)));
+ Dictionary<String, Object> topics = new Hashtable<String, Object>();
+ topics.put(EventConstants.EVENT_TOPIC, new String[] {RepositoryObject.PUBLIC_TOPIC_ROOT + "*",
+ RepositoryObject.PRIVATE_TOPIC_ROOT + "*",
+ RepositoryAdmin.PUBLIC_TOPIC_ROOT + "*",
+ RepositoryAdmin.PRIVATE_TOPIC_ROOT + "*",
+ StatefulGatewayObject.TOPIC_ALL});
+ manager.add(createService()
+ .setImplementation(test)
+ .setInterface(EventHandler.class.getName(), topics));
+ TestUtils.configureObject(test, DependencyManager.class, manager);
+ }
+
+ public void start() throws IOException {
+ Properties props = new Properties();
+ props.put("name", "auditlog");
+ Configuration config = m_configAdmin.createFactoryConfiguration("net.luminis.liq.server.log.store.factory", null);
+ config.update(props);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class[] getTestClasses() {
+ return new Class[] { RepositoryAdminTest.class };
+ }
+
+}
+