Home » geronimo-2.2-source-release » org.apache.geronimo.security.deployment » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   package org.apache.geronimo.security.deployment;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Collection;
   21   import java.util.HashMap;
   22   import java.util.HashSet;
   23   import java.util.List;
   24   import java.util.Map;
   25   import java.util.Set;
   26   
   27   import javax.xml.namespace.QName;
   28   
   29   import org.apache.geronimo.common.DeploymentException;
   30   import org.apache.geronimo.deployment.DeploymentContext;
   31   import org.apache.geronimo.deployment.service.SingleGBeanBuilder;
   32   import org.apache.geronimo.deployment.service.XmlAttributeBuilder;
   33   import org.apache.geronimo.deployment.service.XmlReferenceBuilder;
   34   import org.apache.geronimo.deployment.xbeans.PatternType;
   35   import org.apache.geronimo.deployment.xbeans.XmlAttributeType;
   36   import org.apache.geronimo.gbean.AbstractName;
   37   import org.apache.geronimo.gbean.AbstractNameQuery;
   38   import org.apache.geronimo.gbean.GBeanData;
   39   import org.apache.geronimo.gbean.GBeanInfo;
   40   import org.apache.geronimo.gbean.GBeanInfoBuilder;
   41   import org.apache.geronimo.gbean.GReferenceInfo;
   42   import org.apache.geronimo.gbean.ReferenceMap;
   43   import org.apache.geronimo.gbean.ReferencePatterns;
   44   import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
   45   import org.apache.geronimo.kernel.Kernel;
   46   import org.apache.geronimo.kernel.Naming;
   47   import org.apache.geronimo.security.SecurityNames;
   48   import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
   49   import org.apache.geronimo.security.jaas.LoginModuleControlFlag;
   50   import org.apache.geronimo.security.jaas.LoginModuleControlFlagEditor;
   51   import org.apache.geronimo.security.jaas.LoginModuleGBean;
   52   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerAbstractLoginModuleType;
   53   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginConfigDocument;
   54   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginConfigType;
   55   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginModuleRefType;
   56   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerLoginModuleType;
   57   import org.apache.geronimo.xbeans.geronimo.loginconfig.GerOptionType;
   58   import org.apache.xmlbeans.XmlCursor;
   59   import org.apache.xmlbeans.XmlObject;
   60   import org.apache.xmlbeans.XmlOptions;
   61   
   62   
   63   /**
   64    * @version $Rev: 698441 $ $Date: 2008-09-24 00:10:08 -0700 (Wed, 24 Sep 2008) $
   65    */
   66   public class LoginConfigBuilder implements XmlReferenceBuilder {
   67       public static final String LOGIN_CONFIG_NAMESPACE = GerLoginConfigDocument.type.getDocumentElementName().getNamespaceURI();
   68       private static final QName LOGIN_MODULE_QNAME = new QName(LOGIN_CONFIG_NAMESPACE, "login-module");
   69       private static final QName SERVER_SIDE_QNAME = new QName(null, "server-side");
   70   
   71       private final Naming naming;
   72       private final Map xmlAttributeBuilderMap;
   73   
   74       public LoginConfigBuilder(Kernel kernel, Collection xmlAttributeBuilderMap) {
   75           this(kernel.getNaming(), xmlAttributeBuilderMap);
   76       }
   77   
   78       public LoginConfigBuilder(Naming naming, Collection xmlAttributeBuilders) {
   79           this.naming = naming;
   80           if (xmlAttributeBuilders != null) {
   81               ReferenceMap.Key key = new ReferenceMap.Key() {
   82   
   83                   public Object getKey(Object object) {
   84                       return ((XmlAttributeBuilder) object).getNamespace();
   85                   }
   86               };
   87               xmlAttributeBuilderMap = new ReferenceMap(xmlAttributeBuilders, new HashMap(), key);
   88           } else {
   89               xmlAttributeBuilderMap = new HashMap();
   90           }
   91       }
   92   
   93       public String getNamespace() {
   94           return LOGIN_CONFIG_NAMESPACE;
   95       }
   96   
   97       public ReferencePatterns getReferences(XmlObject xmlObject, DeploymentContext context, AbstractName parentName, ClassLoader classLoader) throws DeploymentException {
   98           List<GBeanData> uses = new ArrayList<GBeanData>();
   99           GerLoginConfigType loginConfig = (GerLoginConfigType) xmlObject.copy().changeType(GerLoginConfigType.type);
  100           XmlCursor xmlCursor = loginConfig.newCursor();
  101           xmlCursor.push();
  102           try {
  103               //munge xml
  104               if (xmlCursor.toChild(LOGIN_MODULE_QNAME)) {
  105                   do {
  106                       xmlCursor.removeAttribute(SERVER_SIDE_QNAME);
  107                   } while (xmlCursor.toNextSibling(LOGIN_MODULE_QNAME));
  108               }
  109               xmlCursor.pop();
  110               //validate
  111               XmlOptions xmlOptions = new XmlOptions();
  112               xmlOptions.setLoadLineNumbers();
  113               Collection errors = new ArrayList();
  114               xmlOptions.setErrorListener(errors);
  115               if (!loginConfig.validate(xmlOptions)) {
  116                   throw new DeploymentException("Invalid login configuration:\n" + errors + "\nDescriptor: " + loginConfig.toString());
  117               }
  118               //find the login modules
  119               Set<String> loginModuleNames = new HashSet<String>();
  120               boolean atStart = true;
  121               while ((atStart && xmlCursor.toFirstChild()) || (!atStart && xmlCursor.toNextSibling())) {
  122                   atStart = false;
  123                   XmlObject child = xmlCursor.getObject();
  124                   GerAbstractLoginModuleType abstractLoginModule = (GerAbstractLoginModuleType) child;
  125                   String controlFlag = abstractLoginModule.getControlFlag().toString();
  126                   boolean wrapPrincipals = (abstractLoginModule.isSetWrapPrincipals() && abstractLoginModule.getWrapPrincipals());
  127                   ReferencePatterns loginModuleReferencePatterns;
  128                   String name;
  129                   if (abstractLoginModule instanceof GerLoginModuleRefType) {
  130                       GerLoginModuleRefType loginModuleRef = (GerLoginModuleRefType) abstractLoginModule;
  131                       PatternType patternType = loginModuleRef.getPattern();
  132                       AbstractNameQuery loginModuleNameQuery = SingleGBeanBuilder.buildAbstractNameQuery(patternType, USE_REFERENCE_INFO);
  133                       loginModuleReferencePatterns = new ReferencePatterns(loginModuleNameQuery);
  134                       name = (String) loginModuleNameQuery.getName().get("name");
  135                       if (name == null) {
  136                           throw new DeploymentException("You must specify the name of the login module in the login module ref " + patternType);
  137                       }
  138   //TODO configid reinstate this check for duplicate domain names
  139   //                    try
  140   //                    {
  141   //                        String loginDomain = (String) context.getAttribute(loginModuleName, "loginDomainName");
  142   //                        if (!loginModuleNames.add(loginDomain))
  143   //                        {
  144   //                            throw new DeploymentException("Security realm contains two login domains called '" + loginDomain + "'");
  145   //                        }
  146   //                    }
  147   //                    catch (DeploymentException e)
  148   //                    {
  149   //                        throw e;
  150   //                    }
  151   //                    catch (Exception e)
  152   //                    {
  153   //                        throw new DeploymentException("Unable to create reference to login module " + name, e);
  154   //                    }
  155                   } else if (abstractLoginModule instanceof GerLoginModuleType) {
  156                       //create the LoginModuleGBean also
  157                       AbstractName loginModuleName;
  158   
  159                       GerLoginModuleType loginModule = (GerLoginModuleType) abstractLoginModule;
  160                       name = trim(loginModule.getLoginDomainName());
  161                       if (!loginModuleNames.add(name)) {
  162                           throw new DeploymentException("Security realm contains two login domains called '" + name + "'");
  163                       }
  164                       String className = trim(loginModule.getLoginModuleClass());
  165                       Map<String, Object> options = new HashMap<String, Object>();
  166                       GerOptionType[] optionArray = loginModule.getOptionArray();
  167                       for (GerOptionType gerOptionType : optionArray) {
  168                           String key = gerOptionType.getName();
  169                           String value = trim(gerOptionType.getStringValue());
  170                           options.put(key, value);
  171                       }
  172                       XmlAttributeType[] xmlOptionArray = loginModule.getXmlOptionArray();
  173                       if (xmlOptionArray != null) {
  174                           for (XmlAttributeType xmlOptionType : xmlOptionArray) {
  175                               String key = xmlOptionType.getName().trim();
  176                               XmlObject[] anys = xmlOptionType.selectChildren(XmlAttributeType.type.qnameSetForWildcardElements());
  177                               if (anys.length != 1) {
  178                                   throw new DeploymentException("Unexpected count of xs:any elements in xml-attribute " + anys.length + " qnameset: " + XmlAttributeType.type.qnameSetForWildcardElements());
  179                               }
  180                               String namespace = xmlObject.getDomNode().getNamespaceURI();
  181                               XmlAttributeBuilder builder = (XmlAttributeBuilder) xmlAttributeBuilderMap.get(namespace);
  182                               if (builder == null) {
  183                                   throw new DeploymentException("No attribute builder deployed for namespace: " + namespace);
  184                               }
  185                               Object value = builder.getValue(xmlObject, null, classLoader);
  186                               options.put(key, value);
  187                           }
  188                       }
  189                       loginModuleName = naming.createChildName(parentName, name, SecurityNames.LOGIN_MODULE);
  190                       loginModuleReferencePatterns = new ReferencePatterns(loginModuleName);
  191                       GBeanData loginModuleGBeanData = new GBeanData(loginModuleName, LoginModuleGBean.GBEAN_INFO);
  192                       loginModuleGBeanData.setAttribute("loginDomainName", name);
  193                       loginModuleGBeanData.setAttribute("loginModuleClass", className);
  194                       loginModuleGBeanData.setAttribute("options", options);
  195                       loginModuleGBeanData.setAttribute("wrapPrincipals", wrapPrincipals);
  196   
  197                       context.addGBean(loginModuleGBeanData);
  198                   } else {
  199                       throw new DeploymentException("Unknown abstract login module type: " + abstractLoginModule.getClass());
  200                   }
  201                   AbstractName thisName;
  202                   thisName = naming.createChildName(parentName, name, "LoginModuleUse");
  203                   GBeanData loginModuleUseGBeanData = new GBeanData(thisName, JaasLoginModuleUse.GBEAN_INFO);
  204                   loginModuleUseGBeanData.setAttribute("controlFlag", getControlFlag(controlFlag));
  205                   loginModuleUseGBeanData.setReferencePatterns("LoginModule", loginModuleReferencePatterns);
  206                   uses.add(loginModuleUseGBeanData);
  207               }
  208               for (int i = uses.size() - 1; i >= 0; i--) {
  209                   GBeanData data = uses.get(i);
  210                   if (i > 0) {
  211                       uses.get(i - 1).setReferencePattern("Next", data.getAbstractName());
  212                   }
  213                   context.addGBean(data);
  214               }
  215           } catch (GBeanAlreadyExistsException e) {
  216               throw new DeploymentException(e);
  217           } finally {
  218               xmlCursor.dispose();
  219           }
  220           return uses.size() == 0 ? null : new ReferencePatterns(uses.get(0).getAbstractName());
  221       }
  222   
  223       private LoginModuleControlFlag getControlFlag(String controlFlag) {
  224           LoginModuleControlFlagEditor editor = new LoginModuleControlFlagEditor();
  225           editor.setAsText(controlFlag);
  226           return (LoginModuleControlFlag) editor.getValue();
  227       }
  228   
  229       private String trim(String string) {
  230           return string == null ? null : string.trim();
  231       }
  232   
  233       public static final GBeanInfo GBEAN_INFO;
  234   
  235       private static final GReferenceInfo USE_REFERENCE_INFO;
  236   
  237       static {
  238           GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(LoginConfigBuilder.class, "XmlReferenceBuilder");
  239           infoBuilder.addAttribute("kernel", Kernel.class, false, false);
  240           infoBuilder.addReference("xmlAttributeBuilders", XmlAttributeBuilder.class, "XmlAttributeBuilder");
  241           infoBuilder.setConstructor(new String[]{"kernel", "xmlAttributeBuilders"});
  242           infoBuilder.addInterface(XmlReferenceBuilder.class);
  243           GBEAN_INFO = infoBuilder.getBeanInfo();
  244   
  245           Set<GReferenceInfo> referenceInfos = JaasLoginModuleUse.GBEAN_INFO.getReferences();
  246           GReferenceInfo found = null;
  247           for (GReferenceInfo testReferenceInfo : referenceInfos) {
  248               String testRefName = testReferenceInfo.getName();
  249               if (testRefName.equals("LoginModule")) {
  250                   found = testReferenceInfo;
  251                   break;
  252               }
  253           }
  254           if (found == null) {
  255               throw new RuntimeException("Someone changed the gbeaninfo on JaasLoginModuleUse");
  256           }
  257           USE_REFERENCE_INFO = found;
  258   
  259       }
  260   
  261       public static GBeanInfo getGBeanInfo() {
  262           return GBEAN_INFO;
  263       }
  264   }

Home » geronimo-2.2-source-release » org.apache.geronimo.security.deployment » [javadoc | source]