Package org.wso2.carbon.base

Source Code of org.wso2.carbon.base.ServerConfiguration

/*
* Copyright 2005,2006 WSO2, Inc. http://www.wso2.org
*
* 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.
*/
package org.wso2.carbon.base;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.securevault.SecretResolver;
import org.wso2.securevault.SecretResolverFactory;
import org.w3c.dom.Element;
import org.wso2.carbon.securevault.SecretManagerInitializer;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.stream.XMLStreamException;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
* This class stores the configuration of the Carbon Server.
*/
@SuppressWarnings("unused")
public class ServerConfiguration {

    /**
     * Classes which are allowed to directly call secured methods in this class
     * <p/>
     * Note that we have to use the String form of the class name and not, for example,
     * RegistryResolver.class.getName() since this may unnecessarily cause NoClassDefFoundErrors
     */
    private static final List<String> ALLOWED_CLASSES =
            Arrays.asList(ServerConfiguration.class.getName(),
                    "org.wso2.carbon.utils.CarbonUtils",
                    "org.wso2.carbon.registry.core.utils.RegistryUtils",
                    "org.wso2.carbon.utils.logging.TenantAwarePatternLayout$TenantAwarePatternParser$ServiceNamePatternConverter");

    /**
     * Constant to be used for properties storing the axis2 repository location.
     */
    public static final String AXIS2_CONFIG_REPO_LOCATION = "Axis2Config.RepositoryLocation";

    /**
     * Constant to be used for properties storing the http port of the servlet transport.
     */
    public static final String HTTP_PORT = "HTTP.Port";

    /**
     * Constant to be used for properties storing the port of the command listener.
     */
    public static final String COMMAND_LISTENER_PORT = "CommandListener.Port";

    private static Log log = LogFactory.getLog(ServerConfiguration.class);

    private Map<String, List<String>> configuration = new HashMap<String, List<String>>();
    private boolean isInitialized;
    private boolean isLoadedConfigurationPreserved = false;
    private String documentXML;
    private SecretResolver secretResolver;
    /**
     * Stores the singleton server configuration instance.
     */
    private static ServerConfiguration instance = new ServerConfiguration();

    /**
     * Method to retrieve an instance of the server configuration.
     *
     * @return instance of the server configuration
     */
    public static ServerConfiguration getInstance() {
        // Need permissions in order to instantiate ServerConfiguration
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        return instance;
    }

    // Private constructor preventing creation of duplicate instances.

    private ServerConfiguration() {
    }

    /**
     * This initializes the server configuration. This method should only be called once, for
     * successive calls, it will be checked.
     *
     * @param xmlInputStream the server configuration file stream.
     *
     * @throws ServerConfigurationException if the operation failed.
     */
    public synchronized void init(InputStream xmlInputStream) throws ServerConfigurationException {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        if (isInitialized) {
            return;
        }

        if (!isLoadedConfigurationPreserved) {
            configuration.clear();
        }

        OMElement documentElement;
        try {
            documentElement = new StAXOMBuilder(xmlInputStream).getDocumentElement();
            SecretManagerInitializer secretManagerInitializer = new SecretManagerInitializer();
            secretManagerInitializer.init();
            secretResolver = SecretResolverFactory.create(documentElement, true);          
            Stack<String> nameStack = new Stack<String>();
            readChildElements(documentElement, nameStack);
            isInitialized = true;
            isLoadedConfigurationPreserved = false;
            documentXML = documentElement.toStringWithConsume();
        } catch (XMLStreamException e) {
            log.fatal("Problem in parsing the configuration file ", e);
            throw new ServerConfigurationException(e);
        }
    }

    /**
     * This initializes the server configuration. This method should only be called once, for
     * successive calls, it will be checked.
     *
     * @param configurationXMLLocation the location of the server configuration file (carbon.xml).
     *
     * @throws ServerConfigurationException if the operation failed.
     */
    public synchronized void init(String configurationXMLLocation)
            throws ServerConfigurationException {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        if (isInitialized) {
            return;
        }
        if (configurationXMLLocation == null) {
            configurationXMLLocation = "conf/carbon.xml";
        }

        InputStream xmlInputStream = null;
        try {
            try {
                //URL will parse the location according to respective RFC's and open a connection.
                URL urlXMLLocation = new URL(configurationXMLLocation);
                xmlInputStream = urlXMLLocation.openStream();
            } catch (MalformedURLException e) {
                File f = new File(configurationXMLLocation);
                try {
                    xmlInputStream = new FileInputStream(f);
                } catch (FileNotFoundException e1) {
                    // As a last resort test in the classpath
                    ClassLoader cl = ServerConfiguration.class.getClassLoader();
                    xmlInputStream = cl.getResourceAsStream(configurationXMLLocation);
                    if (xmlInputStream == null) {
                        log.fatal(
                                "Configuration File cannot be loaded from " +
                                        configurationXMLLocation,
                                e1);
                        throw new ServerConfigurationException(e1);

                    }
                }
            } catch (IOException e) {
                log.fatal("Configuration File cannot be loaded from " + configurationXMLLocation,
                        e);
                throw new ServerConfigurationException(e);
            }
            init(xmlInputStream);
        } finally {
            if (xmlInputStream != null) {
                try {
                    xmlInputStream.close();
                } catch (IOException e) {
                    log.warn("Cannot close input stream", e);
                }
            }
        }
    }

    /**
     * Method to forcibly initialize the server configuration. If there is any configuration loaded,
     * it will not be preserved.
     *
     * @param xmlInputStream the server configuration file stream.
     *
     * @throws ServerConfigurationException if the operation failed.
     */
    public synchronized void forceInit(InputStream xmlInputStream)
            throws ServerConfigurationException {
        isInitialized = false;
        init(xmlInputStream);
    }

    /**
     * Method to forcibly initialize the server configuration. If there is any configuration loaded,
     * it will not be preserved.
     *
     * @param configurationXMLLocation the location of the server configuration file (carbon.xml).
     *
     * @throws ServerConfigurationException if the operation failed.
     */
    public synchronized void forceInit(String configurationXMLLocation)
            throws ServerConfigurationException {
        isInitialized = false;
        init(configurationXMLLocation);
    }

    /**
     * Method to forcibly initialize the server configuration.
     *
     * @param configurationXMLLocation       the location of the server configuration file
     *                                       (carbon.xml).
     * @param isLoadedConfigurationPreserved whether the currently loaded configuration is
     *                                       preserved.
     *
     * @throws ServerConfigurationException if the operation failed.
     */
    public synchronized void forceInit(String configurationXMLLocation,
                                       boolean isLoadedConfigurationPreserved)
            throws ServerConfigurationException {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        isInitialized = false;
        this.isLoadedConfigurationPreserved = isLoadedConfigurationPreserved;
        init(configurationXMLLocation);
    }

    private void readChildElements(OMElement serverConfig,
                                   Stack<String> nameStack) {
        for (Iterator childElements = serverConfig.getChildElements();
             childElements.hasNext();) {
            OMElement element = (OMElement) childElements.next();
            nameStack.push(element.getLocalName());
            if (elementHasText(element)) {
                String key = getKey(nameStack);
                String value = replaceSystemProperty(element.getText());
                if (isProtectedToken(key)) {
                    value = getProtectedValue(key);
                }
                addToConfiguration(key, value);
            }
            readChildElements(element, nameStack);
            nameStack.pop();
        }
    }

    private void addToConfiguration(String key, String value) {
        List<String> list = configuration.get(key);
        if (list == null) {
            list = new ArrayList<String>();
            list.add(value);
            configuration.put(key, list);
        } else {
            if (!list.contains(value)) {
                list.add(value);
            }
        }
    }

    private String replaceSystemProperty(String text) {
        int indexOfStartingChars = -1;
        int indexOfClosingBrace;

        // The following condition deals with properties.
        // Properties are specified as ${system.property},
        // and are assumed to be System properties
        while (indexOfStartingChars < text.indexOf("${") &&
                (indexOfStartingChars = text.indexOf("${")) != -1 &&
                (indexOfClosingBrace = text.indexOf("}")) != -1) { // Is a property used?
            String sysProp = text.substring(indexOfStartingChars + 2,
                    indexOfClosingBrace);
            String propValue = System.getProperty(sysProp);
            if (propValue != null) {
                text = text.substring(0, indexOfStartingChars) + propValue +
                        text.substring(indexOfClosingBrace + 1);
            }
            if (sysProp.equals("carbon.home") && propValue != null) {
                if (propValue.equals(".")) {
                    text = new File(".").getAbsolutePath() + File.separator + text;
                }
            }
        }
        return text;
    }

    /**
     * Method to a given key, value pair into the configuration.
     *
     * @param key   the key to add
     * @param value the value
     */
    public void setConfigurationProperty(String key, String value) {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        addToConfiguration(key, value);

        StringTokenizer tokenizer = new StringTokenizer(key, ".");
        OMElement ele = getDocumentElementInternal();
        String token = "";
        while (tokenizer.hasMoreTokens()) {
            token = tokenizer.nextToken();
            if (ele != null) {
                ele = ele.getFirstChildWithName(new QName("", token, ""));
            } else {
                break;
            }
        }
        if (ele != null) {
            ele.getFirstOMChild().detach();
            ele.setText(token);
        }
    }

    private String getKey(Stack<String> nameStack) {
        StringBuffer key = new StringBuffer();
        for (int i = 0; i < nameStack.size(); i++) {
            String name = nameStack.elementAt(i);
            key.append(name).append(".");
        }
        key.deleteCharAt(key.lastIndexOf("."));

        return key.toString();
    }

    private boolean elementHasText(OMElement element) {
        String text = element.getText();
        return text != null && text.trim().length() != 0;
    }

    /**
     * There can be multiple objects with the same key. This will return the first String from them
     *
     * @param key the search key
     *
     * @return value corresponding to the given key
     */
    public String getFirstProperty(String key) {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        List<String> value = configuration.get(key);
        if (value == null) {
            return null;
        }
        return value.get(0);
    }

    /**
     * There can be multiple object corresponding to the same object.
     *
     * @param key the search key
     *
     * @return the properties corresponding to the <code>key</code>
     */
    public String[] getProperties(String key) {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        List<String> values = configuration.get(key);
        if (values == null) {
            return new String[0];
        }
        return values.toArray(new String[values.size()]);
    }

    /**
     * Method to retrieve the Configuration as an XML Document.
     *
     * @return DOM element containing server configuration.
     */
    public Element getDocumentElement() {
        try {
            return toDOM(getDocumentElementInternal());
        } catch (Exception e) {
            log.error("Cannot get ServerConfiguration document element", e);
            return null;
        }
    }

    private OMElement getDocumentElementInternal() {
        CarbonBaseUtils.checkSecurity(ALLOWED_CLASSES);
        try {
            return (new StAXOMBuilder(new ByteArrayInputStream(documentXML.getBytes())))
                    .getDocumentElement();
        } catch (XMLStreamException e) {
            log.error("Cannot get ServerConfiguration document element", e);
            return null;
        }
    }

    /**
     * Converts a given OMElement to a DOM Element.
     *
     * @param element the OM element to be converted to DOM.
     *
     * @return Returns Element.
     * @throws Exception if the operation failed.
     */
    private static Element toDOM(OMElement element) throws Exception {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        element.serialize(outputStream);
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        return factory.newDocumentBuilder().parse(inputStream).getDocumentElement();
    }

    protected boolean isProtectedToken(String key) {
        return secretResolver != null && secretResolver.isInitialized() &&
               secretResolver.isTokenProtected("Carbon." + key);
    }

    protected String getProtectedValue(String key) {
        return secretResolver.resolve("Carbon." + key);
    }
}
TOP

Related Classes of org.wso2.carbon.base.ServerConfiguration

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.