/* * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.wso2.carbon.inbound.endpoint.protocol.file; import org.apache.commons.lang.WordUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.vfs2.FileContent; import org.apache.commons.vfs2.FileNotFolderException; import org.apache.commons.vfs2.FileNotFoundException; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemException; import org.apache.commons.vfs2.FileSystemManager; import org.apache.commons.vfs2.FileSystemOptions; import org.apache.commons.vfs2.FileType; import org.apache.commons.vfs2.impl.StandardFileSystemManager; import org.apache.commons.vfs2.provider.UriParser; import org.apache.synapse.SynapseException; import org.apache.synapse.commons.vfs.VFSConstants; import org.apache.synapse.commons.vfs.VFSParamDTO; import org.apache.synapse.commons.vfs.VFSUtils; import org.apache.synapse.core.SynapseEnvironment; import org.wso2.carbon.mediation.clustering.ClusteringServiceUtil; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * * This class implement the processing logic related to inbound file protocol. * Common functinalities (with synapse vfs transport) are include in synapse * util that is found in synapse commons * */ public class FilePollingConsumer { private static final Log log = LogFactory.getLog(FilePollingConsumer.class); private Properties vfsProperties; private boolean fileLock = true; private FileSystemManager fsManager = null; private String name; private SynapseEnvironment synapseEnvironment; private long scanInterval; private Long lastRanTime; private int lastCycle; private FileInjectHandler injectHandler; private String fileURI; private FileObject fileObject; private Integer iFileProcessingInterval = null; private Integer iFileProcessingCount = null; private int maxRetryCount; private long reconnectionTimeout; private String strFilePattern; private boolean autoLockRelease; private Boolean autoLockReleaseSameNode; private Long autoLockReleaseInterval; private boolean distributedLock; private Long distributedLockTimeout; private FileSystemOptions fso; public FilePollingConsumer(Properties vfsProperties, String name, SynapseEnvironment synapseEnvironment, long scanInterval) { this.vfsProperties = vfsProperties; this.name = name; this.synapseEnvironment = synapseEnvironment; this.scanInterval = scanInterval; this.lastRanTime = null; setupParams(); try { StandardFileSystemManager fsm = new StandardFileSystemManager(); fsm.setConfiguration(getClass().getClassLoader().getResource("providers.xml")); fsm.init(); fsManager = fsm; } catch (Exception e) { log.error(e); throw new RuntimeException(e); } //Setup SFTP Options try { fso = VFSUtils.attachFileSystemOptions(parseSchemeFileOptions(fileURI),fsManager); } catch (Exception e) { log.warn("Unable to set the sftp Options", e); fso = null; } } /** * Register a handler to process the file stream after reading from the * source * * @param injectHandler */ public void registerHandler(FileInjectHandler injectHandler) { this.injectHandler = injectHandler; } /** * This will be called by the task scheduler. If a cycle execution takes * more than the schedule interval, tasks will call this method ignoring the * interval. Timestamp based check is done to avoid that. */ public void execute() { try { if (log.isDebugEnabled()) { log.debug("Start : File Inbound EP : " + name); } // Check if the cycles are running in correct interval and start // scan long currentTime = (new Date()).getTime(); if (lastRanTime == null || ((lastRanTime + (scanInterval)) <= currentTime)) { lastRanTime = currentTime; poll(); } else if (log.isDebugEnabled()) { log.debug("Skip cycle since cuncurrent rate is higher than the scan interval : VFS Inbound EP : " + name); } if (log.isDebugEnabled()) { log.debug("End : File Inbound EP : " + name); } } catch (Exception e) { log.error("Error while reading file. " + e.getMessage(), e); } } /** * * Do the file processing operation for the given set of properties. Do the * checks and pass the control to processFile method * * */ public FileObject poll() { if (fileURI == null || fileURI.trim().equals("")) { log.error("Invalid file url. Check the inbound endpoint configuration. Endpoint Name : " + name + ", File URL : " + VFSUtils.maskURLPassword(fileURI)); return null; } if (log.isDebugEnabled()) { log.debug("Start : Scanning directory or file : " + VFSUtils.maskURLPassword(fileURI)); } if (!initFileCheck()) { // Unable to read from the source location provided. return null; } // If file/folder found proceed to the processing stage try { lastCycle = 0; if (fileObject.exists() && fileObject.isReadable()) { FileObject[] children = null; try { children = fileObject.getChildren(); } catch (FileNotFolderException ignored) { if (log.isDebugEnabled()) { log.debug("No Folder found. Only file found on : " + VFSUtils.maskURLPassword(fileURI)); } } catch (FileSystemException ex) { log.error(ex.getMessage(), ex); } // if this is a file that would translate to a single message if (children == null || children.length == 0) { // Fail record is a one that is processed but was not moved // or deleted due to an error. boolean isFailedRecord = VFSUtils.isFailRecord(fsManager, fileObject); if (!isFailedRecord) { fileHandler(); if (injectHandler == null) { return fileObject; } } else { try { lastCycle = 2; moveOrDeleteAfterProcessing(fileObject); } catch (SynapseException synapseException) { log.error("File object '" + VFSUtils.maskURLPassword(fileObject.getURL().toString()) + "' " + "cloud not be moved after first attempt", synapseException); } if (fileLock) { // TODO: passing null to avoid build break. Fix properly VFSUtils.releaseLock(fsManager, fileObject, fso); } if (log.isDebugEnabled()) { log.debug("File '" + VFSUtils.maskURLPassword(fileObject.getURL().toString()) + "' has been marked as a failed" + " record, it will not process"); } } } else { FileObject fileObject = directoryHandler(children); if (fileObject != null) { return fileObject; } } } else { log.warn("Unable to access or read file or directory : " + VFSUtils.maskURLPassword(fileURI) + "." + " Reason: " + (fileObject.exists() ? (fileObject.isReadable() ? "Unknown reason" : "The file can not be read!") : "The file does not exists!")); return null; } } catch (FileSystemException e) { log.error( "Error checking for existence and readability : " + VFSUtils.maskURLPassword(fileURI), e); return null; } catch (Exception e) { log.error( "Error while processing the file/folder in URL : " + VFSUtils.maskURLPassword(fileURI), e); return null; } finally { try { if (fsManager != null) { fsManager.closeFileSystem(fileObject.getParent().getFileSystem()); } fileObject.close(); } catch (Exception e) { log.error("Unable to close the file system. " + e.getMessage()); log.error(e); } } if (log.isDebugEnabled()) { log.debug("End : Scanning directory or file : " + VFSUtils.maskURLPassword(fileURI)); } return null; } /** * If not a folder just a file handle the flow * * @throws FileSystemException */ private void fileHandler() throws FileSystemException { if (fileObject.getType() == FileType.FILE) { if (!fileLock || (fileLock && acquireLock(fsManager, fileObject))) { boolean runPostProcess = true; try { if (processFile(fileObject) == null) { runPostProcess = false; } lastCycle = 1; } catch (SynapseException e) { lastCycle = 2; log.error("Error processing File URI : " + VFSUtils.maskURLPassword(fileObject.getName().toString()), e); } if (runPostProcess) { try { moveOrDeleteAfterProcessing(fileObject); } catch (SynapseException synapseException) { lastCycle = 3; log.error("File object '" + VFSUtils.maskURLPassword(fileObject.getURL().toString()) + "' " + "cloud not be moved", synapseException); VFSUtils.markFailRecord(fsManager, fileObject); } } if (fileLock) { // TODO: passing null to avoid build break. Fix properly VFSUtils.releaseLock(fsManager, fileObject, fso); if (log.isDebugEnabled()) { log.debug("Removed the lock file '" + VFSUtils.maskURLPassword(fileObject.toString()) + ".lock' of the file '" + VFSUtils.maskURLPassword(fileObject.toString())); } } } else { log.error("Couldn't get the lock for processing the file : " + VFSUtils.maskURLPassword(fileObject.getName().toString())); } } else { if (log.isDebugEnabled()) { log.debug("Cannot find the file or failed file record. File : " + VFSUtils.maskURLPassword(fileURI)); } } } /** * Setup the required parameters */ private void setupParams() { fileURI = vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_FILE_URI); String strFileLock = vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_LOCKING); if (strFileLock != null && strFileLock.toLowerCase().equals(VFSConstants.TRANSPORT_FILE_LOCKING_DISABLED)) { fileLock = false; } strFilePattern = vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_FILE_NAME_PATTERN); if (vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_INTERVAL) != null) { try { iFileProcessingInterval = Integer.valueOf(vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_INTERVAL)); } catch (NumberFormatException e) { log.warn("Invalid param value for transport.vfs.FileProcessInterval : " + vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_INTERVAL) + ". Expected numeric value."); } } if (vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_COUNT) != null) { try { iFileProcessingCount = Integer.valueOf(vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_COUNT)); } catch (NumberFormatException e) { log.warn("Invalid param value for transport.vfs.FileProcessCount : " + vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_COUNT) + ". Expected numeric value."); } } maxRetryCount = 0; if (vfsProperties.getProperty(VFSConstants.MAX_RETRY_COUNT) != null) { try { maxRetryCount = Integer.valueOf(vfsProperties .getProperty(VFSConstants.MAX_RETRY_COUNT)); } catch (NumberFormatException e) { log.warn("Invalid values for Max Retry Count"); maxRetryCount = 0; } } reconnectionTimeout = 1; if (vfsProperties.getProperty(VFSConstants.RECONNECT_TIMEOUT) != null) { try { reconnectionTimeout = Long.valueOf(vfsProperties .getProperty(VFSConstants.RECONNECT_TIMEOUT)); } catch (NumberFormatException e) { log.warn("Invalid values for Reconnection Timeout"); reconnectionTimeout = 1; } } String strAutoLock = vfsProperties.getProperty(VFSConstants.TRANSPORT_AUTO_LOCK_RELEASE); autoLockRelease = false; autoLockReleaseSameNode = true; autoLockReleaseInterval = null; if (strAutoLock != null) { try { autoLockRelease = Boolean.parseBoolean(strAutoLock); } catch (Exception e) { autoLockRelease = false; log.warn("VFS Auto lock removal not set properly. Current value is : " + strAutoLock, e); } if (autoLockRelease) { String strAutoLockInterval = vfsProperties .getProperty(VFSConstants.TRANSPORT_AUTO_LOCK_RELEASE_INTERVAL); if (strAutoLockInterval != null) { try { autoLockReleaseInterval = Long.parseLong(strAutoLockInterval); } catch (Exception e) { autoLockReleaseInterval = null; log.warn( "VFS Auto lock removal property not set properly. Current value is : " + strAutoLockInterval, e); } } String strAutoLockReleaseSameNode = vfsProperties .getProperty(VFSConstants.TRANSPORT_AUTO_LOCK_RELEASE_SAME_NODE); if (strAutoLockReleaseSameNode != null) { try { autoLockReleaseSameNode = Boolean.parseBoolean(strAutoLockReleaseSameNode); } catch (Exception e) { autoLockReleaseSameNode = true; log.warn( "VFS Auto lock removal property not set properly. Current value is : " + autoLockReleaseSameNode, e); } } } } distributedLock = false; distributedLockTimeout = null; String strDistributedLock = vfsProperties .getProperty(VFSConstants.TRANSPORT_DISTRIBUTED_LOCK); if (strDistributedLock != null) { try { distributedLock = Boolean.parseBoolean(strDistributedLock); } catch (Exception e) { autoLockRelease = false; log.warn("VFS Distributed lock not set properly. Current value is : " + strDistributedLock, e); } if (distributedLock) { String strDistributedLockTimeout = vfsProperties .getProperty(VFSConstants.TRANSPORT_DISTRIBUTED_LOCK_TIMEOUT); if (strDistributedLockTimeout != null) { try { distributedLockTimeout = Long.parseLong(strDistributedLockTimeout); } catch (Exception e) { distributedLockTimeout = null; log.warn( "VFS Distributed lock timeout property not set properly. Current value is : " + strDistributedLockTimeout, e); } } } } } private Map<String, String> parseSchemeFileOptions(String fileURI) { String scheme = UriParser.extractScheme(fileURI); if (scheme == null) { return null; } HashMap<String, String> schemeFileOptions = new HashMap<String, String>(); schemeFileOptions.put(VFSConstants.SCHEME, scheme); try { addOptions(scheme, schemeFileOptions); } catch (Exception e) { log.warn("Error while loading VFS parameter. " + e.getMessage()); } return schemeFileOptions; } private void addOptions(String scheme, Map<String, String> schemeFileOptions) { if (scheme.equals(VFSConstants.SCHEME_SFTP)) { for (VFSConstants.SFTP_FILE_OPTION option : VFSConstants.SFTP_FILE_OPTION.values()) { String strValue = vfsProperties.getProperty(VFSConstants.SFTP_PREFIX + WordUtils.capitalize(option.toString())); if (strValue != null && !strValue.equals("")) { schemeFileOptions.put(option.toString(), strValue); } } } } /** * * Handle directory with chile elements * * @param children * @return * @throws FileSystemException */ private FileObject directoryHandler(FileObject[] children) throws FileSystemException { // Process Directory lastCycle = 0; int failCount = 0; int successCount = 0; int processCount = 0; if (log.isDebugEnabled()) { log.debug("File name pattern : " + vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_FILE_NAME_PATTERN)); } // Sort the files String strSortParam = vfsProperties.getProperty(VFSConstants.FILE_SORT_PARAM); if (strSortParam != null && !"NONE".equals(strSortParam)) { log.debug("Start Sorting the files."); String strSortOrder = vfsProperties.getProperty(VFSConstants.FILE_SORT_ORDER); boolean bSortOrderAsscending = true; if (strSortOrder != null && strSortOrder.toLowerCase().equals("false")) { bSortOrderAsscending = false; } if (log.isDebugEnabled()) { log.debug("Sorting the files by : " + strSortOrder + ". (" + bSortOrderAsscending + ")"); } if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_NAME) && bSortOrderAsscending) { Arrays.sort(children, new FileNameAscComparator()); } else if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_NAME) && !bSortOrderAsscending) { Arrays.sort(children, new FileNameDesComparator()); } else if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_SIZE) && bSortOrderAsscending) { Arrays.sort(children, new FileSizeAscComparator()); } else if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_SIZE) && !bSortOrderAsscending) { Arrays.sort(children, new FileSizeDesComparator()); } else if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_LASTMODIFIEDTIMESTAMP) && bSortOrderAsscending) { Arrays.sort(children, new FileLastmodifiedtimestampAscComparator()); } else if (strSortParam.equals(VFSConstants.FILE_SORT_VALUE_LASTMODIFIEDTIMESTAMP) && !bSortOrderAsscending) { Arrays.sort(children, new FileLastmodifiedtimestampDesComparator()); } log.debug("End Sorting the files."); } for (FileObject child : children) { // skipping *.lock / *.fail file if (child.getName().getBaseName().endsWith(".lock") || child.getName().getBaseName().endsWith(".fail")) { continue; } boolean isFailedRecord = VFSUtils.isFailRecord(fsManager, child); // child's file name matches the file name pattern or process all // files now we try to get the lock and process if ((strFilePattern == null || child.getName().getBaseName().matches(strFilePattern)) && !isFailedRecord) { if (log.isDebugEnabled()) { log.debug("Matching file : " + child.getName().getBaseName()); } if ((!fileLock || (fileLock && acquireLock(fsManager, child)))) { // process the file boolean runPostProcess = true; try { if (log.isDebugEnabled()) { log.debug("Processing file :" + VFSUtils.maskURLPassword(child.toString())); } processCount++; if (processFile(child) == null) { runPostProcess = false; } else { successCount++; } // tell moveOrDeleteAfterProcessing() file was success lastCycle = 1; } catch (Exception e) { if (e.getCause() instanceof FileNotFoundException) { log.warn("Error processing File URI : " + VFSUtils.maskURLPassword(child.getName().toString()) + ". This can be due to file moved from another process."); runPostProcess = false; } else { log.error("Error processing File URI : " + VFSUtils.maskURLPassword(child.getName().toString()), e); failCount++; // tell moveOrDeleteAfterProcessing() file failed lastCycle = 2; } } // skipping un-locking file if failed to do delete/move // after process boolean skipUnlock = false; if (runPostProcess) { try { moveOrDeleteAfterProcessing(child); } catch (SynapseException synapseException) { log.error("File object '" + VFSUtils.maskURLPassword(child.getURL().toString()) + "'cloud not be moved, will remain in \"locked\" state", synapseException); skipUnlock = true; failCount++; lastCycle = 3; VFSUtils.markFailRecord(fsManager, child); } } // if there is a failure or not we'll try to release the // lock if (fileLock && !skipUnlock) { // TODO: passing null to avoid build break. Fix properly VFSUtils.releaseLock(fsManager, child, fso); } if (injectHandler == null) { return child; } } } else if (log.isDebugEnabled() && strFilePattern != null && !child.getName().getBaseName().matches(strFilePattern) && !isFailedRecord) { // child's file name does not match the file name pattern log.debug("Non-Matching file : " + child.getName().getBaseName()); } else if (isFailedRecord) { // it is a failed record try { lastCycle = 1; moveOrDeleteAfterProcessing(child); } catch (SynapseException synapseException) { log.error("File object '" + VFSUtils.maskURLPassword(child.getURL().toString()) + "'cloud not be moved, will remain in \"fail\" state", synapseException); } if (fileLock) { // TODO: passing null to avoid build break. Fix properly VFSUtils.releaseLock(fsManager, child, fso); VFSUtils.releaseLock(fsManager, fileObject, fso); } if (log.isDebugEnabled()) { log.debug("File '" + VFSUtils.maskURLPassword(fileObject.getURL().toString()) + "' has been marked as a failed record, it will not " + "process"); } } //close the file system after processing try{ child.close(); }catch(Exception e){} // Manage throttling of file processing if (iFileProcessingInterval != null && iFileProcessingInterval > 0) { try { if (log.isDebugEnabled()) { log.debug("Put the VFS processor to sleep for : " + iFileProcessingInterval); } Thread.sleep(iFileProcessingInterval); } catch (InterruptedException ie) { log.error("Unable to set the interval between file processors." + ie); } } else if (iFileProcessingCount != null && iFileProcessingCount <= processCount) { break; } } if (failCount == 0 && successCount > 0) { lastCycle = 1; } else if (successCount == 0 && failCount > 0) { lastCycle = 4; } else { lastCycle = 5; } return null; } /** * Check if the file/folder exists before proceeding and retrying */ private boolean initFileCheck() { boolean wasError = true; int retryCount = 0; fileObject = null; while (wasError) { try { retryCount++; fileObject = fsManager.resolveFile(fileURI, fso); if (fileObject == null) { log.error("fileObject is null"); throw new FileSystemException("fileObject is null"); } wasError = false; } catch (FileSystemException e) { if (retryCount >= maxRetryCount) { log.error( "Repeatedly failed to resolve the file URI: " + VFSUtils.maskURLPassword(fileURI), e); return false; } else { log.warn("Failed to resolve the file URI: " + VFSUtils.maskURLPassword(fileURI) + ", in attempt " + retryCount + ", " + e.getMessage() + " Retrying in " + reconnectionTimeout + " milliseconds."); } } if (wasError) { try { Thread.sleep(reconnectionTimeout); } catch (InterruptedException e2) { log.error("Thread was interrupted while waiting to reconnect.", e2); } } } return true; } /** * * Acquire distributed lock if required first, then do the file level locking * * @param fsManager * @param fileObject * @return */ private boolean acquireLock(FileSystemManager fsManager, FileObject fileObject) { String strContext = fileObject.getName().getURI(); boolean rtnValue = false; try { if (distributedLock) { if (distributedLockTimeout != null) { if (!ClusteringServiceUtil.setLock(strContext, distributedLockTimeout)) { return false; } } else if (!ClusteringServiceUtil.setLock(strContext)) { return false; } } // When processing a directory list is fetched initially. Therefore // there is still a chance of file processed by another process. // Need to check the source file before processing. try { String parentURI = fileObject.getParent().getName().getURI(); if(parentURI.contains("?")) { String suffix = parentURI.substring(parentURI.indexOf("?")); strContext += suffix; } FileObject sourceFile = fsManager.resolveFile(strContext); if (!sourceFile.exists()) { return false; } } catch (FileSystemException e) { return false; } VFSParamDTO vfsParamDTO = new VFSParamDTO(); vfsParamDTO.setAutoLockRelease(autoLockRelease); vfsParamDTO.setAutoLockReleaseSameNode(autoLockReleaseSameNode); vfsParamDTO.setAutoLockReleaseInterval(autoLockReleaseInterval); rtnValue = VFSUtils.acquireLock(fsManager, fileObject, vfsParamDTO, fso, true); } finally { if (distributedLock) { ClusteringServiceUtil.releaseLock(strContext); } } return rtnValue; } /** * Actual processing of the file/folder * * @param file * @return * @throws synapseException */ private FileObject processFile(FileObject file) throws SynapseException { try { FileContent content = file.getContent(); String fileName = file.getName().getBaseName(); String filePath = file.getName().getPath(); String fileURI = file.getName().getURI(); if (injectHandler != null) { Map<String, Object> transportHeaders = new HashMap<String, Object>(); transportHeaders.put(VFSConstants.FILE_PATH, filePath); transportHeaders.put(VFSConstants.FILE_NAME, fileName); transportHeaders.put(VFSConstants.FILE_URI, fileURI); try { transportHeaders.put(VFSConstants.FILE_LENGTH, content.getSize()); transportHeaders.put(VFSConstants.LAST_MODIFIED, content.getLastModifiedTime()); } catch (FileSystemException e) { log.warn("Unable to set file length or last modified date header.", e); } injectHandler.setTransportHeaders(transportHeaders); // injectHandler if (!injectHandler.invoke(file, name)) { return null; } } } catch (FileSystemException e) { log.error("Error reading file content or attributes : " + VFSUtils.maskURLPassword(file.toString()), e); } return file; } /** * Do the post processing actions * * @param fileObject * @throws synapseException */ private void moveOrDeleteAfterProcessing(FileObject fileObject) throws SynapseException { String moveToDirectoryURI = null; try { switch (lastCycle) { case 1: if ("MOVE".equals(vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_ACTION_AFTER_PROCESS))) { moveToDirectoryURI = vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_MOVE_AFTER_PROCESS); //Postfix the date given timestamp format String strSubfoldertimestamp = vfsProperties .getProperty(VFSConstants.SUBFOLDER_TIMESTAMP); if (strSubfoldertimestamp != null) { try { SimpleDateFormat sdf = new SimpleDateFormat(strSubfoldertimestamp); String strDateformat = sdf.format(new Date()); int iIndex = moveToDirectoryURI.indexOf("?"); if (iIndex > -1) { moveToDirectoryURI = moveToDirectoryURI.substring(0, iIndex) + strDateformat + moveToDirectoryURI.substring(iIndex, moveToDirectoryURI.length()); }else{ moveToDirectoryURI += strDateformat; } } catch (Exception e) { log.warn("Error generating subfolder name with date", e); } } } break; case 2: if ("MOVE".equals(vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_ACTION_AFTER_FAILURE))) { moveToDirectoryURI = vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_MOVE_AFTER_FAILURE); } break; default: return; } if (moveToDirectoryURI != null) { FileObject moveToDirectory = fsManager.resolveFile(moveToDirectoryURI, fso); String prefix; if (vfsProperties.getProperty(VFSConstants.TRANSPORT_FILE_MOVE_TIMESTAMP_FORMAT) != null) { prefix = new SimpleDateFormat( vfsProperties .getProperty(VFSConstants.TRANSPORT_FILE_MOVE_TIMESTAMP_FORMAT)) .format(new Date()); } else { prefix = ""; } //Forcefully create the folder(s) if does not exists String strForceCreateFolder = vfsProperties.getProperty(VFSConstants.FORCE_CREATE_FOLDER); if(strForceCreateFolder != null && strForceCreateFolder.toLowerCase().equals("true") && !moveToDirectory.exists()){ moveToDirectory.createFolder(); } FileObject dest = moveToDirectory.resolveFile(prefix + fileObject.getName().getBaseName()); if (log.isDebugEnabled()) { log.debug("Moving to file :" + VFSUtils.maskURLPassword(dest.getName().getURI())); } try { fileObject.moveTo(dest); if (VFSUtils.isFailRecord(fsManager, fileObject)) { VFSUtils.releaseFail(fsManager, fileObject); } } catch (FileSystemException e) { if (!VFSUtils.isFailRecord(fsManager, fileObject)) { VFSUtils.markFailRecord(fsManager, fileObject); } log.error("Error moving file : " + VFSUtils.maskURLPassword(fileObject.toString()) + " to " + VFSUtils.maskURLPassword(moveToDirectoryURI), e); } } else { try { if (log.isDebugEnabled()) { log.debug("Deleting file :" + VFSUtils.maskURLPassword(fileObject.toString())); } fileObject.close(); if (!fileObject.delete()) { String msg = "Cannot delete file : " + VFSUtils.maskURLPassword(fileObject.toString()); log.error(msg); throw new SynapseException(msg); } } catch (FileSystemException e) { log.error("Error deleting file : " + VFSUtils.maskURLPassword(fileObject.toString()), e); } } } catch (FileSystemException e) { if (!VFSUtils.isFailRecord(fsManager, fileObject)) { VFSUtils.markFailRecord(fsManager, fileObject); log.error("Error resolving directory to move after processing : " + VFSUtils.maskURLPassword(moveToDirectoryURI), e); } } } /** * Comparator classed used to sort the files according to user input * */ class FileNameAscComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { return o1.getName().compareTo(o2.getName()); } } class FileLastmodifiedtimestampAscComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { Long lDiff = 0l; try { lDiff = o1.getContent().getLastModifiedTime() - o2.getContent().getLastModifiedTime(); } catch (FileSystemException e) { log.warn("Unable to compare lastmodified timestamp of the two files.", e); } return lDiff.intValue(); } } class FileSizeAscComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { Long lDiff = 0l; try { lDiff = o1.getContent().getSize() - o2.getContent().getSize(); } catch (FileSystemException e) { log.warn("Unable to compare size of the two files.", e); } return lDiff.intValue(); } } class FileNameDesComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { return o2.getName().compareTo(o1.getName()); } } class FileLastmodifiedtimestampDesComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { Long lDiff = 0l; try { lDiff = o2.getContent().getLastModifiedTime() - o1.getContent().getLastModifiedTime(); } catch (FileSystemException e) { log.warn("Unable to compare lastmodified timestamp of the two files.", e); } return lDiff.intValue(); } } class FileSizeDesComparator implements Comparator<FileObject> { @Override public int compare(FileObject o1, FileObject o2) { Long lDiff = 0l; try { lDiff = o2.getContent().getSize() - o1.getContent().getSize(); } catch (FileSystemException e) { log.warn("Unable to compare size of the two files.", e); } return lDiff.intValue(); } } protected Properties getInboundProperties() { return vfsProperties; } }