/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 * --------------------------------------------------------------------------
 * $Id: ResourceObjectFactory.java 15428 2008-10-07 11:20:29Z sauthieg $
 * --------------------------------------------------------------------------
 */
package org.ow2.jonas.resource.internal.naming;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
import javax.resource.cci.ConnectionFactory;

import org.ow2.jonas.deployment.rar.ConnectorDesc;
import org.ow2.jonas.deployment.rar.JonasConnectorDesc;
import org.ow2.jonas.lib.util.JNDIUtils;
import org.ow2.jonas.resource.internal.JOnASResourceService;
import org.ow2.jonas.resource.internal.Rar;
import org.ow2.jonas.resource.internal.ResourceServiceConstants;


/**
 * Resource Service {@link ObjectFactory} for {@link ConnectionFactory}.
 * @author Eric Hardesty
 */
public class ResourceObjectFactory implements ObjectFactory {

    /**
     * Create an object using the information provided
     * @param refObj the possibly null object containing reference information to create the  object.
     * @param name the name of this object relative to nameCtx, or null if no name is specified.
     * @param nameCtx the context relative to which the name parameter is specified, or null if name
     *                is relative to the default initial context.
     * @param env the possibly null environment that is used in creating the object.
     * @return Object created or null if unable to create
     * @throws Exception if an exception happened while trying to create the object
     */
    public Object getObjectInstance(final Object refObj,
                                    final Name name,
                                    final Context nameCtx,
                                    final Hashtable env) throws Exception {

        Reference ref = (Reference) refObj;

        if (ref == null) {
            System.out.println("No reference found");
            return null;
        }

        String raname = (String) ref.get(ResourceServiceConstants.JNDI_NAME).getContent();

        // Try to get a local reference
        Object obj = null;
        try {
            obj = JOnASResourceService.getResourceObject(raname);
            if (obj != null) {
                return obj;
            }
        } catch (Throwable ex) {
        }
        // If we did not return previously, we're in the ClientContainer

        // Need to load the factory in the client environment
        String rarObjectName = (String) ref.get(ResourceServiceConstants.RAR_OBJNAME).getContent();
        String factoryType = (String) ref.get(ResourceServiceConstants.FACTORY_TYPE).getContent();
        String factoryOff = (String) ref.get(ResourceServiceConstants.FACTORY_OFFSET).getContent();
        int factoryOffset = Integer.parseInt(factoryOff);

        RefAddr refAddr = null;

        // Create a ConnectorDesc (ra.xml)
        ConnectorDesc conn = null;
        refAddr = ref.get(ResourceServiceConstants.RA_XML);
        if (refAddr != null) {
            conn = (ConnectorDesc) JNDIUtils.getObjectFromBytes((byte[]) refAddr.getContent());
        }

        // Create a JonasConnectorDesc (jonas-ra.xml)
        JonasConnectorDesc jConn = null;
        refAddr = ref.get(ResourceServiceConstants.JONAS_RA_XML);
        if (refAddr != null) {
            jConn = (JonasConnectorDesc) JNDIUtils.getObjectFromBytes((byte[]) refAddr.getContent());
        }

        // This will either get the other server's implementation or a client version
        Rar ra = new Rar();
        obj = ra.createFactory(raname,
                               rarObjectName,
                               factoryOffset,
                               factoryType,
                               conn,
                               jConn);

        return obj;
    }
}
