/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.sun.messaging.naming;

import com.sun.messaging.ConnectionConfiguration;
import com.sun.messaging.ConnectionFactory;
import com.sun.messaging.QueueConnectionFactory;
import com.sun.messaging.TopicConnectionFactory;
import com.sun.messaging.XAQueueConnectionFactory;
import com.sun.messaging.XATopicConnectionFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.RefAddr;
import javax.naming.Reference;

/**
 * Very simple ObjectFactory to OpenMQ that just iterate over all 
 * ConnectionConfiguration static properties and check if they are in the
 * Reference of the JNDI definition. This way any OpenMQ configuration property
 * can be set.
 * 
 * @author ricky
 */
public class CFReflectionObjectFactory implements javax.naming.spi.ObjectFactory {

    /**
     * Perform the iteration using reflection over 
     * @param cf The ConnectionFactory to set properties ConnectionConfiguration
     * class. Any property that exists in the ref is set.
     * @param ref The reference definition
     */
    static private void createConfiguration(ConnectionFactory cf, Reference ref) {
        Field[] fields = ConnectionConfiguration.class.getDeclaredFields();
        if (fields != null) {
            for (Field field : fields) {
                if (field.getType().equals(String.class) && Modifier.isStatic(field.getModifiers())
                        && Modifier.isPublic(field.getModifiers())) {
                    try {
                        // get the value of the conf
                        String fieldValue = (String) field.get(null);
                        // if this value is in the ref just set it
                        RefAddr valueAddr = ref.get(fieldValue);
                        if (valueAddr != null) {
                            cf.setProperty(fieldValue, (String) valueAddr.getContent());
                            //System.err.println("================ String " + fieldValue + ":" + valueAddr.getContent());
                        }
                    } catch (Exception e) {
                    }
                }
            }
        }
    }

    /**
     * 
     * @param obj
     * @param name
     * @param ctx
     * @param env
     * @return
     * @throws Exception 
     */
    @Override
    public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception {
        if (obj instanceof Reference) {
            // get the reference
            Reference ref = (Reference) obj;
            String refClassName = ref.getClassName();
            Object newobj = Class.forName(ref.getClassName()).newInstance();
            // create a Queue or Topic factory
            ConnectionFactory cf = null;
            if (refClassName.equals(com.sun.messaging.QueueConnectionFactory.class.getName())) {
                cf = new QueueConnectionFactory();
            } else if (refClassName.equals(com.sun.messaging.TopicConnectionFactory.class.getName())) {
                cf = new TopicConnectionFactory();
            } else if (refClassName.equals(com.sun.messaging.XAQueueConnectionFactory.class.getName())) {
                cf = new XAQueueConnectionFactory();
            } else if (refClassName.equals(com.sun.messaging.XATopicConnectionFactory.class.getName())) {
                cf = new XATopicConnectionFactory();
            } else {
                throw new MissingVersionNumberException();
            }
            // iterate over all properties of the REF and set if they
            // are equal to one of the class ConnectionConfiguration
            createConfiguration(cf, ref);
            return cf;
        } else {
            return null;
        }
    }
}

