Source Code Cross Referenced for RewindableInputStream.java in  » GIS » GeoServer » org » geoserver » ows » util » 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 » GIS » GeoServer » org.geoserver.ows.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //
002:        // Borrowed from org.apache.xerces.impl.XMLEntityManager,
003:        // slightly modified and commented out. -AK
004:        //
005:        // This class wraps the byte inputstreams we're presented with.
006:        // We need it because java.io.InputStreams don't provide
007:        // functionality to reread processed bytes, and they have a habit
008:        // of reading more than one character when you call their read()
009:        // methods.  This means that, once we discover the true (declared)
010:        // encoding of a document, we can neither backtrack to read the
011:        // whole doc again nor start reading where we are with a new
012:        // reader.
013:        //
014:        // This class allows rewinding an inputStream by allowing a mark
015:        // to be set, and the stream reset to that position.  <strong>The
016:        // class assumes that it needs to read one character per
017:        // invocation when it's read() method is inovked, but uses the
018:        // underlying InputStream's read(char[], offset length) method--it
019:        // won't buffer data read this way!</strong>
020:        //
021:        // @task TODO: How about implementing an ability to completely
022:        //             disable buffering performed by this stream?
023:        //             It is very unlikely that someone will read data from
024:        //             the stream byte by byte with <code>read()</code>
025:        //             method, but if they do, the whole content will
026:        //             be unconditionally stored in internal buffer, resulting
027:        //             in additional (and most probably vain) memory impact.
028:        //
029:        // @author Neil Graham, IBM
030:        // @author Glenn Marcy, IBM
031:        //
032:        package org.geoserver.ows.util;
033:
034:        import java.io.IOException;
035:        import java.io.InputStream;
036:
037:        public class RewindableInputStream extends InputStream {
038:            /**
039:             * Default buffer size before we've finished with the XMLDecl:
040:             * I think the name should be left unchanged to give a hint for
041:             * possible use of this class :)
042:             */
043:            public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64;
044:
045:            /**
046:             * Tells whether <code>read(byte[], int, int)</code> method
047:             * is allowed to read multiple bytes beyond the internal buffer
048:             * (<code>true</code>) or not (<code>true</code> is the default)
049:             */
050:            protected boolean fMayReadChunks;
051:
052:            /**
053:             * Source input stream we are wrapping with rewindable one.
054:             */
055:            protected InputStream fInputStream;
056:
057:            /**
058:             * Internal buffer of bytes already read from source input stream.
059:             * Allows to access the same byte more than once.
060:             */
061:            protected byte[] fData;
062:
063:            /**
064:             * Position in the stream that to which stream pointer can be reset
065:             * with <code>rewind</code> method invocation.
066:             */
067:            protected int fStartOffset;
068:
069:            /**
070:             * Position where the end of underlying stream was encountered. Potentially
071:             * in <code>RewindableInputStream</code> instance stream's "end" could be
072:             * reached more than once, so it is a good thing to know where original
073:             * stream ended to avoid <code>IOExceptions</code>.
074:             */
075:            protected int fEndOffset;
076:
077:            /**
078:             * Offset of the next byte to be read from the stream relative to
079:             * the beginning of the stream (and <code>fData</code> array as well)
080:             */
081:            protected int fOffset;
082:
083:            /**
084:             * Number of read bytes currently stored in <code>fData</code> buffer.
085:             * Size of the buffer itself can be greater than this value, obviously.
086:             */
087:            protected int fLength;
088:
089:            /**
090:             * Offset of the "marked" position in the stream relative to its beginning.
091:             */
092:            protected int fMark;
093:
094:            /**
095:             * Creates new <code>RewindableInputStream</code> object with internal
096:             * buffer of default size and default value of chunked reading flag (which
097:             * is _currently_ <code>true</code>).
098:             *
099:             * @param  is  InputStream that needs basic reset/rewind functionality.
100:             */
101:            public RewindableInputStream(InputStream is) {
102:                this (is, true, DEFAULT_XMLDECL_BUFFER_SIZE);
103:            }
104:
105:            /**
106:             * Creates new RewindableInputStream with internal buffer of specified size
107:             * and no chunk reading beyound the buffer limits allowed.
108:             *
109:             * @param  is  InputStream that needs some reset/rewind functionality.
110:             *
111:             * @param  chunkedMode  See the <code>RewindableInputStream(InputStream,
112:             *                      boolean, int)</code> constructor description.
113:             */
114:            public RewindableInputStream(InputStream is, boolean chunkedMode) {
115:                this (is, chunkedMode, DEFAULT_XMLDECL_BUFFER_SIZE);
116:            }
117:
118:            /**
119:             * Primary constructor that allows to specify all parameters exlicitly
120:             * affecting class work (initial size of the internal buffer and
121:             * chunk read mode).
122:             *
123:             * @param  is  InputStream that needs some reset/rewind functionality.
124:             *
125:             * @param  chunkedMode
126:             *
127:             *         Initial value of <code>fMayReadChunks</code> flag which determines
128:             *         whether multiple bytes can be read from the underlying stream in
129:             *         single reading operation or not. This value can be changed using
130:             *         <code>setChunkedMode</code> (or its aliases). For specific
131:             *         purpose of inferring encoding/charset of XML document typical
132:             *         usage policy is to disable chunked reads while obtaining XML
133:             *         declaration and then enable it to speed up reading the rest of
134:             *         document.
135:             *
136:             * @param  initialSize  Initial size of the internal buffer array.
137:             */
138:            public RewindableInputStream(InputStream is, boolean chunkedMode,
139:                    int initialSize) {
140:                if (0 >= initialSize) {
141:                    initialSize = DEFAULT_XMLDECL_BUFFER_SIZE;
142:                }
143:
144:                fData = new byte[initialSize];
145:
146:                fInputStream = is;
147:                fStartOffset = 0;
148:                fMayReadChunks = chunkedMode;
149:                fEndOffset = -1;
150:                fOffset = 0;
151:                fLength = 0;
152:                fMark = 0;
153:            }
154:
155:            /**
156:             * Sets the position somewhere in the stream to which the stream pointer
157:             * will be reset after <code>rewind</code> invocation. By default this
158:             * position is the beginning of the stream.
159:             *
160:             * @param  offset  New value for "fStartOffset".
161:             */
162:            public void setStartOffset(int offset) {
163:                fStartOffset = offset;
164:            }
165:
166:            /**
167:             * Allows to change the behavior of the stream regarding chunked reading
168:             * at runtime. If you allowed chunked reading and then read some data from
169:             * the stream, you better forget about <code>reset</code>ting or
170:             * <code>rewind</code>ing it after that.
171:             *
172:             * @param  chunkedMode  New value for <code>fMayReadChunks</code>.
173:             */
174:            public void setChunkedMode(boolean chunkedMode) {
175:                fMayReadChunks = chunkedMode;
176:            }
177:
178:            /**
179:             * More conscious alias for <code>setChunkedMode(true)</code>. While last
180:             * method is a general purpose mutator, code may look a bit more clear if
181:             * you use specialized methods to enable/disable chunk read mode.
182:             */
183:            public void enableChunkedMode() {
184:                fMayReadChunks = true;
185:            }
186:
187:            /**
188:             * More conscious alias for <code>setChunkedMode(false)</code>. While last
189:             * method is a general purpose mutator, code may look a bit more clear if
190:             * you use specialized methods to enable/disable chunk read mode.
191:             */
192:            public void disableChunkedMode() {
193:                fMayReadChunks = false;
194:            }
195:
196:            /**
197:             * Quickly reset stream pointer to the beginning of the stream or to
198:             * position which offset was specified during the last
199:             * <code>setStartOffset</code> call.
200:             */
201:            public void rewind() {
202:                fOffset = fStartOffset;
203:            }
204:
205:            /**
206:             * Reads next byte from this stream. This byte is either being read from
207:             * underlying InputStream or taken from the internal buffer in case it was
208:             * already read at some point before.
209:             *
210:             * @return Next byte of data or <code>-1</code> if end of stream is reached.
211:             *
212:             * @throws IOException in case of any I/O errors.
213:             */
214:            public int read() throws IOException {
215:                int b = 0;
216:
217:                // Byte to be read is already in out buffer, simply returning it
218:                if (fOffset < fLength) {
219:                    return fData[fOffset++] & 0xff;
220:                }
221:
222:                /*
223:                 * End of the stream is reached.
224:                 * I also believe that in certain cases fOffset can point to the
225:                 * position after the end of stream, for example, after invalid
226:                 * `setStartOffset()` call followed by `rewind()`.
227:                 * This situation is not handled currently.
228:                 */
229:                if (fOffset == fEndOffset) {
230:                    return -1;
231:                }
232:
233:                /*
234:                 * Ok, we should actually read data from underlying stream, but
235:                 * first it will be good to check if buffer array should be
236:                 * expanded. Each time buffer size is doubled.
237:                 */
238:                if (fOffset == fData.length) {
239:                    byte[] newData = new byte[fOffset << 1];
240:                    System.arraycopy(fData, 0, newData, 0, fOffset);
241:                    fData = newData;
242:                }
243:
244:                // Reading byte from the underlying stream, storing it in buffer and
245:                // then returning it.
246:                b = fInputStream.read();
247:
248:                if (b == -1) {
249:                    fEndOffset = fOffset;
250:
251:                    return -1;
252:                }
253:
254:                fData[fLength++] = (byte) b;
255:                fOffset++;
256:
257:                return b & 0xff;
258:            } // END read()
259:
260:            /**
261:             * Reads up to len bytes of data from the input stream into an array of
262:             * bytes. In its current implementation it cannot return more bytes than
263:             * left in the buffer if in "non-chunked" mode
264:             * (<code>fMayReadChunks == false</code>). After reaching the end of
265:             * the buffer, each invocation of this method will read exactly 1 byte
266:             * then. In "chunked" mode this method <em>may</em> return more than 1
267:             * byte, but it doesn't buffer the result.
268:             *
269:             * <p>From the other hand, for the task of reading xml declaration, such
270:             * behavior may be desirable, as we probably don't need reset/rewind
271:             * functionality after we finished with charset deduction. It is good
272:             * idea to call <code>enableChunkedMode</code> after that, in order to
273:             * improve perfomance and lessen memoery consumption when reading the rest
274:             * of the data.
275:             *
276:             * @return Total number of bytes actually read or <code>-1</code> if end
277:             *         of stream has been reached.
278:             *
279:             * @throws IOException  when an I/O error occurs while reading data
280:             *
281:             * @throws IndexOutOfBoundsException  in case of invalid <code>off</code>,
282:             *                 <code>len</code> and <code>b.length</code> combination
283:             */
284:            public int read(byte[] b, int off, int len) throws IOException {
285:                if (null == b) {
286:                    throw new NullPointerException(
287:                            "Destination byte array is null.");
288:                } else if (0 == len) {
289:                    return 0;
290:                } else if ((b.length < off) || (b.length < (off + len))
291:                        || (0 > off) || (0 > len)) {
292:                    throw new IndexOutOfBoundsException();
293:                }
294:
295:                int bytesLeft = fLength - fOffset;
296:
297:                /*
298:                 * There is no more bytes in the buffer. We either reading 1 byte
299:                 * from underlying InputStream and saving it in the buffer, or
300:                 * getting more bytes without saving them, depending on the value
301:                 * of `fMayReadChunks` field.
302:                 */
303:                if (bytesLeft == 0) {
304:                    if (fOffset == fEndOffset) {
305:                        return -1;
306:                    }
307:
308:                    // better get some more for the voracious reader...
309:                    if (fMayReadChunks) {
310:                        // Hmm, this can be buffered in theory. But in many
311:                        // cases this would be undesirable, so let it be as it is.
312:                        return fInputStream.read(b, off, len);
313:                    }
314:
315:                    int returnedVal = read();
316:
317:                    if (returnedVal == -1) {
318:                        fEndOffset = fOffset;
319:
320:                        return -1;
321:                    }
322:
323:                    b[off] = (byte) returnedVal;
324:
325:                    return 1;
326:                }
327:
328:                /*
329:                 * In non-chunked mode we shouldn't give out more bytes then left
330:                 * in the buffer.
331:                 */
332:                if (fMayReadChunks) {
333:                    // Count of bytes to get form buffer
334:                    int readFromBuffer = (len < bytesLeft) ? len : bytesLeft;
335:
336:                    System.arraycopy(fData, fOffset, b, off, readFromBuffer);
337:
338:                    int readFromStream = 0;
339:
340:                    if (len > bytesLeft) {
341:                        readFromStream = fInputStream.read(b, off + bytesLeft,
342:                                len - bytesLeft);
343:                    }
344:
345:                    fOffset += readFromBuffer;
346:
347:                    return readFromBuffer
348:                            + ((-1 == readFromStream) ? 0 : readFromStream);
349:                } else {
350:                    //
351:                    // This will prevent returning more bytes than the remainder of
352:                    // the buffer array.
353:                    if (len > bytesLeft) {
354:                        len = bytesLeft;
355:                    }
356:
357:                    System.arraycopy(fData, fOffset, b, off, len);
358:
359:                    fOffset += len;
360:
361:                    return len;
362:                }
363:            } // END read(byte[], int, int)
364:
365:            /**
366:             * Skips over and discards <code>n</code> bytes of data from this input
367:             * stream. The skip method may, for a variety of reasons, end up skipping
368:             * over some smaller number of bytes, possibly <code>0</code>. The actual
369:             * number of bytes skipped is returned. If <code>n</code> is negative, no
370:             * bytes are skipped.
371:             *
372:             * @param  n  Number of bytes to be skipped.
373:             *
374:             * @return Number of bytes actually skipped.
375:             *
376:             * @throws IOException if an I/O error occurs.
377:             */
378:            public long skip(long n) throws IOException {
379:                int bytesLeft;
380:
381:                if (n <= 0) {
382:                    return 0;
383:                }
384:
385:                bytesLeft = fLength - fOffset;
386:
387:                // If end of buffer is reached, using `skip()` of the underlying input
388:                // stream
389:                if (bytesLeft == 0) {
390:                    if (fOffset == fEndOffset) {
391:                        return 0;
392:                    }
393:
394:                    return fInputStream.skip(n);
395:                }
396:
397:                // Quickly "skipping" bytes in the buffer by modifying its pointer.
398:                if (n <= bytesLeft) {
399:                    fOffset += n;
400:
401:                    return n;
402:                }
403:
404:                fOffset += bytesLeft;
405:
406:                if (fOffset == fEndOffset) {
407:                    return bytesLeft;
408:                }
409:
410:                n -= bytesLeft;
411:
412:                return fInputStream.skip(n) + bytesLeft;
413:            } // END skip(long)
414:
415:            /**
416:             * Returns the number of bytes that can be read (or skipped over) from this
417:             * input stream without blocking by the next caller of a method for this
418:             * input stream. For <code>RewindableInputStream</code> this can be:
419:             *
420:             * <ul>
421:             *   <li>
422:             *    Number of unread bytes in the <code>fData</code> buffer, i.e. those
423:             *    between current position (fOffset) and total bytes quantity in the
424:             *    buffer (fLength).
425:             *   </li>
426:             *   <li>
427:             *    Result of underlying InputStream's <code>available</code> call
428:             *    if there are no unread bytes in the buffer.
429:             *   </li>
430:             *   <li>
431:             *    <code>-1</code> if end of stream is reached.
432:             *   </li>
433:             * </ul>
434:             *
435:             * @return the number of bytes that can be read from this input stream
436:             *         without blocking.
437:             *
438:             * @throws IOException when an I/O error occurs.
439:             */
440:            public int available() throws IOException {
441:                int bytesLeft = fLength - fOffset;
442:
443:                if (bytesLeft == 0) {
444:                    // Again, the same thing as in `read()`. Do we need to throw
445:                    // an exception if fOffset > fEndOffset???
446:                    if (fOffset == fEndOffset) {
447:                        return -1;
448:                    }
449:
450:                    /*
451:                     * In a manner of speaking, when this class isn't permitting more
452:                     * than one byte at a time to be read, it is "blocking".  The
453:                     * available() method should indicate how much can be read without
454:                     * blocking, so while we're in this mode, it should only indicate
455:                     * that bytes in its buffer are available; otherwise, the result of
456:                     * available() on the underlying InputStream is appropriate.
457:                     */
458:                    return fMayReadChunks ? fInputStream.available() : 0;
459:                }
460:
461:                return bytesLeft;
462:            }
463:
464:            /**
465:             * Sets a mark to the current position in the stream.
466:             *
467:             * @param  howMuch  Not used in this implementation I guess.
468:             */
469:            public void mark(int howMuch) {
470:                fMark = fOffset;
471:            }
472:
473:            /**
474:             * Returns stream pointer to the position previously remembered
475:             * using <code>mark</code> method (or to beginning of the stream,
476:             * if there were no <code>mark</code> method calls).
477:             */
478:            public void reset() {
479:                fOffset = fMark;
480:            }
481:
482:            /**
483:             * Tells that this stream supports mark/reset capability.
484:             * This one definitely supports it :)
485:             *
486:             * @return <code>true</code> if this stream instance supports the mark
487:             *         and reset methods; <code>false</code> otherwise.
488:             */
489:            public boolean markSupported() {
490:                return true;
491:            }
492:
493:            /**
494:             * Closes underlying byte stream.
495:             *
496:             * @throws IOException if an I/O error occurs.
497:             */
498:            public void close() throws IOException {
499:                if (fInputStream != null) {
500:                    fInputStream.close();
501:                    fInputStream = null;
502:                    fData = null;
503:                }
504:            }
505:        } // end of RewindableInputStream class
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.