Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the "License"). You may not use this file except
* in compliance with the License.
*
* You can obtain a copy of the license at
* glassfish/bootstrap/legal/CDDLv1.0.txt or
* https://glassfish.dev.java.net/public/CDDLv1.0.html.
* See the License for the specific language governing
* permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* HEADER in each file and include the License file at
* glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
* add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your
* own identifying information: Portions Copyright [yyyy]
* [name of copyright owner]
*/
// Copyright (c) 1998, 2007, Oracle. All rights reserved.
package oracle.toplink.essentials.internal.ejb.cmp3.metadata;
import java.io.InputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.spi.PersistenceUnitInfo;
import oracle.toplink.essentials.ejb.cmp3.persistence.Archive;
import oracle.toplink.essentials.ejb.cmp3.persistence.ArchiveFactoryImpl;
import oracle.toplink.essentials.ejb.cmp3.persistence.PersistenceUnitProcessor;
import oracle.toplink.essentials.exceptions.PersistenceUnitLoadingException;
import oracle.toplink.essentials.exceptions.ValidationException;
import oracle.toplink.essentials.internal.ejb.cmp3.EntityManagerSetupImpl;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataLogger;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataClass;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.accessors.XMLClassAccessor;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLConstants;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLValidator;
import oracle.toplink.essentials.internal.sessions.AbstractSession;
import oracle.toplink.essentials.logging.AbstractSessionLog;
import oracle.toplink.essentials.logging.SessionLog;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The object/relational metadata processor for the EJB3.0 specification.
*
* @author Guy Pelletier, [email protected]
* @since TopLink EJB 3.0 Reference Implementation
*/
public class MetadataProcessor {
/*
* Design Pattern in use: Builder pattern
* EntityManagerSetupImpl, MetadataProcessor and MetadataProject
* play the role of director, builder and product respectively.
*/
protected ClassLoader m_loader;
protected MetadataLogger m_logger;
protected MetadataProject m_project;
protected MetadataValidator m_validator;
protected AbstractSession m_session;
/**
* INTERNAL:
* Called from EntityManagerSetupImpl. The 'real' EJB 3.0 processing
* that includes XML and annotations.
*/
public MetadataProcessor(PersistenceUnitInfo puInfo, AbstractSession session, ClassLoader loader, boolean enableLazyForOneToOne) {
m_loader = loader;
m_session = session;
m_logger = new MetadataLogger(session);
m_project = new MetadataProject(puInfo, session, enableLazyForOneToOne);
}
/**
* INTERNAL:
* Called from RelationshipWeaverTestSuite. Use this constructor to avoid
* XML processing.
* @deprecated
*/
public MetadataProcessor(AbstractSession session, ClassLoader loader, Collection entities, boolean enableLazyForOneToOne) {
m_loader = loader;
m_project = new MetadataProject(null, session, enableLazyForOneToOne);
m_session = session;
Collection entityNames = new HashSet(entities.size());
for (Class entity : entities) {
m_project.addDescriptor(new MetadataDescriptor(entity));
entityNames.add(entity.getName());
}
m_project.setEntityNames(entityNames);
}
/**
* INTERNAL:
* Method to place EntityListener's on the descriptors from the given
* session. This call is made from the EntityManagerSetup deploy call.
*/
public void addEntityListeners() {
for (MetadataDescriptor descriptor: m_project.getDescriptors()) {
// Process all descriptors that are in our project.
ClassAccessor accessor = descriptor.getClassAccessor();
descriptor.setJavaClass(descriptor.getClassDescriptor().getJavaClass());
// The class loader has changed, update the class stored for
// our class accessor and its list of mapped superclasses.
accessor.setAnnotatedElement(descriptor.getJavaClass());
accessor.clearMappedSuperclasses();
accessor.processListeners(m_loader);
}
}
/**
* INTERNAL:
* Method to place NamedQueries and NamedNativeQueries on the given session.
* This call is made from the EntityManagerSetup deploy call.
*/
public void addNamedQueries() {
m_project.processNamedQueries(m_validator);
m_project.processNamedNativeQueries(m_loader);
}
/**
* INTERNAL:
* Return a set of class names for each entity found in the xml
* descriptor instance document.
*/
private static Set buildEntityClassSetFromXMLDocument(Document document, String fileName, ClassLoader loader) {
XMLHelper helper = new XMLHelper(document, fileName, loader);
// Process the package node.
String defaultPkg = helper.getNodeValue(new String[] {XMLConstants.ENTITY_MAPPINGS, XMLConstants.PACKAGE, XMLConstants.TEXT});
// Handle entities only. Mapped superclasses and embeddables are
// discovered and processed separately.
HashSet classSet = new HashSet();
classSet.addAll(buildEntityClassSetForNodeList(helper, XMLConstants.ENTITY, defaultPkg));
return classSet;
}
/**
* INTERNAL:
* The class name of each node in the node list will be added to the
* provided collection.
*/
private static Set buildEntityClassSetForNodeList(XMLHelper helper, String xPath, String defaultPkg) {
HashSet classNames = new HashSet();
NodeList nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, xPath);
int nodeCount = nodes.getLength();
for (int i = 0; i < nodeCount; i++) {
// Process the required class attribute node.
classNames.add(XMLHelper.getFullyQualifiedClassName(helper.getNode(nodes.item(i), XMLConstants.ATT_CLASS).getNodeValue(), defaultPkg));
}
return classNames;
}
/**
* INTERNAL:
* Return the logger used by the processor.
*/
public MetadataLogger getLogger() {
return m_logger;
}
/**
* INTERNAL:
*/
public MetadataProject getProject() {
return m_project;
}
/**
* INTERNAL:
* Return the validator used by the processor.
*/
public MetadataValidator getValidator() {
return m_validator;
}
/**
* INTERNAL:
* Called from RelationshipWeaverTestSuite which uses only annotations
* and no XML.
*/
public void processAnnotations() {
// Set the correct contextual validator.
m_validator = new MetadataValidator();
// take a copy of the collection to avoid concurrent modification exception
// that would result when embeddables are added lazily.
for (MetadataDescriptor descriptor:
m_project.getDescriptors().toArray(new MetadataDescriptor[]{})) {
// Process all descriptors that are in our project.
ClassAccessor accessor = descriptor.getClassAccessor();
// If there is no accessor on this descriptor then it has not been
// processed yet. Create one and process it.
if (accessor == null) {
accessor = new ClassAccessor(new MetadataClass(descriptor.getJavaClass()), this, descriptor);
descriptor.setClassAccessor(accessor);
accessor.process();
}
}
// Process the project and anything that was deferred like
// sequencing and relationship mappings and we are done.
m_project.process();
}
/**
* INTERNAL:
* Process persistence unit metadata and defaults, and apply them to each
* entity in the collection. Any conflicts in elements defined in multiple
* documents will cause an exception to be thrown. The first instance
* encountered wins, i.e. any conflicts between PU metadata definitions in
* multiple instance documents will cause an exception to be thrown. The
* one exception to this rule is default listeners: all default listeners
* found will be added to a list in the order that they are read from the
* instance document(s).
*/
public void processPersistenceUnitMetadata() {
// For each orm xml instance document, process persistence unit
// metadata/defaults and mapped superclasses.
for (Map.Entry mfDocPair : m_project.getMappingFiles().entrySet()) {
// Initialize a helper for navigating the instance document.
XMLHelper helper = new XMLHelper(mfDocPair.getValue(), mfDocPair.getKey().getFile(), m_loader);
// Store all mapped-superclasses.
NodeList nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.MAPPED_SUPERCLASS);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Class cls = helper.getNodeValue(nodes.item(i), XMLConstants.ATT_CLASS, void.class);
m_project.addMappedSuperclass(cls, node, helper);
}
// Store all embeddable classes.
nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.EMBEDDABLE);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Class cls = helper.getNodeValue(nodes.item(i), XMLConstants.ATT_CLASS, void.class);
m_project.addEmbeddable(cls, node, helper);
}
// Look for a persistence-unit-metadata node.
Node persistenceUnitMetadataNode = helper.getNode(new String[] {XMLConstants.ENTITY_MAPPINGS, XMLConstants.PU_METADATA});
if (persistenceUnitMetadataNode != null) {
MetadataPersistenceUnit persistenceUnit = new MetadataPersistenceUnit();
// Process the xml-mapping-metadata-complete tag.
persistenceUnit.setIsMetadataComplete(helper.getNode(persistenceUnitMetadataNode, XMLConstants.METADATA_COMPLETE) != null);
// process persistence unit defaults
Node persistenceUnitDefaultsNode = helper.getNode(persistenceUnitMetadataNode, XMLConstants.PU_DEFAULTS);
if (persistenceUnitDefaultsNode != null) {
// Process the persistence unit access.
persistenceUnit.setAccess(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.ACCESS));
// Process the persitence unit schema.
persistenceUnit.setSchema(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.SCHEMA));
// Process the persistence unit catalog.
persistenceUnit.setCatalog(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.CATALOG));
// Process the persistence unit cascade-persist.
persistenceUnit.setIsCascadePersist(helper.getNode(persistenceUnitDefaultsNode, XMLConstants.CASCADE_PERSIST) != null);
// Process the default entity-listeners. No conflict
// checking will be done, that is, any and all
// default listeners will be added to the project.
NodeList listenerNodes = helper.getNodes(persistenceUnitDefaultsNode, XMLConstants.ENTITY_LISTENERS, XMLConstants.ENTITY_LISTENER);
if (listenerNodes != null) {
m_project.addDefaultListeners(listenerNodes, helper);
}
}
// Add the metadata persistence unit to the project if
// there is no conflicting metadata (from other
// persistence unit metadata)
MetadataPersistenceUnit existingPersistenceUnit = m_project.getPersistenceUnit();
if (existingPersistenceUnit != null) {
if (! existingPersistenceUnit.equals(persistenceUnit)) {
(new XMLValidator()).throwPersistenceUnitMetadataConflict(existingPersistenceUnit.getConflict());
}
} else {
m_project.setPersistenceUnit(persistenceUnit);
}
}
}
}
/**
* INTERNAL:
* Use this method to set the correct class loader that should be used
* during processing.
*/
public void setClassLoader(ClassLoader loader) {
m_loader = loader;
}
/**
* This method is responsible for figuring out list of mapping files
* to be read for a persistence unit and storing that list in
* {@link MetadataProject}.
* @param throwExceptionOnFail
*/
public void readMappingFiles(boolean throwExceptionOnFail) {
// Initialize the correct contextual objects.
m_validator = new XMLValidator();
// step #1: discover all the standard XML mapping files.
Map list = readStandardMappingFiles();
// step #2: add URLs corresponding to explicitly specified files
list.putAll(readExplicitlySpecifiedMappingFiles(throwExceptionOnFail));
m_project.setMappingFiles(list);
}
private Map readStandardMappingFiles() {
Map list = new HashMap();
final PersistenceUnitInfo puInfo = m_project.getPUInfo();
Collection rootUrls = new HashSet(puInfo.getJarFileUrls());
rootUrls.add(puInfo.getPersistenceUnitRootUrl());
final String ormXMLFile = "META-INF/orm.xml";
for(URL rootURL : rootUrls) {
logMessage("Searching for default mapping file in " + rootURL); // NOI18N
URL ormURL = null;
InputStream stream = null;
try {
Archive m_par = null;
m_par = new ArchiveFactoryImpl().createArchive(rootURL);
ormURL = m_par.getEntryAsURL(ormXMLFile);
stream = m_par.getEntry(ormXMLFile);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
if (stream != null){
logMessage("Found a default mapping file at " + ormURL + " for root URL " + rootURL); // NOI18N
try {
Document document = XMLHelper.parseDocument(stream, ormURL.getFile(), m_loader);
list.put(ormURL, document);
} finally {
try{
stream.close();
} catch (IOException e) {}
}
}
}
return list;
}
private Map readExplicitlySpecifiedMappingFiles(
boolean throwExceptionOnFail) {
Map list = new HashMap();
final PersistenceUnitInfo puInfo = m_project.getPUInfo();
for (String mf : puInfo.getMappingFileNames()) {
try {
Enumeration mfURLs = m_loader.getResources(mf);
if (mfURLs.hasMoreElements()) {
URL nextURL = mfURLs.nextElement();
if(mfURLs.hasMoreElements()) {
handleORMException(ValidationException.nonUniqueMappingFileName(puInfo.getPersistenceUnitName(), mf), mf, throwExceptionOnFail);
}
InputStream stream = null;
stream = nextURL.openStream();
Document document = XMLHelper.parseDocument(stream, nextURL.getFile(), m_loader);
list.put(nextURL, document);
try{
stream.close();
} catch (IOException e) {}
} else {
handleORMException(ValidationException.mappingFileNotFound(puInfo.getPersistenceUnitName(), mf), mf, throwExceptionOnFail);
}
} catch (IOException e) {
handleORMException(
PersistenceUnitLoadingException.exceptionLoadingORMXML(mf, e),
mf, throwExceptionOnFail);
}
}
return list;
}
/**
* Handle an exception that occured while processing ORM xml
*/
private void handleORMException(
RuntimeException e,
String mf,
boolean throwException){
if (m_session == null){
// Metadata processor is mainly used with a session.
// Java SE bootstraping uses some functions such as ORM processing without
// a session. In these cases, it is impossible to get the
// session to properly handle the exception. As a result we
// log an error. The same code will be called later in the bootstrapping
// code and the error will be handled then.
AbstractSessionLog.getLog().log(SessionLog.CONFIG,
EntityManagerSetupImpl.ERROR_LOADING_XML_FILE,
new Object[] {mf, e});
} else if (!throwException) {
// fail quietly
m_session.log(SessionLog.CONFIG,
SessionLog.EJB_OR_METADATA,
EntityManagerSetupImpl.ERROR_LOADING_XML_FILE,
new Object[] {mf, e});
} else {
// fail loudly
m_session.handleException(e);
}
}
/**
* This method is responsible for discovering all the entity classes
* for this PU and adding corresponding MetadataDescriptor in the
* MetadataProject. Don't call this method more than once.
*/
public void buildEntityList() {
Set classNames = buildEntityClassSetFromAnnotations();
// append the list of entity classes that are defined in the XML descriptor
classNames.addAll(buildEntityClassSetFromXMLDocuments());
m_project.setEntityNames(classNames);
// Add a metadata descriptor to the project for every entity class.
// Any persistence unit metadata/defaults will be applied
for (String className : classNames) {
try {
m_project.addDescriptor(
new MetadataDescriptor(m_loader.loadClass(className)));
} catch (ClassNotFoundException e) {
AbstractSessionLog.getLog().log(SessionLog.WARNING,
"exception_loading_entity_class", className, e);
}
}
}
/**
* Return a set of class names that are annotated as either @Entity
* from the base URL of this PersistenceUnit
*/
private Set buildEntityClassSetFromAnnotations() {
Set set = new HashSet();
PersistenceUnitInfo puInfo = m_project.getPUInfo();
for (String className : puInfo.getManagedClassNames()) {
if (PersistenceUnitProcessor.isEntity(className, m_loader, true)) {
set.add(className);
}
}
for (URL url : puInfo.getJarFileUrls()) {
set.addAll(PersistenceUnitProcessor.getEntityClassNamesFromURL(url, m_loader));
}
if (!puInfo.excludeUnlistedClasses()){
set.addAll(PersistenceUnitProcessor.getEntityClassNamesFromURL(
puInfo.getPersistenceUnitRootUrl(), m_loader));
}
return set;
}
/**
* INTERNAL:
* Return a set of class names for each entity found in the
* list of xml descriptor instance documents to be processed by the
* MetadataProcessor.
*
* @return
*/
public Set buildEntityClassSetFromXMLDocuments() {
HashSet classSet = new HashSet();
for (Map.Entry urlToDoc :
m_project.getMappingFiles().entrySet()) {
classSet.addAll(buildEntityClassSetFromXMLDocument(
urlToDoc.getValue(), urlToDoc.getKey().getFile(), m_loader));
}
return classSet;
}
/**
* INTERNAL:
* Process metadata found in all the mapping files for this PU.
* @see #processMappingFile(org.w3c.dom.Document, String)
*/
public void processMappingFiles() {
for (Map.Entry urlToDocPair : m_project.getMappingFiles().entrySet()) {
processMappingFile(urlToDocPair.getValue(), urlToDocPair.getKey().getFile());
}
}
/**
* Process the xml and fill in the project. Process the entity-mappings
* information then process the entities.
*/
private void processMappingFile(Document document, String fileName) {
if (m_project.hasDescriptors()) {
XMLHelper helper = new XMLHelper(document, fileName, m_loader);
// Process the entity mappings ... this is a crude way of doing
// things ... but hey ... the clock is ticking ...
MetadataDescriptor desc = m_project.getDescriptors().iterator().next();
XMLClassAccessor dummyAccessor = new XMLClassAccessor(new MetadataClass(desc.getJavaClass()), null, helper, this, desc);
dummyAccessor.processEntityMappings();
// Process the entity nodes for this xml document.
NodeList entityNodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.ENTITY);
if (entityNodes != null) {
for (int i = 0; i < entityNodes.getLength(); i++) {
Node entityNode = entityNodes.item(i);
Class entityClass = helper.getClassForNode(entityNode);
MetadataDescriptor descriptor = m_project.getDescriptor(entityClass);
// Process all descriptors that are in our project.
ClassAccessor accessor = descriptor.getClassAccessor();
// If there is no accessor on this descriptor then it has not
// been processed yet. Create one and process it.
if (accessor == null) {
accessor = new XMLClassAccessor(new MetadataClass(descriptor.getJavaClass()), entityNode, helper, this, descriptor);
descriptor.setClassAccessor(accessor);
accessor.process();
}
}
}
} else {
// WIP - log a warning that we have no entities to process ...
}
}
/**
* This method frees up resources acquired by this object.
*/
public void cleanup() {
m_project.cleanup();
m_loader = null;
m_project = null;
m_session = null;
}
/**
* Log an untranslated message to the TopLink log at FINER level.
* @param msg message to be logged
*/
private void logMessage(String msg) {
if (m_session == null){
AbstractSessionLog.getLog().log(SessionLog.FINER, msg);
} else {
m_session.logMessage(msg);
}
}
}