001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.reef.tang.formats; 020 021import org.apache.commons.configuration.ConfigurationException; 022import org.apache.commons.configuration.PropertiesConfiguration; 023import org.apache.reef.tang.Configuration; 024import org.apache.reef.tang.ConfigurationBuilder; 025import org.apache.reef.tang.exceptions.BindException; 026import org.apache.reef.tang.exceptions.ClassHierarchyException; 027import org.apache.reef.tang.implementation.ConfigurationBuilderImpl; 028import org.apache.reef.tang.implementation.ConfigurationImpl; 029import org.apache.reef.tang.types.ClassNode; 030import org.apache.reef.tang.types.ConstructorArg; 031import org.apache.reef.tang.types.NamedParameterNode; 032import org.apache.reef.tang.types.Node; 033import org.apache.reef.tang.util.ReflectionUtilities; 034 035import java.io.File; 036import java.io.FileOutputStream; 037import java.io.IOException; 038import java.io.PrintStream; 039import java.util.*; 040import java.util.Map.Entry; 041 042/** 043 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 044 */ 045@Deprecated 046public class ConfigurationFile { 047 048 /** 049 * Write Configuration to the given File. 050 * 051 * @throws IOException 052 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 053 */ 054 @Deprecated 055 public static void writeConfigurationFile( 056 final Configuration conf, final File confFile) throws IOException { 057 try (final PrintStream printStream = new PrintStream(new FileOutputStream(confFile))) { 058 printStream.print(toConfigurationString(conf)); 059 } 060 } 061 062 /** 063 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 064 */ 065 @Deprecated 066 public static void addConfiguration(final ConfigurationBuilder conf, 067 final File tmpConfFile) throws IOException, BindException { 068 final PropertiesConfiguration confFile; 069 try { 070 confFile = new PropertiesConfiguration(tmpConfFile); 071 } catch (final ConfigurationException e) { 072 throw new BindException("Problem parsing config file: " + tmpConfFile, e); 073 } 074 processConfigFile(conf, confFile); 075 } 076 077 /** 078 * @param conf This configuration builder will be modified to incorporate the 079 * contents of the configuration file. 080 * @param contents A string containing the contents of the configuration file. 081 * @throws BindException 082 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 083 */ 084 @Deprecated 085 public static void addConfiguration(final ConfigurationBuilder conf, 086 final String contents) throws BindException { 087 File tmpConfFile = null; 088 try { 089 tmpConfFile = File.createTempFile("tang", "tmp"); 090 try (final FileOutputStream outStream = new FileOutputStream(tmpConfFile)) { 091 outStream.write(contents.getBytes()); 092 } 093 addConfiguration(conf, tmpConfFile); 094 } catch (final IOException ex) { 095 throw new BindException("Error writing config file: " + tmpConfFile, ex); 096 } finally { 097 if (tmpConfFile != null) { 098 tmpConfFile.delete(); 099 } 100 } 101 } 102 103 private static void processConfigFile(ConfigurationBuilder conf, 104 PropertiesConfiguration confFile) throws IOException, BindException { 105 ConfigurationBuilderImpl ci = (ConfigurationBuilderImpl) conf; 106 Iterator<String> it = confFile.getKeys(); 107 Map<String, String> importedNames = new HashMap<>(); 108 109 while (it.hasNext()) { 110 String key = it.next(); 111 String longName = importedNames.get(key); 112 String[] values = confFile.getStringArray(key); 113 if (longName != null) { 114 // System.err.println("Mapped " + key + " to " + longName); 115 key = longName; 116 } 117 for (String value : values) { 118 try { 119 if (key.equals(ConfigurationBuilderImpl.IMPORT)) { 120 ci.getClassHierarchy().getNode(value); 121 final String[] tok = value.split(ReflectionUtilities.regexp); 122 final String lastTok = tok[tok.length - 1]; 123 try { 124 // ci.namespace.getNode(lastTok); 125 ci.getClassHierarchy().getNode(lastTok); 126 throw new IllegalArgumentException("Conflict on short name: " + lastTok); 127 } catch (BindException e) { 128 String oldValue = importedNames.put(lastTok, value); 129 if (oldValue != null) { 130 throw new IllegalArgumentException("Name conflict: " 131 + lastTok + " maps to " + oldValue + " and " + value); 132 } 133 } 134 } else if (value.startsWith(ConfigurationBuilderImpl.INIT)) { 135 String parseValue = value.substring( 136 ConfigurationBuilderImpl.INIT.length(), value.length()); 137 parseValue = parseValue.replaceAll("^[\\s\\(]+", ""); 138 parseValue = parseValue.replaceAll("[\\s\\)]+$", ""); 139 String[] classes = parseValue.split("[\\s\\-]+"); 140 ci.registerLegacyConstructor(key, classes); 141 } else { 142 ci.bind(key, value); 143 } 144 } catch (BindException e) { 145 throw new BindException("Failed to process configuration tuple: [" + key + "=" + value + "]", e); 146 } catch (ClassHierarchyException e) { 147 throw new ClassHierarchyException("Failed to process configuration tuple: [" + key + "=" + value + "]", e); 148 } 149 } 150 } 151 } 152 153 /** 154 * Replace any \'s in the input string with \\. and any "'s with \". 155 * 156 * @param in 157 * @return 158 */ 159 private static String escape(String in) { 160 // After regexp escaping \\\\ = 1 slash, \\\\\\\\ = 2 slashes. 161 162 // Also, the second args of replaceAll are neither strings nor regexps, and 163 // are instead a special DSL used by Matcher. Therefore, we need to double 164 // escape slashes (4 slashes) and quotes (3 slashes + ") in those strings. 165 // Since we need to write \\ and \", we end up with 8 and 7 slashes, 166 // respectively. 167 return in.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\\\""); 168 } 169 170 /** 171 * Obtain the effective configuration of this ConfigurationBuilderImpl 172 * instance. This consists of string-string pairs that could be written 173 * directly to a Properties file, for example. Currently, this method does not 174 * return information about default parameter values that were specified by 175 * parameter annotations, or about the auto-discovered stuff in TypeHierarchy. 176 * All of that should be automatically imported as these keys are parsed on 177 * the other end. 178 * 179 * @return A string containing enough information to rebuild this 180 * configuration object (assuming the same classes / jars are 181 * available when the string is parsed by Tang). 182 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 183 */ 184 @Deprecated 185 public static String toConfigurationString(final Configuration c) { 186 StringBuilder sb = new StringBuilder(); 187 for (String s : toConfigurationStringList(c)) { 188 sb.append(s); 189 sb.append('\n'); 190 } 191 return sb.toString(); 192 } 193 194 /** 195 * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead. 196 */ 197 @Deprecated 198 static List<String> toConfigurationStringList(final Configuration c) { 199 ConfigurationImpl conf = (ConfigurationImpl) c; 200 List<String> l = new ArrayList<>(); 201 for (ClassNode<?> opt : conf.getBoundImplementations()) { 202 l.add(opt.getFullName() 203 + '=' 204 + escape(conf.getBoundImplementation(opt).getFullName())); 205 } 206 for (ClassNode<?> opt : conf.getBoundConstructors()) { 207 l.add(opt.getFullName() 208 + '=' 209 + escape(conf.getBoundConstructor(opt).getFullName())); 210 } 211 for (NamedParameterNode<?> opt : conf.getNamedParameters()) { 212 l.add(opt.getFullName() 213 + '=' 214 + escape(conf.getNamedParameter(opt))); 215 } 216 for (ClassNode<?> cn : conf.getLegacyConstructors()) { 217 StringBuilder sb = new StringBuilder(); 218 join(sb, "-", conf.getLegacyConstructor(cn).getArgs()); 219 l.add(cn.getFullName() 220 + escape('=' 221 + ConfigurationBuilderImpl.INIT 222 + '(' 223 + sb.toString() 224 + ')' 225 )); 226 //s.append(cn.getFullName()).append('=').append(ConfigurationBuilderImpl.INIT).append('('); 227// .append(")\n"); 228 } 229 for (Entry<NamedParameterNode<Set<?>>, Object> e : conf.getBoundSets()) { 230 final String val; 231 if (e.getValue() instanceof String) { 232 val = (String) e.getValue(); 233 } else if (e.getValue() instanceof Node) { 234 val = ((Node) e.getValue()).getFullName(); 235 } else { 236 throw new IllegalStateException(); 237 } 238 l.add(e.getKey().getFullName() + '=' + escape(val)); 239// s.append(e.getKey().getFullName()).append('=').append(val).append("\n"); 240 } 241 return l;//s.toString(); 242 } 243 244 private static StringBuilder join(final StringBuilder sb, final String sep, final ConstructorArg[] types) { 245 if (types.length > 0) { 246 sb.append(types[0].getType()); 247 for (int i = 1; i < types.length; i++) { 248 sb.append(sep).append(types[i].getType()); 249 } 250 } 251 return sb; 252 } 253}