001: /*
002:
003: Derby - Class org.apache.derby.jdbc.ReferenceableDataSource
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021: package org.apache.derby.jdbc;
022:
023: import java.sql.SQLException;
024: import java.lang.reflect.*;
025:
026: import java.io.Serializable;
027: import java.io.PrintWriter;
028: import java.util.Properties;
029:
030: /* -- JNDI -- */
031: import javax.naming.NamingException;
032: import javax.naming.Referenceable;
033: import javax.naming.Reference;
034: import javax.naming.StringRefAddr;
035: import javax.naming.spi.ObjectFactory;
036: import javax.naming.Context;
037: import javax.naming.Name;
038: import javax.naming.Reference;
039: import javax.naming.RefAddr;
040: import java.util.Hashtable;
041: import java.util.Enumeration;
042:
043: /**
044:
045: Cloudscape DataSource implementation base class.
046: ReferenceableDataSource provides support for JDBC standard DataSource attributes and acts
047: as the ObjectFactory to generate Cloudscape DataSource implementations.
048: <P>
049: The standard attributes provided by this class are:
050: <UL>
051: <LI>databaseName
052: <LI>dataSourceName
053: <LI>description
054: <LI>password
055: <LI>user
056: </UL>
057: <BR>
058: See the specific Cloudscape DataSource implementation for details on their meaning.
059: <BR>
060: See the JDBC 3.0 specification for more details.
061:
062:
063: */
064: public class ReferenceableDataSource implements
065: javax.naming.Referenceable, java.io.Serializable, ObjectFactory {
066:
067: private static final long serialVersionUID = 1872877359127597176L;
068:
069: private static final Class[] STRING_ARG = { "".getClass() };
070: private static final Class[] INT_ARG = { Integer.TYPE };
071: private static final Class[] BOOLEAN_ARG = { Boolean.TYPE };
072:
073: private String description;
074: private String dataSourceName;
075: private String databaseName;
076: private String password;
077: private String user;
078: private int loginTimeout;
079:
080: /** instance variables that will not be serialized */
081: transient private PrintWriter printer;
082:
083: /**
084: No-arg constructor.
085: */
086: public ReferenceableDataSource() {
087: update();
088: }
089:
090: /*
091: * Properties to be seen by Bean - access thru reflection.
092: */
093:
094: /**
095: Set the database name. Setting this property is mandatory. If a
096: database named wombat at g:/db needs to be accessed, database name
097: should be set to "g:/db/wombat". The database will be booted if it
098: is not already running in the system.
099:
100: @param databaseName the name of the database
101: */
102: public final synchronized void setDatabaseName(String databaseName) {
103: this .databaseName = databaseName;
104: update();
105: }
106:
107: public String getDatabaseName() {
108: return databaseName;
109: }
110:
111: /**
112: Set the data source name. The property is not mandatory. It is used
113: for informational purposes only.
114:
115: @param dsn the name of the data source
116: */
117: public final void setDataSourceName(String dsn) {
118: dataSourceName = dsn;
119: }
120:
121: /** @return data source name */
122: public final String getDataSourceName() {
123: return dataSourceName;
124: }
125:
126: /**
127: Set the data source descripton. This property is not mandatory.
128: It is used for informational purposes only.
129:
130: @param desc the description of the data source
131: */
132: public final void setDescription(String desc) {
133: description = desc;
134: }
135:
136: /** @return description */
137: public final String getDescription() {
138: return description;
139: }
140:
141: /**
142: Set the <code>user</code> property for the data source.
143: This is user name for any data source getConnection() call
144: that takes no arguments.
145: */
146: public final void setUser(String user) {
147: this .user = user;
148: }
149:
150: /** @return user */
151: public final String getUser() {
152: return user;
153: }
154:
155: /**
156: Set the <code>password</code> property for the data source.
157: This is user's password for any data source getConnection() call
158: that takes no arguments.
159: */
160: public final void setPassword(String password) {
161: this .password = password;
162: }
163:
164: /** @return password */
165: public final String getPassword() {
166: return password;
167: }
168:
169: /*
170: * DataSource methods
171: */
172:
173: /**
174: * Gets the maximum time in seconds that this data source can wait
175: * while attempting to connect to a database. A value of zero
176: * means that the timeout is the default system timeout
177: * if there is one; otherwise it means that there is no timeout.
178: * When a data source object is created, the login timeout is
179: * initially zero.
180: *
181: * @return the data source login time limit
182: * @exception SQLException if a database access error occurs.
183: */
184: public int getLoginTimeout() throws SQLException {
185: return loginTimeout;
186: }
187:
188: /**
189: * Sets the maximum time in seconds that this data source will wait
190: * while attempting to connect to a database. A value of zero
191: * specifies that the timeout is the default system timeout
192: * if there is one; otherwise it specifies that there is no timeout.
193: * When a data source object is created, the login timeout is
194: * initially zero.
195: <P>
196: Cloudscape ignores this property.
197: * @param seconds the data source login time limit
198: * @exception SQLException if a database access error occurs.
199: */
200: public void setLoginTimeout(int seconds) throws SQLException {
201: loginTimeout = seconds;
202: }
203:
204: /**
205: * Get the log writer for this data source.
206: *
207: * <p>The log writer is a character output stream to which all logging
208: * and tracing messages for this data source object instance will be
209: * printed. This includes messages printed by the methods of this
210: * object, messages printed by methods of other objects manufactured
211: * by this object, and so on. Messages printed to a data source
212: * specific log writer are not printed to the log writer associated
213: * with the java.sql.Drivermanager class. When a data source object is
214: * created the log writer is initially null, in other words, logging
215: * is disabled.
216: *
217: * @return the log writer for this data source, null if disabled
218: * @exception SQLException if a database-access error occurs.
219: */
220: public PrintWriter getLogWriter() throws SQLException {
221: return printer;
222: }
223:
224: /**
225: * Set the log writer for this data source.
226: *
227: * <p>The log writer is a character output stream to which all logging
228: * and tracing messages for this data source object instance will be
229: * printed. This includes messages printed by the methods of this
230: * object, messages printed by methods of other objects manufactured
231: * by this object, and so on. Messages printed to a data source
232: * specific log writer are not printed to the log writer associated
233: * with the java.sql.Drivermanager class. When a data source object is
234: * created the log writer is initially null, in other words, logging
235: * is disabled.
236: *
237: * @param out the new log writer; to disable, set to null
238: * @exception SQLException if a database-access error occurs.
239: */
240: public void setLogWriter(PrintWriter out) throws SQLException {
241: printer = out;
242: }
243:
244: /*
245: ** Reference methods etc.
246: */
247:
248: /*
249: * Object Factory method
250: */
251:
252: /**
253: Re-Create Cloudscape datasource given a reference.
254:
255: @param obj The possibly null object containing location or reference
256: information that can be used in creating an object.
257: @param name The name of this object relative to nameCtx, or null if no
258: name is specified.
259: @param nameCtx The context relative to which the name parameter is
260: specified, or null if name is relative to the default initial context.
261: @param environment The possibly null environment that is used in
262: creating the object.
263:
264: @return One of the Cloudscape datasource object created; null if an
265: object cannot be created.
266:
267: @exception Exception if this object factory encountered an exception
268: while attempting to create an object, and no other object factories are
269: to be tried.
270: */
271: public Object getObjectInstance(Object obj, Name name,
272: Context nameCtx, Hashtable environment) throws Exception {
273: Reference ref = (Reference) obj;
274: String classname = ref.getClassName();
275:
276: Object ds = Class.forName(classname).newInstance();
277:
278: for (Enumeration e = ref.getAll(); e.hasMoreElements();) {
279:
280: RefAddr attribute = (RefAddr) e.nextElement();
281:
282: String propertyName = attribute.getType();
283:
284: String value = (String) attribute.getContent();
285:
286: String methodName = "set"
287: + propertyName.substring(0, 1).toUpperCase(
288: java.util.Locale.ENGLISH)
289: + propertyName.substring(1);
290:
291: Method m;
292:
293: Object argValue;
294: try {
295: m = ds.getClass().getMethod(methodName, STRING_ARG);
296: argValue = value;
297: } catch (NoSuchMethodException nsme) {
298: try {
299: m = ds.getClass().getMethod(methodName, INT_ARG);
300: argValue = Integer.valueOf(value);
301: } catch (NoSuchMethodException nsme2) {
302: m = ds.getClass()
303: .getMethod(methodName, BOOLEAN_ARG);
304: argValue = Boolean.valueOf(value);
305: }
306: }
307: m.invoke(ds, new Object[] { argValue });
308: }
309:
310: return ds;
311: }
312:
313: /**
314: Referenceable method.
315:
316: @exception NamingException cannot find named object
317: */
318: public final Reference getReference() throws NamingException {
319: // These fields will be set by the JNDI server when it decides to
320: // materialize a data source.
321: Reference ref = new Reference(this .getClass().getName(),
322: "org.apache.derby.jdbc.ReferenceableDataSource", null);
323:
324: // Look for all the getXXX methods in the class that take no arguments.
325: Method[] methods = this .getClass().getMethods();
326:
327: for (int i = 0; i < methods.length; i++) {
328:
329: Method m = methods[i];
330:
331: // only look for simple getter methods.
332: if (m.getParameterTypes().length != 0)
333: continue;
334:
335: // only non-static methods
336: if (Modifier.isStatic(m.getModifiers()))
337: continue;
338:
339: // Only getXXX methods
340: String methodName = m.getName();
341: if ((methodName.length() < 5)
342: || !methodName.startsWith("get"))
343: continue;
344:
345: Class returnType = m.getReturnType();
346:
347: if (Integer.TYPE.equals(returnType)
348: || STRING_ARG[0].equals(returnType)
349: || Boolean.TYPE.equals(returnType)) {
350:
351: // setSomeProperty
352: // 01234
353:
354: String propertyName = methodName.substring(3, 4)
355: .toLowerCase(java.util.Locale.ENGLISH).concat(
356: methodName.substring(4));
357:
358: try {
359: Object ov = m.invoke(this , null);
360:
361: //Need to check for nullability for all the properties, otherwise
362: //rather than null, "null" string gets stored in jndi.
363: if (ov != null) {
364: ref.add(new StringRefAddr(propertyName, ov
365: .toString()));
366: }
367: } catch (IllegalAccessException iae) {
368: } catch (InvocationTargetException ite) {
369: }
370:
371: }
372: }
373:
374: return ref;
375: }
376:
377: void update() {
378: }
379:
380: /**
381: Return a connection for the Cloudscape family of data source implementations.
382: */
383: java.sql.Connection getConnection(String username, String password,
384: boolean requestPassword) throws SQLException {
385: return null;
386: }
387:
388: }
|