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.persistence;
0020:
0021: import java.lang.reflect.Field;
0022: import java.lang.reflect.Member;
0023: import java.lang.reflect.Method;
0024: import java.security.AccessController;
0025: import java.security.PrivilegedActionException;
0026: import java.util.ArrayList;
0027: import java.util.Collection;
0028: import java.util.EnumSet;
0029: import java.util.HashMap;
0030: import java.util.Map;
0031: import java.util.Set;
0032: import java.util.Stack;
0033: import javax.persistence.CascadeType;
0034: import javax.persistence.GenerationType;
0035: import static javax.persistence.CascadeType.*;
0036:
0037: import org.apache.commons.lang.StringUtils;
0038: import org.xml.sax.Attributes;
0039: import org.xml.sax.SAXException;
0040: import org.apache.openjpa.conf.OpenJPAConfiguration;
0041: import org.apache.openjpa.enhance.PersistenceCapable;
0042: import org.apache.openjpa.event.BeanLifecycleCallbacks;
0043: import org.apache.openjpa.event.LifecycleCallbacks;
0044: import org.apache.openjpa.event.LifecycleEvent;
0045: import org.apache.openjpa.event.MethodLifecycleCallbacks;
0046: import org.apache.openjpa.kernel.QueryLanguages;
0047: import org.apache.openjpa.kernel.jpql.JPQLParser;
0048: import org.apache.openjpa.lib.conf.Configurations;
0049: import org.apache.openjpa.lib.log.Log;
0050: import org.apache.openjpa.lib.meta.CFMetaDataParser;
0051: import org.apache.openjpa.lib.util.J2DoPrivHelper;
0052: import org.apache.openjpa.lib.util.Localizer;
0053: import org.apache.openjpa.meta.ClassMetaData;
0054: import org.apache.openjpa.meta.DelegatingMetaDataFactory;
0055: import org.apache.openjpa.meta.FieldMetaData;
0056: import org.apache.openjpa.meta.JavaTypes;
0057: import org.apache.openjpa.meta.LifecycleMetaData;
0058: import org.apache.openjpa.meta.MetaDataDefaults;
0059: import org.apache.openjpa.meta.MetaDataFactory;
0060: import static org.apache.openjpa.meta.MetaDataModes.*;
0061: import org.apache.openjpa.meta.MetaDataRepository;
0062: import org.apache.openjpa.meta.Order;
0063: import org.apache.openjpa.meta.QueryMetaData;
0064: import org.apache.openjpa.meta.SequenceMetaData;
0065: import org.apache.openjpa.meta.ValueMetaData;
0066: import static org.apache.openjpa.persistence.MetaDataTag.*;
0067: import static org.apache.openjpa.persistence.PersistenceStrategy.*;
0068: import org.apache.openjpa.util.ImplHelper;
0069:
0070: /**
0071: * Custom SAX parser used by the system to quickly parse persistence i
0072: * metadata files.
0073: *
0074: * @author Steve Kim
0075: * @nojavadoc
0076: */
0077: public class XMLPersistenceMetaDataParser extends CFMetaDataParser
0078: implements PersistenceMetaDataFactory.Parser {
0079:
0080: // parse constants
0081: protected static final String ELEM_PKG = "package";
0082: protected static final String ELEM_ACCESS = "access";
0083: protected static final String ELEM_ATTRS = "attributes";
0084: protected static final String ELEM_LISTENER = "entity-listener";
0085: protected static final String ELEM_CASCADE = "cascade";
0086: protected static final String ELEM_CASCADE_ALL = "cascade-all";
0087: protected static final String ELEM_CASCADE_PER = "cascade-persist";
0088: protected static final String ELEM_CASCADE_MER = "cascade-merge";
0089: protected static final String ELEM_CASCADE_REM = "cascade-remove";
0090: protected static final String ELEM_CASCADE_REF = "cascade-refresh";
0091: protected static final String ELEM_PU_META = "persistence-unit-metadata";
0092: protected static final String ELEM_PU_DEF = "persistence-unit-defaults";
0093: protected static final String ELEM_XML_MAP_META_COMPLETE = "xml-mapping-metadata-complete";
0094:
0095: private static final Map<String, Object> _elems = new HashMap<String, Object>();
0096:
0097: static {
0098: _elems.put(ELEM_PKG, ELEM_PKG);
0099: _elems.put(ELEM_ACCESS, ELEM_ACCESS);
0100: _elems.put(ELEM_ATTRS, ELEM_ATTRS);
0101: _elems.put(ELEM_LISTENER, ELEM_LISTENER);
0102: _elems.put(ELEM_CASCADE, ELEM_CASCADE);
0103: _elems.put(ELEM_CASCADE_ALL, ELEM_CASCADE_ALL);
0104: _elems.put(ELEM_CASCADE_PER, ELEM_CASCADE_PER);
0105: _elems.put(ELEM_CASCADE_REM, ELEM_CASCADE_REM);
0106: _elems.put(ELEM_CASCADE_MER, ELEM_CASCADE_MER);
0107: _elems.put(ELEM_CASCADE_REF, ELEM_CASCADE_REF);
0108: _elems.put(ELEM_PU_META, ELEM_PU_META);
0109: _elems.put(ELEM_PU_DEF, ELEM_PU_DEF);
0110: _elems.put(ELEM_XML_MAP_META_COMPLETE,
0111: ELEM_XML_MAP_META_COMPLETE);
0112:
0113: _elems.put("entity-listeners", ENTITY_LISTENERS);
0114: _elems.put("pre-persist", PRE_PERSIST);
0115: _elems.put("post-persist", POST_PERSIST);
0116: _elems.put("pre-remove", PRE_REMOVE);
0117: _elems.put("post-remove", POST_REMOVE);
0118: _elems.put("pre-update", PRE_UPDATE);
0119: _elems.put("post-update", POST_UPDATE);
0120: _elems.put("post-load", POST_LOAD);
0121: _elems.put("exclude-default-listeners",
0122: EXCLUDE_DEFAULT_LISTENERS);
0123: _elems.put("exclude-superclass-listeners",
0124: EXCLUDE_SUPERCLASS_LISTENERS);
0125:
0126: _elems.put("named-query", QUERY);
0127: _elems.put("named-native-query", NATIVE_QUERY);
0128: _elems.put("query-hint", QUERY_HINT);
0129: _elems.put("query", QUERY_STRING);
0130:
0131: _elems.put("flush-mode", FLUSH_MODE);
0132: _elems.put("sequence-generator", SEQ_GENERATOR);
0133:
0134: _elems.put("id", ID);
0135: _elems.put("id-class", ID_CLASS);
0136: _elems.put("embedded-id", EMBEDDED_ID);
0137: _elems.put("version", VERSION);
0138: _elems.put("generated-value", GENERATED_VALUE);
0139: _elems.put("map-key", MAP_KEY);
0140: _elems.put("order-by", ORDER_BY);
0141: _elems.put("lob", LOB);
0142:
0143: _elems.put("basic", BASIC);
0144: _elems.put("many-to-one", MANY_ONE);
0145: _elems.put("one-to-one", ONE_ONE);
0146: _elems.put("embedded", EMBEDDED);
0147: _elems.put("one-to-many", ONE_MANY);
0148: _elems.put("many-to-many", MANY_MANY);
0149: _elems.put("transient", TRANSIENT);
0150: }
0151:
0152: private static final Localizer _loc = Localizer
0153: .forPackage(XMLPersistenceMetaDataParser.class);
0154:
0155: private final OpenJPAConfiguration _conf;
0156: private MetaDataRepository _repos = null;
0157: private AnnotationPersistenceMetaDataParser _parser = null;
0158: private ClassLoader _envLoader = null;
0159: private int _mode = MODE_NONE;
0160: private boolean _override = false;
0161:
0162: private final Stack _elements = new Stack();
0163: private final Stack _parents = new Stack();
0164:
0165: private Class _cls = null;
0166: private int _fieldPos = 0;
0167: private int _clsPos = 0;
0168: private int _access = ClassMetaData.ACCESS_UNKNOWN;
0169: private PersistenceStrategy _strategy = null;
0170: private Set<CascadeType> _cascades = null;
0171: private Set<CascadeType> _pkgCascades = null;
0172:
0173: private Class _listener = null;
0174: private Collection<LifecycleCallbacks>[] _callbacks = null;
0175: private int[] _highs = null;
0176:
0177: /**
0178: * Constructor; supply configuration.
0179: */
0180: public XMLPersistenceMetaDataParser(OpenJPAConfiguration conf) {
0181: _conf = conf;
0182: setValidating(true);
0183: setLog(conf.getLog(OpenJPAConfiguration.LOG_METADATA));
0184: setParseComments(true);
0185: setMode(MODE_META | MODE_MAPPING | MODE_QUERY);
0186: setParseText(true);
0187: }
0188:
0189: /**
0190: * Configuration supplied on construction.
0191: */
0192: public OpenJPAConfiguration getConfiguration() {
0193: return _conf;
0194: }
0195:
0196: /**
0197: * The annotation parser. When class is discovered in an XML file,
0198: * we first parse any annotations present, then override with the XML.
0199: */
0200: public AnnotationPersistenceMetaDataParser getAnnotationParser() {
0201: return _parser;
0202: }
0203:
0204: /**
0205: * The annotation parser. When class is discovered in an XML file,
0206: * we first parse any annotations present, then override with the XML.
0207: */
0208: public void setAnnotationParser(
0209: AnnotationPersistenceMetaDataParser parser) {
0210: _parser = parser;
0211: }
0212:
0213: /**
0214: * Returns the repository for this parser. If none has been set, creates
0215: * a new repository and sets it.
0216: */
0217: public MetaDataRepository getRepository() {
0218: if (_repos == null) {
0219: MetaDataRepository repos = _conf
0220: .newMetaDataRepositoryInstance();
0221: MetaDataFactory mdf = repos.getMetaDataFactory();
0222: if (mdf instanceof DelegatingMetaDataFactory)
0223: mdf = ((DelegatingMetaDataFactory) mdf)
0224: .getInnermostDelegate();
0225: if (mdf instanceof PersistenceMetaDataFactory)
0226: ((PersistenceMetaDataFactory) mdf).setXMLParser(this );
0227: _repos = repos;
0228: }
0229: return _repos;
0230: }
0231:
0232: /**
0233: * Set the metadata repository for this parser.
0234: */
0235: public void setRepository(MetaDataRepository repos) {
0236: _repos = repos;
0237: if (repos != null
0238: && (repos.getValidate() & repos.VALIDATE_RUNTIME) != 0)
0239: setParseComments(false);
0240: }
0241:
0242: /**
0243: * Return the environmental class loader to pass on to parsed
0244: * metadata instances.
0245: */
0246: public ClassLoader getEnvClassLoader() {
0247: return _envLoader;
0248: }
0249:
0250: /**
0251: * Set the environmental class loader to pass on to parsed
0252: * metadata instances.
0253: */
0254: public void setEnvClassLoader(ClassLoader loader) {
0255: _envLoader = loader;
0256: }
0257:
0258: /**
0259: * Whether to allow later parses of mapping information to override
0260: * earlier information for the same class. Defaults to false. Useful
0261: * when a tool is mapping a class, so that .jdo file partial mapping
0262: * information can be used even when mappings are stored in .orm files
0263: * or other locations.
0264: */
0265: public boolean getMappingOverride() {
0266: return _override;
0267: }
0268:
0269: /**
0270: * Whether to allow later parses of mapping information to override
0271: * earlier information for the same class. Defaults to false. Useful
0272: * when a tool is mapping a class, so that .jdo file partial mapping
0273: * information can be used even when mappings are stored in .orm files
0274: * or other locations.
0275: */
0276: public void setMappingOverride(boolean override) {
0277: _override = override;
0278: }
0279:
0280: /**
0281: * The parse mode according to the expected document type. The
0282: * mode constants act as bit flags, and therefore can be combined.
0283: */
0284: public int getMode() {
0285: return _mode;
0286: }
0287:
0288: /**
0289: * The parse mode according to the expected document type.
0290: */
0291: public void setMode(int mode, boolean on) {
0292: if (mode == MODE_NONE)
0293: setMode(MODE_NONE);
0294: else if (on)
0295: setMode(_mode | mode);
0296: else
0297: setMode(_mode & ~mode);
0298: }
0299:
0300: /**
0301: * The parse mode according to the expected document type.
0302: */
0303: public void setMode(int mode) {
0304: _mode = mode;
0305: if (_parser != null)
0306: _parser.setMode(mode);
0307: }
0308:
0309: /**
0310: * Convenience method for interpreting {@link #getMode}.
0311: */
0312: protected boolean isMetaDataMode() {
0313: return (_mode & MODE_META) != 0;
0314: }
0315:
0316: /**
0317: * Convenience method for interpreting {@link #getMode}.
0318: */
0319: protected boolean isQueryMode() {
0320: return (_mode & MODE_QUERY) != 0;
0321: }
0322:
0323: /**
0324: * Convenience method for interpreting {@link #getMode}.
0325: */
0326: protected boolean isMappingMode() {
0327: return (_mode & MODE_MAPPING) != 0;
0328: }
0329:
0330: /**
0331: * Returns true if we're in mapping mode or in metadata mode with
0332: * mapping override enabled.
0333: */
0334: protected boolean isMappingOverrideMode() {
0335: return isMappingMode() || (_override && isMetaDataMode());
0336: }
0337:
0338: ///////////////
0339: // XML parsing
0340: ///////////////
0341:
0342: /**
0343: * Push a parse element onto the stack.
0344: */
0345: protected void pushElement(Object elem) {
0346: _elements.push(elem);
0347: }
0348:
0349: /**
0350: * Pop a parse element from the stack.
0351: */
0352: protected Object popElement() {
0353: return _elements.pop();
0354: }
0355:
0356: /**
0357: * Return the current element being parsed. May be a class metadata,
0358: * field metadata, query metadata, etc.
0359: */
0360: protected Object currentElement() {
0361: if (_elements.isEmpty())
0362: return null;
0363: return _elements.peek();
0364: }
0365:
0366: /**
0367: * Return the current {@link PersistenceStrategy} if any.
0368: */
0369: protected PersistenceStrategy currentStrategy() {
0370: return _strategy;
0371: }
0372:
0373: /**
0374: * Return the tag of the current parent element.
0375: */
0376: protected Object currentParent() {
0377: if (_parents.isEmpty())
0378: return null;
0379: return _parents.peek();
0380: }
0381:
0382: /**
0383: * Return whether we're running the parser at runtime.
0384: */
0385: protected boolean isRuntime() {
0386: return (getRepository().getValidate() & MetaDataRepository.VALIDATE_RUNTIME) != 0;
0387: }
0388:
0389: @Override
0390: protected Object getSchemaSource() {
0391: return XMLPersistenceMetaDataParser.class
0392: .getResourceAsStream("orm-xsd.rsrc");
0393: }
0394:
0395: @Override
0396: protected String getPackageAttributeName() {
0397: return null;
0398: }
0399:
0400: @Override
0401: protected String getClassAttributeName() {
0402: return "class";
0403: }
0404:
0405: @Override
0406: protected int getClassElementDepth() {
0407: return 1;
0408: }
0409:
0410: @Override
0411: protected boolean isClassElementName(String name) {
0412: return "entity".equals(name) || "embeddable".equals(name)
0413: || "mapped-superclass".equals(name);
0414: }
0415:
0416: @Override
0417: protected void reset() {
0418: super .reset();
0419: _elements.clear();
0420: _parents.clear();
0421: _cls = null;
0422: _fieldPos = 0;
0423: _clsPos = 0;
0424:
0425: _access = ClassMetaData.ACCESS_UNKNOWN;
0426: _strategy = null;
0427: _listener = null;
0428: _callbacks = null;
0429: _highs = null;
0430: _cascades = null;
0431: _pkgCascades = null;
0432: }
0433:
0434: @Override
0435: protected boolean startSystemElement(String name, Attributes attrs)
0436: throws SAXException {
0437: Object tag = (Object) _elems.get(name);
0438: boolean ret = false;
0439: if (tag == null) {
0440: if (isMappingOverrideMode())
0441: tag = startSystemMappingElement(name, attrs);
0442: ret = tag != null;
0443: } else if (tag instanceof MetaDataTag) {
0444: switch ((MetaDataTag) tag) {
0445: case QUERY:
0446: ret = startNamedQuery(attrs);
0447: break;
0448: case QUERY_HINT:
0449: ret = startQueryHint(attrs);
0450: break;
0451: case NATIVE_QUERY:
0452: ret = startNamedNativeQuery(attrs);
0453: break;
0454: case QUERY_STRING:
0455: ret = startQueryString(attrs);
0456: break;
0457: case SEQ_GENERATOR:
0458: ret = startSequenceGenerator(attrs);
0459: break;
0460: case FLUSH_MODE:
0461: ret = startFlushMode(attrs);
0462: break;
0463: case ENTITY_LISTENERS:
0464: ret = startEntityListeners(attrs);
0465: break;
0466: case PRE_PERSIST:
0467: case POST_PERSIST:
0468: case PRE_REMOVE:
0469: case POST_REMOVE:
0470: case PRE_UPDATE:
0471: case POST_UPDATE:
0472: case POST_LOAD:
0473: ret = startCallback((MetaDataTag) tag, attrs);
0474: break;
0475: default:
0476: warnUnsupportedTag(name);
0477: }
0478: } else if (tag == ELEM_PU_META || tag == ELEM_PU_DEF)
0479: ret = isMetaDataMode();
0480: else if (tag == ELEM_XML_MAP_META_COMPLETE)
0481: setAnnotationParser(null);
0482: else if (tag == ELEM_ACCESS)
0483: ret = _mode != MODE_QUERY;
0484: else if (tag == ELEM_LISTENER)
0485: ret = startEntityListener(attrs);
0486: else if (tag == ELEM_CASCADE)
0487: ret = isMetaDataMode();
0488: else if (tag == ELEM_CASCADE_ALL || tag == ELEM_CASCADE_PER
0489: || tag == ELEM_CASCADE_MER || tag == ELEM_CASCADE_REM
0490: || tag == ELEM_CASCADE_REF)
0491: ret = startCascade(tag, attrs);
0492:
0493: if (ret)
0494: _parents.push(tag);
0495: return ret;
0496: }
0497:
0498: @Override
0499: protected void endSystemElement(String name) throws SAXException {
0500: Object tag = _elems.get(name);
0501: if (tag == null && isMappingOverrideMode())
0502: endSystemMappingElement(name);
0503: else if (tag instanceof MetaDataTag) {
0504: switch ((MetaDataTag) tag) {
0505: case QUERY:
0506: endNamedQuery();
0507: break;
0508: case QUERY_HINT:
0509: endQueryHint();
0510: break;
0511: case NATIVE_QUERY:
0512: endNamedNativeQuery();
0513: break;
0514: case QUERY_STRING:
0515: endQueryString();
0516: break;
0517: case SEQ_GENERATOR:
0518: endSequenceGenerator();
0519: break;
0520: }
0521: } else if (tag == ELEM_ACCESS)
0522: endAccess();
0523: else if (tag == ELEM_LISTENER)
0524: endEntityListener();
0525:
0526: _parents.pop();
0527: }
0528:
0529: /**
0530: * Implement to parse a mapping element outside of any class.
0531: *
0532: * @return the tag for the given element, or null to skip the element
0533: */
0534: protected Object startSystemMappingElement(String name,
0535: Attributes attrs) throws SAXException {
0536: return null;
0537: }
0538:
0539: /**
0540: * Implement to parse a mapping element outside of any class.
0541: */
0542: protected void endSystemMappingElement(String name)
0543: throws SAXException {
0544: }
0545:
0546: @Override
0547: protected boolean startClassElement(String name, Attributes attrs)
0548: throws SAXException {
0549: Object tag = (Object) _elems.get(name);
0550: boolean ret = false;
0551: if (tag == null) {
0552: if (isMappingOverrideMode())
0553: tag = startClassMappingElement(name, attrs);
0554: ret = tag != null;
0555: } else if (tag instanceof MetaDataTag) {
0556: switch ((MetaDataTag) tag) {
0557: case GENERATED_VALUE:
0558: ret = startGeneratedValue(attrs);
0559: break;
0560: case ID:
0561: ret = startId(attrs);
0562: break;
0563: case EMBEDDED_ID:
0564: ret = startEmbeddedId(attrs);
0565: break;
0566: case ID_CLASS:
0567: ret = startIdClass(attrs);
0568: break;
0569: case LOB:
0570: ret = startLob(attrs);
0571: break;
0572: case QUERY:
0573: ret = startNamedQuery(attrs);
0574: break;
0575: case QUERY_HINT:
0576: ret = startQueryHint(attrs);
0577: break;
0578: case NATIVE_QUERY:
0579: ret = startNamedNativeQuery(attrs);
0580: break;
0581: case QUERY_STRING:
0582: ret = startQueryString(attrs);
0583: break;
0584: case SEQ_GENERATOR:
0585: ret = startSequenceGenerator(attrs);
0586: break;
0587: case VERSION:
0588: ret = startVersion(attrs);
0589: break;
0590: case MAP_KEY:
0591: ret = startMapKey(attrs);
0592: break;
0593: case FLUSH_MODE:
0594: ret = startFlushMode(attrs);
0595: break;
0596: case ORDER_BY:
0597: case ENTITY_LISTENERS:
0598: ret = isMetaDataMode();
0599: break;
0600: case EXCLUDE_DEFAULT_LISTENERS:
0601: ret = startExcludeDefaultListeners(attrs);
0602: break;
0603: case EXCLUDE_SUPERCLASS_LISTENERS:
0604: ret = startExcludeSuperclassListeners(attrs);
0605: break;
0606: case PRE_PERSIST:
0607: case POST_PERSIST:
0608: case PRE_REMOVE:
0609: case POST_REMOVE:
0610: case PRE_UPDATE:
0611: case POST_UPDATE:
0612: case POST_LOAD:
0613: ret = startCallback((MetaDataTag) tag, attrs);
0614: break;
0615: default:
0616: warnUnsupportedTag(name);
0617: }
0618: } else if (tag instanceof PersistenceStrategy) {
0619: PersistenceStrategy ps = (PersistenceStrategy) tag;
0620: ret = startStrategy(ps, attrs);
0621: if (ret)
0622: _strategy = ps;
0623: } else if (tag == ELEM_LISTENER)
0624: ret = startEntityListener(attrs);
0625: else if (tag == ELEM_ATTRS)
0626: ret = _mode != MODE_QUERY;
0627: else if (tag == ELEM_CASCADE)
0628: ret = isMetaDataMode();
0629: else if (tag == ELEM_CASCADE_ALL || tag == ELEM_CASCADE_PER
0630: || tag == ELEM_CASCADE_MER || tag == ELEM_CASCADE_REM
0631: || tag == ELEM_CASCADE_REF)
0632: ret = startCascade(tag, attrs);
0633:
0634: if (ret)
0635: _parents.push(tag);
0636: return ret;
0637: }
0638:
0639: @Override
0640: protected void endClassElement(String name) throws SAXException {
0641: Object tag = _elems.get(name);
0642: if (tag == null && isMappingOverrideMode())
0643: endClassMappingElement(name);
0644: else if (tag instanceof MetaDataTag) {
0645: switch ((MetaDataTag) tag) {
0646: case GENERATED_VALUE:
0647: endGeneratedValue();
0648: break;
0649: case ID:
0650: endId();
0651: break;
0652: case EMBEDDED_ID:
0653: endEmbeddedId();
0654: break;
0655: case ID_CLASS:
0656: endIdClass();
0657: break;
0658: case LOB:
0659: endLob();
0660: break;
0661: case QUERY:
0662: endNamedQuery();
0663: break;
0664: case QUERY_HINT:
0665: endQueryHint();
0666: break;
0667: case NATIVE_QUERY:
0668: endNamedNativeQuery();
0669: break;
0670: case QUERY_STRING:
0671: endQueryString();
0672: break;
0673: case SEQ_GENERATOR:
0674: endSequenceGenerator();
0675: break;
0676: case VERSION:
0677: endVersion();
0678: break;
0679: case ORDER_BY:
0680: endOrderBy();
0681: break;
0682: }
0683: } else if (tag instanceof PersistenceStrategy)
0684: endStrategy((PersistenceStrategy) tag);
0685: else if (tag == ELEM_ACCESS)
0686: endAccess();
0687: else if (tag == ELEM_LISTENER)
0688: endEntityListener();
0689:
0690: _parents.pop();
0691: }
0692:
0693: /**
0694: * Log warning about an unsupported tag.
0695: */
0696: private void warnUnsupportedTag(String name) {
0697: Log log = getLog();
0698: if (log.isInfoEnabled())
0699: log.trace(_loc.get("unsupported-tag", name));
0700: }
0701:
0702: /**
0703: * Implement to parse a mapping element within a class.
0704: *
0705: * @return the tag for the given element, or null to skip element
0706: */
0707: protected Object startClassMappingElement(String name,
0708: Attributes attrs) throws SAXException {
0709: return null;
0710: }
0711:
0712: /**
0713: * Implement to parse a mapping element within a class.
0714: */
0715: protected void endClassMappingElement(String name)
0716: throws SAXException {
0717: }
0718:
0719: @Override
0720: protected boolean startClass(String elem, Attributes attrs)
0721: throws SAXException {
0722: super .startClass(elem, attrs);
0723:
0724: // query mode only?
0725: _cls = classForName(currentClassName());
0726: if (_mode == MODE_QUERY) {
0727: if (_parser != null
0728: && !"true".equals(attrs
0729: .getValue("metadata-complete")))
0730: _parser.parse(_cls);
0731: return true;
0732: }
0733:
0734: Log log = getLog();
0735: if (log.isTraceEnabled())
0736: log.trace(_loc.get("parse-class", _cls.getName()));
0737:
0738: MetaDataRepository repos = getRepository();
0739: ClassMetaData meta = repos.getCachedMetaData(_cls);
0740: if (meta != null
0741: && ((isMetaDataMode() && (meta.getSourceMode() & MODE_META) != 0) || (isMappingMode() && (meta
0742: .getSourceMode() & MODE_MAPPING) != 0))) {
0743: if (log.isWarnEnabled())
0744: log.warn(_loc
0745: .get("dup-metadata", _cls, getSourceName()));
0746: _cls = null;
0747: return false;
0748: }
0749:
0750: // if we don't know the access type, check to see if a superclass
0751: // has already defined the access type
0752: int defaultAccess = _access;
0753: if (defaultAccess == ClassMetaData.ACCESS_UNKNOWN) {
0754: ClassMetaData sup = repos.getCachedMetaData(_cls
0755: .getSuperclass());
0756: if (sup != null)
0757: defaultAccess = sup.getAccessType();
0758: }
0759:
0760: if (meta == null) {
0761: // add metadata for this type
0762: int access = toAccessType(attrs.getValue("access"),
0763: defaultAccess);
0764: meta = repos.addMetaData(_cls, access);
0765: meta.setEnvClassLoader(_envLoader);
0766: meta.setSourceMode(MODE_NONE);
0767:
0768: // parse annotations first so XML overrides them
0769: if (_parser != null
0770: && !"true".equals(attrs
0771: .getValue("metadata-complete")))
0772: _parser.parse(_cls);
0773: }
0774:
0775: boolean mappedSuper = "mapped-superclass".equals(elem);
0776: if (isMetaDataMode()) {
0777: meta.setSource(getSourceFile(), meta.SRC_XML);
0778: meta.setSourceMode(MODE_META, true);
0779: meta.setListingIndex(_clsPos);
0780: String name = attrs.getValue("name");
0781: if (!StringUtils.isEmpty(name))
0782: meta.setTypeAlias(name);
0783: meta.setEmbeddedOnly(mappedSuper
0784: || "embeddable".equals(elem));
0785: if (mappedSuper)
0786: meta.setIdentityType(meta.ID_UNKNOWN);
0787: }
0788: if (isMappingMode())
0789: meta.setSourceMode(MODE_MAPPING, true);
0790: if (isMappingOverrideMode())
0791: startClassMapping(meta, mappedSuper, attrs);
0792: if (isQueryMode())
0793: meta.setSourceMode(MODE_QUERY, true);
0794:
0795: _clsPos++;
0796: _fieldPos = 0;
0797: addComments(meta);
0798: pushElement(meta);
0799: return true;
0800: }
0801:
0802: @Override
0803: protected void endClass(String elem) throws SAXException {
0804: if (_mode != MODE_QUERY) {
0805: ClassMetaData meta = (ClassMetaData) popElement();
0806: storeCallbacks(meta);
0807: if (isMappingOverrideMode())
0808: endClassMapping(meta);
0809: }
0810: _cls = null;
0811: super .endClass(elem);
0812: }
0813:
0814: /**
0815: * Implement to add mapping attributes to class.
0816: */
0817: protected void startClassMapping(ClassMetaData mapping,
0818: boolean mappedSuper, Attributes attrs) throws SAXException {
0819: }
0820:
0821: /**
0822: * Implement to finalize class mapping.
0823: */
0824: protected void endClassMapping(ClassMetaData mapping)
0825: throws SAXException {
0826: }
0827:
0828: /**
0829: * Default access element.
0830: */
0831: private void endAccess() {
0832: _access = toAccessType(currentText(),
0833: ClassMetaData.ACCESS_UNKNOWN);
0834: }
0835:
0836: /**
0837: * Parse the given string as an entity access type, defaulting to given
0838: * default if string is empty.
0839: */
0840: private int toAccessType(String str, int def) {
0841: if (StringUtils.isEmpty(str))
0842: return def;
0843: if ("PROPERTY".equals(str))
0844: return ClassMetaData.ACCESS_PROPERTY;
0845: return ClassMetaData.ACCESS_FIELD;
0846: }
0847:
0848: /**
0849: * Parse flush-mode element.
0850: */
0851: private boolean startFlushMode(Attributes attrs)
0852: throws SAXException {
0853: Log log = getLog();
0854: if (log.isWarnEnabled())
0855: log.warn(_loc.get("unsupported", "flush-mode",
0856: getSourceName()));
0857: return false;
0858: }
0859:
0860: /**
0861: * Parse sequence-generator.
0862: */
0863: protected boolean startSequenceGenerator(Attributes attrs) {
0864: if (!isMappingOverrideMode())
0865: return false;
0866:
0867: String name = attrs.getValue("name");
0868: Log log = getLog();
0869: if (log.isTraceEnabled())
0870: log.trace(_loc.get("parse-sequence", name));
0871:
0872: SequenceMetaData meta = getRepository()
0873: .getCachedSequenceMetaData(name);
0874: if (meta != null && log.isWarnEnabled())
0875: log.warn(_loc.get("override-sequence", name));
0876:
0877: meta = getRepository().addSequenceMetaData(name);
0878: String seq = attrs.getValue("sequence-name");
0879: String val = attrs.getValue("initial-value");
0880: int initial = val == null ? 1 : Integer.parseInt(val);
0881: val = attrs.getValue("allocation-size");
0882: int allocate = val == null ? 50 : Integer.parseInt(val);
0883:
0884: String clsName, props;
0885: if (seq == null || seq.indexOf('(') == -1) {
0886: clsName = SequenceMetaData.IMPL_NATIVE;
0887: props = null;
0888: } else { // plugin
0889: clsName = Configurations.getClassName(seq);
0890: props = Configurations.getProperties(seq);
0891: seq = null;
0892: }
0893:
0894: meta
0895: .setSequencePlugin(Configurations.getPlugin(clsName,
0896: props));
0897: meta.setSequence(seq);
0898: meta.setInitialValue(initial);
0899: meta.setAllocate(allocate);
0900:
0901: Object cur = currentElement();
0902: Object scope = (cur instanceof ClassMetaData) ? ((ClassMetaData) cur)
0903: .getDescribedType()
0904: : null;
0905: meta.setSource(getSourceFile(), scope, meta.SRC_XML);
0906: return true;
0907: }
0908:
0909: protected void endSequenceGenerator() {
0910: }
0911:
0912: /**
0913: * Parse id.
0914: */
0915: protected boolean startId(Attributes attrs) throws SAXException {
0916: FieldMetaData fmd = parseField(attrs);
0917: fmd.setExplicit(true);
0918: fmd.setPrimaryKey(true);
0919: return true;
0920: }
0921:
0922: protected void endId() throws SAXException {
0923: finishField();
0924: }
0925:
0926: /**
0927: * Parse embedded-id.
0928: */
0929: protected boolean startEmbeddedId(Attributes attrs)
0930: throws SAXException {
0931: FieldMetaData fmd = parseField(attrs);
0932: fmd.setExplicit(true);
0933: fmd.setPrimaryKey(true);
0934: fmd.setEmbedded(true);
0935: if (fmd.getEmbeddedMetaData() == null)
0936: fmd.addEmbeddedMetaData();
0937: return true;
0938: }
0939:
0940: protected void endEmbeddedId() throws SAXException {
0941: finishField();
0942: }
0943:
0944: /**
0945: * Parse id-class.
0946: */
0947: protected boolean startIdClass(Attributes attrs)
0948: throws SAXException {
0949: if (!isMetaDataMode())
0950: return false;
0951:
0952: ClassMetaData meta = (ClassMetaData) currentElement();
0953: String cls = attrs.getValue("class");
0954: Class idCls = null;
0955: try {
0956: idCls = classForName(cls);
0957: } catch (Throwable t) {
0958: throw getException(_loc.get("invalid-id-class", meta, cls),
0959: t);
0960: }
0961: meta.setObjectIdType(idCls, true);
0962: return true;
0963: }
0964:
0965: protected void endIdClass() throws SAXException {
0966: }
0967:
0968: /**
0969: * Parse lob.
0970: */
0971: protected boolean startLob(Attributes attrs) throws SAXException {
0972: FieldMetaData fmd = (FieldMetaData) currentElement();
0973: if (fmd.getDeclaredTypeCode() != JavaTypes.STRING
0974: && fmd.getDeclaredType() != char[].class
0975: && fmd.getDeclaredType() != Character[].class
0976: && fmd.getDeclaredType() != byte[].class
0977: && fmd.getDeclaredType() != Byte[].class)
0978: fmd.setSerialized(true);
0979: return true;
0980: }
0981:
0982: protected void endLob() throws SAXException {
0983: }
0984:
0985: /**
0986: * Parse generated-value.
0987: */
0988: protected boolean startGeneratedValue(Attributes attrs)
0989: throws SAXException {
0990: if (!isMappingOverrideMode())
0991: return false;
0992:
0993: String strategy = attrs.getValue("strategy");
0994: String generator = attrs.getValue("generator");
0995: GenerationType type = StringUtils.isEmpty(strategy) ? GenerationType.AUTO
0996: : GenerationType.valueOf(strategy);
0997:
0998: FieldMetaData fmd = (FieldMetaData) currentElement();
0999: AnnotationPersistenceMetaDataParser.parseGeneratedValue(fmd,
1000: type, generator);
1001: return true;
1002: }
1003:
1004: protected void endGeneratedValue() throws SAXException {
1005: }
1006:
1007: /**
1008: * Lazily parse cascades.
1009: */
1010: protected boolean startCascade(Object tag, Attributes attrs)
1011: throws SAXException {
1012: if (!isMetaDataMode())
1013: return false;
1014:
1015: Set<CascadeType> cascades = null;
1016: if (currentElement() instanceof FieldMetaData) {
1017: if (_cascades == null)
1018: _cascades = EnumSet.noneOf(CascadeType.class);
1019: cascades = _cascades;
1020: } else {
1021: if (_pkgCascades == null)
1022: _pkgCascades = EnumSet.noneOf(CascadeType.class);
1023: cascades = _pkgCascades;
1024: }
1025: boolean all = ELEM_CASCADE_ALL == tag;
1026: if (all || ELEM_CASCADE_PER == tag)
1027: cascades.add(PERSIST);
1028: if (all || ELEM_CASCADE_REM == tag)
1029: cascades.add(REMOVE);
1030: if (all || ELEM_CASCADE_MER == tag)
1031: cascades.add(MERGE);
1032: if (all || ELEM_CASCADE_REF == tag)
1033: cascades.add(REFRESH);
1034: return true;
1035: }
1036:
1037: /**
1038: * Set the cached cascades into the field.
1039: */
1040: protected void setCascades(FieldMetaData fmd) {
1041: Set<CascadeType> cascades = _cascades;
1042: if (_cascades == null)
1043: cascades = _pkgCascades;
1044: if (cascades == null)
1045: return;
1046:
1047: ValueMetaData vmd = fmd;
1048: switch (_strategy) {
1049: case ONE_MANY:
1050: case MANY_MANY:
1051: vmd = fmd.getElement();
1052: }
1053: for (CascadeType cascade : cascades) {
1054: switch (cascade) {
1055: case PERSIST:
1056: vmd.setCascadePersist(ValueMetaData.CASCADE_IMMEDIATE);
1057: break;
1058: case MERGE:
1059: vmd.setCascadeAttach(ValueMetaData.CASCADE_IMMEDIATE);
1060: break;
1061: case REMOVE:
1062: vmd.setCascadeDelete(ValueMetaData.CASCADE_IMMEDIATE);
1063: break;
1064: case REFRESH:
1065: vmd.setCascadeRefresh(ValueMetaData.CASCADE_IMMEDIATE);
1066: break;
1067: }
1068: }
1069: _cascades = null;
1070: }
1071:
1072: /**
1073: * Parse common field attributes.
1074: */
1075: private FieldMetaData parseField(Attributes attrs)
1076: throws SAXException {
1077: ClassMetaData meta = (ClassMetaData) currentElement();
1078: String name = attrs.getValue("name");
1079: FieldMetaData field = meta.getDeclaredField(name);
1080: if ((field == null || field.getDeclaredType() == Object.class)
1081: && meta.getDescribedType() != Object.class) {
1082: Member member = null;
1083: Class type = null;
1084: int def = _repos.getMetaDataFactory().getDefaults()
1085: .getDefaultAccessType();
1086: try {
1087: if (meta.getAccessType() == ClassMetaData.ACCESS_PROPERTY
1088: || (meta.getAccessType() == ClassMetaData.ACCESS_UNKNOWN && def == ClassMetaData.ACCESS_PROPERTY)) {
1089: String cap = StringUtils.capitalize(name);
1090: type = meta.getDescribedType();
1091: try {
1092: member = (Method) AccessController
1093: .doPrivileged(J2DoPrivHelper
1094: .getDeclaredMethodAction(type,
1095: "get" + cap,
1096: (Class[]) null));// varargs disambiguate
1097: } catch (Exception excep) {
1098: try {
1099: member = (Method) AccessController
1100: .doPrivileged(J2DoPrivHelper
1101: .getDeclaredMethodAction(
1102: type, "is" + cap,
1103: (Class[]) null));
1104: } catch (Exception excep2) {
1105: throw excep;
1106: }
1107: }
1108: type = ((Method) member).getReturnType();
1109: } else {
1110: member = (Field) AccessController
1111: .doPrivileged(J2DoPrivHelper
1112: .getDeclaredFieldAction(meta
1113: .getDescribedType(), name));
1114: type = ((Field) member).getType();
1115: }
1116: } catch (Exception e) {
1117: if (e instanceof PrivilegedActionException)
1118: e = ((PrivilegedActionException) e).getException();
1119: throw getException(
1120: _loc.get("invalid-attr", name, meta), e);
1121: }
1122:
1123: if (field == null) {
1124: field = meta.addDeclaredField(name, type);
1125: PersistenceMetaDataDefaults.setCascadeNone(field);
1126: PersistenceMetaDataDefaults.setCascadeNone(field
1127: .getKey());
1128: PersistenceMetaDataDefaults.setCascadeNone(field
1129: .getElement());
1130: }
1131: field.backingMember(member);
1132: } else if (field == null) {
1133: field = meta.addDeclaredField(name, Object.class);
1134: PersistenceMetaDataDefaults.setCascadeNone(field);
1135: PersistenceMetaDataDefaults.setCascadeNone(field.getKey());
1136: PersistenceMetaDataDefaults.setCascadeNone(field
1137: .getElement());
1138: }
1139:
1140: if (isMetaDataMode())
1141: field.setListingIndex(_fieldPos);
1142:
1143: _fieldPos++;
1144: pushElement(field);
1145: addComments(field);
1146:
1147: if (isMappingOverrideMode())
1148: startFieldMapping(field, attrs);
1149: return field;
1150: }
1151:
1152: /**
1153: * Pops field element.
1154: */
1155: private void finishField() throws SAXException {
1156: FieldMetaData field = (FieldMetaData) popElement();
1157: setCascades(field);
1158: if (isMappingOverrideMode())
1159: endFieldMapping(field);
1160: _strategy = null;
1161: }
1162:
1163: /**
1164: * Implement to add field mapping data. Does nothing by default.
1165: */
1166: protected void startFieldMapping(FieldMetaData field,
1167: Attributes attrs) throws SAXException {
1168: }
1169:
1170: /**
1171: * Implement to finalize field mapping. Does nothing by default.
1172: */
1173: protected void endFieldMapping(FieldMetaData field)
1174: throws SAXException {
1175: }
1176:
1177: /**
1178: * Parse version.
1179: */
1180: protected boolean startVersion(Attributes attrs)
1181: throws SAXException {
1182: FieldMetaData fmd = parseField(attrs);
1183: fmd.setExplicit(true);
1184: fmd.setVersion(true);
1185: return true;
1186: }
1187:
1188: protected void endVersion() throws SAXException {
1189: finishField();
1190: }
1191:
1192: /**
1193: * Parse strategy element.
1194: */
1195: private boolean startStrategy(PersistenceStrategy strategy,
1196: Attributes attrs) throws SAXException {
1197: FieldMetaData fmd = parseField(attrs);
1198: fmd.setExplicit(true);
1199: fmd.setManagement(FieldMetaData.MANAGE_PERSISTENT);
1200:
1201: String val = attrs.getValue("fetch");
1202: if (val != null)
1203: fmd.setInDefaultFetchGroup("EAGER".equals(val));
1204: val = attrs.getValue("optional");
1205: if ("false".equals(val))
1206: fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
1207: else if ("true".equals(val)
1208: && fmd.getNullValue() == FieldMetaData.NULL_EXCEPTION) {
1209: // Reset value if the field was annotated with optional=false.
1210: // Otherwise leave it alone.
1211: fmd.setNullValue(FieldMetaData.NULL_UNSET);
1212: }
1213: if (isMappingOverrideMode()) {
1214: val = attrs.getValue("mapped-by");
1215: if (val != null)
1216: fmd.setMappedBy(val);
1217: }
1218: parseStrategy(fmd, strategy, attrs);
1219: return true;
1220: }
1221:
1222: private void endStrategy(PersistenceStrategy strategy)
1223: throws SAXException {
1224: finishField();
1225: }
1226:
1227: /**
1228: * Parse strategy specific attributes.
1229: */
1230: private void parseStrategy(FieldMetaData fmd,
1231: PersistenceStrategy strategy, Attributes attrs)
1232: throws SAXException {
1233: switch (strategy) {
1234: case BASIC:
1235: parseBasic(fmd, attrs);
1236: break;
1237: case EMBEDDED:
1238: parseEmbedded(fmd, attrs);
1239: break;
1240: case ONE_ONE:
1241: parseOneToOne(fmd, attrs);
1242: break;
1243: case MANY_ONE:
1244: parseManyToOne(fmd, attrs);
1245: break;
1246: case MANY_MANY:
1247: parseManyToMany(fmd, attrs);
1248: break;
1249: case ONE_MANY:
1250: parseOneToMany(fmd, attrs);
1251: break;
1252: case TRANSIENT:
1253: fmd.setManagement(FieldMetaData.MANAGE_NONE);
1254: break;
1255: }
1256: }
1257:
1258: /**
1259: * Parse basic.
1260: */
1261: protected void parseBasic(FieldMetaData fmd, Attributes attrs)
1262: throws SAXException {
1263: }
1264:
1265: /**
1266: * Parse embedded.
1267: */
1268: protected void parseEmbedded(FieldMetaData fmd, Attributes attrs)
1269: throws SAXException {
1270: assertPC(fmd, "Embedded");
1271: fmd.setEmbedded(true);
1272: fmd.setSerialized(false); // override any Lob annotation
1273: if (fmd.getEmbeddedMetaData() == null)
1274: fmd.addEmbeddedMetaData();
1275: }
1276:
1277: /**
1278: * Throw proper exception if given value is not possibly persistence
1279: * capable.
1280: */
1281: private void assertPC(FieldMetaData fmd, String attr)
1282: throws SAXException {
1283: if (!JavaTypes.maybePC(fmd))
1284: throw getException(_loc.get("bad-meta-anno", fmd, attr));
1285: }
1286:
1287: /**
1288: * Parse one-to-one.
1289: */
1290: protected void parseOneToOne(FieldMetaData fmd, Attributes attrs)
1291: throws SAXException {
1292: String val = attrs.getValue("target-entity");
1293: if (val != null)
1294: fmd.setTypeOverride(classForName(val));
1295: assertPC(fmd, "OneToOne");
1296: fmd.setSerialized(false); // override any Lob annotation
1297: if (!fmd.isDefaultFetchGroupExplicit())
1298: fmd.setInDefaultFetchGroup(true);
1299: }
1300:
1301: /**
1302: * Parse many-to-one.
1303: */
1304: protected void parseManyToOne(FieldMetaData fmd, Attributes attrs)
1305: throws SAXException {
1306: String val = attrs.getValue("target-entity");
1307: if (val != null)
1308: fmd.setTypeOverride(classForName(val));
1309: assertPC(fmd, "ManyToOne");
1310: fmd.setSerialized(false); // override any Lob annotation
1311: if (!fmd.isDefaultFetchGroupExplicit())
1312: fmd.setInDefaultFetchGroup(true);
1313: }
1314:
1315: /**
1316: * Parse many-to-many.
1317: */
1318: protected void parseManyToMany(FieldMetaData fmd, Attributes attrs)
1319: throws SAXException {
1320: String val = attrs.getValue("target-entity");
1321: if (val != null)
1322: fmd.getElement().setDeclaredType(classForName(val));
1323: assertPCCollection(fmd, "ManyToMany");
1324: fmd.setSerialized(false); // override Lob in annotation
1325: }
1326:
1327: /**
1328: * Throw exception if given field not a collection of possible persistence
1329: * capables.
1330: */
1331: private void assertPCCollection(FieldMetaData fmd, String attr)
1332: throws SAXException {
1333: switch (fmd.getDeclaredTypeCode()) {
1334: case JavaTypes.ARRAY:
1335: case JavaTypes.COLLECTION:
1336: case JavaTypes.MAP:
1337: if (JavaTypes.maybePC(fmd.getElement()))
1338: break;
1339: // no break
1340: default:
1341: throw getException(_loc.get("bad-meta-anno", fmd, attr));
1342: }
1343: }
1344:
1345: /**
1346: * Parse one-to-many.
1347: */
1348: protected void parseOneToMany(FieldMetaData fmd, Attributes attrs)
1349: throws SAXException {
1350: String val = attrs.getValue("target-entity");
1351: if (val != null)
1352: fmd.getElement().setDeclaredType(classForName(val));
1353: assertPCCollection(fmd, "OneToMany");
1354: fmd.setSerialized(false); // override any Lob annotation
1355: }
1356:
1357: /**
1358: * Parse map-key.
1359: */
1360: private boolean startMapKey(Attributes attrs) throws SAXException {
1361: if (!isMappingOverrideMode())
1362: return false;
1363:
1364: FieldMetaData fmd = (FieldMetaData) currentElement();
1365: String mapKey = attrs.getValue("name");
1366: if (mapKey == null)
1367: fmd.getKey().setValueMappedBy(ValueMetaData.MAPPED_BY_PK);
1368: else
1369: fmd.getKey().setValueMappedBy(mapKey);
1370: return true;
1371: }
1372:
1373: /**
1374: * Parse order-by.
1375: */
1376: private void endOrderBy() throws SAXException {
1377: FieldMetaData fmd = (FieldMetaData) currentElement();
1378: String dec = currentText();
1379: if (StringUtils.isEmpty(dec))
1380: dec = Order.ELEMENT + " asc";
1381: fmd.setOrderDeclaration(dec);
1382: }
1383:
1384: /**
1385: * Parse named-query.
1386: */
1387: protected boolean startNamedQuery(Attributes attrs)
1388: throws SAXException {
1389: if (!isQueryMode())
1390: return false;
1391:
1392: String name = attrs.getValue("name");
1393: Log log = getLog();
1394: if (log.isTraceEnabled())
1395: log.trace(_loc.get("parse-query", name));
1396:
1397: QueryMetaData meta = getRepository().getCachedQueryMetaData(
1398: null, name);
1399: if (meta != null && log.isWarnEnabled())
1400: log.warn(_loc
1401: .get("override-query", name, currentLocation()));
1402:
1403: meta = getRepository().addQueryMetaData(null, name);
1404: meta.setDefiningType(_cls);
1405: meta.setQueryString(attrs.getValue("query"));
1406: meta.setLanguage(JPQLParser.LANG_JPQL);
1407:
1408: Object cur = currentElement();
1409: Object scope = (cur instanceof ClassMetaData) ? ((ClassMetaData) cur)
1410: .getDescribedType()
1411: : null;
1412: meta.setSource(getSourceFile(), scope, meta.SRC_XML);
1413: if (isMetaDataMode())
1414: meta.setSourceMode(MODE_META);
1415: else if (isMappingMode())
1416: meta.setSourceMode(MODE_MAPPING);
1417: else
1418: meta.setSourceMode(MODE_QUERY);
1419: pushElement(meta);
1420: return true;
1421: }
1422:
1423: protected void endNamedQuery() throws SAXException {
1424: popElement();
1425: }
1426:
1427: protected boolean startQueryString(Attributes attrs)
1428: throws SAXException {
1429: return true;
1430: }
1431:
1432: protected void endQueryString() throws SAXException {
1433: QueryMetaData meta = (QueryMetaData) currentElement();
1434: meta.setQueryString(currentText());
1435: }
1436:
1437: /**
1438: * Parse query-hint.
1439: */
1440: protected boolean startQueryHint(Attributes attrs)
1441: throws SAXException {
1442: QueryMetaData meta = (QueryMetaData) currentElement();
1443: meta.addHint(attrs.getValue("name"), attrs.getValue("value"));
1444: return true;
1445: }
1446:
1447: protected void endQueryHint() throws SAXException {
1448: }
1449:
1450: /**
1451: * Parse native-named-query.
1452: */
1453: protected boolean startNamedNativeQuery(Attributes attrs)
1454: throws SAXException {
1455: if (!isQueryMode())
1456: return false;
1457:
1458: String name = attrs.getValue("name");
1459: Log log = getLog();
1460: if (log.isTraceEnabled())
1461: log.trace(_loc.get("parse-native-query", name));
1462:
1463: QueryMetaData meta = getRepository().getCachedQueryMetaData(
1464: null, name);
1465: if (meta != null && log.isWarnEnabled())
1466: log.warn(_loc
1467: .get("override-query", name, currentLocation()));
1468:
1469: meta = getRepository().addQueryMetaData(null, name);
1470: meta.setDefiningType(_cls);
1471: meta.setQueryString(attrs.getValue("query"));
1472: meta.setLanguage(QueryLanguages.LANG_SQL);
1473: String val = attrs.getValue("result-class");
1474: if (val != null) {
1475: Class type = classForName(val);
1476: if (ImplHelper.isManagedType(getConfiguration(), type))
1477: meta.setCandidateType(type);
1478: else
1479: meta.setResultType(type);
1480: }
1481:
1482: val = attrs.getValue("result-set-mapping");
1483: if (val != null)
1484: meta.setResultSetMappingName(val);
1485:
1486: Object cur = currentElement();
1487: Object scope = (cur instanceof ClassMetaData) ? ((ClassMetaData) cur)
1488: .getDescribedType()
1489: : null;
1490: meta.setSource(getSourceFile(), scope, meta.SRC_XML);
1491: if (isMetaDataMode())
1492: meta.setSourceMode(MODE_META);
1493: else if (isMappingMode())
1494: meta.setSourceMode(MODE_MAPPING);
1495: else
1496: meta.setSourceMode(MODE_QUERY);
1497: pushElement(meta);
1498: return true;
1499: }
1500:
1501: protected void endNamedNativeQuery() throws SAXException {
1502: popElement();
1503: }
1504:
1505: /**
1506: * Start entity-listeners
1507: */
1508: private boolean startEntityListeners(Attributes attrs)
1509: throws SAXException {
1510: if (!isMetaDataMode())
1511: return false;
1512: if (currentElement() == null)
1513: return true;
1514:
1515: // reset listeners declared in annotations.
1516: LifecycleMetaData meta = ((ClassMetaData) currentElement())
1517: .getLifecycleMetaData();
1518: for (int i = 0; i < LifecycleEvent.ALL_EVENTS.length; i++)
1519: meta.setDeclaredCallbacks(i, null, 0);
1520: return true;
1521: }
1522:
1523: /**
1524: * Parse exclude-default-listeners.
1525: */
1526: private boolean startExcludeDefaultListeners(Attributes attrs)
1527: throws SAXException {
1528: if (!isMetaDataMode())
1529: return false;
1530: ClassMetaData meta = (ClassMetaData) currentElement();
1531: meta.getLifecycleMetaData().setIgnoreSystemListeners(true);
1532: return true;
1533: }
1534:
1535: /**
1536: * Parse exclude-superclass-listeners.
1537: */
1538: private boolean startExcludeSuperclassListeners(Attributes attrs)
1539: throws SAXException {
1540: if (!isMetaDataMode())
1541: return false;
1542: ClassMetaData meta = (ClassMetaData) currentElement();
1543: meta.getLifecycleMetaData().setIgnoreSuperclassCallbacks(
1544: LifecycleMetaData.IGNORE_HIGH);
1545: return true;
1546: }
1547:
1548: /**
1549: * Parse entity-listener.
1550: */
1551: private boolean startEntityListener(Attributes attrs)
1552: throws SAXException {
1553: _listener = classForName(attrs.getValue("class"));
1554: boolean system = currentElement() == null;
1555: Collection<LifecycleCallbacks>[] parsed = AnnotationPersistenceMetaDataParser
1556: .parseCallbackMethods(_listener, null, true, true,
1557: _repos);
1558: if (parsed == null)
1559: return true;
1560:
1561: if (_callbacks == null) {
1562: _callbacks = (Collection<LifecycleCallbacks>[]) new Collection[LifecycleEvent.ALL_EVENTS.length];
1563: if (!system)
1564: _highs = new int[LifecycleEvent.ALL_EVENTS.length];
1565: }
1566: for (int i = 0; i < parsed.length; i++) {
1567: if (parsed[i] == null)
1568: continue;
1569: if (_callbacks[i] == null)
1570: _callbacks[i] = parsed[i];
1571: else
1572: _callbacks[i].addAll(parsed[i]);
1573: if (!system)
1574: _highs[i] += parsed[i].size();
1575: }
1576: return true;
1577: }
1578:
1579: private void endEntityListener() throws SAXException {
1580: // should be in endEntityListeners I think to merge callbacks
1581: // into a single listener. But then the user cannot remove.
1582: if (currentElement() == null && _callbacks != null) {
1583: _repos.addSystemListener(new PersistenceListenerAdapter(
1584: _callbacks));
1585: _callbacks = null;
1586: }
1587: _listener = null;
1588: }
1589:
1590: private boolean startCallback(MetaDataTag callback, Attributes attrs)
1591: throws SAXException {
1592: if (!isMetaDataMode())
1593: return false;
1594: int[] events = MetaDataParsers.getEventTypes(callback);
1595: if (events == null)
1596: return false;
1597:
1598: boolean system = currentElement() == null;
1599: Class type = currentElement() == null ? null
1600: : ((ClassMetaData) currentElement()).getDescribedType();
1601: if (type == null)
1602: type = Object.class;
1603:
1604: if (_callbacks == null) {
1605: _callbacks = (Collection<LifecycleCallbacks>[]) new Collection[LifecycleEvent.ALL_EVENTS.length];
1606: if (!system)
1607: _highs = new int[LifecycleEvent.ALL_EVENTS.length];
1608: }
1609:
1610: MetaDataDefaults def = _repos.getMetaDataFactory()
1611: .getDefaults();
1612: LifecycleCallbacks adapter;
1613: if (_listener != null)
1614: adapter = new BeanLifecycleCallbacks(_listener, attrs
1615: .getValue("method-name"), false, type);
1616: else
1617: adapter = new MethodLifecycleCallbacks(_cls, attrs
1618: .getValue("method-name"), false);
1619:
1620: for (int i = 0; i < events.length; i++) {
1621: int event = events[i];
1622: if (_listener != null) {
1623: MetaDataParsers.validateMethodsForSameCallback(
1624: _listener, _callbacks[event],
1625: ((BeanLifecycleCallbacks) adapter)
1626: .getCallbackMethod(), callback, def,
1627: getLog());
1628: } else {
1629: MetaDataParsers.validateMethodsForSameCallback(_cls,
1630: _callbacks[event],
1631: ((MethodLifecycleCallbacks) adapter)
1632: .getCallbackMethod(), callback, def,
1633: getLog());
1634:
1635: }
1636: if (_callbacks[event] == null)
1637: _callbacks[event] = new ArrayList<LifecycleCallbacks>(3);
1638: _callbacks[event].add(adapter);
1639: if (!system && _listener != null)
1640: _highs[event]++;
1641: }
1642: return true;
1643: }
1644:
1645: /**
1646: * Store lifecycle metadata.
1647: */
1648: private void storeCallbacks(ClassMetaData cls) {
1649: LifecycleMetaData meta = cls.getLifecycleMetaData();
1650: Class supCls = cls.getDescribedType().getSuperclass();
1651: Collection<LifecycleCallbacks>[] supCalls = null;
1652: if (!Object.class.equals(supCls)) {
1653: supCalls = AnnotationPersistenceMetaDataParser
1654: .parseCallbackMethods(supCls, null, true, false,
1655: _repos);
1656: }
1657: if (supCalls != null) {
1658: for (int event : LifecycleEvent.ALL_EVENTS) {
1659: if (supCalls[event] == null)
1660: continue;
1661: meta.setNonPCSuperclassCallbacks(event, supCalls[event]
1662: .toArray(new LifecycleCallbacks[supCalls[event]
1663: .size()]), 0);
1664: }
1665: }
1666: if (_callbacks == null)
1667: return;
1668:
1669: for (int event : LifecycleEvent.ALL_EVENTS) {
1670: if (_callbacks[event] == null)
1671: continue;
1672: meta
1673: .setDeclaredCallbacks(
1674: event,
1675: (LifecycleCallbacks[]) _callbacks[event]
1676: .toArray(new LifecycleCallbacks[_callbacks[event]
1677: .size()]), _highs[event]);
1678: }
1679: _callbacks = null;
1680: _highs = null;
1681: }
1682:
1683: /**
1684: * Instantiate the given class, taking into account the default package.
1685: */
1686: protected Class classForName(String name) throws SAXException {
1687: if ("Entity".equals(name))
1688: return PersistenceCapable.class;
1689: return super.classForName(name, isRuntime());
1690: }
1691: }
|