[jboss-cvs] JBossAS SVN: r62221 - trunk/connector/src/main/org/jboss/resource/adapter/jdbc/xa.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Apr 10 12:17:51 EDT 2007


Author: vicky.kak at jboss.com
Date: 2007-04-10 12:17:51 -0400 (Tue, 10 Apr 2007)
New Revision: 62221

Modified:
   trunk/connector/src/main/org/jboss/resource/adapter/jdbc/xa/XAManagedConnectionFactory.java
Log:
[JBAS-3707] Changes 


Modified: trunk/connector/src/main/org/jboss/resource/adapter/jdbc/xa/XAManagedConnectionFactory.java
===================================================================
--- trunk/connector/src/main/org/jboss/resource/adapter/jdbc/xa/XAManagedConnectionFactory.java	2007-04-10 16:14:29 UTC (rev 62220)
+++ trunk/connector/src/main/org/jboss/resource/adapter/jdbc/xa/XAManagedConnectionFactory.java	2007-04-10 16:17:51 UTC (rev 62221)
@@ -22,6 +22,7 @@
 package org.jboss.resource.adapter.jdbc.xa;
 
 import org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnectionFactory;
+import org.jboss.resource.adapter.jdbc.URLSelectorStrategy;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.beans.PropertyEditorManager;
@@ -32,7 +33,9 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Properties;
 import java.util.Set;
 import javax.resource.ResourceException;
@@ -61,7 +64,257 @@
    private Boolean isSameRMOverrideValue;
 
    private XADataSource xads;
+   
+   private String urlProperty;
 
+   private URLSelectorStrategy xadsSelector;
+
+   public String getURLProperty()
+   {
+      return urlProperty;
+   }
+
+   public void setURLProperty(String urlProperty) throws ResourceException
+   {
+      this.urlProperty = urlProperty;
+      initSelector();
+   }
+
+   public void setURLDelimiter(String urlDelimiter) throws ResourceException
+   {
+      this.urlDelimiter = urlDelimiter;
+      initSelector();
+   }
+
+   private void initSelector() throws JBossResourceException
+   {
+      if(urlProperty != null && urlProperty.length() > 0)
+      {
+         String urlsStr = xaProps.getProperty(urlProperty);
+         if(urlsStr != null && urlsStr.trim().length() > 0 && urlDelimiter != null && urlDelimiter.trim().length() > 0)
+         {
+            List xaDataList = new ArrayList();
+
+            // copy xaProps
+            // ctor doesn't work because iteration won't include defaults
+            // Properties xaPropsCopy = new Properties(xaProps);
+            Properties xaPropsCopy = new Properties();
+            for(Iterator i = xaProps.keySet().iterator(); i.hasNext();)
+            {
+               Object key = i.next();
+               xaPropsCopy.put(key, xaProps.get(key));
+            }
+
+            int urlStart = 0;
+            int urlEnd = urlsStr.indexOf(urlDelimiter);
+            while(urlEnd > 0)
+            {
+               String url = urlsStr.substring(urlStart, urlEnd);
+               xaPropsCopy.setProperty(urlProperty, url);
+               XADataSource xads = createXaDataSource(xaPropsCopy);
+               xaDataList.add(new XAData(xads, url));
+               urlStart = ++urlEnd;
+               urlEnd = urlsStr.indexOf(urlDelimiter, urlEnd);
+               log.debug("added XA HA connection url: " + url);
+            }
+
+            if(urlStart != urlsStr.length())
+            {
+               String url = urlsStr.substring(urlStart, urlsStr.length());
+               xaPropsCopy.setProperty(urlProperty, url);
+               XADataSource xads = createXaDataSource(xaPropsCopy);
+               xaDataList.add(new XAData(xads, url));
+               log.debug("added XA HA connection url: " + url);
+            }
+			if(getUrlSelectorStrategyClassName()==null)
+			{
+	            xadsSelector = new XADataSelector(xaDataList);
+				log.debug("Default URLSelectorStrategy is being used : "+xadsSelector);
+			}
+			else
+			{
+				xadsSelector = (URLSelectorStrategy)loadClass(getUrlSelectorStrategyClassName(),xaDataList);
+				log.debug("Customized URLSelectorStrategy is being used : "+xadsSelector);
+			}
+         }
+      }
+   }
+
+   private XADataSource createXaDataSource(Properties xaProps)
+   throws JBossResourceException
+   {
+   if(getXADataSourceClass() == null)
+   {
+      throw new JBossResourceException("No XADataSourceClass supplied!");
+   }
+
+   XADataSource xads;
+   try
+   {
+      Class clazz = Thread.currentThread().getContextClassLoader().loadClass(getXADataSourceClass());
+      xads = (XADataSource)clazz.newInstance();
+      Class[] NOCLASSES = new Class[]{};
+      for(Iterator i = xaProps.keySet().iterator(); i.hasNext();)
+      {
+         String name = (String)i.next();
+         String value = xaProps.getProperty(name);
+         //This is a bad solution.  On the other hand the only known example
+         // of a setter with no getter is for Oracle with password.
+         //Anyway, each xadatasource implementation should get its
+         //own subclass of this that explicitly sets the
+         //properties individually.
+         Class type = null;
+         try
+         {
+            Method getter = clazz.getMethod("get" + name, NOCLASSES);
+            type = getter.getReturnType();
+         }
+         catch(NoSuchMethodException e)
+         {
+            type = String.class;
+         } // end of try-catch
+
+         Method setter = clazz.getMethod("set" + name, new Class[]{type});
+         PropertyEditor editor = PropertyEditorManager.findEditor(type);
+         if(editor == null)
+         {
+            throw new JBossResourceException("No property editor found for type: " + type);
+         } // end of if ()
+         editor.setAsText(value);
+         setter.invoke(xads, new Object[]{editor.getValue()});
+
+      } // end of for ()
+   }
+   catch(ClassNotFoundException cnfe)
+   {
+      throw new JBossResourceException("Class not found for XADataSource " + getXADataSourceClass(), cnfe);
+   } // end of try-catch
+   catch(InstantiationException ie)
+   {
+      throw new JBossResourceException("Could not create an XADataSource: ", ie);
+   } // end of catch
+   catch(IllegalAccessException iae)
+   {
+      throw new JBossResourceException("Could not set a property: ", iae);
+   } // end of catch
+
+   catch(IllegalArgumentException iae)
+   {
+      throw new JBossResourceException("Could not set a property: ", iae);
+   } // end of catch
+
+   catch(InvocationTargetException ite)
+   {
+      throw new JBossResourceException("Could not invoke setter on XADataSource: ", ite);
+   } // end of catch
+   catch(NoSuchMethodException nsme)
+   {
+      throw new JBossResourceException("Could not find accessor on XADataSource: ", nsme);
+   } // end of catch
+
+   return xads;
+   }
+   
+   // Default Implementaion of the URLSelectorStrategy
+   public static class XADataSelector implements URLSelectorStrategy
+   {
+      private final List xaDataList;
+      private int xaDataIndex;
+      private XAData xaData;
+	  
+      public XADataSelector(List xaDataList)
+      {
+         if(xaDataList == null || xaDataList.size() == 0)
+         {
+            throw new IllegalStateException("Expected non-empty list of XADataSource/URL pairs but got: " + xaDataList);
+         }
+
+         this.xaDataList = xaDataList;
+      }
+
+      public synchronized XAData getXAData()
+      {
+         if(xaData == null)
+         {
+            if(xaDataIndex == xaDataList.size())
+            {
+               xaDataIndex = 0;
+            }
+            xaData = (XAData)xaDataList.get(xaDataIndex++);
+         }
+         return xaData;
+      }
+
+      public synchronized void failedXAData(XAData xads)
+      {
+         if(xads.equals(this.xaData))
+         {
+            this.xaData = null;
+         }
+      }
+
+	  /* URLSelectorStrategy Implementation goes here*/	  
+	  public List getCustomSortedUrls()
+	  {
+		 return xaDataList;
+	  }
+	  public void failedUrlObject(Object urlObject)
+	  {
+		 failedXAData((XAData)urlObject);
+	  }
+	  public List getAllUrlObjects()
+	  {
+		 return xaDataList;
+      }
+	  public Object getUrlObject()
+	  {
+		 return getXAData();
+	  }	  
+   }
+   
+   private static class XAData
+   {
+      public final XADataSource xads;
+      public final String url;
+
+      public XAData(XADataSource xads, String url)
+      {
+         this.xads = xads;
+         this.url = url;
+      }
+
+      public boolean equals(Object o)
+      {
+         if(this == o)
+         {
+            return true;
+         }
+         if(!(o instanceof XAData))
+         {
+            return false;
+         }
+
+         final XAData xaData = (XAData)o;
+
+         if(!url.equals(xaData.url))
+         {
+            return false;
+         }
+
+         return true;
+      }
+
+      public int hashCode()
+      {
+         return url.hashCode();
+      }
+
+      public String toString()
+      {
+         return "[XA URL=" + url + "]";
+      }
+   }
+
    public XAManagedConnectionFactory()
    {
    }
@@ -120,6 +373,7 @@
             throw new JBossResourceException("Could not load connection properties", ioe);
          }
       }
+      initSelector();
    }
 
    /**
@@ -143,25 +397,60 @@
    }
 
    public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cri)
-         throws javax.resource.ResourceException
+   		throws javax.resource.ResourceException
    {
-      Properties props = getConnectionProperties(subject, cri);
-      try
-      {
-         final String user = props.getProperty("user");
-         final String password = props.getProperty("password");
-
-         XAConnection xaConnection = (user != null)
-               ? getXADataSource().getXAConnection(user, password)
-               : getXADataSource().getXAConnection();
-
-         return newXAManagedConnection(props, xaConnection);
-      }
-      catch (Exception e)
-      {
-         throw new JBossResourceException("Could not create connection", e);
-      }
+	   if(xadsSelector == null)
+	   {
+		  return getXAManagedConnection(subject,cri);
+	   }
+	
+	   // try to get a connection as many times as many urls we have in the list
+	   for(int i = 0; i < xadsSelector.getCustomSortedUrls().size(); ++i)
+	   {
+		  XAData xaData = (XAData)xadsSelector.getUrlObject();
+	
+	      if(log.isTraceEnabled())
+	      {
+	         log.trace("Trying to create an XA connection to " + xaData.url);
+	      }
+	
+	      try
+	      {
+	    	  return getXAManagedConnection(subject,cri);
+	      }
+	      catch(ResourceException e)
+	      {
+	         log.warn("Failed to create an XA connection to " + xaData.url + ": " + e.getMessage());
+			 xadsSelector.failedUrlObject(xaData);
+	      }
+	   }
+	
+	   // we have supposedly tried all the urls
+	   throw new JBossResourceException(
+	      "Could not create connection using any of the URLs: " + xadsSelector.getAllUrlObjects()
+	   );	   
    }
+   
+   public ManagedConnection getXAManagedConnection(Subject subject, ConnectionRequestInfo cri)
+   		throws javax.resource.ResourceException
+	{
+		Properties props = getConnectionProperties(subject, cri);
+		try
+		{
+		   final String user = props.getProperty("user");
+		   final String password = props.getProperty("password");
+		
+		   XAConnection xaConnection = (user != null)
+				 ? getXADataSource().getXAConnection(user, password)
+				 : getXADataSource().getXAConnection();
+		
+		   return newXAManagedConnection(props, xaConnection);
+		}
+		catch (Exception e)
+		{
+		   throw new JBossResourceException("Could not create connection", e);
+		}
+	}
 
    /**
     * This method can be overwritten by sublcasses to provide rm specific
@@ -226,7 +515,12 @@
    }
 
    protected synchronized XADataSource getXADataSource() throws ResourceException
-   {
+   { 
+	  if(xadsSelector != null)
+	  {
+		   XAData xada = (XAData)xadsSelector.getUrlObject();
+		   return xada.xads;
+	  }
       if (xads == null)
       {
          if (xaDataSourceClass == null)




More information about the jboss-cvs-commits mailing list