All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opensaml.util.resource.ResourceChangeWatcher Maven / Gradle / Ivy

Go to download

The OpenWS library provides a growing set of tools to work with web services at a low level. These tools include classes for creating and reading SOAP messages, transport-independent clients for connecting to web services, and various transports for use with those clients.

The newest version!
/*
 * Licensed to the University Corporation for Advanced Internet Development, 
 * Inc. (UCAID) under one or more contributor license agreements.  See the 
 * NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The UCAID licenses this file to You 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.opensaml.util.resource;

import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask;

import org.joda.time.DateTime;
import org.opensaml.util.resource.ResourceChangeListener.ResourceChange;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A watcher that invokes a callback when a resource update/deletion has been detected.
 */
public class ResourceChangeWatcher extends TimerTask {

    /** Default polling frequency, 12 hours. */
    public static final long DEFAULT_POLL_FREQUENCY = 1000 * 60 * 60 * 12;

    /** Default maximum retry attempts, 0. */
    public static final int DEFAULT_MAX_RETRY_ATTEMPTS = 0;

    /** Class logger. */
    private final Logger log = LoggerFactory.getLogger(ResourceChangeWatcher.class);

    /** Resource being watched. */
    private Resource watchedResource;

    /** Frequency, in milliseconds, the resource is polled for changes. */
    private long pollFrequency;

    /** Max number of polls to try before considering the resource inaccessible. */
    private int maxRetryAttempts;

    /** Number of times the resource has been polled but generated an error. */
    private int currentRetryAttempts;

    /** Whether the resource currently exists. */
    private boolean resourceExist;

    /** Last time the resource was modified. */
    private DateTime lastModification;

    /** Registered listeners of resource change notifications. */
    private List resourceListeners;

    /**
     * Constructor.
     * 
     * @param resource the resource to be watched
     * 
     * @throws ResourceException thrown if resource existence or last modification time can not be determined
     */
    public ResourceChangeWatcher(Resource resource) throws ResourceException {
        this(resource, DEFAULT_POLL_FREQUENCY, DEFAULT_MAX_RETRY_ATTEMPTS);
    }

    /**
     * Constructor.
     * 
     * @param resource the resource to be watched
     * @param pollingFrequency the frequency, in milliseconds, to poll the resource for changes
     * 
     * @throws ResourceException thrown if resource existence or last modification time can not be determined
     */
    public ResourceChangeWatcher(Resource resource, long pollingFrequency) throws ResourceException {
        this(resource, pollingFrequency, DEFAULT_MAX_RETRY_ATTEMPTS);
    }

    /**
     * Constructor.
     * 
     * @param resource the resource to be watched
     * @param pollingFrequency the frequency, in milliseconds, to poll the resource for changes
     * @param retryAttempts maximum number of poll attempts before the resource is considered inaccessible
     * 
     * @throws ResourceException thrown if resource existence or last modification time can not be determined
     */
    public ResourceChangeWatcher(Resource resource, long pollingFrequency, int retryAttempts) throws ResourceException {
        if (resource == null) {
            throw new NullPointerException("Watched resource is null");
        }

        if (pollingFrequency <= 0) {
            throw new IllegalArgumentException("Polling frequency must be greater than zero");
        }

        if (retryAttempts < 0) {
            throw new IllegalArgumentException("Max retry attempts must be greater than, or equal to, zero");
        }

        watchedResource = resource;
        pollFrequency = pollingFrequency;
        maxRetryAttempts = retryAttempts;
        currentRetryAttempts = 0;

        resourceListeners = new ArrayList(5);
        log.debug("Watching resource: " + watchedResource.getLocation()
                + ", polling frequency: {}ms, max retry attempts: {}", pollFrequency, maxRetryAttempts);
        
        try {
            if (watchedResource.exists()) {
                resourceExist = true;
                lastModification = watchedResource.getLastModifiedTime();
            } else {
                resourceExist = false;
            }
        } catch (ResourceException e) {
            log.warn("Resource " + watchedResource.getLocation() + " could not be accessed", e);
            currentRetryAttempts++;
            if (currentRetryAttempts >= maxRetryAttempts) {
                log.error("Resource {} was not accessible at time of ResourceChangeWatcher construction and max retrys are exceeded",
                        watchedResource.getLocation());
                throw e;
            }
        }

    }

    /**
     * Gets the frequency, in milliseconds, the watched resource should be polled.
     * 
     * @return frequency the watched resource should be polled
     */
    public long getPollingFrequency() {
        return pollFrequency;
    }

    /**
     * Gets the list of registered resource listeners. New listeners may be registered with the list or old ones
     * removed.
     * 
     * @return list of registered resource listeners
     */
    public List getResourceListeners() {
        return resourceListeners;
    }

    /** {@inheritDoc} */
    public void run() {
        try {
            log.trace("Checking resource for changes: {}", watchedResource.getLocation());
            if (watchedResource.exists()) {
                if (!resourceExist) {
                    resourceExist = true;
                    signalListeners(ResourceChange.CREATION);
                    lastModification = watchedResource.getLastModifiedTime();
                } else {
                    if (lastModification.isBefore(watchedResource.getLastModifiedTime())) {
                        signalListeners(ResourceChange.UPDATE);
                        lastModification = watchedResource.getLastModifiedTime();
                    }
                }
            } else {
                if (resourceExist) {
                    resourceExist = false;
                    signalListeners(ResourceChange.DELETE);
                }
            }
            currentRetryAttempts = 0;
        } catch (ResourceException e) {
            log.warn("Resource " + watchedResource.getLocation() + " could not be accessed", e);
            currentRetryAttempts++;
            if (currentRetryAttempts >= maxRetryAttempts) {
                cancel();
                log.error("Resource {} was not accessible for max number of retry attempts.  This resource will no longer be watched",
                        watchedResource.getLocation());
            }
        }
    }

    /**
     * Signals all registered listeners of a resource change.
     * 
     * @param changeType the resource change type
     */
    protected void signalListeners(ResourceChange changeType) {
        synchronized (resourceListeners) {
            switch (changeType) {
                case CREATION:
                    log.debug("Publishing creation event for resource: {}", watchedResource.getLocation());
                    for (ResourceChangeListener listener : resourceListeners) {
                        listener.onResourceCreate(watchedResource);
                    }
                    break;
                case UPDATE:
                    log.debug("Publishing update event for resource: {}", watchedResource.getLocation());
                    for (ResourceChangeListener listener : resourceListeners) {
                        listener.onResourceUpdate(watchedResource);
                    }
                    break;
                case DELETE:
                    log.debug("Publishing delete event for resource: {}", watchedResource.getLocation());
                    for (ResourceChangeListener listener : resourceListeners) {
                        listener.onResourceDelete(watchedResource);
                    }
                    break;
                default:
                    break;
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy