001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019 package org.apache.shiro.config;
020
021 import org.apache.shiro.io.ResourceUtils;
022 import org.apache.shiro.util.AbstractFactory;
023 import org.apache.shiro.util.CollectionUtils;
024 import org.apache.shiro.util.Factory;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027
028 /**
029 * Base support class for {@link Factory} implementations that generate their instance(s) based on
030 * {@link Ini} configuration.
031 *
032 * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
033 * @since 1.0
034 */
035 public abstract class IniFactorySupport<T> extends AbstractFactory<T> {
036
037 public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:shiro.ini";
038
039 private static transient final Logger log = LoggerFactory.getLogger(IniFactorySupport.class);
040
041 private Ini ini;
042
043 protected IniFactorySupport() {
044 }
045
046 protected IniFactorySupport(Ini ini) {
047 this.ini = ini;
048 }
049
050 public Ini getIni() {
051 return ini;
052 }
053
054 public void setIni(Ini ini) {
055 this.ini = ini;
056 }
057
058 /**
059 * Returns a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
060 * the file does not exist.
061 *
062 * @return a new Ini instance created from the default {@code classpath:shiro.ini} file, or {@code null} if
063 * the file does not exist.
064 */
065 public static Ini loadDefaultClassPathIni() {
066 Ini ini = null;
067 if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
068 log.debug("Found shiro.ini at the root of the classpath.");
069 ini = new Ini();
070 ini.loadFromPath(DEFAULT_INI_RESOURCE_PATH);
071 if (CollectionUtils.isEmpty(ini)) {
072 log.warn("shiro.ini found at the root of the classpath, but it did not contain any data.");
073 }
074 }
075 return ini;
076 }
077
078 /**
079 * Tries to resolve the Ini instance to use for configuration. This implementation functions as follows:
080 * <ol>
081 * <li>The {@code Ini} instance returned from {@link #getIni()} will be returned if it is not null or empty.</li>
082 * <li>If {@link #getIni()} is {@code null} or empty, this implementation will attempt to find and load the
083 * {@link #loadDefaultClassPathIni() default class path Ini}.</li>
084 * <li>If neither of the two attempts above returns an instance, {@code null} is returned</li>
085 * </ol>
086 *
087 * @return the Ini instance to use for configuration.
088 */
089 protected Ini resolveIni() {
090 Ini ini = getIni();
091 if (CollectionUtils.isEmpty(ini)) {
092 log.debug("Null or empty Ini instance. Falling back to the default {} file.", DEFAULT_INI_RESOURCE_PATH);
093 ini = loadDefaultClassPathIni();
094 }
095 return ini;
096 }
097
098 /**
099 * Creates a new object instance by using a configured INI source. This implementation functions as follows:
100 * <ol>
101 * <li>{@link #resolveIni() Resolve} the {@code Ini} source to use for configuration.</li>
102 * <li>If there was no resolved Ini source, create and return a simple default instance via the
103 * {@link #createDefaultInstance()} method.</li>
104 * </ol>
105 *
106 * @return a new {@code SecurityManager} instance by using a configured INI source.
107 */
108 public T createInstance() {
109 Ini ini = resolveIni();
110
111 T instance;
112
113 if (CollectionUtils.isEmpty(ini)) {
114 log.debug("No populated Ini available. Creating a default instance.");
115 instance = createDefaultInstance();
116 if (instance == null) {
117 String msg = getClass().getName() + " implementation did not return a default instance in " +
118 "the event of a null/empty Ini configuration. This is required to support the " +
119 "Factory interface. Please check your implementation.";
120 throw new IllegalStateException(msg);
121 }
122 } else {
123 log.debug("Creating instance from Ini [" + ini + "]");
124 instance = createInstance(ini);
125 if (instance == null) {
126 String msg = getClass().getName() + " implementation did not return a constructed instance from " +
127 "the createInstance(Ini) method implementation.";
128 throw new IllegalStateException(msg);
129 }
130 }
131
132 return instance;
133 }
134
135 protected abstract T createInstance(Ini ini);
136
137 protected abstract T createDefaultInstance();
138 }