KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > encoding > TypeMappingRegistryImpl


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.encoding;
18
19 import org.apache.axis.Constants;
20 import org.apache.axis.utils.Messages;
21
22 import java.util.HashMap JavaDoc;
23
24 /**
25  * <p>
26  * The TypeMappingRegistry keeps track of the individual TypeMappings.
27  * </p>
28  * <p>
29  * The TypeMappingRegistry for axis contains a default type mapping
30  * that is set for either SOAP 1.1 or SOAP 1.2
31  * The default type mapping is a singleton used for the entire
32  * runtime and should not have anything new registered in it.
33  * </p>
34  * <p>
35  * Instead the new TypeMappings for the deploy and service are
36  * made in a separate TypeMapping which is identified by
37  * the soap encoding. These new TypeMappings delegate back to
38  * the default type mapping when information is not found.
39  * </p>
40  * <p>
41  * So logically we have:
42  * <pre>
43  * TMR
44  * | |
45  * | +---------------> DefaultTM
46  * | ^
47  * | |
48  * +----> TM --delegate---+
49  * </pre>
50  *
51  * But in the implementation, the TMR references
52  * "delegate" TypeMappings (TM') which then reference the actual TM's
53  * </p>
54  * <p>
55  * So the picture is really:
56  * <pre>
57  * TMR
58  * | |
59  * | +-----------TM'------> DefaultTM
60  * | ^
61  * | |
62  * +-TM'-> TM ----+
63  * </pre>
64  *
65  * This extra indirection is necessary because the user may want to
66  * change the default type mapping. In such cases, the TMR
67  * just needs to adjust the TM' for the DefaultTM, and all of the
68  * other TMs will properly delegate to the new one. Here's the picture:
69  * <pre>
70  * TMR
71  * | |
72  * | +-----------TM'--+ DefaultTM
73  * | ^ |
74  * | | +---> New User Defined Default TM
75  * +-TM'-> TM ----+
76  * </pre>
77  *
78  * The other reason that it is necessary is when a deploy
79  * has a TMR, and then TMR's are defined for the individual services
80  * in such cases the delegate() method is invoked on the service
81  * to delegate to the deploy TMR
82  * <pre>
83  * Deploy TMR
84  * | |
85  * | +-----------TM'------> DefaultTM
86  * | ^
87  * | |
88  * +-TM'-> TM ----+
89  *
90  * Service TMR
91  * | |
92  * | +-----------TM'------> DefaultTM
93  * | ^
94  * | |
95  * +-TM'-> TM ----+
96  *
97  * ServiceTMR.delegate(DeployTMR)
98  *
99  * Deploy TMR
100  * | |
101  * | +------------TM'------> DefaultTM
102  * | ^ ^
103  * | | |
104  * +-TM'-> TM ----+ |
105  * ^ |
106  * +-------+ |
107  * | |
108  * | Service TMR |
109  * | | | |
110  * | | +----------TM'-+
111  * | |
112  * | |
113  * | +-TM'-> TM +
114  * | |
115  * +----------------+
116  * </pre>
117  *
118  * So now the service uses the DefaultTM of the Deploy TMR, and
119  * the Service TM properly delegates to the deploy's TM. And
120  * if either the deploy defaultTM or TMs change, the links are not broken.
121  * </p>
122  *
123  * @author James Snell (jasnell@us.ibm.com)
124  * @author Sam Ruby (rubys@us.ibm.com)
125  * Re-written for JAX-RPC Compliance by
126  * @author Rich Scheuerle (scheu@us.ibm.com
127  */

128 public class TypeMappingRegistryImpl implements TypeMappingRegistry {
129     
130     private HashMap JavaDoc mapTM; // Type Mappings keyed with Namespace URI
131
private TypeMappingDelegate defaultDelTM; // Delegate to default Type Mapping
132
private boolean isDelegated = false;
133
134     /**
135      * Construct TypeMappingRegistry
136      * @param tm
137      */

138     public TypeMappingRegistryImpl(TypeMappingImpl tm) {
139         mapTM = new HashMap JavaDoc();
140         defaultDelTM = new TypeMappingDelegate(tm);
141 // TypeMappingDelegate del = new TypeMappingDelegate(new DefaultSOAPEncodingTypeMappingImpl());
142
// register(Constants.URI_SOAP11_ENC, del);
143
}
144
145     /**
146      * Construct TypeMappingRegistry
147      */

148     public TypeMappingRegistryImpl() {
149         this(true);
150     }
151
152     public TypeMappingRegistryImpl(boolean registerDefaults) {
153         mapTM = new HashMap JavaDoc();
154         if (registerDefaults) {
155             defaultDelTM = DefaultTypeMappingImpl.getSingletonDelegate();
156             TypeMappingDelegate del = new TypeMappingDelegate(new DefaultSOAPEncodingTypeMappingImpl());
157             register(Constants.URI_SOAP11_ENC, del);
158         } else {
159             defaultDelTM = new TypeMappingDelegate(TypeMappingDelegate.placeholder);
160         }
161     }
162
163     /**
164      * delegate
165      *
166      * Changes the contained type mappings to delegate to
167      * their corresponding types in the secondary TMR.
168      */

169     public void delegate(TypeMappingRegistry secondaryTMR) {
170
171         if (isDelegated || secondaryTMR == null || secondaryTMR == this) {
172             return;
173         }
174
175         isDelegated = true;
176         String JavaDoc[] keys = secondaryTMR.getRegisteredEncodingStyleURIs();
177         TypeMappingDelegate otherDefault =
178                 ((TypeMappingRegistryImpl)secondaryTMR).defaultDelTM;
179         if (keys != null) {
180             for (int i=0; i < keys.length; i++) {
181                 try {
182                     String JavaDoc nsURI = keys[i];
183                     TypeMappingDelegate tm = (TypeMappingDelegate) mapTM.get(nsURI);
184                     if (tm == null) {
185                         tm = (TypeMappingDelegate)createTypeMapping();
186                         tm.setSupportedEncodings(new String JavaDoc[] { nsURI });
187                         register(nsURI, tm);
188                     }
189
190                     if (tm != null) {
191                         // Get the secondaryTMR's TM'
192
TypeMappingDelegate del = (TypeMappingDelegate)
193                             ((TypeMappingRegistryImpl)secondaryTMR).mapTM.get(nsURI);
194
195                         while (del.next != null) {
196                             TypeMappingDelegate nu = new TypeMappingDelegate(del.delegate);
197                             tm.setNext(nu);
198
199                             if (del.next == otherDefault) {
200                                 nu.setNext(defaultDelTM);
201                                 break;
202                             }
203                             del = del.next;
204                             tm = nu;
205                         }
206                     }
207
208                 } catch (Exception JavaDoc e) {
209                 }
210             }
211         }
212         // Change our defaultDelTM to delegate to the one in
213
// the secondaryTMR
214
if (defaultDelTM.delegate != TypeMappingDelegate.placeholder) {
215             defaultDelTM.setNext(otherDefault);
216         } else {
217             defaultDelTM.delegate = otherDefault.delegate;
218         }
219         
220     }
221             
222
223
224     /********* JAX-RPC Compliant Method Definitions *****************/
225     
226     /**
227      * The method register adds a TypeMapping instance for a specific
228      * namespace
229      *
230      * @param namespaceURI
231      * @param mapping - TypeMapping for specific namespaces
232      *
233      * @return Previous TypeMapping associated with the specified namespaceURI,
234      * or null if there was no TypeMapping associated with the specified namespaceURI
235      *
236      */

237     public javax.xml.rpc.encoding.TypeMapping JavaDoc register(String JavaDoc namespaceURI,
238                          javax.xml.rpc.encoding.TypeMapping JavaDoc mapping) {
239 // namespaceURI = "";
240
if (mapping == null ||
241             !(mapping instanceof TypeMappingDelegate)) {
242             throw new IllegalArgumentException JavaDoc(
243                     Messages.getMessage("badTypeMapping"));
244         }
245         if (namespaceURI == null) {
246             throw new java.lang.IllegalArgumentException JavaDoc(
247                     Messages.getMessage("nullNamespaceURI"));
248         }
249
250         TypeMappingDelegate del = (TypeMappingDelegate)mapping;
251         TypeMappingDelegate old = (TypeMappingDelegate)mapTM.get(namespaceURI);
252         if (old == null) {
253             del.setNext(defaultDelTM);
254         } else {
255             del.setNext(old);
256         }
257         mapTM.put(namespaceURI, del);
258         return old; // Needs works
259
}
260     
261     /**
262      * The method register adds a default TypeMapping instance. If a specific
263      * TypeMapping is not found, the default TypeMapping is used.
264      *
265      * @param mapping - TypeMapping for specific type namespaces
266      *
267      * java.lang.IllegalArgumentException -
268      * if an invalid type mapping is specified or the delegate is already set
269      */

270     public void registerDefault(javax.xml.rpc.encoding.TypeMapping JavaDoc mapping) {
271         if (mapping == null ||
272             !(mapping instanceof TypeMappingDelegate)) {
273             throw new IllegalArgumentException JavaDoc(
274                     Messages.getMessage("badTypeMapping"));
275         }
276
277         /* Don't allow this call after the delegate() method since
278          * the TMR's TypeMappings will be using the default type mapping
279          * of the secondary TMR.
280          */

281         if (defaultDelTM.getNext() != null) {
282             throw new IllegalArgumentException JavaDoc(
283                     Messages.getMessage("defaultTypeMappingSet"));
284         }
285
286         defaultDelTM = (TypeMappingDelegate)mapping;
287     }
288
289     /**
290      * Set up the default type mapping (and the SOAP encoding type mappings)
291      * as per the passed "version" option.
292      *
293      * @param version
294      */

295     public void doRegisterFromVersion(String JavaDoc version) {
296         if (version == null || version.equals("1.0") || version.equals("1.2")) {
297             TypeMappingImpl.dotnet_soapenc_bugfix = false;
298             // Do nothing, just register SOAPENC mapping
299
} else if (version.equals("1.1")) {
300             TypeMappingImpl.dotnet_soapenc_bugfix = true;
301             // Do nothing, no SOAPENC mapping
302
return;
303         } else if (version.equals("1.3")) {
304             // Reset the default TM to the JAXRPC version, then register SOAPENC
305
defaultDelTM = new TypeMappingDelegate(
306                     DefaultJAXRPC11TypeMappingImpl.getSingleton());
307         } else {
308             throw new RuntimeException JavaDoc(
309                     Messages.getMessage("j2wBadTypeMapping00"));
310         }
311         registerSOAPENCDefault(
312                 new TypeMappingDelegate(DefaultSOAPEncodingTypeMappingImpl.
313                                         getSingleton()));
314     }
315     /**
316      * Force registration of the given mapping as the SOAPENC default mapping
317      * @param mapping
318      */

319     private void registerSOAPENCDefault(TypeMappingDelegate mapping) {
320         // This get a bit ugly as we do not want to just overwrite
321
// an existing type mapping for SOAP encodings. This happens
322
// when {client,server}-config.wsdd defines a type mapping for
323
// instance.
324
if (!mapTM.containsKey(Constants.URI_SOAP11_ENC)) {
325             mapTM.put(Constants.URI_SOAP11_ENC, mapping);
326         } else {
327             // We have to make sure the default type mapping is
328
// at the end of the chain.
329
// This is important if the default is switched to
330
// the JAX_RPC 1.1 default type mapping!
331
TypeMappingDelegate del =
332                     (TypeMappingDelegate) mapTM.get(Constants.URI_SOAP11_ENC);
333             while (del.getNext() != null && ! (del.delegate instanceof DefaultTypeMappingImpl)) {
334                 del = del.getNext();
335             }
336             del.setNext(defaultDelTM);
337         }
338
339         if (!mapTM.containsKey(Constants.URI_SOAP12_ENC)) {
340             mapTM.put(Constants.URI_SOAP12_ENC, mapping);
341         } else {
342             // We have to make sure the default type mapping is
343
// at the end of the chain.
344
// This is important if the default is switched to
345
// the JAX_RPC 1.1 default type mapping!
346
TypeMappingDelegate del =
347                     (TypeMappingDelegate) mapTM.get(Constants.URI_SOAP12_ENC);
348             while (del.getNext() != null && ! (del.delegate instanceof DefaultTypeMappingImpl)) {
349                 del = del.getNext();
350             }
351             del.setNext(defaultDelTM);
352         }
353         
354         // Just do this unconditionally in case we used mapping.
355
// This is important if the default is switched to
356
// the JAX_RPC 1.1 default type mapping!
357
mapping.setNext(defaultDelTM);
358     }
359
360     /**
361      * Gets the TypeMapping for the namespace. If not found, the default
362      * TypeMapping is returned.
363      *
364      * @param namespaceURI - The namespace URI of a Web Service
365      * @return The registered TypeMapping
366      * (which may be the default TypeMapping) or null.
367      */

368     public javax.xml.rpc.encoding.TypeMapping JavaDoc
369         getTypeMapping(String JavaDoc namespaceURI) {
370 // namespaceURI = "";
371
TypeMapping del = (TypeMappingDelegate) mapTM.get(namespaceURI);
372         if (del == null) {
373             del = (TypeMapping)getDefaultTypeMapping();
374         }
375         return del;
376     }
377
378     /**
379      * Obtain a type mapping for the given encodingStyle. If no specific
380      * mapping exists for this encodingStyle, we will create and register
381      * one before returning it.
382      *
383      * @param encodingStyle
384      * @return a registered TypeMapping for the given encodingStyle
385      */

386     public TypeMapping getOrMakeTypeMapping(String JavaDoc encodingStyle) {
387         TypeMappingDelegate del = (TypeMappingDelegate) mapTM.get(encodingStyle);
388         if (del == null || del.delegate instanceof DefaultTypeMappingImpl) {
389             del = (TypeMappingDelegate)createTypeMapping();
390             del.setSupportedEncodings(new String JavaDoc[] {encodingStyle});
391             register(encodingStyle, del);
392         }
393         return del;
394     }
395
396     /**
397      * Unregisters the TypeMapping for the namespace.
398      *
399      * @param namespaceURI - The namespace URI
400      * @return The registered TypeMapping .
401      */

402     public javax.xml.rpc.encoding.TypeMapping JavaDoc
403         unregisterTypeMapping(String JavaDoc namespaceURI) {
404         return (TypeMappingDelegate)mapTM.remove(namespaceURI);
405     }
406
407     /**
408      * Removes the TypeMapping for the namespace.
409      *
410      * @param mapping The type mapping to remove
411      * @return true if found and removed
412      */

413     public boolean removeTypeMapping(
414                                   javax.xml.rpc.encoding.TypeMapping JavaDoc mapping) {
415         String JavaDoc[] ns = getRegisteredEncodingStyleURIs();
416         boolean rc = false;
417         for (int i=0; i < ns.length; i++) {
418             if (getTypeMapping(ns[i]) == mapping) {
419                 rc = true;
420                 unregisterTypeMapping(ns[i]);
421             }
422         }
423         return rc;
424     }
425
426     /**
427      * Creates a new empty TypeMapping object for the specified
428      * encoding style or XML schema namespace.
429      *
430      * @return An empty generic TypeMapping object
431      */

432     public javax.xml.rpc.encoding.TypeMapping JavaDoc createTypeMapping() {
433         TypeMappingImpl impl = new TypeMappingImpl();
434         TypeMappingDelegate del = new TypeMappingDelegate(impl);
435         del.setNext(defaultDelTM);
436         return del;
437     }
438         
439
440     /**
441      * Gets a list of namespace URIs registered with this TypeMappingRegistry.
442      *
443      * @return String[] containing names of all registered namespace URIs
444      */

445     public String JavaDoc[] getRegisteredEncodingStyleURIs() {
446         java.util.Set JavaDoc s = mapTM.keySet();
447         if (s != null) {
448             String JavaDoc[] rc = new String JavaDoc[s.size()];
449             int i = 0;
450             java.util.Iterator JavaDoc it = s.iterator();
451             while(it.hasNext()) {
452                 rc[i++] = (String JavaDoc) it.next();
453             }
454             return rc;
455         }
456         return null;
457     }
458
459
460     /**
461      * Removes all TypeMappings and namespaceURIs from this TypeMappingRegistry.
462      */

463     public void clear() {
464         mapTM.clear();
465     }
466
467     /**
468      * Return the default TypeMapping
469      * @return TypeMapping or null
470      **/

471     public javax.xml.rpc.encoding.TypeMapping JavaDoc getDefaultTypeMapping() {
472         return defaultDelTM;
473     }
474
475 }
476
Popular Tags