001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2003-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016: package org.geotools.data;
017:
018: import java.io.IOException;
019: import java.nio.ByteBuffer;
020: import java.nio.ByteOrder;
021: import java.nio.CharBuffer;
022: import java.nio.channels.FileChannel;
023: import java.nio.channels.ReadableByteChannel;
024: import java.nio.charset.Charset;
025: import java.nio.charset.CharsetDecoder;
026:
027: import org.geotools.factory.Hints;
028: import org.geotools.referencing.ReferencingFactoryFinder;
029: import org.opengis.referencing.FactoryException;
030: import org.opengis.referencing.crs.CoordinateReferenceSystem;
031:
032: /**
033: * @author Simone Giannecchini
034: * @since 2.3
035: * @source $URL:
036: * http://svn.geotools.org/geotools/trunk/gt/module/main/src/org/geotools/data/PrjFileReader.java $
037: */
038: public class PrjFileReader {
039:
040: ByteBuffer buffer;
041:
042: ReadableByteChannel channel;
043:
044: CharBuffer charBuffer;
045:
046: CharsetDecoder decoder;
047:
048: CoordinateReferenceSystem crs;
049:
050: /**
051: * Load the index file from the given channel.
052: *
053: * @param channel
054: * The channel to read from.
055: * @throws IOException
056: * If an error occurs.
057: */
058: public PrjFileReader(ReadableByteChannel channel)
059: throws IOException, FactoryException {
060: this (channel, null);
061: }
062:
063: /**
064: * Load the index file from the given channel.
065: *
066: * @param channel
067: * The channel to read from.
068: * @param hints
069: *
070: * @throws IOException
071: * If an error occurs.
072: */
073: public PrjFileReader(ReadableByteChannel channel, final Hints hints)
074: throws IOException, FactoryException {
075: Charset chars = Charset.forName("ISO-8859-1");
076: decoder = chars.newDecoder();
077: this .channel = channel;
078:
079: init();
080:
081: // ok, everything is ready...
082: decoder.decode(buffer, charBuffer, true);
083: buffer.limit(buffer.capacity());
084: charBuffer.flip();
085: crs = ReferencingFactoryFinder.getCRSFactory(hints)
086: .createFromWKT(charBuffer.toString());
087: }
088:
089: /**
090: * Return the Coordinate Reference System retrieved by this reader.
091: *
092: * @deprecated use {@link #getCoordinateReferenceSystem()}.
093: */
094: public CoordinateReferenceSystem getCoodinateSystem() {
095: return crs;
096: }
097:
098: /**
099: * Return the Coordinate Reference System retrieved by this reader.
100: *
101: * @return the Coordinate Reference System
102: */
103: public CoordinateReferenceSystem getCoordinateReferenceSystem() {
104: return crs;
105: }
106:
107: private int fill(ByteBuffer buffer, ReadableByteChannel channel)
108: throws IOException {
109: int r = buffer.remaining();
110: // channel reads return -1 when EOF or other error
111: // because they a non-blocking reads, 0 is a valid return value!!
112: while (buffer.remaining() > 0 && r != -1) {
113: r = channel.read(buffer);
114: }
115: if (r == -1) {
116: buffer.limit(buffer.position());
117: }
118: return r;
119: }
120:
121: private void init() throws IOException {
122: // create the ByteBuffer
123: // if we have a FileChannel, lets map it
124: if (channel instanceof FileChannel) {
125: FileChannel fc = (FileChannel) channel;
126: buffer = fc
127: .map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
128: buffer.position((int) fc.position());
129: } else {
130: // Some other type of channel start with a 8K buffer, should be more than adequate
131: int size = 8 * 1024;
132: // if for some reason its not, resize it
133: // size = header.getRecordLength() > size ? header.getRecordLength() : size;
134: buffer = ByteBuffer.allocateDirect(size);
135: // fill it and reset
136: fill(buffer, channel);
137: buffer.flip();
138: }
139:
140: // The entire file is in little endian
141: buffer.order(ByteOrder.LITTLE_ENDIAN);
142:
143: charBuffer = CharBuffer.allocate(8 * 1024);
144: Charset chars = Charset.forName("ISO-8859-1");
145: decoder = chars.newDecoder();
146:
147: }
148:
149: public void close() throws IOException {
150: if (channel.isOpen()) {
151: channel.close();
152:
153: }
154: }
155:
156: }
|