/* Copyright 2012-2013, Polyvi Inc. (http://polyvi.github.io/openxface) This program is distributed under the terms of the GNU General Public License. This file is part of xFace. xFace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. xFace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with xFace. If not, see <http://www.gnu.org/licenses/>. */ package com.polyvi.xface.core; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.util.Iterator; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.polyvi.xface.util.XLog; import com.polyvi.xface.util.XUtils; public class XOnlineResourceIterator implements Iterator<byte[]>{ private static final String CLASS_NAME = XOnlineResourceIterator.class.getName(); private XIResourceFilter mFilter; private Cursor mCursor; private int mCursorCount; private SQLiteDatabase mDatabase; private InputStream mNextInputStream; public XOnlineResourceIterator(String appUrl, String pathToCacheDatabase, XIResourceFilter filter) { mFilter = filter; mCursorCount = 0; initDatabase(appUrl, pathToCacheDatabase); mNextInputStream = traverseNext(); } /** * 初始化数据库 * @param appUrl[in] * @param pathToCacheDatabase[in] 缓存数据库的路径 */ private void initDatabase(String appUrl, String pathToCacheDatabase) { File file = new File(pathToCacheDatabase); if( file.exists() ) { mDatabase = SQLiteDatabase.openOrCreateDatabase(pathToCacheDatabase, null); /**CacheEntries表结构实例 * |RecNo |cache |type |resource| * | 1| 1| 4| 1| * | 2| 1| 4| 2| * | 3| 1| 2| 3| * | 4| 1| 5| 4| * | 5| 1| 4| 5| */ String sqlCommand = "select * from CacheResources where id in ( select resource from " + "CacheEntries where cache in( select cache from CacheEntries where " + "resource in ( select id from CacheResources where url = \'" + appUrl + "\')))"; mCursor = mDatabase.rawQuery(sqlCommand, null); if( !mCursor.moveToFirst() ) { XLog.e(CLASS_NAME, "Database moveToFirst failed!"); mDatabase.close(); mDatabase = null; mCursor.close(); return; } mCursorCount = mCursor.getCount(); } } @Override public boolean hasNext() { return mNextInputStream != null; } @Override public byte[] next() { InputStream current = mNextInputStream; mNextInputStream = traverseNext(); return XUtils.readBytesFromInputStream(current); } /** * 获得下一个文件 * * @return */ private InputStream traverseNext() { InputStream is = null; while( mCursorCount-- > 0 ) { String fileUrl = null; int fileIndex = 0; fileIndex = mCursor.getColumnIndex("url"); if (-1 != fileIndex){ fileUrl = mCursor.getString(fileIndex); } if (null == fileUrl) { mDatabase.close(); mDatabase = null; mCursor.close(); return null; } if (mFilter.accept(fileUrl)) { is = readInputStreamFromAppCache(); if(null == is) { break; } mCursor.moveToNext(); break; } mCursor.moveToNext(); } if(mCursorCount <= 0 && null != mDatabase){ mDatabase.close(); mDatabase = null; mCursor.close(); } return is; } /** * 从缓存中读取文件的输入流 * * @return 读取的输入流 */ private InputStream readInputStreamFromAppCache(){ InputStream is = null; int columIndex = mCursor.getColumnIndex("data"); if(-1 == columIndex) { XLog.e(CLASS_NAME, "data doesn't exist in Database!"); mDatabase.close(); mDatabase = null; mCursor.close(); return is; } int dataIndex = mCursor.getInt(columIndex); String sqlCommand = "select * from CacheResourceData where id = \'" + dataIndex + "\'"; Cursor cursor = mDatabase.rawQuery(sqlCommand, null); if( !cursor.moveToFirst() ) { XLog.e(CLASS_NAME, "Database moveToFirst failed!"); mDatabase.close(); mDatabase = null; mCursor.close(); cursor.close(); return is; } int fileIndex = cursor.getColumnIndex("data"); byte[] fileData = null; if(-1 != fileIndex){ fileData = cursor.getBlob(fileIndex); } if( null != fileData ) { is = new ByteArrayInputStream(fileData); } cursor.close(); return is; } @Override public void remove() { //TODO: 不支持remove的操作,抛出异常 } }