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 * https://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 /** 045 * Creates a {@code Yaml} object for reading a Yaml file. The object is configured with some default settings. 046 * 047 * @param options options for loading the file 048 * @return the {@code Yaml} instance for loading a file 049 */ 050 private static Yaml createYamlForReading(final LoaderOptions options) { 051 return new Yaml(new SafeConstructor(options), new Representer(new DumperOptions()), new DumperOptions(), options); 052 } 053 054 /** 055 * Creates a new instance of {@code YAMLConfiguration}. 056 */ 057 public YAMLConfiguration() { 058 } 059 060 /** 061 * Creates a new instance of {@code YAMLConfiguration} as a copy of the specified configuration. 062 * 063 * @param c the configuration to be copied 064 */ 065 public YAMLConfiguration(final HierarchicalConfiguration<ImmutableNode> c) { 066 super(c); 067 } 068 069 public void dump(final Writer out, final DumperOptions options) 070 throws ConfigurationException, IOException { 071 final Yaml yaml = new Yaml(options); 072 yaml.dump(constructMap(getNodeModel().getNodeHandler().getRootNode()), out); 073 } 074 075 /** 076 * Loads the configuration from the given input stream. 077 * 078 * @param in the input stream 079 * @throws ConfigurationException if an error occurs 080 */ 081 @Override 082 public void read(final InputStream in) throws ConfigurationException { 083 try { 084 final Yaml yaml = createYamlForReading(new LoaderOptions()); 085 final Map<String, Object> map = yaml.load(in); 086 load(map); 087 } catch (final Exception e) { 088 rethrowException(e); 089 } 090 } 091 092 public void read(final InputStream in, final LoaderOptions options) throws ConfigurationException { 093 try { 094 final Yaml yaml = createYamlForReading(options); 095 final Map<String, Object> map = yaml.load(in); 096 load(map); 097 } catch (final Exception e) { 098 rethrowException(e); 099 } 100 } 101 102 @Override 103 public void read(final Reader in) throws ConfigurationException { 104 try { 105 final Yaml yaml = createYamlForReading(new LoaderOptions()); 106 final Map<String, Object> map = yaml.load(in); 107 load(map); 108 } catch (final Exception e) { 109 rethrowException(e); 110 } 111 } 112 113 public void read(final Reader in, final LoaderOptions options) throws ConfigurationException { 114 try { 115 final Yaml yaml = createYamlForReading(options); 116 final Map<String, Object> map = yaml.load(in); 117 load(map); 118 } catch (final Exception e) { 119 rethrowException(e); 120 } 121 } 122 123 @Override 124 public void write(final Writer out) throws ConfigurationException, IOException { 125 final DumperOptions options = new DumperOptions(); 126 options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); 127 dump(out, options); 128 } 129 130}