001/* 002 * (C) Copyright 2006-2018 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 * $Id$ 020 */ 021 022package org.nuxeo.ecm.platform.importer.properties; 023 024import java.io.File; 025import java.io.FileInputStream; 026import java.io.IOException; 027import java.io.Serializable; 028import java.util.ArrayList; 029import java.util.Collections; 030import java.util.Enumeration; 031import java.util.HashMap; 032import java.util.List; 033import java.util.Map; 034import java.util.Map.Entry; 035import java.util.Properties; 036import java.util.concurrent.locks.ReentrantReadWriteLock; 037import java.util.regex.Pattern; 038 039import org.apache.commons.io.FilenameUtils; 040import org.apache.commons.lang3.StringUtils; 041 042/** 043 * Collects meta-data from a FileSystem and manage inheritence 044 * 045 * @author Thierry Delprat 046 */ 047public class MetadataCollector { 048 049 protected boolean staticInherit = true; 050 051 protected boolean useIntrospection = false; 052 053 public static final String DATE_FORMAT = "MM/dd/yyyy"; 054 055 public static final String LIST_SEPARATOR = "|"; 056 057 public static final String REGEXP_LIST_SEPARATOR = "\\|"; 058 059 public static final String ARRAY_SEPARATOR = "||"; 060 061 public static final String REGEXP_ARRAY_SEPARATOR = "\\|\\|"; 062 063 protected Map<String, Map<String, Serializable>> collectedMetadata = new HashMap<>(); 064 065 protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 066 067 public void addPropertiesFromStrings(String contextPath, Map<String, String> properties) { 068 Map<String, Serializable> collectedProperties = new HashMap<>(); 069 for (Entry<String, String> es : properties.entrySet()) { 070 String name = es.getKey(); 071 Serializable value = parseFromString(name, es.getValue()); 072 collectedProperties.put(name, value); 073 } 074 addProperties(contextPath, collectedProperties); 075 } 076 077 public void addProperties(String contextPath, Map<String, Serializable> collectedProperties) { 078 try { 079 lock.writeLock().lock(); 080 contextPath = FilenameUtils.normalizeNoEndSeparator(contextPath); 081 if (staticInherit) { 082 File file = new File(contextPath); 083 while (!StringUtils.isEmpty(file.getParent())) { 084 file = file.getParentFile(); 085 Map<String, Serializable> parentProperties = collectedMetadata.get(file.toString()); 086 if (parentProperties != null) { 087 for (String name : parentProperties.keySet()) { 088 if (!collectedProperties.containsKey(name)) { 089 collectedProperties.put(name, parentProperties.get(name)); 090 } 091 } 092 } 093 } 094 } 095 collectedMetadata.put(contextPath, collectedProperties); 096 } finally { 097 lock.writeLock().unlock(); 098 } 099 100 } 101 102 protected static Pattern numPattern = Pattern.compile("([0-9\\,\\.\\+\\-]+)"); 103 104 protected Serializable parseFromString(String name, String value) { 105 106 Serializable prop = value; 107 if (useIntrospection) { 108 throw new UnsupportedOperationException("Introspection mode not available"); 109 } else { 110 if (value.contains(ARRAY_SEPARATOR)) { 111 prop = value.split(REGEXP_ARRAY_SEPARATOR); 112 } else if (value.contains(LIST_SEPARATOR)) { 113 List<Serializable> lstprop = new ArrayList<>(); 114 String[] parts = value.split(REGEXP_LIST_SEPARATOR); 115 for (String part : parts) { 116 lstprop.add(parseFromString(name, part)); 117 } 118 prop = (Serializable) lstprop; 119 } 120 } 121 return prop; 122 } 123 124 public Serializable getProperty(String contextPath, String name) { 125 126 Map<String, Serializable> props = getProperties(contextPath); 127 if (props != null) { 128 try { 129 lock.readLock().lock(); 130 return props.get(name); 131 } finally { 132 lock.readLock().unlock(); 133 } 134 } else { 135 return null; 136 } 137 } 138 139 public Map<String, Serializable> getProperties(String contextPath) { 140 141 contextPath = FilenameUtils.normalizeNoEndSeparator(contextPath); 142 143 try { 144 lock.readLock().lock(); 145 Map<String, Serializable> props = collectedMetadata.get(contextPath); 146 147 if (props == null) { 148 File file = new File(contextPath); 149 while (props == null && !StringUtils.isEmpty(file.getParent())) { 150 file = file.getParentFile(); 151 props = collectedMetadata.get(file.getPath()); 152 } 153 } 154 155 if (props != null) { 156 props = Collections.unmodifiableMap(props); 157 } 158 return props; 159 } finally { 160 lock.readLock().unlock(); 161 } 162 } 163 164 public void addPropertyFile(File propertyFile) throws IOException { 165 166 Properties mdProperties = new Properties(); 167 try (var in = new FileInputStream(propertyFile)) { 168 mdProperties.load(in); 169 } 170 171 Map<String, String> stringMap = new HashMap<>(); 172 Enumeration<?> names = mdProperties.propertyNames(); 173 while (names.hasMoreElements()) { 174 String name = (String) names.nextElement(); 175 stringMap.put(name, mdProperties.getProperty(name)); 176 } 177 String contextPath = new File(propertyFile.getPath()).getParent(); 178 addPropertiesFromStrings(contextPath, stringMap); 179 } 180 181}