1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
41 public class LdapDataConnectorBeanDefinitionParser extends BaseDataConnectorBeanDefinitionParser {
42
43
44 public static final QName TYPE_NAME = new QName(DataConnectorNamespaceHandler.NAMESPACE, "LDAPDirectory");
45
46
47 private final Logger log = LoggerFactory.getLogger(LdapDataConnectorBeanDefinitionParser.class);
48
49
50 protected Class getBeanClass(Element element) {
51 return LdapDataConnectorFactoryBean.class;
52 }
53
54
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
177
178
179
180
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
198
199
200
201
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
221
222
223
224
225
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 }