Package org.apache.ace.it.repositoryadmin

Source Code of org.apache.ace.it.repositoryadmin.BaseRepositoryAdminTest$MockUser

/*
* 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 java.io.IOException;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.apache.ace.client.repository.ObjectRepository;
import org.apache.ace.client.repository.RepositoryAdmin;
import org.apache.ace.client.repository.RepositoryObject;
import org.apache.ace.client.repository.SessionFactory;
import org.apache.ace.client.repository.helper.bundle.BundleHelper;
import org.apache.ace.client.repository.object.ArtifactObject;
import org.apache.ace.client.repository.object.DistributionObject;
import org.apache.ace.client.repository.object.FeatureObject;
import org.apache.ace.client.repository.object.TargetObject;
import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
import org.apache.ace.client.repository.repository.ArtifactRepository;
import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
import org.apache.ace.client.repository.repository.DistributionRepository;
import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
import org.apache.ace.client.repository.repository.FeatureRepository;
import org.apache.ace.client.repository.repository.TargetRepository;
import org.apache.ace.client.repository.stateful.StatefulTargetRepository;
import org.apache.ace.http.listener.constants.HttpConstants;
import org.apache.ace.it.IntegrationTestBase;
import org.apache.ace.log.server.store.LogStore;
import org.apache.ace.obr.storage.OBRFileStoreConstants;
import org.apache.ace.repository.Repository;
import org.apache.ace.repository.RepositoryConstants;
import org.apache.ace.test.constants.TestConstants;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.ComponentStateListener;
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.EventConstants;
import org.osgi.service.event.EventHandler;
import org.osgi.service.http.HttpService;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
import org.osgi.util.tracker.ServiceTracker;

public abstract class BaseRepositoryAdminTest extends IntegrationTestBase {

    protected static final String TEST_USER_NAME = "testUser";

    final class MockUser implements User {
        private final String m_name;

        public MockUser() {
            m_name = String.format("user-%s", Long.toHexString(System.nanoTime()));
        }

        public Dictionary<Object, Object> getCredentials() {
            return new Properties();
        }

        public String getName() {
            return m_name;
        }

        public Dictionary<Object, Object> getProperties() {
            return new Properties();
        }

        public int getType() {
            return 0;
        }

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

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

    protected URL m_endpoint;
    protected URL m_obrURL;

    /* All injected by dependency manager */
    protected volatile ConfigurationAdmin m_configAdmin;
    protected volatile RepositoryAdmin m_repositoryAdmin;
    protected volatile ArtifactRepository m_artifactRepository;
    protected volatile Artifact2FeatureAssociationRepository m_artifact2featureRepository;
    protected volatile FeatureRepository m_featureRepository;
    protected volatile Feature2DistributionAssociationRepository m_feature2distributionRepository;
    protected volatile DistributionRepository m_distributionRepository;
    protected volatile Distribution2TargetAssociationRepository m_distribution2targetRepository;
    protected volatile TargetRepository m_targetRepository;
    protected volatile DeploymentVersionRepository m_deploymentVersionRepository;
    protected volatile StatefulTargetRepository m_statefulTargetRepository;
    protected volatile LogStore m_auditLogStore;

    protected final void addObr(String endpoint, String fileLocation) throws IOException, InterruptedException {
        String baseURL = String.format("http://localhost:%d%s/", TestConstants.PORT, endpoint);

        m_obrURL = new URL(baseURL);

        configure("org.apache.ace.client.repository", "obrlocation", m_obrURL.toExternalForm());
        configure("org.apache.ace.obr.servlet", "OBRInstance", "singleOBRServlet", "org.apache.ace.server.servlet.endpoint", endpoint, "authentication.enabled", "false");
        configure("org.apache.ace.obr.storage.file", "OBRInstance", "singleOBRStore", OBRFileStoreConstants.FILE_LOCATION_KEY, fileLocation);

        // Wait for the endpoint to respond.
        URL repoURL = new URL(baseURL + "repository.xml");
        int response = ((HttpURLConnection) repoURL.openConnection()).getResponseCode();
        int tries = 0;
        while ((response != 200) && (tries++ < 50)) {
            response = ((HttpURLConnection) repoURL.openConnection()).getResponseCode();
            Thread.sleep(100); // If we get interrupted, there will be a good reason for it.
        }
        if (tries == 50) {
            throw new IOException("The OBR servlet does not seem to be responding well. Last response code: " + response);
        }
    }

    /* Configure a new repository instance */
    protected final 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_bundleContext, m_bundleContext.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();
    }

    @Override
    protected void configureAdditionalServices() throws Exception {
        // remove all repositories, in case a test case does not reach it's cleanup section due to an exception
        removeAllRepositories();
    }

    @Override
    protected void configureProvisionedServices() throws Exception {
        m_endpoint = new URL(HOST + ENDPOINT_NAME);

        getService(SessionFactory.class).createSession("test-session-ID", null);

        configure("org.apache.ace.log.server.store.filebased", "MaxEvents", "0");

        configureFactory("org.apache.ace.log.server.store.factory",
            "name", "auditlog", "authentication.enabled", "false");
    }

    protected final void cleanUp() throws InvalidSyntaxException, InterruptedException {
        // Simply remove all objects in the repository.
        clearRepository(m_artifactRepository);
        clearResourceProcessors(m_artifactRepository);
        clearRepository(m_artifact2featureRepository);
        clearRepository(m_feature2distributionRepository);
        clearRepository(m_distribution2targetRepository);
        clearRepository(m_artifactRepository);
        clearRepository(m_featureRepository);
        clearRepository(m_distributionRepository);
        clearRepository(m_targetRepository);
        clearRepository(m_deploymentVersionRepository);
        m_statefulTargetRepository.refresh();
        try {
            m_repositoryAdmin.logout(true);
        }
        catch (Exception ioe) {
            // ioe.printStackTrace(System.out);
        }
    }

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

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

    protected ArtifactObject createBasicBundleObject(String symbolicName, String version, String processorPID) {
        return createBasicBundleObject(symbolicName, version, processorPID, null);
    }

    protected ArtifactObject createBasicBundleObject(String symbolicName, String version, String processorPID, String size) {
        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));

        if (version != null) {
            attr.put(BundleHelper.KEY_VERSION, version);
        }
        if (processorPID != null) {
            attr.put(BundleHelper.KEY_RESOURCE_PROCESSOR_PID, processorPID);
        }
        if (size != null) {
            attr.put(ArtifactObject.KEY_SIZE, size);
        }

        Map<String, String> tags = new HashMap<String, String>();
        return m_artifactRepository.create(attr, tags);
    }

    protected DistributionObject createBasicDistributionObject(String name) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(DistributionObject.KEY_NAME, name);
        Map<String, String> tags = new HashMap<String, String>();

        return m_distributionRepository.create(attr, tags);
    }

    protected FeatureObject createBasicFeatureObject(String name) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(FeatureObject.KEY_NAME, name);
        Map<String, String> tags = new HashMap<String, String>();

        return m_featureRepository.create(attr, tags);
    }

    protected TargetObject createBasicTargetObject(String id) {
        Map<String, String> attr = new HashMap<String, String>();
        attr.put(TargetObject.KEY_ID, id);
        Map<String, String> tags = new HashMap<String, String>();

        return m_targetRepository.create(attr, tags);
    }

    /**
     * @return a {@link User} with {@link #TEST_USER_NAME} as user name, can be <code>null</code>.
     */
    protected final User createTestUser() {
        return createUser(TEST_USER_NAME);
    }

    /**
     * @param name
     *            the name of the user to create, cannot be <code>null</code>;
     * @return a {@link User} with the given name, or <code>null</code> in case no such user could be created.
     */
    protected final User createUser(String name) {
        UserAdmin useradmin = getService(UserAdmin.class);
        User user = (User) useradmin.createRole(name, Role.USER);
        if (user == null) {
            user = useradmin.getUser("username", name);
        }
        else {
            user.getProperties().put("username", name);
        }
        return user;
    }

    protected 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");
        propsServlet.put("authentication.enabled", "false");
        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);
        }
    }

    protected Component[] getDependencies() {
        return new Component[] {
            createComponent()
                .setImplementation(this)
                .add(createServiceDependency().setService(HttpService.class).setRequired(true))
                .add(createServiceDependency().setService(RepositoryAdmin.class).setRequired(true))
                .add(createServiceDependency().setService(ArtifactRepository.class).setRequired(true))
                .add(createServiceDependency().setService(Artifact2FeatureAssociationRepository.class).setRequired(true))
                .add(createServiceDependency().setService(FeatureRepository.class).setRequired(true))
                .add(createServiceDependency().setService(Feature2DistributionAssociationRepository.class).setRequired(true))
                .add(createServiceDependency().setService(DistributionRepository.class).setRequired(true))
                .add(createServiceDependency().setService(Distribution2TargetAssociationRepository.class).setRequired(true))
                .add(createServiceDependency().setService(TargetRepository.class).setRequired(true))
                .add(createServiceDependency().setService(DeploymentVersionRepository.class).setRequired(true))
                .add(createServiceDependency().setService(StatefulTargetRepository.class).setRequired(true))
                .add(createServiceDependency().setService(LogStore.class, "(&(" + Constants.OBJECTCLASS + "=" + LogStore.class.getName() + ")(name=auditlog))").setRequired(true))
                .add(createServiceDependency().setService(ConfigurationAdmin.class).setRequired(true))
        };
    }

    protected <T> T runAndWaitForEvent(Callable<T> callable, final boolean debug, final String... topicList) throws Exception {
        return runAndWaitForEvent(callable, debug, null, topicList);
    }
   
    protected <T> T runAndWaitForEvent(Callable<T> callable, final boolean debug, final List<Event> events, final String... topicList) throws Exception {
        Dictionary<String, Object> topics = new Hashtable<String, Object>();
        topics.put(EventConstants.EVENT_TOPIC, topicList);

        final CopyOnWriteArrayList<String> waitingForTopic = new CopyOnWriteArrayList<String>(Arrays.asList(topicList));
        final CountDownLatch topicLatch = new CountDownLatch(topicList.length);
        final CountDownLatch startLatch = new CountDownLatch(1);

        Component comp = m_dependencyManager.createComponent()
            .setInterface(EventHandler.class.getName(), topics)
            .setImplementation(new EventHandler() {
                @Override
                public void handleEvent(Event event) {
                    if (debug) {
                        System.err.println("Received event: " + event.getTopic());
                    }
                    if (waitingForTopic.remove(event.getTopic())) {
                        if (events != null) {
                            events.add(event);
                        }
                        if (debug) {
                            System.err.println("Event was expected.");
                        }
                        topicLatch.countDown();
                    }
                }
            });
        comp.addStateListener(new ComponentStateListener() {
            public void stopping(Component comp) {
            }

            public void stopped(Component comp) {
            }

            public void starting(Component comp) {
            }

            public void started(Component comp) {
                startLatch.countDown();
            }
        });

        if (debug) {
            System.err.printf("Waiting for events: %s.%n", Arrays.toString(topicList));
        }

        m_dependencyManager.add(comp);

        try {
            assertTrue(startLatch.await(1500, TimeUnit.MILLISECONDS));

            T result = null;
            // XXX this is dodgy, I know, but currently a workaround for some spurious failing itests...
            int tries = 10;
            while (tries-- > 0) {
                try {
                    result = callable.call();
                    break;
                }
                catch (Exception exception) {
                    if (exception instanceof ConnectException) {
                        // Restart it...
                        if (tries == 0) {
                            throw exception;
                        }
                    }
                    else {
                        // Rethrow it...
                        throw exception;
                    }
                }
            }

            boolean r = topicLatch.await(15000, TimeUnit.MILLISECONDS);
            if (!r && debug) {
                System.err.println("EVENT NOTIFICATION FAILED!!!");
            }
            assertTrue("We expect the event within a reasonable timeout.", r);

            return result;
        }
        finally {
            m_dependencyManager.remove(comp);
        }
    }

    protected void startRepositoryService() throws IOException {
        // configure the (replication)repository servlets
        configure("org.apache.ace.repository.servlet.RepositoryServlet", HttpConstants.ENDPOINT,
            ENDPOINT_NAME, "authentication.enabled", "false");
    }

    @Override
    protected void doTearDown() throws Exception {
        try {
            m_repositoryAdmin.logout(true);
        }
        catch (RuntimeException e) {
            // Ignore...
        }

        try {
            cleanUp();
        }
        catch (Exception e) {
            // Ignore...
        }

        try {
            removeAllRepositories();
        }
        catch (IOException e) {
            // Ignore...
        }
    }

    private <T extends RepositoryObject> void clearRepository(ObjectRepository<T> rep) {
        for (T entity : rep.get()) {
            try {
                rep.remove(entity);
            }
            catch (RuntimeException e) {
                // Ignore; try to recover...
            }
        }
        assertEquals("Something went wrong clearing the repository.", 0, rep.get().size());
    }

    private void clearResourceProcessors(ArtifactRepository rep) {
        for (ArtifactObject entity : rep.getResourceProcessors()) {
            try {
                rep.remove(entity);
            }
            catch (RuntimeException e) {
                // Ignore; try to recover...
            }
        }
        assertEquals("Something went wrong clearing the repository.", 0, rep.get().size());
    }

    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_bundleContext, m_bundleContext.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();
        }
    }
}
TOP

Related Classes of org.apache.ace.it.repositoryadmin.BaseRepositoryAdminTest$MockUser

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.