001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: Utility.java 8049 2006-02-23 15:50:17Z ehardesty $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.jdbc;
025:
026: import java.lang.reflect.Method;
027: import java.io.ByteArrayInputStream;
028: import java.util.Enumeration;
029: import java.util.Iterator;
030: import java.util.Properties;
031: import java.util.Set;
032: import java.util.Vector;
033:
034: import javax.resource.ResourceException;
035: import javax.resource.spi.ConnectionRequestInfo;
036: import javax.resource.spi.ManagedConnectionFactory;
037: import javax.resource.spi.SecurityException;
038: import javax.resource.spi.security.PasswordCredential;
039: import javax.security.auth.Subject;
040:
041: import org.objectweb.util.monolog.api.BasicLevel;
042: import org.objectweb.util.monolog.api.Logger;
043:
044: /**
045: * <p>This class contains the support methods for the Resource Adapter.
046: * @author Eric Hardesty
047: */
048: public class Utility {
049:
050: static synchronized Object getDataSource(
051: ManagedConnectionFactoryImpl mcf, PasswordCredential pc,
052: Logger trace) throws ResourceException {
053:
054: MCFData prop = mcf.mcfData;
055:
056: if (prop.getMCFData(MCFData.DSCLASS) == null) {
057: ResourceException re = new ResourceException(
058: "A DataSource (dsClass) value must be specified");
059: trace.log(BasicLevel.INFO, re.getMessage());
060: }
061: String clsName = prop.getMCFData(MCFData.DSCLASS);
062: Class dsClass = null;
063: Object dsObj = null;
064: try {
065: dsClass = Class.forName(clsName, true, Thread
066: .currentThread().getContextClassLoader());
067: dsObj = dsClass.newInstance();
068: if (trace.isLoggable(BasicLevel.DEBUG)) {
069: trace.log(BasicLevel.DEBUG, "dsClass(" + clsName
070: + ") is " + dsObj);
071: }
072: } catch (ClassNotFoundException cnfe) {
073: throw new ResourceException("Class Name not found:"
074: + clsName);
075: } catch (Exception ex) {
076: throw new ResourceException("Error in class: " + clsName
077: + " " + ex.getMessage());
078: }
079:
080: Object[] param = new Object[1];
081: String methodName = null;
082: String paramVal = null;
083: Method meth = null;
084: for (Enumeration e = prop.getProperties(); e.hasMoreElements();) {
085: int offset = Integer.parseInt((String) e.nextElement());
086: methodName = MCFData.dsMethodNames[offset];
087: if (!(methodName.equals("setDSClass")
088: || methodName.equals("setDbSpecificMethods") || offset > MCFData.JONASOFFSET)) {
089: try {
090: /* Determine if a String method exist */
091: paramVal = prop.getProperty("" + offset);
092: if (trace.isLoggable(BasicLevel.DEBUG)) {
093: trace.log(BasicLevel.DEBUG, "calling method "
094: + methodName + " with String "
095: + paramVal);
096: }
097: meth = dsClass.getMethod(methodName,
098: new Class[] { String.class });
099: param[0] = paramVal;
100: meth.invoke(dsObj, param);
101: } catch (NoSuchMethodException ns) {
102: try {
103: /* Valid case, determine if an Integer method exist */
104: if (trace.isLoggable(BasicLevel.DEBUG)) {
105: trace.log(BasicLevel.DEBUG,
106: "calling method " + methodName
107: + " with int " + paramVal);
108: }
109: meth = dsClass.getMethod(methodName,
110: new Class[] { int.class });
111: param[0] = new Integer(paramVal);
112: meth.invoke(dsObj, param);
113: } catch (NoSuchMethodException nsme) {
114: // Valid case no String or Integer method continue thru
115: // remainder of properties
116: ;
117: } catch (NumberFormatException nfm) {
118: // Valid case cannot convert to an Integer
119: ;
120: } catch (Exception ex0) {
121: ex0.printStackTrace();
122: throw new ResourceException("Error on method: "
123: + methodName + " " + ex0.getMessage());
124: }
125: } catch (IllegalArgumentException iae) {
126: ;
127: } catch (Exception ex) {
128: ex.printStackTrace();
129: throw new ResourceException("Error on method: "
130: + methodName + " " + ex.getMessage());
131: }
132: }
133: if (methodName.equals("setDbSpecificMethods")) {
134: Vector meths = new Vector();
135: Vector methParams = new Vector();
136: Vector methTypes = new Vector();
137: try {
138: Utility.parseValues(prop.getProperty("" + offset),
139: meths, methParams, methTypes, trace);
140: } catch (Exception ex1) {
141: throw new ResourceException(
142: "Error parsing dbSpecificMethods: "
143: + ex1.getMessage());
144: }
145: if (meths != null && meths.size() > 0) {
146: for (int i = 0; i < meths.size(); i++) {
147: try {
148: /* Determine if a String method exist */
149: methodName = (String) meths.elementAt(i);
150: Class toPass = null;
151: String curMethType = (String) methTypes
152: .elementAt(i);
153: if (curMethType.equalsIgnoreCase("String")) {
154: toPass = String.class;
155: param[0] = (String) methParams
156: .elementAt(i);
157: } else if (curMethType
158: .equalsIgnoreCase("Integer")) {
159: toPass = Integer.class;
160: param[0] = Integer
161: .valueOf((String) methParams
162: .elementAt(i));
163: } else if (curMethType
164: .equalsIgnoreCase("int")) {
165: toPass = int.class;
166: param[0] = Integer
167: .valueOf((String) methParams
168: .elementAt(i));
169: } else if (curMethType.equals("Float")) {
170: toPass = Float.class;
171: param[0] = Float
172: .valueOf((String) methParams
173: .elementAt(i));
174: } else if (curMethType.equals("float")) {
175: toPass = float.class;
176: param[0] = Float
177: .valueOf((String) methParams
178: .elementAt(i));
179: } else if (curMethType.equals("Boolean")) {
180: toPass = Boolean.class;
181: param[0] = Boolean
182: .valueOf((String) methParams
183: .elementAt(i));
184: } else if (curMethType.equals("boolean")) {
185: toPass = boolean.class;
186: param[0] = Boolean
187: .valueOf((String) methParams
188: .elementAt(i));
189: } else if (curMethType
190: .equalsIgnoreCase("Character")) {
191: toPass = Character.class;
192: param[0] = new Character(
193: ((String) methParams
194: .elementAt(i))
195: .charAt(0));
196: } else if (curMethType
197: .equalsIgnoreCase("char")) {
198: toPass = char.class;
199: param[0] = new Character(
200: ((String) methParams
201: .elementAt(i))
202: .charAt(0));
203: } else if (curMethType.equals("Double")) {
204: toPass = Double.class;
205: param[0] = Double
206: .valueOf((String) methParams
207: .elementAt(i));
208: } else if (curMethType.equals("double")) {
209: toPass = double.class;
210: param[0] = Double
211: .valueOf((String) methParams
212: .elementAt(i));
213: } else if (curMethType.equals("Byte")) {
214: toPass = Byte.class;
215: param[0] = Byte
216: .valueOf((String) methParams
217: .elementAt(i));
218: } else if (curMethType.equals("byte")) {
219: toPass = byte.class;
220: param[0] = Byte
221: .valueOf((String) methParams
222: .elementAt(i));
223: } else if (curMethType.equals("Short")) {
224: toPass = Short.class;
225: param[0] = Short
226: .valueOf((String) methParams
227: .elementAt(i));
228: } else if (curMethType.equals("short")) {
229: toPass = short.class;
230: param[0] = Short
231: .valueOf((String) methParams
232: .elementAt(i));
233: } else if (curMethType.equals("Long")) {
234: toPass = Long.class;
235: param[0] = Long
236: .valueOf((String) methParams
237: .elementAt(i));
238: } else if (curMethType.equals("long")) {
239: toPass = long.class;
240: param[0] = Long
241: .valueOf((String) methParams
242: .elementAt(i));
243: } else if (curMethType.equals("Properties")
244: || curMethType
245: .equals("java.lang.Properties")) {
246: toPass = Properties.class;
247: param[0] = Utility.buildProperties(
248: (String) methParams
249: .elementAt(i), trace);
250: }
251: if (trace.isLoggable(BasicLevel.DEBUG)) {
252: trace.log(BasicLevel.DEBUG,
253: "calling method " + methodName
254: + " with " + param[0]);
255: }
256: meth = dsClass.getMethod(methodName,
257: new Class[] { toPass });
258: meth.invoke(dsObj, param);
259: } catch (NoSuchMethodException ns) {
260: throw new ResourceException(
261: "No such method: " + methodName
262: + " " + ns.getMessage());
263: } catch (Exception ex) {
264: ex.printStackTrace();
265: throw new ResourceException(
266: "Error on method: " + methodName
267: + " " + ex.getMessage());
268: }
269: }
270: }
271: }
272: }
273: if (pc != null) {
274: try {
275: param[0] = pc.getUserName();
276: meth = dsClass.getMethod("setUserName",
277: new Class[] { Class.forName("String") });
278: meth.invoke(dsObj, param);
279:
280: param[0] = new String(pc.getPassword());
281: meth = dsClass.getMethod("setPassword",
282: new Class[] { Class.forName("String") });
283: meth.invoke(dsObj, param);
284: } catch (Exception ex) {
285: throw new ResourceException("Error on method: "
286: + methodName + " " + ex.getMessage());
287: }
288: }
289:
290: if (trace.isLoggable(BasicLevel.DEBUG)) {
291: try {
292: meth = dsClass.getMethod("getURL", (Class[]) null);
293: trace.log(BasicLevel.DEBUG, "URL is "
294: + meth.invoke(dsObj, (Object[]) null));
295: } catch (Exception e) {
296: }
297: }
298: return dsObj;
299:
300: }
301:
302: private static Properties buildProperties(String val, Logger trace)
303: throws Exception {
304: if (trace.isLoggable(BasicLevel.DEBUG)) {
305: trace.log(BasicLevel.DEBUG, "" + val);
306: }
307: Properties ret = new Properties();
308:
309: if (val.length() == 0) {
310: return ret;
311: }
312: String pairs = val.substring(1, val.length() - 1);
313: String parseVal = pairs.replace(',', '\n');
314: try {
315: ByteArrayInputStream valStream = new ByteArrayInputStream(
316: parseVal.getBytes());
317: ret.load(valStream);
318: } catch (Exception ex) {
319: throw new Exception(
320: "Invalid value specified for Properties parameter in dbSpecificMethods");
321: }
322:
323: return ret;
324: }
325:
326: private static void parseValues(String val, Vector vMeth,
327: Vector vValues, Vector vTypes, Logger trace)
328: throws Exception {
329: if (trace.isLoggable(BasicLevel.DEBUG)) {
330: trace.log(BasicLevel.DEBUG, "");
331: }
332: char delim = ':';
333: boolean done = false;
334: String methName = null;
335: int offset = 0;
336: boolean parsed = false;
337: String parseVal = val.trim();
338: String typeVal = "";
339: String valVal = "";
340:
341: if (parseVal.length() == 0) {
342: return;
343: }
344: if (parseVal.startsWith(":")) {
345: delim = parseVal.charAt(1);
346: parseVal = parseVal.substring(2);
347: }
348: while (!parsed) {
349: offset = parseVal.indexOf('=');
350: if (offset < 0) {
351: throw new Exception(
352: "Invalid value specified for dbSpecificMethods");
353: }
354: methName = parseVal.substring(0, offset);
355: vMeth.add(methName);
356: parseVal = parseVal.substring(offset + 1);
357: if (parseVal.charAt(0) == delim) {
358: valVal = "";
359: } else {
360: offset = parseVal.indexOf(delim);
361: if (offset < 0) {
362: valVal = parseVal;
363: offset = valVal.length() - 1;
364: } else {
365: valVal = parseVal.substring(0, offset);
366: }
367: }
368: vValues.add(valVal);
369: if (offset < 0) {
370: parsed = true;
371: } else {
372: parseVal = parseVal.substring(offset + 1);
373: if (parseVal.length() == 0) {
374: parsed = true;
375: }
376: }
377: if (parseVal.startsWith("" + delim)) {
378: parseVal = parseVal.substring(1);
379: offset = parseVal.indexOf(delim);
380: if (offset < 0) {
381: typeVal = parseVal;
382: } else {
383: typeVal = parseVal.substring(0, offset);
384: }
385: vTypes.add(typeVal);
386: if (offset < 0) {
387: parsed = true;
388: } else {
389: parseVal = parseVal.substring(offset + 1);
390: if (parseVal.length() == 0) {
391: parsed = true;
392: }
393: }
394: } else {
395: vTypes.add("String");
396: }
397: if (trace.isLoggable(BasicLevel.DEBUG)) {
398: trace.log(BasicLevel.DEBUG, "Parsed: method("
399: + methName + ") value(" + valVal + ") type("
400: + typeVal + ")");
401: }
402: }
403: }
404:
405: /**
406: * Returns the Password credential
407: * @param mcf ManagedConnectionFactory currently being used
408: * @param subject Subject associated with this call
409: * @param info ConnectionRequestInfo
410: * @return PasswordCredential for this user
411: */
412: static synchronized PasswordCredential getPasswordCredential(
413: ManagedConnectionFactory mcf, Subject subject,
414: ConnectionRequestInfo info, java.io.PrintWriter out)
415: throws ResourceException {
416:
417: if (subject == null) {
418: if (info == null) {
419: return null;
420: }
421: ConnectionRequestInfoImpl crii = (ConnectionRequestInfoImpl) info;
422: PasswordCredential pc = new PasswordCredential(crii.user,
423: crii.password.toCharArray());
424: pc.setManagedConnectionFactory(mcf);
425: return pc;
426: }
427: Set cred = subject
428: .getPrivateCredentials(PasswordCredential.class);
429: PasswordCredential pc = null;
430: for (Iterator iter = cred.iterator(); iter.hasNext();) {
431: PasswordCredential tmpPc = (PasswordCredential) iter.next();
432: if (tmpPc.getManagedConnectionFactory().equals(mcf)) {
433: pc = tmpPc;
434: break;
435: }
436: }
437: if (pc == null) {
438: SecurityException se = new SecurityException(
439: "No PasswordCredential found");
440: out.println("" + se);
441: throw se;
442: }
443: return pc;
444: }
445:
446: }
|