001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.configuration2; 019 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.Reader; 023import java.io.Writer; 024import java.util.Map; 025 026import org.apache.commons.configuration2.ex.ConfigurationException; 027import org.apache.commons.configuration2.io.InputStreamSupport; 028import org.apache.commons.configuration2.tree.ImmutableNode; 029import org.yaml.snakeyaml.DumperOptions; 030import org.yaml.snakeyaml.LoaderOptions; 031import org.yaml.snakeyaml.Yaml; 032import org.yaml.snakeyaml.constructor.SafeConstructor; 033import org.yaml.snakeyaml.representer.Representer; 034 035/** 036 * <p> 037 * A specialized hierarchical configuration class that is able to parse YAML documents. 038 * </p> 039 * 040 * @since 2.2 041 */ 042public class YAMLConfiguration extends AbstractYAMLBasedConfiguration implements FileBasedConfiguration, InputStreamSupport { 043 /** 044 * Creates a {@code Yaml} object for reading a Yaml file. The object is configured with some default settings. 045 * 046 * @param options options for loading the file 047 * @return the {@code Yaml} instance for loading a file 048 */ 049 private static Yaml createYamlForReading(final LoaderOptions options) { 050 return new Yaml(new SafeConstructor(options), new Representer(new DumperOptions()), new DumperOptions(), options); 051 } 052 053 /** 054 * Creates a new instance of {@code YAMLConfiguration}. 055 */ 056 public YAMLConfiguration() { 057 } 058 059 /** 060 * Creates a new instance of {@code YAMLConfiguration} as a copy of the specified configuration. 061 * 062 * @param c the configuration to be copied 063 */ 064 public YAMLConfiguration(final HierarchicalConfiguration<ImmutableNode> c) { 065 super(c); 066 } 067 068 public void dump(final Writer out, final DumperOptions options) 069 throws ConfigurationException, IOException { 070 final Yaml yaml = new Yaml(options); 071 yaml.dump(constructMap(getNodeModel().getNodeHandler().getRootNode()), out); 072 } 073 074 /** 075 * Loads the configuration from the given input stream. 076 * 077 * @param in the input stream 078 * @throws ConfigurationException if an error occurs 079 */ 080 @Override 081 public void read(final InputStream in) throws ConfigurationException { 082 try { 083 final Yaml yaml = createYamlForReading(new LoaderOptions()); 084 final Map<String, Object> map = yaml.load(in); 085 load(map); 086 } catch (final Exception e) { 087 rethrowException(e); 088 } 089 } 090 091 public void read(final InputStream in, final LoaderOptions options) throws ConfigurationException { 092 try { 093 final Yaml yaml = createYamlForReading(options); 094 final Map<String, Object> map = yaml.load(in); 095 load(map); 096 } catch (final Exception e) { 097 rethrowException(e); 098 } 099 } 100 101 @Override 102 public void read(final Reader in) throws ConfigurationException { 103 try { 104 final Yaml yaml = createYamlForReading(new LoaderOptions()); 105 final Map<String, Object> map = yaml.load(in); 106 load(map); 107 } catch (final Exception e) { 108 rethrowException(e); 109 } 110 } 111 112 public void read(final Reader in, final LoaderOptions options) throws ConfigurationException { 113 try { 114 final Yaml yaml = createYamlForReading(options); 115 final Map<String, Object> map = yaml.load(in); 116 load(map); 117 } catch (final Exception e) { 118 rethrowException(e); 119 } 120 } 121 122 @Override 123 public void write(final Writer out) throws ConfigurationException, IOException { 124 final DumperOptions options = new DumperOptions(); 125 options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 126 dump(out, options); 127 } 128 129}