Package org.apache.cloudstack.spring.module.model.impl

Source Code of org.apache.cloudstack.spring.module.model.impl.DefaultModuleDefinitionSet$ConfigContext

/*
* 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.cloudstack.spring.module.model.impl;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;

import org.apache.cloudstack.spring.module.context.ResourceApplicationContext;
import org.apache.cloudstack.spring.module.model.ModuleDefinition;
import org.apache.cloudstack.spring.module.model.ModuleDefinitionSet;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.util.StringUtils;

public class DefaultModuleDefinitionSet implements ModuleDefinitionSet {

    private static final Logger log = LoggerFactory.getLogger(DefaultModuleDefinitionSet.class);
   
    public static final String DEFAULT_CONFIG_RESOURCES = "DefaultConfigResources";
    public static final String DEFAULT_CONFIG_PROPERTIES = "DefaultConfigProperties";
    public static final String MODULES_EXCLUDE = "modules.exclude";
    public static final String MODULES_INCLUDE_PREFIX = "modules.include.";
    public static final String MODULE_PROPERITES = "ModuleProperties";
    public static final String DEFAULT_CONFIG_XML = "defaults-context.xml";
   
    String root;
    Map<String, ModuleDefinition> modules;
    Map<String, ApplicationContext> contexts = new HashMap<String, ApplicationContext>();
    ApplicationContext rootContext = null;
    Set<String> excludes = new HashSet<String>();
    Properties configProperties = null;

    public DefaultModuleDefinitionSet(Map<String, ModuleDefinition> modules, String root) {
        super();
        this.root = root;
        this.modules = modules;
    }

    public void load() throws IOException {
        if ( ! loadRootContext() )
            return;
       
        printHierarchy();
        loadContexts();
        startContexts();
    }
   
    protected boolean loadRootContext() {
        ModuleDefinition def = modules.get(root);
       
        if ( def == null )
            return false;
       
        ApplicationContext defaultsContext = getDefaultsContext();
       
        rootContext = loadContext(def, defaultsContext);
       
        return true;
    }
   
    protected void startContexts() {
        withModule(new WithModule() {
            public void with(ModuleDefinition def, Stack<ModuleDefinition> parents) {
                try {
                    ApplicationContext context = getApplicationContext(def.getName());
                    try {
                        Runnable runnable = context.getBean("moduleStartup", Runnable.class);
                        log.info("Starting module [{}]", def.getName());
                        runnable.run();
                    } catch ( BeansException e ) {
                       // Ignore
                    }
                } catch ( EmptyStackException e ) {
                    // The root context is already loaded, so ignore the exception
                }
            }
        });
    }
   
    protected void loadContexts() {
        withModule(new WithModule() {
            public void with(ModuleDefinition def, Stack<ModuleDefinition> parents) {
                try {
                    ApplicationContext parent = getApplicationContext(parents.peek().getName());
                    loadContext(def, parent);
                } catch ( EmptyStackException e ) {
                    // The root context is already loaded, so ignore the exception
                }
            }
        });
    }
    protected ApplicationContext loadContext(ModuleDefinition def, ApplicationContext parent) {
        ResourceApplicationContext context = new ResourceApplicationContext();
        context.setApplicationName("/" + def.getName());
       
        Resource[] resources = getConfigResources(def.getName());
        context.setConfigResources(resources);
        context.setParent(parent);
        context.setClassLoader(def.getClassLoader());

        long start = System.currentTimeMillis();
        if ( log.isInfoEnabled() ) {
            for ( Resource resource : resources ) {
                log.info("Loading module context [{}] from {}", def.getName(), resource);
            }
        }
        context.refresh();
        log.info("Loaded module context [{}] in {} ms", def.getName(), (System.currentTimeMillis() - start));
       
        contexts.put(def.getName(), context);
       
        return context;
    }
   
    protected boolean shouldLoad(ModuleDefinition def) {
        return ! excludes.contains(def.getName());
    }
   
    protected ApplicationContext getDefaultsContext() {
        URL config = DefaultModuleDefinitionSet.class.getResource(DEFAULT_CONFIG_XML);
       
        ResourceApplicationContext context = new ResourceApplicationContext(new UrlResource(config));
        context.setApplicationName("/defaults");
        context.refresh();
       
        @SuppressWarnings("unchecked")
        final List<Resource> resources = (List<Resource>) context.getBean(DEFAULT_CONFIG_RESOURCES);
       
        withModule(new WithModule() {
            public void with(ModuleDefinition def, Stack<ModuleDefinition> parents) {
                for ( Resource defaults : def.getConfigLocations() ) {
                    resources.add(defaults);
                }
            }
        });

        configProperties = (Properties) context.getBean(DEFAULT_CONFIG_PROPERTIES);
        for ( Resource resource : resources ) {
            load(resource, configProperties);
        }

        for ( Resource resource : (Resource[])context.getBean(MODULE_PROPERITES) ) {
            load(resource, configProperties);
        }

        parseExcludes();

        return context;
    }

    protected void parseExcludes() {
        for ( String exclude : configProperties.getProperty(MODULES_EXCLUDE, "").trim().split("\\s*,\\s*") ) {
            if ( StringUtils.hasText(exclude) ) {
                excludes.add(exclude);
            }
        }

        for ( String key : configProperties.stringPropertyNames() ) {
            if ( key.startsWith(MODULES_INCLUDE_PREFIX) ) {
                String module = key.substring(MODULES_INCLUDE_PREFIX.length());
                boolean include = configProperties.getProperty(key).equalsIgnoreCase("true");
                if ( ! include ) {
                    excludes.add(module);
                }
            }
        }
    }

    protected void load(Resource resource, Properties props) {
        InputStream is = null;
        try {
            if ( resource.exists() ) {
                is = resource.getInputStream();
                props.load(is);
            }
        } catch (IOException e) {
            throw new IllegalStateException("Failed to load resource [" + resource + "]", e);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }
   
    protected void printHierarchy() {
        withModule(new WithModule() {
            public void with(ModuleDefinition def, Stack<ModuleDefinition> parents) {
                log.info(String.format("Module Hierarchy:%" + ((parents.size() * 2) + 1) + "s%s", "", def.getName()));
            }
        });
    }
   
    protected void withModule(WithModule with) {
        ModuleDefinition rootDef = modules.get(root);
        withModule(rootDef, new Stack<ModuleDefinition>(), with);
    }
   
    protected void withModule(ModuleDefinition def, Stack<ModuleDefinition> parents, WithModule with) {
        if ( def == null )
            return;
       
        if ( ! shouldLoad(def) ) {
            log.info("Excluding context [{}] based on configuration", def.getName());
            return;
        }
       
        with.with(def, parents);
       
        parents.push(def);
       
        for ( ModuleDefinition child : def.getChildren() ) {
            withModule(child, parents, with);
        }
       
        parents.pop();
    }
   
    private static interface WithModule {
        public void with(ModuleDefinition def, Stack<ModuleDefinition> parents);
    }
   
    @Configuration
    public static class ConfigContext {
       
        List<Resource> resources;
       
        public ConfigContext(List<Resource> resources) {
            super();
            this.resources = resources;
        }

        @Bean(name = DEFAULT_CONFIG_RESOURCES)
        public List<Resource> defaultConfigResources() {
            return new ArrayList<Resource>();
        }
    }

    public ApplicationContext getApplicationContext(String name) {
        return contexts.get(name);
    }

    public Resource[] getConfigResources(String name) {
        Set<Resource> resources = new LinkedHashSet<Resource>();
       
        ModuleDefinition original = null;
        ModuleDefinition def = original = modules.get(name);
       
        if ( def == null )
            return new Resource[] {};
       
        resources.addAll(def.getContextLocations());
       
        while ( def != null ) {
            resources.addAll(def.getInheritableContextLocations());
            def = modules.get(def.getParentName());
        }
       
        resources.addAll(original.getOverrideContextLocations());
       
        return resources.toArray(new Resource[resources.size()]);
    }

    public ModuleDefinition getModuleDefinition(String name) {
        return modules.get(name);
    }
}
TOP

Related Classes of org.apache.cloudstack.spring.module.model.impl.DefaultModuleDefinitionSet$ConfigContext

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.