/* * Copyright 2010-2011 Research In Motion Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package blackberry.web.widget.caching; import java.io.ByteArrayInputStream; import java.io.IOException; import net.rim.device.api.compress.GZIPInputStream; import net.rim.device.api.io.IOUtilities; import net.rim.device.api.io.http.HttpHeaders; import net.rim.device.api.system.CodeSigningKey; import net.rim.device.api.system.ControlledAccessException; import net.rim.device.api.system.PersistentObject; import net.rim.device.api.system.PersistentStore; import net.rim.device.api.util.ByteVector; import net.rim.device.api.util.Persistable; public class CacheItem implements Persistable { private String _url; private long _expires; private int _size; private int _fileSize; private long _storeKey; public CacheItem( long storeKey, String url, long expires, int size, int fileSize ) { _storeKey = storeKey; _url = url; _expires = expires; _size = size; _fileSize = fileSize; } public String getUrl() { return _url; } public long getExpires() { return _expires; } public int getSize() { return _fileSize; } public long getStoreKey() { return _storeKey; } /** * Obtain data from the cached item. * * @return Data from the cached item, or null on error. */ public byte[] getData() { byte[] data = null; // Get the code signing key associated with this BlackBerry WebWorks Application CodeSigningKey codeSigningKey = CodeSigningKey.get( this ); // Check Persistent Store for existing data PersistentObject cacheItemStore = PersistentStore.getPersistentObject( _storeKey ); // If we find an entry in the Persistent store if( cacheItemStore != null ) { Object cacheItemObj = null; try { // codeSigningKey is nullable cacheItemObj = cacheItemStore.getContents( codeSigningKey ); } catch ( ControlledAccessException ignore ) { // cacheItemObj remains null } if( cacheItemObj instanceof ByteVector ) { ByteVector cacheItemVector = (ByteVector) cacheItemObj; data = cacheItemVector.getArray(); } } if( data != null ) { // Create InputStream ByteArrayInputStream dataStream = new ByteArrayInputStream( data ); CacheManager.receiveLine( dataStream ); CacheManager.receiveLine( dataStream ); CacheManager.receiveLine( dataStream ); // Read headers while( true ) { String line = CacheManager.receiveLine( dataStream ); // Headers end with double CRLF if( line.length() == 0 ) { break; } } // Read data try { data = readDataFromStore( dataStream ); } catch ( IOException ignore ) { // data remains null } if( data != null && data.length != _size ) { data = null; } } return data; } /** * @return May return null * * @throws IOException */ private byte[] readDataFromStore( ByteArrayInputStream dataInputStream ) throws IOException { // Check whether it's compressed or not String lineCompressFlag = CacheManager.receiveLine( dataInputStream ); int compressed = -1; try { compressed = Integer.parseInt( lineCompressFlag ); } catch( NumberFormatException ignore ) { // compressed will remain -1 } if( compressed < 0 ) { throw new IOException(); } boolean bCompressed = ( compressed == 1 ); // Read compressed size String lineSize = CacheManager.receiveLine( dataInputStream ); int size = -1; try { size = Integer.parseInt( lineSize ); } catch( NumberFormatException ignore ) { // size will remain -1 } if( size <= 0 ) { throw new IOException(); } byte[] data = new byte[ size ]; int read = dataInputStream.read( data ); if( read != size ) { throw new IOException(); } if( !bCompressed ) { return data; } GZIPInputStream gin = new GZIPInputStream( new ByteArrayInputStream( data ) ); return IOUtilities.streamToBytes( gin ); // Return original data, or null } /** * Obtain headers. * * @return HttpHeaders from the cached item, or null on error. */ public HttpHeaders getHeaders() { HttpHeaders headers = null; byte[] data = null; // Get the code signing key associated with this BlackBerry WebWorks Application CodeSigningKey codeSigningKey = CodeSigningKey.get( this ); // Check Persistent Store for existing data PersistentObject cacheItemStore = PersistentStore.getPersistentObject( _storeKey ); // If we find an entry in the Persistent store if( cacheItemStore != null ) { Object cacheItemObj = null; try { // codeSigningKey is nullable cacheItemObj = cacheItemStore.getContents( codeSigningKey ); } catch ( ControlledAccessException ignore ) { // cacheItemObj remains null } if( cacheItemObj instanceof ByteVector ) { ByteVector cacheItemVector = (ByteVector) cacheItemObj; data = cacheItemVector.getArray(); } } if( data != null ) { // Create InputStream ByteArrayInputStream dataStream = new ByteArrayInputStream( data ); CacheManager.receiveLine( dataStream ); CacheManager.receiveLine( dataStream ); CacheManager.receiveLine( dataStream ); // Read headers headers = new HttpHeaders(); String line = null; while( true ) { line = CacheManager.receiveLine( dataStream ); // Headers end with double CRLF if( line.length() == 0 ) { break; } try { int indexOfColon = line.indexOf( ':' ); if( indexOfColon != -1 ) { headers.setProperty( line.substring( 0, indexOfColon ).trim(), line.substring( indexOfColon + 1 ).trim() ); } else { // Drop the header } } catch( IndexOutOfBoundsException ignore ) { // Drop the header } } } return headers; } }