001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: */package org.apache.cxf.aegis.type;
019:
020: import java.math.BigDecimal;
021: import java.math.BigInteger;
022: import java.net.URI;
023: import java.sql.Time;
024: import java.sql.Timestamp;
025: import java.util.Calendar;
026: import java.util.Collections;
027: import java.util.Date;
028: import java.util.HashMap;
029: import java.util.Iterator;
030: import java.util.Map;
031:
032: import javax.activation.DataHandler;
033: import javax.activation.DataSource;
034: import javax.xml.namespace.QName;
035: import javax.xml.stream.XMLStreamReader;
036: import javax.xml.transform.Source;
037:
038: import org.w3c.dom.Document;
039:
040: import org.apache.commons.logging.Log;
041: import org.apache.commons.logging.LogFactory;
042: import org.apache.cxf.aegis.DatabindingException;
043: import org.apache.cxf.aegis.type.basic.Base64Type;
044: import org.apache.cxf.aegis.type.basic.BigDecimalType;
045: import org.apache.cxf.aegis.type.basic.BigIntegerType;
046: import org.apache.cxf.aegis.type.basic.BooleanType;
047: import org.apache.cxf.aegis.type.basic.CalendarType;
048: import org.apache.cxf.aegis.type.basic.CharacterType;
049: import org.apache.cxf.aegis.type.basic.DateTimeType;
050: import org.apache.cxf.aegis.type.basic.DoubleType;
051: import org.apache.cxf.aegis.type.basic.FloatType;
052: import org.apache.cxf.aegis.type.basic.IntType;
053: import org.apache.cxf.aegis.type.basic.LongType;
054: import org.apache.cxf.aegis.type.basic.ObjectType;
055: import org.apache.cxf.aegis.type.basic.ShortType;
056: import org.apache.cxf.aegis.type.basic.SqlDateType;
057: import org.apache.cxf.aegis.type.basic.StringType;
058: import org.apache.cxf.aegis.type.basic.TimeType;
059: import org.apache.cxf.aegis.type.basic.TimestampType;
060: import org.apache.cxf.aegis.type.basic.URIType;
061: import org.apache.cxf.aegis.type.java5.Java5TypeCreator;
062: import org.apache.cxf.aegis.type.mtom.DataHandlerType;
063: import org.apache.cxf.aegis.type.mtom.DataSourceType;
064: import org.apache.cxf.aegis.type.xml.DocumentType;
065: import org.apache.cxf.aegis.type.xml.JDOMDocumentType;
066: import org.apache.cxf.aegis.type.xml.JDOMElementType;
067: import org.apache.cxf.aegis.type.xml.SourceType;
068: import org.apache.cxf.aegis.type.xml.XMLStreamReaderType;
069: import org.apache.cxf.aegis.util.XmlConstants;
070: import org.apache.cxf.binding.soap.Soap11;
071: import org.apache.cxf.common.classloader.ClassLoaderUtils;
072: import org.jdom.Element;
073:
074: /**
075: * The default implementation of TypeMappingRegistry.
076: *
077: * @author <a href="mailto:dan@envoisolutions.com">Dan Diephouse</a>
078: * @since Feb 22, 2004
079: */
080: public final class DefaultTypeMappingRegistry implements
081: TypeMappingRegistry {
082: static final QName XSD_STRING = new QName(XmlConstants.XSD,
083: "string", XmlConstants.XSD_PREFIX);
084: static final QName XSD_LONG = new QName(XmlConstants.XSD, "long",
085: XmlConstants.XSD_PREFIX);
086: static final QName XSD_FLOAT = new QName(XmlConstants.XSD, "float",
087: XmlConstants.XSD_PREFIX);
088: static final QName XSD_DOUBLE = new QName(XmlConstants.XSD,
089: "double", XmlConstants.XSD_PREFIX);
090: static final QName XSD_INT = new QName(XmlConstants.XSD, "int",
091: XmlConstants.XSD_PREFIX);
092: static final QName XSD_SHORT = new QName(XmlConstants.XSD, "short",
093: XmlConstants.XSD_PREFIX);
094: static final QName XSD_BOOLEAN = new QName(XmlConstants.XSD,
095: "boolean", XmlConstants.XSD_PREFIX);
096: static final QName XSD_DATETIME = new QName(XmlConstants.XSD,
097: "dateTime", XmlConstants.XSD_PREFIX);
098: static final QName XSD_TIME = new QName(XmlConstants.XSD,
099: "dateTime", XmlConstants.XSD_PREFIX);
100: static final QName XSD_BASE64 = new QName(XmlConstants.XSD,
101: "base64Binary", XmlConstants.XSD_PREFIX);
102: static final QName XSD_DECIMAL = new QName(XmlConstants.XSD,
103: "decimal", XmlConstants.XSD_PREFIX);
104: static final QName XSD_INTEGER = new QName(XmlConstants.XSD,
105: "integer", XmlConstants.XSD_PREFIX);
106: static final QName XSD_URI = new QName(XmlConstants.XSD, "anyURI",
107: XmlConstants.XSD_PREFIX);
108: static final QName XSD_ANY = new QName(XmlConstants.XSD, "anyType",
109: XmlConstants.XSD_PREFIX);
110:
111: static final QName XSD_DATE = new QName(XmlConstants.XSD, "date",
112: XmlConstants.XSD_PREFIX);
113: static final QName XSD_DURATION = new QName(XmlConstants.XSD,
114: "duration", XmlConstants.XSD_PREFIX);
115: static final QName XSD_G_YEAR_MONTH = new QName(XmlConstants.XSD,
116: "gYearMonth", XmlConstants.XSD_PREFIX);
117: static final QName XSD_G_MONTH_DAY = new QName(XmlConstants.XSD,
118: "gMonthDay", XmlConstants.XSD_PREFIX);
119: static final QName XSD_G_YEAR = new QName(XmlConstants.XSD,
120: "gYear", XmlConstants.XSD_PREFIX);
121: static final QName XSD_G_MONTH = new QName(XmlConstants.XSD,
122: "gMonth", XmlConstants.XSD_PREFIX);
123: static final QName XSD_G_DAY = new QName(XmlConstants.XSD, "gDay",
124: XmlConstants.XSD_PREFIX);
125:
126: static final String ENCODED_NS = Soap11.getInstance()
127: .getSoapEncodingStyle();
128: static final QName ENCODED_STRING = new QName(ENCODED_NS, "string");
129: static final QName ENCODED_LONG = new QName(ENCODED_NS, "long");
130: static final QName ENCODED_FLOAT = new QName(ENCODED_NS, "float");
131: static final QName ENCODED_CHAR = new QName(ENCODED_NS, "char");
132: static final QName ENCODED_DOUBLE = new QName(ENCODED_NS, "double");
133: static final QName ENCODED_INT = new QName(ENCODED_NS, "int");
134: static final QName ENCODED_SHORT = new QName(ENCODED_NS, "short");
135: static final QName ENCODED_BOOLEAN = new QName(ENCODED_NS,
136: "boolean");
137: static final QName ENCODED_DATETIME = new QName(ENCODED_NS,
138: "dateTime");
139: static final QName ENCODED_BASE64 = new QName(ENCODED_NS,
140: "base64Binary");
141: static final QName ENCODED_DECIMAL = new QName(ENCODED_NS,
142: "decimal");
143: static final QName ENCODED_INTEGER = new QName(ENCODED_NS,
144: "integer");
145:
146: private static final Log LOG = LogFactory
147: .getLog(DefaultTypeMappingRegistry.class);
148:
149: private Map<String, TypeMapping> registry;
150:
151: private TypeMapping defaultTM;
152:
153: private TypeCreator typeCreator;
154:
155: private Configuration typeConfiguration;
156:
157: public DefaultTypeMappingRegistry() {
158: this (false);
159: }
160:
161: public DefaultTypeMappingRegistry(boolean createDefault) {
162: this (null, createDefault);
163: }
164:
165: public DefaultTypeMappingRegistry(TypeCreator typeCreator,
166: boolean createDefault) {
167: registry = Collections
168: .synchronizedMap(new HashMap<String, TypeMapping>());
169:
170: this .typeCreator = typeCreator;
171: this .typeConfiguration = new Configuration();
172:
173: if (createDefault) {
174: createDefaultMappings();
175: }
176: }
177:
178: public TypeMapping register(String encodingStyleURI,
179: TypeMapping mapping) {
180: TypeMapping previous = registry.get(encodingStyleURI);
181:
182: mapping.setEncodingStyleURI(encodingStyleURI);
183:
184: registry.put(encodingStyleURI, mapping);
185:
186: return previous;
187: }
188:
189: public void registerDefault(TypeMapping mapping) {
190: defaultTM = mapping;
191: }
192:
193: /**
194: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#getDefaultTypeMapping()
195: */
196: public TypeMapping getDefaultTypeMapping() {
197: return defaultTM;
198: }
199:
200: /**
201: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#getRegisteredEncodingStyleURIs()
202: */
203: public String[] getRegisteredEncodingStyleURIs() {
204: return registry.keySet().toArray(new String[registry.size()]);
205: }
206:
207: /**
208: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#getTypeMapping(java.lang.String)
209: */
210: public TypeMapping getTypeMapping(String encodingStyleURI) {
211: return registry.get(encodingStyleURI);
212: }
213:
214: /**
215: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#createTypeMapping(boolean)
216: */
217: public TypeMapping createTypeMapping(boolean autoTypes) {
218: return createTypeMapping(getDefaultTypeMapping(), autoTypes);
219: }
220:
221: /**
222: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#createTypeMapping(String,
223: * boolean)
224: */
225: public TypeMapping createTypeMapping(String parentNamespace,
226: boolean autoTypes) {
227: return createTypeMapping(getTypeMapping(parentNamespace),
228: autoTypes);
229: }
230:
231: protected TypeMapping createTypeMapping(TypeMapping parent,
232: boolean autoTypes) {
233: CustomTypeMapping tm = new CustomTypeMapping(parent);
234:
235: if (autoTypes) {
236: tm.setTypeCreator(createTypeCreator());
237: }
238:
239: return tm;
240: }
241:
242: public TypeCreator getTypeCreator() {
243: if (typeCreator == null) {
244: typeCreator = createTypeCreator();
245: }
246:
247: return typeCreator;
248: }
249:
250: public void setTypeCreator(TypeCreator typeCreator) {
251: this .typeCreator = typeCreator;
252: }
253:
254: protected TypeCreator createTypeCreator() {
255: AbstractTypeCreator xmlCreator = createRootTypeCreator();
256:
257: Java5TypeCreator j5Creator = new Java5TypeCreator();
258: j5Creator.setNextCreator(createDefaultTypeCreator());
259: j5Creator.setConfiguration(getConfiguration());
260: xmlCreator.setNextCreator(j5Creator);
261:
262: return xmlCreator;
263: }
264:
265: boolean isJDK5andAbove() {
266: String v = System.getProperty("java.class.version", "44.0");
267: return "49.0".compareTo(v) <= 0;
268: }
269:
270: protected AbstractTypeCreator createRootTypeCreator() {
271: AbstractTypeCreator creator = new XMLTypeCreator();
272: creator.setConfiguration(getConfiguration());
273: return creator;
274: }
275:
276: protected AbstractTypeCreator createDefaultTypeCreator() {
277: AbstractTypeCreator creator = new DefaultTypeCreator();
278: creator.setConfiguration(getConfiguration());
279: return creator;
280: }
281:
282: /**
283: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#unregisterTypeMapping(java.lang.String)
284: */
285: public TypeMapping unregisterTypeMapping(String encodingStyleURI) {
286: TypeMapping tm = registry.get(encodingStyleURI);
287: registry.remove(encodingStyleURI);
288: return tm;
289: }
290:
291: public boolean removeTypeMapping(TypeMapping mapping) {
292: int n = 0;
293:
294: for (Iterator itr = registry.values().iterator(); itr.hasNext();) {
295: if (itr.next().equals(mapping)) {
296: itr.remove();
297: n++;
298: }
299: }
300:
301: return n > 0;
302: }
303:
304: /**
305: * @see org.apache.cxf.aegis.type.TypeMappingRegistry#clear()
306: */
307: public void clear() {
308: registry.clear();
309: }
310:
311: public TypeMapping createDefaultMappings() {
312: TypeMapping tm = createTypeMapping(false);
313:
314: createDefaultMappings(tm);
315:
316: // Create a Type Mapping for SOAP 1.1 Encoding
317: TypeMapping soapTM = createTypeMapping(tm, false);
318:
319: register(soapTM, boolean.class, ENCODED_BOOLEAN,
320: new BooleanType());
321: register(soapTM, int.class, ENCODED_INT, new IntType());
322: register(soapTM, short.class, ENCODED_SHORT, new ShortType());
323: register(soapTM, double.class, ENCODED_DOUBLE, new DoubleType());
324: register(soapTM, float.class, ENCODED_FLOAT, new FloatType());
325: register(soapTM, long.class, ENCODED_LONG, new LongType());
326: register(soapTM, char.class, ENCODED_CHAR, new CharacterType());
327: register(soapTM, Character.class, ENCODED_CHAR,
328: new CharacterType());
329: register(soapTM, String.class, ENCODED_STRING, new StringType());
330: register(soapTM, Boolean.class, ENCODED_BOOLEAN,
331: new BooleanType());
332: register(soapTM, Integer.class, ENCODED_INT, new IntType());
333: register(soapTM, Short.class, ENCODED_SHORT, new ShortType());
334: register(soapTM, Double.class, ENCODED_DOUBLE, new DoubleType());
335: register(soapTM, Float.class, ENCODED_FLOAT, new FloatType());
336: register(soapTM, Long.class, ENCODED_LONG, new LongType());
337: register(soapTM, Date.class, ENCODED_DATETIME,
338: new DateTimeType());
339: register(soapTM, java.sql.Date.class, ENCODED_DATETIME,
340: new SqlDateType());
341: register(soapTM, Calendar.class, ENCODED_DATETIME,
342: new CalendarType());
343: register(soapTM, byte[].class, ENCODED_BASE64, new Base64Type());
344: register(soapTM, BigDecimal.class, ENCODED_DECIMAL,
345: new BigDecimalType());
346: register(soapTM, BigInteger.class, ENCODED_INTEGER,
347: new BigIntegerType());
348:
349: register(soapTM, boolean.class, XSD_BOOLEAN, new BooleanType());
350: register(soapTM, int.class, XSD_INT, new IntType());
351: register(soapTM, short.class, XSD_SHORT, new ShortType());
352: register(soapTM, double.class, XSD_DOUBLE, new DoubleType());
353: register(soapTM, float.class, XSD_FLOAT, new FloatType());
354: register(soapTM, long.class, XSD_LONG, new LongType());
355: register(soapTM, String.class, XSD_STRING, new StringType());
356: register(soapTM, Boolean.class, XSD_BOOLEAN, new BooleanType());
357: register(soapTM, Integer.class, XSD_INT, new IntType());
358: register(soapTM, Short.class, XSD_SHORT, new ShortType());
359: register(soapTM, Double.class, XSD_DOUBLE, new DoubleType());
360: register(soapTM, Float.class, XSD_FLOAT, new FloatType());
361: register(soapTM, Long.class, XSD_LONG, new LongType());
362: register(soapTM, Date.class, XSD_DATETIME, new DateTimeType());
363: register(soapTM, java.sql.Date.class, XSD_DATETIME,
364: new SqlDateType());
365: register(soapTM, Time.class, XSD_TIME, new TimeType());
366: register(soapTM, Timestamp.class, XSD_DATETIME,
367: new TimestampType());
368: register(soapTM, Calendar.class, XSD_DATETIME,
369: new CalendarType());
370: register(soapTM, byte[].class, XSD_BASE64, new Base64Type());
371: register(soapTM, BigDecimal.class, XSD_DECIMAL,
372: new BigDecimalType());
373: register(soapTM, URI.class, XSD_URI, new URIType());
374: register(soapTM, Document.class, XSD_ANY, new DocumentType());
375: register(soapTM, Source.class, XSD_ANY, new SourceType());
376: register(soapTM, XMLStreamReader.class, XSD_ANY,
377: new XMLStreamReaderType());
378: register(soapTM, Element.class, XSD_ANY, new JDOMElementType());
379: register(soapTM, org.jdom.Document.class, XSD_ANY,
380: new JDOMDocumentType());
381: register(soapTM, Object.class, XSD_ANY, new ObjectType());
382: register(soapTM, DataSource.class, XSD_BASE64,
383: new DataSourceType());
384: register(soapTM, DataHandler.class, XSD_BASE64,
385: new DataHandlerType());
386: register(soapTM, BigInteger.class, XSD_INTEGER,
387: new BigIntegerType());
388:
389: register(ENCODED_NS, soapTM);
390:
391: register(XmlConstants.XSD, tm);
392: registerDefault(tm);
393:
394: return tm;
395: }
396:
397: protected void createDefaultMappings(TypeMapping tm) {
398: register(tm, boolean.class, XSD_BOOLEAN, new BooleanType());
399: register(tm, int.class, XSD_INT, new IntType());
400: register(tm, short.class, XSD_SHORT, new ShortType());
401: register(tm, double.class, XSD_DOUBLE, new DoubleType());
402: register(tm, float.class, XSD_FLOAT, new FloatType());
403: register(tm, long.class, XSD_LONG, new LongType());
404: register(tm, char.class, XSD_STRING, new CharacterType());
405: register(tm, Character.class, XSD_STRING, new CharacterType());
406: register(tm, String.class, XSD_STRING, new StringType());
407: register(tm, Boolean.class, XSD_BOOLEAN, new BooleanType());
408: register(tm, Integer.class, XSD_INT, new IntType());
409: register(tm, Short.class, XSD_SHORT, new ShortType());
410: register(tm, Double.class, XSD_DOUBLE, new DoubleType());
411: register(tm, Float.class, XSD_FLOAT, new FloatType());
412: register(tm, Long.class, XSD_LONG, new LongType());
413: register(tm, Date.class, XSD_DATETIME, new DateTimeType());
414: register(tm, java.sql.Date.class, XSD_DATETIME,
415: new SqlDateType());
416: register(tm, Time.class, XSD_TIME, new TimeType());
417: register(tm, Timestamp.class, XSD_DATETIME, new TimestampType());
418: register(tm, Calendar.class, XSD_DATETIME, new CalendarType());
419: register(tm, byte[].class, XSD_BASE64, new Base64Type());
420: register(tm, BigDecimal.class, XSD_DECIMAL,
421: new BigDecimalType());
422: register(tm, BigInteger.class, XSD_INTEGER,
423: new BigIntegerType());
424: register(tm, URI.class, XSD_URI, new URIType());
425: register(tm, Document.class, XSD_ANY, new DocumentType());
426: register(tm, Source.class, XSD_ANY, new SourceType());
427: register(tm, XMLStreamReader.class, XSD_ANY,
428: new XMLStreamReaderType());
429: register(tm, Element.class, XSD_ANY, new JDOMElementType());
430: register(tm, org.jdom.Document.class, XSD_ANY,
431: new JDOMDocumentType());
432: register(tm, Object.class, XSD_ANY, new ObjectType());
433: register(tm, DataSource.class, XSD_BASE64, new DataSourceType());
434: register(tm, DataHandler.class, XSD_BASE64,
435: new DataHandlerType());
436:
437: if (isJDK5andAbove()) {
438: registerIfAvailable(tm, "javax.xml.datatype.Duration",
439: XSD_DURATION,
440: "org.codehaus.xfire.aegis.type.java5.DurationType");
441: registerIfAvailable(tm,
442: "javax.xml.datatype.XMLGregorianCalendar",
443: XSD_DATE,
444: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
445: registerIfAvailable(tm,
446: "javax.xml.datatype.XMLGregorianCalendar",
447: XSD_TIME,
448: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
449: registerIfAvailable(tm,
450: "javax.xml.datatype.XMLGregorianCalendar",
451: XSD_G_DAY,
452: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
453: registerIfAvailable(tm,
454: "javax.xml.datatype.XMLGregorianCalendar",
455: XSD_G_MONTH,
456: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
457: registerIfAvailable(tm,
458: "javax.xml.datatype.XMLGregorianCalendar",
459: XSD_G_MONTH_DAY,
460: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
461: registerIfAvailable(tm,
462: "javax.xml.datatype.XMLGregorianCalendar",
463: XSD_G_YEAR,
464: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
465: registerIfAvailable(tm,
466: "javax.xml.datatype.XMLGregorianCalendar",
467: XSD_G_YEAR_MONTH,
468: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
469: registerIfAvailable(tm,
470: "javax.xml.datatype.XMLGregorianCalendar",
471: XSD_DATETIME,
472: "org.codehaus.xfire.aegis.type.java5.XMLGregorianCalendarType");
473: }
474: }
475:
476: protected void registerIfAvailable(TypeMapping tm,
477: String className, QName typeName, String typeClassName) {
478: try {
479: Class cls = ClassLoaderUtils.loadClass(className,
480: getClass());
481: Class typeCls = ClassLoaderUtils.loadClass(typeClassName,
482: getClass());
483: try {
484: Type type = (Type) typeCls.newInstance();
485:
486: register(tm, cls, typeName, type);
487: } catch (InstantiationException e) {
488: throw new DatabindingException(
489: "Couldn't instantiate Type ", e);
490: } catch (IllegalAccessException e) {
491: throw new DatabindingException(
492: "Couldn't instantiate Type ", e);
493: }
494: } catch (ClassNotFoundException e) {
495: LOG.debug("Could not find optional Type " + className
496: + ". Skipping.");
497: }
498:
499: }
500:
501: protected void register(TypeMapping tm, Class class1, QName name,
502: Type type) {
503: if (!getConfiguration().isDefaultNillable()) {
504: type.setNillable(false);
505: }
506:
507: tm.register(class1, name, type);
508: }
509:
510: public Configuration getConfiguration() {
511: return typeConfiguration;
512: }
513:
514: public void setConfiguration(Configuration tpConfiguration) {
515: this.typeConfiguration = tpConfiguration;
516: }
517:
518: }
|