View Javadoc

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