001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins;
023:
024: import java.io.InputStream;
025: import java.io.ObjectInputStream;
026: import java.io.ObjectStreamClass;
027: import java.io.IOException;
028: import java.lang.reflect.Proxy;
029: import java.security.PrivilegedAction;
030: import java.security.AccessController;
031:
032: import javax.ejb.Handle;
033: import javax.ejb.HomeHandle;
034:
035: import org.jboss.ejb.StatefulSessionEnterpriseContext;
036:
037: /**
038: * The SessionObjectInputStream is used to deserialize stateful session beans when they are activated
039: *
040: * @see org.jboss.ejb.plugins.SessionObjectOutputStream
041: * @author <a href="mailto:rickard.oberg@telkel.com">Rickard berg</a>
042: * @author <a href="mailto:sebastien.alborini@m4x.org">Sebastien Alborini</a>
043: * @author <a href="mailto:scott.stark@jboss.org">Scott Stark</a>
044: * @version $Revision: 57209 $
045: */
046: public class SessionObjectInputStream extends ObjectInputStream {
047: private StatefulSessionEnterpriseContext ctx;
048: private ClassLoader appCl;
049:
050: // Constructors -------------------------------------------------
051: public SessionObjectInputStream(
052: StatefulSessionEnterpriseContext ctx, InputStream in)
053: throws IOException {
054: super (in);
055: EnableResolveObjectAction.enableResolveObject(this );
056:
057: this .ctx = ctx;
058:
059: // cache the application classloader
060: appCl = SecurityActions.getContextClassLoader();
061: }
062:
063: // ObjectInputStream overrides -----------------------------------
064: protected Object resolveObject(Object obj) throws IOException {
065: Object resolved = obj;
066:
067: // section 6.4.1 of the ejb1.1 specification states what must be taken care of
068:
069: // ejb reference (remote interface) : resolve handle to EJB
070: if (obj instanceof Handle)
071: resolved = ((Handle) obj).getEJBObject();
072:
073: // ejb reference (home interface) : resolve handle to EJB Home
074: else if (obj instanceof HomeHandle)
075: resolved = ((HomeHandle) obj).getEJBHome();
076:
077: // naming context: the jnp implementation of contexts is serializable, do nothing
078:
079: else if (obj instanceof HandleWrapper) {
080: HandleWrapper wrapper = (HandleWrapper) obj;
081: try {
082: resolved = wrapper.get();
083: } catch (ClassNotFoundException e) {
084: throw new IOException("Failed to find class: "
085: + e.getMessage());
086: }
087: }
088:
089: else if (obj instanceof StatefulSessionBeanField) {
090: byte type = ((StatefulSessionBeanField) obj).type;
091:
092: // session context: recreate it
093: if (type == StatefulSessionBeanField.SESSION_CONTEXT)
094: resolved = ctx.getSessionContext();
095:
096: // user transaction: restore it
097: else if (type == StatefulSessionBeanField.USER_TRANSACTION)
098: resolved = ctx.getSessionContext().getUserTransaction();
099: }
100: return resolved;
101: }
102:
103: /** Override the ObjectInputStream implementation to use the application class loader
104: */
105: protected Class resolveClass(ObjectStreamClass v)
106: throws IOException, ClassNotFoundException {
107: try {
108: // use the application classloader to resolve the class
109: return appCl.loadClass(v.getName());
110:
111: } catch (ClassNotFoundException e) {
112: // we should probably never get here
113: return super .resolveClass(v);
114: }
115: }
116:
117: /** Override the ObjectInputStream implementation to use the application class loader
118: */
119: protected Class resolveProxyClass(String[] interfaces)
120: throws IOException, ClassNotFoundException {
121: Class clazz = null;
122: Class[] ifaceClasses = new Class[interfaces.length];
123: for (int i = 0; i < interfaces.length; i++)
124: ifaceClasses[i] = Class
125: .forName(interfaces[i], false, appCl);
126: try {
127: clazz = Proxy.getProxyClass(appCl, ifaceClasses);
128: } catch (IllegalArgumentException e) {
129: throw new ClassNotFoundException(
130: "Failed to resolve proxy class", e);
131: }
132: return clazz;
133: }
134:
135: private static class EnableResolveObjectAction implements
136: PrivilegedAction {
137: SessionObjectInputStream is;
138:
139: EnableResolveObjectAction(SessionObjectInputStream is) {
140: this .is = is;
141: }
142:
143: public Object run() {
144: is.enableResolveObject(true);
145: return null;
146: }
147:
148: static void enableResolveObject(SessionObjectInputStream is) {
149: EnableResolveObjectAction action = new EnableResolveObjectAction(
150: is);
151: AccessController.doPrivileged(action);
152: }
153: }
154: }
|