test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java
changeset 48852 478e198da84b
child 57345 ff884a2f247b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java	Tue Feb 13 12:26:22 2018 +0800
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.jndi.ldap.LdapURL;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchResult;
+import java.io.FileNotFoundException;
+import java.io.PrintStream;
+import java.net.ServerSocket;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+public class LDAPTestUtils {
+    public static final String TEST_LDAP_SERVER_THREAD = "test.ldap.server.thread";
+    public static final int CERTS_LOOKUP_MAX_DEPTH = 4;
+
+    protected static boolean debug = true;
+
+    /*
+     * Process command line arguments and return properties in a Hashtable.
+     */
+    public static Hashtable<Object, Object> initEnv(String testname,
+            String[] args) {
+        return initEnv(null, testname, args, false);
+    }
+
+    public static Hashtable<Object, Object> initEnv(ServerSocket socket,
+            String testname, String[] args, boolean authInfo) {
+
+        Hashtable<Object, Object> env = new Hashtable<>();
+        String root = "o=IMC,c=US";
+        String vendor = "Vendor1";
+        String client = "Client1";
+        String realm = "";
+        Vector<String> refs = new Vector<>();
+
+        // set defaults for some JNDI properties
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+                "com.sun.jndi.ldap.LdapCtxFactory");
+
+        if (authInfo) {
+            env.put(Context.SECURITY_AUTHENTICATION, "simple");
+            env.put(Context.SECURITY_PRINCIPAL, "cn=admin,o=IMC,c=US");
+            env.put(Context.SECURITY_CREDENTIALS, "secret99");
+        }
+
+        env.put("root", root);
+        env.put("vendor", vendor);
+        env.put("client", client);
+
+        boolean traceEnable = false;
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-D") && (args.length > i + 1)) {
+                extractProperty(args[++i], env);
+            } else if (args[i].startsWith("-D")) {
+                extractProperty(args[i].substring(2), env);
+            } else if (args[i].equals("-referral") && (args.length > i + 1)) {
+                refs.addElement(args[++i]);
+            } else if (args[i].equals("-trace")) {
+                traceEnable = true;
+            }
+        }
+
+        env.put("disabled.realm", realm);
+
+        if (refs.size() > 0) {
+            env.put("referrals", refs);
+        }
+
+        if (traceEnable) {
+            enableLDAPTrace(env, testname);
+        } else {
+            if (socket != null) {
+                env.put(TEST_LDAP_SERVER_THREAD,
+                        startLDAPServer(socket, getCaptureFile(testname)));
+                env.put("java.naming.provider.url",
+                        "ldap://localhost:" + socket.getLocalPort());
+            } else {
+                // for tests which run against remote server or no server
+                // required
+                debug("Skip local LDAP Server creation "
+                        + "since ServerSocket is null");
+            }
+        }
+
+        return env;
+    }
+
+    /*
+     * Clean-up the directory context.
+     */
+    public static void cleanup(DirContext ctx) {
+        if (ctx != null) {
+            try {
+                ctx.close();
+            } catch (NamingException e) {
+                // ignore
+            }
+        }
+    }
+
+    /*
+     * Clean-up the sub context.
+     */
+    public static void cleanupSubcontext(DirContext ctx, String name) {
+        if (ctx != null) {
+            try {
+                ctx.destroySubcontext(name);
+            } catch (NamingException ne) {
+                // ignore
+            }
+        }
+    }
+
+    /*
+     * Assemble a distinguished name from the base components and the
+     * namespace root.
+     *
+     * The components are prefixed with 'dc=' if the root is a DC-style name.
+     * Otherwise they are prefixed with 'ou='.
+     */
+    public static String buildDN(String[] bases, String root) {
+
+        StringBuilder dn = new StringBuilder();
+        String prefix;
+
+        if (!root.contains("dc=")) {
+            prefix = "ou=";
+        } else {
+            prefix = "dc=";
+        }
+
+        for (String base : bases) {
+            dn.append(prefix).append(base).append(",");
+        }
+
+        return dn.append(root).toString();
+    }
+
+    /*
+     * Scan the results to confirm that the expected name is present.
+     */
+    public static int checkResult(NamingEnumeration results, String name)
+            throws NamingException {
+
+        return checkResult(results, new String[] { name }, null);
+    }
+
+    /*
+     * Scan the results to confirm that the expected names and attributes
+     * are present.
+     */
+    public static int checkResult(NamingEnumeration results, String[] names,
+            Attributes attrs) throws NamingException {
+
+        int found = 0;
+
+        while (results != null && results.hasMore()) {
+
+            SearchResult entry = (SearchResult) results.next();
+            String entryDN = entry.getName();
+
+            debug(">>> received: " + entryDN);
+
+            if (entry.isRelative()) {
+                entryDN = entryDN.toLowerCase(); // normalize
+            } else {
+                LdapURL url = new LdapURL(entryDN); // extract DN
+                entryDN = url.getDN().toLowerCase(); // normalize
+            }
+
+            for (String name : names) {
+                if ((entryDN.contains(name.toLowerCase())) || (entryDN
+                        .equalsIgnoreCase(name))) {
+
+                    debug(">>> checked results: found '" + name + "'");
+
+                    if (attrs == null || foundAttributes(entry, attrs)) {
+                        found++;
+                        break;
+                    }
+                }
+            }
+        }
+
+        debug(">>> checked results: found " + found
+                + " entries that meet the criteria.");
+
+        return found;
+    }
+
+    /*
+     * Confirm that the attributes are present in the entry.
+     */
+    public static boolean foundAttributes(SearchResult entry, Attributes attrs)
+            throws NamingException {
+
+        Attributes eattrs = entry.getAttributes();
+        int found = 0;
+
+        if ((eattrs == null) || (attrs == null)) {
+            return false;
+        }
+
+        for (NamingEnumeration ne = attrs.getAll(); ne.hasMoreElements(); ) {
+
+            Attribute attr = (Attribute) ne.next();
+
+            if (equalsIgnoreCase(eattrs.get(attr.getID()), attr)) {
+                found++;
+            } else {
+                debug(">>> foundAttributes: no match for " + attr.getID());
+            }
+        }
+        debug(">>> foundAttributes: found " + found + " attributes");
+        return (found == attrs.size());
+    }
+
+    public static Thread startLDAPServer(ServerSocket serverSocket,
+            String fileName) {
+        if (serverSocket == null) {
+            throw new RuntimeException("Error: failed to create LDAPServer "
+                    + "since ServerSocket is null");
+        }
+
+        if (!Files.exists(Paths.get(fileName))) {
+            throw new RuntimeException(
+                    "Error: failed to create LDAPServer, not found ldap "
+                            + "cache file " + fileName);
+        }
+
+        Thread thread = new Thread(() -> {
+            try {
+                new test.LDAPServer(serverSocket, fileName);
+            } catch (Exception e) {
+                System.out.println("Warning: LDAP server running with issue");
+                e.printStackTrace();
+            }
+        });
+
+        thread.start();
+        return thread;
+    }
+
+    private static boolean equalsIgnoreCase(Attribute received,
+            Attribute expected) {
+
+        if (received == null || !received.getID()
+                .equalsIgnoreCase(expected.getID())) {
+            return false;
+        }
+
+        try {
+
+            Enumeration expectedVals = expected.getAll();
+            Object obj;
+            while (expectedVals.hasMoreElements()) {
+                obj = expectedVals.nextElement();
+                if (!received.contains(obj)) {
+                    if (!(obj instanceof String)) {
+                        return false;
+                    }
+                    if (!received.contains(((String) obj).toLowerCase())) {
+                        return false;
+                    }
+                }
+            }
+
+        } catch (NamingException e) {
+            return false;
+        }
+
+        return true;
+    }
+
+    private static void extractProperty(String propString,
+            Hashtable<Object, Object> env) {
+        int index;
+
+        if ((index = propString.indexOf('=')) > 0) {
+            env.put(propString.substring(0, index),
+                    propString.substring(index + 1));
+        } else {
+            throw new RuntimeException(
+                    "Failed to extract test args property from " + propString);
+        }
+    }
+
+    private static void enableLDAPTrace(Hashtable<Object, Object> env,
+            String testname) {
+        try {
+            PrintStream outStream = new PrintStream(getCaptureFile(testname));
+            env.put("com.sun.jndi.ldap.trace.ber", outStream);
+        } catch (FileNotFoundException e) {
+            throw new RuntimeException(
+                    "Error: failed to enable ldap trace: " + e.getMessage(), e);
+        }
+    }
+
+    private static String getCaptureFile(String testname) {
+        return Paths.get(System.getProperty("test.src"))
+                .resolve(testname + ".ldap").toString();
+    }
+
+    public static void debug(Object object) {
+        if (debug) {
+            System.out.println(object);
+        }
+    }
+
+    public static String findCertsHome(int depth) {
+        Path path = Paths.get(System.getProperty("test.src", "."))
+                .toAbsolutePath();
+        for (int i = depth; i >= 0; i--) {
+            Path homePath = path.resolve("certs");
+            if (Files.exists(homePath) && Files.isDirectory(homePath)) {
+                return homePath.toString();
+            }
+
+            path = path.getParent();
+            if (path == null) {
+                break;
+            }
+        }
+
+        return System.getProperty("test.src", ".");
+    }
+}