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.beans.PropertyVetoException;
20 import java.util.Hashtable;
21 import java.util.List;
22 import java.util.Map;
23
24 import javax.naming.InitialContext;
25 import javax.naming.NamingException;
26 import javax.sql.DataSource;
27 import javax.xml.namespace.QName;
28
29 import org.opensaml.xml.util.DatatypeHelper;
30 import org.opensaml.xml.util.XMLHelper;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33 import org.springframework.beans.factory.BeanCreationException;
34 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
35 import org.springframework.beans.factory.xml.ParserContext;
36 import org.w3c.dom.Element;
37
38 import com.mchange.v2.c3p0.ComboPooledDataSource;
39
40
41
42
43 public class StoredIDDataConnectorBeanDefinitionParser extends BaseDataConnectorBeanDefinitionParser {
44
45
46 public static final QName TYPE_NAME = new QName(DataConnectorNamespaceHandler.NAMESPACE, "StoredId");
47
48
49 private final Logger log = LoggerFactory.getLogger(StoredIDDataConnectorBeanDefinitionParser.class);
50
51
52 protected Class getBeanClass(Element element) {
53 return StoredIDDataConnectorBeanFactory.class;
54 }
55
56
57 protected void doParse(String pluginId, Element pluginConfig, Map<QName, List<Element>> pluginConfigChildren,
58 BeanDefinitionBuilder pluginBuilder, ParserContext parserContext) {
59 super.doParse(pluginId, pluginConfig, pluginConfigChildren, pluginBuilder, parserContext);
60
61 if (pluginConfig.hasAttributeNS(null, "generatedAttributeID")) {
62 pluginBuilder.addPropertyValue("generatedAttribute", pluginConfig.getAttributeNS(null,
63 "generatedAttributeID"));
64 } else {
65 pluginBuilder.addPropertyValue("generatedAttribute", "storedId");
66 }
67
68 pluginBuilder.addPropertyValue("sourceAttribute", pluginConfig.getAttributeNS(null, "sourceAttributeID"));
69 pluginBuilder.addPropertyValue("salt", pluginConfig.getAttributeNS(null, "salt").getBytes());
70
71 DataSource connectionSource = processConnectionManagement(pluginId, pluginConfigChildren, pluginBuilder);
72 pluginBuilder.addPropertyValue("datasource", connectionSource);
73 }
74
75
76
77
78
79
80
81
82
83
84 protected DataSource processConnectionManagement(String pluginId, Map<QName, List<Element>> pluginConfigChildren,
85 BeanDefinitionBuilder pluginBuilder) {
86 List<Element> cmc = pluginConfigChildren.get(new QName(
87 DataConnectorNamespaceHandler.NAMESPACE, "ContainerManagedConnection"));
88 if (cmc != null && cmc.get(0) != null) {
89 return buildContainerManagedConnection(pluginId, cmc.get(0));
90 } else {
91 return buildApplicationManagedConnection(pluginId, pluginConfigChildren.get(
92 new QName(
93 DataConnectorNamespaceHandler.NAMESPACE, "ApplicationManagedConnection")).get(0));
94 }
95 }
96
97
98
99
100
101
102
103
104
105 protected DataSource buildContainerManagedConnection(String pluginId, Element cmc) {
106 String jndiResource = cmc.getAttributeNS(null, "resourceName");
107 jndiResource = DatatypeHelper.safeTrim(jndiResource);
108
109 Hashtable<String, String> initCtxProps = buildProperties(XMLHelper.getChildElementsByTagNameNS(cmc,
110 DataConnectorNamespaceHandler.NAMESPACE, "JNDIConnectionProperty"));
111 try {
112 InitialContext initCtx = new InitialContext(initCtxProps);
113 DataSource dataSource = (DataSource) initCtx.lookup(jndiResource);
114 if(dataSource == null){
115 log.error("DataSource " + jndiResource + " did not exist in JNDI directory");
116 throw new BeanCreationException("DataSource " + jndiResource + " did not exist in JNDI directory");
117 }
118 if (log.isDebugEnabled()) {
119 log.debug("Retrieved data source for data connector {} from JNDI location {} using properties ",
120 pluginId, initCtxProps);
121 }
122 return dataSource;
123 } catch (NamingException e) {
124 log.error("Unable to retrieve data source for data connector " + pluginId + " from JNDI location "
125 + jndiResource + " using properties " + initCtxProps, e);
126 return null;
127 }
128 }
129
130
131
132
133
134
135
136
137
138 protected DataSource buildApplicationManagedConnection(String pluginId, Element amc) {
139 ComboPooledDataSource datasource = new ComboPooledDataSource();
140
141 String driverClass = DatatypeHelper.safeTrim(amc.getAttributeNS(null, "jdbcDriver"));
142 ClassLoader classLoader = this.getClass().getClassLoader();
143 try{
144 classLoader.loadClass(driverClass);
145 }catch(ClassNotFoundException e){
146 log.error("Unable to create relational database connector, JDBC driver can not be found on the classpath");
147 throw new BeanCreationException("Unable to create relational database connector, JDBC driver can not be found on the classpath");
148 }
149
150 try {
151 datasource.setDriverClass(driverClass);
152 datasource.setJdbcUrl(DatatypeHelper.safeTrim(amc.getAttributeNS(null, "jdbcURL")));
153 datasource.setUser(DatatypeHelper.safeTrim(amc.getAttributeNS(null, "jdbcUserName")));
154 datasource.setPassword(DatatypeHelper.safeTrim(amc.getAttributeNS(null, "jdbcPassword")));
155
156 if (amc.hasAttributeNS(null, "poolAcquireIncrement")) {
157 datasource.setAcquireIncrement(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
158 "poolAcquireIncrement"))));
159 } else {
160 datasource.setAcquireIncrement(3);
161 }
162
163 if (amc.hasAttributeNS(null, "poolAcquireRetryAttempts")) {
164 datasource.setAcquireRetryAttempts(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
165 "poolAcquireRetryAttempts"))));
166 } else {
167 datasource.setAcquireRetryAttempts(36);
168 }
169
170 if (amc.hasAttributeNS(null, "poolAcquireRetryDelay")) {
171 datasource.setAcquireRetryDelay(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
172 "poolAcquireRetryDelay"))));
173 } else {
174 datasource.setAcquireRetryDelay(5000);
175 }
176
177 if (amc.hasAttributeNS(null, "poolBreakAfterAcquireFailure")) {
178 datasource.setBreakAfterAcquireFailure(XMLHelper.getAttributeValueAsBoolean(amc.getAttributeNodeNS(
179 null, "poolBreakAfterAcquireFailure")));
180 } else {
181 datasource.setBreakAfterAcquireFailure(true);
182 }
183
184 if (amc.hasAttributeNS(null, "poolMinSize")) {
185 datasource.setMinPoolSize(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
186 "poolMinSize"))));
187 } else {
188 datasource.setMinPoolSize(2);
189 }
190
191 if (amc.hasAttributeNS(null, "poolMaxSize")) {
192 datasource.setMaxPoolSize(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
193 "poolMaxSize"))));
194 } else {
195 datasource.setMaxPoolSize(50);
196 }
197
198 if (amc.hasAttributeNS(null, "poolMaxIdleTime")) {
199 datasource.setMaxIdleTime(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(null,
200 "poolMaxIdleTime"))));
201 } else {
202 datasource.setMaxIdleTime(600);
203 }
204
205 if (amc.hasAttributeNS(null, "poolIdleTestPeriod")) {
206 datasource.setIdleConnectionTestPeriod(Integer.parseInt(DatatypeHelper.safeTrim(amc.getAttributeNS(
207 null, "poolIdleTestPeriod"))));
208 } else {
209 datasource.setIdleConnectionTestPeriod(180);
210 }
211
212 log.debug("Created application managed data source for data connector {}", pluginId);
213 return datasource;
214 } catch (PropertyVetoException e) {
215 log.error("Unable to create data source for data connector {} with JDBC driver class {}", pluginId,
216 driverClass);
217 return null;
218 }
219 }
220
221
222
223
224
225
226
227
228 protected Hashtable<String, String> buildProperties(List<Element> propertyElements) {
229 if (propertyElements == null || propertyElements.size() < 1) {
230 return null;
231 }
232
233 Hashtable<String, String> properties = new Hashtable<String, String>();
234
235 String propName;
236 String propValue;
237 for (Element propertyElement : propertyElements) {
238 propName = DatatypeHelper.safeTrim(propertyElement.getAttributeNS(null, "name"));
239 propValue = DatatypeHelper.safeTrim(propertyElement.getAttributeNS(null, "value"));
240 properties.put(propName, propValue);
241 }
242
243 return properties;
244 }
245 }