1 /**
2 *
3 * Copyright 2003-2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.geronimo.converter.bea;
18
19 import java.io.Reader;
20 import java.io.IOException;
21 import java.io.StringReader;
22 import java.util.List;
23 import java.util.ArrayList;
24 import java.util.Map;
25 import java.util.HashMap;
26 import java.util.Properties;
27 import java.util.Iterator;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.ParserConfigurationException;
31 import org.apache.geronimo.converter.DOMUtils;
32 import org.apache.geronimo.converter.DatabaseConversionStatus;
33 import org.apache.geronimo.converter.JDBCPool;
34 import org.apache.geronimo.converter.XADatabasePool;
35 import org.apache.geronimo.converter.AbstractDatabasePool;
36 import org.apache.geronimo.kernel.util.XmlUtil;
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.NodeList;
40 import org.w3c.dom.Node;
41 import org.xml.sax.InputSource;
42 import org.xml.sax.SAXException;
43
44 /**
45 * Converts database pools from WebLogic 8.1 to Geronimo
46 *
47 * @version $Rev: 428843 $ $Date: 2006-08-04 11:43:59 -0700 (Fri, 04 Aug 2006) $
48 */
49 public class WebLogic81DatabaseConverter extends DOMUtils {
50 public static DatabaseConversionStatus convert(String libDir, String domainDir) throws IOException {
51 Weblogic81Utils utils = new Weblogic81Utils(libDir, domainDir);
52 String config = utils.getConfigXML();
53 return convert(new StringReader(config));
54 }
55
56 public static DatabaseConversionStatus convert(Reader configXml) throws IOException {
57 List status = new ArrayList();
58 List noTx = new ArrayList();
59 List local = new ArrayList();
60 List xa = new ArrayList();
61
62 DocumentBuilderFactory factory = XmlUtil.newDocumentBuilderFactory();
63 factory.setValidating(false);
64 try {
65 DocumentBuilder builder = factory.newDocumentBuilder();
66 Document doc = builder.parse(new InputSource(configXml));
67 configXml.close();
68 parseDocument(doc, status, local, xa);
69 } catch (ParserConfigurationException e) {
70 throw (IOException)new IOException().initCause(e);
71 } catch (SAXException e) {
72 throw (IOException)new IOException().initCause(e);
73 }
74
75 DatabaseConversionStatus result = new DatabaseConversionStatus();
76 result.setMessages((String[]) status.toArray(new String[status.size()]));
77 result.setNoTXPools((JDBCPool[]) noTx.toArray(new JDBCPool[noTx.size()]));
78 result.setJdbcPools((JDBCPool[]) local.toArray(new JDBCPool[noTx.size()]));
79 result.setXaPools((XADatabasePool[]) xa.toArray(new XADatabasePool[xa.size()]));
80 return result;
81 }
82
83 private static void parseDocument(Document doc, List status, List local, List xa) {
84 Element domain = doc.getDocumentElement();
85 if(!domain.getNodeName().equalsIgnoreCase("Domain")) {
86 status.add("ERROR: Unrecognized file beginning with "+domain.getNodeName()+" element. Expected a WebLogic config.xml file.");
87 return;
88 }
89 NodeList list = domain.getChildNodes();
90 Map pools = new HashMap();
91 for(int i=0; i<list.getLength(); i++) {
92 Node node = list.item(i);
93 if(node.getNodeType() == Node.ELEMENT_NODE) {
94 String name = node.getNodeName();
95 if(name.equalsIgnoreCase("JDBCConnectionPool")) {
96 ConnectionPool pool = getConnectionPool((Element)node, status);
97 pools.put(pool.getName(), pool);
98 } else if(name.equalsIgnoreCase("JDBCDataSource")) {
99 DataSource ds = getDataSource((Element)node, false);
100 ConnectionPool pool = (ConnectionPool) pools.get(ds.getPoolName());
101 if(pool != null) {
102 pool.getDataSources().add(ds);
103 } else {
104 status.add("ERROR: Can't find pool for data source '"+ds.getName()+"' ("+ds.getPoolName()+")");
105 }
106 } else if(name.equalsIgnoreCase("JDBCTxDataSource")) {
107 DataSource ds = getDataSource((Element)node, true);
108 ConnectionPool pool = (ConnectionPool) pools.get(ds.getPoolName());
109 if(pool != null) {
110 pool.getDataSources().add(ds);
111 } else {
112 status.add("ERROR: Can't find pool for data source '"+ds.getName()+"' ("+ds.getPoolName()+")");
113 }
114 } else {
115 status.add("Skipping element '"+name+"'");
116 }
117 }
118 }
119 if(pools.size() > 0) {
120 for (Iterator it = pools.values().iterator(); it.hasNext();) {
121 ConnectionPool pool = (ConnectionPool) it.next();
122 if(pool.getPassword() != null && pool.getPassword().startsWith("{")) {
123 status.add("NOTE: When importing from WebLogic, typically database passwords cannot be recovered, and will need to be re-entered.");
124 break;
125 }
126 }
127 }
128 processPools((ConnectionPool[]) pools.values().toArray(new ConnectionPool[0]),
129 status, local, xa);
130 }
131
132 private static void processPools(ConnectionPool[] pools, List status, List local, List xa) {
133 for (int i = 0; i < pools.length; i++) {
134 ConnectionPool pool = pools[i];
135 boolean isXA;
136 if(pool.hasEmulate()) {
137 isXA = false;
138 } else if(pool.hasNonTX()) {
139 isXA = false;
140 } else if(pool.hasXADriverName()) {
141 isXA = true;
142 } else {
143 isXA = false;
144 status.add("Can't tell whether pool '"+pool.getName()+"' is an XA driver or not; will create local transaction pools in Geronimo.");
145 }
146 if(pool.getDataSources().size() == 0) {
147 status.add("Pool '"+pool.getName()+"' has no associated data sources. Creating a default pool for it.");
148 if(isXA) {
149 xa.add(createXAPool(pool, pool.getName(), null));
150 } else {
151 local.add(createJDBCPool(pool, pool.getName(), null));
152 }
153 } else {
154 for (int j = 0; j < pool.getDataSources().size(); j++) {
155 DataSource ds = (DataSource) pool.getDataSources().get(j);
156 if(isXA) {
157 xa.add(createXAPool(pool, ds.getName(), ds.getJndiName()));
158 } else {
159 local.add(createJDBCPool(pool, ds.getName(), ds.getJndiName()));
160 }
161 }
162 }
163 }
164 }
165
166 private static void populatePool(ConnectionPool pool, AbstractDatabasePool target) {
167 if(pool.getReserveTimeoutSecs() != null) {
168 target.setBlockingTimeoutMillis(new Integer(pool.getReserveTimeoutSecs().intValue()*1000));
169 }
170 if(pool.getIdleTimeoutSecs() != null) {
171 target.setIdleTimeoutMillis(new Integer(pool.getIdleTimeoutSecs().intValue()*1000));
172 }
173 target.setMaxSize(pool.getMax());
174 target.setMinSize(pool.getMin());
175 target.setNewConnectionSQL(pool.getInitSQL());
176 target.setStatementCacheSize(pool.getCacheSize());
177 target.setTestConnectionSQL(pool.getTestTable() == null ? null : "SELECT * FROM "+pool.getTestTable()+" WHERE 0=1");
178 if(pool.getDriverName().toLowerCase().indexOf("oracle") > -1) target.setVendor(JDBCPool.VENDOR_ORACLE);
179 if(pool.getDriverName().toLowerCase().indexOf("mysql") > -1) target.setVendor(JDBCPool.VENDOR_MYSQL);
180 if(pool.getDriverName().toLowerCase().indexOf("sybase") > -1) target.setVendor(JDBCPool.VENDOR_SYBASE);
181 if(pool.getDriverName().toLowerCase().indexOf("informix") > -1) target.setVendor(JDBCPool.VENDOR_INFORMIX);
182 }
183
184 private static JDBCPool createJDBCPool(ConnectionPool pool, String name, String jndiName) {
185 JDBCPool result = new JDBCPool();
186 result.setName(name);
187 result.setJndiName(jndiName);
188 populatePool(pool, result);
189 result.setConnectionProperties(pool.getProperties());
190 result.setDriverClass(pool.getDriverName());
191 result.setJdbcURL(pool.getUrl());
192
193 if(pool.getPassword() != null && !pool.getPassword().startsWith("{")) {
194 result.setPassword(pool.getPassword());
195 }
196 result.setUsername(pool.getUsername());
197 return result;
198 }
199
200 private static XADatabasePool createXAPool(ConnectionPool pool, String name, String jndiName) {
201 XADatabasePool result = new XADatabasePool();
202 result.setName(name);
203 result.setJndiName(jndiName);
204 populatePool(pool, result);
205 result.setXaDataSourceClass(pool.getDriverName());
206 result.setProperties(pool.getProperties());
207 return result;
208 }
209
210 private static DataSource getDataSource(Element root, boolean tx) {
211 DataSource ds = new DataSource();
212 ds.setDeclaredAsTX(tx);
213 ds.setEmulate(getBoolean(root.getAttribute("EnableTwoPhaseCommit"), false));
214 ds.setName(root.getAttribute("Name"));
215 ds.setJndiName(root.getAttribute("JNDIName"));
216 ds.setPoolName(root.getAttribute("PoolName"));
217 return ds;
218 }
219
220 private static boolean getBoolean(String value, boolean defaultResult) {
221 if(value == null) {
222 return defaultResult;
223 }
224 return new Boolean(value).booleanValue();
225 }
226
227 private static ConnectionPool getConnectionPool(Element root, List status) {
228 ConnectionPool pool = new ConnectionPool();
229 pool.setName(root.getAttribute("Name"));
230 pool.setDriverName(root.getAttribute("DriverName"));
231 pool.setUrl(root.getAttribute("URL"));
232 pool.setMin(getInteger(root.getAttribute("InitialCapacity")));
233 pool.setMax(getInteger(root.getAttribute("MaxCapacity")));
234 readProperties(pool.getProperties(), root.getAttribute("Properties"), status);
235 pool.setUsername(pool.getProperties().getProperty("user"));
236 pool.getProperties().remove("user");
237 if(root.hasAttribute("Password")) {
238 pool.setPassword(root.getAttribute("Password"));
239 } else if(root.hasAttribute("PasswordEncrypted")) {
240 pool.setPassword(root.getAttribute("PasswordEncrypted"));
241 }
242 pool.setReserveTimeoutSecs(getInteger(root.getAttribute("ConnectionReserveTimeoutSeconds")));
243 pool.setIdleTimeoutSecs(getInteger(root.getAttribute("InactiveConnectionTimeoutSeconds")));
244 pool.setCacheSize(getInteger(root.getAttribute("StatementCacheSize")));
245 pool.setInitSQL(root.getAttribute("InitSQL"));
246 pool.setTestTable(root.getAttribute("TestTableName"));
247 return pool;
248 }
249
250 private static void readProperties(Properties props, String value, List status) {
251 if(value == null) {
252 return;
253 }
254 value = value.trim();
255 if(value.equals("")) {
256 return;
257 }
258 int last = -1;
259 int pos = value.indexOf(';');
260 while(pos > -1) {
261 String s = value.substring(last+1, pos);
262 int eq = s.indexOf('=');
263 if(eq > -1) {
264 props.setProperty(s.substring(0, eq), s.substring(eq+1));
265 } else {
266 status.add("WARN: Unable to read property '"+s+"'");
267 }
268 last = pos;
269 pos = value.indexOf(';', pos+1);
270 }
271 String s = value.substring(last+1);
272 int eq = s.indexOf('=');
273 if(eq > -1) {
274 props.setProperty(s.substring(0, eq), s.substring(eq+1));
275 } else {
276 status.add("WARN: Unable to read property '"+s+"'");
277 }
278 }
279
280 private static Integer getInteger(String value) {
281 if(value == null) {
282 return null;
283 }
284 value = value.trim();
285 if(value.equals("")) {
286 return null;
287 }
288 return new Integer(value);
289 }
290
291 public static class DataSource {
292 private String name;
293 private String poolName;
294 private String jndiName;
295 private boolean emulate;
296 private boolean declaredAsTX;
297
298 public String getName() {
299 return name;
300 }
301
302 public void setName(String name) {
303 this.name = name;
304 }
305
306 public String getPoolName() {
307 return poolName;
308 }
309
310 public void setPoolName(String poolName) {
311 this.poolName = poolName;
312 }
313
314 public String getJndiName() {
315 return jndiName;
316 }
317
318 public void setJndiName(String jndiName) {
319 this.jndiName = jndiName;
320 }
321
322 public boolean isEmulate() {
323 return emulate;
324 }
325
326 public void setEmulate(boolean emulate) {
327 this.emulate = emulate;
328 }
329
330 public boolean isDeclaredAsTX() {
331 return declaredAsTX;
332 }
333
334 public void setDeclaredAsTX(boolean declaredAsTX) {
335 this.declaredAsTX = declaredAsTX;
336 }
337 }
338
339 public static class ConnectionPool {
340 private String name;
341 private String driverName;
342 private Integer min, max;
343 private String url;
344 private String username;
345 private String password;
346 private Integer reserveTimeoutSecs;
347 private Integer idleTimeoutSecs;
348 private Integer cacheSize;
349 private String initSQL;
350 private String testTable;
351 private Properties properties = new Properties();
352 private List dataSources = new ArrayList();
353
354 public boolean hasEmulate() {
355 for (int i = 0; i < dataSources.size(); i++) {
356 DataSource ds = (DataSource) dataSources.get(i);
357 if(ds.isEmulate()) {
358 return true;
359 }
360 }
361 return false;
362 }
363
364 public boolean hasNonTX() {
365 for (int i = 0; i < dataSources.size(); i++) {
366 DataSource ds = (DataSource) dataSources.get(i);
367 if(!ds.isDeclaredAsTX()) {
368 return true;
369 }
370 }
371 return false;
372 }
373
374 public boolean hasXADriverName() {
375 return driverName.toUpperCase().indexOf("XA") > -1;
376 }
377
378 public String getName() {
379 return name;
380 }
381
382 public void setName(String name) {
383 this.name = name;
384 }
385
386 public String getDriverName() {
387 return driverName;
388 }
389
390 public void setDriverName(String driverName) {
391 this.driverName = driverName;
392 }
393
394 public String getUsername() {
395 return username;
396 }
397
398 public void setUsername(String username) {
399 this.username = username;
400 }
401
402 public String getPassword() {
403 return password;
404 }
405
406 public void setPassword(String password) {
407 this.password = password;
408 }
409
410 public String getInitSQL() {
411 return initSQL;
412 }
413
414 public void setInitSQL(String initSQL) {
415 this.initSQL = initSQL;
416 }
417
418 public String getTestTable() {
419 return testTable;
420 }
421
422 public void setTestTable(String testTable) {
423 this.testTable = testTable;
424 }
425
426 public Properties getProperties() {
427 return properties;
428 }
429
430 public void setProperties(Properties properties) {
431 this.properties = properties;
432 }
433
434 public List getDataSources() {
435 return dataSources;
436 }
437
438 public void setDataSources(List dataSources) {
439 this.dataSources = dataSources;
440 }
441
442 public Integer getMin() {
443 return min;
444 }
445
446 public void setMin(Integer min) {
447 this.min = min;
448 }
449
450 public Integer getMax() {
451 return max;
452 }
453
454 public void setMax(Integer max) {
455 this.max = max;
456 }
457
458 public Integer getReserveTimeoutSecs() {
459 return reserveTimeoutSecs;
460 }
461
462 public void setReserveTimeoutSecs(Integer reserveTimeoutSecs) {
463 this.reserveTimeoutSecs = reserveTimeoutSecs;
464 }
465
466 public Integer getIdleTimeoutSecs() {
467 return idleTimeoutSecs;
468 }
469
470 public void setIdleTimeoutSecs(Integer idleTimeoutSecs) {
471 this.idleTimeoutSecs = idleTimeoutSecs;
472 }
473
474 public Integer getCacheSize() {
475 return cacheSize;
476 }
477
478 public void setCacheSize(Integer cacheSize) {
479 this.cacheSize = cacheSize;
480 }
481
482 public String getUrl() {
483 return url;
484 }
485
486 public void setUrl(String url) {
487 this.url = url;
488 }
489 }
490 }