Source Code Cross Referenced for MetaDataRepository.java in  » Database-ORM » openjpa » org » apache » openjpa » meta » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » openjpa » org.apache.openjpa.meta 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one
0003:         * or more contributor license agreements.  See the NOTICE file
0004:         * distributed with this work for additional information
0005:         * regarding copyright ownership.  The ASF licenses this file
0006:         * to you under the Apache License, Version 2.0 (the
0007:         * "License"); you may not use this file except in compliance
0008:         * with the License.  You may obtain a copy of the License at
0009:         *
0010:         * http://www.apache.org/licenses/LICENSE-2.0
0011:         *
0012:         * Unless required by applicable law or agreed to in writing,
0013:         * software distributed under the License is distributed on an
0014:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015:         * KIND, either express or implied.  See the License for the
0016:         * specific language governing permissions and limitations
0017:         * under the License.    
0018:         */
0019:        package org.apache.openjpa.meta;
0020:
0021:        import java.io.Serializable;
0022:        import java.security.AccessController;
0023:        import java.util.ArrayList;
0024:        import java.util.Arrays;
0025:        import java.util.Collection;
0026:        import java.util.Collections;
0027:        import java.util.HashMap;
0028:        import java.util.HashSet;
0029:        import java.util.Iterator;
0030:        import java.util.LinkedList;
0031:        import java.util.List;
0032:        import java.util.Map;
0033:        import java.util.Set;
0034:        import java.util.SortedSet;
0035:        import java.util.TreeSet;
0036:
0037:        import org.apache.commons.lang.StringUtils;
0038:        import org.apache.openjpa.conf.OpenJPAConfiguration;
0039:        import org.apache.openjpa.enhance.DynamicPersistenceCapable;
0040:        import org.apache.openjpa.enhance.PCRegistry;
0041:        import org.apache.openjpa.enhance.PCRegistry.RegisterClassListener;
0042:        import org.apache.openjpa.enhance.PersistenceCapable;
0043:        import org.apache.openjpa.event.LifecycleEventManager;
0044:        import org.apache.openjpa.lib.conf.Configurable;
0045:        import org.apache.openjpa.lib.conf.Configuration;
0046:        import org.apache.openjpa.lib.log.Log;
0047:        import org.apache.openjpa.lib.util.Closeable;
0048:        import org.apache.openjpa.lib.util.J2DoPrivHelper;
0049:        import org.apache.openjpa.lib.util.Localizer;
0050:        import org.apache.openjpa.lib.util.StringDistance;
0051:        import org.apache.openjpa.util.ImplHelper;
0052:        import org.apache.openjpa.util.InternalException;
0053:        import org.apache.openjpa.util.MetaDataException;
0054:        import org.apache.openjpa.util.OpenJPAId;
0055:        import serp.util.Strings;
0056:
0057:        /**
0058:         * Repository of and factory for persistent metadata.
0059:         *
0060:         * @since 0.3.0
0061:         * @author Abe White
0062:         * @author Steve Kim (query metadata)
0063:         */
0064:        public class MetaDataRepository implements 
0065:                PCRegistry.RegisterClassListener, Configurable, Closeable,
0066:                MetaDataModes, Serializable {
0067:
0068:            /**
0069:             * Constant to not validate any metadata.
0070:             */
0071:            public static final int VALIDATE_NONE = 0;
0072:
0073:            /**
0074:             * Bit flag to validate metadata.
0075:             */
0076:            public static final int VALIDATE_META = 1;
0077:
0078:            /**
0079:             * Bit flag to validate mappings.
0080:             */
0081:            public static final int VALIDATE_MAPPING = 2;
0082:
0083:            /**
0084:             * Bit flag to validate unenhanced metadata only.
0085:             */
0086:            public static final int VALIDATE_UNENHANCED = 4;
0087:
0088:            /**
0089:             * Bit flag for runtime validation. Requires that all classes are
0090:             * enhanced, and performs extra field resolution steps.
0091:             */
0092:            public static final int VALIDATE_RUNTIME = 8;
0093:
0094:            protected static final Class[] EMPTY_CLASSES = new Class[0];
0095:            protected static final NonPersistentMetaData[] EMPTY_NON_PERSISTENT = new NonPersistentMetaData[0];
0096:            protected final ClassMetaData[] EMPTY_METAS;
0097:            protected final FieldMetaData[] EMPTY_FIELDS;
0098:            protected final Order[] EMPTY_ORDERS;
0099:
0100:            private static final Localizer _loc = Localizer
0101:                    .forPackage(MetaDataRepository.class);
0102:
0103:            // system sequence
0104:            private SequenceMetaData _sysSeq = null;
0105:
0106:            // cache of parsed metadata, oid class to class, and interface class
0107:            // to metadatas
0108:            private final Map _metas = new HashMap();
0109:            private final Map _oids = Collections
0110:                    .synchronizedMap(new HashMap());
0111:            private final Map _impls = Collections
0112:                    .synchronizedMap(new HashMap());
0113:            private final Map _ifaces = Collections
0114:                    .synchronizedMap(new HashMap());
0115:            private final Map _queries = new HashMap();
0116:            private final Map _seqs = new HashMap();
0117:            private final Map _aliases = Collections
0118:                    .synchronizedMap(new HashMap());
0119:            private final Map _pawares = Collections
0120:                    .synchronizedMap(new HashMap());
0121:            private final Map _nonMapped = Collections
0122:                    .synchronizedMap(new HashMap());
0123:
0124:            // map of classes to lists of their subclasses
0125:            private final Map _subs = Collections
0126:                    .synchronizedMap(new HashMap());
0127:
0128:            // xml mapping
0129:            protected final XMLMetaData[] EMPTY_XMLMETAS;
0130:            private final Map _xmlmetas = new HashMap();
0131:
0132:            private transient OpenJPAConfiguration _conf = null;
0133:            private transient Log _log = null;
0134:            private transient InterfaceImplGenerator _implGen = null;
0135:            private transient MetaDataFactory _factory = null;
0136:
0137:            private int _resMode = MODE_META | MODE_MAPPING;
0138:            private int _sourceMode = MODE_META | MODE_MAPPING | MODE_QUERY;
0139:            private int _validate = VALIDATE_META | VALIDATE_UNENHANCED;
0140:
0141:            // we buffer up any classes that register themselves to prevent
0142:            // reentrancy errors if classes register during a current parse (common)
0143:            private final Collection _registered = new HashSet();
0144:
0145:            // set of metadatas we're in the process of resolving
0146:            private final SortedSet _resolving = new TreeSet(
0147:                    new MetaDataInheritanceComparator());
0148:            private final SortedSet _mapping = new TreeSet(
0149:                    new MetaDataInheritanceComparator());
0150:            private final List _errs = new LinkedList();
0151:
0152:            // system listeners
0153:            private LifecycleEventManager.ListenerList _listeners = new LifecycleEventManager.ListenerList(
0154:                    3);
0155:
0156:            /**
0157:             * Default constructor.  Configure via {@link Configurable}.
0158:             */
0159:            public MetaDataRepository() {
0160:                EMPTY_METAS = newClassMetaDataArray(0);
0161:                EMPTY_FIELDS = newFieldMetaDataArray(0);
0162:                EMPTY_ORDERS = newOrderArray(0);
0163:                EMPTY_XMLMETAS = newXMLClassMetaDataArray(0);
0164:            }
0165:
0166:            /**
0167:             * Return the configuration for the repository.
0168:             */
0169:            public OpenJPAConfiguration getConfiguration() {
0170:                return _conf;
0171:            }
0172:
0173:            /**
0174:             * Return the metadata log.
0175:             */
0176:            public Log getLog() {
0177:                return _log;
0178:            }
0179:
0180:            /**
0181:             * The I/O used to load metadata.
0182:             */
0183:            public MetaDataFactory getMetaDataFactory() {
0184:                return _factory;
0185:            }
0186:
0187:            /**
0188:             * The I/O used to load metadata.
0189:             */
0190:            public void setMetaDataFactory(MetaDataFactory factory) {
0191:                factory.setRepository(this );
0192:                _factory = factory;
0193:            }
0194:
0195:            /**
0196:             * The metadata validation level. Defaults to
0197:             * <code>VALIDATE_META | VALIDATE_UNENHANCED</code>.
0198:             */
0199:            public int getValidate() {
0200:                return _validate;
0201:            }
0202:
0203:            /**
0204:             * The metadata validation level. Defaults to
0205:             * <code>VALIDATE_META | VALIDATE_UNENHANCED</code>.
0206:             */
0207:            public void setValidate(int validate) {
0208:                _validate = validate;
0209:            }
0210:
0211:            /**
0212:             * The metadata validation level. Defaults to
0213:             * <code>VALIDATE_META | VALIDATE_MAPPING | VALIDATE_UNENHANCED</code>.
0214:             */
0215:            public void setValidate(int validate, boolean on) {
0216:                if (validate == VALIDATE_NONE)
0217:                    _validate = validate;
0218:                else if (on)
0219:                    _validate |= validate;
0220:                else
0221:                    _validate &= ~validate;
0222:            }
0223:
0224:            /**
0225:             * The metadata resolution mode. Defaults to
0226:             * <code>MODE_META | MODE_MAPPING</code>.
0227:             */
0228:            public int getResolve() {
0229:                return _resMode;
0230:            }
0231:
0232:            /**
0233:             * The metadata resolution mode. Defaults to
0234:             * <code>MODE_META | MODE_MAPPING</code>.
0235:             */
0236:            public void setResolve(int mode) {
0237:                _resMode = mode;
0238:            }
0239:
0240:            /**
0241:             * The metadata resolution mode. Defaults to
0242:             * <code>MODE_META | MODE_MAPPING</code>.
0243:             */
0244:            public void setResolve(int mode, boolean on) {
0245:                if (mode == MODE_NONE)
0246:                    _resMode = mode;
0247:                else if (on)
0248:                    _resMode |= mode;
0249:                else
0250:                    _resMode &= ~mode;
0251:            }
0252:
0253:            /**
0254:             * The source mode determining what metadata to load. Defaults to
0255:             * <code>MODE_META | MODE_MAPPING | MODE_QUERY</code>.
0256:             */
0257:            public int getSourceMode() {
0258:                return _sourceMode;
0259:            }
0260:
0261:            /**
0262:             * The source mode determining what metadata to load. Defaults to
0263:             * <code>MODE_META | MODE_MAPPING | MODE_QUERY</code>.
0264:             */
0265:            public void setSourceMode(int mode) {
0266:                _sourceMode = mode;
0267:            }
0268:
0269:            /**
0270:             * The source mode determining what metadata to load. Defaults to
0271:             * <code>MODE_META | MODE_MAPPING | MODE_QUERY</code>.
0272:             */
0273:            public void setSourceMode(int mode, boolean on) {
0274:                if (mode == MODE_NONE)
0275:                    _sourceMode = mode;
0276:                else if (on)
0277:                    _sourceMode |= mode;
0278:                else
0279:                    _sourceMode &= ~mode;
0280:            }
0281:
0282:            /**
0283:             * Return the metadata for the given class.
0284:             *
0285:             * @param cls the class to retrieve metadata for
0286:             * @param envLoader the environmental class loader, if any
0287:             * @param mustExist if true, throws a {@link MetaDataException}
0288:             * if no metadata is found
0289:             */
0290:            public synchronized ClassMetaData getMetaData(Class cls,
0291:                    ClassLoader envLoader, boolean mustExist) {
0292:                if (cls != null
0293:                        && DynamicPersistenceCapable.class
0294:                                .isAssignableFrom(cls))
0295:                    cls = cls.getSuperclass();
0296:
0297:                // if cls is a generated interface, use the user interface
0298:                // to locate metadata
0299:                if (cls != null && _implGen.isImplType(cls))
0300:                    cls = _implGen.toManagedInterface(cls);
0301:
0302:                ClassMetaData meta = getMetaDataInternal(cls, envLoader);
0303:                if (meta == null && mustExist) {
0304:                    if (cls != null && !ImplHelper.isManagedType(_conf, cls))
0305:                        throw new MetaDataException(_loc.get("no-meta-notpc",
0306:                                cls)).setFatal(false);
0307:
0308:                    Set pcNames = getPersistentTypeNames(false, envLoader);
0309:                    if (pcNames != null && pcNames.size() > 0)
0310:                        throw new MetaDataException(_loc.get("no-meta-types",
0311:                                cls, pcNames));
0312:
0313:                    throw new MetaDataException(_loc.get("no-meta", cls));
0314:                }
0315:                resolve(meta);
0316:                return meta;
0317:            }
0318:
0319:            /**
0320:             * Return the metadata for the given alias name.
0321:             *
0322:             * @param alias the alias to class to retrieve metadata for
0323:             * @param envLoader the environmental class loader, if any
0324:             * @param mustExist if true, throws a {@link MetaDataException}
0325:             * if no metadata is found
0326:             * @see ClassMetaData#getTypeAlias
0327:             */
0328:            public ClassMetaData getMetaData(String alias,
0329:                    ClassLoader envLoader, boolean mustExist) {
0330:                if (alias == null && mustExist)
0331:                    throw new MetaDataException(_loc.get("no-alias-meta",
0332:                            alias, _aliases));
0333:                if (alias == null)
0334:                    return null;
0335:
0336:                // check cache
0337:                processRegisteredClasses(envLoader);
0338:                List classList = (List) _aliases.get(alias);
0339:
0340:                // multiple classes may have been defined with the same alias: we
0341:                // will filter by checking against the current list of the
0342:                // persistent types and filter based on which classes are loadable
0343:                // via the current environment's ClassLoader
0344:                Set pcNames = getPersistentTypeNames(false, envLoader);
0345:                Class cls = null;
0346:                for (int i = 0; classList != null && i < classList.size(); i++) {
0347:                    Class c = (Class) classList.get(i);
0348:                    try {
0349:                        // re-load the class in the current environment loader so
0350:                        // that we can handle redeployment of the same class name
0351:                        Class nc = Class.forName(c.getName(), false, envLoader);
0352:
0353:                        // if we have specified a list of persistent clases,
0354:                        // also check to ensure that the class is in that list
0355:                        if (pcNames == null || pcNames.size() == 0
0356:                                || pcNames.contains(nc.getName())) {
0357:                            cls = nc;
0358:                            if (!classList.contains(cls))
0359:                                classList.add(cls);
0360:                            break;
0361:                        }
0362:                    } catch (Throwable t) {
0363:                        // this happens when the class is not loadable by
0364:                        // the environment class loader, so it was probably
0365:                        // listed elsewhere; also ignore linkage failures and
0366:                        // other class loading problems
0367:                    }
0368:                }
0369:                if (cls != null)
0370:                    return getMetaData(cls, envLoader, mustExist);
0371:
0372:                // maybe this is some type we've seen but just isn't valid
0373:                if (_aliases.containsKey(alias)) {
0374:                    if (mustExist)
0375:                        throwNoRegisteredAlias(alias);
0376:                    return null;
0377:                }
0378:
0379:                // record that this is an invalid type
0380:                _aliases.put(alias, null);
0381:
0382:                if (!mustExist)
0383:                    return null;
0384:                return throwNoRegisteredAlias(alias);
0385:            }
0386:
0387:            private ClassMetaData throwNoRegisteredAlias(String alias) {
0388:                String close = getClosestAliasName(alias);
0389:                if (close != null)
0390:                    throw new MetaDataException(_loc.get("no-alias-meta-hint",
0391:                            alias, _aliases, close));
0392:                else
0393:                    throw new MetaDataException(_loc.get("no-alias-meta",
0394:                            alias, _aliases));
0395:            }
0396:
0397:            /**
0398:             * @return the nearest match to the specified alias name
0399:             * @since 1.1.0
0400:             */
0401:            public String getClosestAliasName(String alias) {
0402:                Collection aliases = getAliasNames();
0403:                return StringDistance.getClosestLevenshteinDistance(alias,
0404:                        aliases);
0405:            }
0406:
0407:            /**
0408:             * @return the registered alias names
0409:             * @since 1.1.0
0410:             */
0411:            public Collection getAliasNames() {
0412:                Collection aliases = new HashSet();
0413:                synchronized (_aliases) {
0414:                    for (Iterator iter = _aliases.entrySet().iterator(); iter
0415:                            .hasNext();) {
0416:                        Map.Entry e = (Map.Entry) iter.next();
0417:                        if (e.getValue() != null)
0418:                            aliases.add(e.getKey());
0419:                    }
0420:                }
0421:                return aliases;
0422:            }
0423:
0424:            /**
0425:             * Internal method to get the metadata for the given class, without
0426:             * resolving it.
0427:             */
0428:            private ClassMetaData getMetaDataInternal(Class cls,
0429:                    ClassLoader envLoader) {
0430:                if (cls == null)
0431:                    return null;
0432:
0433:                // check cache for existing metadata, or give up if no metadata and
0434:                // our list of configured persistent types doesn't include the class
0435:                ClassMetaData meta = (ClassMetaData) _metas.get(cls);
0436:                if (meta != null
0437:                        && ((meta.getSourceMode() & MODE_META) != 0 || (_sourceMode & MODE_META) == 0))
0438:                    return meta;
0439:
0440:                // if runtime, cut off search if not in pc list.  we don't do this at
0441:                // dev time so that user can manipulate persistent classes he's writing
0442:                // before adding them to the list
0443:                if ((_validate & VALIDATE_RUNTIME) != 0) {
0444:                    Set pcNames = getPersistentTypeNames(false, envLoader);
0445:                    if (pcNames != null && !pcNames.contains(cls.getName()))
0446:                        return meta;
0447:                }
0448:
0449:                if (meta == null) {
0450:                    // check to see if maybe we know this class has no metadata
0451:                    if (_metas.containsKey(cls))
0452:                        return null;
0453:
0454:                    // make sure this isn't an obviously bad class
0455:                    if (cls.isPrimitive() || cls.getName().startsWith("java.")
0456:                            || cls == PersistenceCapable.class)
0457:                        return null;
0458:
0459:                    // designed to get around jikes 1.17 / JDK1.5 issue where static
0460:                    // initializers are not invoked when a class is referenced, so the
0461:                    // class never registers itself with the system
0462:                    if ((_validate & VALIDATE_RUNTIME) != 0) {
0463:                        try {
0464:                            Class
0465:                                    .forName(
0466:                                            cls.getName(),
0467:                                            true,
0468:                                            (ClassLoader) AccessController
0469:                                                    .doPrivileged(J2DoPrivHelper
0470:                                                            .getClassLoaderAction(cls)));
0471:                        } catch (Throwable t) {
0472:                        }
0473:                    }
0474:                }
0475:
0476:                // not in cache: load metadata or mappings depending on source mode.
0477:                // loading metadata might also load mappings, but doesn't have to
0478:                int mode = 0;
0479:                if ((_sourceMode & MODE_META) != 0)
0480:                    mode = _sourceMode & ~MODE_MAPPING;
0481:                else if ((_sourceMode & MODE_MAPPING) == 0)
0482:                    mode = _sourceMode;
0483:                if (mode != MODE_NONE) {
0484:                    if (_log.isTraceEnabled())
0485:                        _log.trace(_loc
0486:                                .get("load-cls", cls, toModeString(mode)));
0487:                    _factory.load(cls, mode, envLoader);
0488:                }
0489:
0490:                // check cache again
0491:                if (meta == null)
0492:                    meta = (ClassMetaData) _metas.get(cls);
0493:                if (meta != null
0494:                        && ((meta.getSourceMode() & MODE_META) != 0 || (_sourceMode & MODE_META) == 0))
0495:                    return meta;
0496:
0497:                // record that this class has no metadata; checking for this later
0498:                // speeds things up in environments with slow class loading
0499:                // like appservers
0500:                if (meta != null)
0501:                    removeMetaData(meta);
0502:                _metas.put(cls, null);
0503:                return null;
0504:            }
0505:
0506:            /**
0507:             * Return a string representation of the given mode flags.
0508:             */
0509:            private static String toModeString(int mode) {
0510:                StringBuffer buf = new StringBuffer(31);
0511:                if ((mode & MODE_META) != 0)
0512:                    buf.append("[META]");
0513:                if ((mode & MODE_QUERY) != 0)
0514:                    buf.append("[QUERY]");
0515:                if ((mode & MODE_MAPPING) != 0)
0516:                    buf.append("[MAPPING]");
0517:                if ((mode & MODE_MAPPING_INIT) != 0)
0518:                    buf.append("[MAPPING_INIT]");
0519:                return buf.toString();
0520:            }
0521:
0522:            /**
0523:             * Prepare metadata for mapping resolution. This method might map parts
0524:             * of the metadata that don't rely on other classes being mapped, but that
0525:             * other classes might rely on during their own mapping (for example,
0526:             * primary key fields). By default, this method only calls
0527:             * {@link ClassMetaData#defineSuperclassFields}.
0528:             */
0529:            protected void prepareMapping(ClassMetaData meta) {
0530:                meta.defineSuperclassFields(false);
0531:            }
0532:
0533:            /**
0534:             * Resolve the given metadata if needed. There are three goals:
0535:             * <ol>
0536:             * <li>Make sure no unresolved metadata gets back to the client.</li>
0537:             * <li>Avoid infinite reentrant calls for mutually-dependent metadatas by
0538:             * allowing unresolved metadata to be returned to other metadatas.</li>
0539:             * <li>Always make sure the superclass metadata is resolved before the
0540:             * subclass metadata so that the subclass can access the super's list
0541:             * of fields.</li>
0542:             * </ol> Note that the code calling this method is synchronized, so this
0543:             * method doesn't have to be.
0544:             */
0545:            private void resolve(ClassMetaData meta) {
0546:                // return anything that has its metadata resolved, because that means
0547:                // it is either fully resolved or must at least be in the process of
0548:                // resolving mapping, etc since we do that right after meta resolve
0549:                if (meta == null || _resMode == MODE_NONE
0550:                        || (meta.getResolve() & MODE_META) != 0)
0551:                    return;
0552:
0553:                // resolve metadata
0554:                List resolved = resolveMeta(meta);
0555:                if (resolved == null)
0556:                    return;
0557:
0558:                // load mapping data
0559:                for (int i = 0; i < resolved.size(); i++)
0560:                    loadMapping((ClassMetaData) resolved.get(i));
0561:                for (int i = 0; i < resolved.size(); i++)
0562:                    preMapping((ClassMetaData) resolved.get(i));
0563:
0564:                // resolve mappings
0565:                boolean err = true;
0566:                if ((_resMode & MODE_MAPPING) != 0)
0567:                    for (int i = 0; i < resolved.size(); i++)
0568:                        err &= resolveMapping((ClassMetaData) resolved.get(i));
0569:
0570:                // throw errors encountered
0571:                if (err && !_errs.isEmpty()) {
0572:                    RuntimeException re;
0573:                    if (_errs.size() == 1)
0574:                        re = (RuntimeException) _errs.get(0);
0575:                    else
0576:                        re = new MetaDataException(_loc.get("resolve-errs"))
0577:                                .setNestedThrowables((Throwable[]) _errs
0578:                                        .toArray(new Exception[_errs.size()]));
0579:                    _errs.clear();
0580:                    throw re;
0581:                }
0582:            }
0583:
0584:            /**
0585:             * Resolve metadata mode, returning list of processed metadadatas, or null
0586:             * if we're still in the process of resolving other metadatas.
0587:             */
0588:            private List resolveMeta(ClassMetaData meta) {
0589:                if (meta.getPCSuperclass() == null) {
0590:                    // set superclass
0591:                    Class sup = meta.getDescribedType().getSuperclass();
0592:                    ClassMetaData supMeta;
0593:                    while (sup != null && sup != Object.class) {
0594:                        supMeta = getMetaData(sup, meta.getEnvClassLoader(),
0595:                                false);
0596:                        if (supMeta != null) {
0597:                            meta.setPCSuperclass(sup);
0598:                            meta.setPCSuperclassMetaData(supMeta);
0599:                            break;
0600:                        } else
0601:                            sup = sup.getSuperclass();
0602:                    }
0603:                    if (meta.getDescribedType().isInterface()) {
0604:                        Class[] sups = meta.getDescribedType().getInterfaces();
0605:                        for (int i = 0; i < sups.length; i++) {
0606:                            supMeta = getMetaData(sups[i], meta
0607:                                    .getEnvClassLoader(), false);
0608:                            if (supMeta != null) {
0609:                                meta.setPCSuperclass(sup);
0610:                                meta.setPCSuperclassMetaData(supMeta);
0611:                                break;
0612:                            }
0613:                        }
0614:                    }
0615:                    if (_log.isTraceEnabled())
0616:                        _log.trace(_loc.get("assigned-sup", meta, meta
0617:                                .getPCSuperclass()));
0618:                }
0619:
0620:                // resolve relation primary key fields for mapping dependencies
0621:                FieldMetaData[] fmds = meta.getDeclaredFields();
0622:                for (int i = 0; i < fmds.length; i++)
0623:                    if (fmds[i].isPrimaryKey())
0624:                        getMetaData(fmds[i].getDeclaredType(), meta
0625:                                .getEnvClassLoader(), false);
0626:
0627:                // resolve metadata; if we're not in the process of resolving
0628:                // others, this will return the set of interrelated metas that
0629:                // resolved
0630:                return processBuffer(meta, _resolving, MODE_META);
0631:            }
0632:
0633:            /**
0634:             * Load mapping information for the given metadata.
0635:             */
0636:            private void loadMapping(ClassMetaData meta) {
0637:                if ((meta.getResolve() & MODE_MAPPING) != 0)
0638:                    return;
0639:
0640:                // load mapping information
0641:                if ((meta.getSourceMode() & MODE_MAPPING) == 0
0642:                        && (_sourceMode & MODE_MAPPING) != 0) {
0643:                    // embedded-only metadata doesn't have mapping, so always loaded
0644:                    if (meta.isEmbeddedOnly())
0645:                        meta.setSourceMode(MODE_MAPPING, true);
0646:                    else {
0647:                        // load mapping data
0648:                        int mode = _sourceMode & ~MODE_META;
0649:                        if (_log.isTraceEnabled())
0650:                            _log.trace(_loc.get("load-mapping", meta,
0651:                                    toModeString(mode)));
0652:                        try {
0653:                            _factory.load(meta.getDescribedType(), mode, meta
0654:                                    .getEnvClassLoader());
0655:                        } catch (RuntimeException re) {
0656:                            removeMetaData(meta);
0657:                            _errs.add(re);
0658:                        }
0659:                    }
0660:                }
0661:            }
0662:
0663:            /**
0664:             * Pre-mapping preparation.
0665:             */
0666:            private void preMapping(ClassMetaData meta) {
0667:                if ((meta.getResolve() & MODE_MAPPING) != 0)
0668:                    return;
0669:
0670:                // prepare mappings for resolve; if not resolving mappings, then
0671:                // make sure any superclass fields defined in metadata are resolved
0672:                try {
0673:                    if ((_resMode & MODE_MAPPING) != 0) {
0674:                        if (_log.isTraceEnabled())
0675:                            _log.trace(_loc.get("prep-mapping", meta));
0676:                        prepareMapping(meta);
0677:                    } else
0678:                        meta.defineSuperclassFields(false);
0679:                } catch (RuntimeException re) {
0680:                    removeMetaData(meta);
0681:                    _errs.add(re);
0682:                }
0683:            }
0684:
0685:            /**
0686:             * Resolve and initialize mapping.
0687:             *
0688:             * @return false if we're still in the process of resolving mappings
0689:             */
0690:            private boolean resolveMapping(ClassMetaData meta) {
0691:                List mapped = processBuffer(meta, _mapping, MODE_MAPPING);
0692:                if (mapped == null)
0693:                    return false;
0694:
0695:                // initialize mapping for runtime use
0696:                if ((_resMode & MODE_MAPPING_INIT) != 0) {
0697:                    for (int i = 0; i < mapped.size(); i++) {
0698:                        meta = (ClassMetaData) mapped.get(i);
0699:                        try {
0700:                            meta.resolve(MODE_MAPPING_INIT);
0701:                        } catch (RuntimeException re) {
0702:                            removeMetaData(meta);
0703:                            _errs.add(re);
0704:                        }
0705:                    }
0706:                }
0707:                return true;
0708:            }
0709:
0710:            /**
0711:             * Process the given metadata and the associated buffer.
0712:             */
0713:            private List processBuffer(ClassMetaData meta, SortedSet buffer,
0714:                    int mode) {
0715:                // if we're already processing a metadata, just buffer this one; when
0716:                // the initial metadata finishes processing, we traverse the buffer
0717:                // and process all the others that were introduced during reentrant
0718:                // calls
0719:                if (!buffer.add(meta) || buffer.size() != 1)
0720:                    return null;
0721:
0722:                // continually pop a metadata and process it until we run out; note
0723:                // that each processing call might place more metas in the buffer as
0724:                // one class tries to access metadata for another; also note that the
0725:                // buffer orders itself from least to most derived
0726:                ClassMetaData buffered;
0727:                List processed = new ArrayList(5);
0728:                while (!buffer.isEmpty()) {
0729:                    buffered = (ClassMetaData) buffer.first();
0730:                    try {
0731:                        buffered.resolve(mode);
0732:                        processed.add(buffered);
0733:                        buffer.remove(buffered);
0734:                    } catch (RuntimeException re) {
0735:                        _errs.add(re);
0736:
0737:                        // any exception during resolution of one type means we can't
0738:                        // resolve any of the related types, so clear buffer.  this also
0739:                        // ensures that if two types relate to each other and one
0740:                        // dies, we don't get into infinite cycles
0741:                        for (Iterator itr = buffer.iterator(); itr.hasNext();) {
0742:                            meta = (ClassMetaData) itr.next();
0743:                            removeMetaData(meta);
0744:                            if (meta != buffered) {
0745:                                _errs.add(new MetaDataException(_loc.get(
0746:                                        "prev-errs", meta, buffered)));
0747:                            }
0748:                        }
0749:                        buffer.clear();
0750:                    }
0751:                }
0752:                return processed;
0753:            }
0754:
0755:            /**
0756:             * Return all the metadata instances currently in the repository.
0757:             */
0758:            public synchronized ClassMetaData[] getMetaDatas() {
0759:                // prevent concurrent mod errors when resolving one metadata
0760:                // introduces others
0761:                ClassMetaData[] metas = (ClassMetaData[]) _metas.values()
0762:                        .toArray(new ClassMetaData[_metas.size()]);
0763:                for (int i = 0; i < metas.length; i++)
0764:                    if (metas[i] != null)
0765:                        getMetaData(metas[i].getDescribedType(), metas[i]
0766:                                .getEnvClassLoader(), true);
0767:
0768:                List resolved = new ArrayList(_metas.size());
0769:                ClassMetaData meta;
0770:                for (Iterator itr = _metas.values().iterator(); itr.hasNext();) {
0771:                    meta = (ClassMetaData) itr.next();
0772:                    if (meta != null)
0773:                        resolved.add(meta);
0774:                }
0775:                metas = (ClassMetaData[]) resolved
0776:                        .toArray(newClassMetaDataArray(resolved.size()));
0777:                Arrays.sort(metas);
0778:                return metas;
0779:            }
0780:
0781:            /**
0782:             * Return the cached metadata for the given class, without any resolution.
0783:             * Return null if none.
0784:             */
0785:            public ClassMetaData getCachedMetaData(Class cls) {
0786:                return (ClassMetaData) _metas.get(cls);
0787:            }
0788:
0789:            /**
0790:             * Create a new metadata, populate it with default information, add it to
0791:             * the repository, and return it. Use the default access type.
0792:             */
0793:            public ClassMetaData addMetaData(Class cls) {
0794:                return addMetaData(cls, ClassMetaData.ACCESS_UNKNOWN);
0795:            }
0796:
0797:            /**
0798:             * Create a new metadata, populate it with default information, add it to
0799:             * the repository, and return it.
0800:             *
0801:             * @param access the access type to use in populating metadata
0802:             */
0803:            public ClassMetaData addMetaData(Class cls, int access) {
0804:                if (cls == null || cls.isPrimitive())
0805:                    return null;
0806:
0807:                ClassMetaData meta = newClassMetaData(cls);
0808:                _factory.getDefaults().populate(meta, access);
0809:
0810:                // synchronize on this rather than the map, because all other methods
0811:                // that access _metas are synchronized on this
0812:                synchronized (this ) {
0813:                    if (_pawares.containsKey(cls))
0814:                        throw new MetaDataException(_loc.get("pc-and-aware",
0815:                                cls));
0816:                    _metas.put(cls, meta);
0817:                }
0818:                return meta;
0819:            }
0820:
0821:            /**
0822:             * Create a new class metadata instance.
0823:             */
0824:            protected ClassMetaData newClassMetaData(Class type) {
0825:                return new ClassMetaData(type, this );
0826:            }
0827:
0828:            /**
0829:             * Create a new array of the proper class metadata subclass.
0830:             */
0831:            protected ClassMetaData[] newClassMetaDataArray(int length) {
0832:                return new ClassMetaData[length];
0833:            }
0834:
0835:            /**
0836:             * Create a new field metadata instance.
0837:             */
0838:            protected FieldMetaData newFieldMetaData(String name, Class type,
0839:                    ClassMetaData owner) {
0840:                return new FieldMetaData(name, type, owner);
0841:            }
0842:
0843:            /**
0844:             * Create a new array of the proper field metadata subclass.
0845:             */
0846:            protected FieldMetaData[] newFieldMetaDataArray(int length) {
0847:                return new FieldMetaData[length];
0848:            }
0849:
0850:            /**
0851:             * Create a new array of the proper xml class metadata subclass.
0852:             */
0853:            protected XMLMetaData[] newXMLClassMetaDataArray(int length) {
0854:                return new XMLClassMetaData[length];
0855:            }
0856:
0857:            /**
0858:             * Create a new embedded class metadata instance.
0859:             */
0860:            protected ClassMetaData newEmbeddedClassMetaData(ValueMetaData owner) {
0861:                return new ClassMetaData(owner);
0862:            }
0863:
0864:            /**
0865:             * Create a new value metadata instance.
0866:             */
0867:            protected ValueMetaData newValueMetaData(FieldMetaData owner) {
0868:                return new ValueMetaDataImpl(owner);
0869:            }
0870:
0871:            /**
0872:             * Create an {@link Order} for the given field and declaration. This
0873:             * method delegates to {@link #newRelatedFieldOrder} and
0874:             * {@link #newValueFieldOrder} by default.
0875:             */
0876:            protected Order newOrder(FieldMetaData owner, String name,
0877:                    boolean asc) {
0878:                // paths can start with (or equal) '#element'
0879:                if (name.startsWith(Order.ELEMENT))
0880:                    name = name.substring(Order.ELEMENT.length());
0881:                if (name.length() == 0)
0882:                    return newValueOrder(owner, asc);
0883:
0884:                // next token should be '.'
0885:                if (name.charAt(0) == '.')
0886:                    name = name.substring(1);
0887:
0888:                // related field
0889:                ClassMetaData meta = owner.getElement().getTypeMetaData();
0890:                if (meta == null)
0891:                    throw new MetaDataException(_loc.get(
0892:                            "nonpc-field-orderable", owner, name));
0893:                FieldMetaData rel = meta.getField(name);
0894:                if (rel == null)
0895:                    throw new MetaDataException(_loc.get("bad-field-orderable",
0896:                            owner, name));
0897:                return newRelatedFieldOrder(owner, rel, asc);
0898:            }
0899:
0900:            /**
0901:             * Order by the field value.
0902:             */
0903:            protected Order newValueOrder(FieldMetaData owner, boolean asc) {
0904:                return new InMemoryValueOrder(asc, getConfiguration());
0905:            }
0906:
0907:            /**
0908:             * Order by a field of the related type.
0909:             */
0910:            protected Order newRelatedFieldOrder(FieldMetaData owner,
0911:                    FieldMetaData rel, boolean asc) {
0912:                return new InMemoryRelatedFieldOrder(rel, asc,
0913:                        getConfiguration());
0914:            }
0915:
0916:            /**
0917:             * Create an array of orders of the given size.
0918:             */
0919:            protected Order[] newOrderArray(int size) {
0920:                return new Order[size];
0921:            }
0922:
0923:            /**
0924:             * Remove a metadata instance from the repository.
0925:             *
0926:             * @return true if removed, false if not in this repository
0927:             */
0928:            public boolean removeMetaData(ClassMetaData meta) {
0929:                if (meta == null)
0930:                    return false;
0931:                return removeMetaData(meta.getDescribedType());
0932:            }
0933:
0934:            /**
0935:             * Remove a metadata instance from the repository.
0936:             *
0937:             * @return true if removed, false if not in this repository
0938:             */
0939:            public synchronized boolean removeMetaData(Class cls) {
0940:                if (cls == null)
0941:                    return false;
0942:                if (_metas.remove(cls) != null) {
0943:                    Class impl = (Class) _ifaces.remove(cls);
0944:                    if (impl != null)
0945:                        _metas.remove(impl);
0946:                    return true;
0947:                }
0948:                return false;
0949:            }
0950:
0951:            /**
0952:             * Add the given metadata as declared interface implementation.
0953:             */
0954:            void addDeclaredInterfaceImpl(ClassMetaData meta, Class iface) {
0955:                synchronized (_impls) {
0956:                    Collection vals = (Collection) _impls.get(iface);
0957:
0958:                    // check to see if the superclass already declares to avoid dups
0959:                    if (vals != null) {
0960:                        ClassMetaData sup = meta.getPCSuperclassMetaData();
0961:                        for (; sup != null; sup = sup.getPCSuperclassMetaData())
0962:                            if (vals.contains(sup.getDescribedType()))
0963:                                return;
0964:                    }
0965:                    addToCollection(_impls, iface, meta.getDescribedType(),
0966:                            false);
0967:                }
0968:            }
0969:
0970:            /**
0971:             * Set the implementation for the given managed interface.
0972:             */
0973:            synchronized void setInterfaceImpl(ClassMetaData meta, Class impl) {
0974:                if (!meta.isManagedInterface())
0975:                    throw new MetaDataException(_loc.get(
0976:                            "not-managed-interface", meta, impl));
0977:                _ifaces.put(meta.getDescribedType(), impl);
0978:                addDeclaredInterfaceImpl(meta, meta.getDescribedType());
0979:                ClassMetaData sup = meta.getPCSuperclassMetaData();
0980:                while (sup != null) {
0981:                    // record superclass interface info while we can as well as we
0982:                    // will only register concrete superclass in PCRegistry
0983:                    sup.clearSubclassCache();
0984:                    addToCollection(_subs, sup.getDescribedType(), impl, true);
0985:                    sup = (ClassMetaData) sup.getPCSuperclassMetaData();
0986:                }
0987:            }
0988:
0989:            InterfaceImplGenerator getImplGenerator() {
0990:                return _implGen;
0991:            }
0992:
0993:            /**
0994:             * Return the least-derived class metadata for the given application
0995:             * identity object.
0996:             *
0997:             * @param oid the oid to get the metadata for
0998:             * @param envLoader the environmental class loader, if any
0999:             * @param mustExist if true, throws a {@link MetaDataException}
1000:             * if no metadata is found
1001:             */
1002:            public ClassMetaData getMetaData(Object oid, ClassLoader envLoader,
1003:                    boolean mustExist) {
1004:                if (oid == null && mustExist)
1005:                    throw new MetaDataException(_loc.get("no-oid-meta", oid,
1006:                            "?", _oids.toString()));
1007:                if (oid == null)
1008:                    return null;
1009:
1010:                if (oid instanceof  OpenJPAId) {
1011:                    Class cls = ((OpenJPAId) oid).getType();
1012:                    return getMetaData(cls, envLoader, mustExist);
1013:                }
1014:
1015:                // check cache
1016:                processRegisteredClasses(envLoader);
1017:                Class cls = (Class) _oids.get(oid.getClass());
1018:                if (cls != null)
1019:                    return getMetaData(cls, envLoader, mustExist);
1020:
1021:                // maybe this is some type we've seen but just isn't valid
1022:                if (_oids.containsKey(oid.getClass())) {
1023:                    if (mustExist)
1024:                        throw new MetaDataException(_loc.get("no-oid-meta",
1025:                                oid, oid.getClass(), _oids));
1026:                    return null;
1027:                }
1028:
1029:                // if still not match, register any classes that look similar to the
1030:                // oid class and check again
1031:                resolveIdentityClass(oid);
1032:                if (processRegisteredClasses(envLoader).length > 0) {
1033:                    cls = (Class) _oids.get(oid.getClass());
1034:                    if (cls != null)
1035:                        return getMetaData(cls, envLoader, mustExist);
1036:                }
1037:
1038:                // record that this is an invalid type
1039:                _oids.put(oid.getClass(), null);
1040:
1041:                if (!mustExist)
1042:                    return null;
1043:                throw new MetaDataException(_loc.get("no-oid-meta", oid, oid
1044:                        .getClass(), _oids)).setFailedObject(oid);
1045:            }
1046:
1047:            /**
1048:             * Make some guesses about the name of a target class for an
1049:             * unknown application identity class.
1050:             */
1051:            private void resolveIdentityClass(Object oid) {
1052:                if (oid == null)
1053:                    return;
1054:
1055:                Class oidClass = oid.getClass();
1056:                if (_log.isTraceEnabled())
1057:                    _log.trace(_loc.get("resolve-identity", oidClass));
1058:
1059:                ClassLoader cl = (ClassLoader) AccessController
1060:                        .doPrivileged(J2DoPrivHelper
1061:                                .getClassLoaderAction(oidClass));
1062:                String className;
1063:                while (oidClass != null && oidClass != Object.class) {
1064:                    className = oidClass.getName();
1065:
1066:                    // we take a brute-force approach: try to load all the class'
1067:                    // substrings. this will handle the following common naming cases:
1068:                    //
1069:                    //   com.company.MyClass$ID	-> com.company.MyClass
1070:                    //   com.company.MyClassId	-> com.company.MyClass
1071:                    //   com.company.MyClassOid	-> com.company.MyClass
1072:                    //   com.company.MyClassPK	-> com.company.MyClass
1073:                    //
1074:                    // this isn't the fastest thing possible, but this method will
1075:                    // only be called once per JVM per unknown app id class
1076:                    for (int i = className.length(); i > 1; i--) {
1077:                        if (className.charAt(i - 1) == '.')
1078:                            break;
1079:
1080:                        try {
1081:                            Class.forName(className.substring(0, i), true, cl);
1082:                        } catch (Exception e) {
1083:                        } // consume all exceptions
1084:                    }
1085:
1086:                    // move up the OID hierarchy
1087:                    oidClass = oidClass.getSuperclass();
1088:                }
1089:            }
1090:
1091:            /**
1092:             * Return all least-derived metadatas with some mapped assignable type that
1093:             * implement the given class.
1094:             *
1095:             * @param cls the class or interface to retrieve implementors for
1096:             * @param envLoader the environmental class loader, if any
1097:             * @param mustExist if true, throws a {@link MetaDataException}
1098:             * if no metadata is found
1099:             */
1100:            public ClassMetaData[] getImplementorMetaDatas(Class cls,
1101:                    ClassLoader envLoader, boolean mustExist) {
1102:                if (cls == null && mustExist)
1103:                    throw new MetaDataException(_loc.get("no-meta", cls));
1104:                if (cls == null)
1105:                    return EMPTY_METAS;
1106:
1107:                // get impls of given interface / abstract class
1108:                loadRegisteredClassMetaData(envLoader);
1109:                Collection vals = (Collection) _impls.get(cls);
1110:                ClassMetaData meta;
1111:                Collection mapped = null;
1112:                if (vals != null) {
1113:                    synchronized (vals) {
1114:                        for (Iterator itr = vals.iterator(); itr.hasNext();) {
1115:                            meta = getMetaData((Class) itr.next(), envLoader,
1116:                                    true);
1117:                            if (meta.isMapped()
1118:                                    || meta.getMappedPCSubclassMetaDatas().length > 0) {
1119:                                if (mapped == null)
1120:                                    mapped = new ArrayList(vals.size());
1121:                                mapped.add(meta);
1122:                            }
1123:                        }
1124:                    }
1125:                }
1126:
1127:                if (mapped == null && mustExist)
1128:                    throw new MetaDataException(_loc.get("no-meta", cls));
1129:                if (mapped == null)
1130:                    return EMPTY_METAS;
1131:                return (ClassMetaData[]) mapped
1132:                        .toArray(newClassMetaDataArray(mapped.size()));
1133:            }
1134:
1135:            /**
1136:             * Gets the metadata corresponding to the given persistence-aware class. 
1137:             * Returns null, if the given class is not registered as 
1138:             * persistence-aware.
1139:             */
1140:            public NonPersistentMetaData getPersistenceAware(Class cls) {
1141:                return (NonPersistentMetaData) _pawares.get(cls);
1142:            }
1143:
1144:            /**
1145:             * Gets all the metadatas for persistence-aware classes
1146:             * 
1147:             * @return empty array if no class has been registered as pers-aware
1148:             */
1149:            public NonPersistentMetaData[] getPersistenceAwares() {
1150:                synchronized (_pawares) {
1151:                    if (_pawares.isEmpty())
1152:                        return EMPTY_NON_PERSISTENT;
1153:                    return (NonPersistentMetaData[]) _pawares.values().toArray(
1154:                            new NonPersistentMetaData[_pawares.size()]);
1155:                }
1156:            }
1157:
1158:            /**
1159:             * Add the given class as persistence-aware.
1160:             * 
1161:             * @param cls non-null and must not alreaddy be added as persitence-capable
1162:             */
1163:            public NonPersistentMetaData addPersistenceAware(Class cls) {
1164:                if (cls == null)
1165:                    return null;
1166:                synchronized (this ) {
1167:                    if (_pawares.containsKey(cls))
1168:                        return (NonPersistentMetaData) _pawares.get(cls);
1169:                    if (getCachedMetaData(cls) != null)
1170:                        throw new MetaDataException(_loc.get("pc-and-aware",
1171:                                cls));
1172:                    NonPersistentMetaData meta = new NonPersistentMetaData(cls,
1173:                            this , NonPersistentMetaData.TYPE_PERSISTENCE_AWARE);
1174:                    _pawares.put(cls, meta);
1175:                    return meta;
1176:                }
1177:            }
1178:
1179:            /**
1180:             * Remove a persitence-aware class from the repository
1181:             * 
1182:             * @return true if removed
1183:             */
1184:            public boolean removePersistenceAware(Class cls) {
1185:                return _pawares.remove(cls) != null;
1186:            }
1187:
1188:            /**
1189:             * Gets the metadata corresponding to the given non-mapped interface.
1190:             * Returns null, if the given interface is not registered as 
1191:             * persistence-aware.
1192:             */
1193:            public NonPersistentMetaData getNonMappedInterface(Class iface) {
1194:                return (NonPersistentMetaData) _nonMapped.get(iface);
1195:            }
1196:
1197:            /**
1198:             * Gets the corresponding metadatas for all registered, non-mapped
1199:             * interfaces
1200:             * 
1201:             * @return empty array if no non-mapped interface has been registered.
1202:             */
1203:            public NonPersistentMetaData[] getNonMappedInterfaces() {
1204:                synchronized (_nonMapped) {
1205:                    if (_nonMapped.isEmpty())
1206:                        return EMPTY_NON_PERSISTENT;
1207:                    return (NonPersistentMetaData[]) _nonMapped
1208:                            .values()
1209:                            .toArray(
1210:                                    new NonPersistentMetaData[_nonMapped.size()]);
1211:                }
1212:            }
1213:
1214:            /**
1215:             * Add the given non-mapped interface to the repository.
1216:             * 
1217:             * @param iface the non-mapped interface
1218:             */
1219:            public NonPersistentMetaData addNonMappedInterface(Class iface) {
1220:                if (iface == null)
1221:                    return null;
1222:                if (!iface.isInterface())
1223:                    throw new MetaDataException(_loc.get("not-non-mapped",
1224:                            iface));
1225:                synchronized (this ) {
1226:                    if (_nonMapped.containsKey(iface))
1227:                        return (NonPersistentMetaData) _nonMapped.get(iface);
1228:                    if (getCachedMetaData(iface) != null)
1229:                        throw new MetaDataException(_loc.get("non-mapped-pc",
1230:                                iface));
1231:                    NonPersistentMetaData meta = new NonPersistentMetaData(
1232:                            iface, this ,
1233:                            NonPersistentMetaData.TYPE_NON_MAPPED_INTERFACE);
1234:                    _nonMapped.put(iface, meta);
1235:                    return meta;
1236:                }
1237:            }
1238:
1239:            /**
1240:             * Remove a non-mapped interface from the repository
1241:             * 
1242:             * @return true if removed
1243:             */
1244:            public boolean removeNonMappedInterface(Class iface) {
1245:                return _nonMapped.remove(iface) != null;
1246:            }
1247:
1248:            /**
1249:             * Clear the cache of parsed metadata. This method also clears the
1250:             * internal {@link MetaDataFactory MetaDataFactory}'s cache.
1251:             */
1252:            public synchronized void clear() {
1253:                if (_log.isTraceEnabled())
1254:                    _log.trace(_loc.get("clear-repos", this ));
1255:
1256:                _metas.clear();
1257:                _oids.clear();
1258:                _subs.clear();
1259:                _impls.clear();
1260:                _queries.clear();
1261:                _seqs.clear();
1262:                _registered.clear();
1263:                _factory.clear();
1264:                _aliases.clear();
1265:                _pawares.clear();
1266:                _nonMapped.clear();
1267:            }
1268:
1269:            /**
1270:             * Return the set of configured persistent classes, or null if the user
1271:             * did not configure any.
1272:             *
1273:             * @param devpath if true, search for metadata files in directories
1274:             * in the classpath if no classes are configured explicitly
1275:             * @param envLoader the class loader to use, or null for default
1276:             */
1277:            public synchronized Set getPersistentTypeNames(boolean devpath,
1278:                    ClassLoader envLoader) {
1279:                return _factory.getPersistentTypeNames(devpath, envLoader);
1280:            }
1281:
1282:            /**
1283:             * Load the persistent classes named in configuration.
1284:             * This ensures that all subclasses and application identity classes of
1285:             * each type are known in advance, without having to rely on the
1286:             * application loading the classes before performing operations that
1287:             * might involve them.
1288:             *
1289:             * @param devpath if true, search for metadata files in directories
1290:             * in the classpath if the no classes are configured explicitly
1291:             * @param envLoader the class loader to use, or null for default
1292:             * @return the loaded classes, or empty collection if none
1293:             */
1294:            public synchronized Collection loadPersistentTypes(boolean devpath,
1295:                    ClassLoader envLoader) {
1296:                Set names = getPersistentTypeNames(devpath, envLoader);
1297:                if (names == null || names.isEmpty())
1298:                    return Collections.EMPTY_LIST;
1299:
1300:                // attempt to load classes so that they get processed
1301:                ClassLoader clsLoader = _conf.getClassResolverInstance()
1302:                        .getClassLoader(getClass(), envLoader);
1303:                List classes = new ArrayList(names.size());
1304:                Class cls;
1305:                for (Iterator itr = names.iterator(); itr.hasNext();) {
1306:                    cls = classForName((String) itr.next(), clsLoader);
1307:                    if (cls != null) {
1308:                        classes.add(cls);
1309:
1310:                        // if the class is an interface, load its metadata to kick
1311:                        // off the impl generator
1312:                        if (cls.isInterface())
1313:                            getMetaData(cls, clsLoader, false);
1314:                    }
1315:                }
1316:                return classes;
1317:            }
1318:
1319:            /**
1320:             * Return the class for the given name, or null if not loadable.
1321:             */
1322:            private Class classForName(String name, ClassLoader loader) {
1323:                try {
1324:                    return Class.forName(name, true, loader);
1325:                } catch (Exception e) {
1326:                    if ((_validate & VALIDATE_RUNTIME) != 0) {
1327:                        if (_log.isWarnEnabled())
1328:                            _log.warn(_loc.get("bad-discover-class", name));
1329:                    } else if (_log.isInfoEnabled())
1330:                        _log.info(_loc.get("bad-discover-class", name));
1331:                    if (_log.isTraceEnabled())
1332:                        _log.trace(e);
1333:                } catch (NoSuchMethodError nsme) {
1334:                    if (nsme.getMessage().indexOf(".pc") == -1)
1335:                        throw nsme;
1336:
1337:                    // if the error is about a method that uses the PersistenceCapable
1338:                    // 'pc' method prefix, perform some logging and continue. This
1339:                    // probably just means that the class is not yet enhanced.
1340:                    if ((_validate & VALIDATE_RUNTIME) != 0) {
1341:                        if (_log.isWarnEnabled())
1342:                            _log.warn(_loc.get("bad-discover-class", name));
1343:                    } else if (_log.isInfoEnabled())
1344:                        _log.info(_loc.get("bad-discover-class", name));
1345:                    if (_log.isTraceEnabled())
1346:                        _log.trace(nsme);
1347:                }
1348:                return null;
1349:            }
1350:
1351:            /**
1352:             * Return all known subclasses for the given class mapping. Note
1353:             * that this method only works during runtime when the repository is
1354:             * registered as a {@link RegisterClassListener}.
1355:             */
1356:            Collection getPCSubclasses(Class cls) {
1357:                Collection subs = (Collection) _subs.get(cls);
1358:                if (subs == null)
1359:                    return Collections.EMPTY_LIST;
1360:                return subs;
1361:            }
1362:
1363:            ////////////////////////////////////////
1364:            // RegisterClassListener implementation
1365:            ////////////////////////////////////////
1366:
1367:            public void register(Class cls) {
1368:                // buffer registered classes until an oid metadata request is made,
1369:                // at which point we'll parse everything in the buffer
1370:                synchronized (_registered) {
1371:                    _registered.add(cls);
1372:                }
1373:            }
1374:
1375:            /**
1376:             * Parses the metadata for all registered classes.
1377:             */
1378:            private void loadRegisteredClassMetaData(ClassLoader envLoader) {
1379:                Class[] reg = processRegisteredClasses(envLoader);
1380:                for (int i = 0; i < reg.length; i++) {
1381:                    try {
1382:                        getMetaData(reg[i], envLoader, false);
1383:                    } catch (MetaDataException me) {
1384:                        if (_log.isWarnEnabled())
1385:                            _log.warn(me);
1386:                    }
1387:                }
1388:            }
1389:
1390:            /**
1391:             * Updates our datastructures with the latest registered classes.
1392:             */
1393:            Class[] processRegisteredClasses(ClassLoader envLoader) {
1394:                if (_registered.isEmpty())
1395:                    return EMPTY_CLASSES;
1396:
1397:                // copy into new collection to avoid concurrent mod errors on reentrant
1398:                // registrations
1399:                Class[] reg;
1400:                synchronized (_registered) {
1401:                    reg = (Class[]) _registered.toArray(new Class[_registered
1402:                            .size()]);
1403:                    _registered.clear();
1404:                }
1405:
1406:                Collection pcNames = getPersistentTypeNames(false, envLoader);
1407:                Collection failed = null;
1408:                for (int i = 0; i < reg.length; i++) {
1409:                    // don't process types that aren't listed by the user; may belong
1410:                    // to a different persistence unit
1411:                    if (pcNames != null && !pcNames.isEmpty()
1412:                            && !pcNames.contains(reg[i].getName()))
1413:                        continue;
1414:
1415:                    try {
1416:                        processRegisteredClass(reg[i]);
1417:                    } catch (Throwable t) {
1418:                        if (!_conf.getRetryClassRegistration())
1419:                            throw new MetaDataException(_loc.get(
1420:                                    "error-registered", reg[i]), t);
1421:
1422:                        if (_log.isWarnEnabled())
1423:                            _log.warn(_loc.get("failed-registered", reg[i]), t);
1424:                        if (failed == null)
1425:                            failed = new ArrayList();
1426:                        failed.add(reg[i]);
1427:                    }
1428:                }
1429:                if (failed != null) {
1430:                    synchronized (_registered) {
1431:                        _registered.addAll(failed);
1432:                    }
1433:                }
1434:                return reg;
1435:            }
1436:
1437:            /**
1438:             * Updates our datastructures with the given registered class.
1439:             * Relies on the fact that a child class cannot register itself without
1440:             * also registering its parent class by specifying its persistence
1441:             * capable superclass in the registration event.
1442:             */
1443:            private void processRegisteredClass(Class cls) {
1444:                if (_log.isTraceEnabled())
1445:                    _log.trace(_loc.get("process-registered", cls));
1446:
1447:                // update subclass lists; synchronize on this because accessing _metas
1448:                // requires it
1449:                Class leastDerived = cls;
1450:                synchronized (this ) {
1451:                    ClassMetaData meta;
1452:                    for (Class anc = cls; (anc = PCRegistry
1453:                            .getPersistentSuperclass(anc)) != null;) {
1454:                        addToCollection(_subs, anc, cls, true);
1455:                        meta = (ClassMetaData) _metas.get(anc);
1456:                        if (meta != null)
1457:                            meta.clearSubclassCache();
1458:                        leastDerived = anc;
1459:                    }
1460:                }
1461:
1462:                // update oid mappings if this is a base concrete class
1463:                Object oid = null;
1464:                try {
1465:                    oid = PCRegistry.newObjectId(cls);
1466:                } catch (InternalException ie) {
1467:                    // thrown for single field identity with null pk field value
1468:                }
1469:                if (oid != null) {
1470:                    Class existing = (Class) _oids.get(oid.getClass());
1471:                    if (existing != null) {
1472:                        // if there is already a class for this OID, then we know
1473:                        // that multiple classes are using the same OID: therefore,
1474:                        // put the least derived PC superclass into the map. This
1475:                        // gets around the problem of an abstract PC superclass
1476:                        // using application identity (since newObjectId
1477:                        // will return null for abstract classes).
1478:                        Class sup = cls;
1479:                        while (PCRegistry.getPersistentSuperclass(sup) != null)
1480:                            sup = PCRegistry.getPersistentSuperclass(sup);
1481:
1482:                        _oids.put(oid.getClass(), sup);
1483:                    } else if (existing == null
1484:                            || cls.isAssignableFrom(existing))
1485:                        _oids.put(oid.getClass(), cls);
1486:                }
1487:
1488:                // update mappings from interfaces and non-pc superclasses to
1489:                // pc implementing types
1490:                synchronized (_impls) {
1491:                    updateImpls(cls, leastDerived, cls);
1492:                }
1493:
1494:                // set alias for class
1495:                String alias = PCRegistry.getTypeAlias(cls);
1496:                if (alias != null) {
1497:                    synchronized (_aliases) {
1498:                        List classList = (List) _aliases.get(alias);
1499:                        if (classList == null) {
1500:                            classList = new ArrayList(3);
1501:                            _aliases.put(alias, classList);
1502:                        }
1503:                        if (!classList.contains(cls))
1504:                            classList.add(cls);
1505:                    }
1506:                }
1507:            }
1508:
1509:            /**
1510:             * Update the list of implementations of base classes and interfaces.
1511:             */
1512:            private void updateImpls(Class cls, Class leastDerived, Class check) {
1513:                // allow users to query on common non-pc superclasses
1514:                Class sup = check.getSuperclass();
1515:                if (leastDerived == cls && sup != null && sup != Object.class) {
1516:                    addToCollection(_impls, sup, cls, false);
1517:                    updateImpls(cls, leastDerived, sup);
1518:                }
1519:
1520:                // allow users to query on any implemented interfaces unless defaults 
1521:                // say the user must implement persistent interfaces explicitly in meta
1522:                if (!_factory.getDefaults().isDeclaredInterfacePersistent())
1523:                    return;
1524:                Class[] ints = check.getInterfaces();
1525:                for (int i = 0; i < ints.length; i++) {
1526:                    // don't map java-standard interfaces
1527:                    if (ints[i].getName().startsWith("java."))
1528:                        continue;
1529:
1530:                    // only map least-derived interface implementors
1531:                    if (leastDerived == cls || isLeastDerivedImpl(ints[i], cls)) {
1532:                        addToCollection(_impls, ints[i], cls, false);
1533:                        updateImpls(cls, leastDerived, ints[i]);
1534:                    }
1535:                }
1536:            }
1537:
1538:            /**
1539:             * Return true if the given class is the least-derived persistent
1540:             * implementor of the given interface, false otherwise.
1541:             */
1542:            private boolean isLeastDerivedImpl(Class inter, Class cls) {
1543:                Class parent = PCRegistry.getPersistentSuperclass(cls);
1544:                while (parent != null) {
1545:                    if (Arrays.asList(parent.getInterfaces()).contains(inter))
1546:                        return false;
1547:                    parent = PCRegistry.getPersistentSuperclass(parent);
1548:                }
1549:                return true;
1550:            }
1551:
1552:            /**
1553:             * Add the given value to the collection cached in the given map under
1554:             * the given key.
1555:             */
1556:            private void addToCollection(Map map, Class key, Class value,
1557:                    boolean inheritance) {
1558:                synchronized (map) {
1559:                    Collection coll = (Collection) map.get(key);
1560:                    if (coll == null) {
1561:                        if (inheritance) {
1562:                            InheritanceComparator comp = new InheritanceComparator();
1563:                            comp.setBase(key);
1564:                            coll = new TreeSet(comp);
1565:                        } else
1566:                            coll = new LinkedList();
1567:                        map.put(key, coll);
1568:                    }
1569:                    coll.add(value);
1570:                }
1571:            }
1572:
1573:            ///////////////////////////////
1574:            // Configurable implementation
1575:            ///////////////////////////////
1576:
1577:            public void setConfiguration(Configuration conf) {
1578:                _conf = (OpenJPAConfiguration) conf;
1579:                _log = _conf.getLog(OpenJPAConfiguration.LOG_METADATA);
1580:            }
1581:
1582:            public void startConfiguration() {
1583:            }
1584:
1585:            public void endConfiguration() {
1586:                initializeMetaDataFactory();
1587:                if (_implGen == null)
1588:                    _implGen = new InterfaceImplGenerator(this );
1589:            }
1590:
1591:            private void initializeMetaDataFactory() {
1592:                if (_factory == null) {
1593:                    MetaDataFactory mdf = _conf.newMetaDataFactoryInstance();
1594:                    if (mdf == null)
1595:                        throw new MetaDataException(_loc
1596:                                .get("no-metadatafactory"));
1597:                    setMetaDataFactory(mdf);
1598:                }
1599:            }
1600:
1601:            //////////////////
1602:            // Query metadata
1603:            //////////////////
1604:
1605:            /**
1606:             * Return query metadata for the given class, name, and classloader.
1607:             */
1608:            public synchronized QueryMetaData getQueryMetaData(Class cls,
1609:                    String name, ClassLoader envLoader, boolean mustExist) {
1610:                QueryMetaData meta = getQueryMetaDataInternal(cls, name,
1611:                        envLoader);
1612:                if (meta == null) {
1613:                    // load all the metadatas for all the known classes so that
1614:                    // query names are seen and registered
1615:                    resolveAll(envLoader);
1616:                    meta = getQueryMetaDataInternal(cls, name, envLoader);
1617:                }
1618:
1619:                if (meta == null && mustExist) {
1620:                    if (cls == null) {
1621:                        throw new MetaDataException(_loc.get(
1622:                                "no-named-query-null-class",
1623:                                getPersistentTypeNames(false, envLoader), name));
1624:                    } else {
1625:                        throw new MetaDataException(_loc.get("no-named-query",
1626:                                cls, name));
1627:                    }
1628:                }
1629:
1630:                return meta;
1631:            }
1632:
1633:            /** 
1634:             * Resolve all known metadata classes. 
1635:             */
1636:            private void resolveAll(ClassLoader envLoader) {
1637:                Collection types = loadPersistentTypes(false, envLoader);
1638:                for (Iterator i = types.iterator(); i.hasNext();) {
1639:                    Class c = (Class) i.next();
1640:                    getMetaData(c, envLoader, false);
1641:                }
1642:            }
1643:
1644:            /**
1645:             * Return query metadata for the given class, name, and classloader.
1646:             */
1647:            private QueryMetaData getQueryMetaDataInternal(Class cls,
1648:                    String name, ClassLoader envLoader) {
1649:                if (name == null)
1650:                    return null;
1651:
1652:                // check cache
1653:                Object key = getQueryKey(cls, name);
1654:                QueryMetaData qm = (QueryMetaData) _queries.get(key);
1655:                if (qm != null)
1656:                    return qm;
1657:
1658:                // get metadata for class, which will find queries in metadata file
1659:                if (cls != null && getMetaData(cls, envLoader, false) != null) {
1660:                    qm = (QueryMetaData) _queries.get(key);
1661:                    if (qm != null)
1662:                        return qm;
1663:                }
1664:                if ((_sourceMode & MODE_QUERY) == 0)
1665:                    return null;
1666:
1667:                // see if factory can figure out a scope for this query
1668:                if (cls == null)
1669:                    cls = _factory.getQueryScope(name, envLoader);
1670:
1671:                // not in cache; load
1672:                _factory.load(cls, MODE_QUERY, envLoader);
1673:                return (QueryMetaData) _queries.get(key);
1674:            }
1675:
1676:            /**
1677:             * Return the cached query metadata.
1678:             */
1679:            public synchronized QueryMetaData[] getQueryMetaDatas() {
1680:                return (QueryMetaData[]) _queries.values().toArray(
1681:                        new QueryMetaData[_queries.size()]);
1682:            }
1683:
1684:            /**
1685:             * Return the cached query metadata for the given name.
1686:             */
1687:            public synchronized QueryMetaData getCachedQueryMetaData(Class cls,
1688:                    String name) {
1689:                return (QueryMetaData) _queries.get(getQueryKey(cls, name));
1690:            }
1691:
1692:            /**
1693:             * Add a new query metadata to the repository and return it.
1694:             */
1695:            public synchronized QueryMetaData addQueryMetaData(Class cls,
1696:                    String name) {
1697:                QueryMetaData meta = newQueryMetaData(cls, name);
1698:                _queries.put(getQueryKey(meta), meta);
1699:                return meta;
1700:            }
1701:
1702:            /**
1703:             * Create a new query metadata instance.
1704:             */
1705:            protected QueryMetaData newQueryMetaData(Class cls, String name) {
1706:                QueryMetaData meta = new QueryMetaData(name);
1707:                meta.setDefiningType(cls);
1708:                return meta;
1709:            }
1710:
1711:            /**
1712:             * Remove the given query metadata from the repository.
1713:             */
1714:            public synchronized boolean removeQueryMetaData(QueryMetaData meta) {
1715:                if (meta == null)
1716:                    return false;
1717:                return _queries.remove(getQueryKey(meta)) != null;
1718:            }
1719:
1720:            /**
1721:             * Remove query metadata for the given class name if in the repository.
1722:             */
1723:            public synchronized boolean removeQueryMetaData(Class cls,
1724:                    String name) {
1725:                if (name == null)
1726:                    return false;
1727:                return _queries.remove(getQueryKey(cls, name)) != null;
1728:            }
1729:
1730:            /**
1731:             * Return a unique key for a given QueryMetaData.
1732:             */
1733:            private static Object getQueryKey(QueryMetaData meta) {
1734:                if (meta == null)
1735:                    return null;
1736:                return getQueryKey(meta.getDefiningType(), meta.getName());
1737:            }
1738:
1739:            /**
1740:             * Return a unique key for a given class / name. The class
1741:             * argument can be null.
1742:             */
1743:            protected static Object getQueryKey(Class cls, String name) {
1744:                if (cls == null)
1745:                    return name;
1746:                QueryKey key = new QueryKey();
1747:                key.clsName = cls.getName();
1748:                key.name = name;
1749:                return key;
1750:            }
1751:
1752:            /////////////////////
1753:            // Sequence metadata
1754:            /////////////////////
1755:
1756:            /**
1757:             * Return sequence metadata for the given name and classloader.
1758:             */
1759:            public synchronized SequenceMetaData getSequenceMetaData(
1760:                    String name, ClassLoader envLoader, boolean mustExist) {
1761:                SequenceMetaData meta = getSequenceMetaDataInternal(name,
1762:                        envLoader);
1763:                if (meta == null && SequenceMetaData.NAME_SYSTEM.equals(name)) {
1764:                    if (_sysSeq == null)
1765:                        _sysSeq = newSequenceMetaData(name);
1766:                    return _sysSeq;
1767:                }
1768:                if (meta == null && mustExist)
1769:                    throw new MetaDataException(_loc.get("no-named-sequence",
1770:                            name));
1771:                return meta;
1772:            }
1773:
1774:            /**
1775:             * Used internally by metadata to retrieve sequence metadatas based on
1776:             * possibly-unqualified sequence name.
1777:             */
1778:            SequenceMetaData getSequenceMetaData(ClassMetaData context,
1779:                    String name, boolean mustExist) {
1780:                // try with given name
1781:                MetaDataException e = null;
1782:                try {
1783:                    SequenceMetaData seq = getSequenceMetaData(name, context
1784:                            .getEnvClassLoader(), mustExist);
1785:                    if (seq != null)
1786:                        return seq;
1787:                } catch (MetaDataException mde) {
1788:                    e = mde;
1789:                }
1790:
1791:                // if given name already fully qualified, give up
1792:                if (name.indexOf('.') != -1) {
1793:                    if (e != null)
1794:                        throw e;
1795:                    return null;
1796:                }
1797:
1798:                // try with qualified name
1799:                name = Strings.getPackageName(context.getDescribedType()) + "."
1800:                        + name;
1801:                try {
1802:                    return getSequenceMetaData(name, context
1803:                            .getEnvClassLoader(), mustExist);
1804:                } catch (MetaDataException mde) {
1805:                    // throw original exception
1806:                    if (e != null)
1807:                        throw e;
1808:                    throw mde;
1809:                }
1810:            }
1811:
1812:            /**
1813:             * Return sequence metadata for the given name and classloader.
1814:             */
1815:            private SequenceMetaData getSequenceMetaDataInternal(String name,
1816:                    ClassLoader envLoader) {
1817:                if (name == null)
1818:                    return null;
1819:
1820:                // check cache
1821:                SequenceMetaData meta = (SequenceMetaData) _seqs.get(name);
1822:                if (meta == null) {
1823:                    // load metadata for registered classes to hopefully find sequence
1824:                    // definition
1825:                    loadRegisteredClassMetaData(envLoader);
1826:                    meta = (SequenceMetaData) _seqs.get(name);
1827:                }
1828:                return meta;
1829:            }
1830:
1831:            /**
1832:             * Return the cached sequence metadata.
1833:             */
1834:            public synchronized SequenceMetaData[] getSequenceMetaDatas() {
1835:                return (SequenceMetaData[]) _seqs.values().toArray(
1836:                        new SequenceMetaData[_seqs.size()]);
1837:            }
1838:
1839:            /**
1840:             * Return the cached a sequence metadata for the given name.
1841:             */
1842:            public synchronized SequenceMetaData getCachedSequenceMetaData(
1843:                    String name) {
1844:                return (SequenceMetaData) _seqs.get(name);
1845:            }
1846:
1847:            /**
1848:             * Add a new sequence metadata to the repository and return it.
1849:             */
1850:            public synchronized SequenceMetaData addSequenceMetaData(String name) {
1851:                SequenceMetaData meta = newSequenceMetaData(name);
1852:                _seqs.put(name, meta);
1853:                return meta;
1854:            }
1855:
1856:            /**
1857:             * Create a new sequence metadata instance.
1858:             */
1859:            protected SequenceMetaData newSequenceMetaData(String name) {
1860:                return new SequenceMetaData(name, this );
1861:            }
1862:
1863:            /**
1864:             * Remove the given sequence metadata from the repository.
1865:             */
1866:            public synchronized boolean removeSequenceMetaData(
1867:                    SequenceMetaData meta) {
1868:                if (meta == null)
1869:                    return false;
1870:                return _seqs.remove(meta.getName()) != null;
1871:            }
1872:
1873:            /**
1874:             * Remove sequence metadata for the name if in the repository.
1875:             */
1876:            public synchronized boolean removeSequenceMetaData(String name) {
1877:                if (name == null)
1878:                    return false;
1879:                return _seqs.remove(name) != null;
1880:            }
1881:
1882:            /**
1883:             * Add the given system lifecycle listener.
1884:             */
1885:            public synchronized void addSystemListener(Object listener) {
1886:                // copy to avoid issues with ListenerList and avoid unncessary
1887:                // locking on the list during runtime
1888:                LifecycleEventManager.ListenerList listeners = new LifecycleEventManager.ListenerList(
1889:                        _listeners);
1890:                listeners.add(listener);
1891:                _listeners = listeners;
1892:            }
1893:
1894:            /**
1895:             * Remove the given system lifecycle listener.
1896:             */
1897:            public synchronized boolean removeSystemListener(Object listener) {
1898:                if (!_listeners.contains(listener))
1899:                    return false;
1900:
1901:                // copy to avoid issues with ListenerList and avoid unncessary
1902:                // locking on the list during runtime
1903:                LifecycleEventManager.ListenerList listeners = new LifecycleEventManager.ListenerList(
1904:                        _listeners);
1905:                listeners.remove(listener);
1906:                _listeners = listeners;
1907:                return true;
1908:            }
1909:
1910:            /**
1911:             * Return the system lifecycle listeners
1912:             */
1913:            public LifecycleEventManager.ListenerList getSystemListeners() {
1914:                return _listeners;
1915:            }
1916:
1917:            /**
1918:             * Free the resources used by this repository. Closes all user sequences.
1919:             */
1920:            public synchronized void close() {
1921:                SequenceMetaData[] smds = getSequenceMetaDatas();
1922:                for (int i = 0; i < smds.length; i++)
1923:                    smds[i].close();
1924:                clear();
1925:            }
1926:
1927:            /**
1928:             * Query key struct.
1929:             */
1930:            private static class QueryKey implements  Serializable {
1931:
1932:                public String clsName;
1933:                public String name;
1934:
1935:                public int hashCode() {
1936:                    int clsHash = (clsName == null) ? 0 : clsName.hashCode();
1937:                    int nameHash = (name == null) ? 0 : name.hashCode();
1938:                    return clsHash + nameHash;
1939:                }
1940:
1941:                public boolean equals(Object obj) {
1942:                    if (obj == this )
1943:                        return true;
1944:                    if (!(obj instanceof  QueryKey))
1945:                        return false;
1946:
1947:                    QueryKey qk = (QueryKey) obj;
1948:                    return StringUtils.equals(clsName, qk.clsName)
1949:                            && StringUtils.equals(name, qk.name);
1950:                }
1951:            }
1952:
1953:            /**
1954:             * Return XML metadata for a given field metadata
1955:             * @param fmd
1956:             * @return XML metadata
1957:             */
1958:            public synchronized XMLMetaData getXMLMetaData(FieldMetaData fmd) {
1959:                Class cls = fmd.getDeclaredType();
1960:                // check if cached before
1961:                XMLMetaData xmlmeta = (XMLClassMetaData) _xmlmetas.get(cls);
1962:                if (xmlmeta != null)
1963:                    return xmlmeta;
1964:
1965:                // load JAXB XML metadata
1966:                _factory.loadXMLMetaData(fmd);
1967:
1968:                xmlmeta = (XMLClassMetaData) _xmlmetas.get(cls);
1969:
1970:                return xmlmeta;
1971:            }
1972:
1973:            /**
1974:             * Create a new metadata, populate it with default information, add it to
1975:             * the repository, and return it.
1976:             *
1977:             * @param access the access type to use in populating metadata
1978:             */
1979:            public XMLClassMetaData addXMLMetaData(Class type, String name) {
1980:                XMLClassMetaData meta = newXMLClassMetaData(type, name);
1981:
1982:                // synchronize on this rather than the map, because all other methods
1983:                // that access _xmlmetas are synchronized on this
1984:                synchronized (this ) {
1985:                    _xmlmetas.put(type, meta);
1986:                }
1987:                return meta;
1988:            }
1989:
1990:            /**
1991:             * Return the cached XMLClassMetaData for the given class
1992:             * Return null if none.
1993:             */
1994:            public XMLMetaData getCachedXMLMetaData(Class cls) {
1995:                return (XMLMetaData) _xmlmetas.get(cls);
1996:            }
1997:
1998:            /**
1999:             * Create a new xml class metadata
2000:             * @param type
2001:             * @param name
2002:             * @return a XMLClassMetaData
2003:             */
2004:            protected XMLClassMetaData newXMLClassMetaData(Class type,
2005:                    String name) {
2006:                return new XMLClassMetaData(type, name);
2007:            }
2008:
2009:            /**
2010:             * Create a new xml field meta, add it to the fieldMap in the given 
2011:             *     xml class metadata
2012:             * @param type
2013:             * @param name
2014:             * @param meta
2015:             * @return a XMLFieldMetaData
2016:             */
2017:            public XMLFieldMetaData newXMLFieldMetaData(Class type, String name) {
2018:                return new XMLFieldMetaData(type, name);
2019:            }
2020:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.