All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadleafcommerce.common.extensibility.context.EmbeddedBeanDefinitionParser Maven / Gradle / Ivy

/*
 * #%L
 * BroadleafCommerce Common Libraries
 * %%
 * Copyright (C) 2009 - 2014 Broadleaf Commerce
 * %%
 * Licensed 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.
 * #L%
 */
package org.broadleafcommerce.common.extensibility.context;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.exception.ExceptionHelper;
import org.broadleafcommerce.common.extensibility.context.merge.ImportProcessor;
import org.broadleafcommerce.common.extensibility.context.merge.exceptions.MergeException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;

/**
 * Provides merged xml bean import into a declaring Spring application context. Generally, implementation overrides and custom
 * beans are included in a client implementation's war file and declared in a patchConfigLocations context-param in web.xml, which
 * is utilized by {@link org.broadleafcommerce.common.web.extensibility.MergeContextLoaderListener}. However, in some circumstances,
 * it may be desirable to load all the Broadleaf Commerce Spring beans into a declaring application context without the
 * aid of MergeContextLoaderListener. A sample use case for this would be a system that needs to run Broadleaf Commerce
 * as a set of embedded services, perhaps not inside of a traditional web container. Usage is as follows:
 *
 * {@code
 * 
 *     
 *     ...
 * 
 * }
 *
 * Since a new custom namespace is introduced, this special syntax requires the introduction of a new schema into app context
 * xml:
 *
 * {@code
 * 
 * }
 *
 * Note the introduction of the new embedded namespace. Using this syntax, Broadleaf Commerce merge functionality can be
 * achieved on a declared list of app context files and the resulting merged app context will be imported into the
 * declaring app context. This is conceptually similar to Spring's standard {@code } syntax for
 * importing additional app context xml files.
 *
 * @author Jeff Fischer
 */
public class EmbeddedBeanDefinitionParser extends AbstractBeanDefinitionParser {

    private static Log LOG = LogFactory.getLog(EmbeddedBeanDefinitionParser.class);

    @Override
    protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
        try {
            String[] broadleafConfigLocations = StandardConfigLocations.retrieveAll(StandardConfigLocations.APPCONTEXTTYPE);

            ArrayList sources = new ArrayList(20);
            for (String location : broadleafConfigLocations) {
                InputStream source = getClass().getClassLoader().getResourceAsStream(location);
                if (source != null) {
                    sources.add(new ResourceInputStream(source, location));
                }
            }
            ResourceInputStream[] filteredSources = new ResourceInputStream[]{};
            filteredSources = sources.toArray(filteredSources);

            List locations = new ArrayList();
            List overrideItemElements = DomUtils.getChildElementsByTagName(element, "location");
            for (Element overrideItem : overrideItemElements) {
                String location = overrideItem.getAttribute("value");
                Resource[] resources = ((ResourcePatternResolver) parserContext.getReaderContext().getResourceLoader()).getResources(location);
                if (ArrayUtils.isEmpty(resources)) {
                    LOG.warn("Unable to find the resource: " + location);
                } else {
                    locations.add(resources[0]);
                }
            }

            ResourceInputStream[] patches = new ResourceInputStream[locations.size()];
            for (int i = 0; i < locations.size(); i++) {
                patches[i] = new ResourceInputStream(locations.get(i).getInputStream(), locations.get(i).getDescription());

                if (patches[i] == null || patches[i].available() <= 0) {
                    throw new IOException("Unable to open an input stream on specified application context resource: " + locations.get(i).getDescription());
                }
            }

            ImportProcessor importProcessor = new ImportProcessor(parserContext.getReaderContext().getResourceLoader());
            try {
                filteredSources = importProcessor.extract(filteredSources);
                patches = importProcessor.extract(patches);
            } catch (MergeException e) {
                throw new FatalBeanException("Unable to merge source and patch locations", e);
            }

            Resource[] resources = new MergeApplicationContextXmlConfigResource().getConfigResources(filteredSources, patches);
            parserContext.getReaderContext().getReader().loadBeanDefinitions(resources[0]);
            return null;
        } catch (IOException e) {
            throw ExceptionHelper.refineException(e);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy