1 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 ; 28 import javax.resource.spi.ManagedConnection ; 29 import javax.resource.spi.ConnectionRequestInfo ; 30 import javax.sql.XADataSource ; 31 import javax.security.auth.Subject ; 32 import java.util.List ; 33 import java.util.ArrayList ; 34 import java.util.Properties ; 35 import java.util.Iterator ; 36 import java.lang.reflect.Method ; 37 import java.lang.reflect.InvocationTargetException ; 38 import java.beans.PropertyEditorManager ; 39 import java.beans.PropertyEditor ; 40 41 45 public class HAXAManagedConnectionFactory 46 extends XAManagedConnectionFactory 47 { 48 private static final long serialVersionUID = 1898242235188801452L; 49 50 private String urlProperty; 51 private String urlDelimeter; 52 private XADataSelector xadsSelector; 53 54 public String getURLProperty() 55 { 56 return urlProperty; 57 } 58 59 public void setURLProperty(String urlProperty) throws ResourceException 60 { 61 this.urlProperty = urlProperty; 62 initSelector(); 63 } 64 65 public String getURLDelimeter() 66 { 67 return urlDelimeter; 68 } 69 70 public void setURLDelimeter(String urlDelimeter) throws ResourceException 71 { 72 this.urlDelimeter = urlDelimeter; 73 initSelector(); 74 } 75 76 public void setXADataSourceProperties(String xaDataSourceProperties) throws ResourceException 77 { 78 super.setXADataSourceProperties(xaDataSourceProperties); 79 initSelector(); 80 } 81 82 84 public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cri) 85 throws javax.resource.ResourceException 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 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 throw new JBossResourceException( 123 "Could not create connection using any of the URLs: " + xadsSelector.getXADataSourceList() 124 ); 125 } 126 127 protected synchronized XADataSource getXADataSource() throws ResourceException 128 { 129 return xadsSelector.getXAData().xads; 130 } 131 132 134 private XADataSource createXaDataSource(Properties xaProps) 135 throws JBossResourceException 136 { 137 if(getXADataSourceClass() == null) 138 { 139 throw new JBossResourceException("No XADataSourceClass supplied!"); 140 } 141 142 XADataSource xads; 143 try 144 { 145 Class clazz = Thread.currentThread().getContextClassLoader().loadClass(getXADataSourceClass()); 146 xads = (XADataSource )clazz.newInstance(); 147 Class [] NOCLASSES = new Class []{}; 148 for(Iterator i = xaProps.keySet().iterator(); i.hasNext();) 149 { 150 String name = (String )i.next(); 151 String value = xaProps.getProperty(name); 152 Class type = null; 158 try 159 { 160 Method getter = clazz.getMethod("get" + name, NOCLASSES); 161 type = getter.getReturnType(); 162 } 163 catch(NoSuchMethodException e) 164 { 165 type = String .class; 166 } 168 Method setter = clazz.getMethod("set" + name, new Class []{type}); 169 PropertyEditor editor = PropertyEditorManager.findEditor(type); 170 if(editor == null) 171 { 172 throw new JBossResourceException("No property editor found for type: " + type); 173 } editor.setAsText(value); 175 setter.invoke(xads, new Object []{editor.getValue()}); 176 177 } } 179 catch(ClassNotFoundException cnfe) 180 { 181 throw new JBossResourceException("Class not found for XADataSource " + getXADataSourceClass(), cnfe); 182 } catch(InstantiationException ie) 184 { 185 throw new JBossResourceException("Could not create an XADataSource: ", ie); 186 } catch(IllegalAccessException iae) 188 { 189 throw new JBossResourceException("Could not set a property: ", iae); 190 } 192 catch(IllegalArgumentException iae) 193 { 194 throw new JBossResourceException("Could not set a property: ", iae); 195 } 197 catch(InvocationTargetException ite) 198 { 199 throw new JBossResourceException("Could not invoke setter on XADataSource: ", ite); 200 } catch(NoSuchMethodException nsme) 202 { 203 throw new JBossResourceException("Could not find accessor on XADataSource: ", nsme); 204 } 206 return xads; 207 } 208 209 private void initSelector() throws JBossResourceException 210 { 211 if(urlProperty != null && urlProperty.length() > 0) 212 { 213 String urlsStr = xaProps.getProperty(urlProperty); 214 if(urlsStr != null && urlsStr.trim().length() > 0 && urlDelimeter != null && urlDelimeter.trim().length() > 0) 215 { 216 List xaDataList = new ArrayList (); 217 218 Properties xaPropsCopy = new Properties (); 222 for(Iterator i = xaProps.keySet().iterator(); i.hasNext();) 223 { 224 Object 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 url = urlsStr.substring(urlStart, urlEnd); 233 xaPropsCopy.setProperty(urlProperty, url); 234 XADataSource 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 url = urlsStr.substring(urlStart, urlsStr.length()); 244 xaPropsCopy.setProperty(urlProperty, url); 245 XADataSource 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 257 public static class XADataSelector 258 { 259 private final List xaDataList; 260 private int xaDataIndex; 261 private XAData xaData; 262 263 public XADataSelector(List xaDataList) 264 { 265 if(xaDataList == null || xaDataList.size() == 0) 266 { 267 throw new IllegalStateException ("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 getXADataSourceList() 295 { 296 return xaDataList; 297 } 298 } 299 300 private static class XAData 301 { 302 public final XADataSource xads; 303 public final String url; 304 305 public XAData(XADataSource xads, String url) 306 { 307 this.xads = xads; 308 this.url = url; 309 } 310 311 public boolean equals(Object 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 toString() 338 { 339 return "[XA URL=" + url + "]"; 340 } 341 } 342 } 343 | Popular Tags |