// // Copyright (c)1998-2011 Pearson Education, Inc. or its affiliate(s). // All rights reserved. // package openadk.library.services.impl; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Calendar; import openadk.library.ADKException; import openadk.library.DataObjectOutputStream; import openadk.library.ElementDef; import openadk.library.Query; import openadk.library.SIFDataObject; import openadk.library.SIFElement; import openadk.library.SIFVersion; import openadk.library.SIFWriter; import openadk.library.Zone; import openadk.library.common.YesNo; import openadk.library.impl.BaseObjectOutputStream; import openadk.library.impl.ZoneImpl; import openadk.library.infra.SIF_Error; import openadk.library.infra.SIF_Header; import openadk.library.infra.SIF_ObjectData; import openadk.library.infra.SIF_Response; import openadk.library.infra.SIF_ServiceOutput; /* * Clone of */ public abstract class ServiceOutputStreamImpl implements BaseObjectOutputStream { protected String fReqId; protected String fDestId; /** * Construct a new DataObjectOutputStream * @return A new DataObjectOutputStream object, which will always be a * an instanceof DataObjectOutputStreamImpl as defined by the * <code>adkglobal.factory.DataObjectOutputStream</code> system property. * */ public static ServiceOutputStreamImpl newInstance() throws ADKException { String cls = System.getProperty("adkglobal.factory.ServiceOutputStream"); if( cls == null ) cls = "openadk.library.services.impl.ServiceOutputFileStream"; try { return (ServiceOutputStreamImpl)Class.forName(cls).newInstance(); } catch( Throwable thr ) { throw new ADKException("ADK could not create an instance of the class "+cls+": "+thr,null); } } /** * Initialize the output stream. This method must be called after creating * a new instance of this class and before writing any SIFDataObjects to * the stream. * * @param zone The Zone associated with messages that will be written * to the stream * @param query The Query object to use as a source for any SIF_Element * filter restrictions that might be placed on this SIF_Response * @param requestSourceId The SourceId of the associated SIF_Request message * @param requestMsgId The MsgId of the associated SIF_Request message * @param requestSIFMessageVersion The version of the SIF_Message envelope * of the SIF_Request message * @param maxSize The maximum size of rendered SIFDataObject that will be * accepted by this stream. If a SIFDataObject is written to the stream * and its size exceeds this value after rendering the object to an XML * stream, an ObjectTooLargeException will be thrown by the <i>write</i> * method */ public abstract void initialize( Zone zone, Query query, String requestSourceId, String requestMsgId, SIFVersion requestSIFMessageVersion, int maxSize ) throws ADKException; /** * Initialize the output stream. This method must be called after creating * a new instance of this class and before writing any SIFDataObjects to * the stream. * * @param zone The Zone associated with messages that will be written * to the stream * @param queryRestrictions Any field restrictions that were specified in the SIF_Request message. * Call {@link openadk.library.Query#getFieldRestrictions} to obtain * this array. * @param requestSourceId The SourceId of the associated SIF_Request message * @param requestMsgId The MsgId of the associated SIF_Request message * @param requestSIFMessageVersion The version of the SIF_Message envelope * of the SIF_Request message * @param maxSize The maximum size of rendered SIFDataObject that will be * accepted by this stream. If a SIFDataObject is written to the stream * and its size exceeds this value after rendering the object to an XML * stream, an ObjectTooLargeException will be thrown by the <i>write</i> * method */ public abstract void initialize( Zone zone, ElementDef[] queryRestrictions, String requestSourceId, String requestMsgId, SIFVersion requestSIFMessageVersion, int maxSize ) throws ADKException; public abstract void close() throws IOException; /** * Called by the class framework when the Publisher.onQuery method has * returned successfully */ public abstract void commit() throws ADKException; /** * Called by the class framework when the Publisher.onQuery method has * thrown an exception other than SIFException */ public abstract void abort() throws ADKException; /** * Write a SIFDataObject to the stream */ public abstract void write( SIFElement data ) throws ADKException; /** * Called when the Publisher.onQuery method has thrown a SIFException, * indicating an error should be returned in the SIF_Response body */ public abstract void setError( SIF_Error error ) throws ADKException; /** * Calculate the size of a SIF_Response minus the SIF_ObjectData content. */ protected int calcEnvelopeSize( ZoneImpl zone ) { int size = 400; try { SIF_ServiceOutput rsp = new SIF_ServiceOutput(); rsp.setSIF_MorePackets( "Yes" ); rsp.setSIF_ServiceMsgId(fReqId); rsp.setSIF_PacketNumber( 100000000 ); rsp.setSIF_Body( " " ); SIF_Header hdr = rsp.getHeader(); hdr.setSIF_Timestamp( Calendar.getInstance() ); hdr.setSIF_MsgId("012345678901234567890123456789012"); hdr.setSIF_SourceId(zone.getAgent().getId()); hdr.setSIF_Security(zone.getFDispatcher().secureChannel()); hdr.setSIF_DestinationId(fDestId); ByteArrayOutputStream tmp = new ByteArrayOutputStream(); SIFWriter out = new SIFWriter( tmp, zone ); out.write( rsp ); out.flush(); size = tmp.size() + 20 /* just in case */; out.close(); tmp.close(); } catch( Exception ex ) { zone.log.warn( "Error calculating packet size: " + ex, ex ); } return size; } /** * Returns the value that will be set to the SIF_MorePackets element in the message * after this DataObjectOutputStream is closed * @return */ public abstract YesNo getSIF_MorePackets(); /** * Returns the current SIF_PacketNumber * @return */ public abstract int getSIF_PacketNumber(); /** * Sets the value that will be set to the SIF_MorePackets element in the message * after this DataObjectOutputStream is closed * @param morePacketsValue * @exception IllegalStateException thrown if an object has already been written to the output stream */ public abstract void setSIF_MorePackets(YesNo morePacketsValue); /** * Sets the value that will be used for the number of the first packet created by the output stream * * @param packetNumber * @exception IllegalStateException thrown if an object has already been written to the output stream */ public abstract void setSIF_PacketNumber(int packetNumber); }