001: /*
002: * BEGIN_HEADER - DO NOT EDIT
003: *
004: * The contents of this file are subject to the terms
005: * of the Common Development and Distribution License
006: * (the "License"). You may not use this file except
007: * in compliance with the License.
008: *
009: * You can obtain a copy of the license at
010: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
011: * See the License for the specific language governing
012: * permissions and limitations under the License.
013: *
014: * When distributing Covered Code, include this CDDL
015: * HEADER in each file and include the License file at
016: * https://open-esb.dev.java.net/public/CDDLv1.0.html.
017: * If applicable add the following below this CDDL HEADER,
018: * with the fields enclosed by brackets "[]" replaced with
019: * your own identifying information: Portions Copyright
020: * [year] [name of copyright owner]
021: */
022:
023: /*
024: * @(#)FileCommand.java
025: * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
026: *
027: * END_HEADER - DO NOT EDIT
028: */
029: package com.sun.jbi.binding.file;
030:
031: import com.sun.jbi.binding.file.FileBindingContext;
032: import com.sun.jbi.binding.file.framework.Command;
033: import com.sun.jbi.binding.file.util.ConfigData;
034: import com.sun.jbi.binding.file.util.FileBindingUtil;
035: import com.sun.jbi.binding.file.util.StringTranslator;
036:
037: import org.w3c.dom.Text;
038:
039: import org.xml.sax.SAXException;
040: import org.xml.sax.SAXParseException;
041:
042: import java.io.File;
043: import java.io.FileInputStream;
044: import java.io.FileOutputStream;
045: import java.io.RandomAccessFile;
046: import java.nio.channels.FileChannel;
047: import java.nio.channels.FileLock;
048:
049: import java.util.logging.Logger;
050:
051: import javax.jbi.component.ComponentContext;
052: import javax.jbi.messaging.DeliveryChannel;
053: import javax.jbi.messaging.InOnly;
054: import javax.jbi.messaging.InOut;
055: import javax.jbi.messaging.MessageExchangeFactory;
056: import javax.jbi.messaging.NormalizedMessage;
057: import javax.jbi.messaging.RobustInOnly;
058: import javax.jbi.servicedesc.ServiceEndpoint;
059:
060: import javax.xml.namespace.QName;
061: import javax.xml.parsers.SAXParserFactory;
062: import javax.xml.parsers.SAXParser;
063: import org.xml.sax.helpers.DefaultHandler;
064: import javax.xml.parsers.ParserConfigurationException;
065: import javax.xml.transform.Source;
066:
067: import com.sun.jbi.wsdl11wrapper.Wsdl11WrapperHelper;
068: import javax.xml.parsers.DocumentBuilderFactory;
069: import javax.xml.transform.Transformer;
070: import javax.xml.transform.TransformerFactory;
071:
072: import java.util.logging.Level;
073: import javax.xml.transform.stream.StreamResult;
074: import javax.xml.parsers.DocumentBuilder;
075: import org.w3c.dom.Document;
076: import javax.xml.transform.stream.StreamSource;
077: import javax.xml.transform.dom.DOMSource;
078:
079: /**
080: * The FileCommand class reads a file and sends assembles the Normalized
081: * MEssage and sends to to the NMS.
082: *
083: * @author Sun Microsystems, Inc.
084: */
085: public class FileCommand implements Command, FileBindingResources {
086: /**
087: * Input stream for reading the file.
088: */
089: private FileInputStream mFis;
090:
091: /**
092: * Component context.
093: */
094: private ComponentContext mContext;
095:
096: /**
097: * Delivery channel
098: */
099: private DeliveryChannel mChannel;
100:
101: /**
102: * Endpoint bean that stores the endpoint attributes.
103: */
104: private EndpointBean mBean;
105:
106: /**
107: * Exception
108: */
109: private Exception mException;
110:
111: /**
112: * Destination folder to put the processed file.
113: */
114: private File mDestFolder = null;
115:
116: /**
117: * The source file to be sent to NMS
118: */
119: private File mFile = null;
120:
121: /**
122: * Logger Object
123: */
124: private Logger mLog;
125:
126: /**
127: * Exchange factory
128: */
129: private MessageExchangeFactory mFactory;
130:
131: /**
132: * Current operation.
133: */
134: private QName mCurrentOperation;
135:
136: /**
137: * Endpoint reference.
138: */
139: private ServiceEndpoint mServiceEndpoint;
140:
141: /**
142: * Tracking id.
143: */
144: private String mTrkId;
145:
146: /**
147: * Helper for i18n.
148: */
149: private StringTranslator mTranslator;
150:
151: /**
152: * True if a file is locked.
153: */
154: private boolean mFileLocked = false;
155:
156: /**
157: *
158: * Flag to enable input validation
159: */
160: private boolean mInputValidation = true;
161:
162: /**
163: * Creates a new FileCommand object.
164: *
165: * @param file file to be read
166: * @param eb folder to move the processed files.
167: * @param oper operation name.
168: * @param trkid trk id.
169: */
170: FileCommand(File file, EndpointBean eb, QName oper, String trkid) {
171: mLog = FileBindingContext.getInstance().getLogger();
172: mTranslator = new StringTranslator();
173: mFile = file;
174: mContext = FileBindingContext.getInstance().getContext();
175: mBean = eb;
176: mCurrentOperation = oper;
177: mFileLocked = false;
178: mTrkId = trkid;
179: }
180:
181: /**
182: * Returns the name of the folder.
183: *
184: * @return folder name.
185: */
186: public String getName() {
187: if (mFile != null) {
188: return mFile.getAbsolutePath();
189: } else {
190: return "";
191: }
192: }
193:
194: /**
195: * This determines if the input XML document will be validated
196: * for XML well-formedness.
197: */
198: public void setValidating(boolean valid) {
199: mInputValidation = valid;
200: }
201:
202: /**
203: * The run method which sends the normalized message to the respective
204: * service channel. This class is an implementation of the COmmand
205: * interface This method is called when this object is excetuted in a
206: * separate thread.
207: */
208: public void execute() {
209: InOut inout = null;
210: InOnly inonly = null;
211: RobustInOnly robustinonly = null;
212: NormalizedMessage inmsg = null;
213:
214: try {
215: mChannel = mContext.getDeliveryChannel();
216: mFactory = mChannel.createExchangeFactory();
217:
218: Source src = null;
219:
220: src = getSource();
221:
222: dump(src);
223:
224: if (src == null) {
225: mLog.severe(mTranslator
226: .getString(FBC_INVALID_INPUT_FILE));
227: throw mException;
228: }
229:
230: if (mCurrentOperation == null) {
231: mLog.severe(mTranslator
232: .getString(FBC_INVALID_OPERATION_FILE));
233: throw new Exception(mTranslator
234: .getString(FBC_INVALID_OPERATION_FILE));
235: }
236:
237: String mep = mBean.getMEP(mCurrentOperation.getLocalPart());
238:
239: if (mep == null) {
240: mLog.severe(mTranslator
241: .getString(FBC_INVALID_OPERATION_FILE));
242: throw new Exception(mTranslator
243: .getString(FBC_INVALID_OPERATION_FILE));
244: }
245:
246: if (mep.trim().equalsIgnoreCase(
247: MessageProcessor.IN_OUT.trim())) {
248: inout = mFactory.createInOutExchange();
249: inmsg = inout.createMessage();
250: inmsg.setContent(src);
251: sendInOut(inout, inmsg);
252: } else if (mep.trim().equalsIgnoreCase(
253: MessageProcessor.IN_ONLY.trim())) {
254: inonly = mFactory.createInOnlyExchange();
255: inmsg = inonly.createMessage();
256: inmsg.setContent(src);
257: sendInOnly(inonly, inmsg);
258: } else if (mep.trim().equalsIgnoreCase(
259: MessageProcessor.ROBUST_IN_ONLY.trim())) {
260: robustinonly = mFactory.createRobustInOnlyExchange();
261: inmsg = robustinonly.createMessage();
262: inmsg.setContent(src);
263: sendRobustInOnly(robustinonly, inmsg);
264: } else if (mep.trim().equalsIgnoreCase(
265: MessageProcessor.IN_OPTIONAL_OUT.trim())) {
266: mLog.info(mTranslator
267: .getString(FBC_INOPTIONALOUT_NOT_SUPPORTED));
268: throw new Exception(mTranslator
269: .getString(FBC_INOPTIONALOUT_NOT_SUPPORTED));
270: } else {
271: mLog.severe(mTranslator.getString(FBC_INVALID_PATTERN,
272: mBean.getValue(ConfigData.MEP), mBean
273: .getUniqueName()));
274: throw new Exception(mTranslator.getString(
275: FBC_INVALID_PATTERN, mBean
276: .getValue(ConfigData.MEP), mBean
277: .getUniqueName()));
278: }
279: } catch (Exception e) {
280: FileBindingUtil.removeEntry(mTrkId);
281: if (!mFileLocked) {
282: mLog.severe(mTranslator.getString(FBC_SEND_FAILED));
283: e.printStackTrace();
284: writeErrorMessage(e);
285: String procfolder = (String) mBean
286: .getValue(ConfigData.PROCESSEDDIR);
287:
288: if (procfolder != null) {
289: mDestFolder = new File(procfolder);
290: }
291: if (FileBindingUtil
292: .moveFile(mTrkId, mDestFolder, mFile) == null) {
293: mLog.severe(mTranslator.getString(FBC_MOVE_FAILED,
294: mFile.getName(), mDestFolder
295: .getAbsolutePath()));
296: }
297: }
298: }
299: }
300:
301: /**
302: * Closes a file being read.
303: */
304: public void terminate() {
305: try {
306: mFis.close();
307: } catch (Exception e) {
308: ;
309: }
310: }
311:
312: /**
313: * Writes a error message into file.
314: *
315: * @param ex exception message.
316: */
317: public void writeErrorMessage(Exception ex) {
318: StringBuffer sb = new StringBuffer();
319: StackTraceElement[] stckTrElem = null;
320: FileOutputStream out = null;
321:
322: try {
323: out = new FileOutputStream(mBean
324: .getValue(ConfigData.OUTPUTDIR)
325: + File.separatorChar
326: + FileBindingUtil.getBaseName(mFile)
327: + ConfigData.SEPARATOR
328: + mTrkId
329: + "."
330: + ConfigData.ERROR_EXTENSION);
331:
332: if (ex == null) {
333: sb.append(mTranslator.getString(FBC_UNKNOWN_ERROR));
334: } else {
335: sb.append(ex.getMessage());
336: stckTrElem = ex.getStackTrace();
337:
338: if (stckTrElem != null) {
339: for (int i = 0; i < stckTrElem.length; i++) {
340: String stckTrace = stckTrElem[i].toString();
341: sb.append(stckTrace);
342: sb.append("\n");
343: }
344: }
345: }
346:
347: out.write(sb.toString().getBytes());
348: out.close();
349: } catch (Exception e) {
350: mLog.info(mTranslator.getString(FBC_FILE_WRITE_FAILED,
351: mFile.getAbsolutePath()));
352: e.printStackTrace();
353: } finally {
354: try {
355: if (out != null) {
356: out.close();
357: }
358: } catch (Exception e1) {
359: mLog.severe(mTranslator.getString(FBC_CLOSE_FAILED, e1
360: .getMessage()));
361: }
362: }
363: }
364:
365: /**
366: * Sets the endpoint reference.
367: *
368: * @throws Exception EXCEPTION.
369: */
370: private void setServiceEndpoint() throws Exception {
371: /**
372: * Always try to get an endpoint only before sending this gives the
373: * maximum probability of finding an endpoint, also we give an engine
374: * enoughs time to activate the endpoint
375: */
376: try {
377: QName qname = new QName(mBean
378: .getValue(ConfigData.SERVICE_NAMESPACE), mBean
379: .getValue(ConfigData.SERVICE_LOCALNAME));
380: QName iqname = new QName(mBean
381: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
382: .getValue(ConfigData.INTERFACE_LOCALNAME));
383:
384: ServiceEndpoint[] ref = mContext
385: .getEndpointsForService(qname);
386:
387: if ((ref == null) || (ref.length == 0)) {
388: ref = mContext.getEndpoints(iqname);
389: }
390:
391: if ((ref == null) || (ref.length == 0)) {
392: throw new Exception("Cannot locate endpoint for "
393: + qname + " or " + iqname);
394: } else {
395: mServiceEndpoint = ref[0];
396:
397: for (int k = 0; k < ref.length; k++) {
398: if (ref[k].getEndpointName().trim().equals(
399: mBean.getValue(ConfigData.ENDPOINTNAME))) {
400: mServiceEndpoint = ref[k];
401: }
402: }
403: }
404:
405: mBean.setServiceEndpoint(mServiceEndpoint);
406: } catch (Exception me) {
407: me.printStackTrace();
408: throw me;
409: }
410: }
411:
412: /**
413: * Creates a source from the file contents.
414: *
415: * @return source
416: */
417: private Source getSource() {
418: org.w3c.dom.Document doc = null;
419: org.w3c.dom.Document doc1 = null;
420: Text txt = null;
421: FileLock fileLock = null;
422: try {
423: FileOutputStream fos = null;
424: try {
425: /* try to get a lock on this file this way
426: * if u get one, its good
427: */
428: fos = new FileOutputStream(mFile, true);
429: if (fos != null) {
430: fos.close();
431: }
432: } catch (Exception e) {
433: mLog.info(mTranslator.getString(FBC_NO_LOCK, mFile
434: .getAbsolutePath()));
435: mFileLocked = true;
436: return null;
437: }
438: mFis = new FileInputStream(mFile);
439: if (mBean.getDeploymentType().equals("WSDL11")) {
440: DocumentBuilderFactory docbuilderfactory = DocumentBuilderFactory
441: .newInstance();
442: docbuilderfactory.setValidating(false);
443: docbuilderfactory.setNamespaceAware(true);
444: DocumentBuilder docbuilder = docbuilderfactory
445: .newDocumentBuilder();
446: Document d = docbuilder.parse(mFis);
447: Wsdl11WrapperHelper helper = new Wsdl11WrapperHelper(
448: mBean.getWsdlDefinition());
449: QName qname = new QName(mBean
450: .getValue(ConfigData.SERVICE_NAMESPACE), mBean
451: .getValue(ConfigData.SERVICE_LOCALNAME));
452: String epname = mBean.getValue(ConfigData.ENDPOINTNAME);
453: Document wd = helper.wrapMessage(d, qname, epname,
454: mCurrentOperation.getLocalPart(), true);
455:
456: if (mFis != null) {
457: mFis.close();
458: }
459: if (wd == null) {
460: return null;
461: } else {
462: return (new DOMSource(wd));
463: }
464: } else {
465: if (mInputValidation) {
466: SAXParserFactory saxParserFactory = SAXParserFactory
467: .newInstance();
468: saxParserFactory.setValidating(false);
469: saxParserFactory.setNamespaceAware(true);
470: SAXParser saxParser = saxParserFactory
471: .newSAXParser();
472: saxParser.parse(mFis, new DefaultHandler());
473:
474: if (mFis != null) {
475: mFis.close();
476: }
477: }
478: return (new StreamSource(mFile));
479: }
480:
481: } catch (SAXParseException spe) {
482: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
483: .getAbsolutePath()));
484: mLog.severe(spe.getMessage());
485: mException = spe;
486: spe.printStackTrace();
487: } catch (ParserConfigurationException pce) {
488: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
489: .getAbsolutePath()));
490: mLog.severe(pce.getMessage());
491: mException = pce;
492: pce.printStackTrace();
493: } catch (SAXException sxe) {
494: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
495: .getAbsolutePath()));
496: mLog.severe(sxe.getMessage());
497: mException = sxe;
498: sxe.printStackTrace();
499: } catch (Exception e) {
500: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
501: .getAbsolutePath()));
502: mLog.severe(e.getMessage());
503: mException = e;
504: e.printStackTrace();
505: } finally {
506: try {
507: if (mFis != null) {
508: mFis.close();
509: }
510: } catch (Exception e) {
511: ;
512: }
513: }
514:
515: return null;
516: }
517:
518: /**
519: * Creates a source from the file contents.
520: *
521: * @return source
522: */
523: private Source getWsdl11Source() {
524: org.w3c.dom.Document doc = null;
525: org.w3c.dom.Document doc1 = null;
526: Text txt = null;
527: FileLock fileLock = null;
528: try {
529: FileOutputStream fos = null;
530: try {
531: /* try to get a lock on this file this way
532: * if u get one, its good
533: */
534: fos = new FileOutputStream(mFile, true);
535: if (fos != null) {
536: fos.close();
537: }
538: } catch (Exception e) {
539: mLog.info(mTranslator.getString(FBC_NO_LOCK, mFile
540: .getAbsolutePath()));
541: mFileLocked = true;
542: return null;
543: }
544: mFis = new FileInputStream(mFile);
545: } catch (Exception e) {
546: mLog.severe(mTranslator.getString(FBC_INVALID_XML, mFile
547: .getAbsolutePath()));
548: mLog.severe(e.getMessage());
549: mException = e;
550: e.printStackTrace();
551: } finally {
552: try {
553: if (mFis != null) {
554: mFis.close();
555: }
556: } catch (Exception e) {
557: ;
558: }
559: }
560:
561: return null;
562: }
563:
564: /**
565: * Sends an in only message exchange.
566: *
567: * @param inonly inonly message exchange
568: * @param inmsg message to be set in exchange.
569: *
570: * @throws Exception any exception
571: */
572: private void sendInOnly(InOnly inonly, NormalizedMessage inmsg)
573: throws Exception {
574: /**
575: * Whatever is implemented here is a best effort delivery We dont try
576: * to store messages and redelierv is an endpoint is temporarily
577: * unavailable
578: */
579: try {
580: setServiceEndpoint();
581: inonly.setService(mServiceEndpoint.getServiceName());
582: QName iqname = new QName(mBean
583: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
584: .getValue(ConfigData.INTERFACE_LOCALNAME));
585: inonly.setInterfaceName(iqname);
586: inonly.setEndpoint(mServiceEndpoint);
587: inonly.setOperation(mCurrentOperation);
588:
589: inonly.setProperty(ConfigData.FILENAME_PROPERTY,
590: FileBindingUtil.getBaseName(mFile));
591: inonly.setProperty(ConfigData.TRACKINGID_PROPERTY, mTrkId);
592: inonly.setProperty(ConfigData.EXTENSION_PROPERTY,
593: FileBindingUtil.getExtension(mFile));
594: inonly.setInMessage(inmsg);
595: mChannel.send(inonly);
596: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE, inonly
597: .getExchangeId()));
598: } catch (Exception me) {
599: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
600: .getAbsolutePath()));
601: mLog.severe(me.getMessage());
602: mException = me;
603: throw mException;
604: }
605: }
606:
607: /**
608: * Sends an in-out message exchange.
609: *
610: * @param inout message exchange.
611: * @param inmsg message to be set in exchange.
612: *
613: * @throws Exception any exception.
614: */
615: private void sendInOut(InOut inout, NormalizedMessage inmsg)
616: throws Exception {
617: /**
618: * Whatever is implemented here is a best effort delivery We dont try
619: * to store messages and redelierv is an endpoint is temporarily
620: * unavailable
621: */
622: try {
623: setServiceEndpoint();
624: inout.setService(mServiceEndpoint.getServiceName());
625: QName iqname = new QName(mBean
626: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
627: .getValue(ConfigData.INTERFACE_LOCALNAME));
628: inout.setInterfaceName(iqname);
629: inout.setOperation(mCurrentOperation);
630: inout.setEndpoint(mServiceEndpoint);
631: inout.setProperty(ConfigData.FILENAME_PROPERTY,
632: FileBindingUtil.getBaseName(mFile));
633: inout.setProperty(ConfigData.TRACKINGID_PROPERTY, mTrkId);
634: inout.setProperty(ConfigData.EXTENSION_PROPERTY,
635: FileBindingUtil.getExtension(mFile));
636: inout.setInMessage(inmsg);
637: mChannel.send(inout);
638: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE, inout
639: .getExchangeId()));
640: } catch (Exception me) {
641: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
642: .getAbsolutePath()));
643: mLog.severe(me.getMessage());
644: mException = me;
645: throw mException;
646: }
647: }
648:
649: /**
650: * Sends a robust in only message exchange.
651: *
652: * @param robustinonly inonly message exchange
653: * @param inmsg message to be set in exchange.
654: *
655: * @throws Exception any exception
656: */
657: private void sendRobustInOnly(RobustInOnly robustinonly,
658: NormalizedMessage inmsg) throws Exception {
659: /**
660: * Whatever is implemented here is a best effort delivery We dont try
661: * to store messages and redelierv is an endpoint is temporarily
662: * unavailable
663: */
664: try {
665: setServiceEndpoint();
666: robustinonly.setService(mServiceEndpoint.getServiceName());
667: QName iqname = new QName(mBean
668: .getValue(ConfigData.INTERFACE_NAMESPACE), mBean
669: .getValue(ConfigData.INTERFACE_LOCALNAME));
670: robustinonly.setInterfaceName(iqname);
671: robustinonly.setOperation(mCurrentOperation);
672: robustinonly.setEndpoint(mServiceEndpoint);
673: robustinonly.setProperty(ConfigData.FILENAME_PROPERTY,
674: FileBindingUtil.getBaseName(mFile));
675: robustinonly.setProperty(ConfigData.TRACKINGID_PROPERTY,
676: mTrkId);
677: robustinonly.setProperty(ConfigData.EXTENSION_PROPERTY,
678: FileBindingUtil.getExtension(mFile));
679: robustinonly.setInMessage(inmsg);
680: mChannel.send(robustinonly);
681: mLog.info(mTranslator.getString(FBC_SENDING_MESSAGE,
682: robustinonly.getExchangeId()));
683: } catch (Exception me) {
684: mLog.severe(mTranslator.getString(FBC_TRY_LATER, mFile
685: .getAbsolutePath()));
686: mLog.severe(me.getMessage());
687: mException = me;
688: throw me;
689: }
690: }
691:
692: private void dump(Source src) {
693: try {
694: if (mLog.getLevel() == Level.FINEST) {
695: TransformerFactory tFactory = TransformerFactory
696: .newInstance();
697: Transformer trans = tFactory.newTransformer();
698: StreamResult result = new StreamResult(System.out);
699: trans.transform(src, result);
700: }
701:
702: } catch (Throwable t) {
703: ;
704: }
705: }
706: }
|