/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.ace.test.repositoryadmin;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
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.Callable;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import org.apache.ace.client.repository.ObjectRepository;
import org.apache.ace.client.repository.RepositoryAdmin;
import org.apache.ace.client.repository.RepositoryAdminLoginContext;
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.RepositoryObject.WorkingState;
import org.apache.ace.client.repository.helper.ArtifactHelper;
import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
import org.apache.ace.client.repository.helper.PropertyResolver;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
import org.apache.ace.client.repository.object.Artifact2GroupAssociation;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.DeploymentArtifact;
import org.apache.ace.client.repository.object.DeploymentVersionObject;
import org.apache.ace.client.repository.object.GatewayObject;
import org.apache.ace.client.repository.object.Group2LicenseAssociation;
import org.apache.ace.client.repository.object.GroupObject;
import org.apache.ace.client.repository.object.License2GatewayAssociation;
import org.apache.ace.client.repository.object.LicenseObject;
import org.apache.ace.client.repository.repository.Artifact2GroupAssociationRepository;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
import org.apache.ace.client.repository.repository.GatewayRepository;
import org.apache.ace.client.repository.repository.Group2LicenseAssociationRepository;
import org.apache.ace.client.repository.repository.GroupRepository;
import org.apache.ace.client.repository.repository.License2GatewayAssociationRepository;
import org.apache.ace.client.repository.repository.LicenseRepository;
import org.apache.ace.client.repository.stateful.StatefulGatewayObject;
import org.apache.ace.client.repository.stateful.StatefulGatewayRepository;
import org.apache.ace.client.repository.stateful.StatefulGatewayObject.ProvisioningState;
import org.apache.ace.client.repository.stateful.StatefulGatewayObject.RegistrationState;
import org.apache.ace.client.repository.stateful.StatefulGatewayObject.StoreState;
import org.apache.ace.http.listener.constants.HttpConstants;
import org.apache.ace.log.AuditEvent;
import org.apache.ace.log.LogEvent;
import org.apache.ace.obr.storage.file.constants.OBRFileStoreConstants;
import org.apache.ace.repository.Repository;
import org.apache.ace.repository.impl.constants.RepositoryConstants;
import org.apache.ace.scheduler.constants.SchedulerConstants;
import org.apache.ace.server.log.store.LogStore;
import org.apache.ace.test.constants.TestConstants;
import org.apache.ace.test.utils.TestUtils;
import org.apache.felix.dm.DependencyManager;
import org.apache.felix.dm.service.Service;
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.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.useradmin.User;
import org.osgi.util.tracker.ServiceTracker;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.Factory;
import org.testng.annotations.Test;

public class RepositoryAdminTest implements EventHandler {
    private volatile BundleContext m_context; /* Injected by dependency manager */
    private volatile ConfigurationAdmin m_configAdmin; /* Injected by dependency manager */
    private volatile DependencyManager m_depManager; /* injected by dependency manager */
    private volatile RepositoryAdmin m_repositoryAdmin; /* Injected by dependency manager */
    private volatile ArtifactRepository m_artifactRepository; /* Injected by dependency manager */
    private volatile Artifact2GroupAssociationRepository m_artifact2groupRepository; /* Injected by dependency manager */
    private volatile GroupRepository m_groupRepository; /* Injected by dependency manager */
    private volatile Group2LicenseAssociationRepository m_group2licenseRepository; /* Injected by dependency manager */
    private volatile LicenseRepository m_licenseRepository; /* Injected by dependency manager */
    private volatile License2GatewayAssociationRepository m_license2gatewayRepository; /* Injected by dependency manager */
    private volatile GatewayRepository m_gatewayRepository; /* Injected by dependency manager */
    private volatile DeploymentVersionRepository m_deploymentVersionRepository; /* Injected by dependency manager */
    private volatile StatefulGatewayRepository m_statefulGatewayRepository; /* Injected by dependency manager */
    private volatile LogStore m_auditLogStore; /* Injected by dependency manager */

    /*
     * TestNG magic
     */
    private static Object instance;
    public RepositoryAdminTest() {
        if (instance == null) {
            instance = this;
        }
    }

    @Factory
    public Object[] createInstances() {
        return new Object[] { instance };
    }

    @AfterMethod( alwaysRun = true )
    public void cleanUp() throws IOException, InvalidSyntaxException, InterruptedException {
        // Simply remove all objects in the repository.
        clearRepository(m_artifactRepository);
        clearRepository(m_artifact2groupRepository);
        clearRepository(m_group2licenseRepository);
        clearRepository(m_license2gatewayRepository);
        clearRepository(m_artifactRepository);
        clearRepository(m_groupRepository);
        clearRepository(m_licenseRepository);
        clearRepository(m_gatewayRepository);
        clearRepository(m_deploymentVersionRepository);
        m_statefulGatewayRepository.refresh();
        try {
            m_repositoryAdmin.logout(true);
        }
        catch (Exception ioe) {
            //ioe.printStackTrace(System.out);
        }
    }

    public <T extends RepositoryObject> void clearRepository (ObjectRepository<T> rep) {
        for (T entity : rep.get()) {
            rep.remove(entity);
        }
        assert rep.get().size() == 0 : "Something went wrong clearing the repository.";
    }

    /**
     * Add a bundle, group and license, associate all, remove the group, No associations should be left.
     * @throws Exception
     */
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testRemoveBundleGroup() throws Exception {
        final ArtifactObject b1 = createBasicBundleObject("thebundle","1", null);
        final GroupObject g1 = createBasicGroupObject("thegroup");

        final Artifact2GroupAssociation bg = runAndWaitForEvent(new Callable<Artifact2GroupAssociation>() {
            public Artifact2GroupAssociation call() throws Exception {
                return m_artifact2groupRepository.create("(&(" + BundleHelper.KEY_SYMBOLICNAME + "=thebundle)(|("+BundleHelper.KEY_VERSION+">=1)("+BundleHelper.KEY_VERSION+"=<3))(!("+BundleHelper.KEY_VERSION+"=3)))", "(name=thegroup)");
            }
        }, false, Artifact2GroupAssociation.TOPIC_ADDED);

        final LicenseObject l1 = createBasicLicenseObject("thelicense");

        final Group2LicenseAssociation gtl = runAndWaitForEvent(new Callable<Group2LicenseAssociation>() {
            public Group2LicenseAssociation call() throws Exception {
                return m_group2licenseRepository.create("(name=thegroup)","(name=thelicense)");
            }
        }, false, Group2LicenseAssociation.TOPIC_ADDED);

        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b1) : "The left side of the BG-association should be b1.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the BG-association should be g1.";
        assert (gtl.getLeft().size() == 1) && gtl.getLeft().contains(g1) : "The left side of the GtL-association should be g1.";
        assert (gtl.getRight().size() == 1) && gtl.getRight().contains(l1) : "The right side of the GtL-association should be l1.";
        assert bg.isSatisfied() : "The bundlegroup association should be satisfied.";
        assert gtl.isSatisfied() : "The group2license association should be satisfied.";
        assert b1.getGroups().size() == 1 : "Bundle b1 should be associated to one group.";
        assert l1.getGroups().size() == 1 : "License l1 should be associated to one group.";

        //remove the group
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_groupRepository.remove(g1);
                return null;
            }
        }, false,Artifact2GroupAssociation.TOPIC_CHANGED, Group2LicenseAssociation.TOPIC_CHANGED);

        assert !gtl.isSatisfied() : "The bundlegroup association shouldn not be satisfied.";
        assert !bg.isSatisfied() : "The group2license assocation should not be satisfied.";

        assert b1.getGroups().size() == 0 : "Bundle b1 shouldn't be associated to any group, but is associated to " + b1.getGroups();
        assert l1.getGroups().size() == 0 : "License l1 shouldn't be associated to any group.";

        cleanUp();
    }


    @Test( groups = { TestUtils.INTEGRATION } )
    public void testAssociationsWithMovingEndpoints () throws Exception {
        final ArtifactObject b1 = createBasicBundleObject("thebundle", "1", null);
        final GroupObject g1 = createBasicGroupObject("thegroup");
        final Artifact2GroupAssociation bg = runAndWaitForEvent(new Callable<Artifact2GroupAssociation>() {
            public Artifact2GroupAssociation call() throws Exception {
                Map<String, String> properties = new HashMap<String, String>();
                properties.put(BundleHelper.KEY_ASSOCIATION_VERSIONSTATEMENT, "[1,3)");
                return m_artifact2groupRepository.create(b1, properties, g1, null);
            }
        }, false, Artifact2GroupAssociation.TOPIC_ADDED);

        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b1) : "The left side of the association should now be b1; we find " + bg.getLeft().size() + " bundles on the left side of the association.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the association should now be g1.";
        assert b1.getGroups().get(0) == g1 : "b1 should be assocated with g1";
        assert g1.getArtifacts().get(0) == b1 : "g1 should be assocated with b1";

        final ArtifactObject b2 = runAndWaitForEvent(new Callable<ArtifactObject>() {
            public ArtifactObject call() throws Exception {
                return createBasicBundleObject("thebundle", "2", null);
            }
        }, false, Artifact2GroupAssociation.TOPIC_CHANGED);

        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b1) : "The left side of the association should no longer be b1; we find " + bg.getLeft().size() + " bundles.";
        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b2) : "The left side of the association should now be b2.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the association should now be g1.";
        assert b1.getGroups().size() == 0 : "b1 should not be associated with any group.";
        assert b2.getGroups().get(0) == g1 : "b2 should now be assocation with g1";
        assert g1.getArtifacts().get(0) == b2 : "g1 should be assocation with b2";
        assert g1.getArtifacts().size() == 1 : "g1 should be associated with one bundle";

        ArtifactObject b3 = createBasicBundleObject("thebundle", "3", null);

        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b1) : "The left side of the association should no longer be b1.";
        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b2) : "The left side of the association should now be b2.";
        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b3) : "The left side of the association should not be b3.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the association should now be g1.";
        assert b1.getGroups().size() == 0 : "b1 should not be associated with any group.";
        assert b2.getGroups().get(0) == g1 : "b2 should now be assocation with g1";
        assert b3.getGroups().size() == 0 : "b3 should not be associated with any group.";
        assert g1.getArtifacts().get(0) == b2 : "g1 should be assocation with b2";
        assert g1.getArtifacts().size() == 1 : "g1 should be associated with one bundle";

        ArtifactObject b15 = createBasicBundleObject("thebundle", "1.5", null);

        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b1) : "The left side of the association should no longer be b1.";
        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b15) : "The left side of the association should not be b15.";
        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b2) : "The left side of the association should now be b2.";
        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b3) : "The left side of the association should not be b3.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the association should now be g1.";
        assert b1.getGroups().size() == 0 : "b1 should not be associated with any group.";
        assert b15.getGroups().size() == 0 : "b15 should not be associated with any group.";
        assert b2.getGroups().get(0) == g1 : "b2 should now be assocation with g1";
        assert b3.getGroups().size() == 0 : "b3 should not be associated with any group.";
        assert g1.getArtifacts().get(0) == b2 : "g1 should be assocation with b2";
        assert g1.getArtifacts().size() == 1 : "g1 should be associated with one bundle";

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_artifactRepository.remove(b2);
                return null;
            }
        }, false, Artifact2GroupAssociation.TOPIC_CHANGED);

        //note that we cannot test anything for b2: this has been removed, and now has no
        //defined state.
        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b1) : "The left side of the association should no longer be b1.";
        assert (bg.getLeft().size() == 1) && bg.getLeft().contains(b15) : "The left side of the association should now be b15.";
        assert (bg.getLeft().size() == 1) && !bg.getLeft().contains(b3) : "The left side of the association should not be b3.";
        assert (bg.getRight().size() == 1) && bg.getRight().contains(g1) : "The right side of the association should now be g1.";
        assert b1.getGroups().size() == 0 : "b1 should not be associated with any group.";
        assert b15.getGroups().get(0) == g1 : "b15 should now be assocation with g1";
        assert b3.getGroups().size() == 0 : "b3 should not be associated with any group.";
        assert g1.getArtifacts().get(0) == b15 : "g1 should be assocation with b15";
        assert g1.getArtifacts().size() == 1 : "g1 should be associated with one bundle";

        cleanUp();
    }

    private static final String ENDPOINT = "/AdminRepTest";
    private static final String HOST = "http://localhost:" + TestConstants.PORT;

    /**
     * Tests the behavior with logging in and out (with multiple users), and communication
     * with the server.
     * @throws Exception
     */
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testRepositoryAdmin() throws Exception {
        final User user1 = new MockUser("user1");
        final User user2 = new MockUser("user2");

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);

        try {
            m_repositoryAdmin.checkout();
            assert false : "Without being logged in, it should not be possible to do checkout.";
        }
        catch (IllegalStateException ise) {
            //expected
        }

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext1.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", true);
        m_repositoryAdmin.login(loginContext1);

        assert !m_repositoryAdmin.isCurrent() : "When first logging in without checking out, the repository cannot be current.";
        assert !m_repositoryAdmin.isModified() : "Immediately after login, the repository not is modified.";

        try {
            m_repositoryAdmin.commit();
            assert false : "We should not be able to commit before we check something out.";
        }
        catch (IllegalStateException e) {
            // expected
        }

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.checkout();
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_REFRESH);

        assert m_repositoryAdmin.isCurrent() : "After initial checkout, the repository is current.";
        assert !m_repositoryAdmin.isModified() : "Immediately after login, the repository cannot be modified.";

        ArtifactObject b1 = runAndWaitForEvent(new Callable<ArtifactObject>() {
            public ArtifactObject call() throws Exception {
                return createBasicBundleObject("bundle1");
            }
        }, false, ArtifactObject.TOPIC_ADDED, RepositoryAdmin.TOPIC_STATUSCHANGED);

        assert m_repositoryAdmin.isCurrent() : "After initial checkout, the repository is current.";
        assert m_repositoryAdmin.isModified() : "We have added a bundle, so the repository is modified.";
        assert m_artifactRepository.get().size() == 1;
        assert m_repositoryAdmin.getWorkingState(b1).equals(WorkingState.New) : "We expect the working state of our bundle to be New, but it is " + m_repositoryAdmin.getWorkingState(b1);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New) == 1 : "We expect one bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed) == 0 : "We expect 0 bundle object in working state Changed, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Unchanged) == 0 : "We expect 0 bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.logout(false);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGOUT);

        cleanUp();

        assert m_artifactRepository.get().size() == 0;

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.login(loginContext1);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGIN);

        assert m_repositoryAdmin.isCurrent() : "There has not been another commit in between, so we are still current.";
        assert m_repositoryAdmin.isModified() : "We have made changes since the last commit, so the repository must be modified.";
        assert m_artifactRepository.get().size() == 1;
        assert m_repositoryAdmin.getWorkingState(b1).equals(WorkingState.New) : "We expect the working state of our bundle to be New, but it is " + m_repositoryAdmin.getWorkingState(b1);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New) == 1 : "We expect one bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed) == 0 : "We expect 0 bundle object in working state Changed, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Unchanged) == 0 : "We expect 0 bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);

        m_repositoryAdmin.commit();

        assert m_repositoryAdmin.isCurrent() : "After a commit, the repository must be current.";
        assert !m_repositoryAdmin.isModified() : "After a commit, the repository cannot be modified.";

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.logout(false);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGOUT);

        cleanUp();

        final RepositoryAdminLoginContext loginContext2 = m_repositoryAdmin.createLoginContext(user2);
        loginContext2.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext2.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", true);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.login(loginContext2);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGIN);

        assert m_artifactRepository.get().size() == 0;

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.checkout();
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_REFRESH);

        assert m_artifactRepository.get().size() == 1 : "We expect to find 1 bundle after checkout, but we find " + m_artifactRepository.get().size();
        assert m_repositoryAdmin.isCurrent() : "After a checkout, without changing anything, the repository must be current.";
        assert !m_repositoryAdmin.isModified() : "After a checkout, without changing anything, the repository cannot be modified.";

        ArtifactObject b2 = runAndWaitForEvent(new Callable<ArtifactObject>() {
            public ArtifactObject call() throws Exception {
                return createBasicBundleObject("bundle2");
            }
        }, false, ArtifactObject.TOPIC_ADDED, RepositoryAdmin.TOPIC_STATUSCHANGED);

        assert m_artifactRepository.get().size() == 2;
        assert m_repositoryAdmin.isCurrent() : "After changing something in memory without flushing it, the repository still is current.";
        assert m_repositoryAdmin.isModified() : "We have added something, so the repository is modified.";
        assert m_repositoryAdmin.getWorkingState(b1).equals(WorkingState.Unchanged) : "We expect the working state of our bundle1 to be Unchanged, but it is " + m_repositoryAdmin.getWorkingState(b1);
        assert m_repositoryAdmin.getWorkingState(b2).equals(WorkingState.New) : "We expect the working state of our bundle2 to be New, but it is " + m_repositoryAdmin.getWorkingState(b1);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New) == 1 : "We expect one bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed) == 0 : "We expect 0 bundle object in working state Changed, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);
        assert m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Unchanged) == 1 : "We expect 1 bundle object in working state New, but we find "+ m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.logout(false);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGOUT);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.login(loginContext1);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGIN);

        assert m_artifactRepository.get().size() == 1 : "We expect 1 item in the bundle repository, in stead of " + m_artifactRepository.get().size();

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.logout(false);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGOUT);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.login(loginContext2);
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGIN);

        assert m_artifactRepository.get().size() == 2 : "We expect 2 items in the bundle repository, in stead of " + m_artifactRepository.get().size();

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_repositoryAdmin.revert();
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_REFRESH, RepositoryAdmin.TOPIC_STATUSCHANGED);

        assert m_artifactRepository.get().size() == 1 : "We expect 1 item in the bundle repository, in stead of " + m_artifactRepository.get().size();

        try {
            removeAllRepositories();
        }
        catch (Exception e) {
            // Not much we can do...
            e.printStackTrace(System.err);
        }

        cleanUp();
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testAutoApprove() throws Exception {
        User user = new MockUser("user");

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);
        addRepository("deploymentInstance", "apache", "deployment", true);

        RepositoryAdminLoginContext loginContext = m_repositoryAdmin.createLoginContext(user);
        loginContext.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", true);
        loginContext.addDeploymentRepository(new URL(HOST + ENDPOINT), "apache", "deployment", true);
        m_repositoryAdmin.login(loginContext);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                createBasicGatewayObject("testAutoApproveGateway");
                return null;
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_ADDED);

        final StatefulGatewayObject sgo = m_statefulGatewayRepository.get(m_context.createFilter("(" + GatewayObject.KEY_ID + "=" + "testAutoApproveGateway)")).get(0);

        // Set up some deployment information for the gateway.
        final GroupObject g = runAndWaitForEvent(new Callable<GroupObject>() {
            public GroupObject call() throws Exception {
                ArtifactObject b = createBasicBundleObject("myBundle", "1.0", null);
                GroupObject g = createBasicGroupObject("myGroup");
                LicenseObject l = createBasicLicenseObject("myLicense");
                m_artifact2groupRepository.create(b, g);
                m_group2licenseRepository.create(g, l);
                m_license2gatewayRepository.create(l, sgo.getGatewayObject());
                return g;
            }
        }, false, ArtifactObject.TOPIC_ADDED, GroupObject.TOPIC_ADDED, LicenseObject.TOPIC_ADDED,
                  Artifact2GroupAssociation.TOPIC_ADDED, Group2LicenseAssociation.TOPIC_ADDED,
                  License2GatewayAssociation.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert sgo.needsApprove() : "We added some deployment information, so the gateway should need approval.";

        sgo.setAutoApprove(true);

        assert sgo.needsApprove() : "Turning on the autoapprove should not automatically approve whatever was waiting.";

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                sgo.approve();
                return null;
            }
        }, false, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert !sgo.needsApprove() : "We approved the new version by hand, so we should not need approval.";

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                ArtifactObject b = createBasicBundleObject("myBundle2", "1.0", null);
                m_artifact2groupRepository.create(b, g);
                return null;
            }
        }, false, ArtifactObject.TOPIC_ADDED, Artifact2GroupAssociation.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

      assert !sgo.needsApprove() : "With autoapprove on, adding new deployment information should still not need approval (at least, after the two CHANGED events).";

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.unregister(sgo.getID());
                return null;
            }
        }, false, StatefulGatewayObject.TOPIC_STATUS_CHANGED, StatefulGatewayObject.TOPIC_REMOVED);

        try {
            removeAllRepositories();
        }
        catch (Exception e) {
            // Not much we can do...
            e.printStackTrace(System.err);
        }
        cleanUp();
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testStateful() throws Exception {
        User user = new MockUser("user");

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);
        addRepository("deploymentInstance", "apache", "deployment", true);

        RepositoryAdminLoginContext loginContext = m_repositoryAdmin.createLoginContext(user);
        loginContext.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", true);
        loginContext.addDeploymentRepository(new URL(HOST + ENDPOINT), "apache", "deployment", true);
        m_repositoryAdmin.login(loginContext);

        /*
         * First, test some functionality without auditlog data.
         * I would prefer to test without an auditlog present at all, but that
         * is not so easily done.
         */
        testStatefulCreateRemove();
        testStatefulSetAutoApprove();
        testStatefulApprove();

        testStatefulAuditlog();
        testStatefulAuditAndRegister();
        testStrangeNamesInGateways();

        try {
            removeAllRepositories();
        }
        catch (Exception e) {
            // Not much we can do...
            e.printStackTrace(System.err);
        }

        cleanUp();
    }

    private void testStatefulSetAutoApprove() throws Exception {

        // register gateway with
        final Map<String, String> attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, "a_gateway");
        attr.put(GatewayObject.KEY_AUTO_APPROVE, String.valueOf(true));
        final Map<String, String> tags = new HashMap<String, String>();

        final StatefulGatewayObject sgo = runAndWaitForEvent(new Callable<StatefulGatewayObject>() {
            public StatefulGatewayObject call() throws Exception {
                return m_statefulGatewayRepository.preregister(attr, tags);
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_ADDED);

        assert m_gatewayRepository.get().size() == 1 : "We expect to find exactly one gateway in the repository, but we find " + m_gatewayRepository.get().size();
        assert m_statefulGatewayRepository.get().size() == 1 : "We expect to find exactly one stateful gateway in the repository, but we find " + m_statefulGatewayRepository.get().size();

        assert sgo.getAutoApprove() : "The gateway should have auto approved value: true but got: false.";

        sgo.setAutoApprove(false);

        assert !sgo.getAutoApprove() : "The gateway should have auto approved value: false but got: true.";

        //clean up
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.unregister(sgo.getID());
                return null;
            }
        }, false, GatewayObject.TOPIC_REMOVED, StatefulGatewayObject.TOPIC_REMOVED);
    }

    private void testStatefulCreateRemove() throws Exception {
        final Map<String, String> attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, "myNewGateway1");
        final Map<String, String> tags = new HashMap<String, String>();

        try {
            m_statefulGatewayRepository.create(attr, tags);
            assert false : "Creating a stateful gateway repository should not be allowed.";
        }
        catch (UnsupportedOperationException uoe) {
            // expected
        }

        final StatefulGatewayObject sgo = runAndWaitForEvent(new Callable<StatefulGatewayObject>() {
            public StatefulGatewayObject call() throws Exception {
                return m_statefulGatewayRepository.preregister(attr, tags);
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_ADDED);

        assert m_gatewayRepository.get().size() == 1 : "We expect to find exactly one gateway in the repository, but we find " + m_gatewayRepository.get().size();
        assert m_statefulGatewayRepository.get().size() == 1 : "We expect to find exactly one stateful gateway in the repository, but we find " + m_statefulGatewayRepository.get().size();

        try {
            m_statefulGatewayRepository.remove(sgo);
            assert false : "Deleting a stateful gateway repositoy should not be allowed.";
        }
        catch (UnsupportedOperationException uoe) {
            // expected
        }

        assert m_gatewayRepository.get().size() == 1 : "We expect to find exactly one gateway in the repository, but we find " + m_gatewayRepository.get().size();
        assert m_statefulGatewayRepository.get().size() == 1 : "We expect to find exactly one stateful gateway in the repository, but we find " + m_statefulGatewayRepository.get().size();

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.unregister(sgo.getID());
                return null;
            }
        }, false, GatewayObject.TOPIC_REMOVED, StatefulGatewayObject.TOPIC_REMOVED);

        assert m_gatewayRepository.get().size() == 0 : "We expect to find no gateway in the repository, but we find " + m_gatewayRepository.get().size();
        assert m_statefulGatewayRepository.get().size() == 0 : "We expect to find no stateful gateway in the repository, but we find " + m_statefulGatewayRepository.get().size();
    }

    private void testStatefulApprove() throws Exception {
        final Map<String, String> attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, "myNewGateway2");
        final Map<String, String> tags = new HashMap<String, String>();
        final StatefulGatewayObject sgo = runAndWaitForEvent(new Callable<StatefulGatewayObject>() {
            public StatefulGatewayObject call() throws Exception {
                return m_statefulGatewayRepository.preregister(attr, tags);
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_ADDED);

        assert !sgo.needsApprove() : "Without any deployment versions, and no information in the shop, we should not need to approve.";
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "We expect the registration state to be Registered, but it is " + sgo.getRegistrationState();
        assert sgo.getStoreState().equals(StoreState.New) : "We expect the registration state to be New, but it is " + sgo.getStoreState();
        assert sgo.getCurrentVersion().equals(StatefulGatewayObject.UNKNOWN_VERSION);

        final ArtifactObject b11 = createBasicBundleObject("bundle1", "1", null);

        GroupObject g1 = createBasicGroupObject("group1");
        GroupObject g2 = createBasicGroupObject("group2"); // note that this group is not associated to a bundle.

        createDynamicBundle2GroupAssociation(b11, g1);

        final LicenseObject l1 = createBasicLicenseObject("license1");

        m_group2licenseRepository.create(g1, l1);
        m_group2licenseRepository.create(g2, l1);

        runAndWaitForEvent(new Callable<License2GatewayAssociation>() {
                public License2GatewayAssociation call() throws Exception {
                    return m_license2gatewayRepository.create(l1, sgo.getGatewayObject());
                }
            }, false, License2GatewayAssociation.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert sgo.needsApprove() : "We added information that influences our gateway, so we should need to approve it.";
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "We expect the registration state to be Registered, but it is " + sgo.getRegistrationState();
        assert sgo.getStoreState().equals(StoreState.Unapproved) : "We expect the registration state to be Unapproved, but it is " + sgo.getStoreState();
        assert sgo.getArtifactsFromShop().length == 1 : "According to the shop, this gateway needs 1 bundle, but it states we need " + sgo.getArtifactsFromShop().length;
        assert sgo.getArtifactsFromDeployment().length == 0 : "According to the deployment, this gateway needs 0 bundles, but it states we need " + sgo.getArtifactsFromDeployment().length;
        assert sgo.getCurrentVersion().equals(StatefulGatewayObject.UNKNOWN_VERSION);

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                createBasicDeploymentVersionObject("myNewGateway2", "1", b11);
                return null;
            }
        }, false, DeploymentVersionObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert !sgo.needsApprove() : "We manually created a deployment version that reflects the shop, so no approval should be necessary.";
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "We expect the registration state to be Registered, but it is " + sgo.getRegistrationState();
        assert sgo.getStoreState().equals(StoreState.Approved) : "We expect the registration state to be Approved, but it is " + sgo.getStoreState();
        assert sgo.getArtifactsFromShop().length == 1 : "According to the shop, this gateway needs 1 bundle, but it states we need " + sgo.getArtifactsFromShop().length;
        assert sgo.getArtifactsFromDeployment().length == 1 : "According to the deployment, this gateway needs 1 bundles, but it states we need " + sgo.getArtifactsFromDeployment().length;

        runAndWaitForEvent(new Callable<ArtifactObject>() {
            public ArtifactObject call() throws Exception {
                return createBasicBundleObject("bundle1", "2", null);
            }
        }, false, ArtifactObject.TOPIC_ADDED, Artifact2GroupAssociation.TOPIC_CHANGED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert sgo.needsApprove() : "We added a new version of a bundle that is used by the gateway, so approval should be necessary.";
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "We expect the registration state to be Registered, but it is " + sgo.getRegistrationState();
        assert sgo.getStoreState().equals(StoreState.Unapproved) : "We expect the registration state to be Unapproved, but it is " + sgo.getStoreState();
        assert sgo.getArtifactsFromShop().length == 1 : "According to the shop, this gateway needs 1 bundle, but it states we need " + sgo.getArtifactsFromShop().length;
        assert sgo.getArtifactsFromShop()[0].getURL().equals("http://bundle1-2") : "The shop should tell use we need bundle URL 'bundle1-2', but it tells us we need " + sgo.getArtifactsFromShop()[0].getURL();
        assert sgo.getArtifactsFromDeployment().length == 1 : "According to the deployment, this gateway needs 1 bundles, but it states we need " + sgo.getArtifactsFromDeployment().length;
        assert sgo.getArtifactsFromDeployment()[0].getUrl().equals("http://bundle1-1") : "The deployment should tell use we need bundle URL 'bundle1-1', but it tells us we need " + sgo.getArtifactsFromDeployment()[0].getUrl();
        assert sgo.getCurrentVersion().equals("1");

        final String newVersion = runAndWaitForEvent(new Callable<String>() {
            public String call() throws Exception {
                return sgo.approve();
            }
        }, false, DeploymentVersionObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        assert !sgo.needsApprove() : "Immediately after approval, no approval is necessary.";
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "We expect the registration state to be Registered, but it is " + sgo.getRegistrationState();
        assert sgo.getStoreState().equals(StoreState.Approved) : "We expect the registration state to be Approved, but it is " + sgo.getStoreState();
        assert sgo.getArtifactsFromShop().length == 1 : "According to the shop, this gateway needs 1 bundle, but it states we need " + sgo.getArtifactsFromShop().length;
        assert sgo.getArtifactsFromShop()[0].getURL().equals("http://bundle1-2") : "The shop should tell use we need bundle URL 'bundle1-2', but it tells us we need " + sgo.getArtifactsFromShop()[0].getURL();
        assert sgo.getArtifactsFromDeployment().length == 1 : "According to the deployment, this gateway needs 1 bundles, but it states we need " + sgo.getArtifactsFromDeployment().length;
        assert sgo.getArtifactsFromShop()[0].getURL().equals("http://bundle1-2") : "Deployment should tell use we need bundle URL 'bundle1-2', but it tells us we need " + sgo.getArtifactsFromShop()[0].getURL();
        assert m_deploymentVersionRepository.get().size() == 2 : "We expect two deployment versions, but we find " + m_deploymentVersionRepository.get().size();
        assert sgo.getCurrentVersion().equals(newVersion);

        // clean up this object ourselves; we cannot rely on cleanUp() in this case.
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.unregister(sgo.getID());
                return null;
            }
        }, false, GatewayObject.TOPIC_REMOVED, StatefulGatewayObject.TOPIC_REMOVED);

        assert m_statefulGatewayRepository.get().size() == 0;
    }

    private void testStrangeNamesInGateways() throws InvalidSyntaxException, IOException {
        List<LogEvent> events = new ArrayList<LogEvent>();
        Properties props = new Properties();

        // add a gateway with a weird name.
        events.add(new LogEvent(":)", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
        //fill auditlog; no install data
        m_auditLogStore.put(events);

        //see presence of sgo
        int sgrSizeBefore = m_statefulGatewayRepository.get().size();
        m_statefulGatewayRepository.refresh();
        assert m_statefulGatewayRepository.get().size() == sgrSizeBefore + 1 : "After refresh, we expect " + (sgrSizeBefore + 1) + " gateway based on auditlogdata, but we find " + m_statefulGatewayRepository.get().size();
        StatefulGatewayObject sgo = findStatefulGateway(":)");
        sgo.register();
        assert sgo.getRegistrationState().equals(RegistrationState.Registered) : "After registring our gateway, we assume it to be registered.";
        assert sgo.getProvisioningState().equals(ProvisioningState.Idle) : "We expect our object's provisioning state to be Idle, but it is " + m_statefulGatewayRepository.get().get(0).getProvisioningState();

    }


    private void testStatefulAuditlog() throws IOException, InvalidSyntaxException {
        List<LogEvent> events = new ArrayList<LogEvent>();
        Properties props = new Properties();
        events.add(new LogEvent("myGateway", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
        //fill auditlog; no install data
        m_auditLogStore.put(events);

        //see presence of sgo
        assert m_statefulGatewayRepository.get().size() == 0 : "Before audit log refresh, we expect nothing in the stateful repository, but we find " + m_statefulGatewayRepository.get().size();
        m_statefulGatewayRepository.refresh();
        assert m_statefulGatewayRepository.get().size() == 1 : "After refresh, we expect 1 gateway based on auditlogdata, but we find " + m_statefulGatewayRepository.get().size();
        StatefulGatewayObject sgo = m_statefulGatewayRepository.get().get(0);
        assert sgo.getProvisioningState().equals(ProvisioningState.Idle) : "We expect our object's provisioning state to be Idle, but it is " + m_statefulGatewayRepository.get().get(0).getProvisioningState();

        //fill auditlog with complete-data
        events = new ArrayList<LogEvent>();
        props = new Properties();
        props.put(AuditEvent.KEY_NAME, "mypackage");
        props.put(AuditEvent.KEY_VERSION, "123");
        events.add(new LogEvent("myGateway", 1, 2, 2, AuditEvent.DEPLOYMENTCONTROL_INSTALL, props));
        m_auditLogStore.put(events);
        m_statefulGatewayRepository.refresh();

        assert sgo.getLastInstallVersion().equals("123") : "Our last install version should be 123, but it is " + sgo.getLastInstallVersion();
        assert sgo.getProvisioningState().equals(ProvisioningState.InProgress)  : "We expect our object's provisioning state to be InProgress, but it is " + sgo.getProvisioningState();

        //fill auditlog with install data
        events = new ArrayList<LogEvent>();
        props = new Properties();
        props.put(AuditEvent.KEY_NAME, "mypackage");
        props.put(AuditEvent.KEY_VERSION, "123");
        props.put(AuditEvent.KEY_SUCCESS, "false");
        events.add(new LogEvent("myGateway", 1, 3, 3, AuditEvent.DEPLOYMENTADMIN_COMPLETE, props));
        m_auditLogStore.put(events);
        m_statefulGatewayRepository.refresh();

        assert sgo.getLastInstallVersion().equals("123") : "Our last install version should be 123, but it is " + sgo.getLastInstallVersion();
        assert sgo.getProvisioningState().equals(ProvisioningState.Failed)  : "We expect our object's provisioning state to be Failed, but it is " + sgo.getProvisioningState();
        assert !sgo.getLastInstallSuccess() : "Our last install was not successful, but according to the sgo it was.";

        sgo.acknowledgeInstallVersion("123");
        assert sgo.getProvisioningState().equals(ProvisioningState.Idle)  : "We expect our object's provisioning state to be Idle, but it is " + sgo.getProvisioningState();

        //add another install event.
        events = new ArrayList<LogEvent>();
        props = new Properties();
        props.put(AuditEvent.KEY_NAME, "mypackage");
        props.put(AuditEvent.KEY_VERSION, "124");
        events.add(new LogEvent("myGateway", 1, 4, 4, AuditEvent.DEPLOYMENTCONTROL_INSTALL, props));
        m_auditLogStore.put(events);
        m_statefulGatewayRepository.refresh();

        assert sgo.getLastInstallVersion().equals("124") : "Our last install version should be 124, but it is " + sgo.getLastInstallVersion();
        assert sgo.getProvisioningState().equals(ProvisioningState.InProgress)  : "We expect our object's provisioning state to be InProgress, but it is " + sgo.getProvisioningState();

        //fill auditlog with install data
        events = new ArrayList<LogEvent>();
        props = new Properties();
        props.put(AuditEvent.KEY_NAME, "mypackage");
        props.put(AuditEvent.KEY_VERSION, "124");
        props.put(AuditEvent.KEY_SUCCESS, "true");
        events.add(new LogEvent("myGateway", 1, 5, 5, AuditEvent.DEPLOYMENTADMIN_COMPLETE, props));
        m_auditLogStore.put(events);
        m_statefulGatewayRepository.refresh();

        assert sgo.getLastInstallVersion().equals("124") : "Our last install version should be 124, but it is " + sgo.getLastInstallVersion();
        assert sgo.getProvisioningState().equals(ProvisioningState.OK)  : "We expect our object's provisioning state to be OK, but it is " + sgo.getProvisioningState();
        assert sgo.getLastInstallSuccess() : "Our last install was successful, but according to the sgo it was not.";

        sgo.acknowledgeInstallVersion("124");
        assert sgo.getProvisioningState().equals(ProvisioningState.Idle)  : "We expect our object's provisioning state to be Idle, but it is " + sgo.getProvisioningState();
    }

    private void testStatefulAuditAndRegister() throws Exception {
        //preregister gateway
        final Map<String, String> attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, "myNewGateway3");
        final Map<String, String> tags = new HashMap<String, String>();

        final StatefulGatewayObject sgo1 = runAndWaitForEvent(new Callable<StatefulGatewayObject>() {
            public StatefulGatewayObject call() throws Exception {
                return m_statefulGatewayRepository.preregister(attr, tags);
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_ADDED);

        //do checks
        assert sgo1.isRegistered() : "We just preregistered a gateway, so it should be registered.";

        //add auditlog data
        List<LogEvent> events = new ArrayList<LogEvent>();
        Properties props = new Properties();
        events.add(new LogEvent("myNewGateway3", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
        m_auditLogStore.put(events);
        m_statefulGatewayRepository.refresh();

        //do checks
        assert sgo1.isRegistered() : "Adding auditlog data for a gateway does not influence its isRegistered().";
        try {
            sgo1.getGatewayObject();
        }
        catch (IllegalStateException ise) {
            assert false : "We should be able to get sgo1's gatewayObject.";
        }

        //add auditlog data for other gateway
        events = new ArrayList<LogEvent>();
        props = new Properties();
        events.add(new LogEvent("myNewGateway4", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
        m_auditLogStore.put(events);
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.refresh();
                return false;
            }
        }, false, StatefulGatewayObject.TOPIC_ADDED);
        final StatefulGatewayObject sgo2 = findStatefulGateway("myNewGateway4");

        //do checks
        assert sgo1.isRegistered() : "Adding auditlog data for a gateway does not influence its isRegistered().";
        try {
            sgo1.getGatewayObject();
        }
        catch (IllegalStateException ise) {
            assert false : "We should be able to get sgo1's gatewayObject.";
        }
        assert !sgo2.isRegistered() : "sgo2 is only found in the auditlog, so it cannot be in registered.";
        try {
            sgo2.getGatewayObject();
            assert false : "We should not be able to get sgo2's gatewayObject.";
        }
        catch (IllegalStateException ise) {
            // expected
        }

        //remove original gateway
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_statefulGatewayRepository.unregister(sgo1.getID());
                return null;
            }
        }, false, GatewayObject.TOPIC_REMOVED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        //do checks
        assert !sgo1.isRegistered() : "sgo1 is now only found in the auditlog, so it cannot be registered.";
        try {
            sgo1.getGatewayObject();
            assert false : "We should not be able to get sgo1's gatewayObject.";
        }
        catch (IllegalStateException ise) {
            //expected
        }
        assert !sgo2.isRegistered() : "sgo2 is only found in the auditlog, so it cannot be in registered.";
        try {
            sgo2.getGatewayObject();
            assert false : "We should not be able to get sgo2's gatewayObject.";
        }
        catch (IllegalStateException ise) {
            // expected
        }

        //register second gateway
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                sgo2.register();
                return null;
            }
        }, false, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        //do checks
        assert !sgo1.isRegistered() : "sgo1 is now only found in the auditlog, so it cannot be in registered.";
        try {
            sgo1.getGatewayObject();
            assert false : "We should not be able to get sgo1's gatewayObject.";
        }
        catch (IllegalStateException ise) {
            //expected
        }
        assert sgo2.isRegistered() : "sgo2 has been registered.";
        try {
            sgo2.getGatewayObject();
        }
        catch (IllegalStateException ise) {
            assert false : "We should be able to get sgo2's gatewayObject.";
        }

        int nrRegistered = m_statefulGatewayRepository.get(m_context.createFilter("(" + StatefulGatewayObject.KEY_REGISTRATION_STATE + "=" + RegistrationState.Registered + ")")).size();
        assert nrRegistered == 1 : "We expect to filter out one registered gateway, but we find " + nrRegistered;

        // Finally, create a license object
        final LicenseObject l1 = createBasicLicenseObject("thelicense");

        assert !sgo1.isRegistered() : "We just created a Staful GW object, is should not be registered";

        // register sgo1 again and create an association in 1 go
        License2GatewayAssociation lgw1 = runAndWaitForEvent(new Callable<License2GatewayAssociation>() {
            public License2GatewayAssociation call() throws Exception {
                sgo1.register();
                return m_license2gatewayRepository.create(l1, sgo1.getGatewayObject());
            }
        }, false, License2GatewayAssociation.TOPIC_ADDED, GatewayObject.TOPIC_ADDED, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        // checks
        nrRegistered = m_statefulGatewayRepository.get(m_context.createFilter("(" + StatefulGatewayObject.KEY_REGISTRATION_STATE + "=" + RegistrationState.Registered + ")")).size();
        assert nrRegistered == 2 : "We expect to filter out two registered gateways, but we find " + nrRegistered;
        assert sgo1.isRegistered() : "A stateful gw object should be registered";
        assert sgo1.isAssociated(l1, LicenseObject.class) : "The stateful gw object should be associated to thelicense.";
        assert lgw1.isSatisfied() : "Both ends of license - stateful gw should be satisfied.";
    }

    private StatefulGatewayObject findStatefulGateway(String gatewayID) throws InvalidSyntaxException {
        for (StatefulGatewayObject sgo : m_statefulGatewayRepository.get()) {
            if (sgo.getID().equals(gatewayID)) {
                return sgo;
            }
        }
        return null;
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testStatefulApprovalWithArtifacts() throws Exception {
        // some setup: we need a helper.
        ArtifactHelper myHelper = new MockArtifactHelper("mymime");

        Properties serviceProps = new Properties();
        serviceProps.put(ArtifactHelper.KEY_MIMETYPE, "mymime");

        Service myHelperService = m_depManager.createService()
            .setInterface(ArtifactHelper.class.getName(), serviceProps)
            .setImplementation(myHelper);

        m_depManager.add(myHelperService);

        // Empty tag map to be reused througout test
        final Map<String, String> tags = new HashMap<String, String>();

        // First, create a bundle and an artifact, but do not provide a processor for the artifact.
        ArtifactObject b1 = createBasicBundleObject("bundle1");
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(ArtifactObject.KEY_URL, "http://myobject");
        attr.put(ArtifactObject.KEY_PROCESSOR_PID, "my.processor.pid");
        attr.put(ArtifactHelper.KEY_MIMETYPE, "mymime");

        ArtifactObject a1 = m_artifactRepository.create(attr, tags);

        GroupObject g = createBasicGroupObject("group");
        LicenseObject l = createBasicLicenseObject("license");

        attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, "myGateway");

        StatefulGatewayObject sgo = m_statefulGatewayRepository.preregister(attr, tags);

        m_artifact2groupRepository.create(b1, g);
        m_artifact2groupRepository.create(a1, g);

        m_group2licenseRepository.create(g, l);

        m_license2gatewayRepository.create(l, sgo.getGatewayObject());

        try {
            sgo.approve();
            assert false : "Without a resource processor for our artifact, approve should go wrong.";
        }
        catch (IllegalStateException ise) {
            // expected
        }

        // Now, add a processor for the artifact.
        attr = new HashMap<String, String>();
        attr.put(ArtifactObject.KEY_URL, "http://myprocessor");
        attr.put(BundleHelper.KEY_RESOURCE_PROCESSOR_PID, "my.processor.pid");
        attr.put(BundleHelper.KEY_SYMBOLICNAME, "my.processor.bundle");
        attr.put(ArtifactHelper.KEY_MIMETYPE, BundleHelper.MIMETYPE);

        ArtifactObject b2 = m_artifactRepository.create(attr, tags);

        sgo.approve();

        DeploymentVersionObject dep = m_deploymentVersionRepository.getMostRecentDeploymentVersion(sgo.getID());

        DeploymentArtifact[] toDeploy = dep.getDeploymentArtifacts();

        assert toDeploy.length == 3 : "We expect to find three artifacts to deploy, but we find: " + toDeploy.length;
        DeploymentArtifact bundle1 = toDeploy[0];
        assert bundle1.getUrl().equals(b1.getURL()) && (bundle1.getKeys().length == 2) : "The first artifact in the list should be bundle1, but it is '" + toDeploy[0].toString() + "'";
        DeploymentArtifact bundle2 = toDeploy[1];
        assert bundle2.getUrl().equals(b2.getURL()) && (bundle2.getKeys().length == 3) && bundle2.getDirective(DeploymentArtifact.DIRECTIVE_ISCUSTOMIZER).equals("true"): "The first artifact in the list should be bundle1, but it is '" + toDeploy[0].toString() + "'";
        DeploymentArtifact artifact1 = toDeploy[2];
        assert artifact1.getUrl().equals(a1.getURL()) && (artifact1.getKeys().length == 2) && artifact1.getDirective(DeploymentArtifact.DIRECTIVE_KEY_PROCESSORID).equals("my.processor.pid"): "The first artifact in the list should be bundle1, but it is '" + toDeploy[0].toString() + "'";

        cleanUp();

        m_depManager.remove(myHelperService);
    }


    @Test( groups = { TestUtils.INTEGRATION } )
    public void testAutoGatewayOperator() throws Exception {
        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);
        addRepository("deploymentInstance", "apache", "deployment", true);

        // configure automation bundle; new configuration properties; bundle will start
        final Properties props = new Properties();
        props.put("registerGatewayFilter", "(id=anotherGate*)");
        props.put("approveGatewayFilter", "(id=DO_NOTHING)");
        props.put("autoApproveGatewayFilter", "(id=anotherGate*)");
        props.put("commitRepositories","true");
        props.put("gatewayRepository","gateway");
        props.put("deploymentRepository","deployment");
        props.put("storeRepository","store");
        props.put("customerName","apache");
        props.put("hostName",HOST);
        props.put("endpoint",ENDPOINT);

        final Configuration config = m_configAdmin.getConfiguration("org.apache.ace.client.automation", null);

        /*
         * First test the basic scenario where we create some auditlog data, this gateway should be auto-registered after max 1 sec.
         */
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                config.update(props);
                return null;
            }
        }, true, RepositoryAdmin.TOPIC_LOGIN);

        testAutoGatewayReg();

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                config.delete();
                return null;
            }
        }, false, RepositoryAdmin.TOPIC_LOGOUT);

        // Remove all repositories
        try {
            removeAllRepositories();
        }
        catch (Exception e) {
            // Not much we can do...
        }

        cleanUp();
    }

    private void testAutoGatewayReg() throws Exception {
        List<LogEvent> events = new ArrayList<LogEvent>();
        Properties props = new Properties();
        events.add(new LogEvent("anotherGateway", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
        //fill auditlog; no install data
        m_auditLogStore.put(events);

        int initRepoSize = m_statefulGatewayRepository.get().size();

        // Get the processauditlog task and run it
        ServiceTracker tracker = new ServiceTracker(m_context, m_context.createFilter("(&(" + Constants.OBJECTCLASS + "=" + Runnable.class.getName() + ")(" + SchedulerConstants.SCHEDULER_NAME_KEY + "=" + "org.apache.ace.client.processauditlog" + "))"), null);
        tracker.open();

        final Runnable processAuditlog = (Runnable) tracker.waitForService(2000);

        if (processAuditlog != null) {
            // commit should be called
            runAndWaitForEvent(new Callable<Object>() {
                public Object call() throws Exception {
                    processAuditlog.run();
                    return null;
                }
            }, false, RepositoryAdmin.TOPIC_REFRESH);

            assert m_statefulGatewayRepository.get().size() == initRepoSize + 1 : "After refresh, we expect 1 gateway based on auditlogdata, but we find " + m_statefulGatewayRepository.get().size();
            List<StatefulGatewayObject> sgoList = m_statefulGatewayRepository.get(m_context.createFilter("(id=anotherG*)"));
            StatefulGatewayObject sgo = sgoList.get(0);
            assert sgo != null : "Expected one (anotherGateway) in the list.";

            // should be registered and auto approved
            assert sgo.isRegistered(): "The automation gw operator should have registered anotherGateway.";
            assert sgo.getAutoApprove(): "The automation gw operator should have auto-approved anotherGateway.";

            // add a gateway which will not be autoregistered
            events.clear();
            events.add(new LogEvent("secondGateway", 1, 1, 1, AuditEvent.FRAMEWORK_STARTED, props));
            m_auditLogStore.put(events);

            // do auto gateway action
            processAuditlog.run();
            assert m_statefulGatewayRepository.get().size() == initRepoSize + 2 : "After refresh, we expect an additional gateway based on auditlogdata, but we find " + m_statefulGatewayRepository.get().size();
            sgoList = m_statefulGatewayRepository.get(m_context.createFilter("(id=second*)"));
            sgo = sgoList.get(0);

            // second gateway should not be registered
            assert !sgo.isRegistered(): "The automation gw operator should not have registered secongGateway.";
            assert !sgo.getAutoApprove(): "The automation gw operator should not have auto-approved myGateway.";
        }
        else
        {
            assert false : "Could not get a reference to the processAuditLog task.";
        }
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testImportArtifactInvalidURL() throws Exception {
        try {
            m_artifactRepository.importArtifact(null, true);
            assert false : "A null URL cannot be imported into an artifact repository.";
        }
        catch (IllegalArgumentException iae) {
            // expected
        }

        URL invalidfile = new URL("file:/thisfilecannotexist");

        try {
            m_artifactRepository.importArtifact(invalidfile, true);
            assert false : "An illegal URL should result in an error.";
        }
        catch (IllegalArgumentException iae) {
            // expected
        }

        cleanUp();
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testImportArtifactGeneralBundle() throws Exception {
        // Use a valid JAR file, without a Bundle-SymbolicName header.
        Manifest manifest = new Manifest();
        Attributes attributes = manifest.getMainAttributes();
        attributes.putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1");
        attributes.putValue(Constants.BUNDLE_MANIFESTVERSION, "2");

        File temp = File.createTempFile("org.apache.ace.test", ".jar");
        temp.deleteOnExit();
        JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
        jos.close();

        try {
            m_artifactRepository.importArtifact(temp.toURI().toURL(), true);
            assert false : "Without a Bundle-SymbolicName header, the BundleHelper cannot recognize this bundle.";
        }
        catch (IllegalArgumentException re) {
            //expected
        }

        try {
            m_artifactRepository.importArtifact(temp.toURI().toURL(), "notTheBundleMime", true);
            assert false : "We have given an illegal mimetype, so no recognizer or helper can be found.";
        }
        catch (IllegalArgumentException re) {
            //expected
        }

        // Use a valid JAR file, with a Bundle-SymbolicName header, but do not supply an OBR.
        attributes.putValue(BundleHelper.KEY_SYMBOLICNAME, "org.apache.ace.test");

        temp = File.createTempFile("org.apache.ace.test", ".jar");
        temp.deleteOnExit();
        jos = new JarOutputStream(new FileOutputStream(temp), manifest);
        jos.close();

        try {
            m_artifactRepository.importArtifact(temp.toURI().toURL(), true);
            assert false : "No OBR has been started, so the artifact repository should complain that there is no storage available.";
        }
        catch (IOException ise) {
            //expected
        }

        // Supply the OBR.
        addObr("/obr", "store");
        m_artifactRepository.setObrBase(new URL("http://localhost:" + TestConstants.PORT + "/obr/"));

        m_artifactRepository.importArtifact(temp.toURI().toURL(), true);

        assert m_artifactRepository.get().size() == 1;
        assert m_artifactRepository.getResourceProcessors().size() == 0;

        // Create a JAR file which looks like a resource processor supplying bundle.
        attributes.putValue(BundleHelper.KEY_RESOURCE_PROCESSOR_PID, "someProcessor");

        temp = File.createTempFile("org.apache.ace.test", ".jar");
        temp.deleteOnExit();
        jos = new JarOutputStream(new FileOutputStream(temp), manifest);
        jos.close();

        m_artifactRepository.importArtifact(temp.toURI().toURL(), true);

        assert m_artifactRepository.get().size() == 1;
        assert m_artifactRepository.getResourceProcessors().size() == 1;

        deleteObr("/obr");
    }

    private class MockUser implements User {

        private final String m_name;

        public MockUser(String name) {
            m_name = name;
        }

        @SuppressWarnings("unchecked")
        public Dictionary getCredentials() {
            return null;
        }

        public boolean hasCredential(String arg0, Object arg1) {
            return false;
        }

        public String getName() {
            return m_name;
        }

        @SuppressWarnings("unchecked")
        public Dictionary getProperties() {
            return null;
        }

        public int getType() {
            return 0;
        }
    }

    @Test( groups = { TestUtils.INTEGRATION } )
    public void testLoginLogoutAndLoginOnceAgainWhileCreatingAnAssociation() throws IOException, InterruptedException, InvalidSyntaxException {
        User user1 = new MockUser("user1");

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext1.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", true);
        m_repositoryAdmin.login(loginContext1);

        GroupObject g1 = createBasicGroupObject("group1");
        LicenseObject l1 = createBasicLicenseObject("license1");

        m_group2licenseRepository.create(g1, l1);

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);

        try {
            removeAllRepositories();
        }
        catch (IOException ioe) {
            // too bad.
        }
    }

    /**
     * Tests read only repository access: marking a repository as readonly for a login should
     * mean that it does not get committed, but local changes will stay around between logins.
     */
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testReadOnlyRepositoryAccess() throws Exception {
        User user1 = new MockUser("user1");

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("gatewayInstance", "apache", "gateway", true);

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1.addShopRepository(new URL(HOST + ENDPOINT), "apache", "store", true);
        loginContext1.addGatewayRepository(new URL(HOST + ENDPOINT), "apache", "gateway", false);
        m_repositoryAdmin.login(loginContext1);

        m_repositoryAdmin.checkout();

        createBasicGroupObject("group1");
        createBasicGatewayObject("gateway1");

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);

        assert m_groupRepository.get().size() == 1 : "We expect our own group object in the repository; we find " + m_groupRepository.get().size();
        assert m_gatewayRepository.get().size() == 1 : "We expect our own gateway object in the repository; we find " + m_gatewayRepository.get().size();

        m_repositoryAdmin.commit();

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);

        m_repositoryAdmin.checkout();

        assert m_groupRepository.get().size() == 1 : "We expect our own group object in the repository; we find " + m_groupRepository.get().size();
        assert m_gatewayRepository.get().size() == 0 : "Since the gateway repository will not be committed, we expect no gateway objects in the repository; we find " + m_gatewayRepository.get().size();

        cleanUp();
        try {
            removeAllRepositories();
        }
        catch (IOException ioe) {
            // too bad.
        }
    }

    @SuppressWarnings("unchecked")
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testRepostoryLoginDoubleRepository() throws Exception {
        RepositoryAdminLoginContext context = m_repositoryAdmin.createLoginContext(new MockUser("user"));
        context.addRepositories(new URL("http://localhost:" + TestConstants.PORT), "apache", "shop", true, ArtifactRepository.class, Artifact2GroupAssociationRepository.class, GroupRepository.class);
        context.addRepositories(new URL("http://localhost:" + TestConstants.PORT), "apache", "deployment", true, GroupRepository.class, Group2LicenseAssociationRepository.class, LicenseRepository.class);
        try {
            m_repositoryAdmin.login(context);
            assert false : "We tried to log in with two repositories that try to access the same repository service; this should not be allowed.";
        }
        catch (IllegalArgumentException iae) {
            // expected
        }
    }

    private static interface newRepository extends ObjectRepository<LicenseObject> {}

    @SuppressWarnings("unchecked")
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testRepostoryLoginRepositoryWithoutImplementation() throws Exception {
        RepositoryAdminLoginContext context = m_repositoryAdmin.createLoginContext(new MockUser("user"));
        context.addRepositories(new URL("http://localhost:" + TestConstants.PORT), "apache", "shop", true, ArtifactRepository.class, Artifact2GroupAssociationRepository.class, GroupRepository.class);
        context.addRepositories(new URL("http://localhost:" + TestConstants.PORT), "apache", "deployment", true, GroupRepository.class, Group2LicenseAssociationRepository.class, newRepository.class);
        try {
            m_repositoryAdmin.login(context);
            assert false : "We tried to log in with a repository for which no implementation is available; this should not be allowed.";
        }
        catch (IllegalArgumentException iae) {
            // expected
        }
    }

    /**
     * Tests the template processing mechanism: given a custom processor, do the correct calls go out?
     */
    @SuppressWarnings("unchecked")
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testTemplateProcessingInfrastructure() throws Exception {
        // create a preprocessor
        MockArtifactPreprocessor preprocessor = new MockArtifactPreprocessor();

        // create a helper
        MockArtifactHelper helper = new MockArtifactHelper("mymime", preprocessor);

        // register preprocessor and helper
        Properties serviceProps = new Properties();
        serviceProps.put(ArtifactHelper.KEY_MIMETYPE, "mymime");

        Service helperService = m_depManager.createService()
            .setInterface(ArtifactHelper.class.getName(), serviceProps)
            .setImplementation(helper);

        m_depManager.add(helperService);

        // create some tree from artifacts to a gateway
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                ArtifactObject b1 = createBasicBundleObject("myBundle");
                ArtifactObject b2 = createBasicBundleObject("myProcessor", "1.0.0", "myProcessor.pid");
                ArtifactObject a1 = createBasicArtifactObject("myArtifact", "mymime", "myProcessor.pid");
                GroupObject go = createBasicGroupObject("mygroup");
                LicenseObject lo = createBasicLicenseObject("mylicense");
                GatewayObject gwo = createBasicGatewayObject("templategateway");
                m_artifact2groupRepository.create(b1, go);
                // note that we do not associate b2: this is a resource processor, so it will be packed
                // implicitly. It should not be available to a preprocessor either.
                m_artifact2groupRepository.create(a1, go);
                m_group2licenseRepository.create(go, lo);
                m_license2gatewayRepository.create(lo, gwo);
                return null;
            }
        }, false, StatefulGatewayObject.TOPIC_ADDED);

        StatefulGatewayObject sgo = m_statefulGatewayRepository.get(m_context.createFilter("(" + GatewayObject.KEY_ID + "=templategateway)")).get(0);

        // wait until needsApprove is true; depending on timing, this could have happened before or after the TOPIC_ADDED.
        int attempts = 0;
        while (!sgo.needsApprove() && (attempts < 10)) {
            Thread.sleep(10);
        }
        assert sgo.needsApprove() : "With the new assignments, the SGO should need approval.";
        // create a deploymentversion
        sgo.approve();

//        // the preprocessor now has gotten its properties; inspect these
        PropertyResolver gateway = preprocessor.getProps();
        assert gateway.get("id").equals("templategateway") : "The property resolver should be able to resolve 'id'.";
        assert gateway.get("name").equals("mylicense") : "The property resolver should be able to resolve 'name'.";
        assert gateway.get("someunknownproperty") == null : "The property resolver should not be able to resolve 'someunknownproperty'.";

        cleanUp(); // we need to do this before the helper goes away

        m_depManager.remove(helperService);
    }

    /**
     * Tests the full template mechanism, from importing templatable artifacts, to creating deployment
     * versions with it. It uses the configuration (autoconf) helper, which uses a VelocityBased preprocessor.
     */
    @SuppressWarnings("unchecked")
    @Test( groups = { TestUtils.INTEGRATION } )
    public void testTemplateProcessing() throws Exception {
        addObr("/obr", "store");
        m_artifactRepository.setObrBase(new URL("http://localhost:" + TestConstants.PORT + "/obr/"));

        // create some template things
        String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<metatype:MetaData xmlns:metatype= \"http://www.osgi.org/xmlns/metatype/v1.0.0\">\n";
        String xmlFooter = "\n</metatype:MetaData>";

        String noTemplate = "<Attribute content=\"http://someURL\"/>";
        String noTemplateProcessed = "<Attribute content=\"http://someURL\"/>";
        final File noTemplateFile = createFileWithContents("template", "xml", xmlHeader+noTemplate+xmlFooter);

        String simpleTemplate = "<Attribute content=\"http://$context.name\"/>";
        String simpleTemplateProcessed = "<Attribute content=\"http://mylicense\"/>";
        File simpleTemplateFile = createFileWithContents("template", "xml", xmlHeader+simpleTemplate+xmlFooter);

        // create some tree from artifacts to a gateway
        GroupObject go = runAndWaitForEvent(new Callable<GroupObject>() {
            public GroupObject call() throws Exception {
                ArtifactObject b1 = createBasicBundleObject("myBundle");
                ArtifactObject b2 = createBasicBundleObject("myProcessor", "1.0.0", "org.osgi.deployment.rp.autoconf");
                GroupObject go = createBasicGroupObject("mygroup");
                LicenseObject lo = createBasicLicenseObject("mylicense");
                GatewayObject gwo = createBasicGatewayObject("templategateway2");
                m_artifact2groupRepository.create(b1, go);
                // note that we do not associate b2: this is a resource processor, so it will be packed
                // implicitly. It should not be available to a preprocessor either.
                m_group2licenseRepository.create(go, lo);
                m_license2gatewayRepository.create(lo, gwo);
                return go;
            }
        }, false, StatefulGatewayObject.TOPIC_ADDED);

        ArtifactObject a1 = m_artifactRepository.importArtifact(noTemplateFile.toURI().toURL(), true);
        Artifact2GroupAssociation a2g = m_artifact2groupRepository.create(a1, go);

        final StatefulGatewayObject sgo = m_statefulGatewayRepository.get(m_context.createFilter("(" + GatewayObject.KEY_ID + "=templategateway2)")).get(0);

        // create a deploymentversion
        assert sgo.needsApprove() : "With the new assignments, the SGO should need approval.";
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                sgo.approve();
                return null;
            }
        }, false, StatefulGatewayObject.TOPIC_STATUS_CHANGED);

        // find the deployment version
        DeploymentVersionObject dvo = m_deploymentVersionRepository.getMostRecentDeploymentVersion("templategateway2");
        String inFile = tryGetStringFromURL(findXmlUrlInDeploymentObject(dvo), 10, 100);

        assert inFile.equals(xmlHeader + noTemplateProcessed + xmlFooter) : "We expected to find\n" + xmlHeader + noTemplateProcessed + xmlFooter + "\n in the processed artifact, but found\n" + inFile;

        // try the simple template
        m_artifact2groupRepository.remove(a2g);
        a1 = m_artifactRepository.importArtifact(simpleTemplateFile.toURI().toURL(), true);
        a2g = m_artifact2groupRepository.create(a1, go);

        sgo.approve();

        // find the deployment version
        dvo = m_deploymentVersionRepository.getMostRecentDeploymentVersion("templategateway2");
        // sleep for a while, to allow the OBR to process the file.
        Thread.sleep(1000);

        inFile = tryGetStringFromURL(findXmlUrlInDeploymentObject(dvo), 10, 100);

        assert inFile.equals(xmlHeader + simpleTemplateProcessed + xmlFooter) : "We expected to find\n" + xmlHeader + simpleTemplateProcessed + xmlFooter + "\n in the processed artifact, but found\n" + inFile;

        deleteObr("/obr");
    }

    private String tryGetStringFromURL(URL url, int tries, int interval) throws Exception {
        while (true) {
            try {
                String result = getStringFromURL(url);
                return result;
            }
            catch (IOException ioe) {
                Thread.sleep(interval);
                tries--;
                if (tries == 0) {
                   throw ioe;
                }
            }
        }

    }

    /**
     * Helper method for testTemplateProcessing; finds the URL of the first deploymentartifact
     * with 'xml' in its url.
     */
    private URL findXmlUrlInDeploymentObject(DeploymentVersionObject dvo) throws MalformedURLException {
        DeploymentArtifact[] artifacts = dvo.getDeploymentArtifacts();
        for (DeploymentArtifact da : artifacts) {
            if (da.getUrl().contains("xml")) {
                return new URL(da.getUrl());
            }
        }
        return null;
    }

    /**
     * Creates a temporary file with the given name and extension, and stores the given
     * contents in it.
     */
    private File createFileWithContents(String name, String extension, String contents) throws IOException {
        File file = File.createTempFile(name, extension);
        file.deleteOnExit();
        Writer w = new OutputStreamWriter(new FileOutputStream(file));
        w.write(contents);
        w.close();
        return file;
    }

    /**
     * Opens a URL, and gets all data from it as a string.
     */
    private String getStringFromURL(URL url) throws IOException {
        StringBuilder found = new StringBuilder();
        Reader reader = new InputStreamReader(url.openStream());

        char[] buf = new char[1024];
        for (int count = reader.read(buf); count != -1; count = reader.read(buf)) {
            found.append(buf, 0, count);
        }
        reader.close();
        return found.toString();
    }

    private volatile List<String> m_waitingForTopic = Collections.synchronizedList(new ArrayList<String>());
    private volatile Semaphore m_semaphore;
    private volatile boolean m_runAndWaitDebug = false;

    private <T> T runAndWaitForEvent(Callable<T> callable, boolean debug, String... topic) throws Exception {
        m_runAndWaitDebug = debug;
        T result = null;
        m_waitingForTopic.clear();
        m_waitingForTopic.addAll(Arrays.asList(topic));
        m_semaphore = new Semaphore(0);
        result = callable.call();
        assert m_semaphore.tryAcquire(15000, TimeUnit.MILLISECONDS) : "We expect the event within a reasonable timeout.";
        m_semaphore = null;
        return result;
    }

    public void handleEvent(Event event) {
        if (m_runAndWaitDebug) {System.err.println("Received event: " + event.getTopic());}
        if (m_waitingForTopic.remove(event.getTopic())) {
            if (m_runAndWaitDebug) {System.err.println("Event was expected.");}
            if ((m_semaphore != null) && m_waitingForTopic.isEmpty()) {
                m_semaphore.release();
                m_runAndWaitDebug = false;
            }
        }
    }

    private ArtifactObject createBasicBundleObject(String symbolicName) {
        return createBasicBundleObject(symbolicName, null, null);
    }

    private ArtifactObject createBasicBundleObject(String symbolicName, String version, String processorPID) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(BundleHelper.KEY_SYMBOLICNAME, symbolicName);
        attr.put(ArtifactObject.KEY_MIMETYPE, BundleHelper.MIMETYPE);
        attr.put(ArtifactObject.KEY_URL, "http://" + symbolicName + "-" + ((version == null) ? "null" : version));
        Map<String, String> tags = new HashMap<String, String>();

        if (version != null) {
            attr.put(BundleHelper.KEY_VERSION, version);
        }
        if (processorPID != null) {
            attr.put(BundleHelper.KEY_RESOURCE_PROCESSOR_PID, processorPID);
        }
        return m_artifactRepository.create(attr, tags);
    }

    private ArtifactObject createBasicArtifactObject(String name, String mimetype, String processorPID) throws InterruptedException {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(ArtifactObject.KEY_ARTIFACT_NAME, name);
        attr.put(ArtifactObject.KEY_MIMETYPE, mimetype);
        attr.put(ArtifactObject.KEY_URL, "http://" + name);
        attr.put(ArtifactObject.KEY_PROCESSOR_PID, processorPID);
        Map<String, String> tags = new HashMap<String, String>();

        return m_artifactRepository.create(attr, tags);
    }

    private GroupObject createBasicGroupObject(String name) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(GroupObject.KEY_NAME, name);
        Map<String, String> tags = new HashMap<String, String>();

        return m_groupRepository.create(attr, tags);
    }

    private LicenseObject createBasicLicenseObject(String name) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(LicenseObject.KEY_NAME, name);
        Map<String, String> tags = new HashMap<String, String>();

        return m_licenseRepository.create(attr, tags);
    }

    private GatewayObject createBasicGatewayObject(String id) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(GatewayObject.KEY_ID, id);
        Map<String, String> tags = new HashMap<String, String>();

        return m_gatewayRepository.create(attr, tags);
    }

    private DeploymentVersionObject createBasicDeploymentVersionObject(String gatewayID, String version, ArtifactObject... bundles) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(DeploymentVersionObject.KEY_GATEWAYID, gatewayID);
        attr.put(DeploymentVersionObject.KEY_VERSION, version);
        Map<String, String> tags = new HashMap<String, String>();

        List<DeploymentArtifact> artifacts = new ArrayList<DeploymentArtifact>();
        for (ArtifactObject artifact : bundles) {
            Map<String, String> directives = new HashMap<String, String>();
            directives.put(BundleHelper.KEY_SYMBOLICNAME, artifact.getAttribute(BundleHelper.KEY_SYMBOLICNAME));
            directives.put(DeploymentArtifact.DIRECTIVE_KEY_BASEURL, artifact.getURL());
            if (artifact.getAttribute(BundleHelper.KEY_VERSION) != null) {
                directives.put(BundleHelper.KEY_VERSION, artifact.getAttribute(BundleHelper.KEY_VERSION));
            }
            artifacts.add(m_deploymentVersionRepository.createDeploymentArtifact(artifact.getURL(), directives));
        }
        return m_deploymentVersionRepository.create(attr, tags, artifacts.toArray(new DeploymentArtifact[0]));
    }

    private Artifact2GroupAssociation createDynamicBundle2GroupAssociation(ArtifactObject artifact, GroupObject group) {
        Map<String, String> properties = new HashMap<String, String>();
        properties.put(BundleHelper.KEY_ASSOCIATION_VERSIONSTATEMENT, "0.0.0");
        return m_artifact2groupRepository.create(artifact, properties, group, null);
    }

    /*
     * The following code is borrowed from RepositoryTest.java, and is used to instantiate and
     * use repository servlets.
     */

    protected void startRepositoryService() throws IOException {
        // configure the (replication)repository servlets
        setProperty("org.apache.ace.repository.servlet.RepositoryServlet", new Object[][] { { HttpConstants.ENDPOINT, ENDPOINT } });
    }

    @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();
    }

    /* Configure a new repository instance */
    private void addRepository(String instanceName, String customer, String name, 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));
        props.put("factory.instance.pid", instanceName);
        Configuration config = m_configAdmin.createFactoryConfiguration("org.apache.ace.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(5000) == null) {
            throw new IOException("Did not get notified about new repository becoming available in time.");
        }
        tracker.close();
    }

    private void addObr(String endpoint, String fileLocation) throws IOException, InterruptedException, InvalidSyntaxException {
        Properties propsServlet = new Properties();
        propsServlet.put(HttpConstants.ENDPOINT, endpoint);
        propsServlet.put("OBRInstance", "singleOBRServlet");
        Properties propsStore = new Properties();
        propsStore.put(OBRFileStoreConstants.FILE_LOCATION_KEY, fileLocation);
        propsStore.put("OBRInstance", "singleOBRStore");

        Configuration configServlet = m_configAdmin.getConfiguration("org.apache.ace.obr.servlet", null);
        Configuration configStore = m_configAdmin.getConfiguration("org.apache.ace.obr.storage.file", null);

        configServlet.update(propsServlet);
        configStore.update(propsStore);

        // Wait for the endpoint to respond.
        // TODO below there is a similar url that does put a slash between port and endpoint, why?
        URL url = new URL("http://localhost:" + TestConstants.PORT + endpoint + "/repository.xml");
        int response = ((HttpURLConnection) url.openConnection()).getResponseCode();
        int tries = 0;
        while ((response != 200) && (tries < 50)) {
            Thread.sleep(100); //If we get interrupted, there will be a good reason for it.
            response = ((HttpURLConnection) url.openConnection()).getResponseCode();
            tries++;
        }
        if (tries == 50) {
            throw new IOException("The OBR servlet does not seem to be responding well. Last response code: " + response);
        }
    }

    private void deleteObr(String endpoint) throws IOException, InvalidSyntaxException, InterruptedException {
        // This is a little ugly: we cannot just delete the configuration, since that will result in a
        // sharing violation between this bundle and the servlet bundle. In stead, we make the servlet
        // use an invalid endpoint.
        Properties propsServlet = new Properties();
        propsServlet.put(HttpConstants.ENDPOINT, endpoint + "invalid");
        propsServlet.put("OBRInstance", "singleOBRServlet");
        Configuration configServlet = m_configAdmin.getConfiguration("org.apache.ace.obr.servlet");
        configServlet.update(propsServlet);

        URL url = new URL("http://localhost:" + TestConstants.PORT + "/" + endpoint + "/repository.xml");
        int response = ((HttpURLConnection) url.openConnection()).getResponseCode();
        int tries = 0;
        while ((response != 404) && (tries < 50)) {
            Thread.sleep(100); //If we get interrupted, there will be a good reason for it.
            response = ((HttpURLConnection) url.openConnection()).getResponseCode();
            tries++;
        }
        if (tries == 50) {
            throw new IOException("The OBR servlet does not want to go away. Last response code: " + response);
        }
}

    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();
        }
    }

    /* 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);
    }

}

class MockArtifactHelper implements ArtifactHelper {
    private final String m_mimetype;
    private final ArtifactPreprocessor m_preprocessor;

    MockArtifactHelper(String mimetype) {
        this(mimetype, null);
    }

    MockArtifactHelper(String mimetype, ArtifactPreprocessor preprocessor) {
        m_mimetype = mimetype;
        m_preprocessor = preprocessor;
    }

    public boolean canUse(ArtifactObject object) {
        return object.getMimetype().equals(m_mimetype);
    }

    public Map<String, String> checkAttributes(Map<String, String> attributes) {
        return attributes;
    }

    public Comparator<ArtifactObject> getComparator() {
        return null;
    }
    public String[] getDefiningKeys() {
        return new String[0];
    }

    public String[] getMandatoryAttributes() {
        return new String[0];
    }

    public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
        return ("(" + ArtifactObject.KEY_URL + "=" + obj.getURL() + ")");
    }

    public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
        return 1;
    }

    public ArtifactPreprocessor getPreprocessor() {
        return m_preprocessor;
    }
};

class MockArtifactPreprocessor implements ArtifactPreprocessor {
    private PropertyResolver m_props;
    public String preprocess(String url, PropertyResolver props, String gatewayID, String version, URL obrBase) throws IOException {
        m_props = props;
        return url;
    }

    PropertyResolver getProps() {
        return m_props;
    }

    public boolean needsNewVersion(String url, PropertyResolver props, String gatewayID, String fromVersion) {
        return false;
    }
}
