KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > runtime > BindingDirectory


1 /*
2 Copyright (c) 2002-2005, Sosnoski Software Solutions, Inc.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.runtime;
30
31 import java.lang.reflect.Field JavaDoc;
32 import java.lang.reflect.InvocationTargetException JavaDoc;
33 import java.lang.reflect.Method JavaDoc;
34
35 /**
36  * Abstract class with static method to find the binding factory corresponding
37  * to a binding name.
38  *
39  * @author Dennis M. Sosnoski
40  * @version 1.0
41  */

42
43 public abstract class BindingDirectory
44 {
45     /** Name of <code>String[]</code> field giving binding factory name list. */
46     public static final String JavaDoc BINDINGLIST_NAME = "JiBX_bindingList";
47     
48     /** Prefix of binding factory name. */
49     public static final String JavaDoc BINDINGFACTORY_PREFIX = "JiBX_";
50     
51     /** Suffix of binding factory name. */
52     public static final String JavaDoc BINDINGFACTORY_SUFFIX = "Factory";
53     
54     /** Binding factory method to get instance of factory. */
55     public static final String JavaDoc FACTORY_INSTMETHOD = "getInstance";
56     
57     /** Empty argument list. */
58     public static final Class JavaDoc[] EMPTY_ARGS = new Class JavaDoc[0];
59  
60     /**
61      * Get list of bindings for class. This just accesses the static variable
62      * added to each class with a top-level mapping.
63      *
64      * @param clas class with top-level mapping in binding
65      * @return list of bindings defined for that class (as a text string)
66      * @throws JiBXException on error accessing binding information
67      */

68     private static String JavaDoc getBindingList(Class JavaDoc clas)throws JiBXException {
69         try {
70             Field JavaDoc field = clas.getDeclaredField(BINDINGLIST_NAME);
71             try {
72                 // should be able to access field anyway, but just in case
73
field.setAccessible(true);
74             } catch (Exception JavaDoc e) { /* deliberately left empty */ }
75             return (String JavaDoc)field.get(null);
76         } catch (NoSuchFieldException JavaDoc e) {
77             throw new JiBXException
78                 ("Unable to access binding information for class " +
79                 clas.getName() +
80                 "\nMake sure the binding has been compiled", e);
81         } catch (IllegalAccessException JavaDoc e) {
82             throw new JiBXException
83                 ("Error in added code for class " + clas.getName() +
84                 "Please report this to the JiBX developers", e);
85         }
86     }
87  
88     /**
89      * Get instance of factory. Loads the factory class using the classloader
90      * for the supplied class, then calls the get instance method of the
91      * factory class.
92      *
93      * @param name fully qualified name of factory class
94      * @param clas class with class loader to be used for loading factory
95      * @return binding factory instance
96      * @throws JiBXException on error loading or accessing factory
97      */

98     private static IBindingFactory getFactoryFromName(String JavaDoc name, Class JavaDoc clas)
99         throws JiBXException {
100         Throwable JavaDoc ex = null;
101         Object JavaDoc result = null;
102         IBindingFactory ifact = null;
103         try {
104             Class JavaDoc factory = clas.getClassLoader().loadClass(name);
105             Method JavaDoc method = factory.getMethod(FACTORY_INSTMETHOD, EMPTY_ARGS);
106             result = method.invoke(null, null);
107         } catch (SecurityException JavaDoc e) {
108             ex = e;
109         } catch (ClassNotFoundException JavaDoc e) {
110             ex = e;
111         } catch (NoSuchMethodException JavaDoc e) {
112             ex = e;
113         } catch (IllegalAccessException JavaDoc e) {
114             ex = e;
115         } catch (InvocationTargetException JavaDoc e) {
116             ex = e;
117         } finally {
118             if (ex == null) {
119                 if (result instanceof IBindingFactory) {
120                     ifact = (IBindingFactory)result;
121                     int diff = ifact.getCompilerVersion() ^
122                         IBindingFactory.CURRENT_VERSION_NUMBER;
123                     if ((diff & IBindingFactory.COMPATIBLE_VERSION_MASK) != 0) {
124                         throw new JiBXException
125                             ("Binding information for class " + clas.getName() +
126                             " must be recompiled with current binding " +
127                             "compiler (compiled with " +
128                             ifact.getCompilerDistribution() + ", runtime is " +
129                             IBindingFactory.CURRENT_VERSION_NAME + ")");
130                     }
131                 } else {
132                     throw new JiBXException
133                         ("Binding information for class " + clas.getName() +
134                         " must be regenerated with current binding " +
135                         "compiler");
136                 }
137             } else {
138                 throw new JiBXException
139                     ("Unable to access binding information for class " +
140                     clas.getName() + "\nMake sure classes generated by the " +
141                     "binding compiler are available at runtime", ex);
142             }
143         }
144         return ifact;
145     }
146  
147     /**
148      * Get instance of binding factory. Finds the binding factory for the
149      * named binding on the target class, then loads that factory and returns
150      * an instance.
151      *
152      * @param name binding name
153      * @param clas target class for binding
154      * @return binding factory instance
155      * @throws JiBXException on any error in finding or accessing factory
156      */

157     public static IBindingFactory getFactory(String JavaDoc name, Class JavaDoc clas)
158         throws JiBXException {
159         String JavaDoc list = getBindingList(clas);
160         String JavaDoc match = BINDINGFACTORY_PREFIX + name +
161             BINDINGFACTORY_SUFFIX + '|';
162         int index = list.indexOf(match);
163         if (index >= 0) {
164             int mark = list.lastIndexOf('|', index);
165             String JavaDoc fname =
166                 list.substring(mark+1, index + match.length() - 1);
167             mark = fname.indexOf('=');
168             if (mark >= 0) {
169                 fname = fname.substring(0, mark);
170             }
171             return getFactoryFromName(fname, clas);
172         } else {
173             throw new JiBXException("Binding " + name +
174                 " not found for class " + clas.getName());
175         }
176     }
177  
178     /**
179      * Get instance of binding factory. Finds the binding factory for the
180      * target class, then loads that factory and returns an instance. This
181      * method can only be used with target classes that are mapped in only
182      * one binding.
183      *
184      * @param clas target class for binding
185      * @return binding factory instance
186      * @throws JiBXException on any error in finding or accessing factory
187      */

188     public static IBindingFactory getFactory(Class JavaDoc clas) throws JiBXException {
189         String JavaDoc list = getBindingList(clas);
190         if (list != null && list.length() > 2) {
191             String JavaDoc fact = list.substring(1, list.length()-1);
192             if (fact.indexOf('|') < 0) {
193                 return getFactoryFromName(fact, clas);
194             }
195         }
196         throw new JiBXException("Multiple bindings defined for class " +
197             clas.getName());
198     }
199 }
Popular Tags