001: /*
002: * CoadunationUtil: The coadunation util library.
003: * Copyright (C) 2007 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * RMIConnection.java
020: */
021:
022: // package path
023: package com.rift.coad.util.connection;
024:
025: // java imports
026: import java.lang.reflect.Proxy;
027: import java.util.Map;
028: import java.util.concurrent.ConcurrentHashMap;
029: import javax.naming.Context;
030: import javax.rmi.PortableRemoteObject;
031:
032: // logging import
033: import org.apache.log4j.Logger;
034:
035: /**
036: * This object controls the RMI based connection.
037: *
038: * @author Brett Chaldecott
039: */
040: public class RMIConnection implements Connection {
041:
042: // the logger reference
043: protected static Logger log = Logger.getLogger(RMIConnection.class
044: .getName());
045:
046: // the private member variables
047: private Context context = null;
048: private String jndiURL = null;
049: private Object ref = null;
050: private Map connectionMap = new ConcurrentHashMap();
051:
052: /**
053: * Creates a new instance of RMIConnection
054: *
055: * @param context The context object responsible for returning information.
056: * @param jndiURL The url identifying the object.
057: */
058: public RMIConnection(Context context, String jndiURL) {
059: this .context = context;
060: this .jndiURL = jndiURL;
061: }
062:
063: /**
064: * This object returns the connection to the object.
065: *
066: * @return The retrieve connection to the object.
067: * @param type The type of object to narrow.
068: * @exception ConnectionException
069: */
070: public Object getConnection(Class type) throws ConnectionException,
071: java.lang.ClassCastException {
072: try {
073: synchronized (type) {
074: Object proxy = connectionMap.get(type);
075: if (proxy != null) {
076: return proxy;
077: }
078:
079: // check the reference
080: Object ref = null;
081: synchronized (this ) {
082: if (this .ref == null) {
083: this .ref = context.lookup(jndiURL);
084: }
085: ref = this .ref;
086: }
087: Object reference = PortableRemoteObject.narrow(ref,
088: type);
089: proxy = createProxy(type, reference);
090: connectionMap.put(type, proxy);
091: return proxy;
092: }
093: } catch (javax.naming.NameNotFoundException ex) {
094: log.error("The name [" + jndiURL + "] is not found : "
095: + ex.getMessage(), ex);
096: throw new com.rift.coad.util.connection.NameNotFound(
097: "The name [" + jndiURL + "] is not found : "
098: + ex.getMessage(), ex);
099: } catch (java.lang.ClassCastException ex) {
100: log.error("Failed to cast object refered to by [" + jndiURL
101: + "] to a [" + type.getName() + "] because : "
102: + ex.getMessage(), ex);
103: throw ex;
104: } catch (Exception ex) {
105: log.error("Failed to make the connection : "
106: + ex.getMessage(), ex);
107: throw new ConnectionException(
108: "Failed to make the connection : "
109: + ex.getMessage(), ex);
110: }
111: }
112:
113: /**
114: * This method returns true if the object being passed contains a local
115: * url.
116: *
117: * @return TRUE if a local URL, FALSE if not.
118: * @param jndiURL The string url to perform the check on.
119: */
120: public static boolean isRMIConnection(String jndiURL) {
121: if (jndiURL.trim().indexOf("java:comp") == -1) {
122: return true;
123: }
124: return false;
125: }
126:
127: /**
128: * This method is called to invalidate a connection object.
129: */
130: public synchronized void invalidateConnection() {
131: log.debug("Calling clear");
132: ref = null;
133: connectionMap.clear();
134: }
135:
136: /**
137: * This method creates the new proxy.
138: *
139: * @return The reference to the newly create proxy.
140: * @param type The type to create the proxy for.
141: * @param rmiRef The reference to object to make the call on.
142: */
143: private Object createProxy(Class type, Object rmiRef) {
144: ConnectionHandler handler = new ConnectionHandler(this , rmiRef);
145: return (Object) Proxy.newProxyInstance(type.getClassLoader(),
146: new Class[] { type }, handler);
147: }
148: }
|