blob: 94a68861161811d074d6a58124722affebd16db3 [file] [log] [blame]
/*
* 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.ki.config;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ki.KiException;
import org.apache.ki.io.IniResource;
import org.apache.ki.io.ResourceUtils;
import org.apache.ki.mgt.DefaultSecurityManager;
import org.apache.ki.mgt.RealmSecurityManager;
import org.apache.ki.mgt.SecurityManager;
import org.apache.ki.realm.Realm;
import org.apache.ki.realm.RealmFactory;
import org.apache.ki.util.LifecycleUtils;
/**
* A Configuration based on the <a href="http://en.wikipedia.org/wiki/INI_file">.ini format</a>.
*
* @author Les Hazlewood
* @author Jeremy Haile
* @since 0.9
*/
public class IniConfiguration extends TextConfiguration {
//TODO - complete JavaDoc
private static final Logger log = LoggerFactory.getLogger(IniConfiguration.class);
public static final String DEFAULT_INI_RESOURCE_PATH = "classpath:ki.ini";
public static final String MAIN = "main";
public static final String SESSION_MODE_PROPERTY_NAME = "sessionMode";
protected String configUrl;
protected IniResource iniResource;
protected boolean ignoreResourceNotFound = false;
public IniConfiguration() {
}
public IniConfiguration(String configBodyOrResourcePath) {
load(configBodyOrResourcePath);
}
public IniConfiguration(String configBodyOrResourcePath, String charsetName) {
try {
this.iniResource = new IniResource(configBodyOrResourcePath, charsetName);
process(this.iniResource);
} catch (Exception e) {
throw new ConfigurationException(e);
}
}
protected String getConfigUrl() {
return configUrl;
}
public void setConfigUrl(String configUrl) {
this.configUrl = configUrl;
}
public void init() throws KiException {
if (configUrl != null) {
if (ResourceUtils.resourceExists(configUrl)) {
load(configUrl);
} else {
if (ignoreResourceNotFound) {
log.debug("Ki resource [{}] not found. Ignoring since 'ignoreResourceNotFound' is true.", configUrl);
} else {
throw new ConfigurationException("Ki resource [" + configUrl + "] specified as a 'configUrl' " +
"cannot be found. If you want to fall back on default configuration specified " +
"via the 'config' parameter, then set 'ignoreResourceNotFound' to true.");
}
}
} else {
if (ResourceUtils.resourceExists(DEFAULT_INI_RESOURCE_PATH)) {
load(DEFAULT_INI_RESOURCE_PATH);
}
}
// Only call super.init() after we try loading from the configUrl first.
super.init();
SecurityManager sm = getSecurityManager();
if (sm == null) {
//no config specified, use the defaults:
sm = createDefaultSecurityManager();
setSecurityManager(sm);
}
}
protected void load(Reader r) throws ConfigurationException {
try {
this.iniResource = new IniResource(r);
process(this.iniResource);
} catch (Exception e) {
throw new ConfigurationException(e);
}
}
protected void load(Scanner s) throws ConfigurationException {
try {
this.iniResource = new IniResource(s);
process(this.iniResource);
} catch (Exception e) {
throw new ConfigurationException(e);
}
}
public void load(String path) throws ConfigurationException {
try {
this.iniResource = new IniResource(path);
process(this.iniResource);
} catch (Exception e) {
throw new ConfigurationException(e);
}
}
public void load(InputStream is) throws ConfigurationException {
try {
this.iniResource = new IniResource(is);
process(this.iniResource);
} catch (Exception e) {
throw new ConfigurationException(e);
}
}
protected void process(IniResource ini) {
processIni(ini.getSections());
}
protected void processIni(Map<String, Map<String, String>> sections) {
SecurityManager securityManager = createSecurityManager(sections);
if (securityManager == null) {
String msg = "A " + SecurityManager.class + " instance must be created at startup.";
throw new ConfigurationException(msg);
}
setSecurityManager(securityManager);
afterSecurityManagerSet(sections);
}
protected org.apache.ki.mgt.SecurityManager createDefaultSecurityManager() {
return newSecurityManagerInstance();
}
protected SecurityManager createSecurityManager(Map<String, Map<String, String>> sections) {
Map<String, String> mainSection = sections.get(MAIN);
return createSecurityManagerForSection(mainSection);
}
protected RealmSecurityManager newSecurityManagerInstance() {
return new DefaultSecurityManager();
}
@SuppressWarnings({"unchecked"})
protected SecurityManager createSecurityManagerForSection(Map<String, String> mainSection) {
Map<String, Object> defaults = new LinkedHashMap<String, Object>();
RealmSecurityManager securityManager = newSecurityManagerInstance();
defaults.put("securityManager", securityManager);
//convenient alias:
defaults.put("sm", securityManager);
ReflectionBuilder builder = new ReflectionBuilder(defaults);
Map<String, Object> objects = builder.buildObjects(mainSection);
//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, Object> entry : objects.entrySet()) {
String name = entry.getKey();
Object value = entry.getValue();
if (value instanceof RealmSecurityManager) {
securityManager = (RealmSecurityManager) value;
} else if (value instanceof RealmFactory) {
RealmFactory factory = (RealmFactory) value;
LifecycleUtils.init(factory);
Collection<Realm> factoryRealms = factory.getRealms();
if (factoryRealms != null && !factoryRealms.isEmpty()) {
realms.addAll(factoryRealms);
}
} 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())) {
try {
builder.applyProperty(realm, "name", name);
} catch (Exception ignored) {
}
}
realms.add(realm);
}
}
//set them on the SecurityManager
if (!realms.isEmpty()) {
securityManager.setRealms(realms);
LifecycleUtils.init(realms);
}
return securityManager;
}
protected void afterSecurityManagerSet(Map<String, Map<String, String>> sections) {
}
}