maguro      2004/07/30 10:33:44

  Modified:    modules/core/src/java/org/openejb/server/ejbd
                        EjbRequestHandler.java
  Log:

  The double spaces were too much to bear.
  
  Revision  Changes    Path
  1.8       +530 -474  
openejb/modules/core/src/java/org/openejb/server/ejbd/EjbRequestHandler.java
  
  Index: EjbRequestHandler.java
  ===================================================================
  RCS file: 
/home/projects/openejb/scm/openejb/modules/core/src/java/org/openejb/server/ejbd/EjbRequestHandler.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- EjbRequestHandler.java    27 Apr 2004 00:39:55 -0000      1.7
  +++ EjbRequestHandler.java    30 Jul 2004 14:33:44 -0000      1.8
  @@ -1,474 +1,530 @@
  -/**

  - * Redistribution and use of this software and associated documentation

  - * ("Software"), with or without modification, are permitted provided

  - * that the following conditions are met:

  - *

  - * 1. Redistributions of source code must retain copyright

  - *    statements and notices.  Redistributions must also contain a

  - *    copy of this document.

  - *

  - * 2. Redistributions in binary form must reproduce the

  - *    above copyright notice, this list of conditions and the

  - *    following disclaimer in the documentation and/or other

  - *    materials provided with the distribution.

  - *

  - * 3. The name "OpenEJB" must not be used to endorse or promote

  - *    products derived from this Software without prior written

  - *    permission of The OpenEJB Group.  For written permission,

  - *    please contact [EMAIL PROTECTED]

  - *

  - * 4. Products derived from this Software may not be called "OpenEJB"

  - *    nor may "OpenEJB" appear in their names without prior written

  - *    permission of The OpenEJB Group. OpenEJB is a registered

  - *    trademark of The OpenEJB Group.

  - *

  - * 5. Due credit should be given to the OpenEJB Project

  - *    (http://openejb.sf.net/).

  - *

  - * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS

  - * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT

  - * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND

  - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL

  - * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,

  - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES

  - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR

  - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)

  - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,

  - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

  - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED

  - * OF THE POSSIBILITY OF SUCH DAMAGE.

  - *

  - * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.

  - *

  - * $Id$

  - */

  -package org.openejb.server.ejbd;

  -

  -import java.io.ObjectInputStream;

  -import java.io.ObjectOutputStream;

  -import java.rmi.RemoteException;

  -import java.util.Collection;

  -

  -import org.apache.commons.logging.Log;

  -import org.apache.commons.logging.LogFactory;

  -import org.apache.geronimo.core.service.InvocationResult;

  -

  -import org.openejb.ContainerIndex;

  -import org.openejb.EJBContainer;

  -import org.openejb.InvalidateReferenceException;

  -import org.openejb.client.EJBRequest;

  -import org.openejb.client.EJBResponse;

  -import org.openejb.client.RequestMethods;

  -import org.openejb.client.ResponseCodes;

  -import org.openejb.proxy.BaseEJB;

  -import org.openejb.proxy.ProxyInfo;

  -

  -class EjbRequestHandler implements ResponseCodes, RequestMethods {

  -    private static final Log log = LogFactory.getLog(EjbRequestHandler.class);

  -    private final ContainerIndex containerIndex;

  -

  -    EjbRequestHandler(ContainerIndex containerIndex) {

  -        if (containerIndex == null){

  -            containerIndex = ContainerIndex.getInstance();

  -        }

  -        this.containerIndex = containerIndex;

  -    }

  -

  -    public void processRequest(ObjectInputStream input, ObjectOutputStream out) {

  -

  -        EJBObjectInputStream in = (EJBObjectInputStream)input;

  -

  -        //        EJBRequest req = new EJBRequest();

  -        EJBInvocationStream req = new EJBInvocationStream();

  -        EJBResponse res = new EJBResponse();

  -

  -        // TODO:2: This method can throw a large number of exceptions, we should

  -        // be prepared to handle them all.  Look in the ObejctOutputStream code

  -        // for a full list of the exceptions thrown.

  -        // java.io.WriteAbortedException  can be thrown containing a

  -        //

  -        try {

  -            req.readExternal(in);

  -

  -            /*

  -                } catch (java.io.WriteAbortedException e){

  -                    if ( e.detail instanceof java.io.NotSerializableException){

  -                        //TODO:1: Log this warning better. Include information on 
what bean is to blame

  -                        throw new Exception("Client attempting to serialize 
unserializable object: "+ e.detail.getMessage());

  -                    } else {

  -                        throw e.detail;

  -                    }

  -                } catch (java.io.EOFException e) {

  -                    throw new Exception("Reached the end of the stream before the 
full request could be read");

  -                } catch (Throwable t){

  -                    throw new Exception("Cannot read client request: "+ 
t.getClass().getName()+" "+ t.getMessage());

  -                }

  -            */

  -

  -        } catch (Throwable t) {

  -            replyWithFatalError(out, t, "Error caught during request processing");

  -            return;

  -        }

  -

  -        CallContext call = null;

  -        EJBContainer container = null;

  -

  -        try {

  -            container = getContainer(req);

  -            req.setProxyFactory(container.getProxyFactory());

  -            ClassLoader cl = container.getClassLoader();

  -            Thread.currentThread().setContextClassLoader(cl);

  -            in.setClassLoader(cl);

  -            log.warn("setting cl="+cl+" for "+container.getContainerID());

  -        } catch (RemoteException e) {

  -            replyWithFatalError

  -                    (out, e, "No such deployment");

  -            return;

  -            /*

  -                logger.warn( req + "No such deployment: "+e.getMessage());

  -                res.setResponse( EJB_SYS_EXCEPTION, e);

  -                res.writeExternal( out );

  -                return;

  -            */

  -        } catch (Throwable t) {

  -            replyWithFatalError(out, t, "Unkown error occured while retrieving 
deployment");

  -            return;

  -        }

  -

  -        try {

  -            call = CallContext.getCallContext();

  -            call.setEJBRequest(req);

  -            call.setContainer(container);

  -        } catch (Throwable t) {

  -            replyWithFatalError(out, t, "Unable to set the thread context for this 
request");

  -            return;

  -        }

  -

  -        //logger.info( "EJB REQUEST : "+req );

  -

  -        try {

  -            switch (req.getRequestMethod()) {

  -            // Remote interface methods

  -            case EJB_OBJECT_BUSINESS_METHOD:

  -                doEjbObject_BUSINESS_METHOD(req, res);

  -                break;

  -

  -            // Home interface methods

  -            case EJB_HOME_CREATE:

  -                doEjbHome_CREATE(req, res);

  -                break;

  -

  -            case EJB_HOME_FIND:

  -                doEjbHome_FIND(req, res);

  -                break;

  -

  -            // javax.ejb.EJBObject methods

  -            case EJB_OBJECT_GET_EJB_HOME:

  -                doEjbObject_GET_EJB_HOME(req, res);

  -                break;

  -

  -            case EJB_OBJECT_GET_HANDLE:

  -                doEjbObject_GET_HANDLE(req, res);

  -                break;

  -

  -            case EJB_OBJECT_GET_PRIMARY_KEY:

  -                doEjbObject_GET_PRIMARY_KEY(req, res);

  -                break;

  -

  -            case EJB_OBJECT_IS_IDENTICAL:

  -                doEjbObject_IS_IDENTICAL(req, res);

  -                break;

  -

  -            case EJB_OBJECT_REMOVE:

  -                doEjbObject_REMOVE(req, res);

  -                break;

  -

  -                // javax.ejb.EJBHome methods

  -            case EJB_HOME_GET_EJB_META_DATA:

  -                doEjbHome_GET_EJB_META_DATA(req, res);

  -                break;

  -

  -            case EJB_HOME_GET_HOME_HANDLE:

  -                doEjbHome_GET_HOME_HANDLE(req, res);

  -                break;

  -

  -            case EJB_HOME_REMOVE_BY_HANDLE:

  -                doEjbHome_REMOVE_BY_HANDLE(req, res);

  -                break;

  -

  -            case EJB_HOME_REMOVE_BY_PKEY:

  -                doEjbHome_REMOVE_BY_PKEY(req, res);

  -                break;

  -            }

  -        } catch (org.openejb.InvalidateReferenceException e) {

  -            res.setResponse(EJB_SYS_EXCEPTION, e.getCause());

  -        } catch (org.openejb.ApplicationException e) {

  -            res.setResponse(EJB_APP_EXCEPTION, e.getCause());

  -        } catch (org.openejb.SystemException e) {

  -            res.setResponse(EJB_ERROR, e.getCause());

  -            // TODO:2: This means a severe error occured in OpenEJB

  -            // we should restart the container system or take other

  -            // aggressive actions to attempt recovery.

  -            log.fatal(req + ": OpenEJB encountered an unknown system error in 
container: ", e);

  -        } catch (java.lang.Throwable t) {

  -            //System.out.println(req+": Unkown error in container: ");

  -            replyWithFatalError(out, t, "Unknown error in container");

  -            return;

  -        } finally {

  -            log.info("EJB RESPONSE: " + res);

  -            try {

  -                res.writeExternal(out);

  -            } catch (java.io.IOException ie) {

  -                log.fatal("Couldn't write EjbResponse to output stream", ie);

  -            }

  -            call.reset();

  -        }

  -    }

  -

  -    private Object invoke(EJBRequest req) throws Throwable {

  -        CallContext call = CallContext.getCallContext();

  -        EJBContainer container = call.getContainer();

  -        // Prepare yourself ...

  -        // for you are about to enter ...

  -        // the Twilight Zone.

  -        InvocationResult result = null;

  -        try {

  -            result = container.invoke((EJBInvocationStream)req);

  -        } catch (Throwable t) {

  -            RemoteException re;

  -            if (t instanceof RemoteException) {

  -                re = (RemoteException) t;

  -            } else {

  -                re = new RemoteException("The bean encountered a non-application 
exception. method", t);

  -            }

  -            throw new InvalidateReferenceException(re);

  -        }

  -

  -        if (result.isException()) {

  -            throw new org.openejb.ApplicationException(result.getException());

  -        } else {

  -            return result.getResult();

  -        }

  -//        return container.invoke((EJBInvocationStream)req);

  -//        return container.invoke(req.getMethodInstance(), 
req.getMethodParameters(), req.getPrimaryKey());        

  -    }

  -

  -    protected void doEjbObject_BUSINESS_METHOD(EJBRequest req, EJBResponse res) 
throws Throwable {

  -        Object result = invoke(req);

  -

  -        res.setResponse(EJB_OK, result);

  -    }

  -

  -    // Home interface methods

  -    protected void doEjbHome_CREATE(EJBRequest req, EJBResponse res) throws 
Throwable {

  -        Object result = invoke(req);

  -

  -        if (result instanceof BaseEJB) {

  -            BaseEJB proxy = (BaseEJB) result;

  -            ProxyInfo info = proxy.getProxyInfo();

  -            res.setResponse(EJB_OK, info.getPrimaryKey());

  -        } else {

  -            // There should be no else, the entity should be found

  -            // or and exception should be thrown.

  -            //TODO:3: Localize all error messages in an separate file.

  -            result = new RemoteException("The bean is not EJB compliant.  The 
should be created or and exception should be thrown.");

  -            log.error(req + "The bean is not EJB compliant.  The should be created 
or and exception should be thrown.");

  -            res.setResponse(EJB_SYS_EXCEPTION, result);

  -        }

  -    }

  -

  -    /**

  -     * EJB 1.1 --

  -     * 9.1.8 Finder method return type

  -     *

  -     * 9.1.8.1 Single-object finder

  -     *

  -     * Some finder methods (such as ejbFindByPrimaryKey) are designed to return

  -     * at most one entity object. For these single-object finders, the result type

  -     * of the find<METHOD>(...)method defined in the entity bean�s home interface

  -     * is the entity bean�s remote interface. The result type of the corresponding

  -     * ejbFind<METHOD>(...) method defined in the entity�s implementation class is

  -     * the entity bean�s primary key type.

  -     *

  -     * 9.1.8.2 Multi-object finders

  -     *

  -     * Some finder methods are designed to return multiple entity objects. For

  -     * these multi-object finders, the result type of the find<METHOD>(...)method

  -     * defined in the entity bean�s home interface is a col-lection of objects

  -     * implementing the entity bean�s remote interface. The result type of the

  -     * corresponding ejbFind<METHOD>(...) implementation method defined in the

  -     * entity bean�s implementation class is a collection of objects of the entity

  -     * bean�s primary key type.

  -     *

  -     * The Bean Provider can choose two types to define a collection type for a 
finder:

  -     * � the JDK� 1.1 java.util.Enumeration interface

  -     * � the Java� 2 java.util.Collection interface

  -     *

  -     * A Bean Provider that wants to ensure that the entity bean is compatible

  -     * with containers and clients based on JDK TM 1.1 software must use the

  -     * java.util.Enumeration interface for the finder�s result type.

  -     * </P>

  -     */

  -    protected void doEjbHome_FIND(EJBRequest req, EJBResponse res) throws Throwable 
{

  -        Object result = invoke(req);

  -

  -        /* Multiple instances found */

  -        if (result instanceof Collection) {

  -

  -            Object[] objects = ((Collection) result).toArray();

  -

  -            for (int i = 0; i < objects.length; i++) {

  -                if (objects[i] instanceof ProxyInfo) {

  -                    objects[i] = ((ProxyInfo) objects[i]).getPrimaryKey();

  -                } else if (objects[i] instanceof BaseEJB) {

  -                    ProxyInfo proxy = ((BaseEJB) objects[i]).getProxyInfo();

  -                    objects[i] = proxy.getPrimaryKey();

  -                }

  -            }

  -            res.setResponse(EJB_OK_FOUND_COLLECTION, objects);

  -

  -        } else if (result instanceof java.util.Enumeration) {

  -            java.util.Enumeration resultAsEnum = (java.util.Enumeration) result;

  -            java.util.List listOfPKs = new java.util.ArrayList();

  -            while (resultAsEnum.hasMoreElements()) {

  -                Object pk = resultAsEnum.nextElement();

  -                if (pk instanceof ProxyInfo) {

  -                    pk = ((ProxyInfo) pk).getPrimaryKey();

  -                } else if (pk instanceof BaseEJB) {

  -                    ProxyInfo proxy = ((BaseEJB) pk).getProxyInfo();

  -                    pk = proxy.getPrimaryKey();

  -                }

  -                listOfPKs.add(pk);

  -            }

  -

  -            res.setResponse(EJB_OK_FOUND_ENUMERATION, listOfPKs.toArray(new 
Object[listOfPKs.size()]));

  -            /* Single instance found */

  -        } else if (result instanceof ProxyInfo) {

  -            result = ((ProxyInfo) result).getPrimaryKey();

  -            res.setResponse(EJB_OK_FOUND, result);

  -        } else if (result instanceof BaseEJB) {

  -            BaseEJB proxy = (BaseEJB) result;

  -            ProxyInfo info = proxy.getProxyInfo();

  -            res.setResponse(EJB_OK_FOUND, info.getPrimaryKey());

  -        } else {

  -            // There should be no else, the entity should be found

  -            // or an exception should be thrown.

  -            //TODO:3: Localize all error messages in an separate file.

  -            // TODO:4: It should provide more info on the wrong method

  -            final String message = "The bean is not EJB compliant. " +

  -                    "The finder method [" + req.getMethodInstance().getName() + "] 
is declared " +

  -                    "to return neither Collection nor the Remote Interface, " +

  -                    "but [" + result.getClass().getName() + "]";

  -            result = new RemoteException(message);

  -            log.error(req + " " + message);

  -            res.setResponse(EJB_SYS_EXCEPTION, result);

  -        }

  -    }

  -

  -    // javax.ejb.EJBObject methods

  -    private void doEjbObject_GET_EJB_HOME(EJBRequest req, EJBResponse res) throws 
Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbObject_GET_HANDLE(EJBRequest req, EJBResponse res) throws 
Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbObject_GET_PRIMARY_KEY(EJBRequest req, EJBResponse res) 
throws Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbObject_IS_IDENTICAL(EJBRequest req, EJBResponse res) throws 
Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbObject_REMOVE(EJBRequest req, EJBResponse res) throws 
Throwable {

  -        invoke(req);

  -        res.setResponse(EJB_OK, null);

  -    }

  -

  -    // javax.ejb.EJBHome methods

  -    private void doEjbHome_GET_EJB_META_DATA(EJBRequest req, EJBResponse res) 
throws Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbHome_GET_HOME_HANDLE(EJBRequest req, EJBResponse res) throws 
Exception {

  -        checkMethodAuthorization(req, res);

  -    }

  -

  -    private void doEjbHome_REMOVE_BY_HANDLE(EJBRequest req, EJBResponse res) throws 
Throwable {

  -        invoke(req);

  -        res.setResponse(EJB_OK, null);

  -    }

  -

  -    private void doEjbHome_REMOVE_BY_PKEY(EJBRequest req, EJBResponse res) throws 
Throwable {

  -        invoke(req);

  -        res.setResponse(EJB_OK, null);

  -    }

  -

  -    private void checkMethodAuthorization(EJBRequest req, EJBResponse res) throws 
Exception {

  -        // Nothing to do here other than check to see if the client

  -        // is authorized to call this method

  -        // TODO:3: Keep a cache in the client-side handler of methods it can't 
access

  -

  -//        SecurityService sec = OpenEJB.getSecurityService();

  -//        CallContext caller  = CallContext.getCallContext();

  -//        DeploymentInfo di   = caller.getDeploymentInfo();

  -//        String[] authRoles  = di.getAuthorizedRoles( req.getMethodInstance() );

  -//

  -//        if (sec.isCallerAuthorized( req.getClientIdentity(), authRoles )) {

  -        res.setResponse(EJB_OK, null);

  -//        } else {

  -//            this.daemon.logger.info(req + "Unauthorized Access by Principal 
Denied");

  -//            res.setResponse( EJB_APP_EXCEPTION , new 
RemoteException("Unauthorized Access by Principal Denied") );

  -//        }

  -    }

  -

  -    private EJBContainer getContainer(EJBRequest req) throws RemoteException {

  -        EJBContainer container = null;

  -

  -        if (req.getContainerCode() > 0) {

  -            container = containerIndex.getContainer(req.getContainerCode());

  -            if (container == null) {

  -                throw new RemoteException("The deployement with this ID is null");

  -            }

  -            req.setContainerID((String) container.getContainerID());

  -            return container;

  -        }

  -

  -        if (req.getContainerID() == null) {

  -            throw new RemoteException("Invalid deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());

  -        }

  -

  -        int idCode = containerIndex.getContainerIndex(req.getContainerID());

  -

  -        if (idCode == -1) {

  -            throw new RemoteException("No such deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());

  -        }

  -

  -        req.setContainerCode(idCode);

  -

  -        if (req.getContainerCode() < 0 || req.getContainerCode() >= 
containerIndex.length()) {

  -            throw new RemoteException("Invalid deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());

  -        }

  -

  -        container = containerIndex.getContainer(req.getContainerCode());

  -        if (container == null) {

  -            throw new RemoteException("The deployement with this ID is null");

  -        }

  -        return container;

  -    }

  -

  -    private void replyWithFatalError(ObjectOutputStream out, Throwable error, 
String message) {

  -        log.fatal(message, error);

  -        error.printStackTrace();

  -        RemoteException re = new RemoteException("The server has encountered a 
fatal error: " + message + " " + error);

  -        EJBResponse res = new EJBResponse();

  -        res.setResponse(EJB_ERROR, re);

  -        try {

  -            res.writeExternal(out);

  -        } catch (java.io.IOException ie) {

  -            log.error("Failed to write to EJBResponse", ie);

  -        }

  -    }

  -}

  +/**
  + * Redistribution and use of this software and associated documentation
  + * ("Software"), with or without modification, are permitted provided
  + * that the following conditions are met:
  + *
  + * 1. Redistributions of source code must retain copyright
  + *    statements and notices.  Redistributions must also contain a
  + *    copy of this document.
  + *
  + * 2. Redistributions in binary form must reproduce the
  + *    above copyright notice, this list of conditions and the
  + *    following disclaimer in the documentation and/or other
  + *    materials provided with the distribution.
  + *
  + * 3. The name "OpenEJB" must not be used to endorse or promote
  + *    products derived from this Software without prior written
  + *    permission of The OpenEJB Group.  For written permission,
  + *    please contact [EMAIL PROTECTED]
  + *
  + * 4. Products derived from this Software may not be called "OpenEJB"
  + *    nor may "OpenEJB" appear in their names without prior written
  + *    permission of The OpenEJB Group. OpenEJB is a registered
  + *    trademark of The OpenEJB Group.
  + *
  + * 5. Due credit should be given to the OpenEJB Project
  + *    (http://openejb.sf.net/).
  + *
  + * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
  + * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
  + * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
  + * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  + * OF THE POSSIBILITY OF SUCH DAMAGE.
  + *
  + * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.
  + *
  + * $Id$
  + */
  +
  +package org.openejb.server.ejbd;
  +
  +import java.io.ObjectInputStream;
  +import java.io.ObjectOutputStream;
  +import java.rmi.RemoteException;
  +import java.util.Collection;
  +
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.openejb.ContainerIndex;
  +import org.openejb.EJBContainer;
  +import org.openejb.InvalidateReferenceException;
  +import org.openejb.client.EJBRequest;
  +import org.openejb.client.EJBResponse;
  +import org.openejb.client.RequestMethods;
  +import org.openejb.client.ResponseCodes;
  +import org.openejb.proxy.BaseEJB;
  +import org.openejb.proxy.ProxyInfo;
  +
  +import org.apache.geronimo.core.service.InvocationResult;
  +
  +
  +class EjbRequestHandler implements ResponseCodes, RequestMethods {
  +
  +    private static final Log log = LogFactory.getLog(EjbRequestHandler.class);
  +    private final ContainerIndex containerIndex;
  +
  +
  +    EjbRequestHandler(ContainerIndex containerIndex) {
  +
  +        if (containerIndex == null) {
  +            containerIndex = ContainerIndex.getInstance();
  +        }
  +        this.containerIndex = containerIndex;
  +    }
  +
  +
  +    public void processRequest(ObjectInputStream input, ObjectOutputStream out) {
  +
  +        EJBObjectInputStream in = (EJBObjectInputStream) input;
  +
  +        EJBInvocationStream req = new EJBInvocationStream();
  +
  +        EJBResponse res = new EJBResponse();
  +
  +        // TODO:2: This method can throw a large number of exceptions, we should
  +        // be prepared to handle them all.  Look in the ObejctOutputStream code
  +        // for a full list of the exceptions thrown.
  +        // java.io.WriteAbortedException  can be thrown containing a
  +        //
  +        try {
  +            req.readExternal(in);
  +
  +            /*
  +                } catch (java.io.WriteAbortedException e){
  +                    if ( e.detail instanceof java.io.NotSerializableException){
  +                        //TODO:1: Log this warning better. Include information on 
what bean is to blame
  +
  +                        throw new Exception("Client attempting to serialize 
unserializable object: "+ e.detail.getMessage());
  +                    } else {
  +                        throw e.detail;
  +                    }
  +                } catch (java.io.EOFException e) {
  +                    throw new Exception("Reached the end of the stream before the 
full request could be read");
  +                } catch (Throwable t){
  +                    throw new Exception("Cannot read client request: "+ 
t.getClass().getName()+" "+ t.getMessage());
  +                }
  +            */
  +
  +        } catch (Throwable t) {
  +            replyWithFatalError(out, t, "Error caught during request processing");
  +            return;
  +        }
  +
  +        CallContext call = null;
  +        EJBContainer container = null;
  +
  +        try {
  +            container = getContainer(req);
  +            req.setProxyFactory(container.getProxyFactory());
  +            ClassLoader cl = container.getClassLoader();
  +            Thread.currentThread().setContextClassLoader(cl);
  +            in.setClassLoader(cl);
  +            log.warn("setting cl=" + cl + " for " + container.getContainerID());
  +        } catch (RemoteException e) {
  +            replyWithFatalError
  +                    (out, e, "No such deployment");
  +            return;
  +            /*
  +                logger.warn( req + "No such deployment: "+e.getMessage());
  +                res.setResponse( EJB_SYS_EXCEPTION, e);
  +                res.writeExternal( out );
  +                return;
  +            */
  +        } catch (Throwable t) {
  +            replyWithFatalError(out, t, "Unkown error occured while retrieving 
deployment");
  +            return;
  +        }
  +
  +        try {
  +            call = CallContext.getCallContext();
  +            call.setEJBRequest(req);
  +            call.setContainer(container);
  +        } catch (Throwable t) {
  +            replyWithFatalError(out, t, "Unable to set the thread context for this 
request");
  +            return;
  +        }
  +
  +        //logger.info( "EJB REQUEST : "+req );
  +
  +        try {
  +            switch (req.getRequestMethod()) {
  +                // Remote interface methods
  +                case EJB_OBJECT_BUSINESS_METHOD:
  +                    doEjbObject_BUSINESS_METHOD(req, res);
  +                    break;
  +
  +                // Home interface methods
  +                case EJB_HOME_CREATE:
  +                    doEjbHome_CREATE(req, res);
  +                    break;
  +
  +                case EJB_HOME_FIND:
  +                    doEjbHome_FIND(req, res);
  +                    break;
  +
  +                // javax.ejb.EJBObject methods
  +                case EJB_OBJECT_GET_EJB_HOME:
  +                    doEjbObject_GET_EJB_HOME(req, res);
  +                    break;
  +
  +                case EJB_OBJECT_GET_HANDLE:
  +                    doEjbObject_GET_HANDLE(req, res);
  +                    break;
  +
  +                case EJB_OBJECT_GET_PRIMARY_KEY:
  +                    doEjbObject_GET_PRIMARY_KEY(req, res);
  +                    break;
  +
  +                case EJB_OBJECT_IS_IDENTICAL:
  +                    doEjbObject_IS_IDENTICAL(req, res);
  +                    break;
  +
  +                case EJB_OBJECT_REMOVE:
  +                    doEjbObject_REMOVE(req, res);
  +                    break;
  +
  +                // javax.ejb.EJBHome methods
  +                case EJB_HOME_GET_EJB_META_DATA:
  +                    doEjbHome_GET_EJB_META_DATA(req, res);
  +                    break;
  +
  +                case EJB_HOME_GET_HOME_HANDLE:
  +                    doEjbHome_GET_HOME_HANDLE(req, res);
  +                    break;
  +
  +                case EJB_HOME_REMOVE_BY_HANDLE:
  +                    doEjbHome_REMOVE_BY_HANDLE(req, res);
  +                    break;
  +
  +                case EJB_HOME_REMOVE_BY_PKEY:
  +                    doEjbHome_REMOVE_BY_PKEY(req, res);
  +                    break;
  +            }
  +        } catch (org.openejb.InvalidateReferenceException e) {
  +            res.setResponse(EJB_SYS_EXCEPTION, e.getCause());
  +        } catch (org.openejb.ApplicationException e) {
  +            res.setResponse(EJB_APP_EXCEPTION, e.getCause());
  +        } catch (org.openejb.SystemException e) {
  +            res.setResponse(EJB_ERROR, e.getCause());
  +
  +            // TODO:2: This means a severe error occured in OpenEJB
  +            // we should restart the container system or take other
  +            // aggressive actions to attempt recovery.
  +            log.fatal(req + ": OpenEJB encountered an unknown system error in 
container: ", e);
  +        } catch (java.lang.Throwable t) {
  +            //System.out.println(req+": Unkown error in container: ");
  +            replyWithFatalError(out, t, "Unknown error in container");
  +            return;
  +        } finally {
  +            log.info("EJB RESPONSE: " + res);
  +            try {
  +                res.writeExternal(out);
  +            } catch (java.io.IOException ie) {
  +                log.fatal("Couldn't write EjbResponse to output stream", ie);
  +            }
  +            call.reset();
  +        }
  +    }
  +
  +
  +    private Object invoke(EJBRequest req) throws Throwable {
  +
  +        CallContext call = CallContext.getCallContext();
  +        EJBContainer container = call.getContainer();
  +
  +        // Prepare yourself ...
  +        // for you are about to enter ...
  +        // the Twilight Zone.
  +
  +        InvocationResult result = null;
  +        try {
  +            result = container.invoke((EJBInvocationStream) req);
  +        } catch (Throwable t) {
  +            RemoteException re;
  +            if (t instanceof RemoteException) {
  +                re = (RemoteException) t;
  +            } else {
  +                re = new RemoteException("The bean encountered a non-application 
exception. method", t);
  +            }
  +
  +            throw new InvalidateReferenceException(re);
  +
  +        }
  +
  +
  +        if (result.isException()) {
  +            throw new org.openejb.ApplicationException(result.getException());
  +        } else {
  +            return result.getResult();
  +        }
  +
  +//        return container.invoke((EJBInvocationStream)req);
  +//        return container.invoke(req.getMethodInstance(), 
req.getMethodParameters(), req.getPrimaryKey());        
  +
  +    }
  +
  +
  +    protected void doEjbObject_BUSINESS_METHOD(EJBRequest req, EJBResponse res) 
throws Throwable {
  +
  +        Object result = invoke(req);
  +
  +        res.setResponse(EJB_OK, result);
  +    }
  +
  +
  +
  +    // Home interface methods
  +
  +    protected void doEjbHome_CREATE(EJBRequest req, EJBResponse res) throws 
Throwable {
  +
  +        Object result = invoke(req);
  +
  +        if (result instanceof BaseEJB) {
  +            BaseEJB proxy = (BaseEJB) result;
  +            ProxyInfo info = proxy.getProxyInfo();
  +            res.setResponse(EJB_OK, info.getPrimaryKey());
  +        } else {
  +            // There should be no else, the entity should be found
  +            // or and exception should be thrown.
  +            //TODO:3: Localize all error messages in an separate file.
  +            result = new RemoteException("The bean is not EJB compliant.  The 
should be created or and exception should be thrown.");
  +            log.error(req + "The bean is not EJB compliant.  The should be created 
or and exception should be thrown.");
  +            res.setResponse(EJB_SYS_EXCEPTION, result);
  +        }
  +    }
  +
  +
  +    /**
  +     * EJB 1.1 --
  +     * 9.1.8 Finder method return type
  +     * <p/>
  +     * 9.1.8.1 Single-object finder
  +     * <p/>
  +     * Some finder methods (such as ejbFindByPrimaryKey) are designed to return
  +     * at most one entity object. For these single-object finders, the result type
  +     * of the find<METHOD>(...)method defined in the entity bean�s home interface
  +     * is the entity bean�s remote interface. The result type of the corresponding
  +     * ejbFind<METHOD>(...) method defined in the entity�s implementation class is
  +     * the entity bean�s primary key type.
  +     * <p/>
  +     * 9.1.8.2 Multi-object finders
  +     * <p/>
  +     * Some finder methods are designed to return multiple entity objects. For
  +     * these multi-object finders, the result type of the find<METHOD>(...)method
  +     * defined in the entity bean�s home interface is a col-lection of objects
  +     * implementing the entity bean�s remote interface. The result type of the
  +     * corresponding ejbFind<METHOD>(...) implementation method defined in the
  +     * entity bean�s implementation class is a collection of objects of the entity
  +     * bean�s primary key type.
  +     * <p/>
  +     * The Bean Provider can choose two types to define a collection type for a 
finder:
  +     * <p/>
  +     * � the JDK� 1.1 java.util.Enumeration interface
  +     * � the Java� 2 java.util.Collection interface
  +     * <p/>
  +     * A Bean Provider that wants to ensure that the entity bean is compatible
  +     * with containers and clients based on JDK TM 1.1 software must use the
  +     * java.util.Enumeration interface for the finder�s result type.
  +     */
  +
  +    protected void doEjbHome_FIND(EJBRequest req, EJBResponse res) throws Throwable 
{
  +
  +        Object result = invoke(req);
  +
  +        /* Multiple instances found */
  +        if (result instanceof Collection) {
  +
  +            Object[] objects = ((Collection) result).toArray();
  +
  +            for (int i = 0; i < objects.length; i++) {
  +                if (objects[i] instanceof ProxyInfo) {
  +                    objects[i] = ((ProxyInfo) objects[i]).getPrimaryKey();
  +                } else if (objects[i] instanceof BaseEJB) {
  +                    ProxyInfo proxy = ((BaseEJB) objects[i]).getProxyInfo();
  +                    objects[i] = proxy.getPrimaryKey();
  +                }
  +            }
  +            res.setResponse(EJB_OK_FOUND_COLLECTION, objects);
  +
  +        } else if (result instanceof java.util.Enumeration) {
  +            java.util.Enumeration resultAsEnum = (java.util.Enumeration) result;
  +            java.util.List listOfPKs = new java.util.ArrayList();
  +            while (resultAsEnum.hasMoreElements()) {
  +                Object pk = resultAsEnum.nextElement();
  +                if (pk instanceof ProxyInfo) {
  +                    pk = ((ProxyInfo) pk).getPrimaryKey();
  +                } else if (pk instanceof BaseEJB) {
  +                    ProxyInfo proxy = ((BaseEJB) pk).getProxyInfo();
  +                    pk = proxy.getPrimaryKey();
  +                }
  +                listOfPKs.add(pk);
  +            }
  +
  +            res.setResponse(EJB_OK_FOUND_ENUMERATION, listOfPKs.toArray(new 
Object[listOfPKs.size()]));
  +            /* Single instance found */
  +        } else if (result instanceof ProxyInfo) {
  +            result = ((ProxyInfo) result).getPrimaryKey();
  +            res.setResponse(EJB_OK_FOUND, result);
  +        } else if (result instanceof BaseEJB) {
  +            BaseEJB proxy = (BaseEJB) result;
  +            ProxyInfo info = proxy.getProxyInfo();
  +            res.setResponse(EJB_OK_FOUND, info.getPrimaryKey());
  +        } else {
  +
  +            // There should be no else, the entity should be found
  +            // or an exception should be thrown.
  +            //TODO:3: Localize all error messages in an separate file.
  +            // TODO:4: It should provide more info on the wrong method
  +            final String message = "The bean is not EJB compliant. " +
  +                    "The finder method [" + req.getMethodInstance().getName() + "] 
is declared " +
  +                    "to return neither Collection nor the Remote Interface, " +
  +                    "but [" + result.getClass().getName() + "]";
  +
  +            result = new RemoteException(message);
  +            log.error(req + " " + message);
  +            res.setResponse(EJB_SYS_EXCEPTION, result);
  +        }
  +    }
  +
  +
  +
  +    // javax.ejb.EJBObject methods
  +
  +    private void doEjbObject_GET_EJB_HOME(EJBRequest req, EJBResponse res) throws 
Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbObject_GET_HANDLE(EJBRequest req, EJBResponse res) throws 
Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbObject_GET_PRIMARY_KEY(EJBRequest req, EJBResponse res) 
throws Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbObject_IS_IDENTICAL(EJBRequest req, EJBResponse res) throws 
Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbObject_REMOVE(EJBRequest req, EJBResponse res) throws 
Throwable {
  +        invoke(req);
  +        res.setResponse(EJB_OK, null);
  +    }
  +
  +
  +
  +    // javax.ejb.EJBHome methods
  +
  +    private void doEjbHome_GET_EJB_META_DATA(EJBRequest req, EJBResponse res) 
throws Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbHome_GET_HOME_HANDLE(EJBRequest req, EJBResponse res) throws 
Exception {
  +        checkMethodAuthorization(req, res);
  +    }
  +
  +
  +    private void doEjbHome_REMOVE_BY_HANDLE(EJBRequest req, EJBResponse res) throws 
Throwable {
  +        invoke(req);
  +        res.setResponse(EJB_OK, null);
  +    }
  +
  +
  +    private void doEjbHome_REMOVE_BY_PKEY(EJBRequest req, EJBResponse res) throws 
Throwable {
  +        invoke(req);
  +        res.setResponse(EJB_OK, null);
  +    }
  +
  +
  +    private void checkMethodAuthorization(EJBRequest req, EJBResponse res) throws 
Exception {
  +
  +        // Nothing to do here other than check to see if the client
  +        // is authorized to call this method
  +        // TODO:3: Keep a cache in the client-side handler of methods it can't 
access
  +
  +
  +//        SecurityService sec = OpenEJB.getSecurityService();
  +//        CallContext caller  = CallContext.getCallContext();
  +//        DeploymentInfo di   = caller.getDeploymentInfo();
  +//        String[] authRoles  = di.getAuthorizedRoles( req.getMethodInstance() );
  +//
  +//        if (sec.isCallerAuthorized( req.getClientIdentity(), authRoles )) {
  +
  +        res.setResponse(EJB_OK, null);
  +
  +//        } else {
  +//            this.daemon.logger.info(req + "Unauthorized Access by Principal 
Denied");
  +//            res.setResponse( EJB_APP_EXCEPTION , new 
RemoteException("Unauthorized Access by Principal Denied") );
  +//        }
  +
  +    }
  +
  +
  +    private EJBContainer getContainer(EJBRequest req) throws RemoteException {
  +
  +        EJBContainer container = null;
  +
  +        if (req.getContainerCode() > 0) {
  +            container = containerIndex.getContainer(req.getContainerCode());
  +            if (container == null) {
  +                throw new RemoteException("The deployement with this ID is null");
  +            }
  +            req.setContainerID((String) container.getContainerID());
  +            return container;
  +        }
  +
  +        if (req.getContainerID() == null) {
  +            throw new RemoteException("Invalid deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());
  +        }
  +
  +
  +        int idCode = containerIndex.getContainerIndex(req.getContainerID());
  +
  +        if (idCode == -1) {
  +            throw new RemoteException("No such deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());
  +        }
  +
  +        req.setContainerCode(idCode);
  +
  +        if (req.getContainerCode() < 0 || req.getContainerCode() >= 
containerIndex.length()) {
  +            throw new RemoteException("Invalid deployment id and code: id=" + 
req.getContainerID() + ": code=" + req.getContainerCode());
  +        }
  +
  +        container = containerIndex.getContainer(req.getContainerCode());
  +        if (container == null) {
  +            throw new RemoteException("The deployement with this ID is null");
  +        }
  +
  +        return container;
  +    }
  +
  +
  +    private void replyWithFatalError(ObjectOutputStream out, Throwable error, 
String message) {
  +
  +        log.fatal(message, error);
  +        error.printStackTrace();
  +
  +        RemoteException re = new RemoteException("The server has encountered a 
fatal error: " + message + " " + error);
  +        EJBResponse res = new EJBResponse();
  +        res.setResponse(EJB_ERROR, re);
  +        try {
  +            res.writeExternal(out);
  +        } catch (java.io.IOException ie) {
  +            log.error("Failed to write to EJBResponse", ie);
  +        }
  +    }
  +
  +}
  +
  
  
  

Reply via email to