001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.adapter.jdbc.local;
023:
024: import org.jboss.resource.JBossResourceException;
025: import org.jboss.util.JBossStringBuilder;
026:
027: import javax.resource.spi.ManagedConnection;
028: import javax.resource.spi.ConnectionRequestInfo;
029: import javax.resource.ResourceException;
030: import javax.security.auth.Subject;
031: import java.util.List;
032: import java.util.ArrayList;
033: import java.util.Properties;
034: import java.util.Collections;
035: import java.sql.Driver;
036: import java.sql.Connection;
037:
038: /**
039: * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
040: * @version <tt>$Revision: 59773 $</tt>
041: */
042: public class HALocalManagedConnectionFactory extends
043: LocalManagedConnectionFactory {
044: private static final long serialVersionUID = -6506610639011749394L;
045:
046: private URLSelector urlSelector;
047: private String urlDelimiter;
048:
049: public String getURLDelimiter() {
050: return urlDelimiter;
051: }
052:
053: public void setURLDelimiter(String urlDelimiter) {
054: this .urlDelimiter = urlDelimiter;
055: if (getConnectionURL() != null) {
056: initUrlSelector();
057: }
058: }
059:
060: public void setConnectionURL(String connectionURL) {
061: super .setConnectionURL(connectionURL);
062: if (urlDelimiter != null) {
063: initUrlSelector();
064: }
065: }
066:
067: public ManagedConnection createManagedConnection(Subject subject,
068: ConnectionRequestInfo cri) throws ResourceException {
069: boolean trace = log.isTraceEnabled();
070: Properties props = getConnectionProperties(subject, cri);
071: // Some friendly drivers (Oracle, you guessed right) modify the props you supply.
072: // Since we use our copy to identify compatibility in matchManagedConnection, we need
073: // a pristine copy for our own use. So give the friendly driver a copy.
074: Properties copy = (Properties) props.clone();
075: if (trace) {
076: // Make yet another copy to mask the password
077: Properties logCopy = copy;
078: if (copy.getProperty("password") != null) {
079: logCopy = (Properties) props.clone();
080: logCopy.setProperty("password", "--hidden--");
081: }
082: log.trace("Using properties: " + logCopy);
083: }
084:
085: return doCreateManagedConnection(copy, props);
086: }
087:
088: private ManagedConnection doCreateManagedConnection(
089: Properties copy, Properties props)
090: throws JBossResourceException {
091: boolean trace = log.isTraceEnabled();
092:
093: if (urlSelector == null) {
094: JBossStringBuilder buffer = new JBossStringBuilder();
095: buffer
096: .append("Missing configuration for HA local datasource. ");
097: if (getConnectionURL() == null)
098: buffer.append("No connection-url. ");
099: if (urlDelimiter == null)
100: buffer.append("No url-delimiter. ");
101: throw new JBossResourceException(buffer.toString());
102: }
103:
104: // try to get a connection as many times as many urls we have in the list
105: for (int i = 0; i < urlSelector.getUrlList().size(); ++i) {
106: String url = urlSelector.getUrl();
107:
108: if (trace) {
109: log.trace("Trying to create a connection to " + url);
110: }
111:
112: try {
113: Driver d = getDriver(url);
114: Connection con = d.connect(url, copy);
115: if (con == null) {
116: log
117: .warn("Wrong driver class for this connection URL: "
118: + url);
119: urlSelector.failedUrl(url);
120: } else {
121: return new LocalManagedConnection(this , con, props,
122: transactionIsolation,
123: preparedStatementCacheSize);
124: }
125: } catch (Exception e) {
126: log.warn("Failed to create connection for " + url
127: + ": " + e.getMessage());
128: urlSelector.failedUrl(url);
129: }
130: }
131:
132: // we have supposedly tried all the urls
133: throw new JBossResourceException(
134: "Could not create connection using any of the URLs: "
135: + urlSelector.getUrlList());
136: }
137:
138: private void initUrlSelector() {
139: boolean trace = log.isTraceEnabled();
140:
141: List urlsList = new ArrayList();
142: String urlsStr = getConnectionURL();
143: String url;
144: int urlStart = 0;
145: int urlEnd = urlsStr.indexOf(urlDelimiter);
146: while (urlEnd > 0) {
147: url = urlsStr.substring(urlStart, urlEnd);
148: urlsList.add(url);
149: urlStart = ++urlEnd;
150: urlEnd = urlsStr.indexOf(urlDelimiter, urlEnd);
151: if (trace)
152: log.trace("added HA connection url: " + url);
153: }
154:
155: if (urlStart != urlsStr.length()) {
156: url = urlsStr.substring(urlStart, urlsStr.length());
157: urlsList.add(url);
158: if (trace)
159: log.trace("added HA connection url: " + url);
160: }
161:
162: this .urlSelector = new URLSelector(urlsList);
163: }
164:
165: // Inner
166:
167: public static class URLSelector {
168: private final List urls;
169: private int urlIndex;
170: private String url;
171:
172: public URLSelector(List urls) {
173: if (urls == null || urls.size() == 0) {
174: throw new IllegalStateException(
175: "Expected non-empty list of connection URLs but got: "
176: + urls);
177: }
178: this .urls = Collections.unmodifiableList(urls);
179: }
180:
181: public synchronized String getUrl() {
182: if (url == null) {
183: if (urlIndex == urls.size()) {
184: urlIndex = 0;
185: }
186: url = (String) urls.get(urlIndex++);
187: }
188: return url;
189: }
190:
191: public synchronized void failedUrl(String url) {
192: if (url.equals(this .url)) {
193: this .url = null;
194: }
195: }
196:
197: public List getUrlList() {
198: return urls;
199: }
200: }
201: }
|