001/* 002 * (C) Copyright 2006-2008 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nuxeo - initial API and implementation 016 * 017 * $Id$ 018 */ 019 020package org.nuxeo.ecm.platform.importer.properties; 021 022import java.io.File; 023import java.io.FileInputStream; 024import java.io.IOException; 025import java.io.Serializable; 026import java.util.ArrayList; 027import java.util.Collections; 028import java.util.Enumeration; 029import java.util.HashMap; 030import java.util.List; 031import java.util.Map; 032import java.util.Properties; 033import java.util.concurrent.locks.ReentrantReadWriteLock; 034import java.util.regex.Pattern; 035 036import org.apache.commons.io.FilenameUtils; 037import org.apache.commons.lang.StringUtils; 038 039/** 040 * Collects meta-data from a FileSystem and manage inheritence 041 * 042 * @author Thierry Delprat 043 */ 044public class MetadataCollector { 045 046 public static final boolean staticInherit = true; 047 048 public static final boolean useIntrospection = false; 049 050 public static String DATE_FORMAT = "MM/dd/yyyy"; 051 052 public static String LIST_SEPARATOR = "|"; 053 054 public static String REGEXP_LIST_SEPARATOR = "\\|"; 055 056 public static String ARRAY_SEPARATOR = "||"; 057 058 public static String REGEXP_ARRAY_SEPARATOR = "\\|\\|"; 059 060 protected Map<String, Map<String, Serializable>> collectedMetadata = new HashMap<String, Map<String, Serializable>>(); 061 062 protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 063 064 public void addPropertiesFromStrings(String contextPath, Map<String, String> properties) { 065 Map<String, Serializable> collectedProperties = new HashMap<String, Serializable>(); 066 for (String name : properties.keySet()) { 067 Serializable value = parseFromString(name, properties.get(name)); 068 collectedProperties.put(name, value); 069 } 070 addProperties(contextPath, collectedProperties); 071 } 072 073 public void addProperties(String contextPath, Map<String, Serializable> collectedProperties) { 074 try { 075 lock.writeLock().lock(); 076 contextPath = FilenameUtils.normalizeNoEndSeparator(contextPath); 077 if (staticInherit) { 078 File file = new File(contextPath); 079 while (!StringUtils.isEmpty(file.getParent())) { 080 file = file.getParentFile(); 081 Map<String, Serializable> parentProperties = collectedMetadata.get(file.toString()); 082 if (parentProperties != null) { 083 for (String name : parentProperties.keySet()) { 084 if (!collectedProperties.containsKey(name)) { 085 collectedProperties.put(name, parentProperties.get(name)); 086 } 087 } 088 } 089 } 090 } 091 collectedMetadata.put(contextPath, collectedProperties); 092 } finally { 093 lock.writeLock().unlock(); 094 } 095 096 } 097 098 protected static Pattern numPattern = Pattern.compile("([0-9\\,\\.\\+\\-]+)"); 099 100 protected Serializable parseFromString(String name, String value) { 101 102 Serializable prop = value; 103 if (useIntrospection) { 104 throw new UnsupportedOperationException("Introspection mode not available"); 105 } else { 106 if (value.contains(ARRAY_SEPARATOR)) { 107 prop = value.split(REGEXP_ARRAY_SEPARATOR); 108 } else if (value.contains(LIST_SEPARATOR)) { 109 List<Serializable> lstprop = new ArrayList<Serializable>(); 110 String[] parts = value.split(REGEXP_LIST_SEPARATOR); 111 for (String part : parts) { 112 lstprop.add(parseFromString(name, part)); 113 } 114 prop = (Serializable) lstprop; 115 } 116 } 117 return prop; 118 } 119 120 public Serializable getProperty(String contextPath, String name) { 121 122 Map<String, Serializable> props = getProperties(contextPath); 123 if (props != null) { 124 try { 125 lock.readLock().lock(); 126 return props.get(name); 127 } finally { 128 lock.readLock().unlock(); 129 } 130 } else { 131 return null; 132 } 133 } 134 135 public Map<String, Serializable> getProperties(String contextPath) { 136 137 contextPath = FilenameUtils.normalizeNoEndSeparator(contextPath); 138 139 try { 140 lock.readLock().lock(); 141 Map<String, Serializable> props = collectedMetadata.get(contextPath); 142 143 if (props == null) { 144 File file = new File(contextPath); 145 while (props == null && !StringUtils.isEmpty(file.getParent())) { 146 file = file.getParentFile(); 147 props = collectedMetadata.get(file.getPath().toString()); 148 } 149 } 150 151 if (props != null) { 152 props = Collections.unmodifiableMap(props); 153 } 154 return props; 155 } finally { 156 lock.readLock().unlock(); 157 } 158 } 159 160 public void addPropertyFile(File propertyFile) throws IOException { 161 162 Properties mdProperties = new Properties(); 163 mdProperties.load(new FileInputStream(propertyFile)); 164 165 Map<String, String> stringMap = new HashMap<String, String>(); 166 Enumeration names = mdProperties.propertyNames(); 167 while (names.hasMoreElements()) { 168 String name = (String) names.nextElement(); 169 stringMap.put(name, mdProperties.getProperty(name)); 170 } 171 String contextPath = new File(propertyFile.getPath()).getParent(); 172 addPropertiesFromStrings(contextPath, stringMap); 173 } 174 175}