1
0
Fork 0
mirror of https://github.com/geometer/FBReaderJ.git synced 2025-10-05 02:39:23 +02:00

zip fixes

library speed up
code simplification


git-svn-id: https://only.mawhrin.net/repos/FBReaderJ/trunk@942 6a642e6f-84f6-412e-ac94-c4a38d5a04b0
This commit is contained in:
Nikolay Pultsin 2009-04-19 20:11:37 +00:00
parent f22d805f8d
commit 8cdec4f09d
28 changed files with 363 additions and 476 deletions

View file

@ -19,6 +19,7 @@
package org.geometerplus.android.fbreader;
import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
@ -41,8 +42,10 @@ final class SQLiteBooksDatabase extends BooksDatabase {
createTables();
case 1:
updateTables1();
case 2:
updateTables2();
}
myDatabase.setVersion(2);
myDatabase.setVersion(3);
}
protected void executeAsATransaction(Runnable actions) {
@ -84,13 +87,79 @@ final class SQLiteBooksDatabase extends BooksDatabase {
return id;
}
protected void listBooks() {
final Cursor cursor = myDatabase.rawQuery(
"SELECT Authors.name,Authors.sort_key,Books.title,Books.language,Books.encoding,Books.file_name FROM Books LEFT JOIN BookAuthor ON Books.book_id = BookAuthor.book_id LEFT JOIN Authors ON Authors.author_id = BookAuthor.author_id ORDER by Books.file_name", null);
protected Map<String,BookDescription> listBooks() {
Cursor cursor = myDatabase.rawQuery(
"SELECT book_id,file_name,title,encoding,language FROM Books", null
);
final int count = cursor.getCount();
final HashMap<Long,BookDescription> booksById = new HashMap<Long,BookDescription>(count);
final HashMap<String,BookDescription> booksByFilename = new HashMap<String,BookDescription>(count);
while (cursor.moveToNext()) {
System.err.println(cursor.getString(0) + ":" + cursor.getString(2));
final long id = cursor.getLong(0);
final String fileName = cursor.getString(1);
final BookDescription description = createDescription(
id, fileName, cursor.getString(2), cursor.getString(3), cursor.getString(4)
);
booksById.put(id, description);
booksByFilename.put(fileName, description);
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT author_id,name,sort_key FROM Authors", null
);
final HashMap<Long,Author> authorsById = new HashMap<Long,Author>(cursor.getCount());
while (cursor.moveToNext()) {
authorsById.put(cursor.getLong(0), new Author(cursor.getString(1), cursor.getString(2)));
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT book_id,author_id FROM BookAuthor ORDER BY author_index", null
);
while (cursor.moveToNext()) {
BookDescription book = booksById.get(cursor.getLong(0));
if (book != null) {
Author author = authorsById.get(cursor.getLong(1));
if (author != null) {
addAuthor(book, author);
}
}
}
cursor.close();
cursor = myDatabase.rawQuery("SELECT book_id,tag_id FROM BookTag", null);
while (cursor.moveToNext()) {
BookDescription book = booksById.get(cursor.getLong(0));
if (book != null) {
addTag(book, getTagById(cursor.getLong(1)));
}
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT series_id,name FROM Series", null
);
final HashMap<Long,String> seriesById = new HashMap<Long,String>(cursor.getCount());
while (cursor.moveToNext()) {
seriesById.put(cursor.getLong(0), cursor.getString(1));
}
cursor.close();
cursor = myDatabase.rawQuery(
"SELECT book_id,series_id,book_index FROM BookSeries", null
);
while (cursor.moveToNext()) {
BookDescription book = booksById.get(cursor.getLong(0));
if (book != null) {
String series = seriesById.get(cursor.getLong(1));
if (series != null) {
setSeriesInfo(book, series, cursor.getLong(2));
}
}
}
cursor.close();
return booksByFilename;
}
private SQLiteStatement myUpdateBookInfoStatement;
@ -169,7 +238,7 @@ final class SQLiteBooksDatabase extends BooksDatabase {
if (!cursor.moveToNext()) {
return null;
}
ArrayList<Author> list = new ArrayList<Author>(cursor.getCount());
final ArrayList<Author> list = new ArrayList<Author>(cursor.getCount());
do {
list.add(new Author(cursor.getString(0), cursor.getString(1)));
} while (cursor.moveToNext());
@ -415,4 +484,15 @@ final class SQLiteBooksDatabase extends BooksDatabase {
myDatabase.setTransactionSuccessful();
myDatabase.endTransaction();
}
private void updateTables2() {
myDatabase.beginTransaction();
myDatabase.execSQL("CREATE INDEX BookAuthor_BookIndex ON BookAuthor (book_id)");
myDatabase.execSQL("CREATE INDEX BookTag_BookIndex ON BookTag (book_id)");
myDatabase.execSQL("CREATE INDEX BookSeries_BookIndex ON BookSeries (book_id)");
myDatabase.setTransactionSuccessful();
myDatabase.endTransaction();
}
}

View file

@ -28,9 +28,7 @@ public final class ZLAndroidImageManager extends ZLImageManager {
if ("image/palm".equals(singleImage.mimeType())) {
return null;
}
System.err.println("array decoding + " + System.currentTimeMillis());
byte[] array = singleImage.byteData();
System.err.println("array decoding - " + System.currentTimeMillis());
if (array == null) {
return null;
}

View file

@ -7,8 +7,8 @@ public abstract class Decompressor {
public Decompressor(MyBufferedInputStream is, LocalFileHeader header) {
}
public abstract int read(byte b[], int off, int len) throws IOException, WrongZipFormatException;
public abstract int read() throws IOException, WrongZipFormatException;
public abstract int read(byte b[], int off, int len) throws IOException;
public abstract int read() throws IOException;
protected Decompressor() {
}
@ -23,8 +23,7 @@ public abstract class Decompressor {
}
}
public static Decompressor init(MyBufferedInputStream is, LocalFileHeader header)
throws WrongZipFormatException {
public static Decompressor init(MyBufferedInputStream is, LocalFileHeader header) throws ZipException {
switch (header.CompressionMethod) {
case 0:
return new NoCompressionDecompressor(is, header);
@ -38,7 +37,7 @@ public abstract class Decompressor {
}
return new DeflatingDecompressor(is, header);
default:
throw new WrongZipFormatException("Unsupported method of compression");
throw new ZipException("Unsupported method of compression");
}
}

View file

@ -62,7 +62,7 @@ public class DeflatingDecompressor extends Decompressor {
do {
int tmp = myStream.read();
if (tmp < 0) {
throw new RuntimeException("getBit: read after end of file");
throw new ZipException("getBit: read after end of file");
}
myTempInt += tmp << myBitsInBuffer;
myBitsInBuffer += 8;
@ -98,7 +98,7 @@ public class DeflatingDecompressor extends Decompressor {
private static final int MAX_LEN = CircularBuffer.DICTIONARY_LENGTH / 2;
public int read(byte b[], int off, int len) throws IOException, WrongZipFormatException {
public int read(byte b[], int off, int len) throws IOException {
int i = 0;
int available = myOutputBuffer.available();
while (i < len) {
@ -126,7 +126,7 @@ public class DeflatingDecompressor extends Decompressor {
return (i > 0) ? i : -1;
}
public int read() throws IOException, WrongZipFormatException {
public int read() throws IOException {
myCurrentPosition++;
while (myOutputBuffer.available() == 0) {
@ -248,7 +248,7 @@ public class DeflatingDecompressor extends Decompressor {
return tmp & 0x0FFFF;
}
private void readHeader() throws IOException, WrongZipFormatException {
private void readHeader() throws IOException {
if ((myState != ST_HEADER) || (myBytesRead >= myTotalLength)) {
throw new RuntimeException("unexpected case of readheader call");
}
@ -271,7 +271,7 @@ public class DeflatingDecompressor extends Decompressor {
readCodes();
break;
case 3:
throw new WrongZipFormatException(
throw new ZipException(
"Code 11 found in header of delflated block. (means error according to specification)");
}

View file

@ -32,10 +32,10 @@ final class MyBufferedInputStream extends InputStream {
public int read() throws IOException {
myCurrentPosition++;
if (myBytesReady == 0) {
if (myBytesReady <= 0) {
myPositionInBuffer = 0;
myBytesReady = myFileInputStream.read(myBuffer);
if (myBytesReady == 0) {
if (myBytesReady <= 0) {
return -1;
}
}
@ -77,14 +77,17 @@ final class MyBufferedInputStream extends InputStream {
myBytesReady -= n;
myPositionInBuffer += n;
} else {
n -= myBytesReady;
n -= myBytesReady;
myBytesReady = 0;
if (n > myFileInputStream.available()) {
throw new IOException("Not enough bytes to read");
}
n -= myFileInputStream.skip(n);
while (n > 0) {
int skipped = myFileInputStream.read(myBuffer, 0, Math.min(n, myBuffer.length));
if (skipped <= 0) {
break;
throw new IOException("Not enough bytes to read");
}
n -= skipped;
}

View file

@ -13,7 +13,7 @@ public class NoCompressionDecompressor extends Decompressor {
myStream = is;
}
public int read(byte b[], int off, int len) throws IOException, WrongZipFormatException {
public int read(byte b[], int off, int len) throws IOException {
int i = 0;
for (; i < len; ++i) {
int value = read();
@ -25,7 +25,7 @@ public class NoCompressionDecompressor extends Decompressor {
return (i > 0) ? i : -1;
}
public int read() throws IOException, WrongZipFormatException {
public int read() throws IOException {
if (myCurrentPosition < myHeader.getCompressedSize()) {
myCurrentPosition++;
return myStream.read();

View file

@ -1,12 +0,0 @@
package org.amse.ys.zip;
public class WrongZipFormatException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
WrongZipFormatException(String errorText) {
super(errorText);
}
}

View file

@ -0,0 +1,10 @@
package org.amse.ys.zip;
import java.io.IOException;
@SuppressWarnings("serial")
public class ZipException extends IOException {
ZipException(String message) {
super(message);
}
}

View file

@ -20,7 +20,6 @@ public final class ZipFile {
try {
readAllHeaders();
} catch (IOException e) {
} catch (WrongZipFormatException e) {
}
return myFileHeaders.values();
}
@ -50,7 +49,7 @@ public final class ZipFile {
return fileName.equals(fileToFind);
}
private void readAllHeaders() throws IOException, WrongZipFormatException {
private void readAllHeaders() throws IOException {
if (myAllFilesAreRead) {
return;
}
@ -67,7 +66,7 @@ public final class ZipFile {
if (header == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
break; // central directory, no more files
} else {
throw new WrongZipFormatException(
throw new ZipException(
"readHeaders. Wrong signature found = " + header
+ " at position " + baseStream.offset());
}
@ -88,7 +87,7 @@ public final class ZipFile {
do {
int nextByte = baseStream.read();
if (nextByte < 0) {
throw new IOException(
throw new ZipException(
"readFileHeaders. Unexpected end of file when looking for DataDescriptor");
}
signature = ((signature << 8) & (0x0FFFFFFFF)) + (byte) nextByte;
@ -117,7 +116,7 @@ public final class ZipFile {
return (baseStream != null) ? baseStream : new MyBufferedInputStream(myFileName);
}
private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException, WrongZipFormatException {
private ZipInputStream createZipInputStream(LocalFileHeader header) throws IOException {
return new ZipInputStream(this, header);
}
@ -125,11 +124,7 @@ public final class ZipFile {
if (!myFileHeaders.isEmpty()) {
LocalFileHeader header = myFileHeaders.get(entryName);
if (header != null) {
try {
return createZipInputStream(header);
} catch (WrongZipFormatException e) {
return null;
}
return createZipInputStream(header);
}
if (myAllFilesAreRead) {
return null;
@ -145,7 +140,7 @@ public final class ZipFile {
if (signature == LocalFileHeader.FOLDER_HEADER_SIGNATURE) {
break; // central directory, no more files
} else {
throw new IOException(
throw new ZipException(
"Wrong signature " + signature
+ " found at position " + baseStream.offset());
}
@ -155,7 +150,7 @@ public final class ZipFile {
if (header != null) {
try {
return createZipInputStream(header);
} catch (WrongZipFormatException e) {
} catch (ZipException e) {
}
}
} finally {

View file

@ -11,7 +11,7 @@ class ZipInputStream extends InputStream {
private final Decompressor myDecompressor;
private boolean myIsClosed;
public ZipInputStream(ZipFile parent, LocalFileHeader header) throws IOException, WrongZipFormatException {
public ZipInputStream(ZipFile parent, LocalFileHeader header) throws IOException {
myParent = parent;
myBaseStream = parent.getBaseStream();
myBaseStream.setPosition(header.OffsetOfLocalData);
@ -32,19 +32,11 @@ class ZipInputStream extends InputStream {
return 0;
}
try {
return myDecompressor.read(b, off, len);
} catch (WrongZipFormatException e) {
throw new IOException("when reading occured exception " + e.getMessage());
}
return myDecompressor.read(b, off, len);
}
public int read() throws IOException {
try {
return myDecompressor.read();
} catch (WrongZipFormatException e) {
throw new IOException("when reading occured exception " + e.getMessage());
}
return myDecompressor.read();
}
public void close() throws IOException {

View file

@ -58,7 +58,7 @@ public final class BookModel {
myBookTextModels.add(BookTextModel);
Description = description;
ZLFile file = new ZLFile(description.FileName);
FormatPlugin plugin = PluginCollection.instance().getPlugin(file, false);
FormatPlugin plugin = PluginCollection.instance().getPlugin(file);
if (plugin != null) {
plugin.readModel(description, this);
}

View file

@ -20,8 +20,9 @@
package org.geometerplus.fbreader.collection;
import java.util.*;
import java.io.File;
import org.geometerplus.zlibrary.core.filesystem.*;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.library.ZLibrary;
import org.geometerplus.fbreader.formats.PluginCollection;
@ -60,45 +61,59 @@ public class BookCollection {
return ZLibrary.JAR_DATA_PREFIX + "data/help/MiniHelp.en.fb2";
}
private HashSet collectBookFileNames() {
final HashSet dirs = collectDirNames();
final HashSet bookFileNames = new HashSet();
private void addDescription(LinkedList<BookDescription> list,
ZLFile physicalFile,
String fileName,
Map<String,BookDescription> saved) {
BookDescription description = BookDescription.getDescription(fileName, physicalFile, saved.get(fileName), false);
if (description != null) {
list.add(description);
}
}
for (Iterator it = dirs.iterator(); it.hasNext(); ) {
final ZLDir dir = new ZLFile((String)it.next()).getDirectory();
if (dir == null) {
private List<BookDescription> collectBookDescriptions() {
final Queue<String> dirNameQueue = new LinkedList<String>();
final HashSet<String> dirNameSet = new HashSet<String>();
final Map<String,BookDescription> savedDescriptions = BooksDatabase.Instance().listBooks();
final LinkedList<BookDescription> bookDescriptions = new LinkedList<BookDescription>();
addDescription(bookDescriptions, null, getHelpFileName(), savedDescriptions);
dirNameQueue.offer(BookDirectory);
while (!dirNameQueue.isEmpty()) {
String name = dirNameQueue.poll();
if (dirNameSet.contains(name)) {
continue;
}
final ArrayList files = dir.collectFiles();
if (files.isEmpty()) {
dirNameSet.add(name);
File[] items = new File(name).listFiles();
if (items == null) {
continue;
}
final int len = files.size();
for (int i = 0; i < len; ++i) {
final String fileName = dir.getItemPath((String)files.get(i));
final ZLFile file = new ZLFile(fileName);
if (PluginCollection.instance().getPlugin(file, true) != null) {
bookFileNames.add(fileName);
} else if (file.getExtension().equals("zip")) {
if (!BookDescriptionUtil.checkInfo(file)) {
BookDescriptionUtil.resetZipInfo(file);
BookDescriptionUtil.saveInfo(file);
}
final ArrayList zipEntries = new ArrayList();
BookDescriptionUtil.listZipEntries(file, zipEntries);
final int zipEntriesLen = zipEntries.size();
for (int j = 0; j < zipEntriesLen; ++j) {
final String entryName = (String)zipEntries.get(j);
if (!bookFileNames.contains(entryName)) {
bookFileNames.add(entryName);
for (File i : items) {
if (i.getName().startsWith(".")) {
continue;
}
final String fileName = i.getPath();
if (i.isDirectory()) {
dirNameQueue.add(fileName);
} else {
final ZLFile file = new ZLFile(i);
if (PluginCollection.instance().getPlugin(file) != null) {
addDescription(bookDescriptions, null, fileName, savedDescriptions);
} else if (file.isArchive()) {
if (!BookDescriptionUtil.checkInfo(file)) {
BookDescriptionUtil.resetZipInfo(file);
BookDescriptionUtil.saveInfo(file);
}
for (String entryName : BookDescriptionUtil.listZipEntries(file)) {
addDescription(bookDescriptions, file, entryName, savedDescriptions);
}
}
}
}
}
bookFileNames.add(getHelpFileName());
return bookFileNames;
return bookDescriptions;
}
private static class AuthorSeriesPair {
@ -141,14 +156,14 @@ public class BookCollection {
}
private void build() {
final HashSet fileNamesSet = collectBookFileNames();
System.err.println("before build: " + System.currentTimeMillis());
final HashMap<Tag,TagTree> tagTreeMap = new HashMap<Tag,TagTree>();
final HashMap<Author,AuthorTree> authorTreeMap = new HashMap<Author,AuthorTree>();
final HashMap<AuthorSeriesPair,SeriesTree> seriesTreeMap = new HashMap<AuthorSeriesPair,SeriesTree>();
for (Iterator it = fileNamesSet.iterator(); it.hasNext(); ) {
final BookDescription description = BookDescription.getDescription((String)it.next());
final List<BookDescription> allDescriptions = collectBookDescriptions();
System.err.println(allDescriptions.size() + " books");
for (BookDescription description : allDescriptions) {
List<Author> authors = description.authors();
if (authors.isEmpty()) {
authors = (List<Author>)ourNullList;
@ -182,6 +197,15 @@ public class BookCollection {
getTagTree(t, tagTreeMap).createBookSubTree(description);
}
}
BooksDatabase.Instance().executeAsATransaction(new Runnable() {
public void run() {
for (BookDescription description : allDescriptions) {
description.save();
}
}
});
System.err.println("after build: " + System.currentTimeMillis());
}
public void synchronize() {
@ -189,11 +213,7 @@ public class BookCollection {
myCollectionByAuthor.clear();
myCollectionByTag.clear();
BooksDatabase.Instance().executeAsATransaction(new Runnable() {
public void run() {
build();
}
});
build();
myCollectionByAuthor.sortAllChildren();
myCollectionByTag.sortAllChildren();
@ -211,170 +231,4 @@ public class BookCollection {
synchronize();
return myCollectionByTag;
}
private HashSet collectDirNames() {
ArrayList nameQueue = new ArrayList();
HashSet nameSet = new HashSet();
nameQueue.add(BookDirectory);
while (!nameQueue.isEmpty()) {
String name = (String)nameQueue.get(0);
nameQueue.remove(0);
if (!nameSet.contains(name)) {
ZLDir dir = new ZLFile(name).getDirectory();
if (dir != null) {
ArrayList subdirs = dir.collectSubDirs();
for (int i = 0; i < subdirs.size(); ++i) {
nameQueue.add(dir.getItemPath((String)subdirs.get(i)));
}
}
nameSet.add(name);
}
}
return nameSet;
}
/*
private static Author _author(ArrayList books, int index) {
return ((BookDescription)books.get(index)).getAuthor();
}
public void collectSeriesNames(Author author, HashSet set) {
synchronize();
final ArrayList books = myBooks;
if (books.isEmpty()) {
return;
}
int leftIndex = 0;
if (author.compareTo(_author(books, leftIndex)) < 0) {
return;
}
int rightIndex = books.size() - 1;
if (author.compareTo(_author(books, rightIndex)) > 0) {
return;
}
while (rightIndex > leftIndex) {
int middleIndex = leftIndex + (rightIndex - leftIndex) / 2;
final Author middleAuthor = _author(books, middleIndex);
final int result = author.compareTo(middleAuthor);
if (result > 0) {
leftIndex = middleIndex + 1;
} else if (result < 0) {
rightIndex = middleIndex;
} else {
for (int i = middleIndex; i >= 0; --i) {
BookDescription book = (BookDescription)books.get(i);
if (!author.equals(book.getAuthor())) {
break;
}
set.add(book.getSeriesName());
}
for (int i = middleIndex + 1; i <= rightIndex; ++i) {
BookDescription book = (BookDescription)books.get(i);
if (!author.equals(book.getAuthor())) {
break;
}
set.add(book.getSeriesName());
}
break;
}
}
}
public void removeTag(String tag, boolean includeSubTags) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
new BookDescription.WritableBookDescription(
(BookDescription)books.get(i)
).removeTag(tag, includeSubTags);
}
}
public void renameTag(String from, String to, boolean includeSubTags) {
final String checkedName = BookDescriptionUtil.removeWhiteSpacesFromTag(to);
if ((checkedName.length() > 0) && !checkedName.equals(from)) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
new BookDescription.WritableBookDescription((BookDescription)books.get(i)).renameTag(from, checkedName, includeSubTags);
}
}
}
public void cloneTag(String from, String to, boolean includeSubTags) {
final String checkedName = BookDescriptionUtil.removeWhiteSpacesFromTag(to);
if ((checkedName.length() > 0) && !checkedName.equals(from)) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
new BookDescription.WritableBookDescription((BookDescription)books.get(i)).cloneTag(from, checkedName, includeSubTags);
}
}
}
public void addTagToAllBooks(String tag) {
final String checkedName = BookDescriptionUtil.removeWhiteSpacesFromTag(tag);
if (checkedName.length() != 0) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
new BookDescription.WritableBookDescription((BookDescription)books.get(i)).addTag(checkedName, false);
}
}
}
public void addTagToBooksWithNoTags(String tag) {
final String checkedName = BookDescriptionUtil.removeWhiteSpacesFromTag(tag);
if (checkedName.length() != 0) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
BookDescription description = (BookDescription)books.get(i);
if (description.getTags().isEmpty()) {
new BookDescription.WritableBookDescription(description).addTag(checkedName, false);
}
}
}
}
public boolean hasBooks(String tag) {
synchronize();
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
final ArrayList tags = ((BookDescription)books.get(i)).getTags();
final int tagsLen = tags.size();
for (int j = 0; j < tagsLen; ++j) {
if (tag.equals(tags.get(j))) {
return true;
}
}
}
return false;
}
public boolean hasSubtags(String tag) {
synchronize();
final String prefix = tag + '/';
final ArrayList books = myBooks;
final int len = books.size();
for (int i = 0; i < len; ++i) {
final ArrayList tags = ((BookDescription)books.get(i)).getTags();
final int tagsLen = tags.size();
for (int j = 0; j < tagsLen; ++j) {
if (((String)tags.get(j)).startsWith(prefix)) {
return true;
}
}
}
return false;
}
*/
}

View file

@ -27,27 +27,32 @@ import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.fbreader.formats.*;
public class BookDescription {
private final static HashMap<String,BookDescription> ourDescriptions = new HashMap<String,BookDescription>();
public static BookDescription getDescription(String fileName) {
return getDescription(fileName, true);
return getDescription(fileName, null, null, true);
}
public static BookDescription getDescription(String fileName, boolean checkFile) {
static BookDescription getDescription(String fileName, ZLFile file, BookDescription description, boolean readFromDB) {
if (fileName == null) {
return null;
}
String physicalFileName = new ZLFile(fileName).getPhysicalFilePath();
ZLFile file = new ZLFile(physicalFileName);
if (checkFile && !file.exists()) {
return null;
final ZLFile bookFile = new ZLFile(fileName);
String physicalFileName;
if (file == null) {
physicalFileName = bookFile.getPhysicalFilePath();
file = new ZLFile(physicalFileName);
if (!file.exists()) {
return null;
}
} else {
physicalFileName = file.getPath();
}
BookDescription description = ourDescriptions.get(fileName);
if (description == null) {
description = new BookDescription(fileName);
ourDescriptions.put(fileName, description);
description = new BookDescription(fileName, readFromDB);
}
if ((!checkFile || BookDescriptionUtil.checkInfo(file)) && description.isSaved()) {
if (BookDescriptionUtil.checkInfo(file) && description.myIsSaved) {
return description;
}
@ -56,9 +61,7 @@ public class BookDescription {
}
BookDescriptionUtil.saveInfo(file);
ZLFile bookFile = new ZLFile(fileName);
FormatPlugin plugin = PluginCollection.instance().getPlugin(bookFile, false);
final FormatPlugin plugin = PluginCollection.instance().getPlugin(bookFile);
if ((plugin == null) || !plugin.readDescription(fileName, description)) {
return null;
}
@ -67,7 +70,6 @@ public class BookDescription {
if ((title == null) || (title.length() == 0)) {
description.setTitle(bookFile.getName(true));
}
description.save();
return description;
}
@ -78,34 +80,48 @@ public class BookDescription {
private String myEncoding;
private String myLanguage;
private String myTitle;
private ArrayList<Author> myAuthors;
private List<Author> myAuthors;
private ArrayList<Tag> myTags;
private SeriesInfo mySeriesInfo;
private boolean myIsSaved;
private boolean myIsChanged;
private BookDescription(String fileName) {
BookDescription(long bookId, String fileName, String title, String encoding, String language) {
myBookId = bookId;
FileName = fileName;
final BooksDatabase database = BooksDatabase.Instance();
myBookId = database.loadBook(this);
if (myBookId >= 0) {
myAuthors = database.loadAuthors(myBookId);
myTags = database.loadTags(myBookId);
mySeriesInfo = database.loadSeriesInfo(myBookId);
myIsSaved = true;
myIsChanged = false;
}
myTitle = title;
myEncoding = encoding;
myLanguage = language;
myIsSaved = true;
}
public boolean isSaved() {
return myIsSaved;
private BookDescription(String fileName, boolean createFromDatabase) {
FileName = fileName;
if (createFromDatabase) {
final BooksDatabase database = BooksDatabase.Instance();
myBookId = database.loadBook(this);
if (myBookId >= 0) {
myAuthors = database.loadAuthors(myBookId);
myTags = database.loadTags(myBookId);
mySeriesInfo = database.loadSeriesInfo(myBookId);
myIsSaved = true;
}
} else {
myBookId = -1;
}
}
public List<Author> authors() {
return (myAuthors != null) ? Collections.unmodifiableList(myAuthors) : Collections.<Author>emptyList();
}
void addAuthorWithNoCheck(Author author) {
if (myAuthors == null) {
myAuthors = new ArrayList<Author>();
}
myAuthors.add(author);
}
private void addAuthor(Author author) {
if (author == null) {
return;
@ -113,12 +129,10 @@ public class BookDescription {
if (myAuthors == null) {
myAuthors = new ArrayList<Author>();
myAuthors.add(author);
myIsChanged = true;
} else {
if (!myAuthors.contains(author)) {
myAuthors.add(author);
myIsChanged = true;
}
myIsSaved = false;
} else if (!myAuthors.contains(author)) {
myAuthors.add(author);
myIsSaved = false;
}
}
@ -151,6 +165,10 @@ public class BookDescription {
addAuthor(new Author(strippedName, strippedKey));
}
public long getBookId() {
return myBookId;
}
public String getTitle() {
return myTitle;
}
@ -158,7 +176,7 @@ public class BookDescription {
public void setTitle(String title) {
if (!ZLMiscUtil.equals(myTitle, title)) {
myTitle = title;
myIsChanged = true;
myIsSaved = false;
}
}
@ -166,15 +184,22 @@ public class BookDescription {
return mySeriesInfo;
}
void setSeriesInfoWithNoCheck(String name, long index) {
mySeriesInfo = new SeriesInfo(name, index);
}
public void setSeriesInfo(String name, long index) {
if (mySeriesInfo == null) {
if (name != null) {
mySeriesInfo = new SeriesInfo(name, index);
myIsSaved = false;
}
} else if (name == null) {
mySeriesInfo = null;
myIsSaved = false;
} else if (!mySeriesInfo.Name.equals(name) || (mySeriesInfo.Index != index)) {
mySeriesInfo = new SeriesInfo(name, index);
myIsSaved = false;
}
}
@ -185,7 +210,7 @@ public class BookDescription {
public void setLanguage(String language) {
if (!ZLMiscUtil.equals(myLanguage, language)) {
myLanguage = language;
myIsChanged = true;
myIsSaved = false;
}
}
@ -196,7 +221,7 @@ public class BookDescription {
public void setEncoding(String encoding) {
if (!ZLMiscUtil.equals(myEncoding, encoding)) {
myEncoding = encoding;
myIsChanged = true;
myIsSaved = false;
}
}
@ -204,6 +229,13 @@ public class BookDescription {
return (myTags != null) ? Collections.unmodifiableList(myTags) : Collections.<Tag>emptyList();
}
void addTagWithNoCheck(Tag tag) {
if (myTags == null) {
myTags = new ArrayList<Tag>();
}
myTags.add(tag);
}
public void addTag(Tag tag) {
if (tag != null) {
if (myTags == null) {
@ -211,7 +243,7 @@ public class BookDescription {
}
if (!myTags.contains(tag)) {
myTags.add(tag);
myIsChanged = true;
myIsSaved = false;
}
}
}
@ -221,7 +253,7 @@ public class BookDescription {
}
public boolean save() {
if (!myIsChanged) {
if (myIsSaved) {
return false;
}
final BooksDatabase database = BooksDatabase.Instance();
@ -246,7 +278,6 @@ public class BookDescription {
}
});
myIsChanged = false;
myIsSaved = true;
return true;
}

View file

@ -29,7 +29,7 @@ import org.geometerplus.zlibrary.core.options.ZLStringOption;
import org.geometerplus.fbreader.formats.PluginCollection;
public class BookDescriptionUtil {
class BookDescriptionUtil {
private static final String SIZE = "Size";
private static final String ENTRY = "Entry";
private static final String ENTRIES_NUMBER = "EntriesNumber";
@ -43,21 +43,22 @@ public class BookDescriptionUtil {
new ZLIntegerOption(file.getPath(), SIZE, -1).setValue((int)file.size());
}
public static void listZipEntries(ZLFile zipFile, ArrayList entries) {
private static final ArrayList<String> EMPTY = new ArrayList<String>();
public static ArrayList<String> listZipEntries(ZLFile zipFile) {
int entriesNumber = new ZLIntegerOption(zipFile.getPath(), ENTRIES_NUMBER, -1).getValue();
if (entriesNumber == -1) {
resetZipInfo(zipFile);
entriesNumber = new ZLIntegerOption(zipFile.getPath(), ENTRIES_NUMBER, -1).getValue();
if (entriesNumber <= 0) {
return EMPTY;
}
final ZLStringOption entryOption =
new ZLStringOption(zipFile.getPath(), "", "");
final ZLStringOption entryOption = new ZLStringOption(zipFile.getPath(), "", "");
final ArrayList<String> zipEntries = new ArrayList<String>(entriesNumber);
for (int i = 0; i < entriesNumber; ++i) {
entryOption.changeName(ENTRY + i);
final String entry = entryOption.getValue();
if (entry.length() != 0) {
entries.add(entry);
zipEntries.add(entry);
}
}
return zipEntries;
}
public static void resetZipInfo(ZLFile zipFile) {
@ -73,7 +74,7 @@ public class BookDescriptionUtil {
String entry = (String)entries.get(i);
final ZLStringOption entryOption =
new ZLStringOption(zipFile.getPath(), "", "");
if (PluginCollection.instance().getPlugin(new ZLFile(entry), true) != null) {
if (PluginCollection.instance().getPlugin(new ZLFile(entry)) != null) {
final String fullName = zipPrefix + entry;
entryOption.changeName(ENTRY + counter);
entryOption.setValue(fullName);

View file

@ -19,6 +19,7 @@
package org.geometerplus.fbreader.collection;
import java.util.Map;
import java.util.ArrayList;
public abstract class BooksDatabase {
@ -32,6 +33,23 @@ public abstract class BooksDatabase {
ourInstance = this;
}
protected BookDescription createDescription(long bookId, String fileName, String title, String encoding, String language) {
return new BookDescription(bookId, fileName, title, encoding, language);
}
protected void addAuthor(BookDescription description, Author author) {
description.addAuthorWithNoCheck(author);
}
protected void addTag(BookDescription description, Tag tag) {
description.addTagWithNoCheck(tag);
}
protected void setSeriesInfo(BookDescription description, String series, long index) {
description.setSeriesInfoWithNoCheck(series, index);
}
protected abstract Map<String,BookDescription> listBooks();
protected abstract void executeAsATransaction(Runnable actions);
protected abstract long loadBook(BookDescription description);
protected abstract ArrayList<Author> loadAuthors(long bookId);

View file

@ -29,13 +29,7 @@ import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.language.ZLLanguageDetector;
public abstract class FormatPlugin {
public abstract boolean providesMetaInfo();
public abstract boolean acceptsFile(ZLFile file);
public abstract String getIconName();
public String tryOpen(String path) {
return "";
}
public abstract boolean readDescription(String path, BookDescription description);
public abstract boolean readModel(BookDescription description, BookModel model);

View file

@ -31,7 +31,8 @@ import org.geometerplus.fbreader.formats.plucker.PluckerPlugin;
public class PluginCollection {
private static PluginCollection ourInstance;
private final ArrayList myPlugins = new ArrayList();
private final ArrayList<FormatPlugin> myPlugins = new ArrayList<FormatPlugin>();
public ZLStringOption DefaultLanguageOption;
public ZLStringOption DefaultEncodingOption;
public ZLBooleanOption LanguageAutoDetectOption;
@ -40,7 +41,7 @@ public class PluginCollection {
if (ourInstance == null) {
ourInstance = new PluginCollection();
ourInstance.myPlugins.add(new FB2Plugin());
ourInstance.myPlugins.add(new PluckerPlugin());
//ourInstance.myPlugins.add(new PluckerPlugin());
//ourInstance->myPlugins.push_back(new DocBookPlugin());
//ourInstance.myPlugins.add(new HtmlPlugin());
/*ourInstance.myPlugins.add(new TxtPlugin());
@ -69,13 +70,10 @@ public class PluginCollection {
DefaultEncodingOption = new ZLStringOption("Format", "DefaultEncoding", "windows-1252");
}
public FormatPlugin getPlugin(ZLFile file, boolean strong) {
final ArrayList plugins = myPlugins;
final int numberOfPlugins = plugins.size();
for (int i = 0; i < numberOfPlugins; ++i) {
FormatPlugin fp = (FormatPlugin)plugins.get(i);
if ((!strong || fp.providesMetaInfo()) && fp.acceptsFile(file)) {
return fp;
public FormatPlugin getPlugin(ZLFile file) {
for (FormatPlugin plugin : myPlugins) {
if (plugin.acceptsFile(file)) {
return plugin;
}
}
return null;

View file

@ -25,10 +25,6 @@ import org.geometerplus.fbreader.formats.FormatPlugin;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
public class FB2Plugin extends FormatPlugin {
public boolean providesMetaInfo() {
return true;
}
public boolean acceptsFile(ZLFile file) {
return "fb2".equals(file.getExtension());
}
@ -40,8 +36,4 @@ public class FB2Plugin extends FormatPlugin {
public boolean readModel(BookDescription description, BookModel model) {
return new FB2Reader(model).readBook(description.FileName);
}
public String getIconName() {
return "fb2";
}
}

View file

@ -36,17 +36,6 @@ public class HtmlPlugin extends FormatPlugin {
|| "html".equals(file.getExtension());
}
@Override
public String getIconName() {
final String ICON_NAME = "html";
return ICON_NAME;
}
@Override
public boolean providesMetaInfo() {
return true;
}
@Override
public boolean readDescription(String path, BookDescription description) {
return new HtmlDescriptionReader(description).readDescription(path);

View file

@ -27,10 +27,6 @@ import org.geometerplus.fbreader.formats.FormatPlugin;
import org.geometerplus.zlibrary.core.filesystem.*;
public class OEBPlugin extends FormatPlugin {
public boolean providesMetaInfo() {
return true;
}
public boolean acceptsFile(ZLFile file) {
final String extension = file.getExtension().intern();
return (extension == "opf") || (extension == "oebzip") || (extension == "epub");
@ -74,8 +70,4 @@ public class OEBPlugin extends FormatPlugin {
}
return new OEBBookReader(model).readBook(path);
}
public String getIconName() {
return "oeb";
}
}

View file

@ -22,7 +22,7 @@ package org.geometerplus.fbreader.formats.pdb;
import java.io.IOException;
import java.io.InputStream;
import org.geometerplus.fbreader.collection.BookDescriptionUtil;
//import org.geometerplus.fbreader.collection.BookDescriptionUtil;
import org.geometerplus.fbreader.formats.FormatPlugin;
import org.geometerplus.fbreader.formats.plucker.PluckerTextStream;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
@ -38,7 +38,7 @@ public abstract class PdbPlugin extends FormatPlugin {
String fileName = file.getPath();
int index = fileName.indexOf(':');
ZLFile baseFile = (index == -1) ? file : new ZLFile(fileName.substring(0, index));
boolean upToDate = BookDescriptionUtil.checkInfo(baseFile);
boolean upToDate = true;//BookDescriptionUtil.checkInfo(baseFile);
ZLStringOption palmTypeOption = new ZLStringOption(file.getPath(), "PalmType", "");
String palmType = palmTypeOption.getValue();
@ -58,18 +58,10 @@ public abstract class PdbPlugin extends FormatPlugin {
}
palmType = new String(id);
if (!upToDate) {
BookDescriptionUtil.saveInfo(baseFile);
//BookDescriptionUtil.saveInfo(baseFile);
}
palmTypeOption.setValue(palmType);
}
return palmType;
}
public String getIconName() {
return "pdb";
}
public boolean providesMetaInfo() {
return false;
}
}

View file

@ -28,10 +28,6 @@ import org.geometerplus.fbreader.formats.pdb.PdbStream;
import org.geometerplus.zlibrary.core.filesystem.ZLFile;
public class PluckerPlugin extends PdbPlugin {
public boolean providesMetaInfo() {
return false;
}
public boolean acceptsFile(ZLFile file) {
return "DataPlkr".equals(fileType(file));
}
@ -64,8 +60,4 @@ public class PluckerPlugin extends PdbPlugin {
}
return false;
}
public String getIconName() {
return "plucker";
}
}

View file

@ -84,7 +84,6 @@ public abstract class ZLDir {
}
abstract public ArrayList collectSubDirs();
abstract public ArrayList collectFiles();
abstract protected String getDelimiter();
}

View file

@ -38,26 +38,6 @@ class ZLFSDir extends ZLDir {
return File.separator;
};
public ArrayList collectSubDirs() {
File[] dirs = myFile.listFiles();
ArrayList/*<String>*/ newdirs = new ArrayList();
if ((dirs == null) && isRoot()) {
dirs = File.listRoots();
for(int i = 0; i < dirs.length; i++) {
newdirs.add(dirs[i].getPath());
}
} else if (dirs != null) {
for(int i = 0; i < dirs.length; i++) {
if (dirs[i].isDirectory()) {
newdirs.add(dirs[i].getName());
}
}
}
return newdirs;
};
public ArrayList/*<String>*/ collectFiles() {
File[] dirs = myFile.listFiles();
ArrayList/*<String>*/ newdirs = new ArrayList();

View file

@ -26,19 +26,6 @@ import org.geometerplus.zlibrary.core.util.*;
import org.geometerplus.zlibrary.core.library.ZLibrary;
abstract class ZLFSUtil {
static String normalize(String path) {
if (getRootDirectoryPath().equals(path)) {
return path;
}
try {
path = new File(path).getCanonicalPath();
} catch (IOException e) {
}
return path;
}
//public OutputStream createOutputStream(String path);
static ZLDir getRootDirectory() {
return new ZLFSDir(getRootDirectoryPath());
}
@ -67,10 +54,7 @@ abstract class ZLFSUtil {
if (path.startsWith(ZLibrary.JAR_DATA_PREFIX)) {
return (index < ZLibrary.JAR_DATA_PREFIX.length()) ? -1 : index;
}
if (System.getProperty("os.name").startsWith("Windows")) {
return (index == 1) ? -1 : index;
}
return index;
return (index == 1) ? -1 : index;
}
static int findLastFileNameDelimiter(String path) {

View file

@ -40,7 +40,7 @@ public class ZLFile {
private final String myPath;
private final String myNameWithExtension;
private String myNameWithoutExtension;
private final String myExtension;
private String myExtension;
private int myArchiveType;
private ZLFileInfo myInfo;
@ -88,6 +88,16 @@ public class ZLFile {
}
}
public ZLFile(File file) {
myPath = file.getPath();
myInfo = new ZLFileInfo();
myInfo.Exists = file.exists();
myInfo.Size = file.length();
myInfo.IsDirectory = file.isDirectory();
myNameWithExtension = file.getName();
init();
}
public ZLFile(String path) {
if (path.startsWith(ZLibrary.JAR_DATA_PREFIX)) {
myInfo = new ZLFileInfo();
@ -95,7 +105,7 @@ public class ZLFile {
myPath = path;
myNameWithExtension = path;
} else {
myPath = ZLFSUtil.normalize(path);
myPath = path;
int index = ZLFSUtil.findLastFileNameDelimiter(myPath);
if (index < myPath.length() - 1) {
myNameWithExtension = myPath.substring(index + 1);
@ -103,6 +113,10 @@ public class ZLFile {
myNameWithExtension = myPath;
}
}
init();
}
private void init() {
myNameWithoutExtension = myNameWithExtension;
Integer value = (Integer)ourForcedFiles.get(myPath);
@ -127,7 +141,7 @@ public class ZLFile {
myArchiveType = myArchiveType | ArchiveType.ZIP;
} else if (lowerCaseName.endsWith(".tar")) {
myArchiveType = myArchiveType | ArchiveType.TAR;
} else if (lowerCaseName.endsWith(".tgz") || lowerCaseName.endsWith(".ipk")) {
} else if (lowerCaseName.endsWith(".tgz")) {
//nothing to-do myNameWithoutExtension = myNameWithoutExtension.substr(0, myNameWithoutExtension.length() - 3) + "tar";
myArchiveType = myArchiveType | ArchiveType.TAR | ArchiveType.GZIP;
}

View file

@ -32,11 +32,6 @@ class ZLTarDir extends ZLDir {
return ":";
};
private static ArrayList EMPTY = new ArrayList();
public ArrayList collectSubDirs() {
return EMPTY;
};
public ArrayList collectFiles() {
ArrayList names = new ArrayList();

View file

@ -37,9 +37,6 @@ public class ZLZipDir extends ZLDir {
};
private static final ArrayList EMPTY = new ArrayList();
public ArrayList collectSubDirs() {
return EMPTY;
};
public ArrayList/*<String>*/ collectFiles() {
ZipFile zf = null;