001: /*
002: * Jython Database Specification API 2.0
003: *
004: * $Id: Lookup.java 2414 2005-02-23 04:26:23Z bzimmer $
005: *
006: * Copyright (c) 2001 brian zimmer <bzimmer@ziclix.com>
007: *
008: */
009: package com.ziclix.python.sql.connect;
010:
011: import java.sql.*;
012: import java.util.*;
013: import java.lang.reflect.Field;
014: import javax.sql.*;
015: import javax.naming.*;
016:
017: import org.python.core.*;
018: import com.ziclix.python.sql.*;
019: import com.ziclix.python.sql.util.*;
020:
021: /**
022: * Establish a connection through a JNDI lookup. The bound object can be either a <code>DataSource</code>,
023: * <code>ConnectionPooledDataSource</code>, <code>Connection</code> or a <code>String</code>. If it's a
024: * <code>String</code> the value is passed to the DriverManager to obtain a connection, otherwise the
025: * <code>Connection</code> is established using the object.
026: *
027: * @author brian zimmer
028: * @author last revised by $Author: bzimmer $
029: * @version $Revision: 2414 $
030: */
031: public class Lookup extends PyObject {
032:
033: private static final PyString _doc = new PyString(
034: "establish a connection through a JNDI lookup");
035:
036: /**
037: * Constructor Lookup
038: */
039: public Lookup() {
040: }
041:
042: /**
043: * Method __findattr__
044: *
045: * @param name
046: * @return PyObject
047: */
048: public PyObject __findattr__(String name) {
049:
050: if ("__doc__".equals(name)) {
051: return _doc;
052: }
053:
054: return super .__findattr__(name);
055: }
056:
057: /**
058: * Expects a single PyString argument which is the JNDI name of the bound Connection or DataSource.
059: * If any keywords are passed, an attempt is made to match the keyword to a static final Field on
060: * javax.naming.Context. If the Field is found, the value of the Field is substituted as the key
061: * and the value of the keyword is the value put in the Hashtable environment. If the Field is not
062: * found, the key is the keyword with no substitutions.
063: */
064: public PyObject __call__(PyObject[] args, String[] keywords) {
065:
066: Object ref = null;
067: Connection connection = null;
068: Hashtable env = new Hashtable();
069:
070: // figure out the correct params
071: PyArgParser parser = new PyArgParser(args, keywords);
072: Object jndiName = parser.arg(0).__tojava__(String.class);
073:
074: if ((jndiName == null) || (jndiName == Py.NoConversion)) {
075: throw zxJDBC.makeException(zxJDBC.DatabaseError,
076: "lookup name is null");
077: }
078:
079: // add any Context properties
080: String[] kws = parser.kws();
081:
082: for (int i = 0; i < kws.length; i++) {
083: String keyword = kws[i], fieldname = null;
084: Object value = parser.kw(keyword).__tojava__(Object.class);
085:
086: try {
087: Field field = Context.class.getField(keyword);
088:
089: fieldname = (String) field.get(Context.class);
090: } catch (IllegalAccessException e) {
091: throw zxJDBC.makeException(zxJDBC.ProgrammingError, e);
092: } catch (NoSuchFieldException e) {
093: fieldname = keyword;
094: }
095:
096: env.put(fieldname, value);
097: }
098:
099: InitialContext context = null;
100:
101: try {
102: context = new InitialContext(env);
103: ref = context.lookup((String) jndiName);
104: } catch (NamingException e) {
105: throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
106: } finally {
107: if (context != null) {
108: try {
109: context.close();
110: } catch (NamingException e) {
111: }
112: }
113: }
114:
115: if (ref == null) {
116: throw zxJDBC.makeException(zxJDBC.ProgrammingError,
117: "object [" + jndiName + "] not found in JNDI");
118: }
119:
120: try {
121: if (ref instanceof String) {
122: connection = DriverManager
123: .getConnection(((String) ref));
124: } else if (ref instanceof Connection) {
125: connection = (Connection) ref;
126: } else if (ref instanceof DataSource) {
127: connection = ((DataSource) ref).getConnection();
128: } else if (ref instanceof ConnectionPoolDataSource) {
129: connection = ((ConnectionPoolDataSource) ref)
130: .getPooledConnection().getConnection();
131: }
132: } catch (SQLException e) {
133: throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
134: }
135:
136: try {
137: if ((connection == null) || connection.isClosed()) {
138: throw zxJDBC.makeException(zxJDBC.DatabaseError,
139: "unable to establish connection");
140: }
141:
142: return new PyConnection(connection);
143: } catch (SQLException e) {
144: throw zxJDBC.makeException(zxJDBC.DatabaseError, e);
145: }
146: }
147:
148: /**
149: * Method toString
150: *
151: * @return String
152: */
153: public String toString() {
154: return "<lookup object instance at " + Py.id(this ) + ">";
155: }
156:
157: // __class__ boilerplate -- see PyObject for details
158:
159: /**
160: * Field __class__
161: */
162: public static PyClass __class__;
163:
164: /**
165: * Method getPyClass
166: *
167: * @return PyClass
168: */
169: protected PyClass getPyClass() {
170: return __class__;
171: }
172: }
|