001: // Copyright (c) 2004-2005 Sun Microsystems Inc., All Rights Reserved.
002:
003: /*
004: * FileCommand.java
005: * SUN PROPRIETARY/CONFIDENTIAL.
006: * This software is the proprietary information of Sun Microsystems, Inc.
007: * Use is subject to license terms.
008: *
009: */
010: package com.sun.jbi.binding.file;
011:
012: import com.sun.jbi.binding.file.FileBindingContext;
013: import com.sun.jbi.binding.file.framework.Command;
014: import com.sun.jbi.binding.file.util.ConfigData;
015: import com.sun.jbi.binding.file.util.FileBindingUtil;
016: import com.sun.jbi.binding.file.util.StringTranslator;
017:
018: import org.w3c.dom.Text;
019:
020: import org.xml.sax.SAXException;
021: import org.xml.sax.SAXParseException;
022:
023: import java.io.BufferedInputStream;
024: import java.io.File;
025: import java.io.FileInputStream;
026: import java.io.FileOutputStream;
027:
028: import java.util.logging.Logger;
029:
030: import javax.jbi.component.ComponentContext;
031: import javax.jbi.messaging.DeliveryChannel;
032: import javax.jbi.messaging.InOnly;
033: import javax.jbi.messaging.InOut;
034: import javax.jbi.messaging.MessageExchangeFactory;
035: import javax.jbi.messaging.NormalizedMessage;
036: import javax.jbi.messaging.RobustInOnly;
037: import javax.jbi.servicedesc.ServiceEndpoint;
038:
039: import javax.xml.namespace.QName;
040: import javax.xml.parsers.DocumentBuilder;
041: import javax.xml.parsers.DocumentBuilderFactory;
042: import javax.xml.parsers.ParserConfigurationException;
043: import javax.xml.transform.Source;
044: import javax.xml.transform.dom.DOMSource;
045:
046: /**
047: * The FileCommand class reads a file and sends assembles the Normalized
048: * MEssage and sends to to the NMS.
049: *
050: * @author Sun Microsystems, Inc.
051: */
052: public class FileCommand implements Command, FileBindingResources {
053: /**
054: * Buffered stream object for reading file.
055: */
056: private BufferedInputStream mBis;
057:
058: /**
059: * Component context.
060: */
061: private ComponentContext mContext;
062:
063: /**
064: * Delivery channel
065: */
066: private DeliveryChannel mChannel;
067:
068: /**
069: * Endpoint bean that stores the endpoint attributes.
070: */
071: private EndpointBean mBean;
072:
073: /**
074: * Exception
075: */
076: private Exception mException;
077:
078: /**
079: * Destination folder to put the processed file.
080: */
081: private File mDestFolder = null;
082:
083: /**
084: * The source file to be sent to NMS
085: */
086: private File mFile = null;
087:
088: /**
089: * Logger Object
090: */
091: private Logger mLog;
092:
093: /**
094: * Exchange factory
095: */
096: private MessageExchangeFactory mFactory;
097:
098: /**
099: * Current operation.
100: */
101: private QName mCurrentOperation;
102:
103: /**
104: * Endpoint reference.
105: */
106: private ServiceEndpoint mServiceEndpoint;
107:
108: /**
109: * Tracking id.
110: */
111: private String mTrkId;
112:
113: /**
114: * Helper for i18n.
115: */
116: private StringTranslator mTranslator;
117:
118: /**
119: * Creates a new FileCommand object.
120: *
121: * @param file file to be read
122: * @param eb folder to move the processed files.
123: * @param oper operation name.
124: * @param trkid trk id.
125: */
126: FileCommand(File file, EndpointBean eb, QName oper, String trkid) {
127: mLog = FileBindingContext.getInstance().getLogger();
128: mTranslator = new StringTranslator();
129: mFile = file;
130: mContext = FileBindingContext.getInstance().getContext();
131: mBean = eb;
132: mCurrentOperation = oper;
133: mTrkId = trkid;
134: }
135:
136: /**
137: * Returns the name of the folder.
138: *
139: * @return folder name.
140: */
141: public String getName() {
142: if (mFile != null) {
143: return mFile.getAbsolutePath();
144: } else {
145: return "";
146: }
147: }
148:
149: /**
150: * The run method which sends the normalized message to the respective
151: * service channel. This class is an implementation of the COmmand
152: * interface This method is called when this object is excetuted in a
153: * separate thread.
154: */
155: public void execute() {
156: InOut inout = null;
157: InOnly inonly = null;
158: RobustInOnly robustinonly = null;
159: NormalizedMessage inmsg = null;
160:
161: try {
162: mChannel = mContext.getDeliveryChannel();
163: mFactory = mChannel.createExchangeFactory();
164:
165: Source src = getSource();
166:
167: if (src == null) {
168: mLog.severe(mTranslator
169: .getString(FBC_INVALID_INPUT_FILE));
170: throw mException;
171: }
172:
173: if (mCurrentOperation == null) {
174: mLog.severe(mTranslator
175: .getString(FBC_INVALID_OPERATION_FILE));
176: throw new Exception(mTranslator
177: .getString(FBC_INVALID_OPERATION_FILE));
178: }
179:
180: String mep = mBean.getMEP(mCurrentOperation.toString());
181:
182: if (mep == null) {
183: mLog.severe(mTranslator
184: .getString(FBC_INVALID_OPERATION_FILE));
185: throw new Exception(mTranslator
186: .getString(FBC_INVALID_OPERATION_FILE));
187: }
188:
189: if (mep.trim().equalsIgnoreCase(
190: MessageProcessor.IN_OUT.trim())) {
191: inout = mFactory.createInOutExchange();
192: inmsg = inout.createMessage();
193: inmsg.setContent(src);
194: sendInOut(inout, inmsg);
195: } else if (mep.trim().equalsIgnoreCase(
196: MessageProcessor.IN_ONLY.trim())) {
197: inonly = mFactory.createInOnlyExchange();
198: inmsg = inonly.createMessage();
199: inmsg.setContent(src);
200: sendInOnly(inonly, inmsg);
201: } else if (mep.trim().equalsIgnoreCase(
202: MessageProcessor.ROBUST_IN_ONLY.trim())) {
203: robustinonly = mFactory.createRobustInOnlyExchange();
204: inmsg = robustinonly.createMessage();
205: inmsg.setContent(src);
206: sendRobustInOnly(robustinonly, inmsg);
207: } else if (mep.trim().equalsIgnoreCase(
208: MessageProcessor.IN_OPTIONAL_OUT.trim())) {
209: mLog.info(mTranslator
210: .getString(FBC_INOPTIONALOUT_NOT_SUPPORTED));
211: throw new Exception(mTranslator
212: .getString(FBC_INOPTIONALOUT_NOT_SUPPORTED));
213: } else {
214: mLog.severe(mTranslator.getString(FBC_INVALID_PATTERN,
215: mBean.getValue(ConfigData.MEP), mBean
216: .getUniqueName()));
217: throw new Exception(mTranslator.getString(
218: FBC_INVALID_PATTERN, mBean
219: .getValue(ConfigData.MEP), mBean
220: .getUniqueName()));
221: }
222: } catch (Exception e) {
223: mLog.severe(mTranslator.getString(FBC_SEND_FAILED));
224: e.printStackTrace();
225: writeErrorMessage(e);
226:
227: String procfolder = (String) mBean
228: .getValue(ConfigData.PROCESSEDDIR);
229:
230: if (procfolder != null) {
231: mDestFolder = new File(procfolder);
232: }
233:
234: if (!FileBindingUtil.moveFile(mTrkId, mDestFolder, mFile)) {
235: mLog
236: .severe(mTranslator.getString(FBC_MOVE_FAILED,
237: mFile.getName(), mDestFolder
238: .getAbsolutePath()));
239: }
240: }
241: }
242:
243: /**
244: * Closes a file being read.
245: */
246: public void terminate() {
247: try {
248: mBis.close();
249: } catch (Exception e) {
250: ;
251: }
252: }
253:
254: /**
255: * Writes a error message into file.
256: *
257: * @param ex exception message.
258: */
259: public void writeErrorMessage(Exception ex) {
260: StringBuffer sb = new StringBuffer();
261: StackTraceElement[] stckTrElem = null;
262: FileOutputStream out = null;
263:
264: try {
265: out = new FileOutputStream(mBean
266: .getValue(ConfigData.OUTPUTDIR)
267: + File.separatorChar
268: + FileBindingUtil.getBaseName(mFile)
269: + ConfigData.SEPARATOR
270: + mTrkId
271: + "."
272: + ConfigData.ERROR_EXTENSION);
273:
274: if (ex == null) {
275: sb.append(mTranslator.getString(FBC_UNKNOWN_ERROR));
276: } else {
277: sb.append(ex.getMessage());
278: stckTrElem = ex.getStackTrace();
279:
280: if (stckTrElem != null) {
281: for (int i = 0; i < stckTrElem.length; i++) {
282: String stckTrace = stckTrElem[i].toString();
283: sb.append(stckTrace);
284: sb.append("\n");
285: }
286: }
287: }
288:
289: out.write(sb.toString().getBytes());
290: out.close();
291: } catch (Exception e) {
292: mLog.info(mTranslator.getString(FBC_FILE_WRITE_FAILED,
293: mFile.getAbsolutePath()));
294: e.printStackTrace();
295: } finally {
296: try {
297: if (out != null) {
298: out.close();
299: }
300: } catch (Exception e1) {
301: mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED, e1
302: .getMessage()));
303: }
304: }
305: }
306:
307: /**
308: * Sets the endpoint reference.
309: *
310: * @throws Exception EXCEPTION.
311: */
312: private void setServiceEndpoint() throws Exception {
313: /**
314: * Always try to get an endpoint only before sending this gives the
315: * maximum probability of finding an endpoint, also we give an engine
316: * enoughs time to activate the endpoint
317: */
318: try {
319: QName qname = new QName(mBean
320: .getValue(ConfigData.SERVICE_NAMESPACE), mBean
321: .getValue(ConfigData.SERVICE_LOCALNAME));
322: QName iqname = new QName(mBean
323: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
324: .getValue(ConfigData.INTERFACE_LOCALNAME));
325:
326: ServiceEndpoint[] ref = mContext
327: .getEndpointsForService(qname);
328:
329: if ((ref == null) || (ref.length == 0)) {
330: ref = mContext.getEndpoints(iqname);
331: }
332:
333: if ((ref == null) || (ref.length == 0)) {
334: throw new Exception("Cannot locate endpoint for "
335: + qname + " or " + iqname);
336: } else {
337: mServiceEndpoint = ref[0];
338:
339: for (int k = 0; k < ref.length; k++) {
340: if (ref[k].getEndpointName().trim().equals(
341: mBean.getValue(ConfigData.ENDPOINTNAME))) {
342: mServiceEndpoint = ref[k];
343: }
344: }
345: }
346:
347: mBean.setServiceEndpoint(mServiceEndpoint);
348: } catch (Exception me) {
349: me.printStackTrace();
350: throw me;
351: }
352: }
353:
354: /**
355: * Creates a source from the file contents.
356: *
357: * @return source
358: */
359: private Source getSource() {
360: org.w3c.dom.Document doc = null;
361: org.w3c.dom.Document doc1 = null;
362: Text txt = null;
363: FileInputStream fs = null;
364:
365: try {
366: fs = new FileInputStream(mFile);
367: mBis = new BufferedInputStream(fs);
368:
369: DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory
370: .newInstance();
371: docBuilderFactory.setValidating(false);
372: docBuilderFactory.setNamespaceAware(true);
373:
374: DocumentBuilder docBuilder = docBuilderFactory
375: .newDocumentBuilder();
376: doc = docBuilder.parse(mBis);
377: doc.normalize();
378:
379: //String namespace = doc.getDocumentElement().getNamespaceURI();
380: //String localname = doc.getDocumentElement().getLocalName();
381: if (mBis != null) {
382: mBis.close();
383: }
384:
385: if (fs != null) {
386: fs.close();
387: }
388:
389: return (new DOMSource(doc));
390: } catch (SAXParseException spe) {
391: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
392: .getAbsolutePath()));
393: mLog.severe(spe.getMessage());
394: mException = spe;
395: spe.printStackTrace();
396: } catch (ParserConfigurationException pce) {
397: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
398: .getAbsolutePath()));
399: mLog.severe(pce.getMessage());
400: mException = pce;
401: pce.printStackTrace();
402: } catch (SAXException sxe) {
403: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
404: .getAbsolutePath()));
405: mLog.severe(sxe.getMessage());
406: mException = sxe;
407: sxe.printStackTrace();
408: } catch (Exception e) {
409: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
410: .getAbsolutePath()));
411: mLog.severe(e.getMessage());
412: mException = e;
413: e.printStackTrace();
414: } finally {
415: try {
416: if (mBis != null) {
417: mBis.close();
418: }
419:
420: if (fs != null) {
421: fs.close();
422: }
423: } catch (Exception e) {
424: ;
425: }
426: }
427:
428: return null;
429: }
430:
431: /**
432: * Sends an in only message exchange.
433: *
434: * @param inonly inonly message exchange
435: * @param inmsg message to be set in exchange.
436: *
437: * @throws Exception any exception
438: */
439: private void sendInOnly(InOnly inonly, NormalizedMessage inmsg)
440: throws Exception {
441: /**
442: * Whatever is implemented here is a best effort delivery We dont try
443: * to store messages and redelierv is an endpoint is temporarily
444: * unavailable
445: */
446: try {
447: setServiceEndpoint();
448: inonly.setService(mServiceEndpoint.getServiceName());
449: QName iqname = new QName(mBean
450: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
451: .getValue(ConfigData.INTERFACE_LOCALNAME));
452: inonly.setInterfaceName(iqname);
453: inonly.setEndpoint(mServiceEndpoint);
454: inonly.setOperation(mCurrentOperation);
455:
456: inonly.setProperty(ConfigData.FILENAME_PROPERTY,
457: FileBindingUtil.getBaseName(mFile));
458: inonly.setProperty(ConfigData.TRACKINGID_PROPERTY, mTrkId);
459: inonly.setProperty(ConfigData.EXTENSION_PROPERTY,
460: FileBindingUtil.getExtension(mFile));
461: inonly.setInMessage(inmsg);
462: mChannel.send(inonly);
463: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE, inonly
464: .getExchangeId()));
465: } catch (Exception me) {
466: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
467: .getAbsolutePath()));
468: mLog.severe(me.getMessage());
469: mException = me;
470: throw mException;
471: }
472: }
473:
474: /**
475: * Sends an in-out message exchange.
476: *
477: * @param inout message exchange.
478: * @param inmsg message to be set in exchange.
479: *
480: * @throws Exception any exception.
481: */
482: private void sendInOut(InOut inout, NormalizedMessage inmsg)
483: throws Exception {
484: /**
485: * Whatever is implemented here is a best effort delivery We dont try
486: * to store messages and redelierv is an endpoint is temporarily
487: * unavailable
488: */
489: try {
490: setServiceEndpoint();
491: inout.setService(mServiceEndpoint.getServiceName());
492: QName iqname = new QName(mBean
493: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
494: .getValue(ConfigData.INTERFACE_LOCALNAME));
495: inout.setInterfaceName(iqname);
496: inout.setOperation(mCurrentOperation);
497: inout.setEndpoint(mServiceEndpoint);
498: inout.setProperty(ConfigData.FILENAME_PROPERTY,
499: FileBindingUtil.getBaseName(mFile));
500: inout.setProperty(ConfigData.TRACKINGID_PROPERTY, mTrkId);
501: inout.setProperty(ConfigData.EXTENSION_PROPERTY,
502: FileBindingUtil.getExtension(mFile));
503: inout.setInMessage(inmsg);
504: mChannel.send(inout);
505: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE, inout
506: .getExchangeId()));
507: } catch (Exception me) {
508: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
509: .getAbsolutePath()));
510: mLog.severe(me.getMessage());
511: mException = me;
512: throw mException;
513: }
514: }
515:
516: /**
517: * Sends a robust in only message exchange.
518: *
519: * @param robustinonly inonly message exchange
520: * @param inmsg message to be set in exchange.
521: *
522: * @throws Exception any exception
523: */
524: private void sendRobustInOnly(RobustInOnly robustinonly,
525: NormalizedMessage inmsg) throws Exception {
526: /**
527: * Whatever is implemented here is a best effort delivery We dont try
528: * to store messages and redelierv is an endpoint is temporarily
529: * unavailable
530: */
531: try {
532: setServiceEndpoint();
533: robustinonly.setService(mServiceEndpoint.getServiceName());
534: QName iqname = new QName(mBean
535: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
536: .getValue(ConfigData.INTERFACE_LOCALNAME));
537: robustinonly.setInterfaceName(iqname);
538: robustinonly.setOperation(mCurrentOperation);
539: robustinonly.setEndpoint(mServiceEndpoint);
540: robustinonly.setProperty(ConfigData.FILENAME_PROPERTY,
541: FileBindingUtil.getBaseName(mFile));
542: robustinonly.setProperty(ConfigData.TRACKINGID_PROPERTY,
543: mTrkId);
544: robustinonly.setProperty(ConfigData.EXTENSION_PROPERTY,
545: FileBindingUtil.getExtension(mFile));
546: robustinonly.setInMessage(inmsg);
547: mChannel.send(robustinonly);
548: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE,
549: robustinonly.getExchangeId()));
550: } catch (Exception me) {
551: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
552: .getAbsolutePath()));
553: mLog.severe(me.getMessage());
554: mException = me;
555: throw me;
556: }
557: }
558: }
|