shiro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lhazlew...@apache.org
Subject svn commit: r888528 - in /incubator/shiro/trunk/core/src: main/java/org/apache/shiro/config/ main/java/org/apache/shiro/realm/ main/java/org/apache/shiro/realm/text/ test/java/org/apache/shiro/realm/text/ test/resources/org/ test/resources/org/apache/ ...
Date Tue, 08 Dec 2009 19:20:44 GMT
Author: lhazlewood
Date: Tue Dec  8 19:20:43 2009
New Revision: 888528

URL: http://svn.apache.org/viewvc?rev=888528&view=rev
Log:
SHIRO-49 - Changed SimpleAccountRealm to use internal memory Maps instead of caching - however,
auto-reloading of the .properties file source has been temporarily disabled. 
SHIRO-118 -Created IniRealm with accompanying unit tests at 100% code coverage.  Changed parent
TextConfigurationRealm to support map-based configuration.

Added:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/IniRealmTest.java
    incubator/shiro/trunk/core/src/test/resources/org/
    incubator/shiro/trunk/core/src/test/resources/org/apache/
    incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/
    incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/
    incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/
    incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.noUsers.ini
    incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.simple.ini
Modified:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/SimpleAccountRealm.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java Tue Dec  8 19:20:43
2009
@@ -27,9 +27,15 @@
 import java.util.*;
 
 /**
+ * A class representing the <a href="http://en.wikipedia.org/wiki/INI_file">INI</a>
text configuration format.
+ * <p/>
+ * An Ini instance is a map of {@link Ini.Section Section}s, keyed by section name.  Each
+ * {@code Section} is itself a map of {@code String} name/value pairs.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
  * @since 1.0
  */
-public class Ini {
+public class Ini implements Map<String, Ini.Section> {
 
     private static transient final Logger log = LoggerFactory.getLogger(Ini.class);
 
@@ -133,6 +139,15 @@
         return value != null ? value : defaultValue;
     }
 
+    public static Ini fromResourcePath(String resourcePath) throws ConfigurationException
{
+        if (!StringUtils.hasLength(resourcePath)) {
+            throw new IllegalArgumentException("Resource Path argument cannot be null or
empty.");
+        }
+        Ini ini = new Ini();
+        ini.loadFromPath(resourcePath);
+        return ini;
+    }
+
     public void loadFromPath(String resourcePath) throws ConfigurationException {
         InputStream is;
         try {
@@ -271,6 +286,50 @@
         return this.sections.hashCode();
     }
 
+    public int size() {
+        return this.sections.size();
+    }
+
+    public boolean containsKey(Object key) {
+        return this.sections.containsKey(key);
+    }
+
+    public boolean containsValue(Object value) {
+        return this.sections.containsValue(value);
+    }
+
+    public Section get(Object key) {
+        return this.sections.get(key);
+    }
+
+    public Section put(String key, Section value) {
+        return this.sections.put(key, value);
+    }
+
+    public Section remove(Object key) {
+        return this.sections.remove(key);
+    }
+
+    public void putAll(Map<? extends String, ? extends Section> m) {
+        this.sections.putAll(m);
+    }
+
+    public void clear() {
+        this.sections.clear();
+    }
+
+    public Set<String> keySet() {
+        return Collections.unmodifiableSet(this.sections.keySet());
+    }
+
+    public Collection<Section> values() {
+        return Collections.unmodifiableCollection(this.sections.values());
+    }
+
+    public Set<Entry<String, Section>> entrySet() {
+        return Collections.unmodifiableSet(this.sections.entrySet());
+    }
+
     public class Section implements Map<String, String> {
         private final String name;
         private final Map<String, String> props;

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
Tue Dec  8 19:20:43 2009
@@ -19,6 +19,7 @@
 package org.apache.shiro.config;
 
 import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.util.CollectionUtils;
 import org.apache.shiro.util.Factory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -53,10 +54,6 @@
         this.ini = ini;
     }
 
-    protected static boolean isEmpty(Ini ini) {
-        return ini == null || ini.isEmpty();
-    }
-
     /**
      * Returns a new Ini instance created from the default {@code classpath:shiro.ini} file,
or {@code null} if
      * the file does not exist.
@@ -70,7 +67,7 @@
             log.debug("Found shiro.ini at the root of the classpath.");
             ini = new Ini();
             ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
-            if (isEmpty(ini)) {
+            if (CollectionUtils.isEmpty(ini)) {
                 log.warn("shiro.ini found at the root of the classpath, but it did not contain
any data.");
             }
         }
@@ -90,7 +87,7 @@
      */
     protected Ini resolveIni() {
         Ini ini = getIni();
-        if (isEmpty(ini)) {
+        if (CollectionUtils.isEmpty(ini)) {
             log.debug("Null or empty Ini instance.  Falling back to the default {} file.",
DEFAULT_INI_RESOURCE_PATH);
             ini = loadDefaultClassPathIni();
         }
@@ -112,7 +109,7 @@
 
         T instance;
 
-        if (!isEmpty(ini)) {
+        if (!CollectionUtils.isEmpty(ini)) {
             log.debug("Creating instance from Ini [" + ini + "]");
             instance = createInstance(ini);
             if (instance == null) {

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
Tue Dec  8 19:20:43 2009
@@ -56,10 +56,10 @@
     }
 
     protected SecurityManager createInstance(Ini ini) {
-        if (isEmpty(ini)) {
+        if (CollectionUtils.isEmpty(ini)) {
             throw new NullPointerException("Ini argument cannot be null or empty.");
         }
-        SecurityManager securityManager = doCreateSecurityManager(ini);
+        SecurityManager securityManager = createSecurityManager(ini);
         if (securityManager == null) {
             String msg = SecurityManager.class + " instance cannot be null.";
             throw new ConfigurationException(msg);
@@ -71,7 +71,7 @@
         return new DefaultSecurityManager();
     }
 
-    protected SecurityManager doCreateSecurityManager(Ini ini) {
+    protected SecurityManager createSecurityManager(Ini ini) {
         Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME);
         if (CollectionUtils.isEmpty(mainSection)) {
             //try the default:
@@ -85,13 +85,13 @@
             }
             securityManager = createDefaultInstance();
         } else {
-            securityManager = createSecurityManager(mainSection);
+            securityManager = doCreateSecurityManager(mainSection);
         }
         return securityManager;
     }
 
     @SuppressWarnings({"unchecked"})
-    protected SecurityManager createSecurityManager(Ini.Section mainSection) {
+    protected SecurityManager doCreateSecurityManager(Ini.Section mainSection) {
 
         Map<String, Object> defaults = new LinkedHashMap<String, Object>();
 

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/AuthorizingRealm.java
Tue Dec  8 19:20:43 2009
@@ -31,6 +31,7 @@
 import org.slf4j.LoggerFactory;
 
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 
 
 /**
@@ -68,7 +69,7 @@
      */
     private static final String DEFAULT_AUTHORIZATION_CACHE_SUFFIX = "-authorization";
 
-    private static int INSTANCE_COUNT = 0;
+    private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
 
     /*--------------------------------------------
     |    I N S T A N C E   V A R I A B L E S    |
@@ -154,6 +155,10 @@
      */
     public final void init() {
         initAuthorizationCache();
+        onInit();
+    }
+
+    protected void onInit() {
     }
 
     protected void afterCacheManagerSet() {
@@ -164,6 +169,11 @@
     protected void afterAuthorizationCacheSet() {
     }
 
+    protected final String generateAuthorizationCacheName() {
+        //Simple default in case they didn't provide one:
+        return getClass().getName() + "-" + INSTANCE_COUNT.getAndIncrement() + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
+    }
+
     public void initAuthorizationCache() {
         if (log.isTraceEnabled()) {
             log.trace("Initializing authorization cache.");
@@ -183,7 +193,7 @@
                 String cacheName = getAuthorizationCacheName();
                 if (cacheName == null) {
                     //Simple default in case they didn't provide one:
-                    cacheName = getClass().getName() + "-" + INSTANCE_COUNT++ + DEFAULT_AUTHORIZATION_CACHE_SUFFIX;
+                    cacheName = generateAuthorizationCacheName();
                     setAuthorizationCacheName(cacheName);
                 }
                 if (log.isDebugEnabled()) {

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/SimpleAccountRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/SimpleAccountRealm.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/SimpleAccountRealm.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/SimpleAccountRealm.java
Tue Dec  8 19:20:43 2009
@@ -20,26 +20,23 @@
 
 import org.apache.shiro.authc.*;
 import org.apache.shiro.authz.AuthorizationInfo;
-import org.apache.shiro.authz.SimpleAuthorizingAccount;
 import org.apache.shiro.authz.SimpleRole;
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.util.CollectionUtils;
 
-import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Set;
 
-
 /**
- * <p>A simple implementation of the {@link Realm Realm} interface that
+ * A simple implementation of the {@link Realm Realm} interface that
  * uses a set of configured user accounts and roles to support authentication and authorization.
 Each account entry
  * specifies the username, password, and roles for a user.  Roles can also be mapped
- * to permissions and associated with users.</p>
+ * to permissions and associated with users.
  * <p/>
- * <p>User accounts and roles are stored in two {@link org.apache.shiro.cache.Cache
cache}s, so it is the Cache manager implementation that
- * determines if this class stores all data in memory or spools to disk or clusters it, etc
based on the
- * Caches it creates.
+ * User accounts and roles are stored in two {@code Map}s in memory, so it is expected that
the total number of either
+ * is not sufficiently large.
  *
  * @author Jeremy Haile
  * @author Les Hazlewood
@@ -49,36 +46,21 @@
 
     //TODO - complete JavaDoc
 
-    protected Map<String, SimpleRole> roles = null;
+    protected final Map<String, SimpleAccount> users; //username-to-SimpleAccount
+    protected final Map<String, SimpleRole> roles; //roleName-to-SimpleRole
 
     public SimpleAccountRealm() {
-        init();
+        this.users = new LinkedHashMap<String, SimpleAccount>();
+        this.roles = new LinkedHashMap<String, SimpleRole>();
     }
 
     public SimpleAccountRealm(String name) {
+        this();
         setName(name);
-        init();
-    }
-
-    public void afterAuthorizationCacheSet() {
-        initRoleCache();
-        afterRoleCacheSet();
-    }
-
-    public void afterRoleCacheSet() {
-    }
-
-    protected void initRoleCache() {
-        if (getAuthorizationCache() == null) {
-            initAuthorizationCache();
-        }
-
-        this.roles = new HashMap<String, SimpleRole>();
-        accountAndRoleCachesCreated();
     }
 
     protected SimpleAccount getUser(String username) {
-        return (SimpleAccount) getAuthorizationCache().get(username);
+        return this.users.get(username);
     }
 
     public boolean accountExists(String username) {
@@ -91,13 +73,21 @@
 
     public void addAccount(String username, String password, String... roles) {
         Set<String> roleNames = CollectionUtils.asSet(roles);
-        SimpleAccount account = new SimpleAuthorizingAccount(username, password, getName(),
roleNames, null);
+        SimpleAccount account = new SimpleAccount(username, password, getName(), roleNames,
null);
         add(account);
     }
 
+    protected String getUsername(SimpleAccount account) {
+        return getUsername(account.getPrincipals());
+    }
+
+    protected String getUsername(PrincipalCollection principals) {
+        return getAvailablePrincipal(principals).toString();
+    }
+
     protected void add(SimpleAccount account) {
-        Object key = getAuthorizationCacheKey(account.getPrincipals());
-        getAuthorizationCache().put(key, account);
+        String username = getUsername(account);
+        this.users.put(username, account);
     }
 
     protected SimpleRole getRole(String rolename) {
@@ -133,12 +123,9 @@
         return values;
     }
 
-    protected void accountAndRoleCachesCreated() {
-    }
-
     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws
AuthenticationException {
         UsernamePasswordToken upToken = (UsernamePasswordToken) token;
-        SimpleAccount account = (SimpleAccount) getAuthorizationCache().get(upToken.getUsername());
+        SimpleAccount account = getUser(upToken.getUsername());
 
         if (account != null) {
 
@@ -156,7 +143,7 @@
     }
 
     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
-        return (Account) getAuthorizationCache().get(getAuthorizationCacheKey(principals));
+        return this.users.get(getUsername(principals));
     }
 
     protected Object getAuthorizationCacheKey(PrincipalCollection principals) {

Added: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java?rev=888528&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java (added)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/IniRealm.java Tue
Dec  8 19:20:43 2009
@@ -0,0 +1,100 @@
+/*
+ * 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.shiro.realm.text;
+
+import org.apache.shiro.config.Ini;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A {@link org.apache.shiro.realm.Realm Realm} implementation that creates
+ * {@link org.apache.shiro.authc.SimpleAccount SimpleAccount} instances based on
+ * {@link Ini} configuration.
+ * <p/>
+ * This implementation looks for two {@link Ini.Section sections} in the {@code Ini} configuration:
+ * <pre>
+ * [users]
+ * # One or more {@link org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions(String)
user definitions}
+ * ...
+ * [roles]
+ * # One or more {@link org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions(String)
role definitions}</pre>
+ */
+public class IniRealm extends TextConfigurationRealm {
+
+    public static final String USERS_SECTION_NAME = "users";
+    public static final String ROLES_SECTION_NAME = "roles";
+
+    private static transient final Logger log = LoggerFactory.getLogger(IniRealm.class);
+
+    private String resourcePath;
+
+    public IniRealm() {
+        super();
+    }
+
+    public IniRealm(Ini ini) {
+        this();
+        processDefinitions(ini);
+    }
+
+    public String getResourcePath() {
+        return resourcePath;
+    }
+
+    public void setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+    }
+
+    @Override
+    public void onInit() {
+        String resourcePath = getResourcePath();
+        if (StringUtils.hasText(resourcePath)) {
+            log.debug("Resource path {} defined.  Creating INI instance.", resourcePath);
+            Ini ini = Ini.fromResourcePath(resourcePath);
+            processDefinitions(ini);
+        } else {
+            throw new IllegalStateException("No resource path was specified.  Cannot load
account data.");
+        }
+    }
+
+    private void processDefinitions(Ini ini) {
+        if (CollectionUtils.isEmpty(ini)) {
+            log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
+            return;
+        }
+
+        Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);
+        if (!CollectionUtils.isEmpty(rolesSection)) {
+            log.debug("Discovered the [{}] section.  Processing...", ROLES_SECTION_NAME);
+            processRoleDefinitions(rolesSection);
+        }
+
+        Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME);
+        if (!CollectionUtils.isEmpty(usersSection)) {
+            log.debug("Discovered the [{}] section.  Processing...", USERS_SECTION_NAME);
+            processUserDefinitions(usersSection);
+        } else {
+            log.info("{} defined, but there is no [{}] section defined.  This realm will
not be populated with any " +
+                    "users and it is assumed that they will be populated programatically.
 Users must be defined " +
+                    "for this Realm instance to be useful.", getClass().getSimpleName(),
USERS_SECTION_NAME);
+        }
+    }
+}

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/PropertiesRealm.java
Tue Dec  8 19:20:43 2009
@@ -18,6 +18,13 @@
  */
 package org.apache.shiro.realm.text;
 
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.cache.CacheManager;
+import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.util.Destroyable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -28,67 +35,59 @@
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.shiro.ShiroException;
-import org.apache.shiro.cache.CacheManager;
-import org.apache.shiro.io.ResourceUtils;
-import org.apache.shiro.util.Destroyable;
-
 
 /**
- * A subclass of <tt>SimpleAccountRealm</tt> that defers all logic to the parent
class, but just enables
+ * A {@link TextConfigurationRealm} that defers all logic to the parent class, but just enables
  * {@link java.util.Properties Properties} based configuration in addition to the parent
class's String configuration.
- *
- * <p>This class allows processing of a single .properties file for user, role, and
+ * <p/>
+ * This class allows processing of a single .properties file for user, role, and
  * permission configuration.
- *
- * <p>For convenience, if the {@link #setResourcePath resourcePath} attribute is not
set, this class defaults to lookup
- * the properties file definition from <tt>classpath:shiro-users.properties</tt>
(root of the classpath).
+ * <p/>
+ * For convenience, if the {@link #setResourcePath resourcePath} attribute is not set, this
class defaults to lookup
+ * the properties file definition from {@code classpath:shiro-users.properties} (root of
the classpath).
  * This allows you to use this implementation by simply defining this file at the classpath
root, instantiating this
  * class, and then calling {@link #init init()}.
- *
- * <p>Or, you may of course specify any other file path using the <tt>url:</tt>,
<tt>file:</tt>, or <tt>classpath:</tt>
- * prefixes.</p>
- *
- * <p>If none of these are specified, and the shiro-users.properties is not included
at the root of the classpath,
+ * <p/>
+ * Or, you may of course specify any other file path using the {@code url:}, {@code file:},
or {@code classpath:}
+ * prefixes.
+ * <p/>
+ * If none of these are specified, and the shiro-users.properties is not included at the
root of the classpath,
  * a default failsafe configuration will be used.  This is not recommended as it only contains
a few simple users and
- * roles which are probably of little value to production applications.</p>
- *
- * <p>The Properties format understood by this implementation must be written as follows:
- *
- * <p>Each line's key/value pair represents either a user-to-role(s) mapping <em>or</em>
a role-to-permission(s)
+ * roles which are probably of little value to production applications.
+ * <p/>
+ * The Properties format understood by this implementation must be written as follows:
+ * <p/>
+ * Each line's key/value pair represents either a user-to-role(s) mapping <em>or</em>
a role-to-permission(s)
  * mapping.
- *
- * <p>The user-to-role(s) lines have this format:</p>
- *
- * <p><code><b>user.</b><em>username</em> = <em>password</em>,role1,role2,...</code></p>
- *
- * <p>Note that each key is prefixed with the token <tt><b>user.</b></tt>
 Each value must adhere to the
- * the {@link #setUserDefinitions(String) setUserDefinitions(String)} JavaDoc.</p>
- *
- * <p>The role-to-permission(s) lines have this format:</p>
- *
- * <p><code><b>role.</b><em>rolename</em> = <em>permissionDefinition1</em>,
<em>permissionDefinition2</em>, ...</code></p>
- *
- * <p>where each key is prefixed with the token <tt><b>role.</b></tt>
and the value adheres to the format specified in
+ * <p/>
+ * The user-to-role(s) lines have this format:</p>
+ * <p/>
+ * <code><b>user.</b><em>username</em> = <em>password</em>,role1,role2,...</code></p>
+ * <p/>
+ * Note that each key is prefixed with the token <b>{@code user.}</b>  Each value
must adhere to the
+ * the {@link #setUserDefinitions(String) setUserDefinitions(String)} JavaDoc.
+ * <p/>
+ * The role-to-permission(s) lines have this format:</p>
+ * <p/>
+ * <code><b>role.</b><em>rolename</em> = <em>permissionDefinition1</em>,
<em>permissionDefinition2</em>, ...</code>
+ * <p/>
+ * where each key is prefixed with the token <b>{@code role.}</b> and the value
adheres to the format specified in
  * the {@link #setRoleDefinitions(String) setRoleDefinitions(String)} JavaDoc.
- *
- * <p>Here is an example of a very simple properties definition that conforms to the
above format rules and corresponding
+ * <p/>
+ * Here is an example of a very simple properties definition that conforms to the above format
rules and corresponding
  * method JavaDocs:
- *
+ * <p/>
  * <code>user.root = <em>rootPassword</em>,administrator<br/>
  * user.jsmith = <em>jsmithPassword</em>,manager,engineer,employee<br/>
  * user.abrown = <em>abrownPassword</em>,qa,employee<br/>
  * user.djones = <em>djonesPassword</em>,qa,contractor<br/>
  * <br/>
- * role.administrator = org.apache.shiro.authz.support.AllPermission<br/>
- * role.manager = com.domain.UserPermission,*,read,write;com.domain.FilePermission,/usr/local/emailManagers.sh,execute<br/>
- * role.engineer = com.domain.FilePermission,/usr/local/tomcat/bin/startup.sh,read,execute<br/>
- * role.employee = com.domain.IntranetPermission,useWiki<br/>
- * role.qa = com.domain.QAServerPermission,*,view,start,shutdown,restart;com.domain.ProductionServerPermission,*,view<br/>
- * role.contractor = com.domain.IntranetPermission,useTimesheet</code>
+ * role.administrator = *<br/>
+ * role.manager = &quot;user:read,write&quot;, file:execute:/usr/local/emailManagers.sh<br/>
+ * role.engineer = &quot;file:read,execute:/usr/local/tomcat/bin/startup.sh&quot;<br/>
+ * role.employee = application:use:wiki<br/>
+ * role.qa = &quot;server:view,start,shutdown,restart:someQaServer&quot;, server:view:someProductionServer<br/>
+ * role.contractor = application:use:timesheet</code>
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
@@ -98,7 +97,7 @@
 
     //TODO - complete JavaDoc
 
-    /*--------------------------------------------
+    /*-------------------------------------------
     |             C O N S T A N T S             |
     ============================================*/
     private static final int DEFAULT_RELOAD_INTERVAL_SECONDS = 10;
@@ -107,7 +106,7 @@
     private static final String DEFAULT_RESOURCE_PATH = "classpath:shiro-users.properties";
     private static final String FAILSAFE_RESOURCE_PATH = "classpath:org/apache/shiro/realm/text/default-shiro-users.properties";
 
-    /*--------------------------------------------
+    /*-------------------------------------------
     |    I N S T A N C E   V A R I A B L E S    |
     ============================================*/
     private static final Logger log = LoggerFactory.getLogger(PropertiesRealm.class);
@@ -119,18 +118,74 @@
     protected int reloadIntervalSeconds = DEFAULT_RELOAD_INTERVAL_SECONDS;
 
     public PropertiesRealm() {
-        init();
+        super();
+        onInit();
     }
 
-    public PropertiesRealm( CacheManager cacheManager ) {
-        if ( cacheManager == null ) {
-            throw new IllegalArgumentException( "cacheManager argument cannot be null." );
-        }
-        setCacheManager(cacheManager);
-        init();
+    /**
+     * Method argument is always ignored.  This method will be removed prior to 1.0 final.
+     *
+     * @param cacheManager ignored
+     * @deprecated PropertiesRealm is an all-in-memory realm - Caching is not necessary or
desired since you
+     *             never want entries to be expunged.  This constructor will be removed prior
to 1.0 final.
+     */
+    @Deprecated
+    public PropertiesRealm(CacheManager cacheManager) {
+        this();
+    }
+
+    /*--------------------------------------------
+    |  A C C E S S O R S / M O D I F I E R S    |
+    ============================================*/
+
+    /**
+     * Determines whether or not the properties XML format should be used.  For more information,
see
+     * {@link Properties#loadFromXML(java.io.InputStream)}
+     *
+     * @param useXmlFormat true to use XML or false to use the normal format.  Defaults to
false.
+     */
+    public void setUseXmlFormat(boolean useXmlFormat) {
+        this.useXmlFormat = useXmlFormat;
+    }
+
+    /**
+     * Sets the path of the properties file to load user, role, and permission information
from.  The properties
+     * file will be loaded using {@link ResourceUtils#getInputStreamForPath(String)} so any
convention recongized
+     * by that method is accepted here.  For example, to load a file from the classpath use
+     * {@code classpath:myfile.properties}; to load a file from disk simply specify the full
path; to load
+     * a file from a URL use {@code url:www.mysite.com/myfile.properties}.
+     *
+     * @param resourcePath the path to load the properties file from.  This is a required
property.
+     */
+    public void setResourcePath(String resourcePath) {
+        this.resourcePath = resourcePath;
+    }
+
+    /**
+     * TODO: RELOADING IS CURRENTLY DISABLED
+     * <p/>
+     * Sets the interval in seconds at which the property file will be checked for changes
and reloaded.  If this is
+     * set to zero or less, property file reloading will be disabled.  If it is set to 1
or greater, then a
+     * separate thread will be created to monitor the propery file for changes and reload
the file if it is updated.
+     *
+     * @param reloadIntervalSeconds the interval in seconds at which the property file should
be examined for changes.
+     *                              If set to zero or less, reloading is disabled.
+     */
+    public void setReloadIntervalSeconds(int reloadIntervalSeconds) {
+        this.reloadIntervalSeconds = reloadIntervalSeconds;
+    }
+
+    /*--------------------------------------------
+    |               M E T H O D S               |
+    ============================================*/
+
+    @Override
+    public void onInit() {
+        //TODO - cleanup - this method shouldn't be necessary
+        afterRoleCacheSet();
     }
 
-    public void afterRoleCacheSet() {
+    protected void afterRoleCacheSet() {
         try {
             loadProperties();
         } catch (Exception e) {
@@ -177,48 +232,6 @@
         }
     }
 
-    /*--------------------------------------------
-    |  A C C E S S O R S / M O D I F I E R S    |
-    ============================================*/
-
-    /**
-     * Determines whether or not the properties XML format should be used.  For more information,
see
-     * {@link Properties#loadFromXML(java.io.InputStream)}
-     *
-     * @param useXmlFormat true to use XML or false to use the normal format.  Defaults to
false.
-     */
-    public void setUseXmlFormat(boolean useXmlFormat) {
-        this.useXmlFormat = useXmlFormat;
-    }
-
-    /**
-     * Sets the path of the properties file to load user, role, and permission information
from.  The properties
-     * file will be loaded using {@link ResourceUtils#getInputStreamForPath(String)} so any
convention recongized
-     * by that method is accepted here.  For example, to load a file from the classpath use
-     * <tt>classpath:myfile.properties</tt>; to load a file from disk simply
specify the full path; to load
-     * a file from a URL use <tt>url:www.mysite.com/myfile.properties</tt>.
-     *
-     * @param resourcePath the path to load the properties file from.  This is a required
property.
-     */
-    public void setResourcePath(String resourcePath) {
-        this.resourcePath = resourcePath;
-    }
-
-    /**
-     * Sets the interval in seconds at which the property file will be checked for changes
and reloaded.  If this is
-     * set to zero or less, property file reloading will be disabled.  If it is set to 1
or greater, then a
-     * separate thread will be created to monitor the propery file for changes and reload
the file if it is updated.
-     *
-     * @param reloadIntervalSeconds the interval in seconds at which the property file should
be examined for changes.
-     *                              If set to zero or less, reloading is disabled.
-     */
-    public void setReloadIntervalSeconds(int reloadIntervalSeconds) {
-        this.reloadIntervalSeconds = reloadIntervalSeconds;
-    }
-
-    /*--------------------------------------------
-    |               M E T H O D S               |
-    ============================================*/
     private void loadProperties() {
         if (resourcePath == null || resourcePath.length() == 0) {
             throw new IllegalStateException("The resourcePath property is not set.  " +

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java?rev=888528&r1=888527&r2=888528&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
(original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/realm/text/TextConfigurationRealm.java
Tue Dec  8 19:20:43 2009
@@ -18,32 +18,27 @@
  */
 package org.apache.shiro.realm.text;
 
-import java.text.ParseException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-
 import org.apache.shiro.authc.SimpleAccount;
 import org.apache.shiro.authz.Permission;
 import org.apache.shiro.authz.SimpleRole;
+import org.apache.shiro.config.ConfigurationException;
 import org.apache.shiro.realm.SimpleAccountRealm;
-import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.util.PermissionUtils;
 import org.apache.shiro.util.StringUtils;
 
+import java.text.ParseException;
+import java.util.*;
+
 
 /**
- * <p>a SimpleAccountRealm that enables text-based configuration of the initial User,
Role, and Permission objects
+ * A SimpleAccountRealm that enables text-based configuration of the initial User, Role,
and Permission objects
  * created at startup.
- *
- * <p>Each User account definition specifies the username, password, and roles for
a user.  Each Role definition
+ * <p/>
+ * Each User account definition specifies the username, password, and roles for a user. 
Each Role definition
  * specifies a name and an optional collection of assigned Permissions.  Users can be assigned
Roles, and Roles can be
- * assigned Permissions.  By transitive association, each User 'has' all of their Role's
Permissions.</p>
- *
- * <p>User and user-to-role definitinos are specified via the {@link #setUserDefinitions}
method and
+ * assigned Permissions.  By transitive association, each User 'has' all of their Role's
Permissions.
+ * <p/>
+ * User and user-to-role definitinos are specified via the {@link #setUserDefinitions} method
and
  * Role-to-permission definitions are specified via the {@link #setRoleDefinitions} method.
  *
  * @author Les Hazlewood
@@ -57,6 +52,7 @@
     private String roleDefinitions;
 
     public TextConfigurationRealm() {
+        super();
     }
 
     public String getUserDefinitions() {
@@ -66,11 +62,11 @@
     /**
      * <p>Sets a newline (\n) delimited String that defines user-to-password-and-role(s)
key/value pairs according
      * to the following format:
-     *
+     * <p/>
      * <p><code><em>username</em> = <em>password</em>,
role1, role2,...</code></p>
-     *
+     * <p/>
      * <p>Here are some examples of what these lines might look like:</p>
-     *
+     * <p/>
      * <p><code>root = <em>reallyHardToGuessPassword</em>, administrator<br/>
      * jsmith = <em>jsmithsPassword</em>, manager, engineer, employee<br/>
      * abrown = <em>abrownsPassword</em>, qa, employee<br/>
@@ -89,19 +85,19 @@
 
     /**
      * Sets a newline (\n) delimited String that defines role-to-permission definitions.
-     *
+     * <p/>
      * <p>Each line within the string must define a role-to-permission(s) key/value
mapping with the
      * equals character signifies the key/value separation, like so:</p>
-     *
+     * <p/>
      * <p><code><em>rolename</em> = <em>permissionDefinition1</em>,
<em>permissionDefinition2</em>, ...</code></p>
-     *
+     * <p/>
      * <p>where <em>permissionDefinition</em> is an arbitrary String, but
must people will want to use
      * Strings that conform to the {@link org.apache.shiro.authz.permission.WildcardPermission
WildcardPermission}
      * format for ease of use and flexibility.  Note that if an individual <em>permissionDefnition</em>
needs to
      * be internally comma-delimited (e.g. <code>printer:5thFloor:print,info</code>),
you will need to surround that
      * definition with double quotes (&quot;) to avoid parsing errors (e.g.
      * <code>&quot;printer:5thFloor:print,info&quot;</code>).
-     *
+     * <p/>
      * <p><b>NOTE:</b> if you have roles that don't require permission
associations, don't include them in this
      * definition - just defining the role name in the {@link #setUserDefinitions(String)
userDefinitions} is
      * enough to create the role if it does not yet exist.  This property is really only
for configuring realms that
@@ -113,17 +109,13 @@
         this.roleDefinitions = roleDefinitions;
     }
 
-    protected void accountAndRoleCachesCreated() {
-        processDefinitions();
-    }
-
     protected void processDefinitions() {
         try {
             processRoleDefinitions();
             processUserDefinitions();
         } catch (ParseException e) {
             String msg = "Unable to parse user and/or role definitions.";
-            throw new IllegalStateException(msg, e);
+            throw new ConfigurationException(msg, e);
         }
     }
 
@@ -133,6 +125,10 @@
             return;
         }
         Map<String, String> roleDefs = toMap(toLines(roleDefinitions));
+        processRoleDefinitions(roleDefs);
+    }
+
+    protected void processRoleDefinitions(Map<String, String> roleDefs) {
         if (roleDefs == null || roleDefs.isEmpty()) {
             return;
         }
@@ -159,6 +155,11 @@
         }
 
         Map<String, String> userDefs = toMap(toLines(userDefinitions));
+
+        processUserDefinitions(userDefs);
+    }
+
+    protected void processUserDefinitions(Map<String, String> userDefs) {
         if (userDefs == null || userDefs.isEmpty()) {
             return;
         }
@@ -211,17 +212,11 @@
         Map<String, String> pairs = new HashMap<String, String>();
         for (String pairString : keyValuePairs) {
             String[] pair = StringUtils.splitKeyValue(pairString);
-            if( pair != null ) {
+            if (pair != null) {
                 pairs.put(pair[0].trim(), pair[1].trim());
             }
         }
 
         return pairs;
     }
-
-    public void onLogout(PrincipalCollection accountPrincipal) {
-        //override parent method of removing user from cache
-        //we don't want that to happen on cache-only realm since that would permanently
-        //remove the user from the realm.
-    }
 }

Added: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/IniRealmTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/IniRealmTest.java?rev=888528&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/IniRealmTest.java
(added)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/text/IniRealmTest.java
Tue Dec  8 19:20:43 2009
@@ -0,0 +1,70 @@
+/*
+ * 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.shiro.realm.text;
+
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.config.Ini;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+/**
+ * Unit tests for the {@link IniRealm} class.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class IniRealmTest {
+
+    @Test
+    public void testNullIni() {
+        IniRealm realm = new IniRealm(null);
+    }
+
+    @Test
+    public void testEmptyIni() {
+        new IniRealm(new Ini());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testInitWithoutIniResource() {
+        new IniRealm().init();
+    }
+
+    @Test
+    public void testIniFile() {
+        IniRealm realm = new IniRealm();
+        realm.setResourcePath("classpath:org/apache/shiro/realm/text/IniRealmTest.simple.ini");
+        realm.init();
+        assertTrue(realm.roleExists("admin"));
+        UsernamePasswordToken token = new UsernamePasswordToken("user1", "user1");
+        AuthenticationInfo info = realm.getAuthenticationInfo(token);
+        assertNotNull(info);
+        assertTrue(realm.hasRole(info.getPrincipals(), "admin"));
+    }
+
+    @Test
+    public void testIniFileWithoutUsers() {
+        IniRealm realm = new IniRealm();
+        realm.setResourcePath("classpath:org/apache/shiro/realm/text/IniRealmTest.noUsers.ini");
+        realm.init();
+        assertTrue(realm.roleExists("admin"));
+    }
+}

Added: incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.noUsers.ini
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.noUsers.ini?rev=888528&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.noUsers.ini
(added)
+++ incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.noUsers.ini
Tue Dec  8 19:20:43 2009
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+[roles]
+admin = *

Added: incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.simple.ini
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.simple.ini?rev=888528&view=auto
==============================================================================
--- incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.simple.ini
(added)
+++ incubator/shiro/trunk/core/src/test/resources/org/apache/shiro/realm/text/IniRealmTest.simple.ini
Tue Dec  8 19:20:43 2009
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+[users]
+user1 = user1, admin
+
+[roles]
+admin = *
+



Mime
View raw message