/** * * Copyright 2005 The Apache Software Foundation * * Licensed 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.geronimo.security.deployment; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Properties; import java.util.Set; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import org.apache.geronimo.common.DeploymentException; import org.apache.geronimo.deployment.DeploymentContext; import org.apache.geronimo.deployment.service.XmlReferenceBuilder; import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.gbean.GBeanInfo; import org.apache.geronimo.gbean.GBeanInfoBuilder; import org.apache.geronimo.j2ee.j2eeobjectnames.J2eeContext; import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; import org.apache.geronimo.security.jaas.JaasLoginModuleUse; import org.apache.geronimo.security.jaas.LoginModuleGBean; import org.apache.geronimo.xbeans.geronimo.loginconfig.GerAbstractLoginModuleType; import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginConfigType; import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginModuleRefType; import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginModuleType; import org.apache.geronimo.xbeans.geronimo.loginconfig.GerOptionType; import org.apache.xmlbeans.XmlCursor; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlOptions; /** * @version $Rev$ $Date$ */ public class LoginConfigBuilder implements XmlReferenceBuilder { public static final String LOGIN_CONFIG_NAMESPACE = "http://geronimo.apache.org/xml/ns/loginconfig-1.0"; public String getNamespace() { return LOGIN_CONFIG_NAMESPACE; } public Set getReferences(XmlObject xmlObject, DeploymentContext context, J2eeContext j2eeContext, ClassLoader classLoader) throws DeploymentException { GerLoginConfigType loginConfig = (GerLoginConfigType) xmlObject.copy().changeType(GerLoginConfigType.type); XmlOptions xmlOptions = new XmlOptions(); xmlOptions.setLoadLineNumbers(); Collection errors = new ArrayList(); xmlOptions.setErrorListener(errors); if (!loginConfig.validate(xmlOptions)) { throw new DeploymentException("Invalid login configuration:\n" + errors + "\nDescriptor: " + loginConfig.toString()); } XmlCursor xmlCursor = loginConfig.newCursor(); List uses = new ArrayList(); Set loginModuleNames = new HashSet(); try { boolean atStart = true; while ((atStart && xmlCursor.toFirstChild()) || (!atStart && xmlCursor.toNextSibling())) { atStart = false; XmlObject child = xmlCursor.getObject(); GerAbstractLoginModuleType abstractLoginModule = (GerAbstractLoginModuleType) child; String controlFlag = abstractLoginModule.getControlFlag().toString(); boolean wrapPrincipals = (abstractLoginModule.isSetWrapPrincipals() && abstractLoginModule.getWrapPrincipals()); ObjectName loginModuleName; String name; if (abstractLoginModule instanceof GerLoginModuleRefType) { GerLoginModuleRefType loginModuleRef = (GerLoginModuleRefType) abstractLoginModule; String domain = trim(loginModuleRef.getDomain()); String server = trim(loginModuleRef.getServer()); String application = trim(loginModuleRef.getApplication()); String module = trim(loginModuleRef.getModule()); String type = trim(loginModuleRef.getType()); if (type == null) { type = NameFactory.LOGIN_MODULE; } name = trim(loginModuleRef.getName()); try { loginModuleName = NameFactory.getComponentName(domain, server, application, module, name, type, j2eeContext); } catch (MalformedObjectNameException e) { throw new DeploymentException("cannot construct login module name from parts,", e); } try { String loginDomain = (String) context.getAttribute(loginModuleName, "loginDomainName"); if (!loginModuleNames.add(loginDomain)) { throw new DeploymentException("Security realm contains two login domains called '" + loginDomain + "'"); } } catch (DeploymentException e) { throw e; } catch (Exception e) { throw new DeploymentException("Unable to create reference to login module " + name, e); } } else if (abstractLoginModule instanceof GerLoginModuleType) { //create the LoginModuleGBean also name = null; loginModuleName = null; GerLoginModuleType loginModule = (GerLoginModuleType) abstractLoginModule; name = trim(loginModule.getLoginDomainName()); if (!loginModuleNames.add(name)) { throw new DeploymentException("Security realm contains two login domains called '" + name + "'"); } String className = trim(loginModule.getLoginModuleClass()); boolean serverSide = loginModule.getServerSide(); Properties options = new Properties(); GerOptionType[] optionArray = loginModule.getOptionArray(); for (int j = 0; j < optionArray.length; j++) { GerOptionType gerOptionType = optionArray[j]; String key = gerOptionType.getName(); String value = trim(gerOptionType.getStringValue()); options.setProperty(key, value); } try { loginModuleName = NameFactory.getComponentName(null, null, null, null, name, NameFactory.LOGIN_MODULE, j2eeContext); } catch (MalformedObjectNameException e) { throw new DeploymentException("cannot construct login module use name from parts,", e); } GBeanData loginModuleGBeanData = new GBeanData(loginModuleName, LoginModuleGBean.GBEAN_INFO); loginModuleGBeanData.setAttribute("loginDomainName", name); loginModuleGBeanData.setAttribute("loginModuleClass", className); loginModuleGBeanData.setAttribute("options", options); loginModuleGBeanData.setAttribute("serverSide", new Boolean(serverSide)); loginModuleGBeanData.setAttribute("wrapPrincipals", Boolean.valueOf(wrapPrincipals)); context.addGBean(loginModuleGBeanData); } else { throw new DeploymentException("Unknown abstract login module type: " + abstractLoginModule.getClass()); } ObjectName thisName; try { thisName = NameFactory.getComponentName(null, null, null, null, name, "LoginModuleUse", j2eeContext); } catch (MalformedObjectNameException e) { throw new DeploymentException("cannot construct login module use name from parts,", e); } GBeanData loginModuleUseGBeanData = new GBeanData(thisName, JaasLoginModuleUse.GBEAN_INFO); loginModuleUseGBeanData.setAttribute("controlFlag", controlFlag); loginModuleUseGBeanData.setReferencePattern("LoginModule", loginModuleName); uses.add(loginModuleUseGBeanData); } for (int i = uses.size() - 1; i >= 0; i--) { GBeanData data = (GBeanData) uses.get(i); if (i > 0) { ((GBeanData) uses.get(i - 1)).setReferencePattern("Next", data.getName()); } context.addGBean(data); } } finally { xmlCursor.dispose(); } return uses.size() == 0 ? Collections.EMPTY_SET : Collections.singleton(((GBeanData) uses.get(0)).getName()); } private String trim(String string) { return string == null ? null : string.trim(); } public static final GBeanInfo GBEAN_INFO; static { GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(LoginConfigBuilder.class, "XmlReferenceBuilder"); infoBuilder.addInterface(XmlReferenceBuilder.class); GBEAN_INFO = infoBuilder.getBeanInfo(); } public static GBeanInfo getGBeanInfo() { return GBEAN_INFO; } }