/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 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.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.MalformedURLException; import java.net.URL; import java.util.Set; import java.util.TreeSet; 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.xml.JaxbUtils; import org.opennms.netmgt.provision.persist.foreignsource.ForeignSource; import org.opennms.netmgt.provision.persist.requisition.Requisition; /** * <p>FilesystemForeignSourceRepository class.</p> * * @author ranger * @version $Id: $ */ public class FilesystemForeignSourceRepository extends AbstractForeignSourceRepository { private String m_requisitionPath; private String m_foreignSourcePath; private boolean m_updateDateStamps = true; private final ReadWriteLock m_globalLock = new ReentrantReadWriteLock(); private final Lock m_readLock = m_globalLock.readLock(); private final Lock m_writeLock = m_globalLock.writeLock(); /** * <p>Constructor for FilesystemForeignSourceRepository.</p> * * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any. */ public FilesystemForeignSourceRepository() throws ForeignSourceRepositoryException { super(); } /** * <p>getActiveForeignSourceNames</p> * * @return a {@link java.util.Set} object. */ public Set<String> getActiveForeignSourceNames() { m_readLock.lock(); try { final Set<String> fsNames = new TreeSet<String>(); File directory = new File(m_foreignSourcePath); if (directory.exists()) { for (final File file : directory.listFiles()) { if (file.getName().endsWith(".xml")) { fsNames.add(file.getName().replaceAll(".xml$", "")); } } } directory = new File(m_requisitionPath); if (directory.exists()) { for (final File file : directory.listFiles()) { if (file.getName().endsWith(".xml")) { fsNames.add(file.getName().replaceAll(".xml$", "")); } } } return fsNames; } finally { m_readLock.unlock(); } } /** * <p>setUpdateDateStamps</p> * * @param update a boolean. */ public void setUpdateDateStamps(final boolean update) { m_writeLock.lock(); try { m_updateDateStamps = update; } finally { m_writeLock.unlock(); } } /** * <p>getForeignSourceCount</p> * * @return a int. * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any. */ public int getForeignSourceCount() throws ForeignSourceRepositoryException { m_readLock.lock(); try { return getForeignSources().size(); } finally { m_readLock.unlock(); } } /** * <p>getForeignSources</p> * * @return a {@link java.util.Set} object. * @throws org.opennms.netmgt.provision.persist.ForeignSourceRepositoryException if any. */ public Set<ForeignSource> getForeignSources() throws ForeignSourceRepositoryException { m_readLock.lock(); try { final File directory = new File(m_foreignSourcePath); final TreeSet<ForeignSource> foreignSources = new TreeSet<ForeignSource>(); if (directory.exists()) { for (final File file : directory.listFiles()) { if (file.getName().endsWith(".xml")) { foreignSources.add(get(file)); } } } return foreignSources; } finally { m_readLock.unlock(); } } /** {@inheritDoc} */ 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 { final File inputFile = encodeFileName(m_foreignSourcePath, foreignSourceName); if (inputFile != null && inputFile.exists()) { return get(inputFile); } else { final ForeignSource fs = getDefaultForeignSource(); fs.setName(foreignSourceName); return fs; } } finally { m_readLock.unlock(); } } /** {@inheritDoc} */ public void save(final ForeignSource foreignSource) throws ForeignSourceRepositoryException { if (foreignSource == null) { throw new ForeignSourceRepositoryException("can't save a null foreign source!"); } validate(foreignSource); m_writeLock.lock(); try { if (foreignSource.getName().equals("default")) { putDefaultForeignSource(foreignSource); return; } final File outputFile = getOutputFileForForeignSource(foreignSource); OutputStream outputStream = null; Writer writer = null; try { if (m_updateDateStamps) { foreignSource.updateDateStamp(); } 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} */ public void delete(final ForeignSource foreignSource) throws ForeignSourceRepositoryException { m_writeLock.lock(); try { final File deleteFile = getOutputFileForForeignSource(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. */ public Set<Requisition> getRequisitions() throws ForeignSourceRepositoryException { m_readLock.lock(); try { final File directory = new File(m_requisitionPath); final TreeSet<Requisition> requisitions = new TreeSet<Requisition>(); if (directory.exists()) { for (final File file : directory.listFiles()) { if (file.getName().endsWith(".xml")) { try { requisitions.add(getRequisition(file)); } catch (ForeignSourceRepositoryException e) { // race condition, probably got deleted by the importer as part of moving things // need a better way to handle this; move "pending" to the database? } } } } return requisitions; } finally { m_readLock.unlock(); } } /** {@inheritDoc} */ 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 { final File inputFile = encodeFileName(m_requisitionPath, foreignSourceName); if (inputFile != null && inputFile.exists()) { return getRequisition(inputFile); } return null; } 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. */ 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. */ public void save(final Requisition requisition) throws ForeignSourceRepositoryException { if (requisition == null) { throw new ForeignSourceRepositoryException("can't save a null requisition!"); } validate(requisition); m_writeLock.lock(); try { final File outputFile = getOutputFileForRequisition(requisition); Writer writer = null; OutputStream outputStream = null; try { if (m_updateDateStamps) { requisition.updateDateStamp(); } 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. */ public void delete(final Requisition requisition) throws ForeignSourceRepositoryException { if (requisition == null) { throw new ForeignSourceRepositoryException("can't delete a null requisition!"); } m_writeLock.lock(); try { final File deleteFile = getOutputFileForRequisition(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} */ public URL getRequisitionURL(final String foreignSource) throws ForeignSourceRepositoryException { m_readLock.lock(); try { return getOutputFileForRequisition(getRequisition(foreignSource)).toURI().toURL(); } catch (final MalformedURLException e) { throw new ForeignSourceRepositoryException("an error occurred getting the requisition URL", e); } finally { m_readLock.unlock(); } } private ForeignSource get(final File inputFile) throws ForeignSourceRepositoryException { return JaxbUtils.unmarshal(ForeignSource.class, inputFile); } private Requisition getRequisition(final File inputFile) throws ForeignSourceRepositoryException { try { return JaxbUtils.unmarshal(Requisition.class, inputFile); } catch (final Throwable e) { throw new ForeignSourceRepositoryException("unable to unmarshal " + inputFile.getPath(), e); } } private void createPath(final File fsPath) throws ForeignSourceRepositoryException { if (!fsPath.exists()) { if (!fsPath.mkdirs()) { throw new ForeignSourceRepositoryException("unable to create directory " + fsPath.getPath()); } } } private File encodeFileName(final String path, final String foreignSourceName) { // return new File(path, java.net.URLEncoder.encode(foreignSourceName, "UTF-8") + ".xml"); return new File(path, foreignSourceName + ".xml"); } private File getOutputFileForForeignSource(final ForeignSource foreignSource) { final File fsPath = new File(m_foreignSourcePath); createPath(fsPath); return encodeFileName(m_foreignSourcePath, foreignSource.getName()); } private File getOutputFileForRequisition(final Requisition requisition) { final File reqPath = new File(m_requisitionPath); createPath(reqPath); return encodeFileName(m_requisitionPath, requisition.getForeignSource()); } }