com.greglturnquist.springagram.fileservice.s3.FileService.java Source code

Java tutorial

Introduction

Here is the source code for com.greglturnquist.springagram.fileservice.s3.FileService.java

Source

/*
 * Copyright 2015 the original author or authors.
 *
 * 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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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.greglturnquist.springagram.fileservice.s3;

import java.io.IOException;
import java.io.InputStream;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Service;

import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.util.StringInputStream;

/**
 * @author Greg Turnquist
 */
@Service
public class FileService {

    private static final Logger log = LoggerFactory.getLogger(FileService.class);

    private final ResourcePatternResolver resourcePatternResolver;
    private final ResourceLoader resourceLoader;
    private final AmazonS3Client s3Client;

    @Value("${bucket}")
    private String bucket;

    @Autowired
    public FileService(ResourcePatternResolver resourcePatternResolver, ResourceLoader resourceLoader,
            AmazonS3Client s3Client) {

        this.resourcePatternResolver = resourcePatternResolver;
        this.resourceLoader = resourceLoader;
        this.s3Client = s3Client;
    }

    public void saveFile(InputStream input, long length, String filename) throws IOException {

        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(length);
            this.s3Client.putObject(this.bucket, filename, input, metadata);
        } catch (AmazonS3Exception e) {
            if (e.getStatusCode() == 301) {
                updateEndpoint(e);
                saveFile(input, length, filename);
            }
        }
    }

    public Resource[] findAll() throws IOException {

        Resource[] results = new Resource[0];
        try {
            results = this.resourcePatternResolver.getResources(s3ify(this.bucket) + "/" + "*");
        } catch (AmazonS3Exception e) {
            if (e.getStatusCode() == 301) {
                updateEndpoint(e);
                results = this.findAll();
            }
        }
        return results;
    }

    public Resource findOne(String filename) {
        return this.resourceLoader.getResource(s3ify(this.bucket) + "/" + filename);
    }

    public void deleteAll() throws IOException {

        for (Resource resource : this.findAll()) {
            this.deleteOne(resource.getFilename());
        }
    }

    public void deleteOne(String filename) {
        this.s3Client.deleteObject(this.bucket, filename);
    }

    private String s3ify(String s) {
        if (s.startsWith("s3://")) {
            return s;
        } else {
            return "s3://" + s;
        }
    }

    /**
     * Parse the {@link AmazonS3Exception} error result to capture the endpoint for
     * redirection.
     *
     * @param e
     */
    private void updateEndpoint(AmazonS3Exception e) {

        try {
            Document errorResponseDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                    .parse(new StringInputStream(e.getErrorResponseXml()));

            XPathExpression endpointXpathExtr = XPathFactory.newInstance().newXPath().compile("/Error/Endpoint");

            this.s3Client.setEndpoint(endpointXpathExtr.evaluate(errorResponseDoc));
        } catch (Exception ex) {
            throw new RuntimeException(e);
        }
    }

}