Source Code Cross Referenced for DDMWriter.java in  » Database-DBMS » db-derby-10.2 » org » apache » derby » impl » drda » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » db derby 10.2 » org.apache.derby.impl.drda 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:
0003:           Derby - Class org.apache.derby.impl.drda.DDMWriter
0004:
0005:           Licensed to the Apache Software Foundation (ASF) under one or more
0006:           contributor license agreements.  See the NOTICE file distributed with
0007:           this work for additional information regarding copyright ownership.
0008:           The ASF licenses this file to You under the Apache License, Version 2.0
0009:           (the "License"); you may not use this file except in compliance with
0010:           the License.  You may obtain a copy of the License at
0011:
0012:              http://www.apache.org/licenses/LICENSE-2.0
0013:
0014:           Unless required by applicable law or agreed to in writing, software
0015:           distributed under the License is distributed on an "AS IS" BASIS,
0016:           WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017:           See the License for the specific language governing permissions and
0018:           limitations under the License.
0019:
0020:         */
0021:
0022:        package org.apache.derby.impl.drda;
0023:
0024:        import java.io.OutputStream;
0025:        import java.io.InputStream;
0026:        import java.io.BufferedInputStream;
0027:        import java.io.BufferedOutputStream;
0028:        import org.apache.derby.iapi.services.sanity.SanityManager;
0029:        import java.sql.SQLException;
0030:        import java.sql.DataTruncation;
0031:        import java.math.BigDecimal;
0032:        import org.apache.derby.iapi.error.ExceptionSeverity;
0033:        import java.util.Arrays;
0034:        import org.apache.derby.iapi.reference.Property;
0035:        import org.apache.derby.iapi.services.property.PropertyUtil;
0036:
0037:        import java.io.IOException;
0038:
0039:        /**
0040:         The DDMWriter is used to write DRDA protocol.   The DRDA Protocol is
0041:         described in the DDMReader class.
0042:         For more details, see DRDA Volume 3 (Distributed Data Management(DDM)
0043:         Architecture (DDS definition)
0044:         */
0045:        class DDMWriter {
0046:
0047:            // number of nesting levels for collections.  We need to mark the length
0048:            // location of the collection so that we can update it as we add more stuff
0049:            // to the collection
0050:            private final static int MAX_MARKS_NESTING = 10;
0051:
0052:            // Default buffer size
0053:            private final static int DEFAULT_BUFFER_SIZE = 32767;
0054:
0055:            static final BigDecimal ZERO = BigDecimal.valueOf(0L);
0056:
0057:            // output buffer
0058:            private byte[] bytes;
0059:
0060:            // offset into output buffer
0061:            private int offset;
0062:
0063:            // A saved mark in the stream is saved temporarily to revisit the location.
0064:            private int[] markStack = new int[MAX_MARKS_NESTING];
0065:
0066:            // top of the stack
0067:            private int top;
0068:
0069:            // CCSID manager for translation of strings in the protocol to EBCDIC
0070:            private CcsidManager ccsidManager;
0071:
0072:            // DRDA connection thread for this writer
0073:            private DRDAConnThread agent;
0074:
0075:            //	This Object tracks the location of the current
0076:            //	Dss header length bytes.	This is done so
0077:            //	the length bytes can be automatically
0078:            //	updated as information is added to this stream.
0079:            private int dssLengthLocation;
0080:
0081:            // Current correlation ID
0082:            private int correlationID;
0083:
0084:            // Next correlation ID
0085:            private int nextCorrelationID;
0086:
0087:            // is this DRDA protocol or CMD protocol
0088:            private boolean isDRDAProtocol;
0089:            // trace object of the associated session
0090:            private DssTrace dssTrace;
0091:
0092:            // Location within the "bytes" array of the start of the header
0093:            // of the DSS most recently written to the buffer.
0094:            private int prevHdrLocation;
0095:
0096:            // Correlation id of the last DSS that was written to buffer.
0097:            private int previousCorrId;
0098:
0099:            // Chaining bit of the last DSS that was written to buffer.
0100:            private byte previousChainByte;
0101:
0102:            // Whether or not the current DSS is a continuation DSS.
0103:            private boolean isContinuationDss;
0104:
0105:            // In situations where we want to "mark" a buffer location so that
0106:            // we can "back-out" of a write to handle errors, this holds the
0107:            // location within the "bytes" array of the start of the header
0108:            // that immediately precedes the mark.
0109:            private int lastDSSBeforeMark;
0110:
0111:            // Constructors
0112:            DDMWriter(int minSize, CcsidManager ccsidManager,
0113:                    DRDAConnThread agent, DssTrace dssTrace) {
0114:                this .bytes = new byte[minSize];
0115:                this .ccsidManager = ccsidManager;
0116:                this .agent = agent;
0117:                this .prevHdrLocation = -1;
0118:                this .previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
0119:                this .previousChainByte = DssConstants.DSS_NOCHAIN;
0120:                this .isContinuationDss = false;
0121:                this .lastDSSBeforeMark = -1;
0122:                reset(dssTrace);
0123:            }
0124:
0125:            DDMWriter(CcsidManager ccsidManager, DRDAConnThread agent,
0126:                    DssTrace dssTrace) {
0127:                this .bytes = new byte[DEFAULT_BUFFER_SIZE];
0128:                this .ccsidManager = ccsidManager;
0129:                this .agent = agent;
0130:                this .prevHdrLocation = -1;
0131:                this .previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
0132:                this .previousChainByte = DssConstants.DSS_NOCHAIN;
0133:                this .isContinuationDss = false;
0134:                this .lastDSSBeforeMark = -1;
0135:                reset(dssTrace);
0136:            }
0137:
0138:            /**
0139:             * reset values for sending next message
0140:             *
0141:             */
0142:            protected void reset(DssTrace dssTrace) {
0143:                offset = 0;
0144:                top = 0;
0145:                dssLengthLocation = 0;
0146:                nextCorrelationID = 1;
0147:                correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
0148:                isDRDAProtocol = true;
0149:                this .dssTrace = dssTrace;
0150:            }
0151:
0152:            /**
0153:             * set protocol to CMD protocol
0154:             */
0155:            protected void setCMDProtocol() {
0156:                isDRDAProtocol = false;
0157:            }
0158:
0159:            /**
0160:             * Create DSS reply object
0161:             */
0162:            protected void createDssReply() {
0163:                beginDss(DssConstants.DSSFMT_RPYDSS, true);
0164:            }
0165:
0166:            /**
0167:             * Create DSS request object
0168:             * NOTE: This is _ONLY_ used for testing the protocol
0169:             * (via the TestProto.java file in this package)!
0170:             * We should never create a DSS request in normal
0171:             * DRDA processing (we should only create DSS replies
0172:             * and DSS objects).
0173:             */
0174:            protected void createDssRequest() {
0175:                beginDss(DssConstants.DSSFMT_RQSDSS, true);
0176:            }
0177:
0178:            /**
0179:             * Create DSS data object
0180:             */
0181:            protected void createDssObject() {
0182:                beginDss(DssConstants.DSSFMT_OBJDSS, true);
0183:            }
0184:
0185:            /**
0186:             * Mark the DSS that we're currently writing as
0187:             * a continued DSS, which is done by setting
0188:             * the high-order bit to "1", per DDM spec.
0189:             * This means:
0190:             *
0191:             *	1. One or more continuation DSSes will immediately
0192:             * 		follow the current (continued) DSS.
0193:             *	2. All continuation DSSes will have a 2-byte
0194:             * 		continuation header, followed by data; in
0195:             * 		other words, chaining state, correlation
0196:             *		id, dss format info, and code point will
0197:             * 		NOT be included.  All of that info is 
0198:             * 		present ONLY in the FIRST DSS in the
0199:             *		list of continued DSSes.
0200:             *
0201:             *	NOTE: A DSS can be a "continuation" DSS _and_
0202:             * 	a "continued" DSS at the same time.  However,
0203:             * 	the FIRST DSS to be continued canNOT be
0204:             *	a continuation DSS.
0205:             */
0206:            private void markDssAsContinued(boolean forLob) {
0207:
0208:                if (!forLob) {
0209:                    // continuation bit defaults to '1' for lobs, so
0210:                    // we only have to switch it if we're not writing
0211:                    // lobs.
0212:                    bytes[dssLengthLocation] |= 0x80;
0213:                }
0214:
0215:                // We need to set the chaining state, but ONLY
0216:                // IF this is the FIRST DSS in the continuation
0217:                // list (only the first one has chaining state
0218:                // in it's header; the others do not).
0219:                if (!isContinuationDss)
0220:                    endDss(!forLob);
0221:
0222:            }
0223:
0224:            /**
0225:             * End DSS header by writing the length in the length location
0226:             * and setting the chain bit.  Unlike the other two endDss
0227:             * methods, this one overrides the default chaining byte
0228:             * (which is set in beginDss) with the chaining byte that
0229:             * is passed in.  NOTE: This method is only used in
0230:             * association with createDssRequest, and thus is for
0231:             * TESTING purposes only (via TestProto.java).  No calls
0232:             * should be made to this method in normal DRDA processing
0233:             * (because for normal processing, chaining must be
0234:             * determined automatically based on DSS requests).
0235:             */
0236:            protected void endDss(byte chainByte) {
0237:
0238:                // Do regular endDss processing.
0239:                endDss(true);
0240:
0241:                // Now override default chain state.
0242:                bytes[dssLengthLocation + 3] &= 0x0F; // Zero out default
0243:                bytes[dssLengthLocation + 3] |= chainByte;
0244:                previousChainByte = chainByte;
0245:
0246:            }
0247:
0248:            /**
0249:             * End DSS header by writing the length in the length location
0250:             * and setting the chain bit.
0251:             */
0252:            protected void endDss() {
0253:                endDss(true);
0254:            }
0255:
0256:            /**
0257:             * End DSS header by writing the length in the length location
0258:             * and setting the chain bit.
0259:             */
0260:            private void endDss(boolean finalizeLength) {
0261:
0262:                if (finalizeLength)
0263:                    finalizeDssLength();
0264:
0265:                if (isContinuationDss) {
0266:                    // no chaining information for this DSS; so we're done.
0267:                    isContinuationDss = false;
0268:                    return;
0269:                }
0270:
0271:                previousCorrId = correlationID;
0272:                prevHdrLocation = dssLengthLocation;
0273:                previousChainByte = DssConstants.DSSCHAIN_SAME_ID;
0274:
0275:            }
0276:
0277:            /**
0278:             * End final DDM and DSS header by writing the length in the length location
0279:             *
0280:             */
0281:            protected void endDdmAndDss() {
0282:                endDdm(); // updates last DDM object
0283:                endDss();
0284:            }
0285:
0286:            /**
0287:             * Copy Data to End
0288:             * Create a buffer and copy from the position given to the end of data
0289:             *
0290:             * Note that the position given is treated as relative to the
0291:             * current DSS, for there may be other DSS blocks (chained, presumably)
0292:             * which are sitting unwritten in the buffer. The caller doesn't
0293:             * know this, though, and works only with the current DSS.
0294:             *
0295:             * getDSSLength, copyDSSDataToEnd, and truncateDSS work together to
0296:             * provide a sub-protocol for DRDAConnThread to use in its
0297:             * implementation of the LMTBLKPRC protocol. They enable the caller
0298:             * to determine when it has written too much data into the current
0299:             * DSS, to reclaim the extra data that won't fit, and to truncate
0300:             * that extra data once it has been reclaimed and stored elsewhere.
0301:             * Note that this support only works for the current DSS. Earlier,
0302:             * chained DSS blocks cannot be accessed using these methods. For
0303:             * additional background information, the interested reader should
0304:             * investigate bugs DERBY-491 and 492 at:
0305:             * http://issues.apache.org/jira/browse/DERBY-491 and
0306:             * http://issues.apache.org/jira/browse/DERBY-492
0307:             *
0308:             * @param start
0309:             */
0310:            protected byte[] copyDSSDataToEnd(int start) {
0311:                start = start + dssLengthLocation;
0312:                int length = offset - start;
0313:                byte[] temp = new byte[length];
0314:                System.arraycopy(bytes, start, temp, 0, length);
0315:                return temp;
0316:            }
0317:
0318:            // Collection methods
0319:
0320:            /**
0321:             * Mark the location of the length bytes for the collection so they
0322:             * can be updated later
0323:             *
0324:             */
0325:            protected void startDdm(int codePoint) {
0326:                // save the location of the beginning of the collection so
0327:                // that we can come back and fill in the length bytes
0328:                markStack[top++] = offset;
0329:                ensureLength(4); // verify space for length bytes and code point
0330:                offset += 2; // move past the length bytes before writing the code point
0331:                bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
0332:                bytes[offset + 1] = (byte) (codePoint & 0xff);
0333:                offset += 2;
0334:            }
0335:
0336:            /**
0337:             * Erase all writes for the current ddm and reset the
0338:             * top
0339:             */
0340:            protected void clearDdm() {
0341:                offset = markStack[top--];
0342:            }
0343:
0344:            /**
0345:             * Clear the entire send buffer
0346:             *
0347:             */
0348:            protected void clearBuffer() {
0349:                offset = 0;
0350:                top = 0;
0351:                dssLengthLocation = 0;
0352:                correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
0353:                nextCorrelationID = 1;
0354:                isDRDAProtocol = true;
0355:            }
0356:
0357:            /**
0358:             * End the current DDM
0359:             *
0360:             */
0361:            protected void endDdm() {
0362:                // remove the top length location offset from the mark stack
0363:                // calculate the length based on the marked location and end of data.
0364:                int lengthLocation = markStack[--top];
0365:                int length = offset - lengthLocation;
0366:
0367:                // determine if any extended length bytes are needed.	the value returned
0368:                // from calculateExtendedLengthByteCount is the number of extended length
0369:                // bytes required. 0 indicates no exteneded length.
0370:                int extendedLengthByteCount = calculateExtendedLengthByteCount(length);
0371:                if (extendedLengthByteCount != 0) {
0372:                    // ensure there is enough room in the buffer for the extended length bytes.
0373:                    ensureLength(extendedLengthByteCount);
0374:
0375:                    // calculate the length to be placed in the extended length bytes.
0376:                    // this length does not include the 4 byte llcp.
0377:                    int extendedLength = length - 4;
0378:
0379:                    // shift the data to the right by the number of extended
0380:                    // length bytes needed.
0381:                    int extendedLengthLocation = lengthLocation + 4;
0382:                    System.arraycopy(bytes, extendedLengthLocation, bytes,
0383:                            extendedLengthLocation + extendedLengthByteCount,
0384:                            extendedLength);
0385:
0386:                    // write the extended length
0387:                    int shiftSize = (extendedLengthByteCount - 1) * 8;
0388:                    for (int i = 0; i < extendedLengthByteCount; i++) {
0389:                        bytes[extendedLengthLocation++] = (byte) ((extendedLength >>> shiftSize) & 0xff);
0390:                        shiftSize -= 8;
0391:                    }
0392:
0393:                    // adjust the offset to account for the shift and insert
0394:                    offset += extendedLengthByteCount;
0395:
0396:                    // the two byte length field before the codepoint contains the length
0397:                    // of itself, the length of the codepoint, and the number of bytes used
0398:                    // to hold the extended length.	the 2 byte length field also has the first
0399:                    // bit on to indicate extended length bytes were used.
0400:                    length = extendedLengthByteCount + 4;
0401:                    length |= DssConstants.CONTINUATION_BIT;
0402:                }
0403:
0404:                // write the 2 byte length field (2 bytes before codepoint).
0405:                bytes[lengthLocation] = (byte) ((length >>> 8) & 0xff);
0406:                bytes[lengthLocation + 1] = (byte) (length & 0xff);
0407:
0408:            }
0409:
0410:            /**
0411:             * Get the length of the current DSS block we're working on. This is
0412:             * used by the LMTBLKPRC protocol, which does its own conversational
0413:             * blocking protocol above the layer of the DRDA blocking. The LMTBLKPRC
0414:             * implementation (in DRDAConnThread) needs to be able to truncate a
0415:             * DSS block when splitting a QRYDTA response.
0416:             *
0417:             * @return current DSS block length
0418:             */
0419:            protected int getDSSLength() {
0420:                return offset - dssLengthLocation;
0421:            }
0422:
0423:            /**
0424:             * Truncate the current DSS. Before making this call, you should ensure
0425:             * that you have copied the data to be truncated somewhere else, by
0426:             * calling copyDSSDataToEnd
0427:             *
0428:             * @param value DSS length
0429:             */
0430:            protected void truncateDSS(int value) {
0431:                offset = dssLengthLocation + value;
0432:            }
0433:
0434:            // Write routines
0435:
0436:            /**
0437:             * Write byte
0438:             *
0439:             * @param 	value	byte to be written
0440:             */
0441:            protected void writeByte(int value) {
0442:                if (SanityManager.DEBUG) {
0443:                    if (value > 255)
0444:                        SanityManager.THROWASSERT("writeByte value: " + value
0445:                                + " may not be > 255");
0446:                }
0447:
0448:                ensureLength(1);
0449:                bytes[offset++] = (byte) (value & 0xff);
0450:            }
0451:
0452:            /**
0453:             * Write network short
0454:             *
0455:             * @param 	value	value to be written
0456:             */
0457:            protected void writeNetworkShort(int value) {
0458:                ensureLength(2);
0459:                bytes[offset] = (byte) ((value >>> 8) & 0xff);
0460:                bytes[offset + 1] = (byte) (value & 0xff);
0461:                offset += 2;
0462:            }
0463:
0464:            /**
0465:             * Write network int
0466:             *
0467:             * @param 	value	value to be written
0468:             */
0469:            protected void writeNetworkInt(int value) {
0470:                ensureLength(4);
0471:                bytes[offset] = (byte) ((value >>> 24) & 0xff);
0472:                bytes[offset + 1] = (byte) ((value >>> 16) & 0xff);
0473:                bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
0474:                bytes[offset + 3] = (byte) (value & 0xff);
0475:                offset += 4;
0476:            }
0477:
0478:            /**
0479:             * Write byte array
0480:             *
0481:             * @param 	buf	byte array to be written
0482:             * @param	length  - length to write
0483:             */
0484:            protected void writeBytes(byte[] buf, int length) {
0485:                writeBytes(buf, 0, length);
0486:            }
0487:
0488:            /**
0489:             * Write byte array
0490:             *
0491:             * @param 	buf	byte array to be written
0492:             * @param	start  - starting position
0493:             * @param	length  - length to write
0494:             */
0495:            protected void writeBytes(byte[] buf, int start, int length) {
0496:
0497:                if (SanityManager.DEBUG) {
0498:                    if (buf == null && length > 0)
0499:                        SanityManager.THROWASSERT("Buf is null");
0500:                    if (length + start - 1 > buf.length)
0501:                        SanityManager.THROWASSERT("Not enough bytes in buffer");
0502:
0503:                }
0504:                ensureLength(length);
0505:                System.arraycopy(buf, start, bytes, offset, length);
0506:                offset += length;
0507:            }
0508:
0509:            /**
0510:             * Write byte array
0511:             *
0512:             * @param 	buf	byte array to be written
0513:             **/
0514:            protected void writeBytes(byte[] buf) {
0515:                writeBytes(buf, buf.length);
0516:            }
0517:
0518:            protected void writeLDBytes(byte[] buf) {
0519:                writeLDBytes(buf, 0);
0520:            }
0521:
0522:            protected void writeLDBytes(byte[] buf, int index) {
0523:
0524:                int length = buf.length;
0525:                int writeLen = buf.length;
0526:
0527:                writeShort(writeLen);
0528:
0529:                writeBytes(buf, 0, writeLen);
0530:            }
0531:
0532:            /**
0533:             * Write code point and 4 bytes
0534:             *
0535:             * @param 	codePoint - code point to write
0536:             * @param	value  - value to write after code point
0537:             */
0538:            void writeCodePoint4Bytes(int codePoint, int value) {
0539:                ensureLength(4);
0540:                bytes[offset] = (byte) ((codePoint >>> 8) & 0xff);
0541:                bytes[offset + 1] = (byte) (codePoint & 0xff);
0542:                bytes[offset + 2] = (byte) ((value >>> 8) & 0xff);
0543:                bytes[offset + 3] = (byte) (value & 0xff);
0544:                offset += 4;
0545:            }
0546:
0547:            /**
0548:             * Write scalar 1 byte object includes length, codepoint and value
0549:             *
0550:             * @param 	codePoint - code point to write
0551:             * @param	value  - value to write after code point
0552:             */
0553:            void writeScalar1Byte(int codePoint, int value) {
0554:                ensureLength(5);
0555:                bytes[offset] = 0x00;
0556:                bytes[offset + 1] = 0x05;
0557:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0558:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0559:                bytes[offset + 4] = (byte) (value & 0xff);
0560:                offset += 5;
0561:            }
0562:
0563:            /**
0564:             * Write scalar 2 byte object includes length, codepoint and value
0565:             *
0566:             * @param 	codePoint - code point to write
0567:             * @param	value  - value to write after code point
0568:             */
0569:            protected void writeScalar2Bytes(int codePoint, int value) {
0570:                ensureLength(6);
0571:                bytes[offset] = 0x00;
0572:                bytes[offset + 1] = 0x06;
0573:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0574:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0575:                bytes[offset + 4] = (byte) ((value >>> 8) & 0xff);
0576:                bytes[offset + 5] = (byte) (value & 0xff);
0577:                offset += 6;
0578:            }
0579:
0580:            protected void writeScalar2Bytes(int value) {
0581:                ensureLength(2);
0582:                bytes[offset] = (byte) ((value >>> 8) & 0xff);
0583:                bytes[offset + 1] = (byte) (value & 0xff);
0584:                offset += 2;
0585:            }
0586:
0587:            /**
0588:             * Write length and codepoint
0589:             *
0590:             * @param 	length - length of object
0591:             * @param 	codePoint - code point to write
0592:             */
0593:            protected void startDdm(int length, int codePoint) {
0594:                ensureLength(4);
0595:                bytes[offset] = (byte) ((length >>> 8) & 0xff);
0596:                bytes[offset + 1] = (byte) (length & 0xff);
0597:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0598:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0599:                offset += 4;
0600:            }
0601:
0602:            /**
0603:             * Write scalar byte array object includes length, codepoint and value
0604:             *
0605:             * @param 	codePoint - code point to write
0606:             * @param	buf  - value to write after code point
0607:             * @param	length - number of bytes to write
0608:             */
0609:            protected void writeScalarBytes(int codePoint, byte[] buf,
0610:                    int length) {
0611:                if (SanityManager.DEBUG) {
0612:                    if (buf == null && length > 0)
0613:                        SanityManager.THROWASSERT("Buf is null");
0614:                    if (length > buf.length)
0615:                        SanityManager.THROWASSERT("Not enough bytes in buffer");
0616:                }
0617:                ensureLength(length + 4);
0618:                bytes[offset] = (byte) (((length + 4) >>> 8) & 0xff);
0619:                bytes[offset + 1] = (byte) ((length + 4) & 0xff);
0620:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0621:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0622:                System.arraycopy(buf, 0, bytes, offset + 4, length);
0623:                offset += length + 4;
0624:            }
0625:
0626:            protected void writeScalarStream(boolean chainedWithSameCorrelator,
0627:                    int codePoint, EXTDTAInputStream in, boolean writeNullByte)
0628:                    throws DRDAProtocolException {
0629:
0630:                // Stream equivalent of "beginDss"...
0631:                int spareDssLength = prepScalarStream(
0632:                        chainedWithSameCorrelator, codePoint, writeNullByte);
0633:
0634:                // write the data
0635:                int bytesRead = 0;
0636:                int totalBytesRead = 0;
0637:
0638:                try {
0639:
0640:                    OutputStream out = placeLayerBStreamingBuffer(agent
0641:                            .getOutputStream());
0642:
0643:                    boolean isLastSegment = false;
0644:
0645:                    while (!isLastSegment) {
0646:
0647:                        int spareBufferLength = bytes.length - offset;
0648:
0649:                        if (SanityManager.DEBUG) {
0650:
0651:                            if (PropertyUtil
0652:                                    .getSystemProperty("derby.debug.suicideOfLayerBStreaming") != null)
0653:                                throw new IOException();
0654:                        }
0655:
0656:                        bytesRead = in.read(bytes, offset, Math.min(
0657:                                spareDssLength, spareBufferLength));
0658:
0659:                        totalBytesRead += bytesRead;
0660:                        offset += bytesRead;
0661:                        spareDssLength -= bytesRead;
0662:                        spareBufferLength -= bytesRead;
0663:
0664:                        isLastSegment = peekStream(in) < 0;
0665:
0666:                        if (isLastSegment || spareDssLength == 0) {
0667:
0668:                            flushScalarStreamSegment(isLastSegment, out);
0669:
0670:                            if (!isLastSegment)
0671:                                spareDssLength = DssConstants.MAX_DSS_LENGTH - 2;
0672:
0673:                        }
0674:
0675:                    }
0676:
0677:                    out.flush();
0678:
0679:                } catch (IOException e) {
0680:                    agent.markCommunicationsFailure(
0681:                            "DDMWriter.writeScalarStream()", "",
0682:                            e.getMessage(), "*");
0683:                }
0684:
0685:            }
0686:
0687:            /**
0688:             * Begins a DSS stream (for writing LOB data).
0689:             */
0690:            private void beginDss(boolean chainedToNextStructure, int dssType) {
0691:                beginDss(dssType, false); // false => don't ensure length.
0692:
0693:                // always turn on continuation flags... this is helpful for lobs...
0694:                // these bytes will get rest if dss lengths are finalized.
0695:                bytes[dssLengthLocation] = (byte) 0xFF;
0696:                bytes[dssLengthLocation + 1] = (byte) 0xFF;
0697:
0698:                // Set whether or not this DSS should be chained to
0699:                // the next one.  If it's chained, it has to be chained
0700:                // with same id (that's the nature of EXTDTA chaining).
0701:                if (chainedToNextStructure) {
0702:                    dssType |= DssConstants.GDSCHAIN_SAME_ID;
0703:                }
0704:
0705:                bytes[dssLengthLocation + 3] = (byte) (dssType & 0xff);
0706:            }
0707:
0708:            /**
0709:             * prepScalarStream does the following prep for writing stream data:
0710:             * 1.  Flushes an existing DSS segment, if necessary
0711:             * 2.  Determines if extended length bytes are needed
0712:             * 3.  Creates a new DSS/DDM header and a null byte indicator, if applicable
0713:             *
0714:             * If value of length was less than 0, this method processes streaming as Layer B Streaming.
0715:             * cf. page 315 of specification of DRDA, Version 3, Volume 3 
0716:             *
0717:             */
0718:            private int prepScalarStream(boolean chainedWithSameCorrelator,
0719:                    int codePoint, boolean writeNullByte)
0720:                    throws DRDAProtocolException {
0721:
0722:                ensureLength(DEFAULT_BUFFER_SIZE - offset);
0723:
0724:                final int nullIndicatorSize = writeNullByte ? 1 : 0;
0725:
0726:                // flush the existing DSS segment ,
0727:                // if this stream will not fit in the send buffer or 
0728:                // length of this stream is unknown.
0729:                // Here, 10 stands for sum of headers of layer A and B.
0730:
0731:                try {
0732:                    // The existing DSS segment was finalized by endDss; all
0733:                    // we have to do is send it across the wire.
0734:                    sendBytes(agent.getOutputStream());
0735:                } catch (java.io.IOException e) {
0736:                    agent.markCommunicationsFailure(
0737:                            "DDMWriter.writeScalarStream()",
0738:                            "OutputStream.flush()", e.getMessage(), "*");
0739:                }
0740:
0741:                // buildStreamDss should not call ensure length.
0742:                beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
0743:
0744:                writeLengthCodePoint(0x8004, codePoint);
0745:
0746:                // write the null byte, if necessary
0747:                if (writeNullByte)
0748:                    writeByte(0x0);
0749:
0750:                //Here, 6 stands for header of layer A and 
0751:                //4 stands for header of layer B.
0752:                return DssConstants.MAX_DSS_LENGTH - 6 - 4 - nullIndicatorSize;
0753:
0754:            }
0755:
0756:            // method to determine if any data is in the request.
0757:            // this indicates there is a dss object already in the buffer.
0758:            protected boolean doesRequestContainData() {
0759:                return offset != 0;
0760:            }
0761:
0762:            // Writes out a scalar stream DSS segment, along with DSS continuation
0763:            // headers if necessary.
0764:            private void flushScalarStreamSegment(boolean lastSegment,
0765:                    OutputStream out) throws DRDAProtocolException {
0766:
0767:                // either at end of data, end of dss segment, or both.
0768:                if (!lastSegment) {
0769:
0770:                    // 32k segment filled and not at end of data.
0771:                    try {
0772:                        // Mark current DSS as continued, set its chaining state,
0773:                        // then send the data across.
0774:                        markDssAsContinued(true); // true => for lobs
0775:                        sendBytes(out, false);
0776:
0777:                    } catch (java.io.IOException ioe) {
0778:                        agent.markCommunicationsFailure(
0779:                                "DDMWriter.flushScalarStreamSegment()", "", ioe
0780:                                        .getMessage(), "*");
0781:                    }
0782:
0783:                    // Prepare a DSS continuation header for next DSS.
0784:                    dssLengthLocation = offset;
0785:                    bytes[offset++] = (byte) (0xff);
0786:                    bytes[offset++] = (byte) (0xff);
0787:                    isContinuationDss = true;
0788:                } else {
0789:                    // we're done writing the data, so end the DSS.
0790:                    endDss();
0791:
0792:                }
0793:
0794:            }
0795:
0796:            private void writeExtendedLengthBytes(int extendedLengthByteCount,
0797:                    long length) {
0798:                int shiftSize = (extendedLengthByteCount - 1) * 8;
0799:                for (int i = 0; i < extendedLengthByteCount; i++) {
0800:                    bytes[offset + i] = (byte) ((length >>> shiftSize) & 0xff);
0801:                    shiftSize -= 8;
0802:                }
0803:                offset += extendedLengthByteCount;
0804:            }
0805:
0806:            // insert a 4 byte length/codepoint pair into the buffer.
0807:            // total of 4 bytes inserted in buffer.
0808:            // Note: the length value inserted in the buffer is the same as the value
0809:            // passed in as an argument (this value is NOT incremented by 4 before being
0810:            // inserted).
0811:            void writeLengthCodePoint(int length, int codePoint) {
0812:                ensureLength(4);
0813:                bytes[offset] = (byte) ((length >>> 8) & 0xff);
0814:                bytes[offset + 1] = (byte) (length & 0xff);
0815:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0816:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0817:                offset += 4;
0818:            }
0819:
0820:            /**
0821:             * Write scalar object header includes length and codepoint
0822:             *
0823:             * @param 	codePoint - code point to write
0824:             * @param	dataLength - length of object data
0825:             */
0826:            protected void writeScalarHeader(int codePoint, int dataLength) {
0827:                ensureLength(dataLength + 4);
0828:                bytes[offset] = (byte) (((dataLength + 4) >>> 8) & 0xff);
0829:                bytes[offset + 1] = (byte) ((dataLength + 4) & 0xff);
0830:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0831:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0832:                offset += 4;
0833:            }
0834:
0835:            /**
0836:             * Write scalar string object includes length, codepoint and value
0837:             * the string is converted into the appropriate codeset (EBCDIC)
0838:             *
0839:             * @param 	codePoint - code point to write
0840:             * @param	string - string to be written
0841:             */
0842:            void writeScalarString(int codePoint, String string) {
0843:                int stringLength = string.length();
0844:                ensureLength((stringLength * 2) + 4);
0845:                bytes[offset] = (byte) (((stringLength + 4) >>> 8) & 0xff);
0846:                bytes[offset + 1] = (byte) ((stringLength + 4) & 0xff);
0847:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0848:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0849:                offset = ccsidManager
0850:                        .convertFromUCS2(string, bytes, offset + 4);
0851:            }
0852:
0853:            /**
0854:             * Write padded scalar string object includes length, codepoint and value
0855:             * the string is converted into the appropriate codeset (EBCDIC)
0856:             *
0857:             * @param 	codePoint - code point to write
0858:             * @param	string - string to be written
0859:             * @param 	paddedLength - length to pad string to
0860:             */
0861:            void writeScalarPaddedString(int codePoint, String string,
0862:                    int paddedLength) {
0863:                int stringLength = string.length();
0864:                int fillLength = paddedLength - stringLength;
0865:                ensureLength(paddedLength + 4);
0866:                bytes[offset] = (byte) (((paddedLength + 4) >>> 8) & 0xff);
0867:                bytes[offset + 1] = (byte) ((paddedLength + 4) & 0xff);
0868:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0869:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0870:                offset = ccsidManager
0871:                        .convertFromUCS2(string, bytes, offset + 4);
0872:                Arrays.fill(bytes, offset, offset + fillLength,
0873:                        ccsidManager.space);
0874:                offset += fillLength;
0875:            }
0876:
0877:            /**
0878:             * Write padded scalar string object value
0879:             * the string is converted into the appropriate codeset (EBCDIC)
0880:             *
0881:             * @param	string - string to be written
0882:             * @param 	paddedLength - length to pad string to
0883:             */
0884:            protected void writeScalarPaddedString(String string,
0885:                    int paddedLength) {
0886:                int stringLength = string.length();
0887:
0888:                int fillLength = paddedLength - stringLength;
0889:                ensureLength(paddedLength);
0890:                offset = ccsidManager.convertFromUCS2(string, bytes, offset);
0891:                Arrays.fill(bytes, offset, offset + fillLength,
0892:                        ccsidManager.space);
0893:                offset += fillLength;
0894:            }
0895:
0896:            /**
0897:             * Write padded scalar <code>DRDAString</code> object value. The
0898:             * string is converted into the appropriate codeset.
0899:             *
0900:             * @param drdaString string to be written
0901:             * @param paddedLength length to pad string to
0902:             */
0903:            protected void writeScalarPaddedString(DRDAString drdaString,
0904:                    int paddedLength) {
0905:                int stringLength = drdaString.length();
0906:                int fillLength = paddedLength - stringLength;
0907:                ensureLength(paddedLength);
0908:                System.arraycopy(drdaString.getBytes(), 0, bytes, offset,
0909:                        stringLength);
0910:                offset += stringLength;
0911:                Arrays.fill(bytes, offset, offset + fillLength,
0912:                        ccsidManager.space);
0913:                offset += fillLength;
0914:            }
0915:
0916:            /**
0917:             * Write padded scalar byte array object includes length, codepoint and value
0918:             *
0919:             * @param 	codePoint - code point to write
0920:             * @param	buf - byte array to be written
0921:             * @param 	paddedLength - length to pad string to
0922:             * @param	padByte - byte to be used for padding
0923:             */
0924:            protected void writeScalarPaddedBytes(int codePoint, byte[] buf,
0925:                    int paddedLength, byte padByte) {
0926:                int bufLength = buf.length;
0927:                ensureLength(paddedLength + 4);
0928:                bytes[offset] = (byte) (((paddedLength + 4) >>> 8) & 0xff);
0929:                bytes[offset + 1] = (byte) ((paddedLength + 4) & 0xff);
0930:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0931:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0932:                offset += 4;
0933:                System.arraycopy(buf, 0, bytes, offset, bufLength);
0934:                offset += bufLength;
0935:                int fillLength = paddedLength - bufLength;
0936:                Arrays.fill(bytes, offset, offset + fillLength, padByte);
0937:                offset += fillLength;
0938:            }
0939:
0940:            /**
0941:             * Write padded scalar byte array object  value
0942:             *
0943:             * @param	buf - byte array to be written
0944:             * @param 	paddedLength - length to pad string to
0945:             * @param	padByte - byte to be used for padding
0946:             */
0947:            protected void writeScalarPaddedBytes(byte[] buf, int paddedLength,
0948:                    byte padByte) {
0949:                int bufLength = buf.length;
0950:                int fillLength = paddedLength - bufLength;
0951:                ensureLength(paddedLength);
0952:                System.arraycopy(buf, 0, bytes, offset, bufLength);
0953:                offset += bufLength;
0954:                Arrays.fill(bytes, offset, offset + fillLength, padByte);
0955:                offset += fillLength;
0956:            }
0957:
0958:            /**
0959:             * Write scalar byte array object includes length, codepoint and value
0960:             *
0961:             * @param 	codePoint - code point to write
0962:             * @param	buf - byte array to be written
0963:             */
0964:            protected void writeScalarBytes(int codePoint, byte[] buf) {
0965:                int bufLength = buf.length;
0966:                ensureLength(bufLength + 4);
0967:                bytes[offset] = (byte) (((bufLength + 4) >>> 8) & 0xff);
0968:                bytes[offset + 1] = (byte) ((bufLength + 4) & 0xff);
0969:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0970:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0971:                System.arraycopy(buf, 0, bytes, offset + 4, bufLength);
0972:                offset += bufLength + 4;
0973:            }
0974:
0975:            /**
0976:             * Write scalar byte array object includes length, codepoint and value
0977:             *
0978:             * @param 	codePoint - code point to write
0979:             * @param	buf - byte array to be written
0980:             * @param	start - starting point
0981:             * @param 	length - length to write
0982:             */
0983:            protected void writeScalarBytes(int codePoint, byte[] buf,
0984:                    int start, int length) {
0985:                if (SanityManager.DEBUG) {
0986:                    if (buf == null && length > start)
0987:                        SanityManager.THROWASSERT("Buf is null");
0988:                    if (length - start > buf.length)
0989:                        SanityManager.THROWASSERT("Not enough bytes in buffer");
0990:                }
0991:                int numBytes = length - start;
0992:                ensureLength(numBytes + 4);
0993:                bytes[offset] = (byte) (((numBytes + 4) >>> 8) & 0xff);
0994:                bytes[offset + 1] = (byte) ((numBytes + 4) & 0xff);
0995:                bytes[offset + 2] = (byte) ((codePoint >>> 8) & 0xff);
0996:                bytes[offset + 3] = (byte) (codePoint & 0xff);
0997:                offset += 4;
0998:                System.arraycopy(buf, start, bytes, offset, numBytes);
0999:                offset += numBytes;
1000:            }
1001:
1002:            // The following methods write data in the platform format
1003:            // The platform format was indicated during connection time as ASC since
1004:            // JCC doesn't read JVM platform (yet)
1005:
1006:            /**
1007:             * Write platform short
1008:             *
1009:             * @param 	v	value to be written
1010:             */
1011:            protected void writeShort(int v) {
1012:                writeNetworkShort(v);
1013:            }
1014:
1015:            /**
1016:             * Write boolean as short
1017:             * @param b boolean value true = 1 false = 0
1018:             *
1019:             */
1020:            protected void writeShort(boolean b) {
1021:                writeNetworkShort(b ? 1 : 0);
1022:            }
1023:
1024:            /**
1025:             * Write platform int
1026:             *
1027:             * @param 	v	value to be written
1028:             */
1029:            protected void writeInt(int v) {
1030:                writeNetworkInt(v);
1031:            }
1032:
1033:            /**
1034:             * Write platform long
1035:             *
1036:             * @param 	v	value to be written
1037:             */
1038:            protected void writeLong(long v) {
1039:                ensureLength(8);
1040:                bytes[offset] = (byte) ((v >>> 56) & 0xff);
1041:                bytes[offset + 1] = (byte) ((v >>> 48) & 0xff);
1042:                bytes[offset + 2] = (byte) ((v >>> 40) & 0xff);
1043:                bytes[offset + 3] = (byte) ((v >>> 32) & 0xff);
1044:                bytes[offset + 4] = (byte) ((v >>> 24) & 0xff);
1045:                bytes[offset + 5] = (byte) ((v >>> 16) & 0xff);
1046:                bytes[offset + 6] = (byte) ((v >>> 8) & 0xff);
1047:                bytes[offset + 7] = (byte) ((v >>> 0) & 0xff);
1048:                offset += 8;
1049:            }
1050:
1051:            /**
1052:             * Write platform float
1053:             *
1054:             * @param 	v	value to be written
1055:             */
1056:            protected void writeFloat(float v) {
1057:                writeInt(Float.floatToIntBits(v));
1058:            }
1059:
1060:            /**
1061:             * Write platform double
1062:             *
1063:             * @param 	v	value to be written
1064:             */
1065:            protected void writeDouble(double v) {
1066:                writeLong(Double.doubleToLongBits(v));
1067:            }
1068:
1069:            /**
1070:             * Write big decimal to buffer
1071:             *
1072:             * @param v value to write
1073:             * @param precision Precison of decimal or numeric type
1074:             * @param scale declared scale
1075:             * @exception SQLException thrown if number of digits > 31
1076:             */
1077:            protected void writeBigDecimal(java.math.BigDecimal v,
1078:                    int precision, int scale) throws SQLException {
1079:                int length = precision / 2 + 1;
1080:                ensureLength(offset + length);
1081:                bigDecimalToPackedDecimalBytes(v, precision, scale);
1082:                offset += length;
1083:            }
1084:
1085:            /**
1086:             * Write platform boolean
1087:             *
1088:             * @param 	v	value to be written
1089:             */
1090:            protected void writeBoolean(boolean v) {
1091:                ensureLength(1);
1092:                bytes[offset++] = (byte) ((v ? 1 : 0) & 0xff);
1093:            }
1094:
1095:            /**
1096:             * Write length delimited string
1097:             *
1098:             * @param s value to be written with integer
1099:             *
1100:             * @exception DRDAProtocolException
1101:             */
1102:            protected void writeLDString(String s) throws DRDAProtocolException {
1103:                writeLDString(s, 0);
1104:            }
1105:
1106:            /**
1107:             * Write length delimited string
1108:             *
1109:             * @param s              value to be written with integer
1110:             * @param index          column index to put in warning
1111:             * @exception DRDAProtocolException
1112:             */
1113:            protected void writeLDString(String s, int index)
1114:                    throws DRDAProtocolException {
1115:                try {
1116:                    byte[] byteval = s
1117:                            .getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
1118:                    int origLen = byteval.length;
1119:                    boolean multiByteTrunc = false;
1120:                    int writeLen = java.lang.Math.min(
1121:                            FdocaConstants.LONGVARCHAR_MAX_LEN, origLen);
1122:                    /*
1123:                    Need to make sure we truncate on character boundaries.
1124:                    We are assuming
1125:                    http://www.sun.com/developers/gadc/technicalpublications/articles/utf8.html
1126:                    To find the beginning of a multibyte character:
1127:                    1) Does the current byte start with the bit pattern 10xxxxxx?
1128:                    2) If yes, move left and go to step #1.
1129:                    3) Finished
1130:                    We assume that NetworkServerControlImpl.DEFAULT_ENCODING remains UTF-8
1131:                     */
1132:
1133:                    if (SanityManager.DEBUG) {
1134:                        if (!(NetworkServerControlImpl.DEFAULT_ENCODING
1135:                                .equals("UTF8")))
1136:                            SanityManager
1137:                                    .THROWASSERT("Encoding assumed to be UTF8, but is actually"
1138:                                            + NetworkServerControlImpl.DEFAULT_ENCODING);
1139:                    }
1140:
1141:                    if (writeLen != origLen)
1142:                        // first position on the first byte of the multibyte char
1143:                        while ((byteval[writeLen - 1] & 0xC0) == 0x80) {
1144:                            multiByteTrunc = true;
1145:                            writeLen--;
1146:                            // Then subtract one more to get to the end of the
1147:                            // previous character
1148:                            if (multiByteTrunc == true) {
1149:                                writeLen = writeLen - 1;
1150:                            }
1151:                        }
1152:
1153:                    writeShort(writeLen);
1154:                    writeBytes(byteval, writeLen);
1155:                } catch (Exception e) {
1156:                    //this should never happen
1157:                    agent.agentError("Encoding "
1158:                            + NetworkServerControlImpl.DEFAULT_ENCODING
1159:                            + " not supported");
1160:                }
1161:            }
1162:
1163:            /**
1164:             * Write string with default encoding
1165:             *
1166:             * @param s value to be written
1167:             *
1168:             * @exception DRDAProtocolException
1169:             */
1170:            protected void writeString(String s) throws DRDAProtocolException {
1171:                try {
1172:                    writeBytes(s
1173:                            .getBytes(NetworkServerControlImpl.DEFAULT_ENCODING));
1174:                } catch (Exception e) {
1175:                    //this should never happen
1176:                    agent.agentError("Encoding "
1177:                            + NetworkServerControlImpl.DEFAULT_ENCODING
1178:                            + " not supported");
1179:                }
1180:            }
1181:
1182:            /**
1183:             * Write string with default encoding and specified length
1184:             *
1185:             * @param s value to be written
1186:             * @param length number of bytes to be written
1187:             *
1188:             * @exception DRDAProtocolException
1189:             */
1190:            protected void writeString(String s, int length)
1191:                    throws DRDAProtocolException {
1192:                byte[] bs = null;
1193:                try {
1194:                    bs = s.getBytes(NetworkServerControlImpl.DEFAULT_ENCODING);
1195:                } catch (Exception e) {
1196:                    //this should never happen
1197:                    agent.agentError("Encoding "
1198:                            + NetworkServerControlImpl.DEFAULT_ENCODING
1199:                            + " not supported");
1200:                }
1201:                int len = bs.length;
1202:                if (len >= length)
1203:                    writeBytes(bs, length);
1204:                else {
1205:                    writeBytes(bs);
1206:                    padBytes(NetworkServerControlImpl.SPACE_CHAR, length - len);
1207:                }
1208:            }
1209:
1210:            /**
1211:             * Write pad bytes using spaceChar
1212:             *
1213:             * @param   val	value to be written
1214:             * @param	length		length to be written
1215:             */
1216:            protected void padBytes(byte val, int length) {
1217:                Arrays.fill(bytes, offset, offset + length, val);
1218:                offset += length;
1219:            }
1220:
1221:            /**
1222:             * Flush buffer to outputstream
1223:             *
1224:             *
1225:             * @exception IOException
1226:             */
1227:            protected void flush() throws java.io.IOException {
1228:                flush(agent.getOutputStream());
1229:            }
1230:
1231:            /**
1232:             * Flush buffer to specified stream
1233:             *
1234:             * @param socketOutputStream
1235:             *
1236:             * @exception IOException
1237:             */
1238:            protected void flush(OutputStream socketOutputStream)
1239:                    throws java.io.IOException {
1240:                try {
1241:                    socketOutputStream.write(bytes, 0, offset);
1242:                    socketOutputStream.flush();
1243:                } finally {
1244:                    if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
1245:                        dssTrace.writeComBufferData(bytes, 0, offset,
1246:                                DssTrace.TYPE_TRACE_SEND, "Reply", "flush", 5);
1247:                    }
1248:                    reset(dssTrace);
1249:                }
1250:            }
1251:
1252:            // private methods
1253:
1254:            /**
1255:             * Write DSS header
1256:             * DSS Header format is
1257:             * 	2 bytes	- length
1258:             *	1 byte	- 'D0'	- indicates DDM data
1259:             * 	1 byte	- DSS format
1260:             *		|---|---------|----------|
1261:             *		| 0	|	flags |	type     |
1262:             *		|---|---------|----------|
1263:             *		| 0 | 1	2	3 | 4 5 6 7	 |
1264:             *		|---|---------|----------|
1265:             *		bit 0 - '0'
1266:             *		bit 1 - '0' - unchained, '1' - chained
1267:             *		bit 2 - '0'	- do not continue on error, '1' - continue on error
1268:             *		bit 3 - '0' - next DSS has different correlator, '1' - next DSS has
1269:             *						same correlator
1270:             *		type - 1 - Request DSS
1271:             *			 - 2 - Reply DSS
1272:             *			 - 3 - Object DSS
1273:             *			 - 4 - Communications DSS
1274:             *			 - 5 - Request DSS where no reply is expected
1275:             */
1276:            private void beginDss(int dssType, boolean ensureLen) {
1277:
1278:                // save length position, the length will be written at the end
1279:                dssLengthLocation = offset;
1280:
1281:                // Should this really only be for non-stream DSSes?
1282:                if (ensureLen)
1283:                    ensureLength(6);
1284:
1285:                // Skip past length; we'll come back and set it later.
1286:                offset += 2;
1287:
1288:                // write gds info
1289:                bytes[offset] = (byte) 0xD0;
1290:
1291:                // Write DSS type, and default chain bit to be 
1292:                // DssConstants.DSSCHAIN_SAME_ID.  This default
1293:                // will be overridden by calls to "finalizeChain()"
1294:                // and/or calls to "beginDss(boolean, int)" for
1295:                // writing LOB data.
1296:                bytes[offset + 1] = (byte) dssType;
1297:                bytes[offset + 1] |= DssConstants.DSSCHAIN_SAME_ID;
1298:
1299:                // save correlationID for use in error messages while processing
1300:                // this DSS
1301:                correlationID = getCorrelationID();
1302:
1303:                // write the reply correlation id
1304:                bytes[offset + 2] = (byte) ((correlationID >>> 8) & 0xff);
1305:                bytes[offset + 3] = (byte) (correlationID & 0xff);
1306:                offset += 4;
1307:            }
1308:
1309:            /**
1310:             * Finish a DSS Layer A object.
1311:             * The length of dss object will be calculated based on the difference between the
1312:             * start of the dss, saved on the beginDss call, and the current
1313:             * offset into the buffer which marks the end of the data.	In the event
1314:             * the length requires the use of continuation Dss headers, one for each 32k
1315:             * chunk of data, the data will be shifted and the continuation headers
1316:             * will be inserted with the correct values as needed.
1317:             */
1318:            private void finalizeDssLength() {
1319:                // calculate the total size of the dss and the number of bytes which would
1320:                // require continuation dss headers.	The total length already includes the
1321:                // the 6 byte dss header located at the beginning of the dss.	It does not
1322:                // include the length of any continuation headers.
1323:                int totalSize = offset - dssLengthLocation;
1324:                int bytesRequiringContDssHeader = totalSize
1325:                        - DssConstants.MAX_DSS_LENGTH;
1326:
1327:                // determine if continuation headers are needed
1328:                if (bytesRequiringContDssHeader > 0) {
1329:                    // the continuation headers are needed, so calculate how many.
1330:                    // after the first 32767 worth of data, a continuation header is
1331:                    // needed for every 32765 bytes (32765 bytes of data + 2 bytes of
1332:                    // continuation header = 32767 Dss Max Size).
1333:                    int contDssHeaderCount = bytesRequiringContDssHeader / 32765;
1334:                    if (bytesRequiringContDssHeader % 32765 != 0)
1335:                        contDssHeaderCount++;
1336:
1337:                    // right now the code will shift to the right.	In the future we may want
1338:                    // to try something fancier to help reduce the copying (maybe keep
1339:                    // space in the beginning of the buffer??).
1340:                    // the offset points to the next available offset in the buffer to place
1341:                    // a piece of data, so the last dataByte is at offset -1.
1342:                    // various bytes will need to be shifted by different amounts
1343:                    // depending on how many dss headers to insert so the amount to shift
1344:                    // will be calculated and adjusted as needed.	ensure there is enough room
1345:                    // for all the conutinuation headers and adjust the offset to point to the
1346:                    // new end of the data.
1347:                    int dataByte = offset - 1;
1348:                    int shiftSize = contDssHeaderCount * 2;
1349:                    ensureLength(shiftSize);
1350:                    offset += shiftSize;
1351:
1352:                    // Notes on the behavior of the Layer B segmenting loop below:
1353:                    //
1354:                    // We start with the right most chunk. For a 3-segment object we'd
1355:                    // shift 2 segments: shift the first (rightmost) one 4 bytes and 
1356:                    // the second one 2. Note that by 'first' we mean 'first time
1357:                    // through the loop', but that is actually the last segment
1358:                    // of data since we are moving right-to-left. For an object
1359:                    // of K segments we will pass through this loop K-1 times.
1360:                    // The 0th (leftmost) segment is not shifted, as it is
1361:                    // already in the right place. When we are done, we will
1362:                    // have made room in each segment for an additional
1363:                    // 2 bytes for the continuation header. Thus, each
1364:                    // segment K is shifted K*2 bytes to the right.
1365:                    //
1366:                    // Each time through the loop, "dataByte" points to the
1367:                    // last byte in the segment; "dataToShift" is the amount of
1368:                    // data that we need to shift, and "shiftSize" is the
1369:                    // distance that we need to shift it. Since dataByte points
1370:                    // at the last byte, not one byte beyond it (as with the
1371:                    // "offset" variable used elsewhere in DDMWriter), the start
1372:                    // of the segement is actually at (dataByte-dataToShift+1).
1373:                    //
1374:                    // After we have shifted the segment, we move back to the
1375:                    // start of the segment and set the value of the 2-byte DSS
1376:                    // continuation header, which needs to hold the length of
1377:                    // this segment's data, together with the continuation flag
1378:                    // if this is not the rightmost (passOne) segment.
1379:                    //
1380:                    // In general, each segment except the rightmost will contain
1381:                    // 32765 bytes of data, plus the 2-byte header, and its
1382:                    // continuation flag will be set, so the header value will
1383:                    // be 0xFFFF. The rightmost segment will not have the
1384:                    // continuation flag set, so its value may be anything from
1385:                    // 0x0001 to 0x7FFF, depending on the amount of data in that
1386:                    // segment.
1387:                    //
1388:                    // Note that the 0th (leftmost) segment also has a 2-byte
1389:                    // DSS header, which needs to have its continuation flag set.
1390:                    // This is done by resetting the "totalSize" variable below,
1391:                    // at which point that variable no longer holds the total size
1392:                    // of the object, but rather just the length of segment 0. The
1393:                    // total size of the object was written using extended length
1394:                    // bytes by the endDdm() method earlier.
1395:                    //
1396:                    // Additional information about this routine is available in the
1397:                    // bug notes for DERBY-125:
1398:                    // http://issues.apache.org/jira/browse/DERBY-125
1399:
1400:                    // mark passOne to help with calculating the length of the final (first or
1401:                    // rightmost) continuation header.
1402:                    boolean passOne = true;
1403:                    do {
1404:                        // calculate chunk of data to shift
1405:                        int dataToShift = bytesRequiringContDssHeader % 32765;
1406:                        if (dataToShift == 0)
1407:                            dataToShift = 32765;
1408:                        int startOfCopyData = dataByte - dataToShift + 1;
1409:                        System.arraycopy(bytes, startOfCopyData, bytes,
1410:                                startOfCopyData + shiftSize, dataToShift);
1411:                        dataByte -= dataToShift;
1412:
1413:                        // calculate the value the value of the 2 byte continuation dss
1414:                        // header which includes the length of itself.  On the first pass,
1415:                        // if the length is 32767
1416:                        // we do not want to set the continuation dss header flag.
1417:                        int twoByteContDssHeader = dataToShift + 2;
1418:                        if (passOne)
1419:                            passOne = false;
1420:                        else {
1421:                            if (twoByteContDssHeader == DssConstants.MAX_DSS_LENGTH)
1422:                                twoByteContDssHeader = (twoByteContDssHeader | DssConstants.CONTINUATION_BIT);
1423:
1424:                        }
1425:
1426:                        // insert the header's length bytes
1427:                        bytes[dataByte + shiftSize - 1] = (byte) ((twoByteContDssHeader >>> 8) & 0xff);
1428:                        bytes[dataByte + shiftSize] = (byte) (twoByteContDssHeader & 0xff);
1429:
1430:                        // adjust the bytesRequiringContDssHeader and the amount to shift for
1431:                        // data in upstream headers.
1432:                        bytesRequiringContDssHeader -= dataToShift;
1433:                        shiftSize -= 2;
1434:
1435:                        // shift and insert another header for more data.
1436:                    } while (bytesRequiringContDssHeader > 0);
1437:
1438:                    // set the continuation dss header flag on for the first header
1439:                    totalSize = (DssConstants.MAX_DSS_LENGTH | DssConstants.CONTINUATION_BIT);
1440:
1441:                }
1442:
1443:                // insert the length bytes in the 6 byte dss header.
1444:                bytes[dssLengthLocation] = (byte) ((totalSize >>> 8) & 0xff);
1445:                bytes[dssLengthLocation + 1] = (byte) (totalSize & 0xff);
1446:            }
1447:
1448:            protected void writeExtendedLength(long size) {
1449:                int numbytes = calculateExtendedLengthByteCount(size);
1450:                if (size > 0)
1451:                    writeInt(0x8000 | numbytes);
1452:                else
1453:                    writeInt(numbytes);
1454:            }
1455:
1456:            /**
1457:             * Calculate extended length byte count which follows the DSS header
1458:             * for extended DDM.
1459:             *
1460:             * @param ddmSize - size of DDM command
1461:             * @return minimum number of extended length bytes needed. 0 indicates no
1462:             * 	extended length needed.
1463:             */
1464:            private int calculateExtendedLengthByteCount(long ddmSize) {
1465:                if (ddmSize <= 0x7fff)
1466:                    return 0;
1467:                // JCC does not support 2 at this time, so we always send
1468:                // at least 4
1469:                //		else if (ddmSize <= 0xffff)
1470:                //	return 2;
1471:                else if (ddmSize <= 0xffffffffL)
1472:                    return 4;
1473:                else if (ddmSize <= 0xffffffffffffL)
1474:                    return 6;
1475:                else if (ddmSize <= 0x7fffffffffffffffL)
1476:                    return 8;
1477:                else
1478:                    // shouldn't happen
1479:                    // XXX - add sanity debug stuff here
1480:                    return 0;
1481:            }
1482:
1483:            /**
1484:             * Ensure that there is space in the buffer
1485:             *
1486:             * @param length space required
1487:             */
1488:            private void ensureLength(int length) {
1489:                length += offset;
1490:                if (length > bytes.length) {
1491:                    if (SanityManager.DEBUG) {
1492:                        agent.trace("DANGER - Expensive expansion of  buffer");
1493:                    }
1494:                    byte newBytes[] = new byte[Math.max(bytes.length << 1,
1495:                            length)];
1496:                    System.arraycopy(bytes, 0, newBytes, 0, offset);
1497:                    bytes = newBytes;
1498:                }
1499:            }
1500:
1501:            /**
1502:             * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.
1503:             *
1504:             * @param b BigDecimal to write
1505:             * @param precision Precision of decimal or numeric type
1506:             * @return length written.
1507:             *
1508:             * @exception SQLException Thrown if # digits > 31
1509:             */
1510:            private int bigDecimalToPackedDecimalBytes(java.math.BigDecimal b,
1511:                    int precision, int scale) throws SQLException {
1512:                int declaredPrecision = precision;
1513:                int declaredScale = scale;
1514:
1515:                // packed decimal may only be up to 31 digits.
1516:                if (declaredPrecision > 31) // this is a bugcheck only !!!
1517:                {
1518:                    clearDdm();
1519:                    throw new java.sql.SQLException(
1520:                            "Packed decimal may only be up to 31 digits!");
1521:                }
1522:
1523:                // get absolute unscaled value of the BigDecimal as a String.
1524:                String unscaledStr = b.unscaledValue().abs().toString();
1525:
1526:                // get precision of the BigDecimal.
1527:                int bigPrecision = unscaledStr.length();
1528:
1529:                if (bigPrecision > 31) {
1530:                    clearDdm();
1531:                    throw new SQLException(
1532:                            "The numeric literal \""
1533:                                    + b.toString()
1534:                                    + "\" is not valid because its value is out of range.",
1535:                            "42820", -405);
1536:                }
1537:                int bigScale = b.scale();
1538:                int bigWholeIntegerLength = bigPrecision - bigScale;
1539:                if ((bigWholeIntegerLength > 0) && (!unscaledStr.equals("0"))) {
1540:                    // if whole integer part exists, check if overflow.
1541:                    int declaredWholeIntegerLength = declaredPrecision
1542:                            - declaredScale;
1543:                    if (bigWholeIntegerLength > declaredWholeIntegerLength) {
1544:                        clearDdm();
1545:                        throw new SQLException(
1546:                                "Overflow occurred during numeric data type conversion of \""
1547:                                        + b.toString() + "\".", "22003", -413);
1548:                    }
1549:                }
1550:
1551:                // convert the unscaled value to a packed decimal bytes.
1552:
1553:                // get unicode '0' value.
1554:                int zeroBase = '0';
1555:
1556:                // start index in target packed decimal.
1557:                int packedIndex = declaredPrecision - 1;
1558:
1559:                // start index in source big decimal.
1560:                int bigIndex;
1561:
1562:                if (bigScale >= declaredScale) {
1563:                    // If target scale is less than source scale,
1564:                    // discard excessive fraction.
1565:
1566:                    // set start index in source big decimal to ignore excessive fraction.
1567:                    bigIndex = bigPrecision - 1 - (bigScale - declaredScale);
1568:
1569:                    if (bigIndex < 0) {
1570:                        // all digits are discarded, so only process the sign nybble.
1571:                        bytes[offset + (packedIndex + 1) / 2] = (byte) ((b
1572:                                .signum() >= 0) ? 12 : 13); // sign nybble
1573:                    } else {
1574:                        // process the last nybble together with the sign nybble.
1575:                        bytes[offset + (packedIndex + 1) / 2] = (byte) (((unscaledStr
1576:                                .charAt(bigIndex) - zeroBase) << 4) + // last nybble
1577:                        ((b.signum() >= 0) ? 12 : 13)); // sign nybble
1578:                    }
1579:                    packedIndex -= 2;
1580:                    bigIndex -= 2;
1581:                } else {
1582:                    // If target scale is greater than source scale,
1583:                    // pad the fraction with zero.
1584:
1585:                    // set start index in source big decimal to pad fraction with zero.
1586:                    bigIndex = declaredScale - bigScale - 1;
1587:
1588:                    // process the sign nybble.
1589:                    bytes[offset + (packedIndex + 1) / 2] = (byte) ((b.signum() >= 0) ? 12
1590:                            : 13); // sign nybble
1591:
1592:                    for (packedIndex -= 2, bigIndex -= 2; bigIndex >= 0; packedIndex -= 2, bigIndex -= 2)
1593:                        bytes[offset + (packedIndex + 1) / 2] = (byte) 0;
1594:
1595:                    if (bigIndex == -1) {
1596:                        bytes[offset + (packedIndex + 1) / 2] = (byte) ((unscaledStr
1597:                                .charAt(bigPrecision - 1) - zeroBase) << 4); // high nybble
1598:
1599:                        packedIndex -= 2;
1600:                        bigIndex = bigPrecision - 3;
1601:                    } else {
1602:                        bigIndex = bigPrecision - 2;
1603:                    }
1604:                }
1605:
1606:                // process the rest.
1607:                for (; bigIndex >= 0; packedIndex -= 2, bigIndex -= 2) {
1608:                    bytes[offset + (packedIndex + 1) / 2] = (byte) (((unscaledStr
1609:                            .charAt(bigIndex) - zeroBase) << 4) + // high nybble
1610:                    (unscaledStr.charAt(bigIndex + 1) - zeroBase)); // low nybble
1611:                }
1612:
1613:                // process the first nybble when there is one left.
1614:                if (bigIndex == -1) {
1615:                    bytes[offset + (packedIndex + 1) / 2] = (byte) (unscaledStr
1616:                            .charAt(0) - zeroBase);
1617:
1618:                    packedIndex -= 2;
1619:                }
1620:
1621:                // pad zero in front of the big decimal if necessary.
1622:                for (; packedIndex >= -1; packedIndex -= 2)
1623:                    bytes[offset + (packedIndex + 1) / 2] = (byte) 0;
1624:
1625:                return declaredPrecision / 2 + 1;
1626:            }
1627:
1628:            /***
1629:             * Prepend zeros to numeric string
1630:             *
1631:             * @param s string
1632:             * @param precision - length of padded string
1633:             *
1634:             * @return zero padded string
1635:             */
1636:            public static String zeroPadString(String s, int precision) {
1637:
1638:                if (s == null)
1639:                    return s;
1640:
1641:                int slen = s.length();
1642:                if (precision == slen)
1643:                    return s;
1644:                else if (precision > slen) {
1645:                    char[] ca = new char[precision - slen];
1646:                    Arrays.fill(ca, 0, precision - slen, '0');
1647:                    return new String(ca) + s;
1648:                } else {
1649:                    // Shouldn't happen but just in case 
1650:                    // truncate
1651:                    return s.substring(0, precision);
1652:                }
1653:
1654:            }
1655:
1656:            private void sendBytes(java.io.OutputStream socketOutputStream)
1657:                    throws java.io.IOException {
1658:
1659:                sendBytes(socketOutputStream, true);
1660:
1661:            }
1662:
1663:            private void sendBytes(java.io.OutputStream socketOutputStream,
1664:                    boolean flashStream) throws java.io.IOException {
1665:                resetChainState();
1666:                try {
1667:                    socketOutputStream.write(bytes, 0, offset);
1668:                    if (flashStream)
1669:                        socketOutputStream.flush();
1670:                } finally {
1671:                    if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {
1672:                        dssTrace.writeComBufferData(bytes, 0, offset,
1673:                                DssTrace.TYPE_TRACE_SEND, "Reply", "flush", 5);
1674:                    }
1675:                    clearBuffer();
1676:                }
1677:            }
1678:
1679:            protected String toDebugString(String indent) {
1680:                String s = indent + "***** DDMWriter toDebugString ******\n";
1681:                int byteslen = 0;
1682:                if (bytes != null)
1683:                    byteslen = bytes.length;
1684:                s += indent + "byte array length  = " + bytes.length + "\n";
1685:                return s;
1686:            }
1687:
1688:            /**
1689:             * Reset any chaining state that needs to be reset
1690:             * at time of the send
1691:             */
1692:            protected void resetChainState() {
1693:                prevHdrLocation = -1;
1694:            }
1695:
1696:            /**
1697:             * Looks at chaining info for previous DSS written, and use
1698:             * that to figure out what the correlation id for the current
1699:             * DSS should be.  Return that correlation id.
1700:             */
1701:            private int getCorrelationID() {
1702:
1703:                int cId;
1704:                if (previousCorrId != DssConstants.CORRELATION_ID_UNKNOWN) {
1705:                    if (previousChainByte == DssConstants.DSSCHAIN_SAME_ID)
1706:                        // then we have to use the last correlation id we sent.
1707:                        cId = previousCorrId;
1708:                    else
1709:                        // get correlation id as normal.
1710:                        cId = nextCorrelationID++;
1711:                } else {
1712:                    // must be the case that this is the first DSS we're
1713:                    // writing for this connection (because we haven't
1714:                    // called "endDss" yet).  So, get the corr id as
1715:                    // normal.
1716:                    cId = nextCorrelationID++;
1717:                }
1718:
1719:                return cId;
1720:
1721:            }
1722:
1723:            /**
1724:             * Finalize the current DSS chain and send it if
1725:             * needed.
1726:             *
1727:             * Updates the chaining state of the most recently-written-
1728:             * to-buffer DSS to correspond to the most recently-read-
1729:             * from-client request.  If that chaining state indicates
1730:             * we've reached the end of a chain, then we go ahead
1731:             * and send the buffer across the wire.
1732:             * @param socketOutputStream Output stream to which we're flushing.
1733:             */
1734:            protected void finalizeChain(byte currChainByte,
1735:                    OutputStream socketOutputStream)
1736:                    throws DRDAProtocolException {
1737:
1738:                // Go back to previous DSS and override the default
1739:                // chain state (WITH_SAME_ID) with whatever the last
1740:                // request dictates.
1741:
1742:                if (prevHdrLocation != -1) {
1743:                    // Note: == -1 => the previous DSS was already sent; this
1744:                    // should only happen in cases where the buffer filled up
1745:                    // and we had to send it (which means we were probably
1746:                    // writing EXTDTA).  In such cases, proper chaining
1747:                    // should already have been handled @ time of send.
1748:                    bytes[prevHdrLocation + 3] &= 0x0F; // Zero out old chain value.
1749:                    bytes[prevHdrLocation + 3] |= currChainByte;
1750:                }
1751:
1752:                // previousChainByte needs to match what we just did.
1753:                previousChainByte = currChainByte;
1754:
1755:                if (currChainByte != DssConstants.DSS_NOCHAIN)
1756:                    // then we're still inside a chain, so don't send.
1757:                    return;
1758:
1759:                // Else, we just ended the chain, so send it across.
1760:
1761:                if ((SanityManager.DEBUG) && (agent != null))
1762:                    agent.trace("Sending data");
1763:
1764:                resetChainState();
1765:                if (doesRequestContainData()) {
1766:                    try {
1767:                        flush(socketOutputStream);
1768:                    } catch (java.io.IOException e) {
1769:                        agent.markCommunicationsFailure(
1770:                                "DDMWriter.finalizeChain()",
1771:                                "OutputStream.flush()", e.getMessage(), "*");
1772:                    }
1773:                }
1774:
1775:            }
1776:
1777:            /**
1778:             * Takes note of the location of the most recently completed
1779:             * DSS in the buffer, and then returns the current offset.
1780:             * This method is used in conjunction with "clearDSSesBackToMark"
1781:             * to allow for DRDAConnThread to "back-out" DSSes in the
1782:             * event of errors.
1783:             */
1784:            protected int markDSSClearPoint() {
1785:
1786:                lastDSSBeforeMark = prevHdrLocation;
1787:                return offset;
1788:
1789:            }
1790:
1791:            /**
1792:             * Does a logical "clear" of everything written to the buffer after
1793:             * the received mark.  It's assumed that this method will be used
1794:             * in error cases when we've started writing one or more DSSes,
1795:             * but then hit an error and need to back out.  After backing out,
1796:             * we'll always need to write _something_ back to the client to
1797:             * indicate an error (typically, we just write an SQLCARD) but what
1798:             * exactly gets written is handled in DRDAConnThread.  Here, we
1799:             * just do the necessary prep so that whatever comes next will
1800:             * succeed.
1801:             */
1802:            protected void clearDSSesBackToMark(int mark) {
1803:
1804:                // Logical clear.
1805:                offset = mark;
1806:
1807:                // Because we've just cleared out the most recently-
1808:                // written DSSes, we have to make sure the next thing
1809:                // we write will have the correct correlation id.  We
1810:                // do this by setting the value of 'nextCorrelationID'
1811:                // based on the chaining byte from the last remaining
1812:                // DSS (where "remaining" means that it still exists
1813:                // in the buffer after the clear).
1814:                if (lastDSSBeforeMark == -1)
1815:                    // we cleared out the entire buffer; reset corr id.
1816:                    nextCorrelationID = 1;
1817:                else {
1818:                    // last remaining DSS had chaining, so we set "nextCorrelationID"
1819:                    // to be 1 greater than whatever the last remaining DSS had as
1820:                    // its correlation id.
1821:                    nextCorrelationID = 1 + (int) (((bytes[lastDSSBeforeMark + 4] & 0xff) << 8) + (bytes[lastDSSBeforeMark + 5] & 0xff));
1822:                }
1823:
1824:            }
1825:
1826:            private static int peekStream(InputStream in) throws IOException {
1827:
1828:                in.mark(1);
1829:
1830:                try {
1831:                    return in.read();
1832:
1833:                } finally {
1834:                    in.reset();
1835:
1836:                }
1837:            }
1838:
1839:            private static int getLayerBStreamingBufferSize() {
1840:                return PropertyUtil.getSystemInt(
1841:                        Property.DRDA_PROP_STREAMOUTBUFFERSIZE, 0);
1842:            }
1843:
1844:            private static OutputStream placeLayerBStreamingBuffer(
1845:                    OutputStream original) {
1846:
1847:                int size = getLayerBStreamingBufferSize();
1848:
1849:                if (size < 1)
1850:                    return original;
1851:                else
1852:                    return new BufferedOutputStream(original, size);
1853:
1854:            }
1855:
1856:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.