001: /*
002: * Jython Database Specification API 2.0
003: *
004: * $Id: Connectx.java 2617 2005-10-21 21:19:10Z otmarhumbel $
005: *
006: * Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
007: *
008: */
009: package com.ziclix.python.sql.connect;
010:
011: import java.lang.reflect.Field;
012: import java.lang.reflect.InvocationTargetException;
013: import java.lang.reflect.Method;
014: import java.sql.Connection;
015: import java.sql.SQLException;
016:
017: import javax.sql.ConnectionPoolDataSource;
018: import javax.sql.DataSource;
019:
020: import org.python.core.Py;
021: import org.python.core.PyClass;
022: import org.python.core.PyObject;
023: import org.python.core.PyString;
024:
025: import com.ziclix.python.sql.PyConnection;
026: import com.ziclix.python.sql.zxJDBC;
027: import com.ziclix.python.sql.util.PyArgParser;
028:
029: /**
030: * Connect using through a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource.
031: *
032: * @author brian zimmer
033: * @author last revised by $Author: otmarhumbel $
034: * @version $Revision: 2617 $
035: */
036: public class Connectx extends PyObject {
037:
038: private final String SET = "set";
039: private final PyString doc = new PyString(
040: "establish a connection through a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource");
041:
042: /**
043: * Constructor Connectx
044: */
045: public Connectx() {
046: }
047:
048: /**
049: * Method __findattr__
050: *
051: * @param String name
052: * @return PyObject
053: */
054: public PyObject __findattr__(String name) {
055:
056: if ("__doc__".equals(name)) {
057: return doc;
058: }
059:
060: return super .__findattr__(name);
061: }
062:
063: /**
064: * Construct a javax.sql.DataSource or javax.sql.ConnectionPooledDataSource
065: */
066: public PyObject __call__(PyObject[] args, String[] keywords) {
067:
068: Connection c = null;
069: PyConnection pc = null;
070: Object datasource = null;
071: PyArgParser parser = new PyArgParser(args, keywords);
072:
073: try {
074: String _class = (String) parser.arg(0).__tojava__(
075: String.class);
076:
077: datasource = Class.forName(_class).newInstance();
078: } catch (Exception e) {
079: throw zxJDBC.makeException(zxJDBC.DatabaseError,
080: "unable to instantiate datasource");
081: }
082:
083: String[] kws = parser.kws();
084: Class clazz = datasource.getClass();
085:
086: for (int i = 0; i < kws.length; i++) {
087: String methodName = kws[i];
088:
089: if (methodName == null) {
090: continue;
091: }
092:
093: Object value = parser.kw(kws[i]).__tojava__(Object.class);
094:
095: if (methodName.length() > SET.length()) {
096: if (!SET.equals(methodName.substring(0, SET.length()))) {
097:
098: // prepend "set"
099: invoke(datasource, SET
100: + methodName.substring(0, 1).toUpperCase()
101: + methodName.substring(1), value);
102: } else {
103:
104: // starts with "set" so just pass it on
105: invoke(datasource, methodName, value);
106: }
107: } else {
108:
109: // shorter than "set" so it can't be a full method name
110: invoke(datasource, SET
111: + methodName.substring(0, 1).toUpperCase()
112: + methodName.substring(1), value);
113: }
114: }
115:
116: try {
117: if (datasource instanceof ConnectionPoolDataSource) {
118: c = ((ConnectionPoolDataSource) datasource)
119: .getPooledConnection().getConnection();
120: } else if (datasource instanceof DataSource) {
121: c = ((DataSource) datasource).getConnection();
122: }
123: } catch (SQLException e) {
124: throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
125: }
126:
127: try {
128: if ((c == null) || c.isClosed()) {
129: throw zxJDBC.makeException(zxJDBC.DatabaseError,
130: "unable to establish connection");
131: }
132:
133: pc = new PyConnection(c);
134: } catch (SQLException e) {
135: throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
136: }
137:
138: return pc;
139: }
140:
141: /**
142: * Method toString
143: *
144: * @return String
145: */
146: public String toString() {
147: return "<connectx object instance at " + Py.id(this ) + ">";
148: }
149:
150: /**
151: * Method invoke
152: *
153: * @param Object src
154: * @param String methodName
155: * @param Object value
156: */
157: protected void invoke(Object src, String methodName, Object value) {
158:
159: Method method = null;
160: StringBuffer exceptionMsg = new StringBuffer("method [")
161: .append(methodName).append("] using arg type [");
162:
163: exceptionMsg.append(value.getClass()).append("], value [")
164: .append(value.toString()).append("]");
165:
166: try {
167: method = getMethod(src.getClass(), methodName, value
168: .getClass());
169:
170: if (method == null) {
171: throw zxJDBC.makeException("no such " + exceptionMsg);
172: }
173:
174: method.invoke(src, new Object[] { value });
175: } catch (IllegalAccessException e) {
176: throw zxJDBC.makeException("illegal access for "
177: + exceptionMsg);
178: } catch (InvocationTargetException e) {
179: throw zxJDBC
180: .makeException("invocation target exception for "
181: + exceptionMsg);
182: }
183:
184: return;
185: }
186:
187: /**
188: * Try to find the method by the given name. If failing that, see if the valueClass
189: * is perhaps a primitive and attempt to recurse using the primitive type. Failing
190: * that return null.
191: */
192: protected Method getMethod(Class srcClass, String methodName,
193: Class valueClass) {
194:
195: Method method = null;
196:
197: try {
198: method = srcClass.getMethod(methodName,
199: new Class[] { valueClass });
200: } catch (NoSuchMethodException e) {
201: Class primitive = null;
202:
203: try {
204: Field f = valueClass.getField("TYPE");
205:
206: primitive = (Class) f.get(valueClass);
207: } catch (NoSuchFieldException ex) {
208: } catch (IllegalAccessException ex) {
209: } catch (ClassCastException ex) {
210: }
211:
212: if ((primitive != null) && primitive.isPrimitive()) {
213: return getMethod(srcClass, methodName, primitive);
214: }
215: }
216:
217: return method;
218: }
219:
220: // __class__ boilerplate -- see PyObject for details
221:
222: /**
223: * Field __class__
224: */
225: public static PyClass __class__;
226:
227: /**
228: * Method getPyClass
229: *
230: * @return PyClass
231: */
232: protected PyClass getPyClass() {
233: return __class__;
234: }
235: }
|