You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by ad...@apache.org on 2010/05/26 20:34:49 UTC

svn commit: r948527 [22/38] - in /incubator/shiro: branches/shiro-root-1.0.x/ branches/shiro-root-1.0.x/all/ branches/shiro-root-1.0.x/core/src/main/java/org/apache/shiro/ branches/shiro-root-1.0.x/core/src/main/java/org/apache/shiro/aop/ branches/shir...

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=948527&r1=948526&r2=948527&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 Wed May 26 18:34:28 2010
@@ -1,568 +1,568 @@
-/*
- * 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.config;
-
-import org.apache.shiro.io.ResourceUtils;
-import org.apache.shiro.util.CollectionUtils;
-import org.apache.shiro.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.*;
-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.  Name/value pairs are guaranteed to be unique
- * within each {@code Section} only - not across the entire {@code Ini} instance.
- *
- * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
- * @since 1.0
- */
-public class Ini implements Map<String, Ini.Section> {
-
-    private static transient final Logger log = LoggerFactory.getLogger(Ini.class);
-
-    public static final String DEFAULT_SECTION_NAME = ""; //empty string means the first unnamed section
-    public static final String DEFAULT_CHARSET_NAME = "ISO-8859-1";
-
-    public static final String COMMENT_POUND = "#";
-    public static final String COMMENT_SEMICOLON = ";";
-    public static final String SECTION_PREFIX = "[";
-    public static final String SECTION_SUFFIX = "]";
-
-    private final Map<String, Section> sections;
-
-    /**
-     * Creates a new empty {@code Ini} instance.
-     */
-    public Ini() {
-        this.sections = new LinkedHashMap<String, Section>();
-    }
-
-    /**
-     * Creates a new {@code Ini} instance with the specified defaults.
-     *
-     * @param defaults the default sections and/or key-value pairs to copy into the new instance.
-     */
-    public Ini(Ini defaults) {
-        this();
-        if (defaults == null) {
-            throw new NullPointerException("Defaults cannot be null.");
-        }
-        for (Section section : defaults.getSections()) {
-            Section copy = new Section(section);
-            this.sections.put(section.getName(), copy);
-        }
-    }
-
-    /**
-     * Returns {@code true} if no sections have been configured, or if there are sections, but the sections themselves
-     * are all empty, {@code false} otherwise.
-     *
-     * @return {@code true} if no sections have been configured, or if there are sections, but the sections themselves
-     *         are all empty, {@code false} otherwise.
-     */
-    public boolean isEmpty() {
-        Collection<Section> sections = this.sections.values();
-        if (!sections.isEmpty()) {
-            for (Section section : sections) {
-                if (!section.isEmpty()) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Returns the names of all sections managed by this {@code Ini} instance or an empty collection if there are
-     * no sections.
-     *
-     * @return the names of all sections managed by this {@code Ini} instance or an empty collection if there are
-     *         no sections.
-     */
-    public Set<String> getSectionNames() {
-        return Collections.unmodifiableSet(sections.keySet());
-    }
-
-    /**
-     * Returns the sections managed by this {@code Ini} instance or an empty collection if there are
-     * no sections.
-     *
-     * @return the sections managed by this {@code Ini} instance or an empty collection if there are
-     *         no sections.
-     */
-    public Collection<Section> getSections() {
-        return Collections.unmodifiableCollection(sections.values());
-    }
-
-    /**
-     * Returns the {@link Section} with the given name or {@code null} if no section with that name exists.
-     *
-     * @param sectionName the name of the section to retrieve.
-     * @return the {@link Section} with the given name or {@code null} if no section with that name exists.
-     */
-    public Section getSection(String sectionName) {
-        String name = cleanName(sectionName);
-        return sections.get(name);
-    }
-
-    /**
-     * Ensures a section with the specified name exists, adding a new one if it does not yet exist.
-     *
-     * @param sectionName the name of the section to ensure existence
-     * @return the section created if it did not yet exist, or the existing Section that already existed.
-     */
-    public Section addSection(String sectionName) {
-        String name = cleanName(sectionName);
-        Section section = getSection(name);
-        if (section == null) {
-            section = new Section(name);
-            this.sections.put(name, section);
-        }
-        return section;
-    }
-
-    /**
-     * Removes the section with the specified name and returns it, or {@code null} if the section did not exist.
-     *
-     * @param sectionName the name of the section to remove.
-     * @return the section with the specified name or {@code null} if the section did not exist.
-     */
-    public Section removeSection(String sectionName) {
-        String name = cleanName(sectionName);
-        return this.sections.remove(name);
-    }
-
-    private static String cleanName(String sectionName) {
-        String name = StringUtils.clean(sectionName);
-        if (name == null) {
-            log.trace("Specified name was null or empty.  Defaulting to the default section (name = \"\")");
-            name = DEFAULT_SECTION_NAME;
-        }
-        return name;
-    }
-
-    /**
-     * Sets a name/value pair for the section with the given {@code sectionName}.  If the section does not yet exist,
-     * it will be created.  If the {@code sectionName} is null or empty, the name/value pair will be placed in the
-     * default (unnamed, empty string) section.
-     *
-     * @param sectionName   the name of the section to add the name/value pair
-     * @param propertyName  the name of the property to add
-     * @param propertyValue the property value
-     */
-    public void setSectionProperty(String sectionName, String propertyName, String propertyValue) {
-        String name = cleanName(sectionName);
-        Section section = getSection(name);
-        if (section == null) {
-            section = addSection(name);
-        }
-        section.put(propertyName, propertyValue);
-    }
-
-    /**
-     * Returns the value of the specified section property, or {@code null} if the section or property do not exist.
-     *
-     * @param sectionName  the name of the section to retrieve to acquire the property value
-     * @param propertyName the name of the section property for which to return the value
-     * @return the value of the specified section property, or {@code null} if the section or property do not exist.
-     */
-    public String getSectionProperty(String sectionName, String propertyName) {
-        Section section = getSection(sectionName);
-        return section != null ? section.get(propertyName) : null;
-    }
-
-    /**
-     * Returns the value of the specified section property, or the {@code defaultValue} if the section or
-     * property do not exist.
-     *
-     * @param sectionName  the name of the section to add the name/value pair
-     * @param propertyName the name of the property to add
-     * @param defaultValue the default value to return if the section or property do not exist.
-     * @return the value of the specified section property, or the {@code defaultValue} if the section or
-     *         property do not exist.
-     */
-    public String getSectionProperty(String sectionName, String propertyName, String defaultValue) {
-        String value = getSectionProperty(sectionName, propertyName);
-        return value != null ? value : defaultValue;
-    }
-
-    /**
-     * Creates a new {@code Ini} instance loaded with the INI-formatted data in the resource at the given path.  The
-     * resource path may be any value interpretable by the
-     * {@link ResourceUtils#getInputStreamForPath(String) ResourceUtils.getInputStreamForPath} method.
-     *
-     * @param resourcePath the resource location of the INI data to load when creating the {@code Ini} instance.
-     * @return a new {@code Ini} instance loaded with the INI-formatted data in the resource at the given path.
-     * @throws ConfigurationException if the path cannot be loaded into an {@code Ini} instance.
-     */
-    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;
-    }
-
-    /**
-     * Loads data from the specified resource path into this current {@code Ini} instance.  The
-     * resource path may be any value interpretable by the
-     * {@link ResourceUtils#getInputStreamForPath(String) ResourceUtils.getInputStreamForPath} method.
-     *
-     * @param resourcePath the resource location of the INI data to load into this instance.
-     * @throws ConfigurationException if the path cannot be loaded
-     */
-    public void loadFromPath(String resourcePath) throws ConfigurationException {
-        InputStream is;
-        try {
-            is = ResourceUtils.getInputStreamForPath(resourcePath);
-        } catch (IOException e) {
-            throw new ConfigurationException(e);
-        }
-        load(is);
-    }
-
-    /**
-     * Loads the specified raw INI-formatted text into this instance.
-     *
-     * @param iniConfig the raw INI-formatted text to load into this instance.
-     * @throws ConfigurationException if the text cannot be loaded
-     */
-    public void load(String iniConfig) throws ConfigurationException {
-        load(new Scanner(iniConfig));
-    }
-
-    /**
-     * Loads the INI-formatted text backed by the given InputStream into this instance.  This implementation will
-     * close the input stream after it has finished loading.
-     *
-     * @param is the {@code InputStream} from which to read the INI-formatted text
-     * @throws ConfigurationException if unable
-     */
-    public void load(InputStream is) throws ConfigurationException {
-        if (is == null) {
-            throw new NullPointerException("InputStream argument cannot be null.");
-        }
-        InputStreamReader isr;
-        try {
-            isr = new InputStreamReader(is, DEFAULT_CHARSET_NAME);
-        } catch (UnsupportedEncodingException e) {
-            throw new ConfigurationException(e);
-        }
-        load(isr);
-    }
-
-    /**
-     * Loads the INI-formatted text backed by the given Reader into this instance.  This implementation will close the
-     * reader after it has finished loading.
-     *
-     * @param reader the {@code Reader} from which to read the INI-formatted text
-     */
-    public void load(Reader reader) {
-        Scanner scanner = new Scanner(reader);
-        try {
-            load(scanner);
-        } finally {
-            try {
-                scanner.close();
-            } catch (Exception e) {
-                log.debug("Unable to cleanly close the InputStream scanner.  Non-critical - ignoring.", e);
-            }
-        }
-    }
-
-    private static InputStream toInputStream(String content) {
-        byte[] bytes;
-        try {
-            bytes = content.getBytes(DEFAULT_CHARSET_NAME);
-        } catch (UnsupportedEncodingException e) {
-            throw new ConfigurationException(e);
-        }
-        return new ByteArrayInputStream(bytes);
-    }
-
-    private static Properties toProps(String content) {
-        InputStream is = toInputStream(content);
-        Properties props = new Properties();
-        try {
-            props.load(is);
-        } catch (IOException e) {
-            throw new ConfigurationException(e);
-        }
-        return props;
-    }
-
-    private void addSection(String name, StringBuffer content) {
-        if (content.length() > 0) {
-            String contentString = content.toString();
-            String cleaned = StringUtils.clean(contentString);
-            if (cleaned != null) {
-                Properties props = toProps(contentString);
-                if (!props.isEmpty()) {
-                    sections.put(name, new Section(name, props));
-                }
-            }
-        }
-    }
-
-    /**
-     * Loads the INI-formatted text backed by the given Scanner.  This implementation will close the
-     * scanner after it has finished loading.
-     *
-     * @param scanner the {@code Scanner} from which to read the INI-formatted text
-     */
-    public void load(Scanner scanner) {
-
-        String sectionName = DEFAULT_SECTION_NAME;
-        StringBuffer sectionContent = new StringBuffer();
-
-        while (scanner.hasNextLine()) {
-
-            String rawLine = scanner.nextLine();
-            String line = StringUtils.clean(rawLine);
-
-            if (line == null || line.startsWith(COMMENT_POUND) || line.startsWith(COMMENT_SEMICOLON)) {
-                //skip empty lines and comments:
-                continue;
-            }
-
-            String newSectionName = getSectionName(line);
-            if (newSectionName != null) {
-                //found a new section - convert the currently buffered one into a Section object
-                addSection(sectionName, sectionContent);
-
-                //reset the buffer for the new section:
-                sectionContent = new StringBuffer();
-
-                sectionName = newSectionName;
-
-                if (log.isDebugEnabled()) {
-                    log.debug("Parsing " + SECTION_PREFIX + sectionName + SECTION_SUFFIX);
-                }
-            } else {
-                //normal line - add it to the existing content buffer:
-                sectionContent.append(rawLine).append("\n");
-            }
-        }
-
-        //finish any remaining buffered content:
-        addSection(sectionName, sectionContent);
-    }
-
-    protected static boolean isSectionHeader(String line) {
-        String s = StringUtils.clean(line);
-        return s != null && s.startsWith(SECTION_PREFIX) && s.endsWith(SECTION_SUFFIX);
-    }
-
-    protected static String getSectionName(String line) {
-        String s = StringUtils.clean(line);
-        if (isSectionHeader(s)) {
-            return cleanName(s.substring(1, s.length() - 1));
-        }
-        return null;
-    }
-
-    public boolean equals(Object obj) {
-        if (obj instanceof Ini) {
-            Ini ini = (Ini) obj;
-            return this.sections.equals(ini.sections);
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return this.sections.hashCode();
-    }
-
-    public String toString() {
-        if (CollectionUtils.isEmpty(this.sections)) {
-            return "<empty INI>";
-        } else {
-            StringBuilder sb = new StringBuilder("sections=");
-            int i = 0;
-            for (Ini.Section section : this.sections.values()) {
-                if (i > 0) {
-                    sb.append(",");
-                }
-                sb.append(section.toString());
-                i++;
-            }
-            return sb.toString();
-        }
-    }
-
-    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());
-    }
-
-    /**
-     * An {@code Ini.Section} is String-key-to-String-value Map, identifiable by a
-     * {@link #getName() name} unique within an {@link Ini} instance.
-     */
-    public class Section implements Map<String, String> {
-        private final String name;
-        private final Map<String, String> props;
-
-        private Section(String name) {
-            if (name == null) {
-                throw new NullPointerException("name");
-            }
-            this.name = name;
-            this.props = new LinkedHashMap<String, String>();
-        }
-
-        private Section(String name, Properties props) {
-            this(name);
-            Enumeration propNames = props.propertyNames();
-            while (propNames != null && propNames.hasMoreElements()) {
-                String key = propNames.nextElement().toString();
-                String value = props.getProperty(key);
-                if (value != null) {
-                    this.props.put(key, value.trim());
-                }
-            }
-        }
-
-        private Section(Section defaults) {
-            this(defaults.getName());
-            putAll(defaults.props);
-        }
-
-        public String getName() {
-            return this.name;
-        }
-
-        public void clear() {
-            this.props.clear();
-        }
-
-        public boolean containsKey(Object key) {
-            return this.props.containsKey(key);
-        }
-
-        public boolean containsValue(Object value) {
-            return this.props.containsValue(value);
-        }
-
-        public Set<Entry<String, String>> entrySet() {
-            return this.props.entrySet();
-        }
-
-        public String get(Object key) {
-            return this.props.get(key);
-        }
-
-        public boolean isEmpty() {
-            return this.props.isEmpty();
-        }
-
-        public Set<String> keySet() {
-            return this.props.keySet();
-        }
-
-        public String put(String key, String value) {
-            return this.props.put(key, value);
-        }
-
-        public void putAll(Map<? extends String, ? extends String> m) {
-            this.props.putAll(m);
-        }
-
-        public String remove(Object key) {
-            return this.props.remove(key);
-        }
-
-        public int size() {
-            return this.props.size();
-        }
-
-        public Collection<String> values() {
-            return this.props.values();
-        }
-
-        public String toString() {
-            String name = getName();
-            if (DEFAULT_SECTION_NAME.equals(name)) {
-                return "<default>";
-            }
-            return name;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (obj instanceof Section) {
-                Section other = (Section) obj;
-                return getName().equals(other.getName()) && this.props.equals(other.props);
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return this.name.hashCode() * 31 + this.props.hashCode();
-        }
-    }
-
-}
+/*
+ * 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.config;
+
+import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+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.  Name/value pairs are guaranteed to be unique
+ * within each {@code Section} only - not across the entire {@code Ini} instance.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class Ini implements Map<String, Ini.Section> {
+
+    private static transient final Logger log = LoggerFactory.getLogger(Ini.class);
+
+    public static final String DEFAULT_SECTION_NAME = ""; //empty string means the first unnamed section
+    public static final String DEFAULT_CHARSET_NAME = "ISO-8859-1";
+
+    public static final String COMMENT_POUND = "#";
+    public static final String COMMENT_SEMICOLON = ";";
+    public static final String SECTION_PREFIX = "[";
+    public static final String SECTION_SUFFIX = "]";
+
+    private final Map<String, Section> sections;
+
+    /**
+     * Creates a new empty {@code Ini} instance.
+     */
+    public Ini() {
+        this.sections = new LinkedHashMap<String, Section>();
+    }
+
+    /**
+     * Creates a new {@code Ini} instance with the specified defaults.
+     *
+     * @param defaults the default sections and/or key-value pairs to copy into the new instance.
+     */
+    public Ini(Ini defaults) {
+        this();
+        if (defaults == null) {
+            throw new NullPointerException("Defaults cannot be null.");
+        }
+        for (Section section : defaults.getSections()) {
+            Section copy = new Section(section);
+            this.sections.put(section.getName(), copy);
+        }
+    }
+
+    /**
+     * Returns {@code true} if no sections have been configured, or if there are sections, but the sections themselves
+     * are all empty, {@code false} otherwise.
+     *
+     * @return {@code true} if no sections have been configured, or if there are sections, but the sections themselves
+     *         are all empty, {@code false} otherwise.
+     */
+    public boolean isEmpty() {
+        Collection<Section> sections = this.sections.values();
+        if (!sections.isEmpty()) {
+            for (Section section : sections) {
+                if (!section.isEmpty()) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the names of all sections managed by this {@code Ini} instance or an empty collection if there are
+     * no sections.
+     *
+     * @return the names of all sections managed by this {@code Ini} instance or an empty collection if there are
+     *         no sections.
+     */
+    public Set<String> getSectionNames() {
+        return Collections.unmodifiableSet(sections.keySet());
+    }
+
+    /**
+     * Returns the sections managed by this {@code Ini} instance or an empty collection if there are
+     * no sections.
+     *
+     * @return the sections managed by this {@code Ini} instance or an empty collection if there are
+     *         no sections.
+     */
+    public Collection<Section> getSections() {
+        return Collections.unmodifiableCollection(sections.values());
+    }
+
+    /**
+     * Returns the {@link Section} with the given name or {@code null} if no section with that name exists.
+     *
+     * @param sectionName the name of the section to retrieve.
+     * @return the {@link Section} with the given name or {@code null} if no section with that name exists.
+     */
+    public Section getSection(String sectionName) {
+        String name = cleanName(sectionName);
+        return sections.get(name);
+    }
+
+    /**
+     * Ensures a section with the specified name exists, adding a new one if it does not yet exist.
+     *
+     * @param sectionName the name of the section to ensure existence
+     * @return the section created if it did not yet exist, or the existing Section that already existed.
+     */
+    public Section addSection(String sectionName) {
+        String name = cleanName(sectionName);
+        Section section = getSection(name);
+        if (section == null) {
+            section = new Section(name);
+            this.sections.put(name, section);
+        }
+        return section;
+    }
+
+    /**
+     * Removes the section with the specified name and returns it, or {@code null} if the section did not exist.
+     *
+     * @param sectionName the name of the section to remove.
+     * @return the section with the specified name or {@code null} if the section did not exist.
+     */
+    public Section removeSection(String sectionName) {
+        String name = cleanName(sectionName);
+        return this.sections.remove(name);
+    }
+
+    private static String cleanName(String sectionName) {
+        String name = StringUtils.clean(sectionName);
+        if (name == null) {
+            log.trace("Specified name was null or empty.  Defaulting to the default section (name = \"\")");
+            name = DEFAULT_SECTION_NAME;
+        }
+        return name;
+    }
+
+    /**
+     * Sets a name/value pair for the section with the given {@code sectionName}.  If the section does not yet exist,
+     * it will be created.  If the {@code sectionName} is null or empty, the name/value pair will be placed in the
+     * default (unnamed, empty string) section.
+     *
+     * @param sectionName   the name of the section to add the name/value pair
+     * @param propertyName  the name of the property to add
+     * @param propertyValue the property value
+     */
+    public void setSectionProperty(String sectionName, String propertyName, String propertyValue) {
+        String name = cleanName(sectionName);
+        Section section = getSection(name);
+        if (section == null) {
+            section = addSection(name);
+        }
+        section.put(propertyName, propertyValue);
+    }
+
+    /**
+     * Returns the value of the specified section property, or {@code null} if the section or property do not exist.
+     *
+     * @param sectionName  the name of the section to retrieve to acquire the property value
+     * @param propertyName the name of the section property for which to return the value
+     * @return the value of the specified section property, or {@code null} if the section or property do not exist.
+     */
+    public String getSectionProperty(String sectionName, String propertyName) {
+        Section section = getSection(sectionName);
+        return section != null ? section.get(propertyName) : null;
+    }
+
+    /**
+     * Returns the value of the specified section property, or the {@code defaultValue} if the section or
+     * property do not exist.
+     *
+     * @param sectionName  the name of the section to add the name/value pair
+     * @param propertyName the name of the property to add
+     * @param defaultValue the default value to return if the section or property do not exist.
+     * @return the value of the specified section property, or the {@code defaultValue} if the section or
+     *         property do not exist.
+     */
+    public String getSectionProperty(String sectionName, String propertyName, String defaultValue) {
+        String value = getSectionProperty(sectionName, propertyName);
+        return value != null ? value : defaultValue;
+    }
+
+    /**
+     * Creates a new {@code Ini} instance loaded with the INI-formatted data in the resource at the given path.  The
+     * resource path may be any value interpretable by the
+     * {@link ResourceUtils#getInputStreamForPath(String) ResourceUtils.getInputStreamForPath} method.
+     *
+     * @param resourcePath the resource location of the INI data to load when creating the {@code Ini} instance.
+     * @return a new {@code Ini} instance loaded with the INI-formatted data in the resource at the given path.
+     * @throws ConfigurationException if the path cannot be loaded into an {@code Ini} instance.
+     */
+    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;
+    }
+
+    /**
+     * Loads data from the specified resource path into this current {@code Ini} instance.  The
+     * resource path may be any value interpretable by the
+     * {@link ResourceUtils#getInputStreamForPath(String) ResourceUtils.getInputStreamForPath} method.
+     *
+     * @param resourcePath the resource location of the INI data to load into this instance.
+     * @throws ConfigurationException if the path cannot be loaded
+     */
+    public void loadFromPath(String resourcePath) throws ConfigurationException {
+        InputStream is;
+        try {
+            is = ResourceUtils.getInputStreamForPath(resourcePath);
+        } catch (IOException e) {
+            throw new ConfigurationException(e);
+        }
+        load(is);
+    }
+
+    /**
+     * Loads the specified raw INI-formatted text into this instance.
+     *
+     * @param iniConfig the raw INI-formatted text to load into this instance.
+     * @throws ConfigurationException if the text cannot be loaded
+     */
+    public void load(String iniConfig) throws ConfigurationException {
+        load(new Scanner(iniConfig));
+    }
+
+    /**
+     * Loads the INI-formatted text backed by the given InputStream into this instance.  This implementation will
+     * close the input stream after it has finished loading.
+     *
+     * @param is the {@code InputStream} from which to read the INI-formatted text
+     * @throws ConfigurationException if unable
+     */
+    public void load(InputStream is) throws ConfigurationException {
+        if (is == null) {
+            throw new NullPointerException("InputStream argument cannot be null.");
+        }
+        InputStreamReader isr;
+        try {
+            isr = new InputStreamReader(is, DEFAULT_CHARSET_NAME);
+        } catch (UnsupportedEncodingException e) {
+            throw new ConfigurationException(e);
+        }
+        load(isr);
+    }
+
+    /**
+     * Loads the INI-formatted text backed by the given Reader into this instance.  This implementation will close the
+     * reader after it has finished loading.
+     *
+     * @param reader the {@code Reader} from which to read the INI-formatted text
+     */
+    public void load(Reader reader) {
+        Scanner scanner = new Scanner(reader);
+        try {
+            load(scanner);
+        } finally {
+            try {
+                scanner.close();
+            } catch (Exception e) {
+                log.debug("Unable to cleanly close the InputStream scanner.  Non-critical - ignoring.", e);
+            }
+        }
+    }
+
+    private static InputStream toInputStream(String content) {
+        byte[] bytes;
+        try {
+            bytes = content.getBytes(DEFAULT_CHARSET_NAME);
+        } catch (UnsupportedEncodingException e) {
+            throw new ConfigurationException(e);
+        }
+        return new ByteArrayInputStream(bytes);
+    }
+
+    private static Properties toProps(String content) {
+        InputStream is = toInputStream(content);
+        Properties props = new Properties();
+        try {
+            props.load(is);
+        } catch (IOException e) {
+            throw new ConfigurationException(e);
+        }
+        return props;
+    }
+
+    private void addSection(String name, StringBuffer content) {
+        if (content.length() > 0) {
+            String contentString = content.toString();
+            String cleaned = StringUtils.clean(contentString);
+            if (cleaned != null) {
+                Properties props = toProps(contentString);
+                if (!props.isEmpty()) {
+                    sections.put(name, new Section(name, props));
+                }
+            }
+        }
+    }
+
+    /**
+     * Loads the INI-formatted text backed by the given Scanner.  This implementation will close the
+     * scanner after it has finished loading.
+     *
+     * @param scanner the {@code Scanner} from which to read the INI-formatted text
+     */
+    public void load(Scanner scanner) {
+
+        String sectionName = DEFAULT_SECTION_NAME;
+        StringBuffer sectionContent = new StringBuffer();
+
+        while (scanner.hasNextLine()) {
+
+            String rawLine = scanner.nextLine();
+            String line = StringUtils.clean(rawLine);
+
+            if (line == null || line.startsWith(COMMENT_POUND) || line.startsWith(COMMENT_SEMICOLON)) {
+                //skip empty lines and comments:
+                continue;
+            }
+
+            String newSectionName = getSectionName(line);
+            if (newSectionName != null) {
+                //found a new section - convert the currently buffered one into a Section object
+                addSection(sectionName, sectionContent);
+
+                //reset the buffer for the new section:
+                sectionContent = new StringBuffer();
+
+                sectionName = newSectionName;
+
+                if (log.isDebugEnabled()) {
+                    log.debug("Parsing " + SECTION_PREFIX + sectionName + SECTION_SUFFIX);
+                }
+            } else {
+                //normal line - add it to the existing content buffer:
+                sectionContent.append(rawLine).append("\n");
+            }
+        }
+
+        //finish any remaining buffered content:
+        addSection(sectionName, sectionContent);
+    }
+
+    protected static boolean isSectionHeader(String line) {
+        String s = StringUtils.clean(line);
+        return s != null && s.startsWith(SECTION_PREFIX) && s.endsWith(SECTION_SUFFIX);
+    }
+
+    protected static String getSectionName(String line) {
+        String s = StringUtils.clean(line);
+        if (isSectionHeader(s)) {
+            return cleanName(s.substring(1, s.length() - 1));
+        }
+        return null;
+    }
+
+    public boolean equals(Object obj) {
+        if (obj instanceof Ini) {
+            Ini ini = (Ini) obj;
+            return this.sections.equals(ini.sections);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return this.sections.hashCode();
+    }
+
+    public String toString() {
+        if (CollectionUtils.isEmpty(this.sections)) {
+            return "<empty INI>";
+        } else {
+            StringBuilder sb = new StringBuilder("sections=");
+            int i = 0;
+            for (Ini.Section section : this.sections.values()) {
+                if (i > 0) {
+                    sb.append(",");
+                }
+                sb.append(section.toString());
+                i++;
+            }
+            return sb.toString();
+        }
+    }
+
+    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());
+    }
+
+    /**
+     * An {@code Ini.Section} is String-key-to-String-value Map, identifiable by a
+     * {@link #getName() name} unique within an {@link Ini} instance.
+     */
+    public class Section implements Map<String, String> {
+        private final String name;
+        private final Map<String, String> props;
+
+        private Section(String name) {
+            if (name == null) {
+                throw new NullPointerException("name");
+            }
+            this.name = name;
+            this.props = new LinkedHashMap<String, String>();
+        }
+
+        private Section(String name, Properties props) {
+            this(name);
+            Enumeration propNames = props.propertyNames();
+            while (propNames != null && propNames.hasMoreElements()) {
+                String key = propNames.nextElement().toString();
+                String value = props.getProperty(key);
+                if (value != null) {
+                    this.props.put(key, value.trim());
+                }
+            }
+        }
+
+        private Section(Section defaults) {
+            this(defaults.getName());
+            putAll(defaults.props);
+        }
+
+        public String getName() {
+            return this.name;
+        }
+
+        public void clear() {
+            this.props.clear();
+        }
+
+        public boolean containsKey(Object key) {
+            return this.props.containsKey(key);
+        }
+
+        public boolean containsValue(Object value) {
+            return this.props.containsValue(value);
+        }
+
+        public Set<Entry<String, String>> entrySet() {
+            return this.props.entrySet();
+        }
+
+        public String get(Object key) {
+            return this.props.get(key);
+        }
+
+        public boolean isEmpty() {
+            return this.props.isEmpty();
+        }
+
+        public Set<String> keySet() {
+            return this.props.keySet();
+        }
+
+        public String put(String key, String value) {
+            return this.props.put(key, value);
+        }
+
+        public void putAll(Map<? extends String, ? extends String> m) {
+            this.props.putAll(m);
+        }
+
+        public String remove(Object key) {
+            return this.props.remove(key);
+        }
+
+        public int size() {
+            return this.props.size();
+        }
+
+        public Collection<String> values() {
+            return this.props.values();
+        }
+
+        public String toString() {
+            String name = getName();
+            if (DEFAULT_SECTION_NAME.equals(name)) {
+                return "<default>";
+            }
+            return name;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof Section) {
+                Section other = (Section) obj;
+                return getName().equals(other.getName()) && this.props.equals(other.props);
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            return this.name.hashCode() * 31 + this.props.hashCode();
+        }
+    }
+
+}

Propchange: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/Ini.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=948527&r1=948526&r2=948527&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 Wed May 26 18:34:28 2010
@@ -1,138 +1,138 @@
-/*
- * 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.config;
-
-import org.apache.shiro.io.ResourceUtils;
-import org.apache.shiro.util.AbstractFactory;
-import org.apache.shiro.util.CollectionUtils;
-import org.apache.shiro.util.Factory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Base support class for {@link Factory} implementations that generate their instance(s) based on
- * {@link Ini} configuration.
- *
- * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
- * @since 1.0
- */
-public abstract class IniFactorySupport<T> extends AbstractFactory<T> {
-
-    public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
-
-    private static transient final Logger log = LoggerFactory.getLogger(IniFactorySupport.class);
-
-    private Ini ini;
-
-    protected IniFactorySupport() {
-    }
-
-    protected IniFactorySupport(Ini ini) {
-        this.ini = ini;
-    }
-
-    public Ini getIni() {
-        return ini;
-    }
-
-    public void setIni(Ini ini) {
-        this.ini = ini;
-    }
-
-    /**
-     * Returns a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
-     * the file does not exist.
-     *
-     * @return a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
-     *         the file does not exist.
-     */
-    public static Ini loadDefaultClassPathIni() {
-        Ini ini = null;
-        if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
-            log.debug("Found shiro.ini at the root of the classpath.");
-            ini = new Ini();
-            ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
-            if (CollectionUtils.isEmpty(ini)) {
-                log.warn("shiro.ini found at the root of the classpath, but it did not contain any data.");
-            }
-        }
-        return ini;
-    }
-
-    /**
-     * Tries to resolve the Ini instance to use for configuration.  This implementation functions as follows:
-     * <ol>
-     * <li>The {@code Ini} instance returned from {@link #getIni()} will be returned if it is not null or empty.</li>
-     * <li>If {@link #getIni()} is {@code null} or empty, this implementation will attempt to find and load the
-     * {@link #loadDefaultClassPathIni() default class path Ini}.</li>
-     * <li>If neither of the two attempts above returns an instance, {@code null} is returned</li>
-     * </ol>
-     *
-     * @return the Ini instance to use for configuration.
-     */
-    protected Ini resolveIni() {
-        Ini ini = getIni();
-        if (CollectionUtils.isEmpty(ini)) {
-            log.debug("Null or empty Ini instance.  Falling back to the default {} file.", DEFAULT_INI_RESOURCE_PATH);
-            ini = loadDefaultClassPathIni();
-        }
-        return ini;
-    }
-
-    /**
-     * Creates a new object instance by using a configured INI source.  This implementation functions as follows:
-     * <ol>
-     * <li>{@link #resolveIni() Resolve} the {@code Ini} source to use for configuration.</li>
-     * <li>If there was no resolved Ini source, create and return a simple default instance via the
-     * {@link #createDefaultInstance()} method.</li>
-     * </ol>
-     *
-     * @return a new {@code SecurityManager} instance by using a configured INI source.
-     */
-    public T createInstance() {
-        Ini ini = resolveIni();
-
-        T instance;
-
-        if (CollectionUtils.isEmpty(ini)) {
-            log.debug("No populated Ini available.  Creating a default instance.");
-            instance = createDefaultInstance();
-            if (instance == null) {
-                String msg = getClass().getName() + " implementation did not return a default instance in " +
-                        "the event of a null/empty Ini configuration.  This is required to support the " +
-                        "Factory interface.  Please check your implementation.";
-                throw new IllegalStateException(msg);
-            }
-        } else {
-            log.debug("Creating instance from Ini [" + ini + "]");
-            instance = createInstance(ini);
-            if (instance == null) {
-                String msg = getClass().getName() + " implementation did not return a constructed instance from " +
-                        "the createInstance(Ini) method implementation.";
-                throw new IllegalStateException(msg);
-            }
-        }
-
-        return instance;
-    }
-
-    protected abstract T createInstance(Ini ini);
-
-    protected abstract T createDefaultInstance();
-}
+/*
+ * 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.config;
+
+import org.apache.shiro.io.ResourceUtils;
+import org.apache.shiro.util.AbstractFactory;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.Factory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Base support class for {@link Factory} implementations that generate their instance(s) based on
+ * {@link Ini} configuration.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public abstract class IniFactorySupport<T> extends AbstractFactory<T> {
+
+    public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
+
+    private static transient final Logger log = LoggerFactory.getLogger(IniFactorySupport.class);
+
+    private Ini ini;
+
+    protected IniFactorySupport() {
+    }
+
+    protected IniFactorySupport(Ini ini) {
+        this.ini = ini;
+    }
+
+    public Ini getIni() {
+        return ini;
+    }
+
+    public void setIni(Ini ini) {
+        this.ini = ini;
+    }
+
+    /**
+     * Returns a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
+     * the file does not exist.
+     *
+     * @return a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
+     *         the file does not exist.
+     */
+    public static Ini loadDefaultClassPathIni() {
+        Ini ini = null;
+        if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
+            log.debug("Found shiro.ini at the root of the classpath.");
+            ini = new Ini();
+            ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
+            if (CollectionUtils.isEmpty(ini)) {
+                log.warn("shiro.ini found at the root of the classpath, but it did not contain any data.");
+            }
+        }
+        return ini;
+    }
+
+    /**
+     * Tries to resolve the Ini instance to use for configuration.  This implementation functions as follows:
+     * <ol>
+     * <li>The {@code Ini} instance returned from {@link #getIni()} will be returned if it is not null or empty.</li>
+     * <li>If {@link #getIni()} is {@code null} or empty, this implementation will attempt to find and load the
+     * {@link #loadDefaultClassPathIni() default class path Ini}.</li>
+     * <li>If neither of the two attempts above returns an instance, {@code null} is returned</li>
+     * </ol>
+     *
+     * @return the Ini instance to use for configuration.
+     */
+    protected Ini resolveIni() {
+        Ini ini = getIni();
+        if (CollectionUtils.isEmpty(ini)) {
+            log.debug("Null or empty Ini instance.  Falling back to the default {} file.", DEFAULT_INI_RESOURCE_PATH);
+            ini = loadDefaultClassPathIni();
+        }
+        return ini;
+    }
+
+    /**
+     * Creates a new object instance by using a configured INI source.  This implementation functions as follows:
+     * <ol>
+     * <li>{@link #resolveIni() Resolve} the {@code Ini} source to use for configuration.</li>
+     * <li>If there was no resolved Ini source, create and return a simple default instance via the
+     * {@link #createDefaultInstance()} method.</li>
+     * </ol>
+     *
+     * @return a new {@code SecurityManager} instance by using a configured INI source.
+     */
+    public T createInstance() {
+        Ini ini = resolveIni();
+
+        T instance;
+
+        if (CollectionUtils.isEmpty(ini)) {
+            log.debug("No populated Ini available.  Creating a default instance.");
+            instance = createDefaultInstance();
+            if (instance == null) {
+                String msg = getClass().getName() + " implementation did not return a default instance in " +
+                        "the event of a null/empty Ini configuration.  This is required to support the " +
+                        "Factory interface.  Please check your implementation.";
+                throw new IllegalStateException(msg);
+            }
+        } else {
+            log.debug("Creating instance from Ini [" + ini + "]");
+            instance = createInstance(ini);
+            if (instance == null) {
+                String msg = getClass().getName() + " implementation did not return a constructed instance from " +
+                        "the createInstance(Ini) method implementation.";
+                throw new IllegalStateException(msg);
+            }
+        }
+
+        return instance;
+    }
+
+    protected abstract T createInstance(Ini ini);
+
+    protected abstract T createDefaultInstance();
+}

Propchange: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniFactorySupport.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=948527&r1=948526&r2=948527&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 Wed May 26 18:34:28 2010
@@ -1,259 +1,259 @@
-/*
- * 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.config;
-
-import org.apache.shiro.mgt.DefaultSecurityManager;
-import org.apache.shiro.mgt.RealmSecurityManager;
-import org.apache.shiro.mgt.SecurityManager;
-import org.apache.shiro.realm.Realm;
-import org.apache.shiro.realm.RealmFactory;
-import org.apache.shiro.realm.text.IniRealm;
-import org.apache.shiro.util.CollectionUtils;
-import org.apache.shiro.util.Factory;
-import org.apache.shiro.util.LifecycleUtils;
-import org.apache.shiro.util.Nameable;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
-
-/**
- * A {@link Factory} that creates {@link SecurityManager} instances based on {@link Ini} configuration.
- *
- * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
- * @since 1.0
- */
-public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
-
-    public static final String MAIN_SECTION_NAME = "main";
-
-    public static final String SECURITY_MANAGER_NAME = "securityManager";
-    public static final String INI_REALM_NAME = "iniRealm";
-
-    private static transient final Logger log = LoggerFactory.getLogger(IniSecurityManagerFactory.class);
-
-    private ReflectionBuilder builder;
-
-    /**
-     * Creates a new instance.  See the {@link #getInstance()} JavaDoc for detailed explanation of how an INI
-     * source will be resolved to use to build the instance.
-     */
-    public IniSecurityManagerFactory() {
-    }
-
-    public IniSecurityManagerFactory(Ini config) {
-        setIni(config);
-    }
-
-    public IniSecurityManagerFactory(String iniResourcePath) {
-        this(Ini.fromResourcePath(iniResourcePath));
-    }
-
-    public Map<String, ?> getBeans() {
-        return this.builder != null ? Collections.unmodifiableMap(builder.getObjects()) : null;
-    }
-
-    private SecurityManager getSecurityManagerBean() {
-        return builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);
-    }
-
-    protected SecurityManager createDefaultInstance() {
-        return new DefaultSecurityManager();
-    }
-
-    protected SecurityManager createInstance(Ini ini) {
-        if (CollectionUtils.isEmpty(ini)) {
-            throw new NullPointerException("Ini argument cannot be null or empty.");
-        }
-        SecurityManager securityManager = createSecurityManager(ini);
-        if (securityManager == null) {
-            String msg = SecurityManager.class + " instance cannot be null.";
-            throw new ConfigurationException(msg);
-        }
-        return securityManager;
-    }
-
-    private SecurityManager createSecurityManager(Ini ini) {
-        Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME);
-        if (CollectionUtils.isEmpty(mainSection)) {
-            //try the default:
-            mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
-        }
-        return createSecurityManager(ini, mainSection);
-    }
-
-    protected boolean isAutoApplyRealms(SecurityManager securityManager) {
-        boolean autoApply = true;
-        if (securityManager instanceof RealmSecurityManager) {
-            //only apply realms if they haven't been explicitly set by the user:
-            RealmSecurityManager realmSecurityManager = (RealmSecurityManager) securityManager;
-            Collection<Realm> realms = realmSecurityManager.getRealms();
-            if (!CollectionUtils.isEmpty(realms)) {
-                log.info("Realms have been explicitly set on the SecurityManager instance - auto-setting of " +
-                        "realms will not occur.");
-                autoApply = false;
-            }
-        }
-        return autoApply;
-    }
-
-    @SuppressWarnings({"unchecked"})
-    private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) {
-
-        Map<String, ?> defaults = createDefaults(ini, mainSection);
-        Map<String, ?> objects = buildInstances(mainSection, defaults);
-
-        SecurityManager securityManager = getSecurityManagerBean();
-
-        boolean autoApplyRealms = isAutoApplyRealms(securityManager);
-
-        if (autoApplyRealms) {
-            //realms and realm factory might have been created - pull them out first so we can
-            //initialize the securityManager:
-            Collection<Realm> realms = getRealms(objects);
-            //set them on the SecurityManager
-            if (!CollectionUtils.isEmpty(realms)) {
-                applyRealmsToSecurityManager(realms, securityManager);
-            }
-        }
-
-        initRealms(securityManager);
-
-        return securityManager;
-    }
-
-    private void initRealms(SecurityManager securityManager) {
-        Collection<Realm> realms = getRealms(securityManager);
-        if (!CollectionUtils.isEmpty(realms)) {
-            LifecycleUtils.init(realms);
-        }
-    }
-
-    private Collection<Realm> getRealms(SecurityManager securityManager) {
-        assertRealmSecurityManager(securityManager);
-        return ((RealmSecurityManager) securityManager).getRealms();
-    }
-
-    protected Map<String, ?> createDefaults(Ini ini, Ini.Section mainSection) {
-        Map<String, Object> defaults = new LinkedHashMap<String, Object>();
-
-        SecurityManager securityManager = createDefaultInstance();
-        defaults.put(SECURITY_MANAGER_NAME, securityManager);
-
-        if (shouldImplicitlyCreateRealm(ini)) {
-            Realm realm = createRealm(ini);
-            if (realm != null) {
-                defaults.put(INI_REALM_NAME, realm);
-            }
-        }
-
-        return defaults;
-    }
-
-    private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) {
-        this.builder = new ReflectionBuilder(defaults);
-        return this.builder.buildObjects(section);
-    }
-
-    private void addToRealms(Collection<Realm> realms, RealmFactory factory) {
-        LifecycleUtils.init(factory);
-        Collection<Realm> factoryRealms = factory.getRealms();
-        if (!CollectionUtils.isEmpty(realms)) {
-            realms.addAll(factoryRealms);
-        }
-    }
-
-    private Collection<Realm> getRealms(Map<String, ?> instances) {
-
-        //realms and realm factory might have been created - pull them out first so we can
-        //initialize the securityManager:
-        List<Realm> realms = new ArrayList<Realm>();
-
-        //iterate over the map entries to pull out the realm factory(s):
-        for (Map.Entry<String, ?> entry : instances.entrySet()) {
-
-            String name = entry.getKey();
-            Object value = entry.getValue();
-
-            if (value instanceof RealmFactory) {
-                addToRealms(realms, (RealmFactory) value);
-            } else if (value instanceof Realm) {
-                Realm realm = (Realm) value;
-                //set the name if null:
-                String existingName = realm.getName();
-                if (existingName == null || existingName.startsWith(realm.getClass().getName())) {
-                    if (realm instanceof Nameable) {
-                        ((Nameable) realm).setName(name);
-                        log.debug("Applied name '{}' to Nameable realm instance {}", name, realm);
-                    } else {
-                        log.info("Realm does not implement the {} interface.  Configured name will not be applied.",
-                                Nameable.class.getName());
-                    }
-                }
-                realms.add(realm);
-            }
-        }
-
-        return realms;
-    }
-
-    private void assertRealmSecurityManager(SecurityManager securityManager) {
-        if (securityManager == null) {
-            throw new NullPointerException("securityManager instance cannot be null");
-        }
-        if (!(securityManager instanceof RealmSecurityManager)) {
-            String msg = "securityManager instance is not a " + RealmSecurityManager.class.getName() +
-                    " instance.  This is required to access or configure realms on the instance.";
-            throw new ConfigurationException(msg);
-        }
-    }
-
-    protected void applyRealmsToSecurityManager(Collection<Realm> realms, SecurityManager securityManager) {
-        assertRealmSecurityManager(securityManager);
-        ((RealmSecurityManager) securityManager).setRealms(realms);
-    }
-
-    /**
-     * Returns {@code true} if the Ini contains account data and a {@code Realm} should be implicitly
-     * {@link #createRealm(Ini) created} to reflect the account data, {@code false} if no realm should be implicitly
-     * created.
-     *
-     * @param ini the Ini instance to inspect for account data resulting in an implicitly created realm.
-     * @return {@code true} if the Ini contains account data and a {@code Realm} should be implicitly
-     *         {@link #createRealm(Ini) created} to reflect the account data, {@code false} if no realm should be
-     *         implicitly created.
-     */
-    protected boolean shouldImplicitlyCreateRealm(Ini ini) {
-        return !CollectionUtils.isEmpty(ini) &&
-                (!CollectionUtils.isEmpty(ini.getSection(IniRealm.ROLES_SECTION_NAME)) ||
-                        !CollectionUtils.isEmpty(ini.getSection(IniRealm.USERS_SECTION_NAME)));
-    }
-
-    /**
-     * Creates a {@code Realm} from the Ini instance containing account data.
-     *
-     * @param ini the Ini instance from which to acquire the account data.
-     * @return a new Realm instance reflecting the account data discovered in the {@code Ini}.
-     */
-    protected Realm createRealm(Ini ini) {
-        IniRealm realm = new IniRealm(ini);
-        realm.setName(INI_REALM_NAME);
-        return realm;
-    }
+/*
+ * 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.config;
+
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.mgt.RealmSecurityManager;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.realm.Realm;
+import org.apache.shiro.realm.RealmFactory;
+import org.apache.shiro.realm.text.IniRealm;
+import org.apache.shiro.util.CollectionUtils;
+import org.apache.shiro.util.Factory;
+import org.apache.shiro.util.LifecycleUtils;
+import org.apache.shiro.util.Nameable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+/**
+ * A {@link Factory} that creates {@link SecurityManager} instances based on {@link Ini} configuration.
+ *
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
+ * @since 1.0
+ */
+public class IniSecurityManagerFactory extends IniFactorySupport<SecurityManager> {
+
+    public static final String MAIN_SECTION_NAME = "main";
+
+    public static final String SECURITY_MANAGER_NAME = "securityManager";
+    public static final String INI_REALM_NAME = "iniRealm";
+
+    private static transient final Logger log = LoggerFactory.getLogger(IniSecurityManagerFactory.class);
+
+    private ReflectionBuilder builder;
+
+    /**
+     * Creates a new instance.  See the {@link #getInstance()} JavaDoc for detailed explanation of how an INI
+     * source will be resolved to use to build the instance.
+     */
+    public IniSecurityManagerFactory() {
+    }
+
+    public IniSecurityManagerFactory(Ini config) {
+        setIni(config);
+    }
+
+    public IniSecurityManagerFactory(String iniResourcePath) {
+        this(Ini.fromResourcePath(iniResourcePath));
+    }
+
+    public Map<String, ?> getBeans() {
+        return this.builder != null ? Collections.unmodifiableMap(builder.getObjects()) : null;
+    }
+
+    private SecurityManager getSecurityManagerBean() {
+        return builder.getBean(SECURITY_MANAGER_NAME, SecurityManager.class);
+    }
+
+    protected SecurityManager createDefaultInstance() {
+        return new DefaultSecurityManager();
+    }
+
+    protected SecurityManager createInstance(Ini ini) {
+        if (CollectionUtils.isEmpty(ini)) {
+            throw new NullPointerException("Ini argument cannot be null or empty.");
+        }
+        SecurityManager securityManager = createSecurityManager(ini);
+        if (securityManager == null) {
+            String msg = SecurityManager.class + " instance cannot be null.";
+            throw new ConfigurationException(msg);
+        }
+        return securityManager;
+    }
+
+    private SecurityManager createSecurityManager(Ini ini) {
+        Ini.Section mainSection = ini.getSection(MAIN_SECTION_NAME);
+        if (CollectionUtils.isEmpty(mainSection)) {
+            //try the default:
+            mainSection = ini.getSection(Ini.DEFAULT_SECTION_NAME);
+        }
+        return createSecurityManager(ini, mainSection);
+    }
+
+    protected boolean isAutoApplyRealms(SecurityManager securityManager) {
+        boolean autoApply = true;
+        if (securityManager instanceof RealmSecurityManager) {
+            //only apply realms if they haven't been explicitly set by the user:
+            RealmSecurityManager realmSecurityManager = (RealmSecurityManager) securityManager;
+            Collection<Realm> realms = realmSecurityManager.getRealms();
+            if (!CollectionUtils.isEmpty(realms)) {
+                log.info("Realms have been explicitly set on the SecurityManager instance - auto-setting of " +
+                        "realms will not occur.");
+                autoApply = false;
+            }
+        }
+        return autoApply;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private SecurityManager createSecurityManager(Ini ini, Ini.Section mainSection) {
+
+        Map<String, ?> defaults = createDefaults(ini, mainSection);
+        Map<String, ?> objects = buildInstances(mainSection, defaults);
+
+        SecurityManager securityManager = getSecurityManagerBean();
+
+        boolean autoApplyRealms = isAutoApplyRealms(securityManager);
+
+        if (autoApplyRealms) {
+            //realms and realm factory might have been created - pull them out first so we can
+            //initialize the securityManager:
+            Collection<Realm> realms = getRealms(objects);
+            //set them on the SecurityManager
+            if (!CollectionUtils.isEmpty(realms)) {
+                applyRealmsToSecurityManager(realms, securityManager);
+            }
+        }
+
+        initRealms(securityManager);
+
+        return securityManager;
+    }
+
+    private void initRealms(SecurityManager securityManager) {
+        Collection<Realm> realms = getRealms(securityManager);
+        if (!CollectionUtils.isEmpty(realms)) {
+            LifecycleUtils.init(realms);
+        }
+    }
+
+    private Collection<Realm> getRealms(SecurityManager securityManager) {
+        assertRealmSecurityManager(securityManager);
+        return ((RealmSecurityManager) securityManager).getRealms();
+    }
+
+    protected Map<String, ?> createDefaults(Ini ini, Ini.Section mainSection) {
+        Map<String, Object> defaults = new LinkedHashMap<String, Object>();
+
+        SecurityManager securityManager = createDefaultInstance();
+        defaults.put(SECURITY_MANAGER_NAME, securityManager);
+
+        if (shouldImplicitlyCreateRealm(ini)) {
+            Realm realm = createRealm(ini);
+            if (realm != null) {
+                defaults.put(INI_REALM_NAME, realm);
+            }
+        }
+
+        return defaults;
+    }
+
+    private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) {
+        this.builder = new ReflectionBuilder(defaults);
+        return this.builder.buildObjects(section);
+    }
+
+    private void addToRealms(Collection<Realm> realms, RealmFactory factory) {
+        LifecycleUtils.init(factory);
+        Collection<Realm> factoryRealms = factory.getRealms();
+        if (!CollectionUtils.isEmpty(realms)) {
+            realms.addAll(factoryRealms);
+        }
+    }
+
+    private Collection<Realm> getRealms(Map<String, ?> instances) {
+
+        //realms and realm factory might have been created - pull them out first so we can
+        //initialize the securityManager:
+        List<Realm> realms = new ArrayList<Realm>();
+
+        //iterate over the map entries to pull out the realm factory(s):
+        for (Map.Entry<String, ?> entry : instances.entrySet()) {
+
+            String name = entry.getKey();
+            Object value = entry.getValue();
+
+            if (value instanceof RealmFactory) {
+                addToRealms(realms, (RealmFactory) value);
+            } else if (value instanceof Realm) {
+                Realm realm = (Realm) value;
+                //set the name if null:
+                String existingName = realm.getName();
+                if (existingName == null || existingName.startsWith(realm.getClass().getName())) {
+                    if (realm instanceof Nameable) {
+                        ((Nameable) realm).setName(name);
+                        log.debug("Applied name '{}' to Nameable realm instance {}", name, realm);
+                    } else {
+                        log.info("Realm does not implement the {} interface.  Configured name will not be applied.",
+                                Nameable.class.getName());
+                    }
+                }
+                realms.add(realm);
+            }
+        }
+
+        return realms;
+    }
+
+    private void assertRealmSecurityManager(SecurityManager securityManager) {
+        if (securityManager == null) {
+            throw new NullPointerException("securityManager instance cannot be null");
+        }
+        if (!(securityManager instanceof RealmSecurityManager)) {
+            String msg = "securityManager instance is not a " + RealmSecurityManager.class.getName() +
+                    " instance.  This is required to access or configure realms on the instance.";
+            throw new ConfigurationException(msg);
+        }
+    }
+
+    protected void applyRealmsToSecurityManager(Collection<Realm> realms, SecurityManager securityManager) {
+        assertRealmSecurityManager(securityManager);
+        ((RealmSecurityManager) securityManager).setRealms(realms);
+    }
+
+    /**
+     * Returns {@code true} if the Ini contains account data and a {@code Realm} should be implicitly
+     * {@link #createRealm(Ini) created} to reflect the account data, {@code false} if no realm should be implicitly
+     * created.
+     *
+     * @param ini the Ini instance to inspect for account data resulting in an implicitly created realm.
+     * @return {@code true} if the Ini contains account data and a {@code Realm} should be implicitly
+     *         {@link #createRealm(Ini) created} to reflect the account data, {@code false} if no realm should be
+     *         implicitly created.
+     */
+    protected boolean shouldImplicitlyCreateRealm(Ini ini) {
+        return !CollectionUtils.isEmpty(ini) &&
+                (!CollectionUtils.isEmpty(ini.getSection(IniRealm.ROLES_SECTION_NAME)) ||
+                        !CollectionUtils.isEmpty(ini.getSection(IniRealm.USERS_SECTION_NAME)));
+    }
+
+    /**
+     * Creates a {@code Realm} from the Ini instance containing account data.
+     *
+     * @param ini the Ini instance from which to acquire the account data.
+     * @return a new Realm instance reflecting the account data discovered in the {@code Ini}.
+     */
+    protected Realm createRealm(Ini ini) {
+        IniRealm realm = new IniRealm(ini);
+        realm.setName(INI_REALM_NAME);
+        return realm;
+    }
 }
\ No newline at end of file

Propchange: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/config/IniSecurityManagerFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native