001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: *//*
041: * CacheReader.java
042: *
043: * Created on February 16, 2004, 8:11 PM
044: */
045:
046: package org.netbeans.imagecache;
047:
048: import java.awt.Image;
049: import java.awt.Point;
050: import java.awt.image.BufferedImage;
051: import java.awt.image.ColorModel;
052: import java.awt.image.Raster;
053: import java.awt.image.WritableRaster;
054: import java.io.File;
055: import java.io.FileInputStream;
056: import java.io.IOException;
057: import java.nio.ByteBuffer;
058: import java.nio.IntBuffer;
059: import java.nio.LongBuffer;
060: import java.nio.channels.FileChannel;
061: import java.util.ArrayList;
062: import java.util.Arrays;
063:
064: /**
065: *
066: * @author Tim Boudreau
067: */
068: public class CacheReader {
069: static final String filename = CacheWriter.filename;
070: static final int METAENTRY_LENGTH = CacheWriter.METAENTRY_LENGTH;
071: static final int ID_OFFSET = CacheWriter.ID_OFFSET;
072: private File cachefile;
073: private File metafile;
074: private ByteBuffer cachebuffer = null;
075: private ByteBuffer metabuffer = null;
076:
077: /** Creates a new instance of CacheReader */
078: public CacheReader(File cacheDir) throws IOException {
079: this (new File(cacheDir + File.separator + filename + ".cache"),
080: new File(cacheDir + File.separator + filename
081: + ".metadata"));
082: }
083:
084: public CacheReader(File cachefile, File metafile)
085: throws IOException {
086: if (!cachefile.exists() || !metafile.exists()) {
087: throw new IOException("Cache does not exist: " + cachefile
088: + "," + metafile);
089: }
090: this .cachefile = cachefile;
091: this .metafile = metafile;
092: }
093:
094: public String[] getIDs() throws IOException {
095: ArrayList a = new ArrayList();
096: ByteBuffer b = getMetaBuffer().asReadOnlyBuffer();
097: int max = b.limit() / METAENTRY_LENGTH;
098: for (int i = 0; i < max; i++) {
099: int len = b.asIntBuffer().get();
100: b.mark();
101: b.position(b.position() + ID_OFFSET);
102: byte[] bytes = new byte[len];
103: b.get(bytes);
104: a.add(new String(bytes));
105: b.reset();
106: if (i != max - 1) {
107: b.position(b.position() + METAENTRY_LENGTH);
108: }
109: }
110: String[] result = new String[a.size()];
111: result = (String[]) a.toArray(result);
112: return result;
113: }
114:
115: public Image find(String id) throws IOException {
116: ByteBuffer buf = findMetadataFor(toByteArray(id));
117: if (buf == null) {
118: return null;
119: }
120:
121: IntBuffer ibuf = buf.asIntBuffer();
122:
123: int[] intEntries = new int[3];
124: ibuf.get(intEntries);
125:
126: assert id.length() == intEntries[0];
127:
128: int width = intEntries[1];
129: int height = intEntries[2];
130:
131: long[] longEntries = new long[2];
132:
133: buf.position(buf.position() + 12);
134:
135: LongBuffer lbuf = buf.asLongBuffer();
136: lbuf.get(longEntries);
137:
138: //The cast to int is safe, the writer will never write a cache file
139: //bigger than Integer.MAX_VALUE
140: int start = (int) longEntries[0];
141: int end = (int) longEntries[1];
142:
143: ByteBuffer cache = getBuffer().asReadOnlyBuffer();
144: cache.position(start);
145:
146: System.err.println("Cache position is " + cache.position());
147: IntBuffer databuffer = cache.asIntBuffer();
148: System.err.println("IntBuffer position is "
149: + databuffer.position());
150: return createImageFrom(databuffer, width, height);
151: }
152:
153: /*
154: private Image createImageFrom (IntBuffer data, int width, int height) {
155: //Cheap'n'cheesy for now - should really create a custom DataSource which
156: //reads the buffer for its pixel data
157:
158: BufferedImage bi = new BufferedImage (width, height, BufferedImage.TYPE_INT_ARGB);
159: for (int x=0; x < width; x++) {
160: for (int y=0; y < height; y++) {
161: try {
162: bi.setRGB (x, y, data.get());
163: } catch (Exception e) {
164: System.err.println("Exception getting " + x + "," + y + " pos:" + data.position());
165: }
166: }
167: }
168: return bi;
169: }
170: */
171:
172: private Image createImageFrom(IntBuffer data, int width, int height) {
173: CRaster raster = new CRaster(data, width, height);
174: return new CImage(ColorModel.getRGBdefault(), raster, false,
175: null);
176: }
177:
178: /** Locates metadata related to the passed id (converted into a byte
179: * array). Returns either a bytebuffer with the position set to the
180: * start of the metadata or null. */
181: private ByteBuffer findMetadataFor(byte[] id) throws IOException {
182: System.err.println("FindMetadataFor " + new String(id));
183:
184: long result = -1;
185: //Get a buffer clone so we don't have threading problems - never
186: //use the master buffer
187: ByteBuffer buf = getMetaBuffer().asReadOnlyBuffer();
188:
189: IntBuffer ibuf = buf.asIntBuffer();
190:
191: do {
192: //First, see if the ID (image filename) length matches the ID
193: //we received - if it doesn't, no need to examine the record
194: int this IdLength = ibuf.get();
195: System.err.println("pos:" + ibuf.position() + " idLen: "
196: + this IdLength + " looking for len: " + id.length);
197:
198: if (this IdLength == id.length) {
199: //Mark the start of this metadata record and position to
200: //the start of the ID entry
201: System.err.println("Length match. Putting mark at "
202: + (buf.position()) + " and moving to "
203: + (buf.position() + ID_OFFSET)
204: + " to check data");
205: buf.mark().position(buf.position() + ID_OFFSET);
206:
207: byte[] chars = new byte[id.length];
208:
209: //Fetch the ID into the array, and reset the buffer position
210: //for either returning or skipping to the next record
211: buf.get(chars).reset();
212: System.err.println(" id from metadata: "
213: + new String(chars));
214:
215: //Compare it with the id we were passed
216: if (Arrays.equals(chars, id)) {
217: System.err.println(" MATCHED - position: "
218: + buf.position());
219: return buf;
220: }
221: }
222: //Skip ahead to the next record
223: buf.position(buf.position() + METAENTRY_LENGTH);
224: ibuf.position(buf.position() / 4);
225: System.err.println("Buffer pos: " + buf.position()
226: + " ibuf: " + ibuf.position());
227: } while (buf.position() <= buf.limit() - METAENTRY_LENGTH);
228:
229: return null;
230: }
231:
232: private static byte[] toByteArray(String s) {
233: char[] c = s.toCharArray();
234: byte[] result = new byte[c.length];
235: for (int i = 0; i < c.length; i++) {
236: result[i] = (byte) c[i];
237: }
238: return result;
239: }
240:
241: protected ByteBuffer createBuffer(File file) throws IOException {
242: return new FileInputStream(file).getChannel().map(
243: FileChannel.MapMode.READ_ONLY, 0, file.length());
244: }
245:
246: private ByteBuffer getBuffer() throws IOException {
247: if (cachebuffer == null) {
248: cachebuffer = createBuffer(cachefile);
249: }
250: cachebuffer.position(0);
251: return cachebuffer;
252: }
253:
254: private ByteBuffer getMetaBuffer() throws IOException {
255: if (metabuffer == null) {
256: metabuffer = createBuffer(metafile);
257: }
258: return metabuffer;
259: }
260: }
|