View Javadoc

1   /*
2    * Copyright 2007 University Corporation for Advanced Internet Development, Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package edu.internet2.middleware.shibboleth.common.config.attribute.resolver.dataConnector;
18  
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.StringTokenizer;
23  
24  import javax.xml.namespace.QName;
25  
26  import org.opensaml.xml.util.DatatypeHelper;
27  import org.opensaml.xml.util.XMLHelper;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  import org.springframework.beans.factory.config.BeanDefinition;
31  import org.springframework.beans.factory.config.RuntimeBeanReference;
32  import org.springframework.beans.factory.support.BeanDefinitionBuilder;
33  import org.springframework.beans.factory.xml.ParserContext;
34  import org.w3c.dom.Element;
35  
36  import edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.dataConnector.LdapDataConnector.AUTHENTICATION_TYPE;
37  import edu.internet2.middleware.shibboleth.common.attribute.resolver.provider.dataConnector.LdapDataConnector.SEARCH_SCOPE;
38  import edu.internet2.middleware.shibboleth.common.config.SpringConfigurationUtils;
39  
40  /** Spring bean definition parser for configuring an LDAP data connector. */
41  public class LdapDataConnectorBeanDefinitionParser extends BaseDataConnectorBeanDefinitionParser {
42  
43      /** LDAP data connector type name. */
44      public static final QName TYPE_NAME = new QName(DataConnectorNamespaceHandler.NAMESPACE, "LDAPDirectory");
45  
46      /** Class logger. */
47      private final Logger log = LoggerFactory.getLogger(LdapDataConnectorBeanDefinitionParser.class);
48  
49      /** {@inheritDoc} */
50      protected Class getBeanClass(Element element) {
51          return LdapDataConnectorFactoryBean.class;
52      }
53  
54      /** {@inheritDoc} */
55      protected void doParse(String pluginId, Element pluginConfig, Map<QName, List<Element>> pluginConfigChildren,
56              BeanDefinitionBuilder pluginBuilder, ParserContext parserContext) {
57          super.doParse(pluginId, pluginConfig, pluginConfigChildren, pluginBuilder, parserContext);
58  
59          String ldapURL = pluginConfig.getAttributeNS(null, "ldapURL");
60          log.debug("Data connector {} LDAP URL: {}", pluginId, ldapURL);
61          pluginBuilder.addPropertyValue("ldapUrl", ldapURL);
62  
63          String baseDN = pluginConfig.getAttributeNS(null, "baseDN");
64          log.debug("Data connector {} base DN: {}", pluginId, baseDN);
65          pluginBuilder.addPropertyValue("baseDN", baseDN);
66  
67          AUTHENTICATION_TYPE authnType = AUTHENTICATION_TYPE.SIMPLE;
68          if (pluginConfig.hasAttributeNS(null, "authenticationType")) {
69              authnType = AUTHENTICATION_TYPE.valueOf(pluginConfig.getAttributeNS(null, "authenticationType"));
70          }
71          log.debug("Data connector {} authentication type: {}", pluginId, authnType);
72          pluginBuilder.addPropertyValue("authenticationType", authnType);
73  
74          String principal = pluginConfig.getAttributeNS(null, "principal");
75          log.debug("Data connector {} principal: {}", pluginId, principal);
76          pluginBuilder.addPropertyValue("principal", principal);
77  
78          String credential = pluginConfig.getAttributeNS(null, "principalCredential");
79          pluginBuilder.addPropertyValue("principalCredential", credential);
80  
81          String filterTemplate = pluginConfigChildren.get(
82                  new QName(DataConnectorNamespaceHandler.NAMESPACE, "FilterTemplate")).get(0).getTextContent();
83          filterTemplate = DatatypeHelper.safeTrimOrNullString(filterTemplate);
84          log.debug("Data connector {} LDAP filter template: {}", pluginId, filterTemplate);
85          pluginBuilder.addPropertyValue("filterTemplate", filterTemplate);
86  
87          SEARCH_SCOPE searchScope = SEARCH_SCOPE.SUBTREE;
88          if (pluginConfig.hasAttributeNS(null, "searchScope")) {
89              searchScope = SEARCH_SCOPE.valueOf(pluginConfig.getAttributeNS(null, "searchScope"));
90          }
91          log.debug("Data connector {} search scope: {}", pluginId, searchScope);
92          pluginBuilder.addPropertyValue("searchScope", searchScope);
93  
94          String[] returnAttributes = processReturnAttributes(pluginConfigChildren.get(new QName(
95                  DataConnectorNamespaceHandler.NAMESPACE, "ReturnAttributes")));
96          log.debug("Data connector {} return attributes: {}", pluginId, returnAttributes);
97          pluginBuilder.addPropertyValue("returnAttributes", returnAttributes);
98  
99          Map<String, String> ldapProperties = processLDAPProperties(pluginConfigChildren.get(new QName(
100                 DataConnectorNamespaceHandler.NAMESPACE, "LDAPProperty")));
101         log.debug("Data connector {} LDAP properties: {}", pluginId, ldapProperties);
102         pluginBuilder.addPropertyValue("ldapProperties", ldapProperties);
103 
104         RuntimeBeanReference trustCredential = processCredential(pluginConfigChildren.get(new QName(
105                 DataConnectorNamespaceHandler.NAMESPACE, "StartTLSTrustCredential")), parserContext);
106         log.debug("Data connector {} using provided SSL/TLS trust material", pluginId);
107         pluginBuilder.addPropertyValue("trustCredential", trustCredential);
108 
109         RuntimeBeanReference connectionCredential = processCredential(pluginConfigChildren.get(new QName(
110                 DataConnectorNamespaceHandler.NAMESPACE, "StartTLSAuthenticationCredential")), parserContext);
111         log.debug("Data connector {} using provided SSL/TLS client authentication material", pluginId);
112         pluginBuilder.addPropertyValue("connectionCredential", connectionCredential);
113 
114         boolean useStartTLS = false;
115         if (pluginConfig.hasAttributeNS(null, "useStartTLS")) {
116             useStartTLS = XMLHelper.getAttributeValueAsBoolean(pluginConfig.getAttributeNodeNS(null, "useStartTLS"));
117         }
118         log.debug("Data connector {} use startTLS: {}", pluginId, useStartTLS);
119         pluginBuilder.addPropertyValue("useStartTLS", useStartTLS);
120 
121         int poolInitialSize = 0;
122         if (pluginConfig.hasAttributeNS(null, "poolInitialSize")) {
123             poolInitialSize = Integer.parseInt(pluginConfig.getAttributeNS(null, "poolInitialSize"));
124         }
125         log.debug("Data connector {} initial connection pool size: {}", pluginId, poolInitialSize);
126         pluginBuilder.addPropertyValue("poolInitialSize", poolInitialSize);
127 
128         int poolMaxIdleSize = 3;
129         if (pluginConfig.hasAttributeNS(null, "poolMaxIdleSize")) {
130             poolMaxIdleSize = Integer.parseInt(pluginConfig.getAttributeNS(null, "poolMaxIdleSize"));
131         }
132         log.debug("Data connector {} maximum idle connection pool size: {}", pluginId, poolMaxIdleSize);
133         pluginBuilder.addPropertyValue("poolMaxIdleSize", poolMaxIdleSize);
134 
135         int searchTimeLimit = 3000;
136         if (pluginConfig.hasAttributeNS(null, "searchTimeLimit")) {
137             searchTimeLimit = Integer.parseInt(pluginConfig.getAttributeNS(null, "searchTimeLimit"));
138         }
139         log.debug("Data connector {} search timeout: {}ms", pluginId, searchTimeLimit);
140         pluginBuilder.addPropertyValue("searchTimeLimit", searchTimeLimit);
141 
142         int maxResultSize = 1;
143         if (pluginConfig.hasAttributeNS(null, "maxResultSize")) {
144             maxResultSize = Integer.parseInt(pluginConfig.getAttributeNS(null, "maxResultSize"));
145         }
146         log.debug("Data connector {} max search result size: {}", pluginId, maxResultSize);
147         pluginBuilder.addPropertyValue("maxResultSize", maxResultSize);
148 
149         boolean cacheResults = false;
150         if (pluginConfig.hasAttributeNS(null, "cacheResults")) {
151             cacheResults = XMLHelper.getAttributeValueAsBoolean(pluginConfig.getAttributeNodeNS(null, "cacheResults"));
152         }
153         log.debug("Data connector {} cache results: {}", pluginId, cacheResults);
154         pluginBuilder.addPropertyValue("cacheResults", cacheResults);
155 
156         boolean mergeResults = false;
157         if (pluginConfig.hasAttributeNS(null, "mergeResults")) {
158             mergeResults = XMLHelper.getAttributeValueAsBoolean(pluginConfig.getAttributeNodeNS(null, "mergeResults"));
159         }
160         log.debug("Data connector{} merge results: {}", pluginId, mergeResults);
161         pluginBuilder.addPropertyValue("mergeResults", mergeResults);
162 
163         boolean noResultsIsError = false;
164         if (pluginConfig.hasAttributeNS(null, "noResultIsError")) {
165             noResultsIsError = XMLHelper.getAttributeValueAsBoolean(pluginConfig.getAttributeNodeNS(null,
166                     "noResultIsError"));
167         }
168         log.debug("Data connector {} no results is error: {}", pluginId, noResultsIsError);
169         pluginBuilder.addPropertyValue("noResultsIsError", noResultsIsError);
170 
171         String templateEngineRef = pluginConfig.getAttributeNS(null, "templateEngine");
172         pluginBuilder.addPropertyReference("templateEngine", templateEngineRef);
173     }
174 
175     /**
176      * Processes the return attributes provided in the configuration.
177      * 
178      * @param returnAttributes return attributes provided in the configuration
179      * 
180      * @return return attributes provided in the configuration
181      */
182     protected String[] processReturnAttributes(List<Element> returnAttributes) {
183         if (returnAttributes == null || returnAttributes.size() == 0) {
184             return null;
185         }
186 
187         StringTokenizer attributeTokens = new StringTokenizer(returnAttributes.get(0).getTextContent(), " ");
188         String[] attributes = new String[attributeTokens.countTokens()];
189         for (int i = 0; attributeTokens.hasMoreTokens(); i++) {
190             attributes[i] = DatatypeHelper.safeTrimOrNullString(attributeTokens.nextToken());
191         }
192 
193         return attributes;
194     }
195 
196     /**
197      * Processes the LDAP properties provided in the configuration.
198      * 
199      * @param propertyElems LDAP properties provided in the configuration
200      * 
201      * @return LDAP properties provided in the configuration
202      */
203     protected Map<String, String> processLDAPProperties(List<Element> propertyElems) {
204         HashMap<String, String> properties = new HashMap<String, String>();
205 
206         String propName;
207         String propValue;
208         if (propertyElems != null) {
209             for (Element propertyElem : propertyElems) {
210                 propName = DatatypeHelper.safeTrimOrNullString(propertyElem.getAttributeNS(null, "name"));
211                 propValue = DatatypeHelper.safeTrimOrNullString(propertyElem.getAttributeNS(null, "value"));
212                 properties.put(propName, propValue);
213             }
214         }
215 
216         return properties;
217     }
218 
219     /**
220      * Processes a credential element.
221      * 
222      * @param credentials list containing the element to process.
223      * @param parserContext current parser context
224      * 
225      * @return the bean definition for the credential
226      */
227     protected RuntimeBeanReference processCredential(List<Element> credentials, ParserContext parserContext) {
228         if (credentials == null) {
229             return null;
230         }
231 
232         Element credentialElem = credentials.get(0);
233         return SpringConfigurationUtils.parseCustomElement(credentialElem, parserContext);
234     }
235 }