001: package com.jamonapi.proxy;
002:
003: import java.util.Properties;
004: import java.util.regex.Matcher;
005: import java.util.regex.Pattern;
006:
007: import java.sql.*;
008: import com.jamonapi.*;
009: import com.jamonapi.utils.Misc;
010:
011: /** This class will be a proxy for the underlying jdbc driver.
012: * @author steve souza
013: *
014: */
015: public class JAMonDriver implements Driver {
016: private static final String jamonURL = "jdbc:jamon:";
017: static {
018: try {
019: registerDriver("com.jamonapi.proxy.JAMonDriver");
020: } catch (Exception e) {/* can't happen */
021: }
022: ;
023: }
024:
025: private static Driver registerDriver(String className)
026: throws SQLException {
027: Driver d = null;
028:
029: try {
030: d = (Driver) Class.forName(className).newInstance();
031: DriverManager.registerDriver(d);
032: } catch (Exception e) {
033: String message = "MonProxy-Exception: loading JDBC Driver="
034: + e.getMessage();
035: MonitorFactory.add(new MonKeyImp(message, new Object[] {
036: message, Misc.getExceptionTrace(e) }, "Exception"),
037: 1);
038: // MonitorFactory.add(message, "Exception",1);
039: DriverManager.println(message);
040: throw new SQLException("Can not load real driver ("
041: + className + ") from JAMonDriver: "
042: + e.getLocalizedMessage());
043: }
044: return d;
045:
046: }
047:
048: /**
049: * (non-Javadoc)
050: * @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
051: */
052: public Connection connect(String url, Properties info)
053: throws SQLException {
054:
055: if (!acceptsURL(url))
056: return null;
057: // use jamonrealdriver from properties if it is there.
058: URLInfo urlInfo = new URLInfo(url, info);
059: Driver realDriver = getRegisteredDriver(urlInfo.getRealURL());
060:
061: if (realDriver == null) {
062: // for example: com.sybase.jdbc2.jdbc.SybDriver
063: realDriver = registerDriver(urlInfo.getRealDriverName());
064: }
065:
066: Monitor mon = MonitorFactory
067: .start("MonProxy-Interface (class=com.jamonapi.proxy.JAMonDriver): public java.sql.Connection com.jamonapi.proxy.JAMonDriver.connect(java.lang.String, java.util.Properties) throws java.sql.SQLException");
068: Connection conn = null;
069: try {
070: conn = MonProxyFactory.monitor(realDriver.connect(urlInfo
071: .getRealURL(), info));
072: } catch (SQLException sqlException) {
073: String sqlMessage = ",ErrorCode="
074: + sqlException.getErrorCode() + ",SQLState="
075: + sqlException.getSQLState();
076: String label = "MonProxy-Exception: Root cause exception="
077: + sqlException.getClass().getName() + sqlMessage;
078: MonKey key = new MonKeyImp(label, new Object[] { label,
079: Misc.getExceptionTrace(sqlException) }, "Exception");
080: MonitorFactory.add(key, 1); // Message for the exception
081: throw sqlException;
082: } finally {
083: mon.stop();
084: }
085:
086: // call the following method just in case the realDriver returns a proxied connection itself.
087: return conn;
088: }
089:
090: private Driver getRegisteredDriver(String url) {
091: Driver registeredDriver = null;
092: try {
093: registeredDriver = DriverManager.getDriver(url);
094: } catch (Exception e) {/* not an error */
095: }
096:
097: return registeredDriver;
098: }
099:
100: /** Returns true if this driver can respond to the url */
101: public boolean acceptsURL(String url) throws SQLException {
102: if (url == null)
103: return false;
104: else if (url.toLowerCase().startsWith(jamonURL))
105: return true;
106: else
107: return false;
108:
109: }
110:
111: /** Returns this drivers properties. Currently the only property is 'jamonrealdriver' */
112: public DriverPropertyInfo[] getPropertyInfo(String url,
113: Properties info) throws SQLException {
114: return new DriverPropertyInfo[] { getPropertyInfo(
115: "jamonrealdriver",
116: null,
117: "The driver to be proxy monitored. Example: jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?LITERAL_PARAMS=true&PACKETSIZE=512&jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&HOSTNAME=myhost",
118: true), };
119: }
120:
121: private static DriverPropertyInfo getPropertyInfo(String name,
122: String value, String description, boolean required) {
123: DriverPropertyInfo prop = new DriverPropertyInfo(name, value);
124: prop.description = description;
125: prop.required = required;
126:
127: return prop;
128: }
129:
130: public int getMajorVersion() {
131: return 2;
132: }
133:
134: public int getMinorVersion() {
135: return 3;
136: }
137:
138: public boolean jdbcCompliant() {
139: return true;
140: }
141:
142: /** Takes a url of the jamon format: jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&LITERAL_PARAMS=true&PACKETSIZE=512&HOSTNAME=myhost
143: and returns: com.sybase.jdbc3.jdbc.SybDriver
144: */
145:
146: public static String getRealDriverName(String url) {
147: return new URLInfo(url).getRealDriverName();
148: }
149:
150: /** Takes a url of the jamon format: jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&LITERAL_PARAMS=true&PACKETSIZE=512&HOSTNAME=myhost
151: and returns the real url associated with the underlying driver: jdbc:sybase:Tds:myserver:1234/mydatabase?LITERAL_PARAMS=true&PACKETSIZE=512&HOSTNAME=myhost
152: */
153: public static String getRealURL(String url) {
154: return new URLInfo(url).getRealURL();
155: }
156:
157: // Parses a passed in URL.
158: private static class URLInfo {
159: String realDriverName;
160: String realURL;
161: String jamonURL;
162:
163: // sample url: jdbc:jamon:hsqldb:.:pw=steve;jamonrealDriver=org.hsqldb.jdbcDriver;
164: URLInfo(String jamonURL) {
165: this (jamonURL, null);
166: }
167:
168: // sample url: jdbc:jamon:hsqldb:.:pw=steve;jamonrealDriver=org.hsqldb.jdbcDriver;
169: URLInfo(String jamonURL, Properties info) {
170: this .jamonURL = jamonURL;
171: // .*jamonrealdriver - any characters up to jamonrealdriver
172: // [\\s=]* - any number of optional spaces surrounding the equal sign.
173: // ([\\w\\.]*) - trying to get a package name which can have any number of characters [a-zA-Z_0-9] and '.'. This value is what is needed
174: // [\\W]? - 0 or 1 characters that aren't in a package name.
175: realDriverName = (info == null) ? null : info
176: .getProperty("jamonrealdriver");
177: if (realDriverName == null)
178: realDriverName = parseURL(
179: ".*jamonrealdriver[\\s=]*([\\w\\.]*)[\\W]?",
180: jamonURL);
181:
182: // remove all traces of jamon in the url. this might not strictly be required as drivers
183: // probably ignore anything they don't recognize
184: realURL = jamonURL.replaceAll("jdbc:jamon:", "jdbc:");
185: realURL = realURL.replaceAll(
186: "jamonrealdriver[\\s=\\.\\w]*[\\W]?", "");
187: }
188:
189: private String parseURL(String pattern, String url) {
190: String result = "";
191: if (url == null)
192: return result;
193:
194: Pattern re = Pattern.compile(pattern);
195: Matcher matcher = re.matcher(url);
196: if (matcher.lookingAt())
197: result = matcher.group(1);
198:
199: return result.trim();
200: }
201:
202: String getRealDriverName() {
203: return realDriverName;
204: }
205:
206: String getRealURL() {
207: return realURL;
208: }
209:
210: String getJAMonURL() {
211: return jamonURL;
212: }
213:
214: }
215:
216: public static void main(String[] args) throws Exception {
217: String drivers[] = {
218: "jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&LITERAL_PARAMS=true&PACKETSIZE=512&HOSTNAME=myhost",
219: "jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?LITERAL_PARAMS=true&PACKETSIZE=512&HOSTNAME=myhost&jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver2",
220: "jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?LITERAL_PARAMS=true&PACKETSIZE=512&jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&HOSTNAME=myhost",
221: "jdbc:jamon:sybase:Tds:myserver:1234/mydatabase?LITERAL_PARAMS=true&PACKETSIZE=512&jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver&HOSTNAME=myhost",
222: "jdbc:jamon:hsqldb:.jamonrealdriver = org.hsqldb.jdbcDriver;",
223: "jdbc:jamon:hsqldb:.jamonrealdriver = org.hsqldb.jdbcDriver:",
224: "jdbc:jamon:hsqldb:.jamonrealdriver = org.hsqldb.jdbcDriver",
225: "jdbc:jamon:microsoft:sqlserver://localhost:1433;jamonrealdriver=com.microsoft.jdbc.sqlserver.SQLServerDriver",
226: "jdbc:jamon:microsoft:sqlserver:sybase:Tds:127.0.0.1:5000/dbname;jamonrealdriver=com.sybase.jdbc3.jdbc.SybDriver",
227: "jdbc:jamon:informix-sqli://161.144.202.206:3000:INFORMIXSERVER=stars:jamonrealdriver= com.informix.jdbc.IfxDriver:" };
228:
229: for (int i = 0; i < drivers.length; i++) {
230: URLInfo ui = new URLInfo(drivers[i], null);
231: System.out.println("\ni=" + i + "\njamonURL="
232: + ui.getJAMonURL());
233: System.out.println("readdrivername="
234: + ui.getRealDriverName());
235: System.out.println("realurl=" + ui.getRealURL());
236: }
237:
238: for (int i = 0; i < 5; i++) {
239: Properties props = new Properties();
240: props.put("user", "sa");
241: props.put("password", "");
242: Connection conn = null;
243: if (i % 2 == 0) {
244: props.put("jamonrealdriver", "org.hsqldb.jdbcDriver");
245: conn = DriverManager.getConnection(
246: "jdbc:jamon:hsqldb:.", props);
247: } else
248: conn = DriverManager
249: .getConnection(
250: "jdbc:jamon:hsqldb:.jamonrealdriver=org.hsqldb.jdbcDriver",
251: props);
252:
253: Statement s = conn.createStatement();
254: s.close();
255: conn.close();
256: }
257:
258: System.out.println(MonitorFactory.getReport());
259:
260: }
261:
262: }
|