/*
* 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.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.log4j.Logger;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
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.message.format.MessageType;
/**
* Send message via TCP. Each connection is maintained only for the duration of
* the notification.
*/
public class NotifyTcp extends NotificationTarget
{
private Logger log = Logger.getLogger(NotifyTcp.class);
public static final String DESTINATIONS_TAG = "destination";
/**
* The URI for the destination (socket://host:port)
*/
public static final String ATT_URI = "URI";
public static final String PROTOCOL_TAG = "tcp";
public static final int DEFAULT_PORT = 9090; // default port if none is specified.
/**
* Instantiate a NotifyTcp object according to contents of <arg 1>
*
* @param configTree
* ConfigTree - Should contain a nonempty set of child elements
* with elementName="file". Each child element must have a "URI"
* attribute and optionally a "append" element
*/
public NotifyTcp(ConfigTree configTree)
{
super(configTree);
setDestinations(configTree.getChildren(DESTINATIONS_TAG));
payloadProxy = new MessagePayloadProxy(configTree, new String[]
{ BytesBody.BYTES_LOCATION }, new String[]
{ BytesBody.BYTES_LOCATION });
}
/**
* Sends the result of the message to each of the destinations.
*/
public void sendNotification (Message message) throws NotificationException
{
final StringBuilder exceptions = new StringBuilder();
for (URI destination : _destinations)
{
Socket sender = null;
try
{
int port = destination.getPort();
if (port == -1)
{
port = DEFAULT_PORT;
_logger.debug("No port specified for " + destination
+ " so will use default " + DEFAULT_PORT);
}
sender = new Socket(destination.getHost(), port);
Object obj = payloadProxy.getPayload(message);
if (obj != null)
{
if (MessageType.JAVA_SERIALIZED.equals(message.getType()))
{
// handle objects
objectNotification(new ObjectOutputStream(sender.getOutputStream()), obj);
}
else
{
if (obj instanceof byte[])
{
// handle raw bytes (JBESB-3234)
bytesNotification(sender.getOutputStream(), (byte[])obj);
}
else
{
// handle Strings and everything else
stringNotification(sender.getOutputStream(), obj.toString());
}
}
}
}
catch (IOException e)
{
handleException(destination, e, exceptions);
}
catch (MessageDeliverException e)
{
handleException(destination, e, exceptions);
}
finally
{
try
{
if (sender != null)
sender.close();
}
catch (IOException eCl)
{
log.error("IOException while closing socket: ", eCl);
}
}
}
if (exceptions.length() > 0)
throw new NotificationException(exceptions.toString());
}
private void handleException (URI destination, Exception e,
StringBuilder exceptions)
{
final String msg = "[Exception while notifying destination : "
+ destination;
log.error(msg, e);
exceptions.append(NotifyUtil.createExceptionErrorString(msg, e));
}
protected void objectNotification (ObjectOutputStream sender, Object p_o)
throws IOException
{
sender.writeObject(p_o);
sender.flush();
sender.close();
}
protected void bytesNotification (OutputStream sender, byte[] p_b)
throws IOException
{
sender.write(p_b);
sender.flush();
sender.close();
}
protected void stringNotification (OutputStream sender, String p_s)
throws IOException
{
bytesNotification(sender, p_s.getBytes());
}
private void setDestinations (ConfigTree[] dests)
{
if (dests != null)
{
_destinations = new URI[dests.length];
for (int i = 0; i < dests.length; i++)
{
try
{
_destinations[i] = new URI(dests[i].getAttribute(ATT_URI));
if (!_destinations[i].getScheme().equals(PROTOCOL_TAG))
{
throw new IllegalArgumentException(
"Destination is not a tcp socket! "
+ _destinations[i]);
}
}
catch (URISyntaxException ex)
{
_logger.warn("Could not create notify destination: ", ex);
throw new IllegalArgumentException(
"Could not create notify destination", ex);
}
catch (Exception ex)
{
_logger.warn("Problem creating notify destination: ", ex);
throw new IllegalArgumentException(
"Problem creating notify destination", ex);
}
}
}
}
private URI[] _destinations = null;
private MessagePayloadProxy payloadProxy;
private Logger _logger = Logger.getLogger(NotifyTcp.class);
}