/*
* RSSFeed - Azureus2 Plugin
*
* This program 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 2 of
* the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package org.kmallan.azureus.rssfeed;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
public class KMAllanInputStream extends ObjectInputStream {
private static final byte BC_VECTOR = (byte)0x80, BC_VECTOR_VRSN = (byte)0x80, BC_VECTOR_ITM = (byte)0x81;
private static final byte BC_URL_BEAN = (byte)0x82, BC_FILTER_BEAN = (byte)0x83, BC_HIST_BEAN = (byte)0x84;
private static final byte BC_TYPE_STRING = (byte)0x90, BC_TYPE_INT = (byte)0x91, BC_TYPE_LONG = (byte)0x92;
private static final byte BC_TYPE_BOOLEAN = (byte)0x93, BC_TYPE_UNKNOWN = (byte)0x9F;
private static final String[] strings = new String[] {"Name", "StoreDir", "Expression", "Type", "Category", "Mode",
"Location", "Referer", "Cookie", "FileData"};
private static final String[] bools = new String[] {"IsRegex", "MatchTitle", "MatchLink", "MoveTop", "RateUseCustom",
"RenameFile", "RenameIncEpisode", "DisableAfter", "CleanFile",
"Enabled", "ObeyTTL", "LocRef", "UseCookie"};
private static String[] ints = new String[] {"State", "Priority", "RateUpload", "RateDownload", "StartSeason",
"StartEpisode", "EndSeason", "EndEpisode", "Delay", "SeasonStart",
"SeasonEnd", "EpisodeStart", "EpisodeEnd"};
private static String[] longs = new String[] {"ID", "Feed", "FiltID"};
private static Map types;
static {
types = new HashMap();
for(int i = 0; i < strings.length; i++) types.put(strings[i], new Byte(BC_TYPE_STRING));
for(int i = 0; i < bools.length; i++) types.put(bools[i], new Byte(BC_TYPE_BOOLEAN));
for(int i = 0; i < ints.length; i++) types.put(ints[i], new Byte(BC_TYPE_INT));
for(int i = 0; i < longs.length; i++) types.put(longs[i], new Byte(BC_TYPE_LONG));
}
private static byte getType(String name) {
if(types.containsKey(name)) return ((Byte)types.get(name)).byteValue();
else return BC_TYPE_UNKNOWN;
}
public KMAllanInputStream(InputStream in) throws IOException {
super(in);
}
public Vector readVector(String mode) throws IOException, ClassNotFoundException {
if(readByte() != BC_VECTOR) throw new StreamCorruptedException();
Vector vect = new Vector();
if(mode.equalsIgnoreCase("UrlBean")) {
return readBean(UrlBean.class, BC_URL_BEAN, vect);
} else if(mode.equalsIgnoreCase("FilterBean")) {
return readBean(FilterBean.class, BC_FILTER_BEAN, vect);
} else if(mode.equalsIgnoreCase("HistBean")) {
return readBean(HistoryBean.class, BC_HIST_BEAN, vect);
} else {
throw new StreamCorruptedException("Bad Mode: " + mode);
}
}
private Vector readBean(Class beanClass, byte type, Vector vect) throws IOException, ClassNotFoundException {
int vectCount = readInt();
int vectVRSN = 0;
byte vb = readByte();
if(vb == BC_VECTOR_VRSN) {
vectVRSN = readInt();
vb = readByte();
}
if(vb != BC_VECTOR_ITM) throw new StreamCorruptedException();
if(vectVRSN <= 0) throw new StreamCorruptedException("Unsuported Options File Version: " + vectVRSN);
int itemCount = readInt();
String[] items = new String[itemCount];
for(int i = 0; i < itemCount; i++) items[i] = (String)readObject();
for(int n = 0; n < vectCount; n++) {
if(readByte() != type) throw new StreamCorruptedException();
Object bean = null;
try {
bean = beanClass.newInstance();
} catch(Exception e) {
throw new IOException("Unable to create bean instance for '" + beanClass.getName() + "' - " + e);
}
for(int i = 0; i < itemCount; i++) {
byte itemType = getType(items[i]);
byte itemStoreType;
if(vectVRSN == 1) itemStoreType = getStringType();
else itemStoreType = readByte();
if(itemStoreType == BC_TYPE_UNKNOWN) continue;
if(itemStoreType == itemType) {
switch(itemStoreType) {
case BC_TYPE_STRING:
setValue(bean, items[i], (String)readObject(), String.class);
break;
case BC_TYPE_INT:
setValue(bean, items[i], new Integer(readInt()), int.class);
break;
case BC_TYPE_LONG:
setValue(bean, items[i], new Long(readLong()), long.class);
break;
case BC_TYPE_BOOLEAN:
setValue(bean, items[i], new Boolean(readBoolean()), boolean.class);
break;
}
} else {
switch(itemStoreType) {
case BC_TYPE_STRING:
readObject();
break;
case BC_TYPE_INT:
readInt();
break;
case BC_TYPE_LONG:
readLong();
break;
case BC_TYPE_BOOLEAN:
readBoolean();
break;
default: throw new StreamCorruptedException();
}
}
}
vect.add(bean);
}
return vect;
}
private byte getStringType() throws IOException, ClassNotFoundException {
byte byteType = BC_TYPE_UNKNOWN;
String stringType = (String)readObject();
if(stringType.equalsIgnoreCase("String")) byteType = BC_TYPE_STRING;
else if(stringType.equalsIgnoreCase("Int")) byteType = BC_TYPE_INT;
else if(stringType.equalsIgnoreCase("Long")) byteType = BC_TYPE_LONG;
else if(stringType.equalsIgnoreCase("Boolean")) byteType = BC_TYPE_BOOLEAN;
else throw new StreamCorruptedException("Bad Item Type: " + stringType);
return byteType;
}
private void setValue(Object target, String name, Object value, Class type) throws StreamCorruptedException {
try {
Method m = target.getClass().getMethod("set" + name, new Class[] {type});
m.invoke(target, new Object[] {value});
} catch(Exception e) {
throw new StreamCorruptedException(e.toString());
}
}
}