Package org.apache.ace.it.repositoryadmin

Source Code of org.apache.ace.it.repositoryadmin.RepositoryAdminTest

/*
* 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.it.repositoryadmin;

import static org.apache.ace.client.repository.stateful.StatefulTargetObject.TOPIC_ADDED;
import static org.apache.ace.client.repository.stateful.StatefulTargetObject.TOPIC_REMOVED;
import static org.apache.ace.client.repository.stateful.StatefulTargetObject.TOPIC_STATUS_CHANGED;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;

import org.apache.ace.client.repository.RepositoryAdmin;
import org.apache.ace.client.repository.RepositoryAdminLoginContext;
import org.apache.ace.client.repository.RepositoryObject.WorkingState;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.DeploymentVersionObject;
import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
import org.apache.ace.client.repository.object.DistributionObject;
import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
import org.apache.ace.client.repository.object.FeatureObject;
import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.stateful.StatefulTargetObject;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.event.Event;
import org.osgi.service.useradmin.User;

public class RepositoryAdminTest extends BaseRepositoryAdminTest {

    public void testAssociationsWithMovingEndpoints() throws Exception {
        final ArtifactObject b1 = createBasicBundleObject("thebundle", "1", null);
        final FeatureObject g1 = createBasicFeatureObject("thefeature");

        final Artifact2FeatureAssociation bg = runAndWaitForEvent(new Callable<Artifact2FeatureAssociation>() {
            public Artifact2FeatureAssociation call() throws Exception {
                Map<String, String> properties = new HashMap<String, String>();
                properties.put(BundleHelper.KEY_ASSOCIATION_VERSIONSTATEMENT, "[1,3)");
                return m_artifact2featureRepository.create(b1, properties, g1, null);
            }
        }, false, Artifact2FeatureAssociation.TOPIC_ADDED);

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

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

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

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

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

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

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

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

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

        cleanUp();
    }

    public void testAutoApprove() throws Exception {
        User user = new MockUser();

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("targetInstance", "apache", "target", true);
        addRepository("deploymentInstance", "apache", "deployment", true);

        RepositoryAdminLoginContext loginContext = m_repositoryAdmin.createLoginContext(user);
        loginContext
            .add(loginContext.createShopRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("store").setWriteable())
            .add(loginContext.createTargetRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("target").setWriteable())
            .add(loginContext.createDeploymentRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("deployment").setWriteable());

        m_repositoryAdmin.login(loginContext);

        m_repositoryAdmin.checkout();

        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                createBasicTargetObject("testAutoApproveTarget");
                return null;
            }
        }, false, TargetObject.TOPIC_ADDED, TOPIC_ADDED);

        final StatefulTargetObject sgo =
            m_statefulTargetRepository.get(
                m_bundleContext.createFilter("(" + TargetObject.KEY_ID + "=" + "testAutoApproveTarget)")).get(0);

        // Set up some deployment information for the target.
        final FeatureObject g = runAndWaitForEvent(new Callable<FeatureObject>() {
            public FeatureObject call() throws Exception {
                ArtifactObject b = createBasicBundleObject("myBundle", "1.0", null);
                FeatureObject g = createBasicFeatureObject("myFeature");
                DistributionObject l = createBasicDistributionObject("myDistribution");
                m_artifact2featureRepository.create(b, g);
                m_feature2distributionRepository.create(g, l);
                m_distribution2targetRepository.create(l, sgo.getTargetObject());
                return g;
            }
        }, false, ArtifactObject.TOPIC_ADDED, FeatureObject.TOPIC_ADDED, DistributionObject.TOPIC_ADDED,
            Artifact2FeatureAssociation.TOPIC_ADDED, Feature2DistributionAssociation.TOPIC_ADDED,
            Distribution2TargetAssociation.TOPIC_ADDED, TOPIC_STATUS_CHANGED);

        assertTrue("We added some deployment information, so the target should need approval.", sgo.needsApprove());

        sgo.setAutoApprove(true);

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

        sgo.approve();

        List<Event> events = new ArrayList<Event>();
        runAndWaitForEvent(new Callable<Void>() {
            public Void call() throws Exception {
                m_repositoryAdmin.commit();
                return null;
            }
        }, false, events, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED, RepositoryAdmin.TOPIC_REFRESH);

        assertFalse("We approved the new version by hand, so we should not need approval.", sgo.needsApprove());
        assertContainsRefreshCause(events, "commit");

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

        runAndWaitForEvent(new Callable<Void>() {
            public Void call() throws Exception {
                m_repositoryAdmin.commit();
                return null;
            }
        }, false, DeploymentVersionObject.TOPIC_ADDED, TOPIC_STATUS_CHANGED);

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

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

    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.test1", ".jar");
        temp.deleteOnExit();
        JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
        jos.close();

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

        try {
            m_artifactRepository.importArtifact(temp.toURI().toURL(), "notTheBundleMime", true);
            fail("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, String.format("org.apache.ace.test-%d; singleton:=true", System.currentTimeMillis()));

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

        try {
            m_artifactRepository.importArtifact(temp.toURI().toURL(), true);
            fail("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.importArtifact(temp.toURI().toURL(), true);

        assertTrue(m_artifactRepository.get().size() == 1);
        assertTrue(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");
        attributes.putValue(BundleHelper.KEY_VERSION, "1.0.0.processor");

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

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

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

        deleteObr("/obr");
    }

    public void testImportArtifactInvalidURL() throws Exception {
        try {
            m_artifactRepository.importArtifact(null, true);
            fail("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);
            fail("An illegal URL should result in an error.");
        }
        catch (IllegalArgumentException iae) {
            // expected
        }

        cleanUp();
    }

    public void testLoginLogoutAndLoginOnceAgainWhileCreatingAnAssociation() throws IOException, InterruptedException,
        InvalidSyntaxException {
        User user1 = new MockUser();

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("targetInstance", "apache", "target", true);

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1
            .add(loginContext1.createShopRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("store").setWriteable())
            .add(loginContext1.createTargetRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("target").setWriteable());

        m_repositoryAdmin.login(loginContext1);

        FeatureObject g1 = createBasicFeatureObject("feature1");
        DistributionObject l1 = createBasicDistributionObject("distribution1");

        m_feature2distributionRepository.create(g1, l1);

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);
    }

    /**
     * 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.
     */
    public void testReadOnlyRepositoryAccess() throws Exception {
        User user1 = new MockUser();

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("targetInstance", "apache", "target", true);

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1
            .add(loginContext1.createShopRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("store").setWriteable())
            .add(loginContext1.createTargetRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("target"));

        m_repositoryAdmin.login(loginContext1);

        m_repositoryAdmin.checkout();

        createBasicFeatureObject("feature1");
        createBasicTargetObject("target1");

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);

        assertEquals("We expect our own feature object in the repository;", 1, m_featureRepository.get().size());
        assertEquals("We expect our own target object in the repository;", 1, m_targetRepository.get().size());

        m_repositoryAdmin.commit();

        m_repositoryAdmin.logout(false);

        m_repositoryAdmin.login(loginContext1);

        m_repositoryAdmin.checkout();

        assertEquals("We expect our own feature object in the repository;", 1, m_featureRepository.get().size());
        assertEquals("Since the target repository will not be committed, we expect no target objects in the repository;", 0, m_targetRepository.get().size());
    }

    /**
     * Add a bundle, feature and distribution, associate all, remove the feature, No associations should be left.
     *
     * @throws Exception
     */
    public void testRemoveBundleFeature() throws Exception {
        final ArtifactObject b1 = createBasicBundleObject("thebundle", "1", null);
        final FeatureObject g1 = createBasicFeatureObject("thefeature");

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

        final DistributionObject l1 = createBasicDistributionObject("thedistribution");

        final Feature2DistributionAssociation gtl = runAndWaitForEvent(new Callable<Feature2DistributionAssociation>() {
            public Feature2DistributionAssociation call() throws Exception {
                return m_feature2distributionRepository.create("(name=thefeature)", "(name=thedistribution)");
            }
        }, false, Feature2DistributionAssociation.TOPIC_ADDED);

        assertTrue("The left side of the BG-association should be b1.", (bg.getLeft().size() == 1) && bg.getLeft().contains(b1));
        assertTrue("The right side of the BG-association should be g1.", (bg.getRight().size() == 1) && bg.getRight().contains(g1));
        assertTrue("The left side of the GtL-association should be g1.", (gtl.getLeft().size() == 1) && gtl.getLeft().contains(g1));
        assertTrue("The right side of the GtL-association should be l1.", (gtl.getRight().size() == 1) && gtl.getRight().contains(l1));
        assertTrue("The bundlefeature association should be satisfied.", bg.isSatisfied());
        assertTrue("The feature2distribution association should be satisfied.", gtl.isSatisfied());
        assertEquals("Bundle b1 should be associated to one feature.", 1, b1.getFeatures().size());
        assertEquals("Distribution l1 should be associated to one feature.", 1, l1.getFeatures().size());

        // remove the feature
        runAndWaitForEvent(new Callable<Object>() {
            public Object call() throws Exception {
                m_featureRepository.remove(g1);
                return null;
            }
        }, false, Artifact2FeatureAssociation.TOPIC_CHANGED, Feature2DistributionAssociation.TOPIC_CHANGED);

        assertFalse("The bundlefeature association shouldn not be satisfied.", gtl.isSatisfied());
        assertFalse("The feature2distribution assocation should not be satisfied.", bg.isSatisfied());

        assertEquals("Bundle b1 shouldn't be associated to any feature, but is associated to " + b1.getFeatures(), 0, b1.getFeatures().size());
        assertEquals("Distribution l1 shouldn't be associated to any feature.", 0, l1.getFeatures().size());

        cleanUp();
    }

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

        startRepositoryService();

        addRepository("storeInstance", "apache", "store", true);
        addRepository("targetInstance", "apache", "target", true);

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

        final RepositoryAdminLoginContext loginContext1 = m_repositoryAdmin.createLoginContext(user1);
        loginContext1
            .add(loginContext1.createShopRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("store").setWriteable())
            .add(loginContext1.createTargetRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("target").setWriteable());

        m_repositoryAdmin.login(loginContext1);

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

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

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

        assertTrue("After initial checkout, the repository is current.", m_repositoryAdmin.isCurrent());
        assertFalse("Immediately after login, the repository cannot be modified.", m_repositoryAdmin.isModified());
        assertContainsRefreshCause(events, "checkout");

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

        assertTrue("After initial checkout, the repository is current.", m_repositoryAdmin.isCurrent());
        assertTrue("We have added a bundle, so the repository is modified.", m_repositoryAdmin.isModified());
        assertEquals(1, m_artifactRepository.get().size());
        assertEquals("We expect the working state of our bundle to be New;", WorkingState.New, m_repositoryAdmin.getWorkingState(b1));
        assertEquals("We expect one bundle object in working state New;", 1, m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.New));
        assertEquals("We expect 0 bundle objects in working state Changed;", 0, m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Changed));
        assertEquals("We expect 0 bundle objects in working state Unchanged;", 0, m_repositoryAdmin.getNumberWithWorkingState(ArtifactObject.class, WorkingState.Unchanged));

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

        cleanUp();

        assertEquals(0, m_artifactRepository.get().size());

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

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

        m_repositoryAdmin.commit();

        assertTrue("After a commit, the repository must be current.", m_repositoryAdmin.isCurrent());
        assertFalse("After a commit, the repository cannot be modified.", m_repositoryAdmin.isModified());

        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
            .add(loginContext2.createShopRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("store").setWriteable())
            .add(loginContext2.createTargetRepositoryContext()
                .setLocation(m_endpoint).setCustomer("apache").setName("target").setWriteable());

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

        assertEquals(0, m_artifactRepository.get().size());

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

        assertEquals("We expect to find 1 bundle after checkout;", 1, m_artifactRepository.get().size());
        assertTrue("After a checkout, without changing anything, the repository must be current.", m_repositoryAdmin.isCurrent());
        assertFalse("After a checkout, without changing anything, the repository cannot be modified.", m_repositoryAdmin.isModified());

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

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

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

        assertEquals("We expect 1 item in the bundle repository;", 1, 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);

        assertEquals("We expect 2 items in the bundle repository;", 2, m_artifactRepository.get().size());

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

        assertEquals("We expect 1 item in the bundle repository;", 1, m_artifactRepository.get().size());
        assertContainsRefreshCause(events, "revert");
    }

    private void assertContainsRefreshCause(List<Event> events, String cause) {
        boolean found = false;
        for (Event event : events) {
            if (RepositoryAdmin.TOPIC_REFRESH.equals(event.getTopic())) {
                assertEquals("Refresh property does not have the correct cause property?!", event.getProperty("cause"), cause);
                found = true;
            }
        }
        assertTrue("Events did not contain expected refresh event!", found);
    }
}
TOP

Related Classes of org.apache.ace.it.repositoryadmin.RepositoryAdminTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.