View Javadoc

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         // Don't bother putting encrypted passwords into the pool
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 }