001: /*
002: * Copyright (c) 2007, intarsys consulting GmbH
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * - Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * - Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * - Neither the name of intarsys nor the names of its contributors may be used
015: * to endorse or promote products derived from this software without specific
016: * prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
028: * POSSIBILITY OF SUCH DAMAGE.
029: */
030: package de.intarsys.tools.locator;
031:
032: import java.io.IOException;
033: import java.io.InputStream;
034: import java.io.OutputStream;
035: import java.io.Reader;
036: import java.io.Writer;
037: import java.net.URL;
038:
039: import de.intarsys.tools.randomaccess.AbstractRandomAccess;
040: import de.intarsys.tools.randomaccess.IRandomAccess;
041: import de.intarsys.tools.stream.StreamTools;
042:
043: /**
044: * A viewport implementation for {@link ILocator}. This object defines a range
045: * of bytes visible to the client of the viewport.
046: */
047: public class LocatorViewport extends CommonLocator {
048: private ILocator delegate;
049:
050: private long start = 0;
051:
052: private long end = 0;
053:
054: private String name;
055:
056: private class InputStreamProxy extends InputStream {
057: private InputStream is;
058:
059: private int current = 0;
060:
061: public InputStreamProxy(InputStream is) {
062: this .is = is;
063: }
064:
065: public int read() throws IOException {
066: while (current < getStart()) {
067: is.read();
068: current++;
069: }
070: if (current >= getEnd()) {
071: return -1;
072: }
073: int i = is.read();
074: current++;
075: return i;
076: }
077:
078: public void close() throws IOException {
079: is.close();
080: }
081: }
082:
083: private class ReaderProxy extends Reader {
084: private Reader r;
085:
086: private int current = 0;
087:
088: public ReaderProxy(Reader r) {
089: this .r = r;
090: }
091:
092: public void close() throws IOException {
093: r.close();
094: }
095:
096: public int read(char[] cbuf, int off, int len)
097: throws IOException {
098: while (current < getStart()) {
099: r.read();
100: current++;
101: }
102: if (current >= getEnd()) {
103: return -1;
104: }
105: len = Math.min(len, (int) getEnd() - current);
106: int i = r.read(cbuf, off, len);
107: current += i;
108: return i;
109: }
110: }
111:
112: private class RandomAccessProxy extends AbstractRandomAccess {
113: private IRandomAccess ra;
114:
115: private long current = 0;
116:
117: public RandomAccessProxy(IRandomAccess ra) {
118: this .ra = ra;
119: try {
120: seek(0);
121: } catch (IOException e) {
122: throw new RuntimeException(e);
123: }
124: }
125:
126: public void close() throws IOException {
127: ra.close();
128: }
129:
130: public void flush() throws IOException {
131: ra.flush();
132: }
133:
134: public long getLength() throws IOException {
135: long end = Math.min(getEnd(), ra.getLength());
136: return end - getStart();
137: }
138:
139: public long getOffset() throws IOException {
140: return ra.getOffset() - getStart();
141: }
142:
143: public boolean isReadOnly() {
144: return true;
145: }
146:
147: public int read() throws IOException {
148: if (current < getStart()) {
149: seek(0);
150: }
151: if (current >= getLength()) {
152: return -1;
153: }
154: int i = ra.read();
155: setCurrent((int) current + 1);
156: return i;
157: }
158:
159: public int read(byte[] buffer, int start, int numBytes)
160: throws IOException {
161: if (current < getStart()) {
162: seek(0);
163: }
164: if (current >= getLength()) {
165: return -1;
166: }
167: numBytes = Math.min(numBytes, (int) getEnd()
168: - (int) current);
169: int i = ra.read(buffer, start, numBytes);
170: setCurrent((int) current + i);
171: return i;
172: }
173:
174: public int read(byte[] buffer) throws IOException {
175: if (current < getStart()) {
176: seek(0);
177: }
178: if (current >= getLength()) {
179: return -1;
180: }
181: int numBytes = Math.min(buffer.length, (int) getEnd()
182: - (int) current);
183: int i = ra.read(buffer, 0, numBytes);
184: setCurrent((int) current + i);
185: return i;
186: }
187:
188: public void seek(long offset) throws IOException {
189: setCurrent(offset);
190: try {
191: ra.seek(getStart() + current);
192: } catch (IOException e) {
193: throw new RuntimeException(e);
194: }
195: }
196:
197: public void seekBy(long delta) throws IOException {
198: setCurrent(current + delta);
199: try {
200: ra.seek(getStart() + current);
201: } catch (IOException e) {
202: throw new RuntimeException(e);
203: }
204: }
205:
206: public void setLength(long newLength) throws IOException {
207: }
208:
209: public void write(byte[] buffer, int start, int numBytes)
210: throws IOException {
211: }
212:
213: public void write(byte[] buffer) throws IOException {
214: }
215:
216: public void write(int b) throws IOException {
217: }
218:
219: protected void setCurrent(long newCurrent) throws IOException {
220: if (newCurrent < 0) {
221: throw new IOException("offset too low");
222: }
223: if (newCurrent > getLength()) {
224: throw new IOException("offset too high");
225: }
226: current = newCurrent;
227: }
228: }
229:
230: public LocatorViewport(ILocator delegate) {
231: super ();
232: setDelegate(delegate);
233: }
234:
235: /*
236: * (non-Javadoc)
237: *
238: * @see de.intarsys.tools.locator.ILocator#exists()
239: */
240: public boolean exists() {
241: return getDelegate().exists();
242: }
243:
244: /*
245: * (non-Javadoc)
246: *
247: * @see de.intarsys.tools.locator.ILocator#getChild(java.lang.String)
248: */
249: public ILocator getChild(String name) {
250: return getDelegate().getChild(name);
251: }
252:
253: /*
254: * (non-Javadoc)
255: *
256: * @see de.intarsys.tools.locator.ILocator#getFullName()
257: */
258: public String getFullName() {
259: if (getName() != null) {
260: return getName();
261: }
262: return getDelegate().getFullName();
263: }
264:
265: /*
266: * (non-Javadoc)
267: *
268: * @see de.intarsys.tools.locator.ILocator#getInputStream()
269: */
270: public InputStream getInputStream() throws IOException {
271: return new InputStreamProxy(getDelegate().getInputStream());
272: }
273:
274: /*
275: * (non-Javadoc)
276: *
277: * @see de.intarsys.tools.locator.ILocator#getLocalName()
278: */
279: public String getLocalName() {
280: if (getName() != null) {
281: return getName();
282: }
283: return getDelegate().getLocalName();
284: }
285:
286: /*
287: * (non-Javadoc)
288: *
289: * @see de.intarsys.tools.locator.ILocator#getOutputStream()
290: */
291: public OutputStream getOutputStream() throws IOException {
292: return null;
293: }
294:
295: /*
296: * (non-Javadoc)
297: *
298: * @see de.intarsys.tools.locator.ILocator#getParent()
299: */
300: public ILocator getParent() {
301: return getDelegate().getParent();
302: }
303:
304: /*
305: * (non-Javadoc)
306: *
307: * @see de.intarsys.tools.locator.ILocator#getRandomAccess()
308: */
309: public IRandomAccess getRandomAccess() throws IOException {
310: return new RandomAccessProxy(getDelegate().getRandomAccess());
311: }
312:
313: /*
314: * (non-Javadoc)
315: *
316: * @see de.intarsys.tools.locator.ILocator#getReader()
317: */
318: public Reader getReader() throws IOException {
319: return new ReaderProxy(getDelegate().getReader());
320: }
321:
322: /*
323: * (non-Javadoc)
324: *
325: * @see de.intarsys.tools.locator.ILocator#getReader(java.lang.String)
326: */
327: public Reader getReader(String encoding) throws IOException {
328: return new ReaderProxy(getDelegate().getReader(encoding));
329: }
330:
331: /*
332: * (non-Javadoc)
333: *
334: * @see de.intarsys.tools.locator.ILocator#getType()
335: */
336: public String getType() {
337: return getDelegate().getType();
338: }
339:
340: /*
341: * (non-Javadoc)
342: *
343: * @see de.intarsys.tools.locator.ILocator#getTypedName()
344: */
345: public String getTypedName() {
346: return getDelegate().getTypedName();
347: }
348:
349: /*
350: * (non-Javadoc)
351: *
352: * @see de.intarsys.tools.locator.ILocator#getWriter()
353: */
354: public Writer getWriter() throws IOException {
355: return null;
356: }
357:
358: /*
359: * (non-Javadoc)
360: *
361: * @see de.intarsys.tools.locator.ILocator#getWriter(java.lang.String)
362: */
363: public Writer getWriter(String encoding) throws IOException {
364: return null;
365: }
366:
367: /*
368: * (non-Javadoc)
369: *
370: * @see de.intarsys.tools.locator.ILocator#isDirectory()
371: */
372: public boolean isDirectory() {
373: return getDelegate().isDirectory();
374: }
375:
376: /*
377: * (non-Javadoc)
378: *
379: * @see de.intarsys.tools.locator.ILocator#listLocators(de.intarsys.tools.locator.ILocatorNameFilter)
380: */
381: public ILocator[] listLocators(ILocatorNameFilter filter)
382: throws IOException {
383: return getDelegate().listLocators(filter);
384: }
385:
386: /*
387: * (non-Javadoc)
388: *
389: * @see de.intarsys.tools.locator.ILocator#toURL()
390: */
391: public URL toURL() {
392: return getDelegate().toURL();
393: }
394:
395: /*
396: * (non-Javadoc)
397: *
398: * @see de.intarsys.tools.component.ISynchronizable#isOutOfSynch()
399: */
400: public boolean isOutOfSynch() {
401: return getDelegate().isOutOfSynch();
402: }
403:
404: /*
405: * (non-Javadoc)
406: *
407: * @see de.intarsys.tools.component.ISynchronizable#isSynchSynchronous()
408: */
409: public boolean isSynchSynchronous() {
410: return getDelegate().isSynchSynchronous();
411: }
412:
413: /*
414: * (non-Javadoc)
415: *
416: * @see de.intarsys.tools.component.ISynchronizable#synch()
417: */
418: public void synch() {
419: getDelegate().synch();
420: }
421:
422: /**
423: * @return
424: */
425: public ILocator getDelegate() {
426: return delegate;
427: }
428:
429: protected void setDelegate(ILocator delegate) {
430: this .delegate = delegate;
431: //
432: IRandomAccess dra = null;
433: try {
434: dra = getDelegate().getRandomAccess();
435: this .end = dra.getLength();
436: } catch (IOException e) {
437: throw new RuntimeException(e);
438: } finally {
439: StreamTools.close(dra);
440: }
441: }
442:
443: public long getEnd() {
444: return end;
445: }
446:
447: public void setEnd(long end) {
448: IRandomAccess dra = null;
449: try {
450: dra = getDelegate().getRandomAccess();
451: if ((end < 0) || (end > dra.getLength())) {
452: throw new IllegalArgumentException("end");
453: }
454: } catch (IOException e) {
455: throw new RuntimeException(e);
456: } finally {
457: StreamTools.close(dra);
458: }
459: this .end = end;
460: }
461:
462: public long getStart() {
463: return start;
464: }
465:
466: public void setStart(long start) {
467: IRandomAccess dra = null;
468: try {
469: dra = getDelegate().getRandomAccess();
470: if ((start < 0) || (start > dra.getLength())) {
471: throw new IllegalArgumentException("start");
472: }
473: } catch (IOException e) {
474: throw new RuntimeException(e);
475: } finally {
476: StreamTools.close(dra);
477: }
478: this .start = start;
479: }
480:
481: public String getName() {
482: return name;
483: }
484:
485: public void setName(String name) {
486: this .name = name;
487: }
488:
489: /*
490: * (non-Javadoc)
491: *
492: * @see de.intarsys.tools.locator.ILocator#isReadOnly()
493: */
494: public boolean isReadOnly() {
495: return true;
496: }
497:
498: public void rename(String newName) throws IOException {
499: getDelegate().rename(newName);
500: }
501:
502: public void delete() throws IOException {
503: // nothing to do...
504: }
505:
506: }
|