001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (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 * bstefanescu 018 */ 019package org.nuxeo.ecm.automation.core.util; 020 021import java.io.BufferedReader; 022import java.io.IOException; 023import java.io.Reader; 024import java.io.StringReader; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Map.Entry; 029 030import com.google.common.base.Objects; 031import org.codehaus.jackson.JsonNode; 032import org.codehaus.jackson.map.ObjectMapper; 033import org.nuxeo.ecm.automation.core.Constants; 034import org.nuxeo.runtime.api.Framework; 035 036/** 037 * Inline properties file content. This class exists to have a real type for parameters accepting properties content. 038 * 039 * @see Constants 040 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 041 */ 042public class Properties extends HashMap<String, String> { 043 044 private static final long serialVersionUID = 1L; 045 046 public static final String PROPERTIES_MULTILINE_ESCAPE = "nuxeo" + ".automation.properties.multiline.escape"; 047 048 protected static final String multiLineEscape = Objects.firstNonNull( 049 Framework.getProperty(PROPERTIES_MULTILINE_ESCAPE), "true"); 050 051 public Properties() { 052 } 053 054 public Properties(int size) { 055 super(size); 056 } 057 058 public Properties(Map<String, String> props) { 059 super(props); 060 } 061 062 public Properties(String content) throws IOException { 063 StringReader reader = new StringReader(content); 064 loadProperties(reader, this); 065 } 066 067 /** 068 * Constructs a Properties map based on a Json node. 069 * 070 * @param node 071 * @throws IOException 072 * @since 5.7.3 073 */ 074 public Properties(JsonNode node) throws IOException { 075 Iterator<Entry<String, JsonNode>> fields = node.getFields(); 076 ObjectMapper om = new ObjectMapper(); 077 while (fields.hasNext()) { 078 Entry<String, JsonNode> entry = fields.next(); 079 String key = entry.getKey(); 080 JsonNode subNode = entry.getValue(); 081 put(key, extractValueFromNode(subNode, om)); 082 } 083 } 084 085 /** 086 * @param om 087 * @param subNode 088 * @return 089 * @throws IOException 090 * @since 5.8-HF01 091 */ 092 private String extractValueFromNode(JsonNode node, ObjectMapper om) throws IOException { 093 if (!node.isNull()) { 094 return node.isContainerNode() ? om.writeValueAsString(node) : node.getValueAsText(); 095 } else { 096 return null; 097 } 098 } 099 100 public static Map<String, String> loadProperties(Reader reader) throws IOException { 101 Map<String, String> map = new HashMap<String, String>(); 102 loadProperties(reader, map); 103 return map; 104 } 105 106 public static void loadProperties(Reader reader, Map<String, String> map) throws IOException { 107 BufferedReader in = new BufferedReader(reader); 108 String line = in.readLine(); 109 String prevLine = null; 110 while (line != null) { 111 line = line.trim(); 112 if (line.startsWith("#") || line.length() == 0) { 113 prevLine = null; 114 line = in.readLine(); 115 continue; 116 } 117 if (line.endsWith("\\") && Boolean.valueOf(multiLineEscape)) { 118 line = line.substring(0, line.length() - 1); 119 prevLine = prevLine != null ? prevLine + line : line; 120 line = in.readLine(); 121 continue; 122 } 123 if (prevLine != null) { 124 line = prevLine + "\n" + line; 125 } 126 prevLine = null; 127 setPropertyLine(map, line); 128 line = in.readLine(); 129 } 130 if (prevLine != null) { 131 setPropertyLine(map, prevLine); 132 } 133 } 134 135 protected static void setPropertyLine(Map<String, String> map, String line) throws IOException { 136 int i = line.indexOf('='); 137 if (i == -1) { 138 throw new IOException("Invalid property line: " + line); 139 } 140 map.put(line.substring(0, i).trim(), line.substring(i + 1).trim()); 141 } 142 143}