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