001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.converter.bea;
017:
018: import java.io.Reader;
019: import java.io.IOException;
020: import java.io.StringReader;
021: import java.util.List;
022: import java.util.ArrayList;
023: import java.util.Map;
024: import java.util.HashMap;
025: import java.util.Properties;
026: import java.util.Iterator;
027: import javax.xml.parsers.DocumentBuilderFactory;
028: import javax.xml.parsers.DocumentBuilder;
029: import javax.xml.parsers.ParserConfigurationException;
030: import org.apache.geronimo.converter.DOMUtils;
031: import org.apache.geronimo.converter.DatabaseConversionStatus;
032: import org.apache.geronimo.converter.JDBCPool;
033: import org.apache.geronimo.converter.XADatabasePool;
034: import org.apache.geronimo.converter.AbstractDatabasePool;
035: import org.apache.geronimo.kernel.util.XmlUtil;
036: import org.w3c.dom.Document;
037: import org.w3c.dom.Element;
038: import org.w3c.dom.NodeList;
039: import org.w3c.dom.Node;
040: import org.xml.sax.InputSource;
041: import org.xml.sax.SAXException;
042:
043: /**
044: * Converts database pools from WebLogic 8.1 to Geronimo
045: *
046: * @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
047: */
048: public class WebLogic81DatabaseConverter extends DOMUtils {
049: public static DatabaseConversionStatus convert(String libDir,
050: String domainDir) throws IOException {
051: Weblogic81Utils utils = new Weblogic81Utils(libDir, domainDir);
052: String config = utils.getConfigXML();
053: return convert(new StringReader(config));
054: }
055:
056: public static DatabaseConversionStatus convert(Reader configXml)
057: throws IOException {
058: List status = new ArrayList();
059: List noTx = new ArrayList();
060: List local = new ArrayList();
061: List xa = new ArrayList();
062:
063: DocumentBuilderFactory factory = XmlUtil
064: .newDocumentBuilderFactory();
065: factory.setValidating(false);
066: try {
067: DocumentBuilder builder = factory.newDocumentBuilder();
068: Document doc = builder.parse(new InputSource(configXml));
069: configXml.close();
070: parseDocument(doc, status, local, xa);
071: } catch (ParserConfigurationException e) {
072: throw (IOException) new IOException().initCause(e);
073: } catch (SAXException e) {
074: throw (IOException) new IOException().initCause(e);
075: }
076:
077: DatabaseConversionStatus result = new DatabaseConversionStatus();
078: result.setMessages((String[]) status.toArray(new String[status
079: .size()]));
080: result.setNoTXPools((JDBCPool[]) noTx.toArray(new JDBCPool[noTx
081: .size()]));
082: result.setJdbcPools((JDBCPool[]) local
083: .toArray(new JDBCPool[noTx.size()]));
084: result.setXaPools((XADatabasePool[]) xa
085: .toArray(new XADatabasePool[xa.size()]));
086: return result;
087: }
088:
089: private static void parseDocument(Document doc, List status,
090: List local, List xa) {
091: Element domain = doc.getDocumentElement();
092: if (!domain.getNodeName().equalsIgnoreCase("Domain")) {
093: status
094: .add("ERROR: Unrecognized file beginning with "
095: + domain.getNodeName()
096: + " element. Expected a WebLogic config.xml file.");
097: return;
098: }
099: NodeList list = domain.getChildNodes();
100: Map pools = new HashMap();
101: for (int i = 0; i < list.getLength(); i++) {
102: Node node = list.item(i);
103: if (node.getNodeType() == Node.ELEMENT_NODE) {
104: String name = node.getNodeName();
105: if (name.equalsIgnoreCase("JDBCConnectionPool")) {
106: ConnectionPool pool = getConnectionPool(
107: (Element) node, status);
108: pools.put(pool.getName(), pool);
109: } else if (name.equalsIgnoreCase("JDBCDataSource")) {
110: DataSource ds = getDataSource((Element) node, false);
111: ConnectionPool pool = (ConnectionPool) pools.get(ds
112: .getPoolName());
113: if (pool != null) {
114: pool.getDataSources().add(ds);
115: } else {
116: status
117: .add("ERROR: Can't find pool for data source '"
118: + ds.getName()
119: + "' ("
120: + ds.getPoolName() + ")");
121: }
122: } else if (name.equalsIgnoreCase("JDBCTxDataSource")) {
123: DataSource ds = getDataSource((Element) node, true);
124: ConnectionPool pool = (ConnectionPool) pools.get(ds
125: .getPoolName());
126: if (pool != null) {
127: pool.getDataSources().add(ds);
128: } else {
129: status
130: .add("ERROR: Can't find pool for data source '"
131: + ds.getName()
132: + "' ("
133: + ds.getPoolName() + ")");
134: }
135: } else {
136: status.add("Skipping element '" + name + "'");
137: }
138: }
139: }
140: if (pools.size() > 0) {
141: for (Iterator it = pools.values().iterator(); it.hasNext();) {
142: ConnectionPool pool = (ConnectionPool) it.next();
143: if (pool.getPassword() != null
144: && pool.getPassword().startsWith("{")) {
145: status
146: .add("NOTE: When importing from WebLogic, typically database passwords cannot be recovered, and will need to be re-entered.");
147: break;
148: }
149: }
150: }
151: processPools((ConnectionPool[]) pools.values().toArray(
152: new ConnectionPool[0]), status, local, xa);
153: }
154:
155: private static void processPools(ConnectionPool[] pools,
156: List status, List local, List xa) {
157: for (int i = 0; i < pools.length; i++) {
158: ConnectionPool pool = pools[i];
159: boolean isXA;
160: if (pool.hasEmulate()) {
161: isXA = false;
162: } else if (pool.hasNonTX()) {
163: isXA = false;
164: } else if (pool.hasXADriverName()) {
165: isXA = true;
166: } else {
167: isXA = false;
168: status
169: .add("Can't tell whether pool '"
170: + pool.getName()
171: + "' is an XA driver or not; will create local transaction pools in Geronimo.");
172: }
173: if (pool.getDataSources().size() == 0) {
174: status
175: .add("Pool '"
176: + pool.getName()
177: + "' has no associated data sources. Creating a default pool for it.");
178: if (isXA) {
179: xa.add(createXAPool(pool, pool.getName(), null));
180: } else {
181: local
182: .add(createJDBCPool(pool, pool.getName(),
183: null));
184: }
185: } else {
186: for (int j = 0; j < pool.getDataSources().size(); j++) {
187: DataSource ds = (DataSource) pool.getDataSources()
188: .get(j);
189: if (isXA) {
190: xa.add(createXAPool(pool, ds.getName(), ds
191: .getJndiName()));
192: } else {
193: local.add(createJDBCPool(pool, ds.getName(), ds
194: .getJndiName()));
195: }
196: }
197: }
198: }
199: }
200:
201: private static void populatePool(ConnectionPool pool,
202: AbstractDatabasePool target) {
203: if (pool.getReserveTimeoutSecs() != null) {
204: target.setBlockingTimeoutMillis(new Integer(pool
205: .getReserveTimeoutSecs().intValue() * 1000));
206: }
207: if (pool.getIdleTimeoutSecs() != null) {
208: target.setIdleTimeoutMillis(new Integer(pool
209: .getIdleTimeoutSecs().intValue() * 1000));
210: }
211: target.setMaxSize(pool.getMax());
212: target.setMinSize(pool.getMin());
213: target.setNewConnectionSQL(pool.getInitSQL());
214: target.setStatementCacheSize(pool.getCacheSize());
215: target
216: .setTestConnectionSQL(pool.getTestTable() == null ? null
217: : "SELECT * FROM " + pool.getTestTable()
218: + " WHERE 0=1");
219: if (pool.getDriverName().toLowerCase().indexOf("oracle") > -1)
220: target.setVendor(JDBCPool.VENDOR_ORACLE);
221: if (pool.getDriverName().toLowerCase().indexOf("mysql") > -1)
222: target.setVendor(JDBCPool.VENDOR_MYSQL);
223: if (pool.getDriverName().toLowerCase().indexOf("sybase") > -1)
224: target.setVendor(JDBCPool.VENDOR_SYBASE);
225: if (pool.getDriverName().toLowerCase().indexOf("informix") > -1)
226: target.setVendor(JDBCPool.VENDOR_INFORMIX);
227: }
228:
229: private static JDBCPool createJDBCPool(ConnectionPool pool,
230: String name, String jndiName) {
231: JDBCPool result = new JDBCPool();
232: result.setName(name);
233: result.setJndiName(jndiName);
234: populatePool(pool, result);
235: result.setConnectionProperties(pool.getProperties());
236: result.setDriverClass(pool.getDriverName());
237: result.setJdbcURL(pool.getUrl());
238: // Don't bother putting encrypted passwords into the pool
239: if (pool.getPassword() != null
240: && !pool.getPassword().startsWith("{")) {
241: result.setPassword(pool.getPassword());
242: }
243: result.setUsername(pool.getUsername());
244: return result;
245: }
246:
247: private static XADatabasePool createXAPool(ConnectionPool pool,
248: String name, String jndiName) {
249: XADatabasePool result = new XADatabasePool();
250: result.setName(name);
251: result.setJndiName(jndiName);
252: populatePool(pool, result);
253: result.setXaDataSourceClass(pool.getDriverName());
254: result.setProperties(pool.getProperties());
255: return result;
256: }
257:
258: private static DataSource getDataSource(Element root, boolean tx) {
259: DataSource ds = new DataSource();
260: ds.setDeclaredAsTX(tx);
261: ds.setEmulate(getBoolean(root
262: .getAttribute("EnableTwoPhaseCommit"), false));
263: ds.setName(root.getAttribute("Name"));
264: ds.setJndiName(root.getAttribute("JNDIName"));
265: ds.setPoolName(root.getAttribute("PoolName"));
266: return ds;
267: }
268:
269: private static boolean getBoolean(String value,
270: boolean defaultResult) {
271: if (value == null) {
272: return defaultResult;
273: }
274: return new Boolean(value).booleanValue();
275: }
276:
277: private static ConnectionPool getConnectionPool(Element root,
278: List status) {
279: ConnectionPool pool = new ConnectionPool();
280: pool.setName(root.getAttribute("Name"));
281: pool.setDriverName(root.getAttribute("DriverName"));
282: pool.setUrl(root.getAttribute("URL"));
283: pool.setMin(getInteger(root.getAttribute("InitialCapacity")));
284: pool.setMax(getInteger(root.getAttribute("MaxCapacity")));
285: readProperties(pool.getProperties(), root
286: .getAttribute("Properties"), status);
287: pool.setUsername(pool.getProperties().getProperty("user"));
288: pool.getProperties().remove("user");
289: if (root.hasAttribute("Password")) {
290: pool.setPassword(root.getAttribute("Password"));
291: } else if (root.hasAttribute("PasswordEncrypted")) {
292: pool.setPassword(root.getAttribute("PasswordEncrypted"));
293: }
294: pool.setReserveTimeoutSecs(getInteger(root
295: .getAttribute("ConnectionReserveTimeoutSeconds")));
296: pool.setIdleTimeoutSecs(getInteger(root
297: .getAttribute("InactiveConnectionTimeoutSeconds")));
298: pool.setCacheSize(getInteger(root
299: .getAttribute("StatementCacheSize")));
300: pool.setInitSQL(root.getAttribute("InitSQL"));
301: pool.setTestTable(root.getAttribute("TestTableName"));
302: return pool;
303: }
304:
305: private static void readProperties(Properties props, String value,
306: List status) {
307: if (value == null) {
308: return;
309: }
310: value = value.trim();
311: if (value.equals("")) {
312: return;
313: }
314: int last = -1;
315: int pos = value.indexOf(';');
316: while (pos > -1) {
317: String s = value.substring(last + 1, pos);
318: int eq = s.indexOf('=');
319: if (eq > -1) {
320: props.setProperty(s.substring(0, eq), s
321: .substring(eq + 1));
322: } else {
323: status.add("WARN: Unable to read property '" + s + "'");
324: }
325: last = pos;
326: pos = value.indexOf(';', pos + 1);
327: }
328: String s = value.substring(last + 1);
329: int eq = s.indexOf('=');
330: if (eq > -1) {
331: props.setProperty(s.substring(0, eq), s.substring(eq + 1));
332: } else {
333: status.add("WARN: Unable to read property '" + s + "'");
334: }
335: }
336:
337: private static Integer getInteger(String value) {
338: if (value == null) {
339: return null;
340: }
341: value = value.trim();
342: if (value.equals("")) {
343: return null;
344: }
345: return new Integer(value);
346: }
347:
348: public static class DataSource {
349: private String name;
350: private String poolName;
351: private String jndiName;
352: private boolean emulate;
353: private boolean declaredAsTX;
354:
355: public String getName() {
356: return name;
357: }
358:
359: public void setName(String name) {
360: this .name = name;
361: }
362:
363: public String getPoolName() {
364: return poolName;
365: }
366:
367: public void setPoolName(String poolName) {
368: this .poolName = poolName;
369: }
370:
371: public String getJndiName() {
372: return jndiName;
373: }
374:
375: public void setJndiName(String jndiName) {
376: this .jndiName = jndiName;
377: }
378:
379: public boolean isEmulate() {
380: return emulate;
381: }
382:
383: public void setEmulate(boolean emulate) {
384: this .emulate = emulate;
385: }
386:
387: public boolean isDeclaredAsTX() {
388: return declaredAsTX;
389: }
390:
391: public void setDeclaredAsTX(boolean declaredAsTX) {
392: this .declaredAsTX = declaredAsTX;
393: }
394: }
395:
396: public static class ConnectionPool {
397: private String name;
398: private String driverName;
399: private Integer min, max;
400: private String url;
401: private String username;
402: private String password;
403: private Integer reserveTimeoutSecs;
404: private Integer idleTimeoutSecs;
405: private Integer cacheSize;
406: private String initSQL;
407: private String testTable;
408: private Properties properties = new Properties();
409: private List dataSources = new ArrayList();
410:
411: public boolean hasEmulate() {
412: for (int i = 0; i < dataSources.size(); i++) {
413: DataSource ds = (DataSource) dataSources.get(i);
414: if (ds.isEmulate()) {
415: return true;
416: }
417: }
418: return false;
419: }
420:
421: public boolean hasNonTX() {
422: for (int i = 0; i < dataSources.size(); i++) {
423: DataSource ds = (DataSource) dataSources.get(i);
424: if (!ds.isDeclaredAsTX()) {
425: return true;
426: }
427: }
428: return false;
429: }
430:
431: public boolean hasXADriverName() {
432: return driverName.toUpperCase().indexOf("XA") > -1;
433: }
434:
435: public String getName() {
436: return name;
437: }
438:
439: public void setName(String name) {
440: this .name = name;
441: }
442:
443: public String getDriverName() {
444: return driverName;
445: }
446:
447: public void setDriverName(String driverName) {
448: this .driverName = driverName;
449: }
450:
451: public String getUsername() {
452: return username;
453: }
454:
455: public void setUsername(String username) {
456: this .username = username;
457: }
458:
459: public String getPassword() {
460: return password;
461: }
462:
463: public void setPassword(String password) {
464: this .password = password;
465: }
466:
467: public String getInitSQL() {
468: return initSQL;
469: }
470:
471: public void setInitSQL(String initSQL) {
472: this .initSQL = initSQL;
473: }
474:
475: public String getTestTable() {
476: return testTable;
477: }
478:
479: public void setTestTable(String testTable) {
480: this .testTable = testTable;
481: }
482:
483: public Properties getProperties() {
484: return properties;
485: }
486:
487: public void setProperties(Properties properties) {
488: this .properties = properties;
489: }
490:
491: public List getDataSources() {
492: return dataSources;
493: }
494:
495: public void setDataSources(List dataSources) {
496: this .dataSources = dataSources;
497: }
498:
499: public Integer getMin() {
500: return min;
501: }
502:
503: public void setMin(Integer min) {
504: this .min = min;
505: }
506:
507: public Integer getMax() {
508: return max;
509: }
510:
511: public void setMax(Integer max) {
512: this .max = max;
513: }
514:
515: public Integer getReserveTimeoutSecs() {
516: return reserveTimeoutSecs;
517: }
518:
519: public void setReserveTimeoutSecs(Integer reserveTimeoutSecs) {
520: this .reserveTimeoutSecs = reserveTimeoutSecs;
521: }
522:
523: public Integer getIdleTimeoutSecs() {
524: return idleTimeoutSecs;
525: }
526:
527: public void setIdleTimeoutSecs(Integer idleTimeoutSecs) {
528: this .idleTimeoutSecs = idleTimeoutSecs;
529: }
530:
531: public Integer getCacheSize() {
532: return cacheSize;
533: }
534:
535: public void setCacheSize(Integer cacheSize) {
536: this .cacheSize = cacheSize;
537: }
538:
539: public String getUrl() {
540: return url;
541: }
542:
543: public void setUrl(String url) {
544: this.url = url;
545: }
546: }
547: }
|