Coverage Report - org.apache.shiro.realm.text.IniRealm
 
Classes in this File Line Coverage Branch Coverage Complexity
IniRealm
77%
41/53
68%
15/22
2.556
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one
 3  
  * or more contributor license agreements.  See the NOTICE file
 4  
  * distributed with this work for additional information
 5  
  * regarding copyright ownership.  The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the
 7  
  * "License"); you may not use this file except in compliance
 8  
  * with the License.  You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing,
 13  
  * software distributed under the License is distributed on an
 14  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15  
  * KIND, either express or implied.  See the License for the
 16  
  * specific language governing permissions and limitations
 17  
  * under the License.
 18  
  */
 19  
 package org.apache.shiro.realm.text;
 20  
 
 21  
 import org.apache.shiro.config.Ini;
 22  
 import org.apache.shiro.util.CollectionUtils;
 23  
 import org.apache.shiro.util.StringUtils;
 24  
 import org.slf4j.Logger;
 25  
 import org.slf4j.LoggerFactory;
 26  
 
 27  
 /**
 28  
  * A {@link org.apache.shiro.realm.Realm Realm} implementation that creates
 29  
  * {@link org.apache.shiro.authc.SimpleAccount SimpleAccount} instances based on
 30  
  * {@link Ini} configuration.
 31  
  * <p/>
 32  
  * This implementation looks for two {@link Ini.Section sections} in the {@code Ini} configuration:
 33  
  * <pre>
 34  
  * [users]
 35  
  * # One or more {@link org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions(String) user definitions}
 36  
  * ...
 37  
  * [roles]
 38  
  * # One or more {@link org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions(String) role definitions}</pre>
 39  
  * <p/>
 40  
  * This class also supports setting the {@link #setResourcePath(String) resourcePath} property to create account
 41  
  * data from an .ini resource.  This will only be used if there isn't already account data in the Realm.
 42  
  *
 43  
  * @since 1.0
 44  
  */
 45  
 public class IniRealm extends TextConfigurationRealm {
 46  
 
 47  
     public static final String USERS_SECTION_NAME = "users";
 48  
     public static final String ROLES_SECTION_NAME = "roles";
 49  
 
 50  1
     private static transient final Logger log = LoggerFactory.getLogger(IniRealm.class);
 51  
 
 52  
     private String resourcePath;
 53  
     private Ini ini; //reference added in 1.2 for SHIRO-322
 54  
 
 55  
     public IniRealm() {
 56  23
         super();
 57  23
     }
 58  
 
 59  
     /**
 60  
      * This constructor will immediately process the definitions in the {@code Ini} argument.  If you need to perform
 61  
      * additional configuration before processing (e.g. setting a permissionResolver, etc), do not call this
 62  
      * constructor.  Instead, do the following:
 63  
      * <ol>
 64  
      * <li>Call the default no-arg constructor</li>
 65  
      * <li>Set the Ini instance you wish to use via {@code #setIni}</li>
 66  
      * <li>Set any other configuration properties</li>
 67  
      * <li>Call {@link #init()}</li>
 68  
      * </ol>
 69  
      *
 70  
      * @param ini the Ini instance which will be inspected to create accounts, groups and permissions for this realm.
 71  
      */
 72  
     public IniRealm(Ini ini) {
 73  13
         this();
 74  13
         processDefinitions(ini);
 75  13
     }
 76  
 
 77  
     /**
 78  
      * This constructor will immediately process the definitions in the {@code Ini} resolved from the specified
 79  
      * {@code resourcePath}.  If you need to perform additional configuration before processing (e.g. setting a
 80  
      * permissionResolver, etc), do not call this constructor.  Instead, do the following:
 81  
      * <ol>
 82  
      * <li>Call the default no-arg constructor</li>
 83  
      * <li>Set the Ini instance you wish to use via {@code #setIni}</li>
 84  
      * <li>Set any other configuration properties</li>
 85  
      * <li>Call {@link #init()}</li>
 86  
      * </ol>
 87  
      *
 88  
      * @param resourcePath the resource path of the Ini config which will be inspected to create accounts, groups and
 89  
      *                     permissions for this realm.
 90  
      */
 91  
     public IniRealm(String resourcePath) {
 92  0
         this();
 93  0
         Ini ini = Ini.fromResourcePath(resourcePath);
 94  0
         this.ini = ini;
 95  0
         this.resourcePath = resourcePath;
 96  0
         processDefinitions(ini);
 97  0
     }
 98  
 
 99  
     public String getResourcePath() {
 100  10
         return resourcePath;
 101  
     }
 102  
 
 103  
     public void setResourcePath(String resourcePath) {
 104  2
         this.resourcePath = resourcePath;
 105  2
     }
 106  
 
 107  
     /**
 108  
      * Returns the Ini instance used to configure this realm.  Provided for JavaBeans-style configuration of this
 109  
      * realm, particularly useful in Dependency Injection environments.
 110  
      * 
 111  
      * @return the Ini instance which will be inspected to create accounts, groups and permissions for this realm.
 112  
      */
 113  
     public Ini getIni() {
 114  10
         return ini;
 115  
     }
 116  
 
 117  
     /**
 118  
      * Sets the Ini instance used to configure this realm.  Provided for JavaBeans-style configuration of this
 119  
      * realm, particularly useful in Dependency Injection environments.
 120  
      * 
 121  
      * @param ini the Ini instance which will be inspected to create accounts, groups and permissions for this realm.
 122  
      */
 123  
     public void setIni(Ini ini) {
 124  9
         this.ini = ini;
 125  9
     }
 126  
 
 127  
     @Override
 128  
     protected void onInit() {
 129  10
         super.onInit();
 130  
 
 131  
         // This is an in-memory realm only - no need for an additional cache when we're already
 132  
         // as memory-efficient as we can be.
 133  
         
 134  10
         Ini ini = getIni();
 135  10
         String resourcePath = getResourcePath();
 136  
                 
 137  10
         if (!CollectionUtils.isEmpty(this.users) || !CollectionUtils.isEmpty(this.roles)) {
 138  0
             if (!CollectionUtils.isEmpty(ini)) {
 139  0
                 log.warn("Users or Roles are already populated.  Configured Ini instance will be ignored.");
 140  
             }
 141  0
             if (StringUtils.hasText(resourcePath)) {
 142  0
                 log.warn("Users or Roles are already populated.  resourcePath '{}' will be ignored.", resourcePath);
 143  
             }
 144  
             
 145  0
             log.debug("Instance is already populated with users or roles.  No additional user/role population " +
 146  
                     "will be performed.");
 147  0
             return;
 148  
         }
 149  
         
 150  10
         if (CollectionUtils.isEmpty(ini)) {
 151  3
             log.debug("No INI instance configuration present.  Checking resourcePath...");
 152  
             
 153  3
             if (StringUtils.hasText(resourcePath)) {
 154  2
                 log.debug("Resource path {} defined.  Creating INI instance.", resourcePath);
 155  2
                 ini = Ini.fromResourcePath(resourcePath);
 156  2
                 if (!CollectionUtils.isEmpty(ini)) {
 157  2
                     setIni(ini);
 158  
                 }
 159  
             }
 160  
         }
 161  
         
 162  10
         if (CollectionUtils.isEmpty(ini)) {
 163  1
             String msg = "Ini instance and/or resourcePath resulted in null or empty Ini configuration.  Cannot " +
 164  
                     "load account data.";
 165  1
             throw new IllegalStateException(msg);
 166  
         }
 167  
 
 168  9
         processDefinitions(ini);
 169  9
     }
 170  
 
 171  
     private void processDefinitions(Ini ini) {
 172  22
         if (CollectionUtils.isEmpty(ini)) {
 173  2
             log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
 174  2
             return;
 175  
         }
 176  
 
 177  20
         Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);
 178  20
         if (!CollectionUtils.isEmpty(rolesSection)) {
 179  4
             log.debug("Discovered the [{}] section.  Processing...", ROLES_SECTION_NAME);
 180  4
             processRoleDefinitions(rolesSection);
 181  
         }
 182  
 
 183  20
         Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME);
 184  20
         if (!CollectionUtils.isEmpty(usersSection)) {
 185  19
             log.debug("Discovered the [{}] section.  Processing...", USERS_SECTION_NAME);
 186  19
             processUserDefinitions(usersSection);
 187  
         } else {
 188  1
             log.info("{} defined, but there is no [{}] section defined.  This realm will not be populated with any " +
 189  
                     "users and it is assumed that they will be populated programatically.  Users must be defined " +
 190  
                     "for this Realm instance to be useful.", getClass().getSimpleName(), USERS_SECTION_NAME);
 191  
         }
 192  20
     }
 193  
 }