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 + -
显示快捷键?