/*****************************************************************************
* This file is part of Rinzo
*
* Author: Claudio Cancinos
* WWW: https://sourceforge.net/projects/editorxml
* Copyright (C): 2008, Claudio Cancinos
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser 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 Lesser General Public
* License along with this program; If not, see <http://www.gnu.org/licenses/>
****************************************************************************/
package ar.com.tadp.xml.rinzo.core.resources.cache;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import ar.com.tadp.xml.rinzo.core.utils.FileUtils;
/**
* @author ccancinos
*/
public class CacheDefinitionsSerializer {
private static final String NULPUB = "<pub null='true'/>";
private static final String BEGPUB = "<pub>";
private static final String ENDPUB = "</pub>";
private static final String NULABS = "<abs null='true'/>";
private static final String BEGABS = "<abs>";
private static final String ENDABS = "</abs>";
private static final String BEGREL = "<rel>";
private static final String ENDREL = "</rel>";
private static final String BEGFIL = "<file>";
private static final String ENDFIL = "</file>";
private static final String INDENT = " ";
private static final String FILE_START = "<?xml version='1.0' encoding='UTF-8'?>" + FileUtils.EOL +
"<!-- Cached file directory. Do not edit this file by hand -->" + FileUtils.EOL +
"<meta>" + FileUtils.EOL;
private static final String FILE_END = "</meta>" + FileUtils.EOL;
private static final MessageFormat FULL_FILE_DEF = new MessageFormat(
INDENT + "<file>" + FileUtils.EOL +
INDENT + INDENT + "<pub>{0}</pub>" + FileUtils.EOL +
INDENT + INDENT + "<abs>{1}</abs>" + FileUtils.EOL +
INDENT + INDENT + "<rel>{2}</rel>" + FileUtils.EOL +
INDENT + "</file>"
);
private static final MessageFormat NO_PUB_FILE_DEF = new MessageFormat(
INDENT + "<file>" + FileUtils.EOL +
INDENT + INDENT + "<pub null='true'/>" + FileUtils.EOL +
INDENT + INDENT + "<abs>{1}</abs>" + FileUtils.EOL +
INDENT + INDENT + "<rel>{2}</rel>" + FileUtils.EOL +
INDENT + "</file>"
);
/**
* Levanta las el mapeo de los documentos cacheados de la persistencia en
* xml
* @param cacheDefinitionsFile
*/
public Collection<DocumentStructureDeclaration> getCacheDefinitions(File cacheDefinitionsFile) throws IOException {
Collection<DocumentStructureDeclaration> entries = new ArrayList<DocumentStructureDeclaration>();
char ac[] = FileUtils.readContents(fileReader(cacheDefinitionsFile));
int i = 0;
int j = ac.length;
do {
i = skipto('<', ac, i, j);
if (i != j) {
boolean flag = match(BEGPUB, ac, i, j);
if (!flag && !match(NULPUB, ac, i, j)) {
i++;
} else {
String s = null;
if (flag) {
i += BEGPUB.length();
int k = i;
i = skipto('<', ac, i, j);
if (i == j || !match(ENDPUB, ac, i, j))
throw new IllegalStateException("Missing " + ENDPUB + " in meta file");
s = decode(new String(ac, k, i - k));
i += ENDPUB.length();
} else {
i += NULPUB.length();
}
String s1 = null;
i = skipto('<', ac, i, j);
if (match(NULABS, ac, i, j)) {
i += NULABS.length();
} else {
if (i == j || !match(BEGABS, ac, i, j))
throw new IllegalStateException("Missing " + NULABS + " in meta file");
i += BEGABS.length();
int l = i;
i = skipto('<', ac, i, j);
if (i == j || !match(ENDABS, ac, i, j))
throw new IllegalStateException("Missing </abs> in meta file");
s1 = decode(new String(ac, l, i - l));
i += ENDABS.length();
}
i = skipto('<', ac, i, j);
if (i == j || !match(BEGREL, ac, i, j))
throw new IllegalStateException("Missing <rel> in meta file");
i += BEGREL.length();
int i1 = i;
i = skipto('<', ac, i, j);
if (i == j || !match(ENDREL, ac, i, j))
throw new IllegalStateException("Missing </rel> in meta file");
String s2 = new String(ac, i1, i - i1);
i += ENDREL.length();
//FIXME URGENT!!! aca se comprobaba que el nombre del archivo en cache termine con un n�mero menor al de fMaxRel.
// try {
// int j1 = Integer.parseInt(s2.substring(1));
// if (fMaxRel < j1)
// fMaxRel = j1;
// } catch (NumberFormatException _ex) {
// throw new IllegalStateException("Unknown rel format " + s2);
// }
entries.add(new DocumentStructureDeclaration(s, s1, s2));
}
} else {
return entries;
}
} while (true);
}
public void saveCacheDefinitions(File cacheDefinitionsFile, Collection<DocumentStructureDeclaration> entries) {
Writer writer = fileWriter(cacheDefinitionsFile);
try {
writer.write(FILE_START);
for (DocumentStructureDeclaration structureDeclaration : entries) {
Object[] params = {this.encode(structureDeclaration.getPublicId()), this.encode(structureDeclaration.getSystemId()), structureDeclaration.getLocalCachedName()};
MessageFormat formatter = (structureDeclaration.getPublicId() == null) ? NO_PUB_FILE_DEF : FULL_FILE_DEF;
writer.write(formatter.format(params));
}
writer.write(FILE_END);
} catch (Exception e) {
throw new RuntimeException("Error trying to write the cached file directory",e);
} finally {
try {
writer.close();
} catch (IOException exception) {
throw new RuntimeException("Error trying to clse the cached file directory", exception);
}
}
return;
}
public void saveCacheDefinitionsOld(File cacheDefinitionsFile, Collection<DocumentStructureDeclaration> entries) {
Writer writer = fileWriter(cacheDefinitionsFile);
try {
writer.write("<?xml version='1.0' encoding='UTF-8'?>");
writeEOL(writer);
writer.write("<!-- Cached file directory. Do not edit this file by hand -->");
writeEOL(writer);
writer.write("<meta>");
writeEOL(writer);
for (DocumentStructureDeclaration structureDeclaration : entries) {
writer.write(" " + BEGFIL);
writeEOL(writer);
if (structureDeclaration.getPublicId() != null) {
writer.write(" " + BEGPUB);
writer.write(encode(structureDeclaration.getPublicId()));
writer.write(ENDPUB);
} else {
writer.write(" " + NULPUB);
}
writeEOL(writer);
if (structureDeclaration.getSystemId() != null) {
writer.write(" " + BEGABS);
writer.write(encode(structureDeclaration.getSystemId()));
writer.write(ENDABS);
} else {
writer.write(" " + NULABS);
}
writeEOL(writer);
writer.write(" " + BEGREL);
writer.write(structureDeclaration.getLocalCachedName());
writer.write(ENDREL);
writeEOL(writer);
writer.write(" " + ENDFIL);
}
writer.write("</meta>");
writeEOL(writer);
} catch (Exception e) {
throw new RuntimeException("Error trying to write the cached file directory",e);
} finally {
try {
writer.close();
} catch (IOException exception) {
throw new RuntimeException("Error trying to clse the cached file directory", exception);
}
}
return;
}
private int skipto(char c, char ac[], int i, int j) {
for (; i < j && ac[i] != c; i++)
if (ac[i] == c)
break;
return i;
}
private boolean match(String s, char ac[], int i, int j) {
int k = i + s.length();
if (k > j)
return false;
int l = 0;
for (; i < k; i++) {
if (ac[i] != s.charAt(l))
return false;
l++;
}
return true;
}
private String decode(String s) {
StringBuffer stringbuffer = new StringBuffer();
char ac[] = s.toCharArray();
int i = 0;
for (int j = ac.length; i < j; i++)
if (ac[i] == '&') {
if (match("<", ac, i, j)) {
stringbuffer.append('<');
i += 3;
} else if (match("&", ac, i, j)) {
stringbuffer.append('&');
i += 4;
} else {
stringbuffer.append('&');
}
} else {
stringbuffer.append(ac[i]);
}
return stringbuffer.toString();
}
private void writeEOL(Writer writer) throws IOException {
writer.write(FileUtils.EOL);
}
private String encode(String s) {
StringBuffer stringbuffer = new StringBuffer();
int i = 0;
for (int j = s.length(); i < j; i++) {
char c = s.charAt(i);
if (c == '<')
stringbuffer.append("<");
else if (c == '&')
stringbuffer.append("&");
else
stringbuffer.append(c);
}
return stringbuffer.toString();
}
private Reader fileReader(File file) throws IOException {
return new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
}
private Writer fileWriter(File file) {
try {
return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
} catch (Exception exception) {
throw new RuntimeException("Error trying to create a writer for a file", exception);
}
}
}