hierarchicalproperties.java

来自「bpel执行引擎用来执行bpel业务流程」· Java 代码 · 共 471 行 · 第 1/2 页

JAVA
471
字号
/* * 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.ode.utils;import org.apache.commons.collections.map.MultiKeyMap;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import javax.xml.namespace.QName;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.HashMap;import java.util.HashSet;import java.util.Map;import java.util.Properties;import java.util.Set;import java.util.Collections;import java.util.Iterator;/** * This class load a regular property file in {@link java.util.Properties} instance. The main feature is that property can * be chained in three levels. Then when querying for a property, if it's not found in the deepest level, * the parent will be queryed and so on. * <p/> * A prefix must be defined to discriminate the property name and the level-1, level-2 names. The default prefix is {@link #ODE_PREFFIX}. * <p/> * Properties must respect the following pattern: [level1.[level2.]prefix.]property * <p/> * A concrete use case could be the definition of properties for wsdl services and ports. * <br/>Level 0 would be: values common to all services and ports. * <br/>Level 1: values common to a given service. * <br/>Level 2: values common to a given port. * <p/> * For instance, if the property file looks like this: * <pre> * timeout=40000 * film-service.port-of-cannes.ode.timeout=50000 * <p/> * max-redirects=30 * brel-service.ode.max-redirects=40 * brel-service.port-of-amsterdam.ode.max-redirects=60 * </pre> * The following values may be expected: * <pre> * getProperty("max-redirects")                                       => 30 * getProperty("brel-service", "max-redirects")                       => 40 * getProperty("brel-service", "port-of-amsterdam", "max-redirects")  => 60 * <p/> * getProperty("film-service", "timeout")                       => 40000 * getProperty("film-service", "port-of-cannes", "timeout")     => 50000 * getProperty("brel-service", "port-of-amsterdam", "timeout")  => 40000 * </pre> * <p/> * Values may contain some environment variables. For instance, message=You're using ${java.version}. * <p/> * This class is not thread-safe. * * @author <a href="mailto:midon@intalio.com">Alexis Midon</a> */public class HierarchicalProperties {    private static final Log log = LogFactory.getLog(HierarchicalProperties.class);    public static final String ODE_PREFFIX = "ode";    // the raw properties as of loaded from the filesystem    private Properties props = new Properties();    private Map<String, String> aliases = new HashMap<String, String>();    private File file;    private String prefix;    private String dotted_prefix;    /*        This map contains ChainedMap instances chained according to the service and/or port they are associated with.        All ChainedMap instances has a common parent.        The ChainedMap instances are chained to each others so that if a property is not found for [service, port],        the ChainedMap associated to [service] will be queried, and if still not found, then the common parent.        The ChainedMap instance common to all services and ports is associated to the [null, null] key.        ChainedMap instance common to all ports of a given service is associated to [service, null].        ChainedMap instance of a given service, port couple is associated to [service, port].        The ChainedMap instances contain string values as loaded from the filesystem.     */    private MultiKeyMap hierarchicalMap = new MultiKeyMap();    // map used to cache immutable versions of the maps    private transient MultiKeyMap cacheOfImmutableMaps = new MultiKeyMap();    /**     * @param file   the property file to be loaded. The file may not exist.     *               But if the file exists it has to be a file (not a directory), otherwhise an IOException is thrown.     * @param prefix the property prefix     * @throws IOException     */    public HierarchicalProperties(File file, String prefix) throws IOException {        this.file = file;        this.prefix = prefix;        this.dotted_prefix = "." + prefix + ".";        loadFile();    }    public HierarchicalProperties(File file) throws IOException {        this(file, ODE_PREFFIX);    }    /**     * Clear all existing content, read the file and parse each property. Simply logs a message and returns if the file does not exist.     *     * @throws IOException if the file is a Directory     */    public void loadFile() throws IOException {        if (!file.exists()) {            if (log.isDebugEnabled()) log.debug("File does not exist [" + file + "] Properties will be empty.");            return;        }        // #1. clear all existing content        clear();        // #2. read the file        FileInputStream fis = new FileInputStream(file);        try {            if (log.isDebugEnabled()) log.debug("Loading property file: " + file);            props.load(fis);        } finally {            fis.close();        }        // #3. put the root map        hierarchicalMap.put(null, null, new ChainedMap());        // #4. process each property        for (Iterator it = props.entrySet().iterator(); it.hasNext();) {            Map.Entry e = (Map.Entry) it.next();            String key = (String) e.getKey();            String value = (String) e.getValue();            // replace any env variables by its value            value = SystemUtils.replaceSystemProperties(value);            props.put(key, value);            if (key.startsWith("alias.")) {                final String alias = key.substring("alias.".length(), key.length());                if(log.isDebugEnabled()) log.debug("Alias found: "+alias+" -> "+value);                aliases.put(value, alias);            } else {                // parse the property name                String[] info = parseProperty((String) key);                String nsalias = info[0];                String service = info[1];                String port = info[2];                String targetedProperty = info[3];                QName qname = nsalias != null ? new QName(nsalias, service) : null;                // get the map associated to this port                ChainedMap p = (ChainedMap) hierarchicalMap.get(qname, port);                if (p == null) {                    // create it if necessary                    // get the associated service map                    ChainedMap s = (ChainedMap) hierarchicalMap.get(qname, null);                    if (s == null) {                        // create the service map if necessary, the parent is the root map.                        s = new ChainedMap(getRootMap());                        // put it in the multi-map                        hierarchicalMap.put(qname, null, s);                    }                    // create the map itself and link it to theservice map                    p = new ChainedMap(s);                    // put it in the multi-map                    hierarchicalMap.put(qname, port, p);                }                // save the key/value in its chained map                p.put(targetedProperty, value);            }        }    }    /**     * Clear all content. If {@link #loadFile()} is not invoked later, all returned values will be null.     */    public void clear() {        props.clear();        aliases.clear();        hierarchicalMap.clear();        cacheOfImmutableMaps.clear();    }    protected ChainedMap getRootMap() {        Object o = hierarchicalMap.get(null, null);        if (o == null) {            o = new ChainedMap();            hierarchicalMap.put(null, null, o);        }        return (ChainedMap) o;    }    public Map getProperties(String serviceNamespaceURI, String serviceLocalPart) {        return getProperties(new QName(serviceNamespaceURI, serviceLocalPart));    }    /**     * @param service     * @return a map containing all the properties for the given service.     * @see #getProperties(String, String)     */    public Map getProperties(QName service) {        return getProperties(service, null);    }    public Map getProperties(String serviceNamespaceURI, String serviceLocalPart, String port) {        return getProperties(new QName(serviceNamespaceURI, serviceLocalPart), port);    }    /**     * Return a map containing all the properties for the given port. The map is an immutable snapshot of the properties.     * Meaning that futur changes to the properties will NOT be reflected in the returned map.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?