/*
 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javax.sql.rowset.spi;

import java.util.Map;
import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Vector;
import java.util.Properties;
import java.util.Collection;
import java.util.StringTokenizer;
import java.util.logging.*;
import java.util.*;

import java.sql.*;
import javax.sql.*;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.FileNotFoundException;

import javax.naming.*;

/**
 * The Service Provider Interface (SPI) mechanism that generates <code>SyncProvider</code>
 * instances to be used by disconnected <code>RowSet</code> objects.
 * The <code>SyncProvider</code> instances in turn provide the
 * <code>javax.sql.RowSetReader</code> object the <code>RowSet</code> object
 * needs to populate itself with data and the
 * <code>javax.sql.RowSetWriter</code> object it needs to
 * propagate changes to its
 * data back to the underlying data source.
 * <P>
 * Because the methods in the <code>SyncFactory</code> class are all static,
 * there is only one <code>SyncFactory</code> object
 * per Java VM at any one time. This ensures that there is a single source from which a
 * <code>RowSet</code> implementation can obtain its <code>SyncProvider</code>
 * implementation.
 * <p>
 * <h3>1.0 Overview</h3>
 * The <code>SyncFactory</code> class provides an internal registry of available
 * synchronization provider implementations (<code>SyncProvider</code> objects).
 * This registry may be queried to determine which
 * synchronization providers are available.
 * The following line of code gets an enumeration of the providers currently registered.
 * <PRE>
 *     java.util.Enumeration e = SyncFactory.getRegisteredProviders();
 * </PRE>
 * All standard <code>RowSet</code> implementations must provide at least two providers:
 * <UL>
 *  <LI>an optimistic provider for use with a <code>CachedRowSet</code> implementation
 *     or an implementation derived from it
 *  <LI>an XML provider, which is used for reading and writing XML, such as with
 *       <code>WebRowSet</code> objects
 * </UL>
 * Note that the JDBC RowSet Implementations include the <code>SyncProvider</code>
 * implemtations <code>RIOptimisticProvider</code> and <code>RIXmlProvider</code>,
 * which satisfy this requirement.
 * <P>
 * The <code>SyncFactory</code> class provides accessor methods to assist
 * applications in determining which synchronization providers are currently
 * registered with the <code>SyncFactory</code>.
 * <p>
 * Other methods let <code>RowSet</code> persistence providers be
 * registered or de-registered with the factory mechanism. This
 * allows additional synchronization provider implementations to be made
 * available to <code>RowSet</code> objects at run time.
 * <p>
 * Applications can apply a degree of filtering to determine the level of
 * synchronization that a <code>SyncProvider</code> implementation offers.
 * The following criteria determine whether a provider is
 * made available to a <code>RowSet</code> object:
 * <ol>
 * <li>If a particular provider is specified by a <code>RowSet</code> object, and
 * the <code>SyncFactory</code> does not contain a reference to this provider,
 * a <code>SyncFactoryException</code> is thrown stating that the synchronization
 * provider could not be found.
 * <p>
 * <li>If a <code>RowSet</code> implementation is instantiated with a specified
 * provider and the specified provider has been properly registered, the
 * requested provider is supplied. Otherwise a <code>SyncFactoryException</code>
 * is thrown.
 * <p>
 * <li>If a <code>RowSet</code> object does not specify a
 * <code>SyncProvider</code> implementation and no additional
 * <code>SyncProvider</code> implementations are available, the reference
 * implementation providers are supplied.
 * </ol>
 * <h3>2.0 Registering <code>SyncProvider</code> Implementations</h3>
 * <p>
 * Both vendors and developers can register <code>SyncProvider</code>
 * implementations using one of the following mechanisms.
 * <ul>
 * <LI><B>Using the command line</B><BR>
 * The name of the provider is supplied on the command line, which will add
 * the provider to the system properties.
 * For example:
 * <PRE>
 *    -Drowset.provider.classname=com.fred.providers.HighAvailabilityProvider
 * </PRE>
 * <li><b>Using the Standard Properties File</b><BR>
 * The reference implementation is targeted
 * to ship with J2SE 1.5, which will include an additional resource file
 * that may be edited by hand. Here is an example of the properties file
 * included in the reference implementation:
 * <PRE>
 *   #Default JDBC RowSet sync providers listing
 *   #
 *
 *   # Optimistic synchronization provider
 *   rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
 *   rowset.provider.vendor.0=Sun Microsystems Inc
 *   rowset.provider.version.0=1.0
 *
 *   # XML Provider using standard XML schema
 *   rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
 *   rowset.provider.vendor.1=Sun Microsystems Inc.
 *   rowset.provider.version.1=1.0
 * </PRE>
 * The <code>SyncFactory</code> checks this file and registers the
 * <code>SyncProvider</code> implementations that it contains. A
 * developer or vendor can add other implementations to this file.
 * For example, here is a possible addition:
 * <PRE>
 *     rowset.provider.classname.2=com.fred.providers.HighAvailabilityProvider
 *     rowset.provider.vendor.2=Fred, Inc.
 *     rowset.provider.version.2=1.0
 * </PRE>
 * <p>
 * <li><b>Using a JNDI Context</b><BR>
 * Available providers can be registered on a JNDI
 * context, and the <code>SyncFactory</code> will attempt to load
 * <code>SyncProvider</code> implementations from that JNDI context.
 * For example, the following code fragment registers a provider implementation
 * on a JNDI context.  This is something a deployer would normally do. In this
 * example, <code>MyProvider</code> is being registered on a CosNaming
 * namespace, which is the namespace used by J2EE resources.
 * <PRE>
 *    import javax.naming.*;
 *
 *    Hashtable svrEnv = new  Hashtable();
 *    srvEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
 *
 *    Context ctx = new InitialContext(svrEnv);
 *    com.fred.providers.MyProvider = new MyProvider();
 *    ctx.rebind("providers/MyProvider", syncProvider);
 * </PRE>
 * </ul>
 * Next, an application will register the JNDI context with the
 * <code>SyncFactory</code> instance.  This allows the <code>SyncFactory</code>
 * to browse within the JNDI context looking for <code>SyncProvider</code>
 * implementations.
 * <PRE>
 *    Hashtable appEnv = new Hashtable();
 *    appEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
 *    appEnv.put(Context.PROVIDER_URL, "iiop://hostname/providers");
 *    Context ctx = new InitialContext(appEnv);
 *
 *    SyncFactory.registerJNDIContext(ctx);
 * </PRE>
 * If a <code>RowSet</code> object attempts to obtain a <code>MyProvider</code>
 * object, the <code>SyncFactory</code> will try to locate it. First it searches
 * for it in the system properties, then it looks in the resource files, and
 * finally it checks the JNDI context that has been set. The <code>SyncFactory</code>
 * instance verifies that the requested provider is a valid extension of the
 * <code>SyncProvider</code> abstract class and then gives it to the
 * <code>RowSet</code> object. In the following code fragment, a new
 * <code>CachedRowSet</code> object is created and initialized with
 * <i>env</i>, which contains the binding to <code>MyProvider</code>.
 * <PRE>
 *    Hashtable env = new Hashtable();
 *    env.put(SyncFactory.ROWSET_SYNC_PROVIDER, "com.fred.providers.MyProvider");
 *    CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env);
 * </PRE>
 * Further details on these mechanisms are available in the
 * <code>javax.sql.rowset.spi</code> package specification.
 *
 * @author  Jonathan Bruce
 * @see javax.sql.rowset.spi.SyncProvider
 * @see javax.sql.rowset.spi.SyncFactoryException
 */
public class SyncFactory {

    /*
     * The variable that represents the singleton instance
     * of the <code>SyncFactory</code> class.
     */
    private static SyncFactory syncFactory = null;

    /**
     * Creates a new <code>SyncFactory</code> object, which is the singleton
     * instance.
     * Having a private constructor guarantees that no more than
     * one <code>SyncProvider</code> object can exist at a time.
     */
    private SyncFactory() {};

    /**
     * The standard property-id for a synchronization provider implementation
     * name.
     */
    public static String ROWSET_SYNC_PROVIDER =
        "rowset.provider.classname";

    /**
     * The standard property-id for a synchronization provider implementation
     * vendor name.
     */
    public static String ROWSET_SYNC_VENDOR =
        "rowset.provider.vendor";

    /**
     * The standard property-id for a synchronization provider implementation
     * version tag.
     */
    public static String ROWSET_SYNC_PROVIDER_VERSION =
        "rowset.provider.version";

    /**
     * The standard resource file name.
     */
    private static String ROWSET_PROPERTIES = "rowset.properties";

    /**
     * The RI Optimistic Provider.
     */
    private static String default_provider =
        "com.sun.rowset.providers.RIOptimisticProvider";

    /**
     * The initial JNDI context where <code>SyncProvider</code> implementations can
     * be stored and from which they can be invoked.
     */
    private static Context ic;

    /**
     * The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
     */
    private static Logger rsLogger;

    /**
     *
     */
    private static Level rsLevel;

    /**
     * The registry of available <code>SyncProvider</code> implementations.
     * See section 2.0 of the class comment for <code>SyncFactory</code> for an
     * explanation of how a provider can be added to this registry.
     */
    private static Hashtable implementations;

    /**
     * Internal sync object used to maintain the SPI as a singleton
     */
    private static Object logSync = new Object();

    /**
     * Internal PrintWriter field for logging facility
     */
    private static java.io.PrintWriter logWriter = null;

    /**
     * Adds the the given synchronization provider to the factory register. Guidelines
     * are provided in the <code>SyncProvider</code> specification for the
     * required naming conventions for <code>SyncProvider</code>
     * implementations.
     * <p>
     * Synchronization providers bound to a JNDI context can be
     * registered by binding a SyncProvider instance to a JNDI namespace.
     * <ul>
     * <pre>
     * SyncProvider p = new MySyncProvider();
     * InitialContext ic = new InitialContext();
     * ic.bind ("jdbc/rowset/MySyncProvider", p);
     * </pre>
     * </ul>
     * Furthermore, an initial JNDI context should be set with the
     * <code>SyncFactory</code> using the <code>setJNDIContext</code> method.
     * The <code>SyncFactory</code> leverages this context to search for
     * available <code>SyncProvider</code> objects bound to the JNDI
     * context and its child nodes.
     *
     * @param providerID A <code>String</code> object with the unique ID of the
     *             synchronization provider being registered
     * @throws SyncFactoryException if an attempt is made to supply an empty
     *         or null provider name
     * @see #setJNDIContext
     */
    public static synchronized void registerProvider(String providerID)
        throws SyncFactoryException {

        ProviderImpl impl = new ProviderImpl();
        impl.setClassname(providerID);
        initMapIfNecessary();
        implementations.put(providerID, impl);

    }

    /**
     * Returns the <code>SyncFactory</code> singleton.
     *
     * @return the <code>SyncFactory</code> instance
     */
     public static SyncFactory getSyncFactory(){

         // This method uses the Singleton Design Pattern
         // with Double-Checked Locking Pattern for
         // 1. Creating single instance of the SyncFactory
         // 2. Make the class thread safe, so that at one time
         //    only one thread enters the synchronized block
         //    to instantiate.

         // if syncFactory object is already there
         // don't go into synchronized block and return
         // that object.
         // else go into synchronized block

         if(syncFactory == null){
             synchronized(SyncFactory.class) {
                if(syncFactory == null){
                    syncFactory = new SyncFactory();
                } //end if
             } //end synchronized block
         } //end if
         return syncFactory;
     }

    /**
     * Removes the designated currently registered synchronization provider from the
     * Factory SPI register.
     *
     * @param providerID The unique-id of the synchronization provider
     * @throws SyncFactoryException If an attempt is made to
     * unregister a SyncProvider implementation that was not registered.
     */
    public static synchronized void unregisterProvider(String providerID)
        throws SyncFactoryException {
        initMapIfNecessary();
        if (implementations.containsKey(providerID)) {
            implementations.remove(providerID);
        }
    }

    private static String colon = ":";
    private static String strFileSep = "/";

    private static synchronized void initMapIfNecessary() throws SyncFactoryException {

        // Local implementation class names and keys from Properties
        // file, translate names into Class objects using Class.forName
        // and store mappings
        Properties properties = new Properties();

        if (implementations == null) {
            implementations = new Hashtable();

            try {

                // check if user is supplying his Synchronisation Provider
                // Implementation  if not use Sun's implementation.
                // properties.load(new FileInputStream(ROWSET_PROPERTIES));

                // The rowset.properties needs to be in jdk/jre/lib when
                // integrated with jdk.
                // else it should be picked from -D option from command line.

                // -Drowset.properties will add to standard properties. Similar
                // keys will over-write

                /*
                 * Dependent on application
                 */
                String strRowsetProperties = System.getProperty("rowset.properties");
                if ( strRowsetProperties != null) {
                    // Load user's implementation of SyncProvider
                    // here. -Drowset.properties=/abc/def/pqr.txt
                    ROWSET_PROPERTIES = strRowsetProperties;
                    properties.load(new FileInputStream(ROWSET_PROPERTIES));
                    parseProperties(properties);
                }

                /*
                 * Always available
                 */
                ROWSET_PROPERTIES = "javax" + strFileSep + "sql" +
                    strFileSep + "rowset" + strFileSep +
                    "rowset.properties";
                // properties.load(
                //                ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES));

                ClassLoader cl = Thread.currentThread().getContextClassLoader();

                properties.load(cl.getResourceAsStream(ROWSET_PROPERTIES));
                parseProperties(properties);

                // removed else, has properties should sum together

            } catch (FileNotFoundException e) {
                throw new SyncFactoryException("Cannot locate properties file: " + e);
            } catch (IOException e) {
                throw new SyncFactoryException("IOException: " + e);
            }

            /*
             * Now deal with -Drowset.provider.classname
             * load additional properties from -D command line
             */
            properties.clear();
            String providerImpls = System.getProperty(ROWSET_SYNC_PROVIDER);

            if (providerImpls != null) {
                int i = 0;
                if (providerImpls.indexOf(colon) > 0) {
                    StringTokenizer tokenizer = new StringTokenizer(providerImpls, colon);
                    while (tokenizer.hasMoreElements()) {
                        properties.put(ROWSET_SYNC_PROVIDER + "." + i, tokenizer.nextToken());
                        i++;
                    }
                } else {
                    properties.put(ROWSET_SYNC_PROVIDER, providerImpls);
                }
                parseProperties(properties);
            }
        }
    }

    /**
     * The internal boolean switch that indicates whether a JNDI
     * context has been established or not.
     */
    private static boolean jndiCtxEstablished = false;

    /**
     * The internal debug switch.
     */
    private static boolean debug = false;

    /**
     * Internal registry count for the number of providers contained in the
     * registry.
     */
    private static int providerImplIndex = 0;

    /**
     * Internal handler for all standard property parsing. Parses standard
     * ROWSET properties and stores lazy references into the the internal registry.
     */
    private static void parseProperties(Properties p) {

        ProviderImpl impl = null;
        String key = null;
        String[] propertyNames = null;

        for (Enumeration e = p.propertyNames(); e.hasMoreElements() ;) {

            String str = (String)e.nextElement();

            int w = str.length();

            if (str.startsWith(SyncFactory.ROWSET_SYNC_PROVIDER)) {

                impl = new ProviderImpl();
                impl.setIndex(providerImplIndex++);

                if (w == (SyncFactory.ROWSET_SYNC_PROVIDER).length()) {
                    // no property index has been set.
                    propertyNames = getPropertyNames(false);
                } else {
                    // property index has been set.
                    propertyNames = getPropertyNames(true, str.substring(w-1));
                }

                key = p.getProperty(propertyNames[0]);
                impl.setClassname(key);
                impl.setVendor(p.getProperty(propertyNames[1]));
                impl.setVersion(p.getProperty(propertyNames[2]));
                implementations.put(key, impl);
            }
        }
    }

    /**
     * Used by the parseProperties methods to disassemble each property tuple.
     */
    private static String[] getPropertyNames(boolean append) {
        return getPropertyNames(append, null);
    }

    /**
     * Disassembles each property and its associated value. Also handles
     * overloaded property names that contain indexes.
     */
    private static String[] getPropertyNames(boolean append,
                                             String propertyIndex) {
        String dot = ".";
        String[] propertyNames =
            new String[] {SyncFactory.ROWSET_SYNC_PROVIDER,
                              SyncFactory.ROWSET_SYNC_VENDOR,
                              SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
        if (append) {
            for (int i = 0; i < propertyNames.length; i++) {
                propertyNames[i] = propertyNames[i] +
                    dot +
                    propertyIndex;
            }
            return propertyNames;
        } else {
            return propertyNames;
        }
    }

    /**
     * Internal debug method that outputs the registry contents.
     */
    private static void showImpl(ProviderImpl impl) {
        System.out.println("Provider implementation:");
        System.out.println("Classname: " + impl.getClassname());
        System.out.println("Vendor: " + impl.getVendor());
        System.out.println("Version: " + impl.getVersion());
        System.out.println("Impl index: " + impl.getIndex());
    }

    /**
     * Returns the <code>SyncProvider</code> instance identified by <i>providerID</i>.
     *
     * @param providerID the unique identifier of the provider
     * @return a <code>SyncProvider</code> implementation
     * @throws SyncFactoryException If the SyncProvider cannot be found or
     * some error was encountered when trying to invoke this provider.
     */
    public static SyncProvider getInstance(String providerID)
        throws SyncFactoryException {
        initMapIfNecessary(); // populate HashTable
        initJNDIContext();    // check JNDI context for any additional bindings

        ProviderImpl impl = (ProviderImpl)implementations.get(providerID);

        if (impl == null) {
            // Requested SyncProvider is unavailable. Return default provider.
            return new com.sun.rowset.providers.RIOptimisticProvider();
        }

        // Attempt to invoke classname from registered SyncProvider list
        Class c = null;
        try {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();

            /**
             * The SyncProvider implementation of the user will be in
             * the classpath. We need to find the ClassLoader which loads
             * this SyncFactory and try to laod the SyncProvider class from
             * there.
             **/

            c = Class.forName(providerID, true, cl);

            if (c != null) {
                return (SyncProvider)c.newInstance();
            } else {
                return new com.sun.rowset.providers.RIOptimisticProvider();
            }

        } catch (IllegalAccessException e) {
            throw new SyncFactoryException("IllegalAccessException: " + e.getMessage());
        } catch (InstantiationException e) {
            throw new SyncFactoryException("InstantiationException: " + e.getMessage());
        } catch (ClassNotFoundException e) {
            throw new SyncFactoryException("ClassNotFoundException: " + e.getMessage());
        }
    }
    /**
     * Returns an Enumeration of currently registered synchronization
     * providers.  A <code>RowSet</code> implementation may use any provider in
     * the enumeration as its <code>SyncProvider</code> object.
     * <p>
     * At a minimum, the reference synchronization provider allowing
     * RowSet content data to be stored using a JDBC driver should be
     * possible.
     *
     * @return Enumeration  A enumeration of available synchronization
     * providers that are registered with this Factory
     */
    public static Enumeration<SyncProvider> getRegisteredProviders()
        throws SyncFactoryException {
        initMapIfNecessary();
        // return a collection of classnames
        // of type SyncProvider
        return implementations.elements();
    }

    /**
     * Sets the logging object to be used by the <code>SyncProvider</code>
     * implementation provided by the <code>SyncFactory</code>. All
     * <code>SyncProvider</code> implementations can log their events to
     * this object and the application can retrieve a handle to this
     * object using the <code>getLogger</code> method.
     *
     * @param logger A Logger object instance
     */
    public static void setLogger(Logger logger) {
        rsLogger = logger;
    }

    /**
     * Sets the logging object that is used by <code>SyncProvider</code>
     * implementations provided by the <code>SyncFactory</code> SPI. All
     * <code>SyncProvider</code> implementations can log their events
     * to this object and the application can retrieve a handle to this
     * object using the <code>getLogger</code> method.
     *
     * @param logger a Logger object instance
     * @param level a Level object instance indicating the degree of logging
     * required
     */
    public static void setLogger(Logger logger, Level level) {
        // singleton

        rsLogger = logger;
        rsLogger.setLevel(level);
    }

    /**
     * Returns the logging object for applications to retrieve
     * synchronization events posted by SyncProvider implementations.
     *
     * @throws SyncFactoryException if no logging object has been set.
     */
    public static Logger getLogger() throws SyncFactoryException {
        // only one logger per session
        if(rsLogger == null){
           throw new SyncFactoryException("(SyncFactory) : No logger has been set");
        }
        return rsLogger;
    }

   /**
    * Sets the initial JNDI context from which SyncProvider implementations
    * can be retrieved from a JNDI namespace
    *
    * @param ctx a valid JNDI context
    * @throws SyncFactoryException if the supplied JNDI context is null
    */
    public static void setJNDIContext(javax.naming.Context ctx)
        throws SyncFactoryException {
        if (ctx == null) {
            throw new SyncFactoryException("Invalid JNDI context supplied");
        }
        ic = ctx;
        jndiCtxEstablished = true;
   }

    /**
     * Controls JNDI context intialization.
     *
     * @throws SyncFactoryException if an error occurs parsing the JNDI context
     */
    private static void initJNDIContext() throws SyncFactoryException {

        if (jndiCtxEstablished && (ic != null) && (lazyJNDICtxRefresh == false)) {
            try {
                parseProperties(parseJNDIContext());
                lazyJNDICtxRefresh = true; // touch JNDI namespace once.
            } catch (NamingException e) {
                e.printStackTrace();
                throw new SyncFactoryException("SPI: NamingException: " + e.getExplanation());
            } catch (Exception e) {
                e.printStackTrace();
        throw new SyncFactoryException("SPI: Exception: " + e.getMessage());
            }
        }
    }
    /**
     * Internal switch indicating whether the JNDI namespace should be re-read.
     */
    private static boolean lazyJNDICtxRefresh = false;

    /**
     * Parses the set JNDI Context and passes bindings to the enumerateBindings
     * method when complete.
     */
    private static Properties parseJNDIContext() throws NamingException {

        NamingEnumeration bindings = ic.listBindings("");
        Properties properties = new Properties();

        // Hunt one level below context for available SyncProvider objects
        enumerateBindings(bindings, properties);

        return properties;
    }

    /**
     * Scans each binding on JNDI context and determines if any binding is an
     * instance of SyncProvider, if so, add this to the registry and continue to
     * scan the current context using a re-entrant call to this method until all
     * bindings have been enumerated.
     */
    private static void enumerateBindings(NamingEnumeration bindings,
        Properties properties) throws NamingException {

        boolean syncProviderObj = false; // move to parameters ?

        try {
            Binding bd = null;
            Object elementObj = null;
            String element = null;
            while (bindings.hasMore()) {
                bd = (Binding)bindings.next();
                element = bd.getName();
                elementObj = bd.getObject();

                if (!(ic.lookup(element) instanceof Context)) {
                     // skip directories/sub-contexts
                     if (ic.lookup(element) instanceof SyncProvider) {
                        syncProviderObj = true;
                     }
                }

                if (syncProviderObj) {
                    SyncProvider sync = (SyncProvider)elementObj;
                    properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
                        sync.getProviderID());
                    syncProviderObj = false; // reset
                }

            }
        } catch (javax.naming.NotContextException e) {
            bindings.next();
            // Re-entrant call into method
            enumerateBindings(bindings, properties);
        }
    }
}

   /**
     * Internal class that defines the lazy reference construct for each registered
     * SyncProvider implementation.
     */
   class ProviderImpl extends SyncProvider {
        private String className = null;
        private String vendorName = null;
        private String ver = null;
        private int index;

        public void setClassname(String classname) {
            className = classname;
        }

        public String getClassname() {
            return className;
        }

        public void setVendor(String vendor) {
            vendorName = vendor;
        }

        public String getVendor() {
            return vendorName;
        }

        public void setVersion(String providerVer) {
            ver = providerVer;
        }

        public String getVersion() {
            return ver;
        }

        public void setIndex(int i) {
            index = i;
        }

        public int getIndex() {
            return index;
        }

        public int getDataSourceLock() throws SyncProviderException {

           int dsLock = 0;
            try
            {
               dsLock = SyncFactory.getInstance(className).getDataSourceLock();
            } catch(SyncFactoryException sfEx) {

                 throw new SyncProviderException(sfEx.getMessage());
             }

            return dsLock;
        }

        public int getProviderGrade() {

           int grade = 0;

           try
           {
              grade =  SyncFactory.getInstance(className).getProviderGrade();
           } catch(SyncFactoryException sfEx) {
               //
           }

           return grade;
        }

        public String getProviderID() {
            return className;
        }

        /*
        public javax.sql.RowSetInternal getRowSetInternal() {
          try
           {
              return SyncFactory.getInstance(className).getRowSetInternal();
           } catch(SyncFactoryException sfEx) {
               //
           }
        }
        */

        public javax.sql.RowSetReader getRowSetReader() {

        RowSetReader rsReader = null;;

        try
        {
           rsReader = SyncFactory.getInstance(className).getRowSetReader();
         } catch(SyncFactoryException sfEx) {
               //
         }

         return rsReader;

        }

        public javax.sql.RowSetWriter getRowSetWriter() {

        RowSetWriter rsWriter = null;
        try
           {
            rsWriter =  SyncFactory.getInstance(className).getRowSetWriter();
           } catch(SyncFactoryException sfEx) {
               //
           }

           return rsWriter;
        }
        public void setDataSourceLock(int param)
        throws SyncProviderException {

         try
           {
              SyncFactory.getInstance(className).setDataSourceLock(param);
           } catch(SyncFactoryException sfEx) {

               throw new SyncProviderException(sfEx.getMessage());
           }
        }

        public int supportsUpdatableView() {

        int view = 0;

        try
         {
           view = SyncFactory.getInstance(className).supportsUpdatableView();
         } catch(SyncFactoryException sfEx) {
               //
         }

         return view;
       }

    }
