activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gtu...@apache.org
Subject [3/4] activemq git commit: https://issues.apache.org/jira/browse/AMQ-5876 - refactor properties loading such that it can be reused by cert and props login modules. Both loading on start and refreshing if reload=true and lastMod indicates change
Date Wed, 08 Jul 2015 11:18:44 GMT
https://issues.apache.org/jira/browse/AMQ-5876 - refactor properties loading such that it can
be reused by cert and props login modules. Both loading on start and refreshing if reload=true
and lastMod indicates change


Project: http://git-wip-us.apache.org/repos/asf/activemq/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq/commit/59cd0189
Tree: http://git-wip-us.apache.org/repos/asf/activemq/tree/59cd0189
Diff: http://git-wip-us.apache.org/repos/asf/activemq/diff/59cd0189

Branch: refs/heads/master
Commit: 59cd0189791fa075790ed8c7cc8e4d20637ff548
Parents: 6f457d2
Author: gtully <gary.tully@gmail.com>
Authored: Wed Jul 8 12:06:30 2015 +0100
Committer: gtully <gary.tully@gmail.com>
Committed: Wed Jul 8 12:07:04 2015 +0100

----------------------------------------------------------------------
 .../activemq/jaas/CertificateLoginModule.java   |     10 +-
 .../activemq/jaas/PrincipalProperties.java      |     71 -
 .../apache/activemq/jaas/PropertiesLoader.java  |    135 +
 .../activemq/jaas/PropertiesLoginModule.java    |     81 +-
 .../activemq/jaas/ReloadableProperties.java     |     97 +
 .../jaas/TextFileCertificateLoginModule.java    |     55 +-
 .../PropertiesLoginModuleRaceConditionTest.java |      2 +-
 .../TextFileCertificateLoginModuleTest.java     |    129 +
 .../src/test/resources/cert-groups.properties   |      0
 .../test/resources/cert-users-LARGE.properties  | 200010 ++++++++++++++++
 .../test/resources/cert-users-SMALL.properties  |    100 +
 11 files changed, 200494 insertions(+), 196 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
b/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
index 7f00ed0..4cf3930 100644
--- a/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
+++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/CertificateLoginModule.java
@@ -43,7 +43,7 @@ import org.slf4j.LoggerFactory;
  * 
  * @author sepandm@gmail.com (Sepand)
  */
-public abstract class CertificateLoginModule implements LoginModule {
+public abstract class CertificateLoginModule extends PropertiesLoader implements LoginModule
{
 
     private static final Logger LOG = LoggerFactory.getLogger(CertificateLoginModule.class);
 
@@ -54,7 +54,6 @@ public abstract class CertificateLoginModule implements LoginModule {
     private String username;
     private Set<String> groups;
     private Set<Principal> principals = new HashSet<Principal>();
-    private boolean debug;
 
     /**
      * Overriding to allow for proper initialization. Standard JAAS.
@@ -63,12 +62,7 @@ public abstract class CertificateLoginModule implements LoginModule {
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         this.subject = subject;
         this.callbackHandler = callbackHandler;
-
-        debug = "true".equalsIgnoreCase((String)options.get("debug"));
-
-        if (debug) {
-            LOG.debug("Initialized debug");
-        }
+        init(options);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/PrincipalProperties.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/PrincipalProperties.java
b/activemq-jaas/src/main/java/org/apache/activemq/jaas/PrincipalProperties.java
deleted file mode 100644
index 3ff623c..0000000
--- a/activemq-jaas/src/main/java/org/apache/activemq/jaas/PrincipalProperties.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * 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.activemq.jaas;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.slf4j.Logger;
-
-class PrincipalProperties {
-    private final Properties principals;
-    private final long reloadTime;
-
-    PrincipalProperties(final String type, final File source, final Logger log) {
-        Properties props = new Properties();
-        long reloadTime = 0;
-        try {
-            load(source, props);
-            reloadTime = System.currentTimeMillis();
-        } catch (IOException ioe) {
-            log.warn("Unable to load " + type + " properties file " + source);
-        }
-        this.reloadTime = reloadTime;
-        this.principals = props;
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    Set<Map.Entry<String, String>> entries() {
-        return (Set) principals.entrySet();
-    }
-
-    String getProperty(String name) {
-        return principals.getProperty(name);
-    }
-
-    long getReloadTime() {
-        return reloadTime;
-    }
-
-    private void load(final File source, Properties props) throws FileNotFoundException,
IOException {
-        FileInputStream in = new FileInputStream(source);
-        try {
-            props.load(in);
-        } finally {
-            in.close();
-        }
-    }
-
-    Properties getPrincipals() {
-        return principals;
-    }
-}

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoader.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoader.java b/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoader.java
new file mode 100644
index 0000000..80c65ea
--- /dev/null
+++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoader.java
@@ -0,0 +1,135 @@
+/**
+ * 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.activemq.jaas;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PropertiesLoader {
+    private static final Logger LOG = LoggerFactory.getLogger(PropertiesLoader.class);
+    static Map<FileNameKey, ReloadableProperties> staticCache = new HashMap<FileNameKey,
ReloadableProperties>();
+    protected boolean debug;
+
+    public void init(Map options) {
+        debug = booleanOption("debug", options);
+        if (debug) {
+            LOG.debug("Initialized debug");
+        }
+    }
+
+    public ReloadableProperties load(String nameProperty, String fallbackName, Map options)
{
+        ReloadableProperties result;
+        FileNameKey key = new FileNameKey(nameProperty, fallbackName, options);
+        key.setDebug(debug);
+
+        synchronized (staticCache) {
+            result = staticCache.get(key);
+            if (result == null) {
+                result = new ReloadableProperties(key);
+                staticCache.put(key, result);
+            }
+        }
+
+        return result.obtained();
+    }
+
+    private static boolean booleanOption(String name, Map options) {
+        return Boolean.parseBoolean((String) options.get(name));
+    }
+
+    public class FileNameKey {
+        final File file;
+        final String absPath;
+        final boolean reload;
+        private boolean decrypt;
+        private boolean debug;
+
+        public FileNameKey(String nameProperty, String fallbackName, Map options) {
+            this.file = new File(baseDir(options), stringOption(nameProperty, fallbackName,
options));
+            absPath = file.getAbsolutePath();
+            reload = booleanOption("reload", options);
+            decrypt = booleanOption("decrypt", options);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return other instanceof FileNameKey && this.absPath.equals(((FileNameKey)
other).absPath);
+        }
+
+        public int hashCode() {
+            return this.absPath.hashCode();
+        }
+
+        public boolean isReload() {
+            return reload;
+        }
+
+        public File file() {
+            return file;
+        }
+
+        public boolean isDecrypt() {
+            return decrypt;
+        }
+
+        public void setDecrypt(boolean decrypt) {
+            this.decrypt = decrypt;
+        }
+
+        private String stringOption(String key, String nameDefault, Map options) {
+            Object result = options.get(key);
+            return result != null ? result.toString() : nameDefault;
+        }
+
+        private File baseDir(Map options) {
+            File baseDir = null;
+            if (options.get("baseDir") != null) {
+                baseDir = new File((String) options.get("baseDir"));
+            } else {
+                if (System.getProperty("java.security.auth.login.config") != null) {
+                    baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
+                }
+            }
+            if (debug) {
+                LOG.debug("Using basedir=" + baseDir.getAbsolutePath());
+            }
+            return baseDir;
+        }
+
+        public String toString() {
+            return "PropsFile=" + absPath;
+        }
+
+        public void setDebug(boolean debug) {
+            this.debug = debug;
+        }
+
+        public boolean isDebug() {
+            return debug;
+        }
+    }
+
+    /**
+     * For test-usage only.
+     */
+    public static void resetUsersAndGroupsCache() {
+        staticCache.clear();
+    }
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoginModule.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoginModule.java
b/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoginModule.java
index 2961520..42596d2 100644
--- a/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoginModule.java
+++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/PropertiesLoginModule.java
@@ -16,11 +16,11 @@
  */
 package org.apache.activemq.jaas;
 
-import java.io.File;
 import java.io.IOException;
 import java.security.Principal;
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Properties;
 import java.util.Set;
 
 import javax.security.auth.Subject;
@@ -36,80 +36,30 @@ import javax.security.auth.spi.LoginModule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class PropertiesLoginModule implements LoginModule {
+public class PropertiesLoginModule extends PropertiesLoader implements LoginModule {
 
-    private static final String USER_FILE = "org.apache.activemq.jaas.properties.user";
-    private static final String GROUP_FILE = "org.apache.activemq.jaas.properties.group";
+    private static final String USER_FILE_PROP_NAME = "org.apache.activemq.jaas.properties.user";
+    private static final String GROUP_FILE_PROP_NAME = "org.apache.activemq.jaas.properties.group";
 
     private static final Logger LOG = LoggerFactory.getLogger(PropertiesLoginModule.class);
 
     private Subject subject;
     private CallbackHandler callbackHandler;
 
-    private boolean debug;
-    private boolean reload = false;
-    private static volatile PrincipalProperties users;
-    private static volatile PrincipalProperties groups;
+    private Properties users;
+    private Properties groups;
     private String user;
     private final Set<Principal> principals = new HashSet<Principal>();
-    private File baseDir;
     private boolean loginSucceeded;
-    private boolean decrypt = true;
 
     @Override
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         this.subject = subject;
         this.callbackHandler = callbackHandler;
         loginSucceeded = false;
-
-        debug = "true".equalsIgnoreCase((String) options.get("debug"));
-        if (options.get("reload") != null) {
-            reload = "true".equalsIgnoreCase((String) options.get("reload"));
-        }
-
-        if (options.get("baseDir") != null) {
-            baseDir = new File((String) options.get("baseDir"));
-        }
-
-        setBaseDir();
-        String usersFile = (String) options.get(USER_FILE) + "";
-        File uf = baseDir != null ? new File(baseDir, usersFile) : new File(usersFile);
-
-        if (reload || users == null || uf.lastModified() > users.getReloadTime()) {
-            if (debug) {
-                LOG.debug("Reloading users from " + uf.getAbsolutePath());
-            }
-            users = new PrincipalProperties("user", uf, LOG);
-            if( decrypt ) {
-                try {
-                    EncryptionSupport.decrypt(users.getPrincipals());
-                } catch(NoClassDefFoundError e) {
-                    // this Happens whe jasypt is not on the classpath..
-                    decrypt = false;
-                    LOG.info("jasypt is not on the classpath: password decryption disabled.");
-                }
-            }
-        }
-
-        String groupsFile = (String) options.get(GROUP_FILE) + "";
-        File gf = baseDir != null ? new File(baseDir, groupsFile) : new File(groupsFile);
-        if (reload || groups == null || gf.lastModified() > groups.getReloadTime()) {
-            if (debug) {
-                LOG.debug("Reloading groups from " + gf.getAbsolutePath());
-            }
-            groups = new PrincipalProperties("group", gf, LOG);
-        }
-    }
-
-    private void setBaseDir() {
-        if (baseDir == null) {
-            if (System.getProperty("java.security.auth.login.config") != null) {
-                baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
-                if (debug) {
-                    LOG.debug("Using basedir=" + baseDir.getAbsolutePath());
-                }
-            }
-        }
+        init(options);
+        users = load(USER_FILE_PROP_NAME, "user", options).getProps();
+        groups = load(GROUP_FILE_PROP_NAME, "group", options).getProps();
     }
 
     @Override
@@ -155,9 +105,9 @@ public class PropertiesLoginModule implements LoginModule {
         if (result) {
             principals.add(new UserPrincipal(user));
 
-            for (Map.Entry<String, String> entry : groups.entries()) {
-                String name = entry.getKey();
-                String[] userList = entry.getValue().split(",");
+            for (Map.Entry<Object, Object> entry : groups.entrySet()) {
+                String name = (String) entry.getKey();
+                String[] userList = ((String)entry.getValue()).split(",");
                 for (int i = 0; i < userList.length; i++) {
                     if (user.equals(userList[i])) {
                         principals.add(new GroupPrincipal(name));
@@ -204,11 +154,4 @@ public class PropertiesLoginModule implements LoginModule {
         loginSucceeded = false;
     }
 
-    /**
-     * For test-usage only.
-     */
-    static void resetUsersAndGroupsCache() {
-        users = null;
-        groups = null;
-    }
 }

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/ReloadableProperties.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/ReloadableProperties.java
b/activemq-jaas/src/main/java/org/apache/activemq/jaas/ReloadableProperties.java
new file mode 100644
index 0000000..958a7bd
--- /dev/null
+++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/ReloadableProperties.java
@@ -0,0 +1,97 @@
+/**
+ * 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.activemq.jaas;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReloadableProperties {
+    private static final Logger LOG = LoggerFactory.getLogger(ReloadableProperties.class);
+
+    private Properties props = new Properties();
+    private Map<String, String> invertedProps;
+    private long reloadTime = -1;
+    private final PropertiesLoader.FileNameKey key;
+
+    public ReloadableProperties(PropertiesLoader.FileNameKey key) {
+        this.key = key;
+    }
+
+    public synchronized Properties getProps() {
+        return props;
+    }
+
+    public synchronized ReloadableProperties obtained() {
+        if (reloadTime < 0 || (key.isReload() && hasModificationAfter(reloadTime)))
{
+            props = new Properties();
+            try {
+                load(key.file(), props);
+                invertedProps = null;
+                if (key.isDebug()) {
+                    LOG.debug("Load of: " + key);
+                }
+            } catch (IOException e) {
+                LOG.error("Failed to load: " + key + ", reason:" + e.getLocalizedMessage());
+                if (key.isDebug()) {
+                    LOG.debug("Load of: " + key + ", failure exception" + e);
+                }
+            }
+            reloadTime = System.currentTimeMillis();
+        }
+        return this;
+    }
+
+    public synchronized Map<String, String> invertedPropertiesMap() {
+        if (invertedProps == null) {
+            invertedProps = new HashMap<>(props.size());
+            for (Map.Entry<Object, Object> val : props.entrySet()) {
+                invertedProps.put((String) val.getValue(), (String) val.getKey());
+            }
+        }
+        return invertedProps;
+    }
+
+    private void load(final File source, Properties props) throws IOException {
+        FileInputStream in = new FileInputStream(source);
+        try {
+            props.load(in);
+            if (key.isDecrypt()) {
+                try {
+                    EncryptionSupport.decrypt(this.props);
+                } catch (NoClassDefFoundError e) {
+                    // this Happens whe jasypt is not on the classpath..
+                    key.setDecrypt(false);
+                    LOG.info("jasypt is not on the classpath: password decryption disabled.");
+                }
+            }
+
+        } finally {
+            in.close();
+        }
+    }
+
+    private boolean hasModificationAfter(long reloadTime) {
+        return key.file.lastModified() > reloadTime;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
b/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
index 284eaba..9b887ae 100644
--- a/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
+++ b/activemq-jaas/src/main/java/org/apache/activemq/jaas/TextFileCertificateLoginModule.java
@@ -17,8 +17,6 @@
 
 package org.apache.activemq.jaas;
 
-import java.io.File;
-import java.io.IOException;
 import java.security.cert.X509Certificate;
 import java.util.Enumeration;
 import java.util.HashSet;
@@ -45,12 +43,11 @@ import javax.security.auth.login.LoginException;
  */
 public class TextFileCertificateLoginModule extends CertificateLoginModule {
 
-    private static final String USER_FILE = "org.apache.activemq.jaas.textfiledn.user";
-    private static final String GROUP_FILE = "org.apache.activemq.jaas.textfiledn.group";
+    private static final String USER_FILE_PROP_NAME = "org.apache.activemq.jaas.textfiledn.user";
+    private static final String GROUP_FILE_PROP_NAME = "org.apache.activemq.jaas.textfiledn.group";
 
-    private File baseDir;
-    private String usersFilePathname;
-    private String groupsFilePathname;
+    private Properties groups;
+    private Map<String, String> usersByDn;
 
     /**
      * Performs initialization of file paths. A standard JAAS override.
@@ -58,15 +55,10 @@ public class TextFileCertificateLoginModule extends CertificateLoginModule
{
     @Override
     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState,
Map options) {
         super.initialize(subject, callbackHandler, sharedState, options);
-        if (System.getProperty("java.security.auth.login.config") != null) {
-            baseDir = new File(System.getProperty("java.security.auth.login.config")).getParentFile();
-        } else {
-            baseDir = new File(".");
-        }
 
-        usersFilePathname = (String)options.get(USER_FILE) + "";
-        groupsFilePathname = (String)options.get(GROUP_FILE) + "";
-    }
+        usersByDn = load(USER_FILE_PROP_NAME, "", options).invertedPropertiesMap();
+        groups = load(GROUP_FILE_PROP_NAME, "", options).getProps();
+     }
 
     /**
      * Overriding to allow DN authorization based on DNs specified in text
@@ -84,28 +76,7 @@ public class TextFileCertificateLoginModule extends CertificateLoginModule
{
             throw new LoginException("Client certificates not found. Cannot authenticate.");
         }
 
-        File usersFile = new File(baseDir, usersFilePathname);
-
-        Properties users = new Properties();
-
-        try(java.io.FileInputStream in = new java.io.FileInputStream(usersFile)) {
-            users.load(in);
-        } catch (IOException ioe) {
-            throw new LoginException("Unable to load user properties file " + usersFile);
-        }
-
-        String dn = getDistinguishedName(certs);
-
-        Enumeration<Object> keys = users.keys();
-        for (Enumeration<Object> vals = users.elements(); vals.hasMoreElements();)
{
-            if (((String)vals.nextElement()).equals(dn)) {
-                return (String)keys.nextElement();
-            } else {
-                keys.nextElement();
-            }
-        }
-
-        return null;
+        return usersByDn.get(getDistinguishedName(certs));
     }
 
     /**
@@ -118,16 +89,6 @@ public class TextFileCertificateLoginModule extends CertificateLoginModule
{
      */
     @Override
     protected Set<String> getUserGroups(String username) throws LoginException {
-        File groupsFile = new File(baseDir, groupsFilePathname);
-
-        Properties groups = new Properties();
-        try {
-            java.io.FileInputStream in = new java.io.FileInputStream(groupsFile);
-            groups.load(in);
-            in.close();
-        } catch (IOException ioe) {
-            throw new LoginException("Unable to load group properties file " + groupsFile);
-        }
         Set<String> userGroups = new HashSet<String>();
         for (Enumeration<Object> enumeration = groups.keys(); enumeration.hasMoreElements();)
{
             String groupName = (String)enumeration.nextElement();

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-jaas/src/test/java/org/apache/activemq/jaas/PropertiesLoginModuleRaceConditionTest.java
----------------------------------------------------------------------
diff --git a/activemq-jaas/src/test/java/org/apache/activemq/jaas/PropertiesLoginModuleRaceConditionTest.java
b/activemq-jaas/src/test/java/org/apache/activemq/jaas/PropertiesLoginModuleRaceConditionTest.java
index 5e38671..b401bd8 100644
--- a/activemq-jaas/src/test/java/org/apache/activemq/jaas/PropertiesLoginModuleRaceConditionTest.java
+++ b/activemq-jaas/src/test/java/org/apache/activemq/jaas/PropertiesLoginModuleRaceConditionTest.java
@@ -121,7 +121,7 @@ public class PropertiesLoginModuleRaceConditionTest {
     public void after() throws InterruptedException {
         pool.shutdown();
         assertTrue(pool.awaitTermination(500, TimeUnit.SECONDS));
-        PropertiesLoginModule.resetUsersAndGroupsCache();
+        PropertiesLoader.resetUsersAndGroupsCache();
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-unit-tests/src/test/java/org/apache/activemq/security/TextFileCertificateLoginModuleTest.java
----------------------------------------------------------------------
diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/security/TextFileCertificateLoginModuleTest.java
b/activemq-unit-tests/src/test/java/org/apache/activemq/security/TextFileCertificateLoginModuleTest.java
new file mode 100644
index 0000000..76681c6
--- /dev/null
+++ b/activemq-unit-tests/src/test/java/org/apache/activemq/security/TextFileCertificateLoginModuleTest.java
@@ -0,0 +1,129 @@
+/**
+ * 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.activemq.security;
+
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import org.apache.activemq.jaas.CertificateLoginModule;
+import org.apache.activemq.jaas.JaasCertificateCallbackHandler;
+import org.apache.activemq.jaas.PropertiesLoader;
+import org.apache.activemq.jaas.TextFileCertificateLoginModule;
+import org.apache.activemq.transport.tcp.StubX509Certificate;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TextFileCertificateLoginModuleTest {
+
+    private static final String CERT_USERS_FILE_SMALL = "cert-users-SMALL.properties";
+    private static final String CERT_USERS_FILE_LARGE = "cert-users-LARGE.properties";
+    private static final String CERT_GROUPS_FILE = "cert-groups.properties";
+
+    private static final Logger LOG = LoggerFactory.getLogger(TextFileCertificateLoginModuleTest.class);
+    private static final int NUMBER_SUBJECTS = 10;
+
+    static {
+        String path = System.getProperty("java.security.auth.login.config");
+        if (path == null) {
+            URL resource = TextFileCertificateLoginModuleTest.class.getClassLoader().getResource("login.config");
+            if (resource != null) {
+                path = resource.getFile();
+                System.setProperty("java.security.auth.login.config", path);
+            }
+        }
+    }
+
+    private CertificateLoginModule loginModule;
+
+    @Before
+    public void setUp() throws Exception {
+        loginModule = new TextFileCertificateLoginModule();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        PropertiesLoader.resetUsersAndGroupsCache();
+    }
+
+    @Test
+    public void testLoginWithSMALLUsersFile() throws Exception {
+        loginTest(CERT_USERS_FILE_SMALL, CERT_GROUPS_FILE);
+    }
+
+    @Test
+    public void testLoginWithLARGEUsersFile() throws Exception {
+        loginTest(CERT_USERS_FILE_LARGE, CERT_GROUPS_FILE);
+    }
+
+    private void loginTest(String usersFiles, String groupsFile) throws LoginException {
+
+        HashMap options = new HashMap<String, String>();
+        options.put("org.apache.activemq.jaas.textfiledn.user", usersFiles);
+        options.put("org.apache.activemq.jaas.textfiledn.group", groupsFile);
+        options.put("reload", "true");
+
+        JaasCertificateCallbackHandler[] callbackHandlers = new JaasCertificateCallbackHandler[NUMBER_SUBJECTS];
+        Subject[] subjects = new Subject[NUMBER_SUBJECTS];
+
+        for (int i = 0; i < callbackHandlers.length; i++) {
+            callbackHandlers[i] = getJaasCertificateCallbackHandler("DN=TEST_USER_" + (i
+ 1));
+        }
+
+        long startTime = System.currentTimeMillis();
+
+        for (int outer=0; outer<500;outer++) {
+            for (int i = 0; i < NUMBER_SUBJECTS; i++) {
+                Subject subject = doAuthenticate(options, callbackHandlers[i]);
+                subjects[i] = subject;
+            }
+        }
+
+        long endTime = System.currentTimeMillis();
+        long timeTaken = endTime - startTime;
+
+
+        for (int i = 0; i < NUMBER_SUBJECTS; i++) {
+            LOG.info("subject is: " + subjects[i].getPrincipals().toString());
+        }
+
+        LOG.info(usersFiles + ": Time taken is " + timeTaken);
+
+    }
+
+    private JaasCertificateCallbackHandler getJaasCertificateCallbackHandler(String user)
{
+        JMXPrincipal principal = new JMXPrincipal(user);
+        X509Certificate cert = new StubX509Certificate(principal);
+        return new JaasCertificateCallbackHandler(new X509Certificate[]{cert});
+    }
+
+    private Subject doAuthenticate(HashMap options, JaasCertificateCallbackHandler callbackHandler)
throws LoginException {
+        Subject mySubject = new Subject();
+        loginModule.initialize(mySubject, callbackHandler, null, options);
+        loginModule.login();
+        loginModule.commit();
+        return mySubject;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq/blob/59cd0189/activemq-unit-tests/src/test/resources/cert-groups.properties
----------------------------------------------------------------------
diff --git a/activemq-unit-tests/src/test/resources/cert-groups.properties b/activemq-unit-tests/src/test/resources/cert-groups.properties
new file mode 100644
index 0000000..e69de29


Mime
View raw message