org.opennms.netmgt.provision.persist.FasterFilesystemForeignSourceRepository.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.netmgt.provision.persist.FasterFilesystemForeignSourceRepository.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2009-2013 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2013 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.netmgt.provision.persist;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.io.IOUtils;
import org.opennms.core.utils.FileReloadCallback;
import org.opennms.core.xml.JaxbUtils;
import org.opennms.netmgt.provision.persist.foreignsource.ForeignSource;
import org.opennms.netmgt.provision.persist.requisition.Requisition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

/**
 * <p>FilesystemForeignSourceRepository class.</p>
 *
 * @author ranger
 * @version $Id: $
 */
public class FasterFilesystemForeignSourceRepository extends AbstractForeignSourceRepository
        implements InitializingBean {

    private static final Logger LOG = LoggerFactory.getLogger(FasterFilesystemForeignSourceRepository.class);
    private String m_requisitionPath;
    private String m_foreignSourcePath;

    private final ReadWriteLock m_globalLock = new ReentrantReadWriteLock();
    private final Lock m_readLock = m_globalLock.readLock();
    private final Lock m_writeLock = m_globalLock.writeLock();

    private DirectoryWatcher<ForeignSource> m_foreignSources;
    private DirectoryWatcher<Requisition> m_requisitions;

    /**
     * <p>Constructor for FilesystemForeignSourceRepository.</p>
     *
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    public FasterFilesystemForeignSourceRepository() throws ForeignSourceRepositoryException {
        super();
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(m_requisitionPath, "Requisition path must not be empty.");
        Assert.notNull(m_foreignSourcePath, "Foreign source path must not be empty.");

        m_foreignSources = new DirectoryWatcher<ForeignSource>(new File(m_foreignSourcePath), fsLoader());
        m_requisitions = new DirectoryWatcher<Requisition>(new File(m_requisitionPath), reqLoader());
    }

    /**
     * <p>getActiveForeignSourceNames</p>
     *
     * @return a {@link java.util.Set} object.
     */
    @Override
    public Set<String> getActiveForeignSourceNames() {
        m_readLock.lock();
        try {
            Set<String> activeForeignSourceNames = new LinkedHashSet<String>();
            activeForeignSourceNames.addAll(m_foreignSources.getBaseNamesWithExtension(".xml"));
            activeForeignSourceNames.addAll(m_requisitions.getBaseNamesWithExtension(".xml"));
            return activeForeignSourceNames;

        } finally {
            m_readLock.unlock();
        }
    }

    /**
     * <p>getForeignSourceCount</p>
     *
     * @return a int.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public int getForeignSourceCount() throws ForeignSourceRepositoryException {
        m_readLock.lock();
        try {
            return m_foreignSources.getBaseNamesWithExtension(".xml").size();
        } finally {
            m_readLock.unlock();
        }
    }

    /**
     * <p>getForeignSources</p>
     *
     * @return a {@link java.util.Set} object.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public Set<ForeignSource> getForeignSources() throws ForeignSourceRepositoryException {
        m_readLock.lock();
        try {
            Set<ForeignSource> foreignSources = new LinkedHashSet<ForeignSource>();
            for (String baseName : m_foreignSources.getBaseNamesWithExtension(".xml")) {
                try {
                    ForeignSource contents = m_foreignSources.getContents(baseName + ".xml");
                    foreignSources.add(contents);
                } catch (FileNotFoundException e) {
                    LOG.info("Unable to load foreignSource {}: It must have been deleted by another thread",
                            baseName, e);
                }
            }
            return foreignSources;
        } finally {
            m_readLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public ForeignSource getForeignSource(final String foreignSourceName) throws ForeignSourceRepositoryException {
        if (foreignSourceName == null) {
            throw new ForeignSourceRepositoryException("can't get a foreign source with a null name!");
        }
        m_readLock.lock();
        try {
            return m_foreignSources.getContents(foreignSourceName + ".xml");
        } catch (FileNotFoundException e) {
            final ForeignSource fs = getDefaultForeignSource();
            fs.setName(foreignSourceName);
            return fs;
        } finally {
            m_readLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public void save(final ForeignSource foreignSource) throws ForeignSourceRepositoryException {
        if (foreignSource == null) {
            throw new ForeignSourceRepositoryException("can't save a null foreign source!");
        }

        LOG.debug("Writing foreign source {} to {}", foreignSource.getName(), m_foreignSourcePath);
        validate(foreignSource);

        m_writeLock.lock();
        try {
            if (foreignSource.getName().equals("default")) {
                putDefaultForeignSource(foreignSource);
                return;
            }
            final File outputFile = RequisitionFileUtils.getOutputFileForForeignSource(m_foreignSourcePath,
                    foreignSource);
            OutputStream outputStream = null;
            Writer writer = null;
            try {
                outputStream = new FileOutputStream(outputFile);
                writer = new OutputStreamWriter(outputStream, "UTF-8");
                JaxbUtils.marshal(foreignSource, writer);
            } catch (final Throwable e) {
                throw new ForeignSourceRepositoryException("unable to write requisition to " + outputFile.getPath(),
                        e);
            } finally {
                IOUtils.closeQuietly(writer);
                IOUtils.closeQuietly(outputStream);
            }
        } finally {
            m_writeLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public void delete(final ForeignSource foreignSource) throws ForeignSourceRepositoryException {
        m_writeLock.lock();
        try {
            LOG.debug("Deleting foreign source {} from {} (if necessary)", foreignSource.getName(),
                    m_foreignSourcePath);
            final File deleteFile = RequisitionFileUtils.getOutputFileForForeignSource(m_foreignSourcePath,
                    foreignSource);
            if (deleteFile.exists()) {
                if (!deleteFile.delete()) {
                    throw new ForeignSourceRepositoryException(
                            "unable to delete foreign source file " + deleteFile);
                }
            }
        } finally {
            m_writeLock.unlock();
        }
    }

    /**
     * <p>getRequisitions</p>
     *
     * @return a {@link java.util.Set} object.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public Set<Requisition> getRequisitions() throws ForeignSourceRepositoryException {
        m_readLock.lock();
        try {
            Set<Requisition> requisitions = new LinkedHashSet<Requisition>();
            for (String baseName : m_requisitions.getBaseNamesWithExtension(".xml")) {
                try {
                    Requisition contents = m_requisitions.getContents(baseName + ".xml");
                    requisitions.add(contents);
                } catch (FileNotFoundException e) {
                    LOG.info("Unable to load requisition {}: It must have been deleted by another thread", baseName,
                            e);
                }
            }
            return requisitions;
        } finally {
            m_readLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public Requisition getRequisition(final String foreignSourceName) throws ForeignSourceRepositoryException {
        if (foreignSourceName == null) {
            throw new ForeignSourceRepositoryException("can't get a requisition with a null foreign source name!");
        }
        m_readLock.lock();
        try {
            return m_requisitions.getContents(foreignSourceName + ".xml");
        } catch (FileNotFoundException e) {
            throw new ForeignSourceRepositoryException("Requisition: " + foreignSourceName + " does not exist.", e);
        } finally {
            m_readLock.unlock();
        }
    }

    /**
     * <p>getRequisition</p>
     *
     * @param foreignSource a {@link org.opennms.netmgt.provision.persist.foreignsource.ForeignSource} object.
     * @return a {@link org.opennms.netmgt.provision.persist.requisition.Requisition} object.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public Requisition getRequisition(final ForeignSource foreignSource) throws ForeignSourceRepositoryException {
        if (foreignSource == null) {
            throw new ForeignSourceRepositoryException("can't get a requisition with a null foreign source name!");
        }
        m_readLock.lock();
        try {
            return getRequisition(foreignSource.getName());
        } finally {
            m_readLock.unlock();
        }
    }

    /**
     * <p>save</p>
     *
     * @param requisition a {@link org.opennms.netmgt.provision.persist.requisition.Requisition} object.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public void save(final Requisition requisition) throws ForeignSourceRepositoryException {
        if (requisition == null) {
            throw new ForeignSourceRepositoryException("can't save a null requisition!");
        }

        LOG.debug("Writing requisition {} to {}", requisition.getForeignSource(), m_requisitionPath);
        validate(requisition);

        m_writeLock.lock();
        try {
            final File outputFile = RequisitionFileUtils.getOutputFileForRequisition(m_requisitionPath,
                    requisition);
            Writer writer = null;
            OutputStream outputStream = null;
            try {
                outputStream = new FileOutputStream(outputFile);
                writer = new OutputStreamWriter(outputStream, "UTF-8");
                JaxbUtils.marshal(requisition, writer);
            } catch (final Throwable e) {
                throw new ForeignSourceRepositoryException("unable to write requisition to " + outputFile.getPath(),
                        e);
            } finally {
                IOUtils.closeQuietly(writer);
                IOUtils.closeQuietly(outputStream);
            }
        } finally {
            m_writeLock.unlock();
        }
    }

    /**
     * <p>delete</p>
     *
     * @param requisition a {@link org.opennms.netmgt.provision.persist.requisition.Requisition} object.
     * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any.
     */
    @Override
    public void delete(final Requisition requisition) throws ForeignSourceRepositoryException {
        if (requisition == null) {
            throw new ForeignSourceRepositoryException("can't delete a null requisition!");
        }
        m_writeLock.lock();
        try {
            LOG.debug("Deleting requisition {} from {} (if necessary)", requisition.getForeignSource(),
                    m_requisitionPath);
            final File deleteFile = RequisitionFileUtils.getOutputFileForRequisition(m_requisitionPath,
                    requisition);
            if (deleteFile.exists()) {
                if (!deleteFile.delete()) {
                    throw new ForeignSourceRepositoryException("unable to delete requisition file " + deleteFile);
                }
            }
        } finally {
            m_writeLock.unlock();
        }
    }

    /**
     * <p>setRequisitionPath</p>
     *
     * @param path a {@link java.lang.String} object.
     */
    public void setRequisitionPath(final String path) {
        m_writeLock.lock();
        try {
            m_requisitionPath = path;
        } finally {
            m_writeLock.unlock();
        }
    }

    /**
     * <p>setForeignSourcePath</p>
     *
     * @param path a {@link java.lang.String} object.
     */
    public void setForeignSourcePath(final String path) {
        m_writeLock.lock();
        try {
            m_foreignSourcePath = path;
        } finally {
            m_writeLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public Date getRequisitionDate(final String foreignSource) throws ForeignSourceRepositoryException {
        m_readLock.lock();
        try {
            final Requisition requisition = getRequisition(foreignSource);
            if (requisition == null) {
                return null;
            }
            return requisition.getDate();
        } finally {
            m_readLock.unlock();
        }
    }

    /** {@inheritDoc} */
    @Override
    public URL getRequisitionURL(final String foreignSource) throws ForeignSourceRepositoryException {
        m_readLock.lock();
        try {
            final Requisition requisition = getRequisition(foreignSource);
            if (requisition == null) {
                return null;
            }
            return RequisitionFileUtils.getOutputFileForRequisition(m_requisitionPath, requisition).toURI().toURL();
        } catch (final MalformedURLException e) {
            throw new ForeignSourceRepositoryException("an error occurred getting the requisition URL", e);
        } finally {
            m_readLock.unlock();
        }
    }

    @Override
    public void flush() throws ForeignSourceRepositoryException {
        // Unnecessary, there is no caching/delayed writes in FilesystemForeignSourceRepository
        LOG.debug("flush() called");
    }

    private FileReloadCallback<ForeignSource> fsLoader() {
        return new FileReloadCallback<ForeignSource>() {

            @Override
            public ForeignSource reload(ForeignSource object, Resource resource) throws IOException {
                return RequisitionFileUtils.getForeignSourceFromFile(resource.getFile());
            }
        };
    };

    private FileReloadCallback<Requisition> reqLoader() {
        return new FileReloadCallback<Requisition>() {

            @Override
            public Requisition reload(Requisition object, Resource resource) throws IOException {
                return RequisitionFileUtils.getRequisitionFromFile(resource.getFile());
            }
        };
    }

}