KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > resource > adapter > jdbc > xa > HAXAManagedConnectionFactory


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.resource.adapter.jdbc.xa;
23
24 import org.jboss.resource.JBossResourceException;
25 import org.jboss.util.JBossStringBuilder;
26
27 import javax.resource.ResourceException JavaDoc;
28 import javax.resource.spi.ManagedConnection JavaDoc;
29 import javax.resource.spi.ConnectionRequestInfo JavaDoc;
30 import javax.sql.XADataSource JavaDoc;
31 import javax.security.auth.Subject JavaDoc;
32 import java.util.List JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.Properties JavaDoc;
35 import java.util.Iterator JavaDoc;
36 import java.lang.reflect.Method JavaDoc;
37 import java.lang.reflect.InvocationTargetException JavaDoc;
38 import java.beans.PropertyEditorManager JavaDoc;
39 import java.beans.PropertyEditor JavaDoc;
40
41 /**
42  * @author <a HREF="mailto:alex@jboss.org">Alexey Loubyansky</a>
43  * @version <tt>$Revision: 43316 $</tt>
44  */

45 public class HAXAManagedConnectionFactory
46    extends XAManagedConnectionFactory
47 {
48    private static final long serialVersionUID = 1898242235188801452L;
49
50    private String JavaDoc urlProperty;
51    private String JavaDoc urlDelimeter;
52    private XADataSelector xadsSelector;
53
54    public String JavaDoc getURLProperty()
55    {
56       return urlProperty;
57    }
58
59    public void setURLProperty(String JavaDoc urlProperty) throws ResourceException
60    {
61       this.urlProperty = urlProperty;
62       initSelector();
63    }
64
65    public String JavaDoc getURLDelimeter()
66    {
67       return urlDelimeter;
68    }
69
70    public void setURLDelimeter(String JavaDoc urlDelimeter) throws ResourceException
71    {
72       this.urlDelimeter = urlDelimeter;
73       initSelector();
74    }
75
76    public void setXADataSourceProperties(String JavaDoc xaDataSourceProperties) throws ResourceException
77    {
78       super.setXADataSourceProperties(xaDataSourceProperties);
79       initSelector();
80    }
81
82    // Protected
83

84    public ManagedConnection JavaDoc createManagedConnection(Subject JavaDoc subject, ConnectionRequestInfo JavaDoc cri)
85       throws javax.resource.ResourceException JavaDoc
86    {
87       if(xadsSelector == null)
88       {
89          JBossStringBuilder buffer = new JBossStringBuilder();
90          buffer.append("Missing configuration for HA XA datasource.");
91          if (urlProperty == null)
92             buffer.append(" No url property.");
93          else if (xaProps.containsKey(urlProperty) == false)
94             buffer.append(" ").append(urlProperty).append(" not found in datasource properties.");
95          if (urlDelimeter == null)
96             buffer.append(" No url-delimiter.");
97          throw new JBossResourceException(buffer.toString());
98       }
99
100       // try to get a connection as many times as many urls we have in the list
101
for(int i = 0; i < xadsSelector.getXADataSourceList().size(); ++i)
102       {
103          XAData xaData = xadsSelector.getXAData();
104
105          if(log.isTraceEnabled())
106          {
107             log.trace("Trying to create an XA connection to " + xaData.url);
108          }
109
110          try
111          {
112             return super.createManagedConnection(subject, cri);
113          }
114          catch(ResourceException e)
115          {
116             log.warn("Failed to create an XA connection to " + xaData.url + ": " + e.getMessage());
117             xadsSelector.failedXAData(xaData);
118          }
119       }
120
121       // we have supposedly tried all the urls
122
throw new JBossResourceException(
123          "Could not create connection using any of the URLs: " + xadsSelector.getXADataSourceList()
124       );
125    }
126
127    protected synchronized XADataSource JavaDoc getXADataSource() throws ResourceException
128    {
129       return xadsSelector.getXAData().xads;
130    }
131
132    // Private
133

134    private XADataSource JavaDoc createXaDataSource(Properties JavaDoc xaProps)
135       throws JBossResourceException
136    {
137       if(getXADataSourceClass() == null)
138       {
139          throw new JBossResourceException("No XADataSourceClass supplied!");
140       }
141
142       XADataSource JavaDoc xads;
143       try
144       {
145          Class JavaDoc clazz = Thread.currentThread().getContextClassLoader().loadClass(getXADataSourceClass());
146          xads = (XADataSource JavaDoc)clazz.newInstance();
147          Class JavaDoc[] NOCLASSES = new Class JavaDoc[]{};
148          for(Iterator JavaDoc i = xaProps.keySet().iterator(); i.hasNext();)
149          {
150             String JavaDoc name = (String JavaDoc)i.next();
151             String JavaDoc value = xaProps.getProperty(name);
152             //This is a bad solution. On the other hand the only known example
153
// of a setter with no getter is for Oracle with password.
154
//Anyway, each xadatasource implementation should get its
155
//own subclass of this that explicitly sets the
156
//properties individually.
157
Class JavaDoc type = null;
158             try
159             {
160                Method JavaDoc getter = clazz.getMethod("get" + name, NOCLASSES);
161                type = getter.getReturnType();
162             }
163             catch(NoSuchMethodException JavaDoc e)
164             {
165                type = String JavaDoc.class;
166             } // end of try-catch
167

168             Method JavaDoc setter = clazz.getMethod("set" + name, new Class JavaDoc[]{type});
169             PropertyEditor JavaDoc editor = PropertyEditorManager.findEditor(type);
170             if(editor == null)
171             {
172                throw new JBossResourceException("No property editor found for type: " + type);
173             } // end of if ()
174
editor.setAsText(value);
175             setter.invoke(xads, new Object JavaDoc[]{editor.getValue()});
176
177          } // end of for ()
178
}
179       catch(ClassNotFoundException JavaDoc cnfe)
180       {
181          throw new JBossResourceException("Class not found for XADataSource " + getXADataSourceClass(), cnfe);
182       } // end of try-catch
183
catch(InstantiationException JavaDoc ie)
184       {
185          throw new JBossResourceException("Could not create an XADataSource: ", ie);
186       } // end of catch
187
catch(IllegalAccessException JavaDoc iae)
188       {
189          throw new JBossResourceException("Could not set a property: ", iae);
190       } // end of catch
191

192       catch(IllegalArgumentException JavaDoc iae)
193       {
194          throw new JBossResourceException("Could not set a property: ", iae);
195       } // end of catch
196

197       catch(InvocationTargetException JavaDoc ite)
198       {
199          throw new JBossResourceException("Could not invoke setter on XADataSource: ", ite);
200       } // end of catch
201
catch(NoSuchMethodException JavaDoc nsme)
202       {
203          throw new JBossResourceException("Could not find accessor on XADataSource: ", nsme);
204       } // end of catch
205

206       return xads;
207    }
208
209    private void initSelector() throws JBossResourceException
210    {
211       if(urlProperty != null && urlProperty.length() > 0)
212       {
213          String JavaDoc urlsStr = xaProps.getProperty(urlProperty);
214          if(urlsStr != null && urlsStr.trim().length() > 0 && urlDelimeter != null && urlDelimeter.trim().length() > 0)
215          {
216             List JavaDoc xaDataList = new ArrayList JavaDoc();
217
218             // copy xaProps
219
// ctor doesn't work because iteration won't include defaults
220
// Properties xaPropsCopy = new Properties(xaProps);
221
Properties JavaDoc xaPropsCopy = new Properties JavaDoc();
222             for(Iterator JavaDoc i = xaProps.keySet().iterator(); i.hasNext();)
223             {
224                Object JavaDoc key = i.next();
225                xaPropsCopy.put(key, xaProps.get(key));
226             }
227
228             int urlStart = 0;
229             int urlEnd = urlsStr.indexOf(urlDelimeter);
230             while(urlEnd > 0)
231             {
232                String JavaDoc url = urlsStr.substring(urlStart, urlEnd);
233                xaPropsCopy.setProperty(urlProperty, url);
234                XADataSource JavaDoc xads = createXaDataSource(xaPropsCopy);
235                xaDataList.add(new XAData(xads, url));
236                urlStart = ++urlEnd;
237                urlEnd = urlsStr.indexOf(urlDelimeter, urlEnd);
238                log.debug("added XA HA connection url: " + url);
239             }
240
241             if(urlStart != urlsStr.length())
242             {
243                String JavaDoc url = urlsStr.substring(urlStart, urlsStr.length());
244                xaPropsCopy.setProperty(urlProperty, url);
245                XADataSource JavaDoc xads = createXaDataSource(xaPropsCopy);
246                xaDataList.add(new XAData(xads, url));
247                log.debug("added XA HA connection url: " + url);
248             }
249
250             xadsSelector = new XADataSelector(xaDataList);
251          }
252       }
253    }
254
255    // Inner
256

257    public static class XADataSelector
258    {
259       private final List JavaDoc xaDataList;
260       private int xaDataIndex;
261       private XAData xaData;
262
263       public XADataSelector(List JavaDoc xaDataList)
264       {
265          if(xaDataList == null || xaDataList.size() == 0)
266          {
267             throw new IllegalStateException JavaDoc("Expected non-empty list of XADataSource/URL pairs but got: " + xaDataList);
268          }
269
270          this.xaDataList = xaDataList;
271       }
272
273       public synchronized XAData getXAData()
274       {
275          if(xaData == null)
276          {
277             if(xaDataIndex == xaDataList.size())
278             {
279                xaDataIndex = 0;
280             }
281             xaData = (XAData)xaDataList.get(xaDataIndex++);
282          }
283          return xaData;
284       }
285
286       public synchronized void failedXAData(XAData xads)
287       {
288          if(xads.equals(this.xaData))
289          {
290             this.xaData = null;
291          }
292       }
293
294       public List JavaDoc getXADataSourceList()
295       {
296          return xaDataList;
297       }
298    }
299
300    private static class XAData
301    {
302       public final XADataSource JavaDoc xads;
303       public final String JavaDoc url;
304
305       public XAData(XADataSource JavaDoc xads, String JavaDoc url)
306       {
307          this.xads = xads;
308          this.url = url;
309       }
310
311       public boolean equals(Object JavaDoc o)
312       {
313          if(this == o)
314          {
315             return true;
316          }
317          if(!(o instanceof XAData))
318          {
319             return false;
320          }
321
322          final XAData xaData = (XAData)o;
323
324          if(!url.equals(xaData.url))
325          {
326             return false;
327          }
328
329          return true;
330       }
331
332       public int hashCode()
333       {
334          return url.hashCode();
335       }
336
337       public String JavaDoc toString()
338       {
339          return "[XA URL=" + url + "]";
340       }
341    }
342 }
343
Popular Tags