You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by de...@apache.org on 2009/12/11 01:06:22 UTC
svn commit: r889476 [4/5] - in /openjpa/branches/1.1.x:
openjpa-kernel/src/main/java/org/apache/openjpa/meta/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/mappedsuperclass/idclass/
openjpa-persistence/src/main/java/...
Modified: openjpa/branches/1.1.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java?rev=889476&r1=889475&r2=889476&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java (original)
+++ openjpa/branches/1.1.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java Fri Dec 11 00:06:21 2009
@@ -1,1706 +1,1709 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.openjpa.persistence;
-
-import java.io.File;
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Field;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import javax.persistence.Basic;
-import javax.persistence.CascadeType;
-import javax.persistence.Embeddable;
-import javax.persistence.Embedded;
-import javax.persistence.EmbeddedId;
-import javax.persistence.Entity;
-import javax.persistence.EntityListeners;
-import javax.persistence.ExcludeDefaultListeners;
-import javax.persistence.ExcludeSuperclassListeners;
-import javax.persistence.FetchType;
-import javax.persistence.FlushModeType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import static javax.persistence.GenerationType.AUTO;
-import javax.persistence.Id;
-import javax.persistence.IdClass;
-import javax.persistence.Lob;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapKey;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.NamedNativeQueries;
-import javax.persistence.NamedNativeQuery;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
-import javax.persistence.OrderBy;
-import javax.persistence.PostLoad;
-import javax.persistence.PostPersist;
-import javax.persistence.PostRemove;
-import javax.persistence.PostUpdate;
-import javax.persistence.PrePersist;
-import javax.persistence.PreRemove;
-import javax.persistence.PreUpdate;
-import javax.persistence.QueryHint;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.Version;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.event.BeanLifecycleCallbacks;
-import org.apache.openjpa.event.LifecycleCallbacks;
-import org.apache.openjpa.event.LifecycleEvent;
-import org.apache.openjpa.event.MethodLifecycleCallbacks;
-import org.apache.openjpa.kernel.QueryLanguages;
-import org.apache.openjpa.kernel.jpql.JPQLParser;
-import org.apache.openjpa.lib.conf.Configurations;
-import org.apache.openjpa.lib.log.Log;
-import org.apache.openjpa.lib.util.J2DoPriv5Helper;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.meta.ClassMetaData;
-import org.apache.openjpa.meta.DelegatingMetaDataFactory;
-import org.apache.openjpa.meta.FieldMetaData;
-import org.apache.openjpa.meta.JavaTypes;
-import org.apache.openjpa.meta.LifecycleMetaData;
-import org.apache.openjpa.meta.MetaDataFactory;
-import org.apache.openjpa.meta.MetaDataModes;
-import org.apache.openjpa.meta.MetaDataRepository;
-import org.apache.openjpa.meta.Order;
-import org.apache.openjpa.meta.QueryMetaData;
-import org.apache.openjpa.meta.SequenceMetaData;
-import org.apache.openjpa.meta.UpdateStrategies;
-import org.apache.openjpa.meta.ValueMetaData;
-import org.apache.openjpa.meta.ValueStrategies;
-import org.apache.openjpa.meta.MetaDataDefaults;
-import static org.apache.openjpa.persistence.MetaDataTag.*;
-import org.apache.openjpa.util.ImplHelper;
-import org.apache.openjpa.util.InternalException;
-import org.apache.openjpa.util.MetaDataException;
-import org.apache.openjpa.util.UnsupportedException;
-import org.apache.openjpa.util.UserException;
-
-import serp.util.Numbers;
-import serp.util.Strings;
-
-/**
- * Persistence annotation metadata parser. Currently does not parse
- * deployment descriptors.
- *
- * @author Abe White
- * @author Steve Kim
- * @nojavadoc
- */
-public class AnnotationPersistenceMetaDataParser
- implements MetaDataModes {
-
- private static final Localizer _loc = Localizer.forPackage
- (AnnotationPersistenceMetaDataParser.class);
-
- private static final Map<Class, MetaDataTag> _tags =
- new HashMap<Class, MetaDataTag>();
-
- static {
- _tags.put(EmbeddedId.class, EMBEDDED_ID);
- _tags.put(EntityListeners.class, ENTITY_LISTENERS);
- _tags.put(ExcludeDefaultListeners.class, EXCLUDE_DEFAULT_LISTENERS);
- _tags.put(ExcludeSuperclassListeners.class,
- EXCLUDE_SUPERCLASS_LISTENERS);
- _tags.put(FlushModeType.class, FLUSH_MODE);
- _tags.put(GeneratedValue.class, GENERATED_VALUE);
- _tags.put(Id.class, ID);
- _tags.put(IdClass.class, ID_CLASS);
- _tags.put(MapKey.class, MAP_KEY);
- _tags.put(NamedNativeQueries.class, NATIVE_QUERIES);
- _tags.put(NamedNativeQuery.class, NATIVE_QUERY);
- _tags.put(NamedQueries.class, QUERIES);
- _tags.put(NamedQuery.class, QUERY);
- _tags.put(OrderBy.class, ORDER_BY);
- _tags.put(PostLoad.class, POST_LOAD);
- _tags.put(PostPersist.class, POST_PERSIST);
- _tags.put(PostRemove.class, POST_REMOVE);
- _tags.put(PostUpdate.class, POST_UPDATE);
- _tags.put(PrePersist.class, PRE_PERSIST);
- _tags.put(PreRemove.class, PRE_REMOVE);
- _tags.put(PreUpdate.class, PRE_UPDATE);
- _tags.put(SequenceGenerator.class, SEQ_GENERATOR);
- _tags.put(Version.class, VERSION);
- _tags.put(DataCache.class, DATA_CACHE);
- _tags.put(DataStoreId.class, DATASTORE_ID);
- _tags.put(Dependent.class, DEPENDENT);
- _tags.put(DetachedState.class, DETACHED_STATE);
- _tags.put(ElementDependent.class, ELEM_DEPENDENT);
- _tags.put(ElementType.class, ELEM_TYPE);
- _tags.put(ExternalValues.class, EXTERNAL_VALS);
- _tags.put(Externalizer.class, EXTERNALIZER);
- _tags.put(Factory.class, FACTORY);
- _tags.put(FetchGroup.class, FETCH_GROUP);
- _tags.put(FetchGroups.class, FETCH_GROUPS);
- _tags.put(InverseLogical.class, INVERSE_LOGICAL);
- _tags.put(KeyDependent.class, KEY_DEPENDENT);
- _tags.put(KeyType.class, KEY_TYPE);
- _tags.put(LoadFetchGroup.class, LOAD_FETCH_GROUP);
- _tags.put(LRS.class, LRS);
- _tags.put(ManagedInterface.class, MANAGED_INTERFACE);
- _tags.put(ReadOnly.class, READ_ONLY);
- _tags.put(Type.class, TYPE);
- }
-
- private final OpenJPAConfiguration _conf;
- private final Log _log;
- private MetaDataRepository _repos = null;
- private ClassLoader _envLoader = null;
- private boolean _override = false;
- private int _mode = MODE_NONE;
-
- // packages and their parse modes
- private final Map<Package, Integer> _pkgs = new HashMap<Package, Integer>();
-
- // the class we were invoked to parse
- private Class _cls = null;
- private File _file = null;
-
- /**
- * Constructor; supply configuration.
- */
- public AnnotationPersistenceMetaDataParser(OpenJPAConfiguration conf) {
- _conf = conf;
- _log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
- }
-
- /**
- * Configuration supplied on construction.
- */
- public OpenJPAConfiguration getConfiguration() {
- return _conf;
- }
-
- /**
- * Metadata log.
- */
- public Log getLog() {
- return _log;
- }
-
- /**
- * Returns the repository for this parser. If none has been set,
- * create a new repository and sets it.
- */
- public MetaDataRepository getRepository() {
- if (_repos == null) {
- MetaDataRepository repos = _conf.newMetaDataRepositoryInstance();
- MetaDataFactory mdf = repos.getMetaDataFactory();
- if (mdf instanceof DelegatingMetaDataFactory)
- mdf = ((DelegatingMetaDataFactory) mdf).getInnermostDelegate();
- if (mdf instanceof PersistenceMetaDataFactory)
- ((PersistenceMetaDataFactory) mdf).setAnnotationParser(this);
- _repos = repos;
- }
- return _repos;
- }
-
- /**
- * Set the metadata repository for this parser.
- */
- public void setRepository(MetaDataRepository repos) {
- _repos = repos;
- }
-
- /**
- * Return the environmental class loader to pass on to parsed
- * metadata instances.
- */
- public ClassLoader getEnvClassLoader() {
- return _envLoader;
- }
-
- /**
- * Set the environmental class loader to pass on to parsed
- * metadata instances.
- */
- public void setEnvClassLoader(ClassLoader loader) {
- _envLoader = loader;
- }
-
- /**
- * Whether to allow later parses of mapping information to override
- * earlier information for the same class. Defaults to false. Useful
- * when a tool is mapping a class, so that annotation partial mapping
- * information can be used even when mappings are stored in another
- * location.
- */
- public boolean getMappingOverride() {
- return _override;
- }
-
- /**
- * Whether to allow later parses of mapping information to override
- * earlier information for the same class. Defaults to false. Useful
- * when a tool is mapping a class, so that annotation partial mapping
- * information can be used even when mappings are stored in another
- * location.
- */
- public void setMappingOverride(boolean override) {
- _override = override;
- }
-
- /**
- * The parse mode.
- */
- public int getMode() {
- return _mode;
- }
-
- /**
- * The parse mode.
- */
- public void setMode(int mode, boolean on) {
- if (mode == MODE_NONE)
- _mode = MODE_NONE;
- else if (on)
- _mode |= mode;
- else
- _mode &= ~mode;
- }
-
- /**
- * The parse mode.
- */
- public void setMode(int mode) {
- _mode = mode;
- }
-
- /**
- * Convenience method for interpreting {@link #getMode}.
- */
- protected boolean isMetaDataMode() {
- return (_mode & MODE_META) != 0;
- }
-
- /**
- * Convenience method for interpreting {@link #getMode}.
- */
- protected boolean isQueryMode() {
- return (_mode & MODE_QUERY) != 0;
- }
-
- /**
- * Convenience method for interpreting {@link #getMode}.
- */
- protected boolean isMappingMode() {
- return (_mode & MODE_MAPPING) != 0;
- }
-
- /**
- * Returns true if we're in mapping mode or in metadata mode with
- * mapping overide enabled.
- */
- protected boolean isMappingOverrideMode() {
- return isMappingMode() || (_override && isMetaDataMode());
- }
-
- /**
- * Clear caches.
- */
- public void clear() {
- _cls = null;
- _file = null;
- _pkgs.clear();
- }
-
- /**
- * Parse persistence metadata for the given class.
- */
- public void parse(Class cls) {
- if (_log.isTraceEnabled())
- _log.trace(_loc.get("parse-class", cls.getName()));
-
- _cls = cls;
- try {
- parsePackageAnnotations();
- ClassMetaData meta = parseClassAnnotations();
- updateSourceMode(meta);
- } finally {
- _cls = null;
- _file = null;
- }
- }
-
- /**
- * Update the source mode to the class package and class to indicate that
- * we've fully parsed them.
- */
- private void updateSourceMode(ClassMetaData meta) {
- if (_cls.getPackage() != null)
- addSourceMode(_cls.getPackage(), _mode);
- if (meta != null)
- meta.setSourceMode(_mode, true);
- }
-
- /**
- * Parse information in package-level class annotations.
- */
- private void parsePackageAnnotations() {
- Package pkg = _cls.getPackage();
- if (pkg == null)
- return;
-
- int pkgMode = getSourceMode(pkg);
- if (pkgMode == 0 && _log.isTraceEnabled())
- _log.trace(_loc.get("parse-package", _cls.getName()));
- if ((pkgMode & _mode) == _mode) // already visited
- return;
-
- MetaDataTag tag;
- for (Annotation anno : pkg.getDeclaredAnnotations()) {
- tag = _tags.get(anno.annotationType());
- if (tag == null) {
- handleUnknownPackageAnnotation(pkg, anno);
- continue;
- }
-
- switch (tag) {
- case NATIVE_QUERIES:
- if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
- parseNamedNativeQueries(pkg,
- ((NamedNativeQueries) anno).value());
- break;
- case NATIVE_QUERY:
- if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
- parseNamedNativeQueries(pkg, (NamedNativeQuery) anno);
- break;
- case QUERIES:
- if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
- parseNamedQueries(pkg, ((NamedQueries) anno).value());
- break;
- case QUERY:
- if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
- parseNamedQueries(pkg, (NamedQuery) anno);
- break;
- case SEQ_GENERATOR:
- if (isMappingOverrideMode() &&
- (pkgMode & MODE_MAPPING) == 0)
- parseSequenceGenerator(pkg, (SequenceGenerator) anno);
- break;
- default:
- throw new UnsupportedException(_loc.get("unsupported", pkg,
- anno.toString()));
- }
- }
-
- // always parse mapping stuff after metadata stuff, in case there are
- // dependencies on metadata
- if (isMappingOverrideMode() && (pkgMode & MODE_MAPPING) == 0)
- parsePackageMappingAnnotations(pkg);
- }
-
- /**
- * Parse package mapping annotations.
- */
- protected void parsePackageMappingAnnotations(Package pkg) {
- }
-
- /**
- * Allow subclasses to handle unknown annotations.
- */
- protected boolean handleUnknownPackageAnnotation(Package pkg,
- Annotation anno) {
- return false;
- }
-
- /**
- * The source mode for the given package.
- */
- private int getSourceMode(Package pkg) {
- Number num = _pkgs.get(pkg);
- return (num == null) ? 0 : num.intValue();
- }
-
- /**
- * Add to the source mode for the given package.
- */
- private void addSourceMode(Package pkg, int mode) {
- Integer num = _pkgs.get(pkg);
- if (num == null)
- num = Numbers.valueOf(mode);
- else
- num = Numbers.valueOf(num.intValue() | mode);
- _pkgs.put(pkg, num);
- }
-
- /**
- * Read annotations for the current type.
- */
- private ClassMetaData parseClassAnnotations() {
- // check immediately whether the user is using any annotations,
- // regardless of mode. this prevents adding non-entity classes to
- // repository if we're ignoring these annotations in mapping mode
- if (!((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
- .isAnnotationPresentAction(_cls, Entity.class))).booleanValue()
- && !((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
- .isAnnotationPresentAction(_cls, Embeddable.class)))
- .booleanValue()
- && !((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
- .isAnnotationPresentAction(_cls, MappedSuperclass.class)))
- .booleanValue())
- return null;
-
- // find / create metadata
- ClassMetaData meta = getMetaData();
- if (meta == null)
- return null;
-
- Entity entity = (Entity) _cls.getAnnotation(Entity.class);
- if (isMetaDataMode()) {
- // while the spec only provides for embedded exclusive, it doesn't
- // seem hard to support otherwise
- if (entity == null)
- meta.setEmbeddedOnly(true);
- else {
- meta.setEmbeddedOnly(false);
- if (!StringUtils.isEmpty(entity.name()))
- meta.setTypeAlias(entity.name());
- }
- }
-
- // track fetch groups to parse them after fields, since they
- // rely on field metadata
- FetchGroup[] fgs = null;
- DetachedState detached = null;
-
- // track listeners since we need to merge them with entity callbacks
- Collection<LifecycleCallbacks>[] listeners = null;
- MetaDataTag tag;
- for (Annotation anno : _cls.getDeclaredAnnotations()) {
- tag = _tags.get(anno.annotationType());
- if (tag == null) {
- handleUnknownClassAnnotation(meta, anno);
- continue;
- }
-
- switch (tag) {
- case ENTITY_LISTENERS:
- if (isMetaDataMode())
- listeners = parseEntityListeners(meta,
- (EntityListeners) anno);
- break;
- case EXCLUDE_DEFAULT_LISTENERS:
- if (isMetaDataMode())
- meta.getLifecycleMetaData()
- .setIgnoreSystemListeners(true);
- break;
- case EXCLUDE_SUPERCLASS_LISTENERS:
- if (isMetaDataMode())
- meta.getLifecycleMetaData().setIgnoreSuperclassCallbacks
- (LifecycleMetaData.IGNORE_HIGH);
- break;
- case FLUSH_MODE:
- if (isMetaDataMode())
- warnFlushMode(meta);
- break;
- case ID_CLASS:
- if (isMetaDataMode())
- meta.setObjectIdType(((IdClass) anno).value(), true);
- break;
- case NATIVE_QUERIES:
- if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
- parseNamedNativeQueries(_cls,
- ((NamedNativeQueries) anno).value());
- break;
- case NATIVE_QUERY:
- if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
- parseNamedNativeQueries(_cls, (NamedNativeQuery) anno);
- break;
- case QUERIES:
- if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
- parseNamedQueries(_cls, ((NamedQueries) anno).value());
- break;
- case QUERY:
- if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
- parseNamedQueries(_cls, (NamedQuery) anno);
- break;
- case SEQ_GENERATOR:
- if (isMappingOverrideMode())
- parseSequenceGenerator(_cls, (SequenceGenerator) anno);
- break;
- case DATA_CACHE:
- if (isMetaDataMode())
- parseDataCache(meta, (DataCache) anno);
- break;
- case DATASTORE_ID:
- if (isMetaDataMode())
- parseDataStoreId(meta, (DataStoreId) anno);
- break;
- case DETACHED_STATE:
- detached = (DetachedState) anno;
- break;
- case FETCH_GROUP:
- if (isMetaDataMode())
- fgs = new FetchGroup[]{ (FetchGroup) anno };
- break;
- case FETCH_GROUPS:
- if (isMetaDataMode())
- fgs = ((FetchGroups) anno).value();
- break;
- case MANAGED_INTERFACE:
- if (isMetaDataMode())
- parseManagedInterface(meta, (ManagedInterface) anno);
- break;
- default:
- throw new UnsupportedException(_loc.get("unsupported", _cls,
- anno.toString()));
- }
- }
-
- if (isMetaDataMode()) {
- parseDetachedState(meta, detached);
-
- // merge callback methods with declared listeners
- int[] highs = null;
- if (listeners != null) {
- highs = new int[listeners.length];
- for (int i = 0; i < listeners.length; i++)
- if (listeners[i] != null)
- highs[i] = listeners[i].size();
- }
- recordCallbacks(meta, parseCallbackMethods(_cls, listeners, false,
- false, getRepository()), highs, false);
-
- // scan possibly non-PC hierarchy for callbacks.
- // redundant for PC superclass but we don't know that yet
- // so let LifecycleMetaData determine that
- if (_cls.getSuperclass() != null &&
- !Object.class.equals(_cls.getSuperclass())) {
- recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
- null, true, false, getRepository()), null, true);
- }
- }
-
- for (FieldMetaData fmd : meta.getDeclaredFields())
- if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
- parseMemberAnnotations(fmd);
- // parse fetch groups after fields
- if (fgs != null)
- parseFetchGroups(meta, fgs);
-
- // always parse mapping after metadata in case there are dependencies
- if (isMappingOverrideMode()) {
- parseClassMappingAnnotations(meta);
- for (FieldMetaData fmd : meta.getDeclaredFields())
- if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
- parseMemberMappingAnnotations(fmd);
- }
- return meta;
- }
-
- /**
- * Parse class mapping annotations.
- */
- protected void parseClassMappingAnnotations(ClassMetaData meta) {
- }
-
- /**
- * Allow subclasses to handle unknown annotations.
- */
- protected boolean handleUnknownClassAnnotation(ClassMetaData meta,
- Annotation anno) {
- return false;
- }
-
- /**
- * Find or create metadata for the given type. May return null if
- * this class has already been parsed fully.
- */
- private ClassMetaData getMetaData() {
- ClassMetaData meta = getRepository().getCachedMetaData(_cls);
- if (meta != null &&
- ((isMetaDataMode() && (meta.getSourceMode() & MODE_META) != 0) ||
- (isMappingMode() &&
- (meta.getSourceMode() & MODE_MAPPING) != 0))) {
- if (_log.isWarnEnabled())
- _log.warn(_loc.get("dup-metadata", _cls.getName()));
- return null;
- }
-
- if (meta == null) {
- meta = getRepository().addMetaData(_cls);
- meta.setEnvClassLoader(_envLoader);
- meta.setSourceMode(MODE_NONE);
- meta.setSource(getSourceFile(), meta.SRC_ANNOTATIONS);
- }
- return meta;
- }
-
- /**
- * Determine the source file we're parsing.
- */
- protected File getSourceFile() {
- if (_file != null)
- return _file;
-
- Class cls = _cls;
- while (cls.getEnclosingClass() != null)
- cls = cls.getEnclosingClass();
-
- String rsrc = StringUtils.replace(cls.getName(), ".", "/");
- ClassLoader loader = (ClassLoader) AccessController.doPrivileged(
- J2DoPriv5Helper.getClassLoaderAction(cls));
- if (loader == null)
- loader = (ClassLoader) AccessController.doPrivileged(
- J2DoPriv5Helper.getSystemClassLoaderAction());
- if (loader == null)
- return null;
- URL url = (URL) AccessController.doPrivileged(
- J2DoPriv5Helper.getResourceAction(loader, rsrc + ".java"));
- if (url == null) {
- url = (URL) AccessController.doPrivileged(
- J2DoPriv5Helper.getResourceAction(loader, rsrc + ".class"));
- if (url == null)
- return null;
- }
- try {
- _file = new File(url.toURI());
- } catch (URISyntaxException e) {
- } catch (IllegalArgumentException iae) {
- // this is thrown when the URI is non-hierarchical (aka JBoss)
- }
- return _file;
- }
-
- /**
- * Parse @DataStoreId.
- */
- private void parseDataStoreId(ClassMetaData meta, DataStoreId id) {
- meta.setIdentityType(ClassMetaData.ID_DATASTORE);
-
- int strat = getGeneratedValueStrategy(meta, id.strategy(),
- id.generator());
- if (strat != -1)
- meta.setIdentityStrategy(strat);
- else {
- switch (id.strategy()) {
- case TABLE:
- case SEQUENCE:
- // technically we should have separate system table and
- // sequence generators, but it's easier to just rely on
- // the system org.apache.openjpa.Sequence setting for both
- if (StringUtils.isEmpty(id.generator()))
- meta.setIdentitySequenceName(
- SequenceMetaData.NAME_SYSTEM);
- else
- meta.setIdentitySequenceName(id.generator());
- break;
- case AUTO:
- meta.setIdentityStrategy(ValueStrategies.NATIVE);
- break;
- case IDENTITY:
- meta.setIdentityStrategy(ValueStrategies.AUTOASSIGN);
- break;
- default:
- throw new UnsupportedException(id.strategy().toString());
- }
- }
- }
-
- /**
- * Warn that @FlushMode is not supported.
- */
- private void warnFlushMode(Object context) {
- if (_log.isWarnEnabled())
- _log.warn(_loc.get("unsupported", "FlushMode", context));
- }
-
- /**
- * Parse @DataCache.
- */
- private void parseDataCache(ClassMetaData meta, DataCache cache) {
- if (cache.timeout() != Integer.MIN_VALUE)
- meta.setDataCacheTimeout(cache.timeout());
- if (!StringUtils.isEmpty(cache.name()))
- meta.setDataCacheName(cache.name());
- else if (cache.enabled())
- meta.setDataCacheName(
- org.apache.openjpa.datacache.DataCache.NAME_DEFAULT);
- else
- meta.setDataCacheName(null);
- }
-
- private void parseManagedInterface(ClassMetaData meta,
- ManagedInterface iface) {
- meta.setManagedInterface(true);
- }
-
- /**
- * Parse @DetachedState. The annotation may be null.
- */
- private void parseDetachedState(ClassMetaData meta,
- DetachedState detached) {
- if (detached != null) {
- if (!detached.enabled())
- meta.setDetachedState(null);
- else if (StringUtils.isEmpty(detached.fieldName()))
- meta.setDetachedState(ClassMetaData.SYNTHETIC);
- else
- meta.setDetachedState(detached.fieldName());
- } else {
- Field[] fields = (Field[]) AccessController.doPrivileged(
- J2DoPriv5Helper.getDeclaredFieldsAction(
- meta.getDescribedType()));
- for (int i = 0; i < fields.length; i++)
- if (((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
- .isAnnotationPresentAction(fields[i], DetachedState.class)))
- .booleanValue())
- meta.setDetachedState(fields[i].getName());
- }
- }
-
- /**
- * Parse @EntityListeners
- */
- private Collection<LifecycleCallbacks>[] parseEntityListeners
- (ClassMetaData meta, EntityListeners listeners) {
- Class[] classes = listeners.value();
- Collection<LifecycleCallbacks>[] parsed = null;
- for (Class cls : classes)
- parsed = parseCallbackMethods(cls, parsed, true, true,
- getRepository());
- return parsed;
- }
-
- /**
- * Parse callback methods into the given array, and return that array,
- * creating one if null. Each index into the array is a collection of
- * callback adapters for that numeric event type.
- *
- * @param sups whether to scan superclasses
- * @param listener whether this is a listener or not
- */
- public static Collection<LifecycleCallbacks>[] parseCallbackMethods
- (Class cls, Collection<LifecycleCallbacks>[] callbacks, boolean sups,
- boolean listener, MetaDataRepository repos) {
-
- if (cls == null)
- throw new IllegalArgumentException("cls cannot be null");
-
- // first sort / filter based on inheritance
- Set<Method> methods = new TreeSet<Method>(MethodComparator.
- getInstance());
-
- int mods;
- Class sup = cls;
- MethodKey key;
- Set<MethodKey> seen = new HashSet<MethodKey>();
- do {
- for (Method m : (Method[]) AccessController.doPrivileged(
- J2DoPriv5Helper.getDeclaredMethodsAction(sup))) {
- mods = m.getModifiers();
- if (Modifier.isStatic(mods) || Modifier.isFinal(mods) ||
- Object.class.equals(m.getDeclaringClass()))
- continue;
-
- key = new MethodKey(m);
- if (!seen.contains(key)) {
- methods.add(m);
- seen.add(key);
- }
- }
- sup = sup.getSuperclass();
- } while (sups && !Object.class.equals(sup));
-
- MetaDataDefaults def = repos.getMetaDataFactory().getDefaults();
- for (Method m : methods) {
- for (Annotation anno : (Annotation[]) AccessController
- .doPrivileged(J2DoPriv5Helper
- .getDeclaredAnnotationsAction(m))) {
- MetaDataTag tag = _tags.get(anno.annotationType());
- if (tag == null)
- continue;
- int[] events = MetaDataParsers.getEventTypes(tag);
- if (events == null)
- continue;
-
- if (callbacks == null)
- callbacks = (Collection<LifecycleCallbacks>[])
- new Collection[LifecycleEvent.ALL_EVENTS.length];
-
- for (int i = 0; i < events.length; i++) {
- int e = events[i];
- if (callbacks[e] == null)
- callbacks[e] = new ArrayList(3);
- MetaDataParsers.validateMethodsForSameCallback(cls,
- callbacks[e], m, tag, def, repos.getLog());
- if (listener) {
- callbacks[e].add(new BeanLifecycleCallbacks(cls, m,
- false));
- } else {
- callbacks[e].add(new MethodLifecycleCallbacks(m,
- false));
- }
- }
- }
- }
- return callbacks;
- }
-
- /**
- * Store lifecycle metadata.
- */
- private void recordCallbacks(ClassMetaData cls,
- Collection<LifecycleCallbacks>[] callbacks, int[] highs,
- boolean superClass) {
- if (callbacks == null)
- return;
- LifecycleMetaData meta = cls.getLifecycleMetaData();
- LifecycleCallbacks[] array;
- for (int event : LifecycleEvent.ALL_EVENTS) {
- if (callbacks[event] == null)
- continue;
- array = callbacks[event].toArray
- (new LifecycleCallbacks[callbacks[event].size()]);
-
- if (superClass) {
- meta.setNonPCSuperclassCallbacks(event, array,
- (highs == null) ? 0 : highs[event]);
- } else {
- meta.setDeclaredCallbacks(event, array,
- (highs == null) ? 0 : highs[event]);
- }
- }
- }
-
- /**
- * Create fetch groups.
- * If FetchGroup A includes FetchGroup B, then a bi-link is set between
- * A and B. Both A and B must be declared in the same Class.
- * <br>
- * Call {@link #parseFetchAttribute(ClassMetaData,
- * org.apache.openjpa.meta.FetchGroup, FetchAttribute) only after the
- * bi-links have been established, because a field f will not only add the
- * fetch group A which explictly includes f to its custom fetch groups but
- * also will also add any fetch group B that includes A.
- */
- private void parseFetchGroups(ClassMetaData meta, FetchGroup... groups) {
- org.apache.openjpa.meta.FetchGroup fg;
- for (FetchGroup group : groups) {
- if (StringUtils.isEmpty(group.name()))
- throw new MetaDataException(_loc.get("unnamed-fg", meta));
-
- fg = meta.addDeclaredFetchGroup(group.name());
- if (group.postLoad())
- fg.setPostLoad(true);
- for (String s : group.fetchGroups()) {
- fg.addDeclaredInclude(s);
- }
- }
- // Add the parent-child style bi-links between fetch groups in a
- // separate pass.
- for (FetchGroup group:groups) {
- fg = meta.getFetchGroup(group.name());
- String[] includedFetchGropNames = fg.getDeclaredIncludes();
- for (String includedFectchGroupName:includedFetchGropNames) {
- org.apache.openjpa.meta.FetchGroup child =
- meta.getFetchGroup(includedFectchGroupName);
- if (child == null)
- throw new UserException(_loc.get("missing-included-fg",
- meta.getDescribedType().getName(), fg.getName(),
- includedFectchGroupName));
- child.addContainedBy(fg);
- }
- }
-
- for (FetchGroup group : groups) {
- fg = meta.getFetchGroup(group.name());
- for (FetchAttribute attr : group.attributes())
- parseFetchAttribute(meta, fg, attr);
- }
- }
-
-
- /**
- * Set a field's fetch group.
- */
- private void parseFetchAttribute(ClassMetaData meta,
- org.apache.openjpa.meta.FetchGroup fg, FetchAttribute attr) {
- FieldMetaData field = meta.getDeclaredField(attr.name());
- if (field == null
- || field.getManagement() != FieldMetaData.MANAGE_PERSISTENT)
- throw new MetaDataException(_loc.get("bad-fg-field", fg.getName(),
- meta, attr.name()));
-
- field.setInFetchGroup(fg.getName(), true);
- Set parentFetchGroups = fg.getContainedBy();
- for (Object parentFetchGroup:parentFetchGroups)
- field.setInFetchGroup(parentFetchGroup.toString(), true);
- if (attr.recursionDepth() != Integer.MIN_VALUE)
- fg.setRecursionDepth(field, attr.recursionDepth());
- }
-
- /**
- * Read annotations for the given member.
- */
- private void parseMemberAnnotations(FieldMetaData fmd) {
- // look for persistence strategy in annotation table
- Member member = getRepository().getMetaDataFactory().getDefaults().
- getBackingMember(fmd);
- PersistenceStrategy pstrat = PersistenceMetaDataDefaults.
- getPersistenceStrategy(fmd, member);
- if (pstrat == null)
- return;
- fmd.setExplicit(true);
-
- AnnotatedElement el = (AnnotatedElement) member;
- boolean lob = ((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
- .isAnnotationPresentAction(el, Lob.class))).booleanValue();
- if (isMetaDataMode()) {
- switch (pstrat) {
- case BASIC:
- parseBasic(fmd, (Basic) el.getAnnotation(Basic.class), lob);
- break;
- case MANY_ONE:
- parseManyToOne(fmd, (ManyToOne) el.getAnnotation
- (ManyToOne.class));
- break;
- case ONE_ONE:
- parseOneToOne(fmd, (OneToOne) el.getAnnotation
- (OneToOne.class));
- break;
- case EMBEDDED:
- parseEmbedded(fmd, (Embedded) el.getAnnotation
- (Embedded.class));
- break;
- case ONE_MANY:
- parseOneToMany(fmd, (OneToMany) el.getAnnotation
- (OneToMany.class));
- break;
- case MANY_MANY:
- parseManyToMany(fmd, (ManyToMany) el.getAnnotation
- (ManyToMany.class));
- break;
- case PERS:
- parsePersistent(fmd, (Persistent) el.getAnnotation
- (Persistent.class));
- break;
- case PERS_COLL:
- parsePersistentCollection(fmd, (PersistentCollection)
- el.getAnnotation(PersistentCollection.class));
- break;
- case PERS_MAP:
- parsePersistentMap(fmd, (PersistentMap)
- el.getAnnotation(PersistentMap.class));
- break;
- case TRANSIENT:
- break;
- default:
- throw new InternalException();
- }
- }
-
- if (isMappingOverrideMode() && lob)
- parseLobMapping(fmd);
-
- // extensions
- MetaDataTag tag;
- for (Annotation anno : el.getDeclaredAnnotations()) {
- tag = _tags.get(anno.annotationType());
- if (tag == null) {
- handleUnknownMemberAnnotation(fmd, anno);
- continue;
- }
-
- switch (tag) {
- case FLUSH_MODE:
- if (isMetaDataMode())
- warnFlushMode(fmd);
- break;
- case GENERATED_VALUE:
- if (isMappingOverrideMode())
- parseGeneratedValue(fmd, (GeneratedValue) anno);
- break;
- case ID:
- case EMBEDDED_ID:
- fmd.setPrimaryKey(true);
- break;
- case MAP_KEY:
- if (isMappingOverrideMode())
- parseMapKey(fmd, (MapKey) anno);
- break;
- case ORDER_BY:
- parseOrderBy(fmd,
- (OrderBy) el.getAnnotation(OrderBy.class));
- break;
- case SEQ_GENERATOR:
- if (isMappingOverrideMode())
- parseSequenceGenerator(el, (SequenceGenerator) anno);
- break;
- case VERSION:
- fmd.setVersion(true);
- break;
- case DEPENDENT:
- if (isMetaDataMode() && ((Dependent) anno).value())
- fmd.setCascadeDelete(ValueMetaData.CASCADE_AUTO);
- break;
- case ELEM_DEPENDENT:
- if (isMetaDataMode() && ((ElementDependent) anno).value())
- fmd.getElement().setCascadeDelete
- (ValueMetaData.CASCADE_AUTO);
- break;
- case ELEM_TYPE:
- if (isMetaDataMode())
- fmd.getElement().setTypeOverride(toOverrideType
- (((ElementType) anno).value()));
- break;
- case EXTERNAL_VALS:
- if (isMetaDataMode())
- fmd.setExternalValues(Strings.join(((ExternalValues)
- anno).value(), ","));
- break;
- case EXTERNALIZER:
- if (isMetaDataMode())
- fmd.setExternalizer(((Externalizer) anno).value());
- break;
- case FACTORY:
- if (isMetaDataMode())
- fmd.setFactory(((Factory) anno).value());
- break;
- case INVERSE_LOGICAL:
- if (isMetaDataMode())
- fmd.setInverse(((InverseLogical) anno).value());
- break;
- case KEY_DEPENDENT:
- if (isMetaDataMode() && ((KeyDependent) anno).value())
- fmd.getKey()
- .setCascadeDelete(ValueMetaData.CASCADE_AUTO);
- break;
- case KEY_TYPE:
- if (isMetaDataMode())
- fmd.getKey().setTypeOverride(toOverrideType(((KeyType)
- anno).value()));
- break;
- case LOAD_FETCH_GROUP:
- if (isMetaDataMode())
- fmd.setLoadFetchGroup(((LoadFetchGroup) anno).value());
- break;
- case LRS:
- if (isMetaDataMode())
- fmd.setLRS(((LRS) anno).value());
- break;
- case READ_ONLY:
- if (isMetaDataMode())
- parseReadOnly(fmd, (ReadOnly) anno);
- break;
- case TYPE:
- if (isMetaDataMode())
- fmd.setTypeOverride(toOverrideType(((Type) anno).
- value()));
- break;
- default:
- throw new UnsupportedException(_loc.get("unsupported", fmd,
- anno.toString()));
- }
- }
- }
-
- /**
- * Parse member mapping components.
- */
- protected void parseMemberMappingAnnotations(FieldMetaData fmd) {
- }
-
- /**
- * Allow subclasses to handle unknown annotations.
- */
- protected boolean handleUnknownMemberAnnotation(FieldMetaData fmd,
- Annotation anno) {
- return false;
- }
-
- /**
- * Convert the given class to its OpenJPA type override equivalent.
- */
- private static Class toOverrideType(Class cls) {
- return (cls == Entity.class)
- ? org.apache.openjpa.enhance.PersistenceCapable.class : cls;
- }
-
- /**
- * Parse @ReadOnly.
- */
- private void parseReadOnly(FieldMetaData fmd, ReadOnly ro) {
- if (ro.value() == UpdateAction.RESTRICT)
- fmd.setUpdateStrategy(UpdateStrategies.RESTRICT);
- else if (ro.value() == UpdateAction.IGNORE)
- fmd.setUpdateStrategy(UpdateStrategies.IGNORE);
- else
- throw new InternalException();
- }
-
- /**
- * Sets value generation information for the given field.
- */
- private void parseGeneratedValue(FieldMetaData fmd, GeneratedValue gen) {
- GenerationType strategy = gen.strategy();
- String generator = gen.generator();
- parseGeneratedValue(fmd, strategy, generator);
- }
-
- /**
- * Sets value generation information for the given field.
- */
- static void parseGeneratedValue(FieldMetaData fmd, GenerationType strategy,
- String generator) {
- int strat = getGeneratedValueStrategy(fmd, strategy, generator);
- if (strat != -1)
- fmd.setValueStrategy(strat);
- else {
- switch (strategy) {
- case TABLE:
- case SEQUENCE:
- // technically we should have separate system table and
- // sequence generators, but it's easier to just rely on
- // the system org.apache.openjpa.Sequence setting for both
- if (StringUtils.isEmpty(generator))
- fmd.setValueSequenceName(SequenceMetaData.NAME_SYSTEM);
- else
- fmd.setValueSequenceName(generator);
- break;
- case AUTO:
- fmd.setValueSequenceName(SequenceMetaData.NAME_SYSTEM);
- break;
- case IDENTITY:
- fmd.setValueStrategy(ValueStrategies.AUTOASSIGN);
- break;
- default:
- throw new UnsupportedException(strategy.toString());
- }
- }
- }
-
- /**
- * Return the value strategy for the given generator, or -1 if the
- * strategy depends on the <code>GenerationType</code> rather than the
- * generator name.
- */
- private static int getGeneratedValueStrategy(Object context,
- GenerationType strategy, String generator) {
- if (strategy != AUTO || StringUtils.isEmpty(generator))
- return -1;
-
- if (Generator.UUID_HEX.equals(generator))
- return ValueStrategies.UUID_HEX;
- if (Generator.UUID_STRING.equals(generator))
- return ValueStrategies.UUID_STRING;
- throw new MetaDataException(_loc.get("generator-bad-strategy",
- context, generator));
- }
-
- /**
- * Parse @Basic. Given annotation may be null.
- */
- private void parseBasic(FieldMetaData fmd, Basic anno, boolean lob) {
- Class type = fmd.getDeclaredType();
- if (lob && type != String.class
- && type != char[].class && type != Character[].class
- && type != byte[].class && type != Byte[].class)
- fmd.setSerialized(true);
- else if (!lob) {
- switch (fmd.getDeclaredTypeCode()) {
- case JavaTypes.OBJECT:
- if (Enum.class.isAssignableFrom(type))
- break;
- // else no break
- case JavaTypes.COLLECTION:
- case JavaTypes.MAP:
- case JavaTypes.PC:
- case JavaTypes.PC_UNTYPED:
- if (Serializable.class.isAssignableFrom(type))
- fmd.setSerialized(true);
- else
- throw new MetaDataException(_loc.get("bad-meta-anno",
- fmd, "Basic"));
- break;
- case JavaTypes.ARRAY:
- if (type == char[].class || type == Character[].class
- || type == byte[].class || type == Byte[].class)
- break;
- if (Serializable.class.isAssignableFrom
- (type.getComponentType()))
- fmd.setSerialized(true);
- else
- throw new MetaDataException(_loc.get("bad-meta-anno",
- fmd, "Basic"));
- break;
- }
- }
-
- if (anno == null)
- return;
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (!anno.optional())
- fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
- }
-
- /**
- * Parse @ManyToOne.
- */
- private void parseManyToOne(FieldMetaData fmd, ManyToOne anno) {
- if (!JavaTypes.maybePC(fmd.getValue()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "ManyToOne"));
-
- // don't specifically exclude relation from DFG b/c that will prevent
- // us from even reading the fk when reading from the primary table,
- // which is not what most users will want
- if (anno.fetch() == FetchType.EAGER)
- fmd.setInDefaultFetchGroup(true);
- if (!anno.optional())
- fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
- if (anno.targetEntity() != void.class)
- fmd.setTypeOverride(anno.targetEntity());
- setCascades(fmd, anno.cascade());
- }
-
- /**
- * Parse @OneToOne.
- */
- private void parseOneToOne(FieldMetaData fmd, OneToOne anno) {
- if (!JavaTypes.maybePC(fmd.getValue()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "OneToOne"));
-
- // don't specifically exclude relation from DFG b/c that will prevent
- // us from even reading the fk when reading from the primary table,
- // which is not what most users will want
- if (anno.fetch() == FetchType.EAGER)
- fmd.setInDefaultFetchGroup(true);
- if (!anno.optional())
- fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
-
- if (isMappingOverrideMode() && !StringUtils.isEmpty(anno.mappedBy()))
- fmd.setMappedBy(anno.mappedBy());
- if (anno.targetEntity() != void.class)
- fmd.setTypeOverride(anno.targetEntity());
- setCascades(fmd, anno.cascade());
- }
-
- /**
- * Parse @Embedded. Given annotation may be null.
- */
- private void parseEmbedded(FieldMetaData fmd, Embedded anno) {
- if (!JavaTypes.maybePC(fmd.getValue()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "Embedded"));
-
- fmd.setInDefaultFetchGroup(true);
- fmd.setEmbedded(true);
- if (fmd.getEmbeddedMetaData() == null)
- fmd.addEmbeddedMetaData();
- }
-
- /**
- * Parse @OneToMany.
- */
- private void parseOneToMany(FieldMetaData fmd, OneToMany anno) {
- switch (fmd.getDeclaredTypeCode()) {
- case JavaTypes.ARRAY:
- case JavaTypes.COLLECTION:
- case JavaTypes.MAP:
- if (JavaTypes.maybePC(fmd.getElement()))
- break;
- // no break
- default:
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "OneToMany"));
- }
-
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (isMappingOverrideMode() && !StringUtils.isEmpty(anno.mappedBy()))
- fmd.setMappedBy(anno.mappedBy());
- if (anno.targetEntity() != void.class)
- fmd.getElement().setDeclaredType(anno.targetEntity());
- setCascades(fmd.getElement(), anno.cascade());
- }
-
- /**
- * Parse @ManyToMany.
- */
- private void parseManyToMany(FieldMetaData fmd, ManyToMany anno) {
- switch (fmd.getDeclaredTypeCode()) {
- case JavaTypes.ARRAY:
- case JavaTypes.COLLECTION:
- case JavaTypes.MAP:
- if (JavaTypes.maybePC(fmd.getElement()))
- break;
- // no break
- default:
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "OneToMany"));
- }
-
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (isMappingOverrideMode() && !StringUtils.isEmpty(anno.mappedBy()))
- fmd.setMappedBy(anno.mappedBy());
- if (anno.targetEntity() != void.class)
- fmd.getElement().setDeclaredType(anno.targetEntity());
- setCascades(fmd.getElement(), anno.cascade());
- }
-
- /**
- * Parse @MapKey.
- */
- private void parseMapKey(FieldMetaData fmd, MapKey anno) {
- String name = anno.name();
- if (StringUtils.isEmpty(name))
- fmd.getKey().setValueMappedBy(ValueMetaData.MAPPED_BY_PK);
- else
- fmd.getKey().setValueMappedBy(name);
- }
-
- /**
- * Setup the field as a LOB mapping.
- */
- protected void parseLobMapping(FieldMetaData fmd) {
- }
-
- /**
- * Parse @OrderBy.
- */
- private void parseOrderBy(FieldMetaData fmd, OrderBy anno) {
- String dec = anno.value();
- if (dec.length() == 0)
- dec = Order.ELEMENT + " asc";
- fmd.setOrderDeclaration(dec);
- }
-
- /**
- * Parse @Persistent.
- */
- private void parsePersistent(FieldMetaData fmd, Persistent anno) {
- switch (fmd.getDeclaredTypeCode()) {
- case JavaTypes.ARRAY:
- if (fmd.getDeclaredType() == byte[].class
- || fmd.getDeclaredType() == Byte[].class
- || fmd.getDeclaredType() == char[].class
- || fmd.getDeclaredType() == Character[].class)
- break;
- // no break
- case JavaTypes.COLLECTION:
- case JavaTypes.MAP:
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "Persistent"));
- }
-
- if (!StringUtils.isEmpty(anno.mappedBy()))
- fmd.setMappedBy(anno.mappedBy());
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (!anno.optional())
- fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
- setCascades(fmd, anno.cascade());
- if (anno.embedded()) {
- if (!JavaTypes.maybePC(fmd.getValue()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "Persistent(embedded=true)"));
- fmd.setEmbedded(true);
- if (fmd.getEmbeddedMetaData() == null)
- fmd.addEmbeddedMetaData();
- }
- }
-
- /**
- * Parse @PersistentCollection.
- */
- private void parsePersistentCollection(FieldMetaData fmd,
- PersistentCollection anno) {
- if (fmd.getDeclaredTypeCode() != JavaTypes.ARRAY
- && fmd.getDeclaredTypeCode() != JavaTypes.COLLECTION)
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "PersistentCollection"));
-
- if (!StringUtils.isEmpty(anno.mappedBy()))
- fmd.setMappedBy(anno.mappedBy());
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (anno.elementType() != void.class)
- fmd.getElement().setDeclaredType(anno.elementType());
- setCascades(fmd.getElement(), anno.elementCascade());
- if (anno.elementEmbedded()) {
- if (!JavaTypes.maybePC(fmd.getElement()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "PersistentCollection(embeddedElement=true)"));
- fmd.getElement().setEmbedded(true);
- if (fmd.getElement().getEmbeddedMetaData() == null)
- fmd.getElement().addEmbeddedMetaData();
- }
- }
-
- /**
- * Parse @PersistentMap.
- */
- private void parsePersistentMap(FieldMetaData fmd, PersistentMap anno) {
- if (fmd.getDeclaredTypeCode() != JavaTypes.MAP)
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "PersistentMap"));
-
- fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
- if (anno.keyType() != void.class)
- fmd.getKey().setDeclaredType(anno.keyType());
- if (anno.elementType() != void.class)
- fmd.getElement().setDeclaredType(anno.elementType());
- setCascades(fmd.getKey(), anno.keyCascade());
- setCascades(fmd.getElement(), anno.elementCascade());
- if (anno.keyEmbedded()) {
- if (!JavaTypes.maybePC(fmd.getKey()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "PersistentMap(embeddedKey=true)"));
- fmd.getKey().setEmbedded(true);
- if (fmd.getKey().getEmbeddedMetaData() == null)
- fmd.getKey().addEmbeddedMetaData();
- }
- if (anno.elementEmbedded()) {
- if (!JavaTypes.maybePC(fmd.getElement()))
- throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
- "PersistentMap(embeddedValue=true)"));
- fmd.getElement().setEmbedded(true);
- if (fmd.getElement().getEmbeddedMetaData() == null)
- fmd.getElement().addEmbeddedMetaData();
- }
- }
-
- /**
- * Set cascades on relation.
- */
- private void setCascades(ValueMetaData vmd, CascadeType[] cascades) {
- for (CascadeType cascade : cascades) {
- if (cascade == CascadeType.ALL || cascade == CascadeType.REMOVE)
- vmd.setCascadeDelete(ValueMetaData.CASCADE_IMMEDIATE);
- if (cascade == CascadeType.ALL || cascade == CascadeType.PERSIST)
- vmd.setCascadePersist(ValueMetaData.CASCADE_IMMEDIATE);
- if (cascade == CascadeType.ALL || cascade == CascadeType.MERGE)
- vmd.setCascadeAttach(ValueMetaData.CASCADE_IMMEDIATE);
- if (cascade == CascadeType.ALL || cascade == CascadeType.REFRESH)
- vmd.setCascadeRefresh(ValueMetaData.CASCADE_IMMEDIATE);
- }
- }
-
- /**
- * Parse @SequenceGenerator.
- */
- private void parseSequenceGenerator(AnnotatedElement el,
- SequenceGenerator gen) {
- String name = gen.name();
- if (StringUtils.isEmpty(name))
- throw new MetaDataException(_loc.get("no-seq-name", el));
-
- if (_log.isTraceEnabled())
- _log.trace(_loc.get("parse-sequence", name));
-
- SequenceMetaData meta = getRepository().getCachedSequenceMetaData
- (name);
- if (meta != null) {
- if (_log.isWarnEnabled())
- _log.warn(_loc.get("dup-sequence", name, el));
- return;
- }
-
- // create new sequence
- meta = getRepository().addSequenceMetaData(name);
- String seq = gen.sequenceName();
- int initial = gen.initialValue();
- int allocate = gen.allocationSize();
- // don't allow initial of 0 b/c looks like def value
- if (initial == 0)
- initial = 1;
-
- // create plugin string from info
- String clsName, props;
- if (StringUtils.isEmpty(seq)) {
- clsName = SequenceMetaData.IMPL_NATIVE;
- props = null;
- } else if (seq.indexOf('(') != -1) // plugin
- {
- clsName = Configurations.getClassName(seq);
- props = Configurations.getProperties(seq);
- seq = null;
- } else {
- clsName = SequenceMetaData.IMPL_NATIVE;
- props = null;
- }
-
- meta.setSequencePlugin(Configurations.getPlugin(clsName, props));
- meta.setSequence(seq);
- meta.setInitialValue(initial);
- meta.setAllocate(allocate);
- meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
- meta.SRC_ANNOTATIONS);
- }
-
- /**
- * Parse @NamedQuery.
- */
- private void parseNamedQueries(AnnotatedElement el, NamedQuery... queries) {
- QueryMetaData meta;
- for (NamedQuery query : queries) {
- if (StringUtils.isEmpty(query.name()))
- throw new MetaDataException(_loc.get("no-query-name", el));
- if (StringUtils.isEmpty(query.query()))
- throw new MetaDataException(_loc.get("no-query-string",
- query.name(), el));
-
- if (_log.isTraceEnabled())
- _log.trace(_loc.get("parse-query", query.name()));
-
- meta = getRepository().getCachedQueryMetaData(null, query.name());
- if (meta != null) {
- if (_log.isWarnEnabled())
- _log.warn(_loc.get("dup-query", query.name(), el));
- continue;
- }
-
- meta = getRepository().addQueryMetaData(null, query.name());
- meta.setQueryString(query.query());
- meta.setLanguage(JPQLParser.LANG_JPQL);
- for (QueryHint hint : query.hints())
- meta.addHint(hint.name(), hint.value());
-
- meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
- meta.SRC_ANNOTATIONS);
- if (isMetaDataMode())
- meta.setSourceMode(MODE_META);
- else if (isMappingMode())
- meta.setSourceMode(MODE_MAPPING);
- else
- meta.setSourceMode(MODE_QUERY);
- }
- }
-
- /**
- * Parse @NamedNativeQuery.
- */
- private void parseNamedNativeQueries(AnnotatedElement el,
- NamedNativeQuery... queries) {
- QueryMetaData meta;
- for (NamedNativeQuery query : queries) {
- if (StringUtils.isEmpty(query.name()))
- throw new MetaDataException(_loc.get("no-native-query-name",
- el));
- if (StringUtils.isEmpty(query.query()))
- throw new MetaDataException(_loc.get("no-native-query-string",
- query.name(), el));
-
- if (_log.isTraceEnabled())
- _log.trace(_loc.get("parse-native-query", query.name()));
-
- meta = getRepository().getCachedQueryMetaData(null, query.name());
- if (meta != null) {
- if (_log.isWarnEnabled())
- _log.warn(_loc.get("dup-query", query.name(), el));
- continue;
- }
-
- meta = getRepository().addQueryMetaData(null, query.name());
- meta.setQueryString(query.query());
- meta.setLanguage(QueryLanguages.LANG_SQL);
- Class res = query.resultClass();
- if (ImplHelper.isManagedType(getConfiguration(), res))
- meta.setCandidateType(res);
- else if (!void.class.equals(res))
- meta.setResultType(res);
-
- if (!StringUtils.isEmpty(query.resultSetMapping()))
- meta.setResultSetMappingName(query.resultSetMapping());
-
- meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
- meta.SRC_ANNOTATIONS);
- if (isMetaDataMode())
- meta.setSourceMode(MODE_META);
- else if (isMappingMode())
- meta.setSourceMode(MODE_MAPPING);
- else
- meta.setSourceMode(MODE_QUERY);
- }
- }
-
- private static class MethodKey {
-
- private final Method _method;
-
- public MethodKey(Method m) {
- _method = m;
- }
-
- public int hashCode() {
- int code = 46 * 12 + _method.getName().hashCode();
- for (Class param : _method.getParameterTypes())
- code = 46 * code + param.hashCode();
- return code;
- }
-
- public boolean equals(Object o) {
- if (!(o instanceof MethodKey))
- return false;
- Method other = ((MethodKey) o)._method;
- if (!_method.getName().equals(other.getName()))
- return false;
- return Arrays.equals(_method.getParameterTypes(),
- other.getParameterTypes());
- }
- }
-
- private static class MethodComparator implements Comparator {
-
- private static MethodComparator INSTANCE = null;
-
- public static MethodComparator getInstance() {
- if (INSTANCE == null)
- INSTANCE = new MethodComparator();
- return INSTANCE;
- }
-
- public int compare(Object o1, Object o2) {
- Method m1 = (Method) o1;
- Method m2 = (Method) o2;
-
- Class c1 = m1.getDeclaringClass();
- Class c2 = m2.getDeclaringClass();
- if (!c1.equals(c2)) {
- if (c1.isAssignableFrom(c2))
- return -1;
- else
- return 1;
- }
- int compare = m1.getName ().compareTo (m2.getName ());
- if (compare == 0)
- return m1.hashCode () - m2.hashCode ();
- return compare;
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence;
+
+import java.io.File;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Embeddable;
+import javax.persistence.Embedded;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.ExcludeDefaultListeners;
+import javax.persistence.ExcludeSuperclassListeners;
+import javax.persistence.FetchType;
+import javax.persistence.FlushModeType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import static javax.persistence.GenerationType.AUTO;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.Lob;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapKey;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.NamedNativeQueries;
+import javax.persistence.NamedNativeQuery;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.OrderBy;
+import javax.persistence.PostLoad;
+import javax.persistence.PostPersist;
+import javax.persistence.PostRemove;
+import javax.persistence.PostUpdate;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+import javax.persistence.QueryHint;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Version;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.event.BeanLifecycleCallbacks;
+import org.apache.openjpa.event.LifecycleCallbacks;
+import org.apache.openjpa.event.LifecycleEvent;
+import org.apache.openjpa.event.MethodLifecycleCallbacks;
+import org.apache.openjpa.kernel.QueryLanguages;
+import org.apache.openjpa.kernel.jpql.JPQLParser;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.J2DoPriv5Helper;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.DelegatingMetaDataFactory;
+import org.apache.openjpa.meta.FieldMetaData;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.meta.LifecycleMetaData;
+import org.apache.openjpa.meta.MetaDataFactory;
+import org.apache.openjpa.meta.MetaDataModes;
+import org.apache.openjpa.meta.MetaDataRepository;
+import org.apache.openjpa.meta.Order;
+import org.apache.openjpa.meta.QueryMetaData;
+import org.apache.openjpa.meta.SequenceMetaData;
+import org.apache.openjpa.meta.UpdateStrategies;
+import org.apache.openjpa.meta.ValueMetaData;
+import org.apache.openjpa.meta.ValueStrategies;
+import org.apache.openjpa.meta.MetaDataDefaults;
+import static org.apache.openjpa.persistence.MetaDataTag.*;
+import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.MetaDataException;
+import org.apache.openjpa.util.UnsupportedException;
+import org.apache.openjpa.util.UserException;
+
+import serp.util.Numbers;
+import serp.util.Strings;
+
+/**
+ * Persistence annotation metadata parser. Currently does not parse
+ * deployment descriptors.
+ *
+ * @author Abe White
+ * @author Steve Kim
+ * @nojavadoc
+ */
+public class AnnotationPersistenceMetaDataParser
+ implements MetaDataModes {
+
+ private static final Localizer _loc = Localizer.forPackage
+ (AnnotationPersistenceMetaDataParser.class);
+
+ private static final Map<Class, MetaDataTag> _tags =
+ new HashMap<Class, MetaDataTag>();
+
+ static {
+ _tags.put(EmbeddedId.class, EMBEDDED_ID);
+ _tags.put(EntityListeners.class, ENTITY_LISTENERS);
+ _tags.put(ExcludeDefaultListeners.class, EXCLUDE_DEFAULT_LISTENERS);
+ _tags.put(ExcludeSuperclassListeners.class,
+ EXCLUDE_SUPERCLASS_LISTENERS);
+ _tags.put(FlushModeType.class, FLUSH_MODE);
+ _tags.put(GeneratedValue.class, GENERATED_VALUE);
+ _tags.put(Id.class, ID);
+ _tags.put(IdClass.class, ID_CLASS);
+ _tags.put(MapKey.class, MAP_KEY);
+ _tags.put(NamedNativeQueries.class, NATIVE_QUERIES);
+ _tags.put(NamedNativeQuery.class, NATIVE_QUERY);
+ _tags.put(NamedQueries.class, QUERIES);
+ _tags.put(NamedQuery.class, QUERY);
+ _tags.put(OrderBy.class, ORDER_BY);
+ _tags.put(PostLoad.class, POST_LOAD);
+ _tags.put(PostPersist.class, POST_PERSIST);
+ _tags.put(PostRemove.class, POST_REMOVE);
+ _tags.put(PostUpdate.class, POST_UPDATE);
+ _tags.put(PrePersist.class, PRE_PERSIST);
+ _tags.put(PreRemove.class, PRE_REMOVE);
+ _tags.put(PreUpdate.class, PRE_UPDATE);
+ _tags.put(SequenceGenerator.class, SEQ_GENERATOR);
+ _tags.put(Version.class, VERSION);
+ _tags.put(DataCache.class, DATA_CACHE);
+ _tags.put(DataStoreId.class, DATASTORE_ID);
+ _tags.put(Dependent.class, DEPENDENT);
+ _tags.put(DetachedState.class, DETACHED_STATE);
+ _tags.put(ElementDependent.class, ELEM_DEPENDENT);
+ _tags.put(ElementType.class, ELEM_TYPE);
+ _tags.put(ExternalValues.class, EXTERNAL_VALS);
+ _tags.put(Externalizer.class, EXTERNALIZER);
+ _tags.put(Factory.class, FACTORY);
+ _tags.put(FetchGroup.class, FETCH_GROUP);
+ _tags.put(FetchGroups.class, FETCH_GROUPS);
+ _tags.put(InverseLogical.class, INVERSE_LOGICAL);
+ _tags.put(KeyDependent.class, KEY_DEPENDENT);
+ _tags.put(KeyType.class, KEY_TYPE);
+ _tags.put(LoadFetchGroup.class, LOAD_FETCH_GROUP);
+ _tags.put(LRS.class, LRS);
+ _tags.put(ManagedInterface.class, MANAGED_INTERFACE);
+ _tags.put(ReadOnly.class, READ_ONLY);
+ _tags.put(Type.class, TYPE);
+ }
+
+ private final OpenJPAConfiguration _conf;
+ private final Log _log;
+ private MetaDataRepository _repos = null;
+ private ClassLoader _envLoader = null;
+ private boolean _override = false;
+ private int _mode = MODE_NONE;
+
+ // packages and their parse modes
+ private final Map<Package, Integer> _pkgs = new HashMap<Package, Integer>();
+
+ // the class we were invoked to parse
+ private Class _cls = null;
+ private File _file = null;
+
+ /**
+ * Constructor; supply configuration.
+ */
+ public AnnotationPersistenceMetaDataParser(OpenJPAConfiguration conf) {
+ _conf = conf;
+ _log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
+ }
+
+ /**
+ * Configuration supplied on construction.
+ */
+ public OpenJPAConfiguration getConfiguration() {
+ return _conf;
+ }
+
+ /**
+ * Metadata log.
+ */
+ public Log getLog() {
+ return _log;
+ }
+
+ /**
+ * Returns the repository for this parser. If none has been set,
+ * create a new repository and sets it.
+ */
+ public MetaDataRepository getRepository() {
+ if (_repos == null) {
+ MetaDataRepository repos = _conf.newMetaDataRepositoryInstance();
+ MetaDataFactory mdf = repos.getMetaDataFactory();
+ if (mdf instanceof DelegatingMetaDataFactory)
+ mdf = ((DelegatingMetaDataFactory) mdf).getInnermostDelegate();
+ if (mdf instanceof PersistenceMetaDataFactory)
+ ((PersistenceMetaDataFactory) mdf).setAnnotationParser(this);
+ _repos = repos;
+ }
+ return _repos;
+ }
+
+ /**
+ * Set the metadata repository for this parser.
+ */
+ public void setRepository(MetaDataRepository repos) {
+ _repos = repos;
+ }
+
+ /**
+ * Return the environmental class loader to pass on to parsed
+ * metadata instances.
+ */
+ public ClassLoader getEnvClassLoader() {
+ return _envLoader;
+ }
+
+ /**
+ * Set the environmental class loader to pass on to parsed
+ * metadata instances.
+ */
+ public void setEnvClassLoader(ClassLoader loader) {
+ _envLoader = loader;
+ }
+
+ /**
+ * Whether to allow later parses of mapping information to override
+ * earlier information for the same class. Defaults to false. Useful
+ * when a tool is mapping a class, so that annotation partial mapping
+ * information can be used even when mappings are stored in another
+ * location.
+ */
+ public boolean getMappingOverride() {
+ return _override;
+ }
+
+ /**
+ * Whether to allow later parses of mapping information to override
+ * earlier information for the same class. Defaults to false. Useful
+ * when a tool is mapping a class, so that annotation partial mapping
+ * information can be used even when mappings are stored in another
+ * location.
+ */
+ public void setMappingOverride(boolean override) {
+ _override = override;
+ }
+
+ /**
+ * The parse mode.
+ */
+ public int getMode() {
+ return _mode;
+ }
+
+ /**
+ * The parse mode.
+ */
+ public void setMode(int mode, boolean on) {
+ if (mode == MODE_NONE)
+ _mode = MODE_NONE;
+ else if (on)
+ _mode |= mode;
+ else
+ _mode &= ~mode;
+ }
+
+ /**
+ * The parse mode.
+ */
+ public void setMode(int mode) {
+ _mode = mode;
+ }
+
+ /**
+ * Convenience method for interpreting {@link #getMode}.
+ */
+ protected boolean isMetaDataMode() {
+ return (_mode & MODE_META) != 0;
+ }
+
+ /**
+ * Convenience method for interpreting {@link #getMode}.
+ */
+ protected boolean isQueryMode() {
+ return (_mode & MODE_QUERY) != 0;
+ }
+
+ /**
+ * Convenience method for interpreting {@link #getMode}.
+ */
+ protected boolean isMappingMode() {
+ return (_mode & MODE_MAPPING) != 0;
+ }
+
+ /**
+ * Returns true if we're in mapping mode or in metadata mode with
+ * mapping overide enabled.
+ */
+ protected boolean isMappingOverrideMode() {
+ return isMappingMode() || (_override && isMetaDataMode());
+ }
+
+ /**
+ * Clear caches.
+ */
+ public void clear() {
+ _cls = null;
+ _file = null;
+ _pkgs.clear();
+ }
+
+ /**
+ * Parse persistence metadata for the given class.
+ */
+ public void parse(Class cls) {
+ if (_log.isTraceEnabled())
+ _log.trace(_loc.get("parse-class", cls.getName()));
+
+ _cls = cls;
+ try {
+ parsePackageAnnotations();
+ ClassMetaData meta = parseClassAnnotations();
+ updateSourceMode(meta);
+ } finally {
+ _cls = null;
+ _file = null;
+ }
+ }
+
+ /**
+ * Update the source mode to the class package and class to indicate that
+ * we've fully parsed them.
+ */
+ private void updateSourceMode(ClassMetaData meta) {
+ if (_cls.getPackage() != null)
+ addSourceMode(_cls.getPackage(), _mode);
+ if (meta != null)
+ meta.setSourceMode(_mode, true);
+ }
+
+ /**
+ * Parse information in package-level class annotations.
+ */
+ private void parsePackageAnnotations() {
+ Package pkg = _cls.getPackage();
+ if (pkg == null)
+ return;
+
+ int pkgMode = getSourceMode(pkg);
+ if (pkgMode == 0 && _log.isTraceEnabled())
+ _log.trace(_loc.get("parse-package", _cls.getName()));
+ if ((pkgMode & _mode) == _mode) // already visited
+ return;
+
+ MetaDataTag tag;
+ for (Annotation anno : pkg.getDeclaredAnnotations()) {
+ tag = _tags.get(anno.annotationType());
+ if (tag == null) {
+ handleUnknownPackageAnnotation(pkg, anno);
+ continue;
+ }
+
+ switch (tag) {
+ case NATIVE_QUERIES:
+ if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
+ parseNamedNativeQueries(pkg,
+ ((NamedNativeQueries) anno).value());
+ break;
+ case NATIVE_QUERY:
+ if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
+ parseNamedNativeQueries(pkg, (NamedNativeQuery) anno);
+ break;
+ case QUERIES:
+ if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
+ parseNamedQueries(pkg, ((NamedQueries) anno).value());
+ break;
+ case QUERY:
+ if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
+ parseNamedQueries(pkg, (NamedQuery) anno);
+ break;
+ case SEQ_GENERATOR:
+ if (isMappingOverrideMode() &&
+ (pkgMode & MODE_MAPPING) == 0)
+ parseSequenceGenerator(pkg, (SequenceGenerator) anno);
+ break;
+ default:
+ throw new UnsupportedException(_loc.get("unsupported", pkg,
+ anno.toString()));
+ }
+ }
+
+ // always parse mapping stuff after metadata stuff, in case there are
+ // dependencies on metadata
+ if (isMappingOverrideMode() && (pkgMode & MODE_MAPPING) == 0)
+ parsePackageMappingAnnotations(pkg);
+ }
+
+ /**
+ * Parse package mapping annotations.
+ */
+ protected void parsePackageMappingAnnotations(Package pkg) {
+ }
+
+ /**
+ * Allow subclasses to handle unknown annotations.
+ */
+ protected boolean handleUnknownPackageAnnotation(Package pkg,
+ Annotation anno) {
+ return false;
+ }
+
+ /**
+ * The source mode for the given package.
+ */
+ private int getSourceMode(Package pkg) {
+ Number num = _pkgs.get(pkg);
+ return (num == null) ? 0 : num.intValue();
+ }
+
+ /**
+ * Add to the source mode for the given package.
+ */
+ private void addSourceMode(Package pkg, int mode) {
+ Integer num = _pkgs.get(pkg);
+ if (num == null)
+ num = Numbers.valueOf(mode);
+ else
+ num = Numbers.valueOf(num.intValue() | mode);
+ _pkgs.put(pkg, num);
+ }
+
+ /**
+ * Read annotations for the current type.
+ */
+ private ClassMetaData parseClassAnnotations() {
+ // check immediately whether the user is using any annotations,
+ // regardless of mode. this prevents adding non-entity classes to
+ // repository if we're ignoring these annotations in mapping mode
+ if (!((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
+ .isAnnotationPresentAction(_cls, Entity.class))).booleanValue()
+ && !((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
+ .isAnnotationPresentAction(_cls, Embeddable.class)))
+ .booleanValue()
+ && !((Boolean) AccessController.doPrivileged(J2DoPriv5Helper
+ .isAnnotationPresentAction(_cls, MappedSuperclass.class)))
+ .booleanValue())
+ return null;
+
+ // find / create metadata
+ ClassMetaData meta = getMetaData();
+ if (meta == null)
+ return null;
+
+ Entity entity = (Entity) _cls.getAnnotation(Entity.class);
+ MappedSuperclass mapped = (MappedSuperclass)
+ _cls.getAnnotation(MappedSuperclass.class);
+ if (isMetaDataMode()) {
+ meta.setAbstract(mapped != null);
+ // while the spec only provides for embedded exclusive, it doesn't
+ // seem hard to support otherwise
+ if (entity == null)
+ meta.setEmbeddedOnly(true);
+ else {
+ meta.setEmbeddedOnly(false);
+ if (!StringUtils.isEmpty(entity.name()))
+ meta.setTypeAlias(entity.name());
+ }
+ }
+
+ // track fetch groups to parse them after fields, since they
+ // rely on field metadata
+ FetchGroup[] fgs = null;
+ DetachedState detached = null;
+
+ // track listeners since we need to merge them with entity callbacks
+ Collection<LifecycleCallbacks>[] listeners = null;
+ MetaDataTag tag;
+ for (Annotation anno : _cls.getDeclaredAnnotations()) {
+ tag = _tags.get(anno.annotationType());
+ if (tag == null) {
+ handleUnknownClassAnnotation(meta, anno);
+ continue;
+ }
+
+ switch (tag) {
+ case ENTITY_LISTENERS:
+ if (isMetaDataMode())
+ listeners = parseEntityListeners(meta,
+ (EntityListeners) anno);
+ break;
+ case EXCLUDE_DEFAULT_LISTENERS:
+ if (isMetaDataMode())
+ meta.getLifecycleMetaData()
+ .setIgnoreSystemListeners(true);
+ break;
+ case EXCLUDE_SUPERCLASS_LISTENERS:
+ if (isMetaDataMode())
+ meta.getLifecycleMetaData().setIgnoreSuperclassCallbacks
+ (LifecycleMetaData.IGNORE_HIGH);
+ break;
+ case FLUSH_MODE:
+ if (isMetaDataMode())
+ warnFlushMode(meta);
+ break;
+ case ID_CLASS:
+ if (isMetaDataMode())
+ meta.setObjectIdType(((IdClass) anno).value(), true);
+ break;
+ case NATIVE_QUERIES:
+ if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
+ parseNamedNativeQueries(_cls,
+ ((NamedNativeQueries) anno).value());
+ break;
+ case NATIVE_QUERY:
+ if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
+ parseNamedNativeQueries(_cls, (NamedNativeQuery) anno);
+ break;
+ case QUERIES:
+ if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
+ parseNamedQueries(_cls, ((NamedQueries) anno).value());
+ break;
+ case QUERY:
+ if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY) == 0)
+ parseNamedQueries(_cls, (NamedQuery) anno);
+ break;
+ case SEQ_GENERATOR:
+ if (isMappingOverrideMode())
+ parseSequenceGenerator(_cls, (SequenceGenerator) anno);
+ break;
+ case DATA_CACHE:
+ if (isMetaDataMode())
+ parseDataCache(meta, (DataCache) anno);
+ break;
+ case DATASTORE_ID:
+ if (isMetaDataMode())
+ parseDataStoreId(meta, (DataStoreId) anno);
+ break;
+ case DETACHED_STATE:
+ detached = (DetachedState) anno;
+ break;
+ case FETCH_GROUP:
+ if (isMetaDataMode())
+ fgs = new FetchGroup[]{ (FetchGroup) anno };
+ break;
+ case FETCH_GROUPS:
+ if (isMetaDataMode())
+ fgs = ((FetchGroups) anno).value();
+ break;
+ case MANAGED_INTERFACE:
+ if (isMetaDataMode())
+ parseManagedInterface(meta, (ManagedInterface) anno);
+ break;
+ default:
+ throw new UnsupportedException(_loc.get("unsupported", _cls,
+ anno.toString()));
+ }
+ }
+
+ if (isMetaDataMode()) {
+ parseDetachedState(meta, detached);
+
+ // merge callback methods with declared listeners
+ int[] highs = null;
+ if (listeners != null) {
+ highs = new int[listeners.length];
+ for (int i = 0; i < listeners.length; i++)
+ if (listeners[i] != null)
+ highs[i] = listeners[i].size();
+ }
+ recordCallbacks(meta, parseCallbackMethods(_cls, listeners, false,
+ false, getRepository()), highs, false);
+
+ // scan possibly non-PC hierarchy for callbacks.
+ // redundant for PC superclass but we don't know that yet
+ // so let LifecycleMetaData determine that
+ if (_cls.getSuperclass() != null &&
+ !Object.class.equals(_cls.getSuperclass())) {
+ recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
+ null, true, false, getRepository()), null, true);
+ }
+ }
+
+ for (FieldMetaData fmd : meta.getDeclaredFields())
+ if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
+ parseMemberAnnotations(fmd);
+ // parse fetch groups after fields
+ if (fgs != null)
+ parseFetchGroups(meta, fgs);
+
+ // always parse mapping after metadata in case there are dependencies
+ if (isMappingOverrideMode()) {
+ parseClassMappingAnnotations(meta);
+ for (FieldMetaData fmd : meta.getDeclaredFields())
+ if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
+ parseMemberMappingAnnotations(fmd);
+ }
+ return meta;
+ }
+
+ /**
+ * Parse class mapping annotations.
[... 1079 lines stripped ...]