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

org.openas2.processor.receiver.DirectoryPollingModule Maven / Gradle / Ivy

Go to download

Open source implementation of the AS2 standard for signed encrypted and compressed document transfer

There is a newer version: 2.10.1
Show newest version
package org.openas2.processor.receiver;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openas2.OpenAS2Exception;
import org.openas2.Session;
import org.openas2.message.Message;
import org.openas2.params.InvalidParameterException;
import org.openas2.util.IOUtil;

public abstract class DirectoryPollingModule extends PollingModule {
    public static final String PARAM_OUTBOX_DIRECTORY = "outboxdir";
    public static final String PARAM_FILE_EXTENSION_FILTER = "fileextensionfilter";
    public static final String PARAM_FILE_EXTENSION_EXCLUDE_FILTER = "fileextensionexcludefilter";
    private Map trackedFiles;
    private String outboxDir;
    private String errorDir;
    private String sentDir = null;
    private List allowExtensions;
    private List excludeExtensions;

    private Log logger = LogFactory.getLog(DirectoryPollingModule.class.getSimpleName());

    public void init(Session session, Map options) throws OpenAS2Exception {
	super.init(session, options);
	// Check all the directories are configured and actually exist on the file
	// system
	try {
	    outboxDir = getParameter(PARAM_OUTBOX_DIRECTORY, true);
	    IOUtil.getDirectoryFile(outboxDir);
	    errorDir = getParameter(PARAM_ERROR_DIRECTORY, true);
	    IOUtil.getDirectoryFile(errorDir);
	    sentDir = getParameter(PARAM_SENT_DIRECTORY, false);
	    if (sentDir != null)
		IOUtil.getDirectoryFile(sentDir);
	    String pendingInfoFolder = getSession().getProcessor().getParameters().get("pendingmdninfo");
	    IOUtil.getDirectoryFile(pendingInfoFolder);
	    String pendingFolder = getSession().getProcessor().getParameters().get("pendingmdn");
	    IOUtil.getDirectoryFile(pendingFolder);
	    String allowExtensionFilter = getParameter(PARAM_FILE_EXTENSION_FILTER, "");
	    String excludeExtensionFilter = getParameter(PARAM_FILE_EXTENSION_EXCLUDE_FILTER, "");

	    if (allowExtensionFilter == null || allowExtensionFilter.length() < 1)
		this.allowExtensions = new ArrayList();
	    else
		this.allowExtensions = Arrays.asList(allowExtensionFilter.split("\\s*,\\s*"));
	    if (excludeExtensionFilter == null || excludeExtensionFilter.length() < 1)
		this.excludeExtensions = new ArrayList();
	    else
		this.excludeExtensions = Arrays.asList(excludeExtensionFilter.split("\\s*,\\s*"));

	} catch (IOException e) {
	    throw new OpenAS2Exception("Failed to initialise directory poller.", e);
	}
    }

    @Override
    public boolean healthcheck(List failures) {
	try {
	    IOUtil.getDirectoryFile(outboxDir);
	} catch (IOException e) {
	    failures.add(this.getClass().getSimpleName() + " - Polling directory is not accessible: " + outboxDir);
	    return false;
	}
	return true;
    }

    public void poll() {
	try {
	    // update tracking info. if a file is ready, process it
	    updateTracking();

	    // scan the directory for new files
	    scanDirectory(outboxDir);
	} catch (OpenAS2Exception oae) {
	    oae.terminate();
	} catch (Exception e) {
	    logger.error("Unexpected error occurred polling directory for files to send: " + outboxDir, e);
	}
    }

    protected void scanDirectory(String directory) throws IOException, InvalidParameterException {
	File dir = IOUtil.getDirectoryFile(directory);
	// get a list of entries in the directory
	File[] files = IOUtil.getFiles(dir, allowExtensions, excludeExtensions);
	if (files == null) {
	    throw new InvalidParameterException("Error getting list of files in directory", this,
		    PARAM_OUTBOX_DIRECTORY, dir.getAbsolutePath());
	}

	// iterator through each entry, and start tracking new files
	if (files.length > 0) {
	    for (int i = 0; i < files.length; i++) {
		File currentFile = files[i];

		if (checkFile(currentFile)) {
		    // start watching the file's size if it's not already being
		    // watched
		    trackFile(currentFile);
		}
	    }
	}
    }

    protected boolean checkFile(File file) {
	if (file.exists() && file.isFile()) {
	    try {
		// check for a write-lock on file, will skip file if it's write
		// locked
		FileOutputStream fOut = new FileOutputStream(file, true);
		fOut.close();
		return true;
	    } catch (IOException ioe) {
		// a sharing violation occurred, ignore the file for now
		if (logger.isDebugEnabled()) {
		    try {
			logger.debug("Directory poller detected a non-writable file and will be ignored: "
				+ file.getCanonicalPath());
		    } catch (IOException e) {
			e.printStackTrace();
		    }
		}
	    }
	}
	return false;
    }

    private void trackFile(File file) {
	Map trackedFiles = getTrackedFiles();
	String filePath = file.getAbsolutePath();
	if (trackedFiles.get(filePath) == null) {
	    trackedFiles.put(filePath, file.length());
	}
    }

    private void updateTracking() {
	// clone the trackedFiles map, iterator through the clone and modify the
	// original to avoid iterator exceptions
	// is there a better way to do this?
	Map trackedFiles = getTrackedFiles();
	Map trackedFilesClone = new HashMap(trackedFiles);

	for (Map.Entry fileEntry : trackedFilesClone.entrySet()) {
	    // get the file and it's stored length
	    File file = new File(fileEntry.getKey());
	    long fileLength = fileEntry.getValue().longValue();

	    // if the file no longer exists, remove it from the tracker
	    if (!checkFile(file)) {
		trackedFiles.remove(fileEntry.getKey());
	    } else {
		// if the file length has changed, update the tracker
		long newLength = file.length();
		if (newLength != fileLength) {
		    trackedFiles.put(fileEntry.getKey(), Long.valueOf(newLength));
		} else {
		    // if the file length has stayed the same, process the file
		    // and stop tracking it
		    try {
			processFile(file);
		    } catch (OpenAS2Exception e) {
			e.terminate();
			try {
			    IOUtil.handleError(file, errorDir);
			} catch (OpenAS2Exception e1) {
			    logger.error("Error handling file error for file: " + file.getAbsolutePath(), e1);
			    forceStop(e1);
			    return;
			}
		    } finally {
			trackedFiles.remove(fileEntry.getKey());
		    }
		}
	    }
	}
    }

    protected abstract Message createMessage();

    protected void processFile(File file) throws OpenAS2Exception {

	if (logger.isInfoEnabled())
	    logger.info("processing " + file.getAbsolutePath());

	try (FileInputStream in = new FileInputStream(file)) {
	    processDocument(in, file.getName());
	    try {
		IOUtil.deleteFile(file);
	    } catch (IOException e) {
		throw new OpenAS2Exception("Failed to delete file handed off for processing:" + file.getAbsolutePath(),
			e);
	    }
	} catch (IOException e) {
	    throw new OpenAS2Exception("Failed to process file:" + file.getAbsolutePath(), e);
	}
    }

    private Map getTrackedFiles() {
	if (trackedFiles == null) {
	    trackedFiles = new HashMap();
	}
	return trackedFiles;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy