/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.soa.esb.notification;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.notification.PropertySubstituter;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.addressing.eprs.FTPEpr;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.body.content.BytesBody;
import org.jboss.soa.esb.util.RemoteFileSystem;
import org.jboss.soa.esb.util.RemoteFileSystemException;
import org.jboss.soa.esb.util.RemoteFileSystemFactory;
import org.jboss.soa.esb.listeners.ListenerUtil;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
/**
* Sends a message to an outgoing FTP server. The outgoing filename can have
* values of message properties injected into it to make it unique. The
* notification-details property looks something like:
*
*<pre>
*<NotificationList type="OK" xmlns="http://anonsvn.labs.jboss.com/labs/jbossesb/trunk/product/etc/schemas/xml/jbossesb-1.0.1.xsd">
* <target class="NotifyFTP">
* <ftp URL="ftp://username:pwd@server.com/remote/dir" filename="{jbossesb.message.id}.txt"/>
* </target>
*</NotificationList>
*</pre>
*
* @author <a href="mailto:rex.sheridan@sapience360.com">Rex Sheridan</a>
*/
public class NotifyFTP extends NotificationTarget {
private Logger log = Logger.getLogger( NotifyFTP.class );
/** Configuration entries */
private ConfigTree config;
/** Used to get access to remote filesystem */
private FTPEpr epr;
/** Filename created on server */
private String fileName;
/** FTP child tag name */
public static final String CHILD_FTP = "ftp";
/** Filename attribute */
public static final String ATTR_FILENAME = "filename";
/** Base filename for temp file */
public static final String TEMP_FILE_BASE = "jbossesb-NotifyFTP";
private MessagePayloadProxy payloadProxy;
/**
* Create an outgoing FTP notification based on the given configuration.
*
* @param config
*/
public NotifyFTP(ConfigTree config) {
this.config = config;
payloadProxy = new MessagePayloadProxy(config,
new String[] {BytesBody.BYTES_LOCATION},
new String[] {BytesBody.BYTES_LOCATION});
}
/**
* Get the ConfigTree for the 'ftp' element.
*
* @return ConfigTree
*/
protected ConfigTree getFtpConfig() throws NotificationException {
ConfigTree[] ftps = config.getChildren(CHILD_FTP);
if (ftps.length != 1) {
throw new NotificationException("NotifyFTP requires exactly one 'ftp' element.");
}
return ftps[0];
}
/**
* Lazy loads filename from config tree.
*
* @return String
*/
protected String getFileName(Message message) throws NotificationException {
if (fileName == null) {
ConfigTree ftpConfig = getFtpConfig();
fileName = ftpConfig.getAttribute(ATTR_FILENAME);
if (StringUtils.isEmpty(fileName)) {
throw new NotificationException("NotifyFTP: Filename attribute is required.");
}
fileName = PropertySubstituter.replaceArguments(fileName, message);
}
return fileName;
}
/**
* Builds an FTP EPR from the configuration data.
*
* @return FTPEpr
*/
protected FTPEpr getFtpEpr() throws NotificationException {
if (epr == null) {
ConfigTree ftpConfig = getFtpConfig();
String url = ftpConfig.getAttribute(FTPEpr.URL_TAG);
try {
epr = (FTPEpr) ListenerUtil.fileEprFromElement(ftpConfig);
}
catch (final ConfigurationException ex)
{
throw new NotificationException(ex);
}
catch (final ClassCastException ex)
{
throw new NotificationException("Not an FTPEpr!", ex);
}
}
return epr;
}
/*
* (non-Javadoc)
*
* @see org.jboss.soa.esb.notification.NotificationTarget#sendNotification(org.jboss.soa.esb.message.Message)
*/
public void sendNotification(Message message) throws NotificationException {
File fileToSend = null;
RemoteFileSystem rfs = null;
try {
fileToSend = getFileToSend( message );
rfs = RemoteFileSystemFactory.getRemoteFileSystem(getFtpEpr(), true);
rfs.uploadFile(fileToSend, getFileName(message));
} catch (RemoteFileSystemException e) {
throw new NotificationException("Could not complete FTP notification", e);
} catch (IOException e) {
throw new NotificationException("Could not complete FTP notification", e);
} finally {
if (fileToSend != null) {
fileToSend.delete();
}
if (rfs != null) {
rfs.quit();
}
}
}
protected File getFileToSend( final Message message ) throws IOException
{
FileOutputStream stream = null;
File tmpFile = null;
try
{
tmpFile = File.createTempFile(TEMP_FILE_BASE, null);
stream = new FileOutputStream(tmpFile);
Object payload = payloadProxy.getPayload(message);
if (payload instanceof byte[])
IOUtils.write((byte[]) payload, stream);
else
IOUtils.write(payload.toString(), stream);
stream.close();
}
catch (MessageDeliverException e)
{
log.error( "MessageDeliveryException while calling getPayLoad : " + e );
}
finally
{
if (stream != null)
IOUtils.closeQuietly(stream);
}
return tmpFile;
}
}