001: /**********************************************************************
002: Copyright (c) 2003 Andy Jefferson and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015: Contributors:
016: 2004 Erik Bengtson - added interfaces methods
017: ...
018: **********************************************************************/package org.jpox;
019:
020: import java.lang.reflect.Modifier;
021: import java.util.Arrays;
022: import java.util.Collection;
023: import java.util.HashMap;
024: import java.util.HashSet;
025: import java.util.Iterator;
026: import java.util.Map;
027: import java.util.Set;
028:
029: import org.jpox.api.ApiAdapter;
030: import org.jpox.exceptions.JPOXException;
031: import org.jpox.metadata.FieldPersistenceModifier;
032: import org.jpox.plugin.ConfigurationElement;
033: import org.jpox.plugin.ExtensionPoint;
034: import org.jpox.plugin.PluginManager;
035: import org.jpox.sco.SCOList;
036: import org.jpox.sco.SCOMap;
037: import org.jpox.util.JPOXLogger;
038: import org.jpox.util.JavaUtils;
039: import org.jpox.util.Localiser;
040: import org.jpox.util.StringUtils;
041:
042: /**
043: * Registry of type support within JPOX.
044: * The plugin mechanism provides the registration of supported types, so that users can register
045: * support for their own types and these are loaded when the TypeManager is constructed.
046: *
047: * @version $Revision: 1.49 $
048: */
049: public class TypeManager {
050: private static final Localiser LOCALISER = Localiser
051: .getInstance("org.jpox.Localisation");
052:
053: protected final ClassLoaderResolver clr;
054:
055: protected final ApiAdapter api;
056:
057: /** The types, keyed by the class name. */
058: Map types = new HashMap();
059:
060: /** Shortcut for the type names which default to 'persistence-modifier="persistent"' */
061: private static String[] DEFAULT_PERSISTENT_TYPE;
062:
063: /** Shortcut for the type names which default to 'default-fetch-group="true"' */
064: private static String[] DEFAULT_FETCH_GROUP_TRUE;
065:
066: /** Shortcut for the type names which default to 'embedded="true"' */
067: private static String[] DEFAULT_EMBEDDED_TYPE;
068:
069: /**
070: * Constructor, loading JPOX's support for type mappings using the plugin mechanism.
071: * @param api The API in use
072: * @param clr the ClassLoader Resolver
073: * @param mgr the PluginManager
074: **/
075: public TypeManager(ApiAdapter api, PluginManager mgr,
076: ClassLoaderResolver clr) {
077: this .clr = clr;
078: this .api = api;
079: loadUserTypes(mgr, clr);
080: }
081:
082: /**
083: * Convenience method returning whether the passed type is a reference type.
084: * This typically means whether it is an interface or java.lang.Object.
085: * @param cls The class
086: * @return Whether it is a reference type
087: */
088: public boolean isReferenceType(Class cls) {
089: if (cls == null) {
090: return false;
091: }
092: return cls.isInterface()
093: || cls.getName().equals("java.lang.Object");
094: }
095:
096: /**
097: * Accessor for whether a class is supported.
098: * @param className The class name
099: * @return Whether the class is supported (to some degree)
100: */
101: public boolean isSupportedType(String className) {
102: if (className == null) {
103: return false;
104: }
105:
106: JPOXType type = getType(className);
107: if (type == null) {
108: try {
109: Class cls = clr.classForName(className);
110: type = findJPOXTypeForClass(cls);
111: return (type.getSCOMappingType() != null);
112: } catch (Exception e) {
113: }
114: return false;
115: } else {
116: return (type.getSCOMappingType() != null);
117: }
118: }
119:
120: /**
121: * Accessor for the Supported Types.
122: * @return Set of supported types (containing the fully qualified class names (String)).
123: **/
124: public Set getSupportedTypes() {
125: return new HashSet(types.keySet());
126: }
127:
128: /**
129: * Accessor for whether a class is a supported second class mutable type
130: * @param class_name The class name
131: * @return Whether it is a second class mutable type
132: */
133: public boolean isSecondClassMutableType(String class_name) {
134: return (getSecondClassWrapper(class_name) != null);
135: }
136:
137: /**
138: * Accessor for whether the type is a List type that uses a SCOList wrapper type.
139: * @param c The class
140: * @return if c is a List type
141: */
142: public boolean isSCOList(Class c) {
143: if (c == null) {
144: return false;
145: }
146: if (c.isInterface() && !isSupportedType(c.getName())) {
147: return false;
148: }
149:
150: JPOXType type = getType(c.getName());
151: return type != null ? SCOList.class.isAssignableFrom(type
152: .getSCOMutableWrapperType()) : false;
153: }
154:
155: /**
156: * Accessor for whether the type is a Map type that uses a SCOMap wrapper type.
157: * @param c The class
158: * @return true if c is a Map type
159: */
160: public boolean isSCOMap(Class c) {
161: if (c == null) {
162: return false;
163: }
164: if (c.isInterface() && !isSupportedType(c.getName())) {
165: return false;
166: }
167:
168: JPOXType type = getType(c.getName());
169: return type != null ? SCOMap.class.isAssignableFrom(type
170: .getSCOMutableWrapperType()) : false;
171: }
172:
173: /**
174: * Accessor for the Java Mapping type class for the supplied class.
175: * @param className The class name
176: * @return The Java mapping type
177: */
178: public Class getMappingType(String className) {
179: if (className == null) {
180: return null;
181: }
182:
183: JPOXType type = getType(className);
184: if (type == null) {
185: // Check if this is a SCO wrapper
186: Collection supportedTypes = new HashSet(types.values());
187: Iterator iter = supportedTypes.iterator();
188: while (iter.hasNext()) {
189: type = (JPOXType) iter.next();
190: if (type.scoMutableWrapperType != null
191: && type.scoMutableWrapperType.getName().equals(
192: className)) {
193: // SCO wrapper with same name, so return the JavaTypeMapping for that
194: return type.getSCOMappingType();
195: } else if (type.scoMutableSimpleWrapperType != null
196: && type.scoMutableSimpleWrapperType.getName()
197: .equals(className)) {
198: // SCO wrapper with same name, so return the JavaTypeMapping for that
199: return type.getSCOMappingType();
200: }
201: }
202:
203: // Not SCO wrapper so find a type
204: try {
205: Class cls = clr.classForName(className);
206: type = findJPOXTypeForClass(cls);
207: return type.getSCOMappingType();
208: } catch (Exception e) {
209: return null;
210: }
211: } else {
212: return type.getSCOMappingType();
213: }
214: }
215:
216: /**
217: * Accessor for the Second Class Wrapper class for the supplied class.
218: * A type will have a SCO wrapper if it is SCO supported and is mutable.
219: * @param className The class name
220: * @return The second class wrapper
221: */
222: public Class getSecondClassWrapper(String className) {
223: if (className == null) {
224: return null;
225: }
226:
227: JPOXType type = getType(className);
228: return type == null ? null : type.getSCOMutableWrapperType();
229: }
230:
231: /**
232: * Accessor for the SCO "simple" wrapper class for the supplied class.
233: * A type will have a SCO wrapper if it is SCO supported and is mutable.
234: * The "simple" wrapper provides simple wrapping of operations and dirty detection only.
235: * @param className The class name
236: * @return The second class wrapper
237: */
238: public Class getSecondClassWrapperSimple(String className) {
239: if (className == null) {
240: return null;
241: }
242:
243: JPOXType type = getType(className);
244: return type == null ? null : type
245: .getSCOMutableSimpleWrapperType();
246: }
247:
248: /**
249: * Accessor for whether a class is a Second Class Wrapper type.
250: * @param className The name of the class
251: * @return Whether it is a second class wrapper type
252: */
253: public boolean isSecondClassWrapper(String className) {
254: if (className == null) {
255: return false;
256: }
257:
258: Iterator iter = types.values().iterator();
259: while (iter.hasNext()) {
260: JPOXType type = (JPOXType) iter.next();
261: if (type.getSCOMutableWrapperType() != null
262: && type.getSCOMutableWrapperType().getName()
263: .equals(className)) {
264: return true;
265: }
266: if (type.getSCOMutableSimpleWrapperType() != null
267: && type.getSCOMutableSimpleWrapperType().getName()
268: .equals(className)) {
269: return true;
270: }
271: }
272: return false;
273: }
274:
275: /**
276: * Accessor for the default "persistence-modifier" for a field given the
277: * class, its modifier and whether it is a PersistentCapable class.
278: * @param c The class
279: * @param modifier The modifiers for the field
280: * @param isPCclass Whether it is persistence capable.
281: * @return The default field PersistenceModifier.
282: */
283: public final FieldPersistenceModifier getDefaultFieldPersistenceModifier(
284: Class c, int modifier, boolean isPCclass) {
285: // Static, Transient and Final fields are all not persistent
286: if (Modifier.isStatic(modifier)
287: || Modifier.isTransient(modifier)
288: || Modifier.isFinal(modifier)) {
289: // Static, transient and final fields are not persistent
290: return FieldPersistenceModifier.NONE;
291: }
292:
293: if (isPCclass) {
294: // All PC class fields are persistent by default
295: return FieldPersistenceModifier.PERSISTENT;
296: }
297:
298: if (c == null) {
299: throw new JPOXException("class is null");
300: }
301:
302: if (Arrays.binarySearch(DEFAULT_PERSISTENT_TYPE, c.getName()) >= 0) {
303: // Use the specified "jpoxtypes" default persistence modifier for this type (if specified)
304: return FieldPersistenceModifier.PERSISTENT;
305: }
306: if (c.isArray() && api.isPersistable(c.getComponentType())) {
307: // Arrays of PC types are, by default, persistent
308: return FieldPersistenceModifier.PERSISTENT;
309: }
310:
311: // Try to find a class that this class extends that is supported
312: JPOXType type = findJPOXTypeForClass(c);
313: if (type != null) {
314: return (type.dftPersistent ? FieldPersistenceModifier.PERSISTENT
315: : FieldPersistenceModifier.NONE);
316: }
317:
318: return FieldPersistenceModifier.NONE;
319: }
320:
321: /**
322: * Accessor for whether the class is by default in the default fetch group.
323: * @param c The class
324: * @return return true if is part of default fetch group by default
325: */
326: public boolean isDefaultFetchGroup(Class c) {
327: if (c == null) {
328: return false;
329: }
330: if (Arrays.binarySearch(DEFAULT_FETCH_GROUP_TRUE, c.getName()) >= 0) {
331: return true;
332: }
333:
334: // Try to find a class that this class extends that is supported
335: JPOXType type = findJPOXTypeForClass(c);
336: if (type != null) {
337: return type.dfg;
338: }
339:
340: return false;
341: }
342:
343: /**
344: * Utility to return whether a type defaults to embedded or not.
345: * See JDO 2 Section 18.14 <field> for definition. This only provides for the
346: * basic types, and ignores arrays/collections.
347: * @param c The type
348: * @return Whether it defaults to embedded or not.
349: */
350: public boolean isDefaultEmbeddedType(Class c) {
351: if (c == null) {
352: return false;
353: }
354: if (Arrays.binarySearch(DEFAULT_EMBEDDED_TYPE, c.getName()) >= 0) {
355: return true;
356: }
357:
358: // Try to find a class that this class extends that is supported
359: JPOXType type = findJPOXTypeForClass(c);
360: if (type != null) {
361: return type.dftEmbedded;
362: }
363:
364: return false;
365: }
366:
367: /**
368: * Utility class to retrieve a supported type
369: * @param className The class name
370: * @return The internal type information for the class
371: */
372: protected JPOXType getType(String className) {
373: if (className == null) {
374: return null;
375: }
376:
377: return (JPOXType) types.get(className);
378: }
379:
380: protected JPOXType findJPOXTypeForClass(Class cls) {
381: JPOXType type = getType(cls.getName());
382: if (type != null) {
383: return type;
384: }
385:
386: // Not supported so try to find one that is supported that this class derives from
387: Class componentCls = (cls.isArray() ? cls.getComponentType()
388: : null);
389: Collection supportedTypes = new HashSet(types.values());
390: Iterator iter = supportedTypes.iterator();
391: while (iter.hasNext()) {
392: type = (JPOXType) iter.next();
393: if (type.cls == cls) {
394: return type;
395: }
396: if (!type.cls.getName().equals("java.lang.Object")
397: && !type.cls.getName().equals(
398: "java.io.Serializable")) {
399: if (componentCls != null) {
400: // Array type
401: if (type.cls.isArray()
402: && type.cls.getComponentType()
403: .isAssignableFrom(componentCls)) {
404: addTypeInternal(cls, type);
405: return type;
406: }
407: } else {
408: // Basic type
409: if (type.cls.isAssignableFrom(cls)) {
410: // Copy the mapping of this type
411: addTypeInternal(cls, type);
412: return type;
413: }
414: }
415: }
416: }
417:
418: // Not supported
419: return null;
420: }
421:
422: /**
423: * Inner class defining a supported type.
424: * The type is supported to some degree by JPOX, maybe as FCO or maybe as SCO.
425: * Only has SCO wrapper class if is SCO mutable.
426: */
427: static class JPOXType {
428: /** supported class. */
429: final Class cls;
430:
431: /** mapping class. An extension of {@link org.jpox.store.mapping.JavaTypeMapping}*/
432: final Class scoMappingType;
433: /** sco wrapper for mutable types. An implementation of {@link org.jpox.sco.SCO} */
434: final Class scoMutableWrapperType;
435: /** sco wrapper for mutable types. An implementation of {@link org.jpox.sco.SCO} */
436: final Class scoMutableSimpleWrapperType;
437: /** default-fetch-group */
438: final boolean dfg;
439: /** minimum required java version **/
440: final String javaVersion;
441: /** if this type is persistent by default. If not, the metadata must explicitily set persistent-modifier="persistent" **/
442: final boolean dftPersistent;
443: /** if this type is embedded by default. If not, the metadata must explicitily set embedded="true" **/
444: final boolean dftEmbedded;
445: /** if this type is restricted only to the specified java version */
446: final boolean javaRestricted;
447:
448: /**
449: * Constructor.
450: * @param cls the java type class being supported
451: * @param sco_mapping_type the mapping class. An extension of {@link org.jpox.store.mapping.JavaTypeMapping}
452: * @param sco_wrapper_type the SCO wrapper class name. An implementation of {@link org.jpox.sco.SCO}
453: * @param sco_simple_wrapper_type the SCO "simple" wrapper class name. An implementation of {@link org.jpox.sco.SCO}
454: * @param dfg default fetch group
455: * @param dftPersistent if this type is persistent by default
456: * @param dftEmbedded if this type is embedded by default
457: * @param javaVersion minimum required java version
458: * @param javaRestricted if this type is restricted only to the specified java version by
459: * <code>javaVersion</code>
460: */
461: public JPOXType(Class cls, Class sco_mapping_type,
462: Class sco_wrapper_type, Class sco_simple_wrapper_type,
463: boolean dfg, boolean dftPersistent,
464: boolean dftEmbedded, String javaVersion,
465: boolean javaRestricted) {
466: this .cls = cls;
467: this .scoMappingType = sco_mapping_type;
468: this .scoMutableWrapperType = sco_wrapper_type;
469: this .scoMutableSimpleWrapperType = sco_simple_wrapper_type;
470: this .dfg = dfg;
471: this .javaVersion = javaVersion;
472: this .dftPersistent = dftPersistent;
473: this .javaRestricted = javaRestricted;
474: this .dftEmbedded = dftEmbedded;
475: }
476:
477: /**
478: * Accessor for the mapping class. An extension of {@link org.jpox.store.mapping.JavaTypeMapping}
479: * @return the mapping class. An extension of {@link org.jpox.store.mapping.JavaTypeMapping}
480: */
481: public Class getSCOMappingType() {
482: return scoMappingType;
483: }
484:
485: /**
486: * Accessor for the SCO wrapper class name. An implementation of {@link org.jpox.sco.SCO}
487: * @return the SCO wrapper class name. An implementation of {@link org.jpox.sco.SCO}
488: */
489: public Class getSCOMutableWrapperType() {
490: return scoMutableWrapperType;
491: }
492:
493: /**
494: * Accessor for the SCO "simple" wrapper class name. An implementation of {@link org.jpox.sco.SCO}
495: * @return the SCO wrapper class name. An implementation of {@link org.jpox.sco.SCO}
496: */
497: public Class getSCOMutableSimpleWrapperType() {
498: return scoMutableSimpleWrapperType;
499: }
500:
501: public String toString() {
502: StringBuffer str = new StringBuffer(cls.getName() + " [");
503: if (scoMappingType != null) {
504: str.append(" SCO : mapping=" + scoMappingType);
505: }
506: if (scoMutableWrapperType != null) {
507: str.append(" SCO : mutable wrapper="
508: + scoMutableWrapperType);
509: }
510: if (scoMutableSimpleWrapperType != null) {
511: str.append(" SCO : simple wrapper="
512: + scoMutableSimpleWrapperType);
513: }
514: str.append(" default-fetch-group : " + dfg);
515: str.append(" java version : " + javaVersion
516: + (javaRestricted ? " restricted" : ""));
517: str.append(" default persisted : " + dftPersistent);
518: str.append(" default embedded : " + dftEmbedded);
519: str.append("]");
520: return str.toString();
521: }
522: }
523:
524: /**
525: * Method to load the user type mappings that are currently registered in the PluginManager.
526: * @param mgr the PluginManager
527: * @param clr the ClassLoaderResolver
528: */
529: private void loadUserTypes(PluginManager mgr,
530: ClassLoaderResolver clr) {
531: ExtensionPoint exPoint = mgr
532: .getExtensionPoint("org.jpox.store_mapping");
533: for (int i = 0; i < exPoint.getExtensions().length; i++) {
534: ConfigurationElement[] elms = exPoint.getExtensions()[i]
535: .getConfigurationElements();
536: for (int e = 0; e < elms.length; e++) {
537: String javaName = elms[e].getAttribute("java-type")
538: .trim();
539: String mappingClassName = elms[e]
540: .getAttribute("mapping-class");
541: String fullWrapperClassName = elms[e]
542: .getAttribute("sco-wrapper");
543: String simpleWrapperClassName = elms[e]
544: .getAttribute("sco-wrapper-simple");
545: String defaultFetchGroup = elms[e]
546: .getAttribute("default-fetch-group");
547: String defaultPersistent = elms[e]
548: .getAttribute("default-persistent");
549: String defaultEmbedded = elms[e]
550: .getAttribute("default-embedded");
551: String javaVersionRestrict = elms[e]
552: .getAttribute("java-version-restrict");
553: if (simpleWrapperClassName == null) {
554: // No simple wrapper specified so fallback to the full wrapper
555: simpleWrapperClassName = fullWrapperClassName;
556: }
557: boolean dfg = false;
558: if (defaultFetchGroup != null) {
559: if (defaultFetchGroup.equalsIgnoreCase("true")) {
560: dfg = Boolean.TRUE.booleanValue();
561: }
562: }
563: boolean dftPersistent = false;
564: if (defaultPersistent != null) {
565: if (defaultPersistent.equalsIgnoreCase("true")) {
566: dftPersistent = Boolean.TRUE.booleanValue();
567: }
568: }
569: boolean dftEmbedded = false;
570: if (defaultEmbedded != null) {
571: if (defaultEmbedded.equalsIgnoreCase("true")) {
572: dftEmbedded = Boolean.TRUE.booleanValue();
573: }
574: }
575: boolean javaRestricted = false;
576: if (javaVersionRestrict != null) {
577: if (javaVersionRestrict.equalsIgnoreCase("true")) {
578: javaRestricted = Boolean.TRUE.booleanValue();
579: }
580: }
581: String javaVersion = elms[e]
582: .getAttribute("java-version");
583: if (javaVersion == null || javaVersion.length() < 1) {
584: javaVersion = "1.3";
585: }
586:
587: addType(mgr, elms[e].getExtension().getPlugin()
588: .getSymbolicName(), javaName, mappingClassName,
589: fullWrapperClassName, simpleWrapperClassName,
590: dfg, dftPersistent, dftEmbedded, javaVersion,
591: javaRestricted, clr);
592: }
593: }
594: }
595:
596: /**
597: * Method to add support for a Java class (to some degree).
598: * @param mgr The PluginManager
599: * @param pluginId the plug-in id
600: * @param className Name of the class to add
601: * @param mappingClassName The Java mapping type
602: * @param fullWrapperClassName The SCO wrapper type (for mutable SCOs)
603: * @param simpleWrapperClassName The SCO "simple" wrapper type (for mutable SCOs)
604: * @param dfg whether this type should be on the default fetch group
605: * @param dftPersistent if this type is persistent by default. If not, the metadata must explicitily set persistent-modifier="persistent"
606: * @param dftEmbedded If this type is by default embedded
607: * @param javaVersion the minimum java version required at runtime to add this type
608: * @param javaRestricted if this type is restricted only to the specified java version
609: * @param clr the ClassLoaderResolver
610: */
611: private void addType(PluginManager mgr, String pluginId,
612: String className, String mappingClassName,
613: String fullWrapperClassName, String simpleWrapperClassName,
614: boolean dfg, boolean dftPersistent, boolean dftEmbedded,
615: String javaVersion, boolean javaRestricted,
616: ClassLoaderResolver clr) {
617: if (className == null) {
618: return;
619: }
620:
621: if ((JavaUtils.isGreaterEqualsThan(javaVersion) && !javaRestricted)
622: || (JavaUtils.isEqualsThan(javaVersion) && javaRestricted)) {
623: Class fullWrapperType = null;
624: Class simpleWrapperType = null;
625: Class mappingType = null;
626: if (!StringUtils.isWhitespace(mappingClassName)) {
627: try {
628: mappingType = mgr.loadClass(pluginId,
629: mappingClassName);
630: } catch (JPOXException jpe) {
631: JPOXLogger.PERSISTENCE.error(LOCALISER.msg(
632: "016004", mappingClassName));
633: return;
634: }
635: }
636: if (!StringUtils.isWhitespace(fullWrapperClassName)) {
637: try {
638: fullWrapperType = mgr.loadClass(pluginId,
639: fullWrapperClassName);
640: } catch (JPOXException jpe) {
641: JPOXLogger.PERSISTENCE.error(LOCALISER.msg(
642: "016005", fullWrapperClassName));
643: return;
644: }
645: }
646: if (!StringUtils.isWhitespace(simpleWrapperClassName)) {
647: try {
648: simpleWrapperType = mgr.loadClass(pluginId,
649: simpleWrapperClassName);
650: } catch (JPOXException jpe) {
651: JPOXLogger.PERSISTENCE.error(LOCALISER.msg(
652: "016005", simpleWrapperClassName));
653: return;
654: }
655: }
656:
657: Class cls = null;
658: try {
659: cls = clr.classForName(className);
660: } catch (Exception e) {
661: // Class not found so ignore. Should log this
662: }
663: if (cls != null) {
664: JPOXType type = new JPOXType(cls, mappingType,
665: fullWrapperType, simpleWrapperType, dfg,
666: dftPersistent, dftEmbedded, javaVersion,
667: javaRestricted);
668: if (dftPersistent) {
669: addDefaultPersistent(className);
670: }
671: if (dfg) {
672: addDefaultFetchGroup(className);
673: }
674: if (dftEmbedded) {
675: addDefaultEmbedded(className);
676: }
677: types.put(className, type);
678: if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
679: JPOXLogger.PERSISTENCE.debug(LOCALISER.msg(
680: "016000", className, "" + dftPersistent, ""
681: + dfg, "" + dftEmbedded));
682: }
683: }
684: }
685: }
686:
687: /**
688: * Method to add support for a type when it is derived from a type we already support hence shortcutting
689: * the check process.
690: * @param cls The class
691: * @param type JPOXType that we already support that we want to use for this types support also
692: */
693: private void addTypeInternal(Class cls, JPOXType type) {
694: if (cls == null) {
695: return;
696: }
697:
698: String className = cls.getName();
699: types.put(className, type);
700: if (type.dftPersistent) {
701: addDefaultPersistent(className);
702: }
703: if (type.dfg) {
704: addDefaultFetchGroup(className);
705: }
706: if (type.dftEmbedded) {
707: addDefaultEmbedded(className);
708: }
709: if (JPOXLogger.PERSISTENCE.isDebugEnabled()) {
710: JPOXLogger.PERSISTENCE.debug(LOCALISER.msg("016001",
711: className, type.cls.getName()));
712: }
713: }
714:
715: /**
716: * Add a default persistent type
717: * @param className the type name
718: */
719: private synchronized void addDefaultPersistent(String className) {
720: if (DEFAULT_PERSISTENT_TYPE == null) {
721: DEFAULT_PERSISTENT_TYPE = new String[1];
722: DEFAULT_PERSISTENT_TYPE[0] = className;
723: } else {
724: String[] temp = new String[DEFAULT_PERSISTENT_TYPE.length + 1];
725: System.arraycopy(DEFAULT_PERSISTENT_TYPE, 0, temp, 0,
726: DEFAULT_PERSISTENT_TYPE.length);
727: temp[temp.length - 1] = className;
728: Arrays.sort(temp);
729: DEFAULT_PERSISTENT_TYPE = temp;
730: }
731: }
732:
733: /**
734: * Add a default fetch group type
735: * @param className the type name
736: */
737: private synchronized void addDefaultFetchGroup(String className) {
738: if (DEFAULT_FETCH_GROUP_TRUE == null) {
739: DEFAULT_FETCH_GROUP_TRUE = new String[1];
740: DEFAULT_FETCH_GROUP_TRUE[0] = className;
741: } else {
742: String[] temp = new String[DEFAULT_FETCH_GROUP_TRUE.length + 1];
743: System.arraycopy(DEFAULT_FETCH_GROUP_TRUE, 0, temp, 0,
744: DEFAULT_FETCH_GROUP_TRUE.length);
745: temp[temp.length - 1] = className;
746: Arrays.sort(temp);
747: DEFAULT_FETCH_GROUP_TRUE = temp;
748: }
749: }
750:
751: /**
752: * Add a default embedded type
753: * @param className the type name
754: */
755: private synchronized void addDefaultEmbedded(String className) {
756: if (DEFAULT_EMBEDDED_TYPE == null) {
757: DEFAULT_EMBEDDED_TYPE = new String[1];
758: DEFAULT_EMBEDDED_TYPE[0] = className;
759: } else {
760: String[] temp = new String[DEFAULT_EMBEDDED_TYPE.length + 1];
761: System.arraycopy(DEFAULT_EMBEDDED_TYPE, 0, temp, 0,
762: DEFAULT_EMBEDDED_TYPE.length);
763: temp[temp.length - 1] = className;
764: Arrays.sort(temp);
765: DEFAULT_EMBEDDED_TYPE = temp;
766: }
767: }
768: }
|