// Copyright (c) 2004-2005 Sun Microsystems Inc., All Rights Reserved.
/*
* MessageProcessor.java
*
* SUN PROPRIETARY/CONFIDENTIAL.
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package com.sun.jbi.binding.file;
import com.sun.jbi.binding.file.framework.Command;
import com.sun.jbi.binding.file.util.ConfigData;
import com.sun.jbi.binding.file.util.FileBindingUtil;
import com.sun.jbi.binding.file.util.StringTranslator;
import org.w3c.dom.Element;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.net.URI;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.logging.Logger;
import javax.jbi.messaging.DeliveryChannel;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.Fault;
import javax.jbi.messaging.InOnly;
import javax.jbi.messaging.InOut;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.MessagingException;
import javax.jbi.messaging.NormalizedMessage;
import javax.jbi.messaging.RobustInOnly;
import javax.xml.namespace.QName;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
/**
* Message Processor which parses the message received from NMR.
*
* @author Sun Microsystems, Inc.
*/
public class MessageProcessor
implements Command, FileBindingResources
{
/**
* In Only MEP.
*/
public static final String IN_ONLY =
"http://www.w3.org/2004/08/wsdl/in-only";
/**
* In Out MEP.
*/
public static final String IN_OUT = "http://www.w3.org/2004/08/wsdl/in-out";
/**
* In Optional Out MEP.
*/
public static final String IN_OPTIONAL_OUT =
"http://www.w3.org/2004/08/wsdl/in-opt-out";
/**
* Robust In Only MEP.
*/
public static final String ROBUST_IN_ONLY =
"http://www.w3.org/2004/08/wsdl/robust-in-only";
/**
* Out Only MEP.
*/
public static final String OUT_ONLY =
"http://www.w3.org/2004/08/wsdl/out-only";
/**
* Out In MEP.
*/
public static final String OUT_IN = "http://www.w3.org/2004/08/wsdl/out-in";
/**
* Out Optional In MEP.
*/
public static final String OUT_OPTIONAL_IN =
"http://www.w3.org/2004/08/wsdl/out-opt-in";
/**
* Robust Out Only MEP.
*/
public static final String ROBUST_OUT_ONLY =
"http://www.w3.org/2004/08/wsdl/robust-out-only";
/**
* Out-only MEP.
*/
private static final String OUTONLY = "provider";
/**
* String representing property name in exchange
*/
private static final String FILENAME_PROPERTY = "FILENAME";
/**
* String representing property name in exchange
*/
private static final String FILEEXTENSION_PROPERTY = "FILEEXTENSION";
/**
* String representing default prefix
*/
private static final String DEFAULT_PREFIX = "out";
/**
* String representing default extension
*/
private static final String DEFAULT_EXTENSION = "xml";
/**
* Channel for this binding.
*/
private DeliveryChannel mChannel;
/**
* Registry for storing active deployments.
*/
private DeploymentRegistry mRegistry;
/**
* Endpoint Bean for the exhange being processed
*/
private EndpointBean mEndpointBean;
/**
* Excpetion.
*/
private Exception mException;
/**
* Logger object.
*/
private Logger mLog;
/**
* Message exchange object.
*/
private MessageExchange mExchange;
/**
* Name of file to be written out
*/
private String mFileName;
/**
*
*/
/**
*
*/
private String mOperation;
/**
* Helper for i18n.
*/
private StringTranslator mTranslator;
/**
* Creates a new MessageProcessor object.
*
* @param chnl binding channel.
* @param exchange message exchange.
*/
public MessageProcessor(
DeliveryChannel chnl,
MessageExchange exchange)
{
mChannel = chnl;
mRegistry = DeploymentRegistry.getInstance();
mExchange = exchange;
mLog = FileBindingContext.getInstance().getLogger();
mTranslator = new StringTranslator();
}
/**
* Util method to return current date.
*
* @return date
*/
public String getDate()
{
Calendar cal = new GregorianCalendar();
Date dt = cal.getTime();
DateFormat format = new SimpleDateFormat("ddHHmmssSS");
String sdate = format.format(dt);
return sdate;
}
/**
* Command pattern for executing in a thread pool.
*/
public void execute()
{
URI pattern = mExchange.getPattern();
String pat = pattern.toString().trim();
mOperation = mExchange.getOperation().toString();
setBean();
if (mEndpointBean == null)
{
mLog.severe(mTranslator.getString(
FBC_START_DEPLOYMENT_FAILED_BEANNULL,
mExchange.getExchangeId()));
return;
}
int role = mEndpointBean.getRole();
if (pat.trim().equals(IN_OUT.trim()))
{
mLog.info(mTranslator.getString(FBC_RECEIVED_INOUT,
mExchange.getExchangeId()));
if (role == ConfigData.CONSUMER)
{
processInOut((InOut) mExchange);
}
else if (role == ConfigData.PROVIDER)
{
mLog.info(mTranslator.getString(FBC_RECEIVED_OUTIN,
mExchange.getExchangeId()));
}
}
else if (pat.trim().equals(IN_ONLY.trim()))
{
mLog.info(mTranslator.getString(FBC_RECEIVED_INONLY,
mExchange.getExchangeId()));
if (role == ConfigData.CONSUMER)
{
processInOnly((InOnly) mExchange);
}
else if (role == ConfigData.PROVIDER)
{
processOutOnly((InOnly) mExchange);
}
}
else if (pat.trim().equals(ROBUST_IN_ONLY.trim()))
{
mLog.info(mTranslator.getString(FBC_RECEIVED_ROBUSTINONLY,
mExchange.getExchangeId()));
if (role == ConfigData.CONSUMER)
{
processRobustInOnly((RobustInOnly) mExchange);
}
else if (role == ConfigData.PROVIDER)
{
processRobustOutOnly((RobustInOnly) mExchange);
}
}
else if (pat.trim().equals(IN_OPTIONAL_OUT.trim()))
{
mLog.info(mTranslator.getString(FBC_RECEIVED_INOPTIONALOUT,
mExchange.getExchangeId()));
}
else
{
mLog.info(mTranslator.getString(FBC_RECEIVED_UNSUPPORTED_MEP,
mExchange.getExchangeId()));
}
}
/**
* Processes inonly message.
*
* @param inonly inony message.
*/
public void processInOnly(InOnly inonly)
{
try
{
move();
if (canTerminate())
{
return;
}
else
{
mLog.severe(mTranslator.getString(FBC_INVALID_MESSAGE_STATE));
}
}
catch (Exception me)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_INONLY_FAILED));
mLog.severe(me.getMessage());
}
}
/**
* Processes in-out message.
*
* @param inout inout message.
*/
public void processInOut(InOut inout)
{
/* This must be a response, cannot be a request , so set status
* and send
*/
try
{
move();
if (canTerminate())
{
return;
}
NormalizedMessage outmsg = inout.getOutMessage();
Fault fault = inout.getFault();
updateFileName();
if (outmsg != null)
{
if (writeOutMessage(outmsg))
{
inout.setStatus(ExchangeStatus.DONE);
}
else
{
inout.setStatus(ExchangeStatus.ERROR);
}
}
else if (fault != null)
{
if (writeFaultMessage(fault))
{
inout.setStatus(ExchangeStatus.DONE);
}
else
{
inout.setStatus(ExchangeStatus.ERROR);
}
}
else
{
mLog.severe(mTranslator.getString(FBC_INVALID_MESSAGE_STATE));
return;
}
mChannel.send(inout);
}
catch (MessagingException me)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_INOUT_FAILED));
mLog.severe(me.getMessage());
me.printStackTrace();
}
}
/**
* Processes out only message.
*
* @param outonly outonly message.
*/
public void processOutOnly(InOnly outonly)
{
try
{
if (canTerminate())
{
return;
}
QName operation = outonly.getOperation();
String mep = mEndpointBean.getMEP(operation.toString());
if ((mep == null) || (!mep.trim().equals(IN_ONLY)))
{
mLog.severe(mTranslator.getString(FBC_INCONSISTENT_OPERATION)
+ "MEP " + mep + " Operation : " + operation.toString());
outonly.setError(new Exception(mTranslator.getString(
FBC_INCONSISTENT_OPERATION)));
outonly.setStatus(ExchangeStatus.ERROR);
}
else
{
NormalizedMessage outmsg = outonly.getInMessage();
updateFileName();
if (writeOutMessage(outmsg))
{
outonly.setStatus(ExchangeStatus.DONE);
}
else
{
outonly.setStatus(ExchangeStatus.ERROR);
}
}
mChannel.send(outonly);
}
catch (MessagingException me)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_OUTONLY_FAILED));
mLog.severe(me.getMessage());
}
catch (RuntimeException re)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_OUTONLY_FAILED));
mLog.severe(re.getMessage());
}
}
/**
* Processes robust inonly messages.
*
* @param robustinonly robustinonly exchange.
*/
public void processRobustInOnly(RobustInOnly robustinonly)
{
/* This must be a response, cannot be a request , so set status
* and send
*/
try
{
move();
if (canTerminate())
{
return;
}
updateFileName();
Fault fault = robustinonly.getFault();
if (fault != null)
{
if (writeFaultMessage(fault))
{
robustinonly.setStatus(ExchangeStatus.DONE);
}
else
{
robustinonly.setStatus(ExchangeStatus.ERROR);
}
mChannel.send(robustinonly);
}
}
catch (MessagingException me)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_ROBUSTINONLY_FAILED));
mLog.severe(me.getMessage());
}
}
/**
* Writes a error message into file.
*
* @param ex exception message.
*
* @return true if successfull, false otherwise.
*/
public boolean writeErrorMessage(Exception ex)
{
StringBuffer sb = new StringBuffer();
StackTraceElement [] stckTrElem = null;
FileOutputStream out = null;
try
{
out = new FileOutputStream(mFileName);
if (ex == null)
{
sb.append("Unknown error occurred");
}
else
{
sb.append(ex.getMessage());
stckTrElem = ex.getStackTrace();
if (stckTrElem != null)
{
for (int i = 0; i < stckTrElem.length; i++)
{
String stckTrace = stckTrElem[i].toString();
sb.append(stckTrace);
sb.append("\n");
}
}
}
out.write(sb.toString().getBytes());
out.close();
return true;
}
catch (Exception e)
{
mLog.info(mTranslator.getString(FBC_FILE_WRITE_FAILED, mFileName));
e.printStackTrace();
mException = e;
return false;
}
finally
{
try
{
if (out != null)
{
out.close();
}
}
catch (Exception e1)
{
mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED,
e1.getMessage()));
}
}
}
/**
* Writes a fault message into file.
*
* @param msg fault message.
*
* @return true if successfull, false otherwise.
*/
public boolean writeFaultMessage(Fault msg)
{
if (msg == null)
{
return false;
}
javax.xml.transform.Source doc = msg.getContent();
if (doc == null)
{
mLog.severe(mTranslator.getString(FBC_CONTENT_NULL));
return false;
}
return writeMessage(doc);
}
/**
* Writes a sucess response message into file.
*
* @param doc normalized message.
*
* @return true if successfull, false otherwise.
*/
public boolean writeMessage(javax.xml.transform.Source doc)
{
Element ele = null;
FileOutputStream out = null;
PrintWriter pw = null;
File f = new File(mFileName);
try
{
out = new FileOutputStream(f);
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer trans = tFactory.newTransformer();
trans.setOutputProperty(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION,
"yes");
StreamResult result = new StreamResult(out);
trans.transform(doc, result);
out.close();
return true;
}
catch (Exception e)
{
mLog.severe(mTranslator.getString(FBC_FILE_WRITE_FAILED, mFileName));
mLog.severe(e.getMessage());
mException = e;
mFileName =
getBaseName(mFileName) + "." + ConfigData.ERROR_EXTENSION;
writeErrorMessage(e);
try
{
if (out != null)
{
out.close();
}
f.delete();
}
catch (Exception e1)
{
mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED,
e1.getMessage()));
}
return false;
}
finally
{
try
{
if (out != null)
{
out.close();
}
}
catch (Exception e1)
{
mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED,
e1.getMessage()));
}
}
}
/**
* Writes an output message into file.
*
* @param msg normalized message.
*
* @return true if successfull, false otherwise.
*/
public boolean writeOutMessage(NormalizedMessage msg)
{
if (msg == null)
{
return false;
}
javax.xml.transform.Source doc = msg.getContent();
if (doc == null)
{
mLog.severe(mTranslator.getString(FBC_CONTENT_NULL));
return false;
}
return writeMessage(doc);
}
/**
* Util method to get base name of file.
*
* @param fname file name
*
* @return base name
*/
private String getBaseName(String fname)
{
int k = fname.lastIndexOf('.');
if (k == -1)
{
return fname;
}
if (k == 0)
{
return "";
}
return fname.substring(0, k);
}
/**
* Finds a bean object from the message exchange parameters.
*/
private void setBean()
{
String sname = mExchange.getEndpoint().getServiceName().toString();
String epname = mExchange.getEndpoint().getEndpointName();
QName intername = mExchange.getInterfaceName();
if ((sname == null) || (epname == null))
{
mLog.severe(mTranslator.getString(
FBC_START_DEPLOYMENT_FAILED_BEANNULL,
mExchange.getExchangeId()));
return;
}
// try for a provider endpoint first
if (mExchange.getRole().equals(MessageExchange.Role.PROVIDER))
{
mEndpointBean = mRegistry.findEndpoint(sname + epname);
}
else
{
mEndpointBean = mRegistry.findEndpoint(sname);
/**
* There is a possiblity that the message was routed initially
* with the interface name and not the service name
* So we have to try an endpoint with interface name now
*/
if (mEndpointBean == null)
{
if (intername != null)
{
mEndpointBean =
mRegistry.findEndpointByInterface(intername.
toString().trim());
}
}
}
if (mEndpointBean == null)
{
mLog.severe(mTranslator.getString(
FBC_START_DEPLOYMENT_FAILED_BEANNULL,
sname + " " + epname + " "
+ mExchange.getExchangeId()));
}
}
/**
* Util method to check for termination of exhcange.
*
* @return true of exchange can be terminated false othrewise.
*/
private boolean canTerminate()
{
Exception exc;
String sname = mExchange.getEndpoint().getServiceName().toString();
String epname = mExchange.getEndpoint().getEndpointName();
if (mEndpointBean == null)
{
mLog.severe(mTranslator.getString(
FBC_START_DEPLOYMENT_FAILED_BEANNULL,
mExchange.getExchangeId()));
return true;
}
if (mExchange.getStatus() == ExchangeStatus.DONE)
{
mLog.info(mTranslator.getString(FBC_EXCHANGE_DONE,
mExchange.getExchangeId()));
if (!mExchange.getPattern().toString().trim().equals(OUT_IN))
{
updateFileName();
writeSuccessMessage();
}
return true;
}
if (mExchange.getStatus() == ExchangeStatus.ERROR)
{
mLog.info(mTranslator.getString(FBC_EXCHANGE_ERROR,
mExchange.getExchangeId()));
exc = mExchange.getError();
updateFileName();
if (writeErrorMessage(exc))
{
mLog.info(mTranslator.getString(FBC_WRITE_ERROR_SUCCESS));
}
else
{
mLog.info(mTranslator.getString(FBC_WRITE_ERROR_FAILED));
}
return true;
}
return false;
}
/**
*
*/
private void move()
{
String trk = null;
String fn = null;
String ext = null;
QName operation = null;
try
{
trk = (String) mExchange.getProperty(ConfigData.TRACKINGID_PROPERTY);
ext = (String) mExchange.getProperty(ConfigData.EXTENSION_PROPERTY);
fn = (String) mExchange.getProperty(ConfigData.FILENAME_PROPERTY);
operation = mExchange.getOperation();
}
catch (Exception e)
{
mLog.severe(mTranslator.getString(FBC_MOVE_FAILED, e.getMessage()));
}
if (trk == null)
{
mLog.severe(mTranslator.getString(FBC_MOVE_FAILED,
mExchange.getExchangeId()));
}
else
{
String filepath = FileBindingUtil.getFilePath(trk);
String destfolder =
(String) mEndpointBean.getValue(ConfigData.PROCESSEDDIR);
String inputdir =
(String) mEndpointBean.getValue(ConfigData.INPUTDIR);
String filename = fn + "." + ext;
String movefilename = null;
if (operation.toString().equals(mEndpointBean.getDefaultOperation()
.toString()))
{
// cud be in inputdir or in folder under the operation
File f = new File(inputdir + File.separator + filename);
if (f.exists())
{
movefilename = inputdir + File.separator + filename;
}
else
{
movefilename =
inputdir + File.separator + operation.getLocalPart()
+ File.separator + filename;
}
}
else
{
movefilename =
inputdir + File.separator + operation.getLocalPart()
+ File.separator + filename;
}
if (!FileBindingUtil.moveFile(trk, destfolder, movefilename))
{
mLog.severe(mTranslator.getString(FBC_MOVE_FAILED, filename,
destfolder));
}
FileBindingUtil.removeEntry(trk);
}
}
/**
* Processes robust out only messages.
*
* @param robustoutonly robust out only message.
*/
private void processRobustOutOnly(RobustInOnly robustoutonly)
{
/* This must be a request , cannot be a request , so set status
* and send
*/
try
{
if (canTerminate())
{
return;
}
QName operation = robustoutonly.getOperation();
String mep = mEndpointBean.getMEP(operation.toString());
if ((mep == null) || (!mep.trim().equals(ROBUST_IN_ONLY)))
{
mLog.severe(mTranslator.getString(FBC_INCONSISTENT_OPERATION)
+ "MEP " + mep + " Operation : " + operation.toString());
robustoutonly.setError(new Exception(mTranslator.getString(
FBC_INCONSISTENT_OPERATION)));
robustoutonly.setStatus(ExchangeStatus.ERROR);
}
else
{
NormalizedMessage outmsg = robustoutonly.getInMessage();
updateFileName();
if (writeOutMessage(outmsg))
{
robustoutonly.setStatus(ExchangeStatus.DONE);
}
else
{
/* Have to set some error here
*/
robustoutonly.setError(mException);
}
}
mChannel.send(robustoutonly);
}
catch (MessagingException me)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_ROBUSTOUTONLY_FAILED));
me.printStackTrace();
mLog.severe(me.getMessage());
}
catch (RuntimeException re)
{
mLog.severe(mTranslator.getString(FBC_PROCESS_ROBUSTOUTONLY_FAILED));
re.printStackTrace();
mLog.severe(re.getMessage());
}
catch (Throwable th)
{
th.printStackTrace();
}
}
/**
* Updates the file name according to the state.
*/
private void updateFileName()
{
String prefix = null;
String folder = null;
String filename = null;
String extension = null;
String fileextension = null;
String trkid = null;
String prefixsep = null;
String newext = null;
try
{
prefix = mEndpointBean.getPrefix(mOperation);
folder = mEndpointBean.getValue(ConfigData.OUTPUTDIR);
extension = mEndpointBean.getExtension(mOperation);
if (null == prefix)
{
prefixsep = DEFAULT_PREFIX + ConfigData.SEPARATOR;
}
else if (prefix.trim().equals(""))
{
prefixsep = "";
}
else
{
prefixsep = prefix + ConfigData.SEPARATOR;
}
if (mEndpointBean.getRole() == ConfigData.CONSUMER)
{
filename = (String) mExchange.getProperty(FILENAME_PROPERTY);
fileextension =
(String) mExchange.getProperty(FILEEXTENSION_PROPERTY);
trkid =
(String) mExchange.getProperty(ConfigData.TRACKINGID_PROPERTY);
}
if (mEndpointBean.getRole() == ConfigData.PROVIDER)
{
filename = OUTONLY;
trkid = FileBindingUtil.getTrackingId();
}
if (null == extension)
{
if (fileextension != null)
{
newext = "." + fileextension;
}
else
{
newext = "." + DEFAULT_EXTENSION;
}
}
else if (extension.trim().equals(""))
{
newext = "";
}
else
{
newext = "." + extension;
}
if (mExchange.getStatus() == ExchangeStatus.ERROR)
{
mFileName =
folder + File.separatorChar + prefixsep + filename
+ ConfigData.SEPARATOR + trkid + "."
+ ConfigData.ERROR_EXTENSION;
}
else
{
mFileName =
folder + File.separatorChar + prefixsep + filename
+ ConfigData.SEPARATOR + trkid + newext;
}
}
catch (Exception e)
{
e.printStackTrace();
mFileName =
folder + File.separatorChar + trkid + "."
+ ConfigData.ERROR_EXTENSION;
}
}
/**
* Writes out a success message to file.
*/
private void writeSuccessMessage()
{
FileOutputStream out = null;
String fname;
fname = getBaseName(mFileName) + "." + ConfigData.DONE_EXTENSION;
try
{
out = new FileOutputStream(fname);
out.write(mTranslator.getString(FBC_DONE_MESSAGE).getBytes());
out.close();
}
catch (Exception e)
{
mLog.severe(mTranslator.getString(FBC_FILE_WRITE_FAILED, fname));
mLog.severe(e.getMessage());
mException = e;
}
finally
{
try
{
if (out != null)
{
out.close();
}
}
catch (Exception e1)
{
mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED,
e1.getMessage()));
}
}
}
}
|