/*
 * Copyright 2014 Amazon Technologies, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and
 * limitations under the License.
 */
package com.amediamanager.config;

import java.io.IOException;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.S3Object;
import com.amediamanager.config.ConfigurationSettings.ConfigProps;

public abstract class S3ConfigurationProvider extends ConfigurationProvider {
    private static final Logger LOG = LoggerFactory.getLogger(S3ConfigurationProvider.class);
    private String bucket;
    private String key;
    private Properties properties;

    @Override
    public void loadProperties() {
    	this.properties = null;
    	
    	// Load properties if there is a bucket and key
        if (bucket != null && key != null) {
            AmazonS3 s3Client = new AmazonS3Client();
            try {
                S3Object object = s3Client.getObject(this.bucket, this.key);
                if (object != null) {
                    this.properties = new Properties();
                    try {
                        this.properties.load(object.getObjectContent());
                    } catch (IOException e) {
                        this.properties = null;
                        LOG.warn("Found configuration file in S3 but failed to load properties (s3://{}/{})", new Object[]{this.bucket, this.key, e});
                    } finally {
                        try {
                            object.close();
                        } catch (IOException e) {
                            // Don't care
                        }
                    }
                }
            } catch (AmazonS3Exception ase) {
                LOG.error("Error loading config from s3://{}/{}", new Object[]{this.bucket, this.key, ase});
            }
        }
    }

    @Override
    public void persistNewProperty(String key, String value) {
        if (this.properties != null) {
            this.properties.put(key, value);
            AmazonS3 s3Client = new AmazonS3Client();
            try {
                s3Client.putObject(this.bucket, this.key,
                        IOUtils.toInputStream(this.propsToString(this.properties)), null);
            } catch (AmazonS3Exception ase) {
                LOG.error("Error persisting config from s3://{}/{}", new Object[]{this.bucket, this.key, ase});
            }
        } else {
        	LOG.error("Could not persist new property because this.properties is null.");
        }
    }

    @Override
    public void persistNewProperty(ConfigProps property, String value) {
        persistNewProperty(property.name(), value);
    }

    @Override
    public String getPrettyName() {
        return this.getClass().getSimpleName();
    }

    @Override
    public Properties getProperties() {
    	return properties;
    }
    
    /**
     * This setter is only exposed to make the coding challenge feasible. The challenge
     * subclass implements loadProperties and needs access to set this.properties.
     * @param properties
     */
    public void setProperties(Properties properties) {
    	this.properties = properties;
    }
    
    public String getBucket() {
    	return this.bucket;
    }
    
    public void setBucket(String bucket) {
    	this.bucket = bucket;
    }
    
    public String getKey() {
    	return this.key;
    }
    
    public void setKey(String key) {
    	this.key = key;
    }
}

@@ -689,16 +689,312 @@
 ctory;%0A%0A
+import com.amazonaws.auth.AWSCredentialsProvider;%0Aimport com.amazonaws.auth.AWSCredentialsProviderChain;%0Aimport com.amazonaws.auth.EnvironmentVariableCredentialsProvider;%0Aimport com.amazonaws.auth.InstanceProfileCredentialsProvider;%0Aimport com.amazonaws.auth.SystemPropertiesCredentialsProvider;%0A
 import c
@@ -1685,32 +1685,329 @@
  key != null) %7B%0A
+          AWSCredentialsProvider creds = new AWSCredentialsProviderChain(%0A                      new InstanceProfileCredentialsProvider(),%0A                  %09%09new EnvironmentVariableCredentialsProvider(),%0A                      new SystemPropertiesCredentialsProvider()%0A                          );%0A
             Amaz
@@ -2033,32 +2033,37 @@
  AmazonS3Client(
+creds
 );%0A            t

Use a creds provider chain when looking up s3-based config