KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > sql > rowset > spi > SyncFactory


1 /*
2  * @(#)SyncFactory.java 1.13 04/07/17
3  * @(#)SyncFactory.java 1.11 04/06/25
4  *
5  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
6  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
7  */

8
9 package javax.sql.rowset.spi;
10
11 import java.util.Map JavaDoc;
12 import java.util.Hashtable JavaDoc;
13 import java.util.Enumeration JavaDoc;
14 import java.util.Vector JavaDoc;
15 import java.util.Properties JavaDoc;
16 import java.util.Collection JavaDoc;
17 import java.util.StringTokenizer JavaDoc;
18 import java.util.logging.*;
19 import java.util.*;
20
21 import java.sql.*;
22 import javax.sql.*;
23
24 import java.io.FileInputStream JavaDoc;
25 import java.io.IOException JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27
28 import javax.naming.*;
29
30 /**
31  * The Service Provider Interface (SPI) mechanism that generates <code>SyncProvider</code>
32  * instances to be used by disconnected <code>RowSet</code> objects.
33  * The <code>SyncProvider</code> instances in turn provide the
34  * <code>javax.sql.RowSetReader</code> object the <code>RowSet</code> object
35  * needs to populate itself with data and the
36  * <code>javax.sql.RowSetWriter</code> object it needs to
37  * propagate changes to its
38  * data back to the underlying data source.
39  * <P>
40  * Because the methods in the <code>SyncFactory</code> class are all static,
41  * there is only one <code>SyncFactory</code> object
42  * per Java VM at any one time. This ensures that there is a single source from which a
43  * <code>RowSet</code> implementation can obtain its <code>SyncProvider</code>
44  * implementation.
45  * <p>
46  * <h3>1.0 Overview</h3>
47  * The <code>SyncFactory</code> class provides an internal registry of available
48  * synchronization provider implementations (<code>SyncProvider</code> objects).
49  * This registry may be queried to determine which
50  * synchronization providers are available.
51  * The following line of code gets an enumeration of the providers currently registered.
52  * <PRE>
53  * java.util.Enumeration e = SyncFactory.getRegisteredProviders();
54  * </PRE>
55  * All standard <code>RowSet</code> implementations must provide at least two providers:
56  * <UL>
57  * <LI>an optimistic provider for use with a <code>CachedRowSet</code> implementation
58  * or an implementation derived from it
59  * <LI>an XML provider, which is used for reading and writing XML, such as with
60  * <code>WebRowSet</code> objects
61  * </UL>
62  * Note that the JDBC RowSet Implementations include the <code>SyncProvider</code>
63  * implemtations <code>RIOptimisticProvider</code> and <code>RIXmlProvider</code>,
64  * which satisfy this requirement.
65  * <P>
66  * The <code>SyncFactory</code> class provides accessor methods to assist
67  * applications in determining which synchronization providers are currently
68  * registered with the <code>SyncFactory</code>.
69  * <p>
70  * Other methods let <code>RowSet</code> persistence providers be
71  * registered or de-registered with the factory mechanism. This
72  * allows additional synchronization provider implementations to be made
73  * available to <code>RowSet</code> objects at run time.
74  * <p>
75  * Applications can apply a degree of filtering to determine the level of
76  * synchronization that a <code>SyncProvider</code> implementation offers.
77  * The following criteria determine whether a provider is
78  * made available to a <code>RowSet</code> object:
79  * <ol>
80  * <li>If a particular provider is specified by a <code>RowSet</code> object, and
81  * the <code>SyncFactory</code> does not contain a reference to this provider,
82  * a <code>SyncFactoryException</code> is thrown stating that the synchronization
83  * provider could not be found.
84  * <p>
85  * <li>If a <code>RowSet</code> implementation is instantiated with a specified
86  * provider and the specified provider has been properly registered, the
87  * requested provider is supplied. Otherwise a <code>SyncFactoryException</code>
88  * is thrown.
89  * <p>
90  * <li>If a <code>RowSet</code> object does not specify a
91  * <code>SyncProvider</code> implementation and no additional
92  * <code>SyncProvider</code> implementations are available, the reference
93  * implementation providers are supplied.
94  * </ol>
95  * <h3>2.0 Registering <code>SyncProvider</code> Implementations</h3>
96  * <p>
97  * Both vendors and developers can register <code>SyncProvider</code>
98  * implementations using one of the following mechanisms.
99  * <ul>
100  * <LI><B>Using the command line</B><BR>
101  * The name of the provider is supplied on the command line, which will add
102  * the provider to the system properties.
103  * For example:
104  * <PRE>
105  * -Drowset.provider.classname=com.fred.providers.HighAvailabilityProvider
106  * </PRE>
107  * <li><b>Using the Standard Properties File</b><BR>
108  * The reference implementation is targeted
109  * to ship with J2SE 1.5, which will include an additional resource file
110  * that may be edited by hand. Here is an example of the properties file
111  * included in the reference implementation:
112  * <PRE>
113  * #Default JDBC RowSet sync providers listing
114  * #
115  *
116  * # Optimistic synchronization provider
117  * rowset.provider.classname.0=com.sun.rowset.providers.RIOptimisticProvider
118  * rowset.provider.vendor.0=Sun Microsystems Inc
119  * rowset.provider.version.0=1.0
120  *
121  * # XML Provider using standard XML schema
122  * rowset.provider.classname.1=com.sun.rowset.providers.RIXMLProvider
123  * rowset.provider.vendor.1=Sun Microsystems Inc.
124  * rowset.provider.version.1=1.0
125  * </PRE>
126  * The <code>SyncFactory</code> checks this file and registers the
127  * <code>SyncProvider</code> implementations that it contains. A
128  * developer or vendor can add other implementations to this file.
129  * For example, here is a possible addition:
130  * <PRE>
131  * rowset.provider.classname.2=com.fred.providers.HighAvailabilityProvider
132  * rowset.provider.vendor.2=Fred, Inc.
133  * rowset.provider.version.2=1.0
134  * </PRE>
135  * <p>
136  * <li><b>Using a JNDI Context</b><BR>
137  * Available providers can be registered on a JNDI
138  * context, and the <code>SyncFactory</code> will attempt to load
139  * <code>SyncProvider</code> implementations from that JNDI context.
140  * For example, the following code fragment registers a provider implementation
141  * on a JNDI context. This is something a deployer would normally do. In this
142  * example, <code>MyProvider</code> is being registered on a CosNaming
143  * namespace, which is the namespace used by J2EE resources.
144  * <PRE>
145  * import javax.naming.*;
146  *
147  * Hashtable svrEnv = new Hashtable();
148  * srvEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
149  *
150  * Context ctx = new InitialContext(svrEnv);
151  * com.fred.providers.MyProvider = new MyProvider();
152  * ctx.rebind("providers/MyProvider", syncProvider);
153  * </PRE>
154  * </ul>
155  * Next, an application will register the JNDI context with the
156  * <code>SyncFactory</code> instance. This allows the <code>SyncFactory</code>
157  * to browse within the JNDI context looking for <code>SyncProvider</code>
158  * implementations.
159  * <PRE>
160  * Hashtable appEnv = new Hashtable();
161  * appEnv.put(Context.INITIAL_CONTEXT_FACTORY, "CosNaming");
162  * appEnv.put(Context.PROVIDER_URL, "iiop://hostname/providers");
163  * Context ctx = new InitialContext(appEnv);
164  *
165  * SyncFactory.registerJNDIContext(ctx);
166  * </PRE>
167  * If a <code>RowSet</code> object attempts to obtain a <code>MyProvider</code>
168  * object, the <code>SyncFactory</code> will try to locate it. First it searches
169  * for it in the system properties, then it looks in the resource files, and
170  * finally it checks the JNDI context that has been set. The <code>SyncFactory</code>
171  * instance verifies that the requested provider is a valid extension of the
172  * <code>SyncProvider</code> abstract class and then gives it to the
173  * <code>RowSet</code> object. In the following code fragment, a new
174  * <code>CachedRowSet</code> object is created and initialized with
175  * <i>env</i>, which contains the binding to <code>MyProvider</code>.
176  * <PRE>
177  * Hashtable env = new Hashtable();
178  * env.put(SyncFactory.ROWSET_SYNC_PROVIDER, "com.fred.providers.MyProvider");
179  * CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env);
180  * </PRE>
181  * Further details on these mechanisms are available in the
182  * <code>javax.sql.rowset.spi</code> package specification.
183  *
184  * @author Jonathan Bruce
185  * @see javax.sql.rowset.spi.SyncProvider
186  * @see javax.sql.rowset.spi.SyncFactoryException
187  */

188 public class SyncFactory {
189     
190     /*
191      * The variable that represents the singleton instance
192      * of the <code>SyncFactory</code> class.
193      */

194     private static SyncFactory JavaDoc syncFactory = null;
195  
196     /**
197      * Creates a new <code>SyncFactory</code> object, which is the singleton
198      * instance.
199      * Having a private constructor guarantees that no more than
200      * one <code>SyncProvider</code> object can exist at a time.
201      */

202     private SyncFactory() {};
203     
204     /**
205      * The standard property-id for a synchronization provider implementation
206      * name.
207      */

208     public static String JavaDoc ROWSET_SYNC_PROVIDER =
209     "rowset.provider.classname";
210
211     /**
212      * The standard property-id for a synchronization provider implementation
213      * vendor name.
214      */

215     public static String JavaDoc ROWSET_SYNC_VENDOR =
216     "rowset.provider.vendor";
217
218     /**
219      * The standard property-id for a synchronization provider implementation
220      * version tag.
221      */

222     public static String JavaDoc ROWSET_SYNC_PROVIDER_VERSION =
223     "rowset.provider.version";
224
225     /**
226      * The standard resource file name.
227      */

228     private static String JavaDoc ROWSET_PROPERTIES = "rowset.properties";
229     
230     /**
231      * The RI Optimistic Provider.
232      */

233     private static String JavaDoc default_provider =
234         "com.sun.rowset.providers.RIOptimisticProvider";
235
236     /**
237      * The initial JNDI context where <code>SyncProvider</code> implementations can
238      * be stored and from which they can be invoked.
239      */

240     private static Context ic;
241
242     /**
243      * The <code>Logger</code> object to be used by the <code>SyncFactory</code>.
244      */

245     private static Logger rsLogger;
246
247     /**
248      *
249      */

250     private static Level rsLevel;
251            
252     /**
253      * The registry of available <code>SyncProvider</code> implementations.
254      * See section 2.0 of the class comment for <code>SyncFactory</code> for an
255      * explanation of how a provider can be added to this registry.
256      */

257     private static Hashtable JavaDoc implementations;
258
259     /**
260      * Internal sync object used to maintain the SPI as a singleton
261      */

262     private static Object JavaDoc logSync = new Object JavaDoc();
263     
264     /**
265      * Internal PrintWriter field for logging facility
266      */

267     private static java.io.PrintWriter JavaDoc logWriter = null;
268
269     /**
270      * Adds the the given synchronization provider to the factory register. Guidelines
271      * are provided in the <code>SyncProvider</code> specification for the
272      * required naming conventions for <code>SyncProvider</code>
273      * implementations.
274      * <p>
275      * Synchronization providers bound to a JNDI context can be
276      * registered by binding a SyncProvider instance to a JNDI namespace.
277      * <ul>
278      * <pre>
279      * SyncProvider p = new MySyncProvider();
280      * InitialContext ic = new InitialContext();
281      * ic.bind ("jdbc/rowset/MySyncProvider", p);
282      * </pre>
283      * </ul>
284      * Furthermore, an initial JNDI context should be set with the
285      * <code>SyncFactory</code> using the <code>setJNDIContext</code> method.
286      * The <code>SyncFactory</code> leverages this context to search for
287      * available <code>SyncProvider</code> objects bound to the JNDI
288      * context and its child nodes.
289      *
290      * @param providerID A <code>String</code> object with the unique ID of the
291      * synchronization provider being registered
292      * @throws SyncFactoryException if an attempt is made to supply an empty
293      * or null provider name
294      * @see #setJNDIContext
295      */

296     public static synchronized void registerProvider(String JavaDoc providerID)
297         throws SyncFactoryException JavaDoc {
298         
299         ProviderImpl impl = new ProviderImpl();
300         impl.setClassname(providerID);
301         initMapIfNecessary();
302         implementations.put(providerID, impl);
303         
304     }
305
306     /**
307      * Returns the <code>SyncFactory</code> singleton.
308      *
309      * @return the <code>SyncFactory</code> instance
310      */

311      public static SyncFactory JavaDoc getSyncFactory(){
312          
313          // This method uses the Singleton Design Pattern
314
// with Double-Checked Locking Pattern for
315
// 1. Creating single instance of the SyncFactory
316
// 2. Make the class thread safe, so that at one time
317
// only one thread enters the synchronized block
318
// to instantiate.
319

320          // if syncFactory object is already there
321
// don't go into synchronized block and return
322
// that object.
323
// else go into synchronized block
324

325          if(syncFactory == null){
326          synchronized(SyncFactory JavaDoc.class) {
327             if(syncFactory == null){
328                 syncFactory = new SyncFactory JavaDoc();
329             } //end if
330
} //end synchronized block
331
} //end if
332
return syncFactory;
333      }
334
335     /**
336      * Removes the designated currently registered synchronization provider from the
337      * Factory SPI register.
338      *
339      * @param providerID The unique-id of the synchronization provider
340      * @throws SyncFactoryException If an attempt is made to
341      * unregister a SyncProvider implementation that was not registered.
342      */

343     public static synchronized void unregisterProvider(String JavaDoc providerID)
344         throws SyncFactoryException JavaDoc {
345         initMapIfNecessary();
346         if (implementations.containsKey(providerID)) {
347             implementations.remove(providerID);
348         }
349     }
350
351     private static String JavaDoc colon = ":";
352     private static String JavaDoc strFileSep = "/";
353     
354     private static synchronized void initMapIfNecessary() throws SyncFactoryException JavaDoc {
355         
356         // Local implementation class names and keys from Properties
357
// file, translate names into Class objects using Class.forName
358
// and store mappings
359
Properties JavaDoc properties = new Properties JavaDoc();
360                                 
361         if (implementations == null) {
362             implementations = new Hashtable JavaDoc();
363                         
364             try {
365                                 
366                 // check if user is supplying his Synchronisation Provider
367
// Implementation if not use Sun's implementation.
368
// properties.load(new FileInputStream(ROWSET_PROPERTIES));
369

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

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

377                 /*
378                  * Dependent on application
379                  */

380                 String JavaDoc strRowsetProperties = System.getProperty("rowset.properties");
381                 if ( strRowsetProperties != null) {
382                     // Load user's implementation of SyncProvider
383
// here. -Drowset.properties=/abc/def/pqr.txt
384
ROWSET_PROPERTIES = strRowsetProperties;
385                     properties.load(new FileInputStream JavaDoc(ROWSET_PROPERTIES));
386                     parseProperties(properties);
387                 }
388                  
389                 /*
390                  * Always available
391                  */

392                 ROWSET_PROPERTIES = "javax" + strFileSep + "sql" +
393                     strFileSep + "rowset" + strFileSep +
394                     "rowset.properties";
395                 // properties.load(
396
// ClassLoader.getSystemResourceAsStream(ROWSET_PROPERTIES));
397

398                 ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
399                 
400                 properties.load(cl.getResourceAsStream(ROWSET_PROPERTIES));
401                 parseProperties(properties);
402
403                 // removed else, has properties should sum together
404

405             } catch (FileNotFoundException JavaDoc e) {
406                 throw new SyncFactoryException JavaDoc("Cannot locate properties file: " + e);
407             } catch (IOException JavaDoc e) {
408                 throw new SyncFactoryException JavaDoc("IOException: " + e);
409             }
410                                       
411             /*
412              * Now deal with -Drowset.provider.classname
413              * load additional properties from -D command line
414              */

415             properties.clear();
416             String JavaDoc providerImpls = System.getProperty(ROWSET_SYNC_PROVIDER);
417
418             if (providerImpls != null) {
419                 int i = 0;
420                 if (providerImpls.indexOf(colon) > 0) {
421                     StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(providerImpls, colon);
422                     while (tokenizer.hasMoreElements()) {
423                         properties.put(ROWSET_SYNC_PROVIDER + "." + i, tokenizer.nextToken());
424                         i++;
425                     }
426                 } else {
427                     properties.put(ROWSET_SYNC_PROVIDER, providerImpls);
428                 }
429                 parseProperties(properties);
430             }
431         }
432     }
433     
434     /**
435      * The internal boolean switch that indicates whether a JNDI
436      * context has been established or not.
437      */

438     private static boolean jndiCtxEstablished = false;
439     
440     /**
441      * The internal debug switch.
442      */

443     private static boolean debug = false;
444     
445     /**
446      * Internal registry count for the number of providers contained in the
447      * registry.
448      */

449     private static int providerImplIndex = 0;
450
451     /**
452      * Internal handler for all standard property parsing. Parses standard
453      * ROWSET properties and stores lazy references into the the internal registry.
454      */

455     private static void parseProperties(Properties JavaDoc p) {
456
457         ProviderImpl impl = null;
458         String JavaDoc key = null;
459         String JavaDoc[] propertyNames = null;
460         
461         for (Enumeration JavaDoc e = p.propertyNames(); e.hasMoreElements() ;) {
462
463             String JavaDoc str = (String JavaDoc)e.nextElement();
464                                
465             int w = str.length();
466
467             if (str.startsWith(SyncFactory.ROWSET_SYNC_PROVIDER)) {
468                 
469                 impl = new ProviderImpl();
470                 impl.setIndex(providerImplIndex++);
471
472                 if (w == (SyncFactory.ROWSET_SYNC_PROVIDER).length()) {
473                     // no property index has been set.
474
propertyNames = getPropertyNames(false);
475                 } else {
476                     // property index has been set.
477
propertyNames = getPropertyNames(true, str.substring(w-1));
478                 }
479
480                 key = p.getProperty(propertyNames[0]);
481                 impl.setClassname(key);
482                 impl.setVendor(p.getProperty(propertyNames[1]));
483                 impl.setVersion(p.getProperty(propertyNames[2]));
484                 implementations.put(key, impl);
485             }
486         }
487     }
488
489     /**
490      * Used by the parseProperties methods to disassemble each property tuple.
491      */

492     private static String JavaDoc[] getPropertyNames(boolean append) {
493         return getPropertyNames(append, null);
494     }
495     
496     /**
497      * Disassembles each property and its associated value. Also handles
498      * overloaded property names that contain indexes.
499      */

500     private static String JavaDoc[] getPropertyNames(boolean append,
501                                              String JavaDoc propertyIndex) {
502         String JavaDoc dot = ".";
503         String JavaDoc[] propertyNames =
504             new String JavaDoc[] {SyncFactory.ROWSET_SYNC_PROVIDER,
505                               SyncFactory.ROWSET_SYNC_VENDOR,
506                               SyncFactory.ROWSET_SYNC_PROVIDER_VERSION};
507         if (append) {
508             for (int i = 0; i < propertyNames.length; i++) {
509                 propertyNames[i] = propertyNames[i] +
510                     dot +
511                     propertyIndex;
512             }
513             return propertyNames;
514         } else {
515             return propertyNames;
516         }
517     }
518
519     /**
520      * Internal debug method that outputs the registry contents.
521      */

522     private static void showImpl(ProviderImpl impl) {
523         System.out.println("Provider implementation:");
524         System.out.println("Classname: " + impl.getClassname());
525         System.out.println("Vendor: " + impl.getVendor());
526         System.out.println("Version: " + impl.getVersion());
527         System.out.println("Impl index: " + impl.getIndex());
528     }
529
530     /**
531      * Returns the <code>SyncProvider</code> instance identified by <i>providerID</i>.
532      *
533      * @param providerID the unique identifier of the provider
534      * @return a <code>SyncProvider</code> implementation
535      * @throws SyncFactoryException If the SyncProvider cannot be found or
536      * some error was encountered when trying to invoke this provider.
537      */

538     public static SyncProvider JavaDoc getInstance(String JavaDoc providerID)
539     throws SyncFactoryException JavaDoc {
540         initMapIfNecessary(); // populate HashTable
541
initJNDIContext(); // check JNDI context for any additional bindings
542

543         ProviderImpl impl = (ProviderImpl)implementations.get(providerID);
544         
545         if (impl == null) {
546             // Requested SyncProvider is unavailable. Return default provider.
547
return new com.sun.rowset.providers.RIOptimisticProvider();
548         }
549         
550         // Attempt to invoke classname from registered SyncProvider list
551
Class JavaDoc c = null;
552         try {
553             ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
554             
555             /**
556              * The SyncProvider implementation of the user will be in
557              * the classpath. We need to find the ClassLoader which loads
558              * this SyncFactory and try to laod the SyncProvider class from
559              * there.
560              **/

561         
562         c = Class.forName(providerID, true, cl);
563             
564             if (c != null) {
565                 return (SyncProvider JavaDoc)c.newInstance();
566             } else {
567                 return new com.sun.rowset.providers.RIOptimisticProvider();
568             }
569             
570         } catch (IllegalAccessException JavaDoc e) {
571             throw new SyncFactoryException JavaDoc("IllegalAccessException: " + e.getMessage());
572         } catch (InstantiationException JavaDoc e) {
573             throw new SyncFactoryException JavaDoc("InstantiationException: " + e.getMessage());
574         } catch (ClassNotFoundException JavaDoc e) {
575             throw new SyncFactoryException JavaDoc("ClassNotFoundException: " + e.getMessage());
576         }
577     }
578     /**
579      * Returns an Enumeration of currently registered synchronization
580      * providers. A <code>RowSet</code> implementation may use any provider in
581      * the enumeration as its <code>SyncProvider</code> object.
582      * <p>
583      * At a minimum, the reference synchronization provider allowing
584      * RowSet content data to be stored using a JDBC driver should be
585      * possible.
586      *
587      * @return Enumeration A enumeration of available synchronization
588      * providers that are registered with this Factory
589      */

590     public static Enumeration JavaDoc<SyncProvider JavaDoc> getRegisteredProviders()
591         throws SyncFactoryException JavaDoc {
592         initMapIfNecessary();
593         // return a collection of classnames
594
// of type SyncProvider
595
return implementations.elements();
596     }
597         
598     /**
599      * Sets the logging object to be used by the <code>SyncProvider</code>
600      * implementation provided by the <code>SyncFactory</code>. All
601      * <code>SyncProvider</code> implementations can log their events to
602      * this object and the application can retrieve a handle to this
603      * object using the <code>getLogger</code> method.
604      *
605      * @param logger A Logger object instance
606      */

607     public static void setLogger(Logger logger) {
608         rsLogger = logger;
609     }
610
611     /**
612      * Sets the logging object that is used by <code>SyncProvider</code>
613      * implementations provided by the <code>SyncFactory</code> SPI. All
614      * <code>SyncProvider</code> implementations can log their events
615      * to this object and the application can retrieve a handle to this
616      * object using the <code>getLogger</code> method.
617      *
618      * @param logger a Logger object instance
619      * @param level a Level object instance indicating the degree of logging
620      * required
621      */

622     public static void setLogger(Logger logger, Level level) {
623     // singleton
624

625     rsLogger = logger;
626     rsLogger.setLevel(level);
627     }
628
629     /**
630      * Returns the logging object for applications to retrieve
631      * synchronization events posted by SyncProvider implementations.
632      *
633      * @throws SyncFactoryException if no logging object has been set.
634      */

635     public static Logger getLogger() throws SyncFactoryException JavaDoc {
636     // only one logger per session
637
if(rsLogger == null){
638        throw new SyncFactoryException JavaDoc("(SyncFactory) : No logger has been set");
639     }
640     return rsLogger;
641     }
642
643    /**
644     * Sets the initial JNDI context from which SyncProvider implementations
645     * can be retrieved from a JNDI namespace
646     *
647     * @param ctx a valid JNDI context
648     * @throws SyncFactoryException if the supplied JNDI context is null
649     */

650     public static void setJNDIContext(javax.naming.Context JavaDoc ctx)
651     throws SyncFactoryException JavaDoc {
652     if (ctx == null) {
653         throw new SyncFactoryException JavaDoc("Invalid JNDI context supplied");
654     }
655     ic = ctx;
656         jndiCtxEstablished = true;
657    }
658     
659     /**
660      * Controls JNDI context intialization.
661      *
662      * @throws SyncFactoryException if an error occurs parsing the JNDI context
663      */

664     private static void initJNDIContext() throws SyncFactoryException JavaDoc {
665                         
666         if (jndiCtxEstablished && (ic != null) && (lazyJNDICtxRefresh == false)) {
667             try {
668                 parseProperties(parseJNDIContext());
669                 lazyJNDICtxRefresh = true; // touch JNDI namespace once.
670
} catch (NamingException e) {
671         e.printStackTrace();
672                 throw new SyncFactoryException JavaDoc("SPI: NamingException: " + e.getExplanation());
673             } catch (Exception JavaDoc e) {
674         e.printStackTrace();
675     throw new SyncFactoryException JavaDoc("SPI: Exception: " + e.getMessage());
676         }
677         }
678     }
679     /**
680      * Internal switch indicating whether the JNDI namespace should be re-read.
681      */

682     private static boolean lazyJNDICtxRefresh = false;
683         
684     /**
685      * Parses the set JNDI Context and passes bindings to the enumerateBindings
686      * method when complete.
687      */

688     private static Properties JavaDoc parseJNDIContext() throws NamingException {
689                 
690         NamingEnumeration bindings = ic.listBindings("");
691         Properties JavaDoc properties = new Properties JavaDoc();
692         
693         // Hunt one level below context for available SyncProvider objects
694
enumerateBindings(bindings, properties);
695
696         return properties;
697     }
698
699     /**
700      * Scans each binding on JNDI context and determines if any binding is an
701      * instance of SyncProvider, if so, add this to the registry and continue to
702      * scan the current context using a re-entrant call to this method until all
703      * bindings have been enumerated.
704      */

705     private static void enumerateBindings(NamingEnumeration bindings,
706     Properties JavaDoc properties) throws NamingException {
707
708     boolean syncProviderObj = false; // move to parameters ?
709

710     try {
711         Binding bd = null;
712         Object JavaDoc elementObj = null;
713         String JavaDoc element = null;
714         while (bindings.hasMore()) {
715             bd = (Binding)bindings.next();
716             element = bd.getName();
717             elementObj = bd.getObject();
718
719             if (!(ic.lookup(element) instanceof Context)) {
720              // skip directories/sub-contexts
721
if (ic.lookup(element) instanceof SyncProvider JavaDoc) {
722             syncProviderObj = true;
723              }
724         }
725
726         if (syncProviderObj) {
727             SyncProvider JavaDoc sync = (SyncProvider JavaDoc)elementObj;
728             properties.put(SyncFactory.ROWSET_SYNC_PROVIDER,
729             sync.getProviderID());
730             syncProviderObj = false; // reset
731
}
732
733             }
734     } catch (javax.naming.NotContextException JavaDoc e) {
735         bindings.next();
736         // Re-entrant call into method
737
enumerateBindings(bindings, properties);
738     }
739     }
740 }
741
742    /**
743      * Internal class that defines the lazy reference construct for each registered
744      * SyncProvider implementation.
745      */

746    class ProviderImpl extends SyncProvider JavaDoc {
747         private String JavaDoc className = null;
748         private String JavaDoc vendorName = null;
749         private String JavaDoc ver = null;
750         private int index;
751
752         public void setClassname(String JavaDoc classname) {
753             className = classname;
754         }
755
756         public String JavaDoc getClassname() {
757             return className;
758         }
759
760         public void setVendor(String JavaDoc vendor) {
761             vendorName = vendor;
762         }
763
764         public String JavaDoc getVendor() {
765             return vendorName;
766         }
767
768         public void setVersion(String JavaDoc providerVer) {
769             ver = providerVer;
770         }
771             
772         public String JavaDoc getVersion() {
773             return ver;
774         }
775
776         public void setIndex(int i) {
777             index = i;
778         }
779             
780         public int getIndex() {
781             return index;
782         }
783         
784         public int getDataSourceLock() throws SyncProviderException JavaDoc {
785         
786            int dsLock = 0;
787             try
788             {
789                dsLock = SyncFactory.getInstance(className).getDataSourceLock();
790             } catch(SyncFactoryException JavaDoc sfEx) {
791             
792                  throw new SyncProviderException JavaDoc(sfEx.getMessage());
793              }
794              
795             return dsLock;
796         }
797         
798         public int getProviderGrade() {
799         
800            int grade = 0;
801            
802            try
803            {
804               grade = SyncFactory.getInstance(className).getProviderGrade();
805            } catch(SyncFactoryException JavaDoc sfEx) {
806                //
807
}
808            
809            return grade;
810         }
811         
812         public String JavaDoc getProviderID() {
813             return className;
814         }
815         
816         /*
817         public javax.sql.RowSetInternal getRowSetInternal() {
818           try
819            {
820               return SyncFactory.getInstance(className).getRowSetInternal();
821            } catch(SyncFactoryException sfEx) {
822                //
823            }
824         }
825         */

826         
827         public javax.sql.RowSetReader JavaDoc getRowSetReader() {
828         
829         RowSetReader rsReader = null;;
830         
831         try
832         {
833            rsReader = SyncFactory.getInstance(className).getRowSetReader();
834          } catch(SyncFactoryException JavaDoc sfEx) {
835                //
836
}
837          
838          return rsReader;
839          
840         }
841         
842         public javax.sql.RowSetWriter JavaDoc getRowSetWriter() {
843         
844         RowSetWriter rsWriter = null;
845         try
846            {
847             rsWriter = SyncFactory.getInstance(className).getRowSetWriter();
848            } catch(SyncFactoryException JavaDoc sfEx) {
849                //
850
}
851            
852            return rsWriter;
853         }
854         public void setDataSourceLock(int param)
855         throws SyncProviderException JavaDoc {
856          
857          try
858            {
859               SyncFactory.getInstance(className).setDataSourceLock(param);
860            } catch(SyncFactoryException JavaDoc sfEx) {
861                
862                throw new SyncProviderException JavaDoc(sfEx.getMessage());
863            }
864         }
865         
866         public int supportsUpdatableView() {
867         
868         int view = 0;
869         
870         try
871          {
872            view = SyncFactory.getInstance(className).supportsUpdatableView();
873          } catch(SyncFactoryException JavaDoc sfEx) {
874                //
875
}
876          
877          return view;
878        }
879         
880     }
881
882
Popular Tags