org.brekka.stillingar.spring.snapshot.ResourceSnapshotManager.java Source code

Java tutorial

Introduction

Here is the source code for org.brekka.stillingar.spring.snapshot.ResourceSnapshotManager.java

Source

/*
 * Copyright 2011 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 org.brekka.stillingar.spring.snapshot;

import static java.lang.String.format;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.brekka.stillingar.api.ConfigurationException;
import org.brekka.stillingar.api.ConfigurationSource;
import org.brekka.stillingar.api.ConfigurationSourceLoader;
import org.brekka.stillingar.core.snapshot.InvalidSnapshotException;
import org.brekka.stillingar.core.snapshot.NoSnapshotAvailableException;
import org.brekka.stillingar.core.snapshot.Snapshot;
import org.brekka.stillingar.core.snapshot.SnapshotManager;
import org.brekka.stillingar.spring.resource.RejectedResourceHandler;
import org.brekka.stillingar.spring.resource.ResourceSelector;
import org.springframework.core.io.Resource;

/**
 * Snapshot manager based around resources.
 * 
 * @author Andrew Taylor
 */
public class ResourceSnapshotManager implements SnapshotManager {

    /**
     * Logger
     */
    private static final Log log = LogFactory.getLog(ResourceSnapshotManager.class);

    /**
     * Will actually load the configuration sources
     */
    private final ConfigurationSourceLoader configurationSourceLoader;

    /**
     * Determines what resource will be used to load snapshots from.
     */
    private final ResourceSelector resourceSelector;

    /**
     * Monitors activity on the resource.
     */
    private final ResourceMonitor resourceMonitor;

    /**
     * Can listen for when a resource is rejected.
     */
    private RejectedResourceHandler rejectedResourceHandler;

    /**
     * The configuration resource identified by the {@link ResourceSelector}.
     */
    private Resource configurationResource;

    /**
     * @param resourceSelector Determines where the resources that the snapshots will be based on will be loaded from.
     * @param configurationSourceLoader Will actually load the snapshots
     */
    public ResourceSnapshotManager(ResourceSelector resourceSelector,
            ConfigurationSourceLoader configurationSourceLoader, ResourceMonitor resourceMonitor) {
        this.resourceSelector = resourceSelector;
        this.configurationSourceLoader = configurationSourceLoader;
        ResourceMonitor selectedMonitor = checkSelectedMonitor(resourceSelector, resourceMonitor);
        this.resourceMonitor = selectedMonitor;
    }

    /**
     * @param selector
     * @param monitor
     * @return
     * @throws NoSnapshotAvailableException
     */
    protected ResourceMonitor checkSelectedMonitor(ResourceSelector selector, ResourceMonitor monitor) {
        ResourceMonitor selectedMonitor;
        try {
            Resource resource = selector.getResource();
            if (monitor.canMonitor(resource)) {
                selectedMonitor = monitor;
            } else {
                if (log.isWarnEnabled()) {
                    log.warn(String.format("Requested ResourceMonitor %s is not compatable with Resource %s",
                            monitor, resource));
                }
                selectedMonitor = new NoopResourceMonitor();
            }
        } catch (NoSnapshotAvailableException e) {
            log.warn(
                    "Could not load resource to check for monitor compatability. Assuming requested resource monitor is correct");
            selectedMonitor = monitor;
        }
        return selectedMonitor;
    }

    /* (non-Javadoc)
     * @see org.brekka.stillingar.core.snapshot.SnapshotManager#retrieveInitial()
     */
    @Override
    public Snapshot retrieveInitial() throws NoSnapshotAvailableException {
        Resource resource = resourceSelector.getResource();
        this.configurationResource = resource;
        Snapshot snapshot = performLoad(resource);
        this.resourceMonitor.initialise(resource);
        return snapshot;
    }

    /* (non-Javadoc)
    * @see org.brekka.stillingar.core.snapshot.SnapshotManager#retrieveUpdated()
    */
    @Override
    public Snapshot retrieveUpdated() throws InvalidSnapshotException {
        if (configurationResource == null) {
            // No initial configuration yet, just return null
            return null;
        }
        if (resourceMonitor.hasChanged()) {
            Snapshot snapshot = performLoad(configurationResource);
            return snapshot;
        }
        return null;
    }

    /* (non-Javadoc)
      * @see org.brekka.stillingar.core.snapshot.SnapshotManager#reject(org.brekka.stillingar.core.snapshot.Snapshot)
      */
    @Override
    public void reject(Snapshot rejectedSnapshot) {
        if (rejectedSnapshot instanceof ResourceSnapshot) {
            ResourceSnapshot resourceSnapshot = (ResourceSnapshot) rejectedSnapshot;
            Resource resource = resourceSnapshot.getResource();
            if (rejectedResourceHandler != null) {
                rejectedResourceHandler.rejected(resource);
            }
        }
    }

    /**
     * Perform the load operation that will convert a resource into a snapshot.
     * @param resourceToLoad the resouce to load into a snapshot
     * @return the snapshot loaded from the specified resource
     * @throws ConfigurationException if something goes wrong such as an IO error.
     */
    protected Snapshot performLoad(Resource resourceToLoad) {
        Snapshot snapshot = null;
        if (resourceToLoad != null && resourceToLoad.exists() && resourceToLoad.isReadable()) {
            InputStream sourceStream = null;
            try {
                sourceStream = resourceToLoad.getInputStream();
                long timestamp = resourceToLoad.lastModified();
                ConfigurationSource configurationSource = configurationSourceLoader.parse(sourceStream, null);
                snapshot = new ResourceSnapshot(configurationSource, new Date(timestamp), resourceToLoad);
            } catch (IOException e) {
                throw new ConfigurationException(format("Resouce '%s'", resourceToLoad), e);
            } catch (RuntimeException e) {
                // Wrap to include location details
                throw new ConfigurationException(format("Resouce '%s' processing problem", resourceToLoad), e);
            } finally {
                closeQuietly(sourceStream);
            }
        }
        return snapshot;
    }

    /**
     * @param rejectedResourceHandler the rejectedResourceHandler to set
     */
    public void setRejectedResourceHandler(RejectedResourceHandler rejectedResourceHandler) {
        this.rejectedResourceHandler = rejectedResourceHandler;
    }

    /**
     * Close the steams
     */
    private static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        } catch (IOException ioe) {
            // Ignore
        }
    }

}