com.springsource.insight.plugin.ldap.LdapOperationCollectionAspectTestSupport.java Source code

Java tutorial

Introduction

Here is the source code for com.springsource.insight.plugin.ldap.LdapOperationCollectionAspectTestSupport.java

Source

/**
 * Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved.
 *
 * Licensed 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 com.springsource.insight.plugin.ldap;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.naming.Context;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.directory.server.core.DefaultDirectoryService;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.springframework.security.ldap.server.ApacheDSContainer;
import org.springframework.util.FileSystemUtils;

import com.springsource.insight.collection.test.OperationCollectionAspectTestSupport;
import com.springsource.insight.intercept.application.ApplicationName;
import com.springsource.insight.intercept.operation.Operation;
import com.springsource.insight.intercept.operation.OperationFields;
import com.springsource.insight.intercept.server.ServerName;
import com.springsource.insight.intercept.topology.ExternalResourceDescriptor;
import com.springsource.insight.intercept.topology.ExternalResourceType;
import com.springsource.insight.intercept.topology.MD5NameGenerator;
import com.springsource.insight.intercept.trace.Frame;
import com.springsource.insight.intercept.trace.FrameId;
import com.springsource.insight.intercept.trace.SimpleFrame;
import com.springsource.insight.intercept.trace.Trace;
import com.springsource.insight.intercept.trace.TraceId;
import com.springsource.insight.util.ClassUtil;
import com.springsource.insight.util.FileUtil;
import com.springsource.insight.util.StringUtil;
import com.springsource.insight.util.time.TimeRange;

/**
 * A spring equivalent to <code>OperationCollectionAspectTestSupport</code>
 */
public abstract class LdapOperationCollectionAspectTestSupport extends OperationCollectionAspectTestSupport {
    private static final Log LOG = LogFactory.getLog(LdapOperationCollectionAspectTestSupport.class);
    // Use non-default port to avoid conflicts if built on servers that have a running sever
    protected static final int TEST_PORT = 53899;
    // NOTE: the DN(s) should match the one in the LDIF file
    protected static final String ROOT_DN = "dc=springframework,dc=org",
            LDAP_URL = "ldap://localhost:" + TEST_PORT + "/" + ROOT_DN;
    // NOTE: these are the defaults - haven't figured out how to override them...
    protected static final String LDAP_USERNAME = "uid=admin,ou=system", LDAP_PASSWORD = "secret";
    // NOTE: taken from a Spring security sample code
    protected static final String LDIF_LOCATION = "META-INF/testUsers.ldif",
            LDIF_RESUOURCE = "classpath:" + LDIF_LOCATION;
    protected static Collection<Map<String, Set<String>>> LDIF_ENTRIES;
    private static ApacheDSContainer dsContainer;

    protected final Log logger = LogFactory.getLog(getClass());
    protected static final LdapExternalResourceAnalyzer analyzer = LdapExternalResourceAnalyzer.getInstance();

    protected LdapOperationCollectionAspectTestSupport() {
        super();
    }

    @BeforeClass
    public static final void startLdapServer() throws Exception {
        File apacheWorkDir = resolveApacheWorkDir(LdapOperationCollectionAspectTestSupport.class);
        // see ApacheDSContainer#afterPropertiesSet() as to why this is necessary
        if (FileSystemUtils.deleteRecursively(apacheWorkDir)) {
            System.out.println("Deleted " + apacheWorkDir.getAbsolutePath());
        }

        dsContainer = new ApacheDSContainer(ROOT_DN, LDIF_RESUOURCE);
        dsContainer.setPort(TEST_PORT);
        dsContainer.setWorkingDirectory(apacheWorkDir);

        DefaultDirectoryService dsService = dsContainer.getService();
        dsService.setShutdownHookEnabled(true);

        LOG.info("Starting LDAP server on port " + TEST_PORT);
        dsContainer.afterPropertiesSet();
        LOG.info("LDAP server started");

        LDIF_ENTRIES = readLdifEntries(LDIF_LOCATION);
        LOG.info("Read " + LDIF_ENTRIES.size() + " LDIF entries from " + LDIF_LOCATION);
    }

    @AfterClass
    public static final void stopLdapServer() throws Exception {
        if (dsContainer == null) {
            LOG.warn("No current LDAP server instance running...");
            return;
        }

        LOG.info("Stopping LDAP server ...");
        dsContainer.destroy();
        LOG.info("LDAP server stopped...");
    }

    protected Operation assertContextOperation(String testName, String lookupName, Map<?, ?> environment) {
        Operation op = getLastEntered();
        assertNotNull(testName + ": No operation generated", op);
        assertEquals(testName + ": Mismatched operation type", LdapDefinitions.LDAP_OP, op.getType());
        assertEquals(testName + ": Mismatched lookup name", lookupName,
                op.get(LdapDefinitions.LOOKUP_NAME_ATTR, String.class));

        LdapOperationCollectionAspectSupport aspectInstance = (LdapOperationCollectionAspectSupport) getAspect();
        assertEquals(testName + ": Mismatched action", aspectInstance.action,
                op.get(OperationFields.METHOD_NAME, String.class));

        Class<?> contextClass = aspectInstance.contextClass;
        assertEquals(testName + ": Mismatched short class name", contextClass.getSimpleName(),
                op.get(OperationFields.SHORT_CLASS_NAME, String.class));
        assertEquals(testName + ": Mismatched full class name", contextClass.getName(),
                op.get(OperationFields.CLASS_NAME, String.class));
        return op;
    }

    protected static final Collection<ExternalResourceDescriptor> assertExternalResourceAnalysis(String testName,
            Operation op, String ldapUrl) throws URISyntaxException {
        Frame frame = new SimpleFrame(FrameId.valueOf("0"), null, op, TimeRange.FULL_RANGE,
                Collections.<Frame>emptyList());
        Trace trace = new Trace(ServerName.valueOf("fake-server"), ApplicationName.valueOf("fake-app"),
                new Date(System.currentTimeMillis()), TraceId.valueOf("0"), frame);
        Collection<ExternalResourceDescriptor> result = analyzer.locateExternalResourceName(trace);
        assertNotNull(testName + ": No external resources recovered", result);
        assertEquals(testName + ": Mismatched number of results", 1, result.size());

        ExternalResourceDescriptor desc = result.iterator().next();
        assertSame(testName + ": Mismatched result frame", frame, desc.getFrame());
        assertEquals(testName + ": Mismathed name", MD5NameGenerator.getName(ldapUrl), desc.getName());
        assertEquals(testName + ": Mismatched vendor", ldapUrl, desc.getVendor());
        assertEquals(testName + ": Mismatched label", ldapUrl, desc.getLabel());
        assertEquals(testName + ": Mismatched type", ExternalResourceType.LDAP.name(), desc.getType());

        URI uri = new URI(ldapUrl);
        assertEquals(testName + ": Mismatched host", uri.getHost(), desc.getHost());
        assertEquals(testName + ": Mismatched port", LdapExternalResourceAnalyzer.resolvePort(uri), desc.getPort());
        return result;
    }

    private static File resolveApacheWorkDir(Class<?> anchorClass) {
        // see ApacheDSContainer#afterPropertiesSet
        String apacheWorkDir = System.getProperty("apacheDSWorkDir");
        if (apacheWorkDir != null) {
            LOG.info(
                    "resolveApacheWorkDir(" + anchorClass.getSimpleName() + ") using pre-defined " + apacheWorkDir);
            return new File(apacheWorkDir);
        }

        File targetDir = FileUtil.detectTargetFolder(anchorClass);
        if (targetDir == null) {
            throw new IllegalStateException("No target folder for " + anchorClass.getSimpleName());
        }

        targetDir = new File(targetDir, "apacheDSWorkDir");
        LOG.info("resolveApacheWorkDir(" + anchorClass.getSimpleName() + ") location: " + targetDir);
        return targetDir;
    }

    private static Collection<Map<String, Set<String>>> readLdifEntries(String location) throws IOException {
        ClassLoader cl = ClassUtil.getDefaultClassLoader();
        InputStream in = cl.getResourceAsStream(location);
        assertNotNull("No LDIF input at " + location, in);

        BufferedReader rdr = new BufferedReader(new InputStreamReader(in));
        try {
            return readLdifEntries(rdr);
        } finally {
            rdr.close();
        }
    }

    private static Collection<Map<String, Set<String>>> readLdifEntries(BufferedReader rdr) throws IOException {
        Collection<Map<String, Set<String>>> result = new LinkedList<Map<String, Set<String>>>();
        Map<String, Set<String>> curEntry = null;
        for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
            line = line.trim();
            if (LOG.isTraceEnabled()) {
                LOG.trace("readLdifEntries - " + line);
            }

            // empty line signals end of entry
            if (StringUtil.isEmpty(line)) {
                if (curEntry != null) {
                    result.add(curEntry);
                }

                curEntry = null;
                continue;
            }

            if (curEntry == null) {
                curEntry = new TreeMap<String, Set<String>>(String.CASE_INSENSITIVE_ORDER);
            }

            int namePos = line.indexOf(':');
            String name = line.substring(0, namePos), value = line.substring(namePos + 2).trim();
            if (StringUtil.isEmpty(name) || StringUtil.isEmpty(value)) {
                throw new IllegalArgumentException("Bad line: " + line);
            }

            if ("dn".equalsIgnoreCase(name)) {
                assertTrue("DN(" + value + ") not subset of root (" + ROOT_DN + ")",
                        value.toLowerCase().endsWith(ROOT_DN.toLowerCase()));
            }

            Set<String> values = curEntry.get(name);
            if (values == null) {
                values = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
                curEntry.put(name, values);
            }

            if (!values.add(value)) {
                throw new IllegalStateException("Duplicate values for name=" + name + " at line " + line);
            }
        }

        return result;
    }

    protected static final Hashtable<String, Object> createEnvironment() {
        Hashtable<String, Object> env = new Hashtable<String, Object>();
        env.put(Context.PROVIDER_URL, LDAP_URL);
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.SECURITY_PRINCIPAL, LDAP_USERNAME);
        env.put(Context.SECURITY_CREDENTIALS, LDAP_PASSWORD);
        return env;
    }
}