Package org.apache.geronimo.persistence.builder

Source Code of org.apache.geronimo.persistence.builder.PersistenceRefBuilder

/**
*  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.geronimo.persistence.builder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;
import org.apache.geronimo.common.DeploymentException;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.gbean.GBeanData;
import org.apache.geronimo.gbean.annotation.GBean;
import org.apache.geronimo.gbean.annotation.ParamAttribute;
import org.apache.geronimo.j2ee.annotation.ReferenceType;
import org.apache.geronimo.j2ee.deployment.EARContext;
import org.apache.geronimo.j2ee.deployment.Module;
import org.apache.geronimo.j2ee.deployment.annotation.PersistenceContextAnnotationHelper;
import org.apache.geronimo.j2ee.deployment.annotation.PersistenceUnitAnnotationHelper;
import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
import org.apache.geronimo.kernel.GBeanNotFoundException;
import org.apache.geronimo.kernel.config.Configuration;
import org.apache.geronimo.kernel.repository.Environment;
import org.apache.geronimo.naming.deployment.AbstractNamingBuilder;
import org.apache.geronimo.naming.reference.PersistenceContextReference;
import org.apache.geronimo.naming.reference.PersistenceUnitReference;
import org.apache.geronimo.schema.NamespaceElementConverter;
import org.apache.geronimo.schema.SchemaConversionUtils;
import org.apache.geronimo.xbeans.geronimo.naming.GerPatternType;
import org.apache.geronimo.xbeans.geronimo.naming.GerPersistenceContextRefDocument;
import org.apache.geronimo.xbeans.geronimo.naming.GerPersistenceContextRefType;
import org.apache.geronimo.xbeans.geronimo.naming.GerPersistenceContextTypeType;
import org.apache.geronimo.xbeans.geronimo.naming.GerPersistenceUnitRefDocument;
import org.apache.geronimo.xbeans.geronimo.naming.GerPersistenceUnitRefType;
import org.apache.geronimo.xbeans.geronimo.naming.GerPropertyType;
import org.apache.openejb.jee.InjectionTarget;
import org.apache.openejb.jee.JndiConsumer;
import org.apache.openejb.jee.PersistenceContextRef;
import org.apache.openejb.jee.PersistenceContextType;
import org.apache.openejb.jee.PersistenceRef;
import org.apache.openejb.jee.PersistenceUnitRef;
import org.apache.openejb.jee.Property;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.XmlObject;

/**
* @version $Rev: 1329978 $ $Date: 2012-04-25 04:01:45 +0800 (Wed, 25 Apr 2012) $
*/
@GBean(j2eeType = NameFactory.MODULE_BUILDER)
public class PersistenceRefBuilder extends AbstractNamingBuilder {
    private static final QName PERSISTENCE_UNIT_REF_QNAME = new QName(JEE_NAMESPACE, "persistence-unit-ref");
    private static final QNameSet PERSISTENCE_UNIT_REF_QNAME_SET = QNameSet.singleton(PERSISTENCE_UNIT_REF_QNAME);
    private static final QName GER_PERSISTENCE_UNIT_REF_QNAME = GerPersistenceUnitRefDocument.type.getDocumentElementName();
    private static final QNameSet GER_PERSISTENCE_UNIT_REF_QNAME_SET = QNameSet.singleton(GER_PERSISTENCE_UNIT_REF_QNAME);
    private static final Set PERSISTENCE_UNIT_INTERFACE_TYPES = Collections.singleton("org.apache.geronimo.persistence.PersistenceUnitGBean");
    private static final QName GER_PERSISTENCE_CONTEXT_REF_QNAME = GerPersistenceContextRefDocument.type.getDocumentElementName();
    private static final QNameSet GER_PERSISTENCE_CONTEXT_REF_QNAME_SET = QNameSet.singleton(GER_PERSISTENCE_CONTEXT_REF_QNAME);
    private final AbstractNameQuery defaultPersistenceUnitAbstractNameQuery;
    private final boolean strictMatching;


    public PersistenceRefBuilder(@ParamAttribute(name = "defaultEnvironment") Environment defaultEnvironment,
                                 @ParamAttribute(name = "defaultPersistenceUnitAbstractNameQuery") AbstractNameQuery defaultPersistenceUnitAbstractNameQuery,
                                 @ParamAttribute(name = "strictMatching") boolean strictMatching) {
        super(defaultEnvironment);
        this.defaultPersistenceUnitAbstractNameQuery = defaultPersistenceUnitAbstractNameQuery;
        this.strictMatching = strictMatching;
    }

    protected boolean willMergeEnvironment(JndiConsumer specDD, XmlObject plan) throws DeploymentException {
        if (specDD != null && !specDD.getPersistenceUnitRef().isEmpty()) {
            return true;
        }
        return plan != null && plan.selectChildren(PersistenceRefBuilder.GER_PERSISTENCE_UNIT_REF_QNAME_SET).length > 0;
    }

    public void buildNaming(JndiConsumer specDD, XmlObject plan, Module module, Map<EARContext.Key, Object> sharedContext) throws DeploymentException {
        Configuration localConfiguration = module.getEarContext().getConfiguration();
        List<DeploymentException> problems = new ArrayList<DeploymentException>();

        // Discover and process any @PersistenceUnitRef and @PersistenceContextRef annotations (if !metadata-complete)
        if (module.getClassFinder() != null) {
            processAnnotations(specDD, module);
        }

        //persistenceUnit refs
        Collection<PersistenceUnitRef> specPersistenceUnitRefsUntyped = specDD.getPersistenceUnitRef();
        Map<String, GerPersistenceUnitRefType> gerPersistenceUnitRefsUntyped = getGerPersistenceUnitRefs(plan);
        for (Map.Entry<String, PersistenceUnitRef> entry : specDD.getPersistenceUnitRefMap().entrySet()) {
            try {
                String persistenceUnitRefName = entry.getKey();
                PersistenceUnitRef persistenceUnitRef = entry.getValue();
                AbstractNameQuery persistenceUnitNameQuery;
                GerPersistenceUnitRefType gerPersistenceUnitRef = gerPersistenceUnitRefsUntyped.remove(persistenceUnitRefName);
                if (gerPersistenceUnitRef != null) {
                    persistenceUnitNameQuery = findPersistenceUnit(gerPersistenceUnitRef, localConfiguration);
                } else {
                    persistenceUnitNameQuery = findPersistenceUnitQuery(module, localConfiguration, persistenceUnitRef);
                }

                PersistenceUnitReference reference = new PersistenceUnitReference(module.getConfigId(), persistenceUnitNameQuery);

                put(persistenceUnitRefName, reference, ReferenceType.PERSISTENCE_UNIT, module.getJndiContext(), persistenceUnitRef.getInjectionTarget(), sharedContext);
            } catch (DeploymentException e) {
                problems.add(e);
            }

        }
        //geronimo-only persistence unit refs have no injections
        for (GerPersistenceUnitRefType gerPersistenceUnitRef : gerPersistenceUnitRefsUntyped.values()) {
            try {
                String persistenceUnitRefName = gerPersistenceUnitRef.getPersistenceUnitRefName();
                AbstractNameQuery persistenceUnitNameQuery = findPersistenceUnit(gerPersistenceUnitRef, localConfiguration);
                PersistenceUnitReference reference = new PersistenceUnitReference(module.getConfigId(), persistenceUnitNameQuery);
                put(persistenceUnitRefName, reference, ReferenceType.PERSISTENCE_UNIT, module.getJndiContext(), Collections.<InjectionTarget>emptySet(), sharedContext);
            } catch (DeploymentException e) {
                problems.add(e);
            }
        }


        //persistence context refs
        Collection<PersistenceContextRef> specPersistenceContextRefsUntyped = specDD.getPersistenceContextRef();
        Map<String, GerPersistenceContextRefType> gerPersistenceContextRefsUntyped = getGerPersistenceContextRefs(plan);
        for (Map.Entry<String, PersistenceContextRef> entry : specDD.getPersistenceContextRefMap().entrySet()) {
            try {
                String persistenceContextRefName = entry.getKey();
                PersistenceContextRef persistenceContextRef = entry.getValue();
                PersistenceContextType persistenceContextType = persistenceContextRef.getPersistenceContextType();
                boolean transactionScoped = persistenceContextType == null || persistenceContextType.equals(PersistenceContextType.TRANSACTION);

                List<Property> propertyTypes = persistenceContextRef.getPersistenceProperty();
                Map<String, String> properties = new HashMap<String, String>();
                for (Property propertyType : propertyTypes) {
                    String key = propertyType.getName();
                    String value = propertyType.getValue();
                    properties.put(key, value);
                }

                AbstractNameQuery persistenceUnitNameQuery;
                GerPersistenceContextRefType gerPersistenceContextRef = gerPersistenceContextRefsUntyped.remove(persistenceContextRefName);
                if (gerPersistenceContextRef != null) {
                    persistenceUnitNameQuery = findPersistenceUnit(gerPersistenceContextRef, localConfiguration);
                    addProperties(gerPersistenceContextRef, properties);
                } else {
                    persistenceUnitNameQuery = findPersistenceUnitQuery(module, localConfiguration, persistenceContextRef);
                }
                PersistenceContextReference reference = new PersistenceContextReference(module.getConfigId(), persistenceUnitNameQuery, transactionScoped, properties);
                put(persistenceContextRefName, reference, ReferenceType.PERSISTENCE_CONTEXT, module.getJndiContext(), persistenceContextRef.getInjectionTarget(), sharedContext);
            } catch (DeploymentException e) {
                problems.add(e);
            }
        }

        // Support persistence context refs that are mentioned only in the geronimo plan
        for (GerPersistenceContextRefType gerPersistenceContextRef : gerPersistenceContextRefsUntyped.values()) {
            try {
                String persistenceContextRefName = gerPersistenceContextRef.getPersistenceContextRefName();
                GerPersistenceContextTypeType.Enum persistenceContextType = gerPersistenceContextRef.getPersistenceContextType();
                boolean transactionScoped = persistenceContextType == null || !persistenceContextType.equals(GerPersistenceContextTypeType.EXTENDED);
                Map<String, String> properties = new HashMap<String, String>();
                addProperties(gerPersistenceContextRef, properties);
                AbstractNameQuery persistenceUnitNameQuery = findPersistenceUnit(gerPersistenceContextRef, localConfiguration);
                PersistenceContextReference reference = new PersistenceContextReference(module.getConfigId(), persistenceUnitNameQuery, transactionScoped, properties);
                put(persistenceContextRefName, reference, ReferenceType.PERSISTENCE_CONTEXT, module.getJndiContext(), Collections.<InjectionTarget> emptySet(), sharedContext);
            } catch (DeploymentException e) {
                problems.add(e);
            }

        }

        if (!problems.isEmpty()) {
            throw new DeploymentException("At least one deployment problem:", problems);
        }
    }

    private AbstractNameQuery findPersistenceUnitQuery(Module module, Configuration localConfiguration, PersistenceRef persistenceRef) throws DeploymentException {
        AbstractNameQuery persistenceUnitNameQuery;
        if (persistenceRef.getPersistenceUnitName() != null && !persistenceRef.getPersistenceUnitName().trim().isEmpty()) {
            String persistenceUnitName = persistenceRef.getPersistenceUnitName().trim();
            persistenceUnitNameQuery = findPersistenceUnit(module, localConfiguration, persistenceUnitName);
        } else {
            LinkedHashSet<GBeanData> gbeans = new LinkedHashSet<GBeanData>();
            do {
                AbstractName childName = module.getEarContext().getNaming().createChildName(module.getModuleName(), "", NameFactory.PERSISTENCE_UNIT);
                Map<String, String> name = new HashMap<String, String>(childName.getName());
                name.remove(NameFactory.J2EE_NAME);
               
                persistenceUnitNameQuery = new AbstractNameQuery(null, name, PERSISTENCE_UNIT_INTERFACE_TYPES);
                Set<AbstractNameQuery> patterns = Collections.singleton(persistenceUnitNameQuery);
                gbeans = localConfiguration.findGBeanDatas(module.getEarContext().getConfiguration(), patterns);
               
                if (!gbeans.isEmpty()) {
                    persistenceUnitNameQuery = checkForDefaultPersistenceUnit(gbeans);
                    break;
                }
                               
                module = module.getParentModule();
            } while(module!=null);
           
            if (gbeans.isEmpty()) {
                if (defaultPersistenceUnitAbstractNameQuery == null) {
                    throw new DeploymentException("No default PersistenceUnit specified, and none located");
                }
                persistenceUnitNameQuery = defaultPersistenceUnitAbstractNameQuery;
            }
            checkForGBean(localConfiguration, persistenceUnitNameQuery, false, false, new HashSet<AbstractName>());
        }
        return persistenceUnitNameQuery;
    }

    private AbstractNameQuery findPersistenceUnit(Module module, Configuration localConfiguration, String persistenceUnitName) throws DeploymentException {
        AbstractNameQuery persistenceUnitNameQuery;
        //First try unrestricted search using provided name
        Map<String, String> nameMap = new HashMap<String, String>();
        nameMap.put("j2eeType", NameFactory.PERSISTENCE_UNIT);
        nameMap.put("name", persistenceUnitName);
        //Do not set configId, so the query will work on both server and application client sides
        persistenceUnitNameQuery = new AbstractNameQuery(null, nameMap, PERSISTENCE_UNIT_INTERFACE_TYPES);
        Set<AbstractName> matches = new HashSet<AbstractName>();
        switch (checkForGBean(localConfiguration, persistenceUnitNameQuery, strictMatching, true, matches)) {
            case 1:
                return persistenceUnitNameQuery;
            case 0:
                //try unrestricted search on name persistence/<name>
                persistenceUnitName = "persistence/" + persistenceUnitName;
                nameMap.put("name", persistenceUnitName);
                persistenceUnitNameQuery = new AbstractNameQuery(null, nameMap, PERSISTENCE_UNIT_INTERFACE_TYPES);
                if (1 == checkForGBean(localConfiguration, persistenceUnitNameQuery, false, true, new HashSet<AbstractName>())) {
                    return persistenceUnitNameQuery;
                }
            case 2:
        }
        //there was more than one match, and if necessary persistence/ was prepended to the name.
        AbstractName childName = module.getEarContext().getNaming().createChildName(module.getModuleName(), persistenceUnitName, NameFactory.PERSISTENCE_UNIT);
        persistenceUnitNameQuery = new AbstractNameQuery(null, childName.getName(), PERSISTENCE_UNIT_INTERFACE_TYPES);
        try {
            checkForGBean(localConfiguration, persistenceUnitNameQuery, false, false, new HashSet<AbstractName>());
            return persistenceUnitNameQuery;
        } catch (DeploymentException e) {
            //
            for (Iterator<AbstractName> i = matches.iterator(); i.hasNext();) {
                AbstractName abstractName = i.next();
                if (isParentModule(abstractName.getName(), childName.getName())) {
                    return new AbstractNameQuery(abstractName.getArtifact(), abstractName.getName(), PERSISTENCE_UNIT_INTERFACE_TYPES);
                }
            }
            throw e;
        }
    }

    private static String getModuleType(Map name) {
        if (name.containsKey(NameFactory.WEB_MODULE))  {
            return NameFactory.WEB_MODULE;
        } else if (name.containsKey(NameFactory.EJB_MODULE)) {
            return NameFactory.EJB_MODULE;
        } else if (name.containsKey(NameFactory.APP_CLIENT_MODULE)) {
            return NameFactory.APP_CLIENT_MODULE;
        } else if (name.containsKey(NameFactory.APP_CLIENT_MODULE)) {
            return NameFactory.APP_CLIENT_MODULE;
        } else {
            return null;
        }
    }

    private boolean isParentModule(Map parent, Map child) {
        String parentModuleType = getModuleType(parent);
        String childModuleType = getModuleType(child);
        if (parentModuleType == null && childModuleType != null) {
            return true;
        } else {
            return false;
        }
    }


    private static int checkForGBean(Configuration localConfiguration, AbstractNameQuery persistenceQuery, boolean allowNone, boolean allowMultiple, Set<AbstractName> matches) throws DeploymentException {
        try {
            localConfiguration.findGBeanData(persistenceQuery);
            return 1;
        } catch (GBeanNotFoundException e) {
            if (e.hasMatches()) {
                if (allowMultiple) {
                    matches.addAll(e.getMatches());
                    return 2;
                }
                throw new DeploymentException("More than one reference at deploy time for query " + persistenceQuery + ". " + e.getMatches(), e);
            } else if (allowNone) {
                return 0;
            }
            throw new DeploymentException("No references found at deploy time for query " + persistenceQuery, e);
        }
    }

    private static AbstractNameQuery checkForDefaultPersistenceUnit(LinkedHashSet<GBeanData> gbeans) throws DeploymentException {
        AbstractNameQuery persistenceUnitNameQuery = null;
        for (java.util.Iterator it = gbeans.iterator(); it.hasNext();) {
            GBeanData gbean = (GBeanData) it.next();
            AbstractName name = gbean.getAbstractName();
            Map nameMap = name.getName();
            if ("cmp".equals(nameMap.get("name"))) {
                it.remove();
            } else {
                persistenceUnitNameQuery = new AbstractNameQuery(null, name.getName());
            }
        }
        if (gbeans.size() > 1) {
            throw new DeploymentException("Too many matches for no-name persistence unit: " + gbeans);
        }
        return persistenceUnitNameQuery;
    }

    private void processAnnotations(JndiConsumer specDD, Module module) throws DeploymentException {
        // Process all the annotations for this naming builder type
        PersistenceUnitAnnotationHelper.processAnnotations(specDD, module.getClassFinder());
        PersistenceContextAnnotationHelper.processAnnotations(specDD, module.getClassFinder());
    }

    private AbstractNameQuery findPersistenceUnit(GerPersistenceUnitRefType gerPersistenceRef, Configuration localConfiguration) throws DeploymentException {
        AbstractNameQuery persistenceUnitNameQuery;
        if (gerPersistenceRef.isSetPersistenceUnitName()) {
            String persistenceUnitName = gerPersistenceRef.getPersistenceUnitName();
            persistenceUnitNameQuery = new AbstractNameQuery(null, Collections.singletonMap("name", persistenceUnitName), PERSISTENCE_UNIT_INTERFACE_TYPES);
        } else {
            GerPatternType gbeanLocator = gerPersistenceRef.getPattern();

            persistenceUnitNameQuery = buildAbstractNameQuery(gbeanLocator, null, null, PERSISTENCE_UNIT_INTERFACE_TYPES);
        }
        checkForGBean(localConfiguration, persistenceUnitNameQuery, false, false, new HashSet<AbstractName>());
        return persistenceUnitNameQuery;
    }

    private AbstractNameQuery findPersistenceUnit(GerPersistenceContextRefType persistenceContextRef, Configuration localConfiguration) throws DeploymentException {
        AbstractNameQuery persistenceUnitNameQuery;
        if (persistenceContextRef.isSetPersistenceUnitName()) {
            String persistenceUnitName = persistenceContextRef.getPersistenceUnitName();
            persistenceUnitNameQuery = new AbstractNameQuery(null, Collections.singletonMap("name", persistenceUnitName), PERSISTENCE_UNIT_INTERFACE_TYPES);
        } else {
            GerPatternType gbeanLocator = persistenceContextRef.getPattern();

            persistenceUnitNameQuery = buildAbstractNameQuery(gbeanLocator, null, null, PERSISTENCE_UNIT_INTERFACE_TYPES);
        }
        checkForGBean(localConfiguration, persistenceUnitNameQuery, false, false, new HashSet<AbstractName>());
        return persistenceUnitNameQuery;
    }

    public QNameSet getSpecQNameSet() {
        SchemaConversionUtils.registerNamespaceConversions(Collections.singletonMap(PersistenceRefBuilder.GER_PERSISTENCE_UNIT_REF_QNAME.getLocalPart(), new NamespaceElementConverter(PersistenceRefBuilder.GER_PERSISTENCE_UNIT_REF_QNAME.getNamespaceURI())));
        return PERSISTENCE_UNIT_REF_QNAME_SET;
    }

    public QNameSet getPlanQNameSet() {
        return GER_PERSISTENCE_UNIT_REF_QNAME_SET;
    }

    private Map<String, GerPersistenceUnitRefType> getGerPersistenceUnitRefs(XmlObject plan) throws DeploymentException {
        Map<String, GerPersistenceUnitRefType> map = new HashMap<String, GerPersistenceUnitRefType>();
        if (plan != null) {
            List<GerPersistenceUnitRefType> refs = convert(plan.selectChildren(PersistenceRefBuilder.GER_PERSISTENCE_UNIT_REF_QNAME_SET), NAMING_CONVERTER, GerPersistenceUnitRefType.class, GerPersistenceUnitRefType.type);
            for (GerPersistenceUnitRefType ref : refs) {
                map.put(getJndiName(ref.getPersistenceUnitRefName().trim()), ref);
            }
        }
        return map;
    }

    private void addProperties(GerPersistenceContextRefType persistenceContextRef, Map<String, String> properties) {
        GerPropertyType[] propertyTypes = persistenceContextRef.getPropertyArray();
        for (GerPropertyType propertyType : propertyTypes) {
            String key = propertyType.getKey();
            String value = propertyType.getValue();
            properties.put(key, value);
        }
    }

    private Map<String, GerPersistenceContextRefType> getGerPersistenceContextRefs(XmlObject plan) throws DeploymentException {
        Map<String, GerPersistenceContextRefType> map = new HashMap<String, GerPersistenceContextRefType>();
        if (plan != null) {
            List<GerPersistenceContextRefType> refs = convert(plan.selectChildren(GER_PERSISTENCE_CONTEXT_REF_QNAME_SET), NAMING_CONVERTER, GerPersistenceContextRefType.class, GerPersistenceContextRefType.type);
            for (GerPersistenceContextRefType ref : refs) {
                map.put(getJndiName(ref.getPersistenceContextRefName().trim()), ref);
            }
        }
        return map;
    }


}
TOP

Related Classes of org.apache.geronimo.persistence.builder.PersistenceRefBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.