mirror of
https://github.com/yacy/yacy_search_server.git
synced 2024-09-21 00:00:13 +02:00
1d8d51075c
- removed the plasma package. The name of that package came from a very early pre-version of YaCy, even before YaCy was named AnomicHTTPProxy. The Proxy project introduced search for cache contents using class files that had been developed during the plasma project. Information from 2002 about plasma can be found here: http://web.archive.org/web/20020802110827/http://anomic.de/AnomicPlasma/index.html We stil have one class that comes mostly unchanged from the plasma project, the Condenser class. But this is now part of the document package and all other classes in the plasma package can be assigned to other packages. - cleaned up the http package: better structure of that class and clean isolation of server and client classes. The old HTCache becomes part of the client sub-package of http. - because the plasmaSwitchboard is now part of the search package all servlets had to be touched to declare a different package source. git-svn-id: https://svn.berlios.de/svnroot/repos/yacy/trunk@6232 6c8d7289-2bf4-0310-a012-ef5d649a1542
568 lines
26 KiB
Java
568 lines
26 KiB
Java
//httpTemplate.java
|
|
//-------------------------------------
|
|
//(C) by Michael Peter Christen; mc@yacy.net
|
|
//first published on http://www.anomic.de
|
|
//Frankfurt, Germany, 2004
|
|
//last major change: 16.01.2005
|
|
|
|
//$LastChangedDate$
|
|
//$LastChangedRevision$
|
|
//$LastChangedBy$
|
|
|
|
//extended for multi- and alternatives-templates by Alexander Schier
|
|
|
|
//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
|
|
|
|
//Using this software in any meaning (reading, learning, copying, compiling,
|
|
//running) means that you agree that the Author(s) is (are) not responsible
|
|
//for cost, loss of data or any harm that may be caused directly or indirectly
|
|
//by usage of this softare or this documentation. The usage of this software
|
|
//is on your own risk. The installation and usage (starting/running) of this
|
|
//software may allow other people or application to access your computer and
|
|
//any attached devices and is highly dependent on the configuration of the
|
|
//software which must be done by the user of the software; the author(s) is
|
|
//(are) also not responsible for proper configuration and usage of the
|
|
//software, even if provoked by documentation provided together with
|
|
//the software.
|
|
|
|
//Any changes to this file according to the GPL as documented in the file
|
|
//gpl.txt aside this file in the shipment you received can be done to the
|
|
//lines that follows this copyright notice here, but changes must not be
|
|
//done inside the copyright notice above. A re-distribution must contain
|
|
//the intact and unchanged copyright notice.
|
|
//Contributions and changes to the program code must be marked as such.
|
|
|
|
package de.anomic.http.server;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.io.PushbackInputStream;
|
|
import java.io.UnsupportedEncodingException;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
|
|
import de.anomic.kelondro.util.ByteBuffer;
|
|
import de.anomic.kelondro.util.FileUtils;
|
|
import de.anomic.yacy.logging.Log;
|
|
|
|
/**
|
|
* A template engine, which substitutes patterns in strings<br>
|
|
*
|
|
* The template engine supports four types of templates:<br>
|
|
* <ol>
|
|
* <li>Normal templates: the template will be replaced by a string.</li>
|
|
* <li>Multi templates: the template will be used more than one time.<br>
|
|
* i.e. for lists</li>
|
|
* <li>3. Alternatives: the program chooses one of multiple alternatives.</li>
|
|
* <li>Includes: another file with templates will be included.</li>
|
|
* </ol>
|
|
*
|
|
* All these templates can be used recursivly.<p>
|
|
* <b>HTML-Example</b><br>
|
|
* <pre>
|
|
* <html><head></head><body>
|
|
* #{times}#
|
|
* Good #(daytime)#morning::evening#(/daytime)#, #[name]#!(#[num]#. Greeting)<br>
|
|
* #{/times}#
|
|
* </body></html>
|
|
* </pre>
|
|
* <p>
|
|
* The corresponding Hashtable to use this Template:<br>
|
|
* <b>Java Example</b><br>
|
|
* <pre>
|
|
* Hashtable pattern;
|
|
* pattern.put("times", 10); //10 greetings
|
|
* for(int i=0;i<=9;i++){
|
|
* pattern.put("times_"+i+"_daytime", 1); //index: 1, second Entry, evening
|
|
* pattern.put("times_"+i+"_name", "John Connor");
|
|
* pattern.put("times_"+i+"_num", (i+1));
|
|
* }
|
|
* </pre>
|
|
* <p>
|
|
* <b>Recursion</b><br>
|
|
* If you use recursive templates, the templates will be used from
|
|
* the external to the internal templates.
|
|
* In our Example, the Template in #{times}##{/times}# will be repeated ten times.<br>
|
|
* Then the inner Templates will be applied.
|
|
* <p>
|
|
* The inner templates have a prefix, so they may have the same name as a template on another level,
|
|
* or templates which are in another recursive template.<br>
|
|
* <b>The Prefixes:</b>
|
|
* <ul>
|
|
* <li>Multi templates: multitemplatename_index_</li>
|
|
* <li>Alterantives: alternativename_</li>
|
|
* </ul>
|
|
* So the Names in the Hashtable are:
|
|
* <ul>
|
|
* <li>Multi templates: multitemplatename_index_templatename</li>
|
|
* <li>Alterantives: alternativename_templatename</li>
|
|
* </ul>
|
|
* <i>#(alternative)#::#{repeat}##[test]##{/repeat}##(/alternative)#</i><br>
|
|
* would be adressed as "alternative_repeat_"+number+"_test"
|
|
*/
|
|
public final class TemplateEngine {
|
|
|
|
public final static byte hash = (byte)'#';
|
|
|
|
public final static byte[] dpdpa = "::".getBytes();
|
|
|
|
private final static byte lbr = (byte)'[';
|
|
private final static byte rbr = (byte)']';
|
|
private final static byte[] pOpen = {hash, lbr};
|
|
private final static byte[] pClose = {rbr, hash};
|
|
|
|
private final static byte lcbr = (byte)'{';
|
|
private final static byte rcbr = (byte)'}';
|
|
private final static byte[] mOpen = {hash, lcbr};
|
|
private final static byte[] mClose = {rcbr, hash};
|
|
|
|
private final static byte lrbr = (byte)'(';
|
|
private final static byte rrbr = (byte)')';
|
|
private final static byte[] aOpen = {hash, lrbr};
|
|
private final static byte[] aClose = {rrbr, hash};
|
|
|
|
private final static byte ps = (byte)'%';
|
|
private final static byte[] iOpen = {hash, ps};
|
|
private final static byte[] iClose = {ps, hash};
|
|
|
|
private final static byte[] slash = {(byte)'/'};
|
|
|
|
private final static Object[] meta_quotation = new Object[] {
|
|
new Object[] {pOpen, pClose},
|
|
new Object[] {mOpen, mClose},
|
|
new Object[] {aOpen, aClose},
|
|
new Object[] {iOpen, iClose}
|
|
};
|
|
|
|
public final static ByteBuffer[] splitQuotations(final ByteBuffer text) {
|
|
final List<ByteBuffer> l = splitQuotation(text, 0);
|
|
final ByteBuffer[] sbbs = new ByteBuffer[l.size()];
|
|
for (int i = 0; i < l.size(); i++) sbbs[i] = l.get(i);
|
|
return sbbs;
|
|
}
|
|
|
|
private final static List<ByteBuffer> splitQuotation(ByteBuffer text, int qoff) {
|
|
final ArrayList<ByteBuffer> l = new ArrayList<ByteBuffer>();
|
|
if (qoff >= meta_quotation.length) {
|
|
if (text.length() > 0) l.add(text);
|
|
return l;
|
|
}
|
|
int p = -1, q;
|
|
final byte[] left = (byte[]) ((Object[]) meta_quotation[qoff])[0];
|
|
final byte[] right = (byte[]) ((Object[]) meta_quotation[qoff])[1];
|
|
qoff++;
|
|
while ((text.length() > 0) && ((p = text.indexOf(left)) >= 0)) {
|
|
q = text.indexOf(right, p + 1);
|
|
if (q >= 0) {
|
|
// found a pattern
|
|
l.addAll(splitQuotation(new ByteBuffer(text.getBytes(0, p)), qoff));
|
|
l.add(new ByteBuffer(text.getBytes(p, q + right.length - p)));
|
|
text = new ByteBuffer(text.getBytes(q + right.length));
|
|
} else {
|
|
// found only pattern start, no closing parantesis (a syntax error that is silently accepted here)
|
|
l.addAll(splitQuotation(new ByteBuffer(text.getBytes(0, p)), qoff));
|
|
l.addAll(splitQuotation(new ByteBuffer(text.getBytes(p)), qoff));
|
|
text.clear();
|
|
}
|
|
}
|
|
|
|
// find double-points
|
|
while ((text.length() > 0) && ((p = text.indexOf(dpdpa)) >= 0)) {
|
|
l.addAll(splitQuotation(new ByteBuffer(text.getBytes(0, p)), qoff));
|
|
l.add(new ByteBuffer(dpdpa));
|
|
l.addAll(splitQuotation(new ByteBuffer(text.getBytes(p + 2)), qoff));
|
|
text.clear();
|
|
}
|
|
|
|
// add remaining
|
|
if (text.length() > 0) l.addAll(splitQuotation(text, qoff));
|
|
return l;
|
|
}
|
|
|
|
/**
|
|
* transfer until a specified pattern is found; everything but the pattern is transfered so far
|
|
* the function returns true, if the pattern is found
|
|
*/
|
|
private final static boolean transferUntil(final PushbackInputStream i, final OutputStream o, final byte[] pattern) throws IOException {
|
|
int b, bb;
|
|
boolean equal;
|
|
while ((b = i.read()) > 0) {
|
|
if ((b & 0xFF) == pattern[0]) {
|
|
// read the whole pattern
|
|
equal = true;
|
|
lo: for (int n = 1; n < pattern.length; n++) {
|
|
if (((bb = i.read()) & 0xFF) != pattern[n]) {
|
|
// push back all
|
|
i.unread(bb);
|
|
equal = false;
|
|
for (int nn = n - 1; nn > 0; nn--) i.unread(pattern[nn]);
|
|
break lo;
|
|
}
|
|
}
|
|
if (equal) return true;
|
|
}
|
|
o.write(b);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private final static boolean transferUntil(final PushbackInputStream i, final OutputStream o, final byte p) throws IOException {
|
|
int b;
|
|
while ((b = i.read()) > 0) {
|
|
if ((b & 0xFF) == p) return true;
|
|
o.write(b);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public final static void writeTemplate(final InputStream in, final OutputStream out, final HashMap<String, String> pattern, final byte[] dflt) throws IOException {
|
|
if (pattern == null) {
|
|
FileUtils.copy(in, out);
|
|
} else {
|
|
writeTemplate(in, out, pattern, dflt, new byte[0]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads a input stream, and writes the data with replaced templates on a output stream
|
|
*/
|
|
private final static byte[] writeTemplate(final InputStream in, final OutputStream out, final HashMap<String, String> pattern, final byte[] dflt, final byte[] prefix) throws IOException {
|
|
final PushbackInputStream pis = new PushbackInputStream(in, 100);
|
|
ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
|
|
byte[] key;
|
|
byte[] multi_key;
|
|
byte[] replacement;
|
|
int bb;
|
|
final ByteBuffer structure = new ByteBuffer();
|
|
while (transferUntil(pis, out, hash)) {
|
|
bb = pis.read();
|
|
keyStream.reset();
|
|
|
|
// #{
|
|
if ((bb & 0xFF) == lcbr) { //multi
|
|
if (transferUntil(pis, keyStream, mClose)) { //close tag
|
|
//multi_key = "_" + keyStream.toString(); //for _Key
|
|
bb = pis.read();
|
|
if ((bb & 0xFF) != 10){ //kill newline
|
|
pis.unread(bb);
|
|
}
|
|
multi_key = keyStream.toByteArray(); //IMPORTANT: no prefix here
|
|
keyStream.reset(); //reset stream
|
|
|
|
//this needs multi_key without prefix
|
|
if (transferUntil(pis, keyStream, appendBytes(mOpen,slash,multi_key,mClose))){
|
|
bb = pis.read();
|
|
if((bb & 0xFF) != 10){ //kill newline
|
|
pis.unread(bb);
|
|
}
|
|
|
|
final byte[] text=keyStream.toByteArray(); //text between #{key}# an #{/key}#
|
|
int num=0;
|
|
final String patternKey = getPatternKey(prefix, multi_key);
|
|
if(pattern.containsKey(patternKey) && pattern.get(patternKey) != null){
|
|
try{
|
|
num=Integer.parseInt(pattern.get(patternKey)); // Key contains the iteration number as string
|
|
}catch(final NumberFormatException e){
|
|
num=0;
|
|
}
|
|
}
|
|
|
|
structure.append('<')
|
|
.append(multi_key)
|
|
.append(" type=\"multi\" num=\"".getBytes())
|
|
.append(Integer.toString(num).getBytes())
|
|
.append("\">\n".getBytes());
|
|
for(int i=0;i < num;i++) {
|
|
final PushbackInputStream pis2 = new PushbackInputStream(new ByteArrayInputStream(text));
|
|
//System.out.println("recursing with text(prefix="+ multi_key + "_" + i + "_" +"):"); //DEBUG
|
|
//System.out.println(text);
|
|
structure.append(writeTemplate(pis2, out, pattern, dflt, newPrefix(prefix,multi_key,i)));
|
|
}//for
|
|
structure.append("</".getBytes()).append(multi_key).append(">\n".getBytes());
|
|
} else {//transferUntil
|
|
Log.logSevere("TEMPLATE", "No Close Key found for #{"+new String(multi_key)+"}#"); //prefix here?
|
|
}
|
|
}
|
|
|
|
// #(
|
|
} else if ((bb & 0xFF) == lrbr) { //alternative
|
|
int others=0;
|
|
final ByteBuffer text= new ByteBuffer();
|
|
|
|
transferUntil(pis, keyStream, aClose);
|
|
key = keyStream.toByteArray(); //Caution: Key does not contain prefix
|
|
|
|
keyStream.reset(); //clear
|
|
|
|
boolean byName=false;
|
|
int whichPattern=0;
|
|
byte[] patternName = new byte[0];
|
|
final String patternKey = getPatternKey(prefix, key);
|
|
if(pattern.containsKey(patternKey) && pattern.get(patternKey) != null){
|
|
final String patternId=pattern.get(patternKey);
|
|
try{
|
|
whichPattern=Integer.parseInt(patternId); //index
|
|
}catch(final NumberFormatException e){
|
|
whichPattern=0;
|
|
byName=true;
|
|
patternName=patternId.getBytes("UTF-8");
|
|
}
|
|
}
|
|
|
|
int currentPattern=0;
|
|
boolean found=false;
|
|
keyStream.reset(); //reset stream
|
|
PushbackInputStream pis2;
|
|
if (byName) {
|
|
//TODO: better Error Handling
|
|
transferUntil(pis, keyStream, appendBytes("%%".getBytes(), patternName, null, null));
|
|
if(pis.available()==0){
|
|
Log.logSevere("TEMPLATE", "No such Template: %%"+new String(patternName));
|
|
return structure.getBytes();
|
|
}
|
|
keyStream.reset();
|
|
transferUntil(pis, keyStream, dpdpa);
|
|
pis2 = new PushbackInputStream(new ByteArrayInputStream(keyStream.toByteArray()));
|
|
structure.append(writeTemplate(pis2, out, pattern, dflt, newPrefix(prefix,key)));
|
|
transferUntil(pis, keyStream, appendBytes("#(/".getBytes(),key,")#".getBytes("UTF-8"),null));
|
|
if(pis.available()==0){
|
|
Log.logSevere("TEMPLATE", "No Close Key found for #("+new String(key)+")# (by Name)");
|
|
}
|
|
} else {
|
|
while(!found){
|
|
bb=pis.read(); // performance problem? trace always points to this line
|
|
if ((bb & 0xFF) == hash){
|
|
bb=pis.read();
|
|
if ((bb & 0xFF) == lrbr){
|
|
transferUntil(pis, keyStream, aClose);
|
|
|
|
//reached the end. output last string.
|
|
if (java.util.Arrays.equals(keyStream.toByteArray(),appendBytes(slash, key, null,null))) {
|
|
pis2 = new PushbackInputStream(new ByteArrayInputStream(text.getBytes()));
|
|
//this maybe the wrong, but its the last
|
|
structure.append('<').append(key).append(" type=\"alternative\" which=\"".getBytes()).append(Integer.toString(whichPattern).getBytes()).append("\" found=\"0\">\n".getBytes());
|
|
structure.append(writeTemplate(pis2, out, pattern, dflt, newPrefix(prefix,key)));
|
|
structure.append("</".getBytes()).append(key).append(">\n".getBytes());
|
|
found=true;
|
|
}else if(others >0 && keyStream.toString().startsWith("/")){ //close nested
|
|
others--;
|
|
text.append(aOpen).append(keyStream.toByteArray()).append(")#".getBytes());
|
|
} else { //nested
|
|
others++;
|
|
text.append(aOpen).append(keyStream.toByteArray()).append(")#".getBytes());
|
|
}
|
|
keyStream.reset(); //reset stream
|
|
continue;
|
|
} //is not #(
|
|
pis.unread(bb);//is processed in next loop
|
|
bb = (hash);//will be added to text this loop
|
|
//text += "#";
|
|
}else if ((bb & 0xFF) == ':' && others==0){//ignore :: in nested Expressions
|
|
bb=pis.read();
|
|
if ((bb & 0xFF) == ':'){
|
|
if(currentPattern == whichPattern){ //found the pattern
|
|
pis2 = new PushbackInputStream(new ByteArrayInputStream(text.getBytes()));
|
|
structure.append('<').append(key).append(" type=\"alternative\" which=\"".getBytes()).append(Integer.toString(whichPattern).getBytes()).append("\" found=\"0\">\n".getBytes());
|
|
structure.append(writeTemplate(pis2, out, pattern, dflt, newPrefix(prefix,key)));
|
|
structure.append("</".getBytes()).append(key).append(">\n".getBytes());
|
|
|
|
transferUntil(pis, keyStream, appendBytes("#(/".getBytes(),key,")#".getBytes("UTF-8"),null));//to #(/key)#.
|
|
|
|
found=true;
|
|
}
|
|
currentPattern++;
|
|
text.clear();
|
|
continue;
|
|
}
|
|
text.append(":".getBytes());
|
|
}
|
|
if(!found){
|
|
text.append((byte)bb);/*
|
|
if(pis.available()==0){
|
|
serverLog.logSevere("TEMPLATE", "No Close Key found for #("+new String(key)+")# (by Index)");
|
|
found=true;
|
|
}*/
|
|
}
|
|
}//while
|
|
}//if(byName) (else branch)
|
|
|
|
// #[
|
|
} else if ((bb & 0xFF) == lbr) { //normal
|
|
if (transferUntil(pis, keyStream, pClose)) {
|
|
// pattern detected, write replacement
|
|
key = keyStream.toByteArray();
|
|
final String patternKey = getPatternKey(prefix, key);
|
|
replacement = replacePattern(patternKey, pattern, dflt); //replace
|
|
structure.append("<".getBytes()).append(key).append(" type=\"normal\">\n".getBytes());
|
|
structure.append(replacement);
|
|
structure.append("</".getBytes()).append(key).append(">\n".getBytes());
|
|
|
|
FileUtils.copy(replacement, out);
|
|
} else {
|
|
// inconsistency, simply finalize this
|
|
FileUtils.copy(pis, out);
|
|
return structure.getBytes();
|
|
}
|
|
|
|
// #%
|
|
} else if ((bb & 0xFF) == ps) { //include
|
|
final ByteBuffer include = new ByteBuffer();
|
|
keyStream.reset(); //reset stream
|
|
if(transferUntil(pis, keyStream, iClose)){
|
|
byte[] filename = keyStream.toByteArray();
|
|
//if(filename.startsWith( Character.toString((char)lbr) ) && filename.endsWith( Character.toString((char)rbr) )){ //simple pattern for filename
|
|
if((filename[0] == lbr) && (filename[filename.length-1] == rbr)){ //simple pattern for filename
|
|
final byte[] newFilename = new byte[filename.length-2];
|
|
System.arraycopy(filename, 1, newFilename, 0, newFilename.length);
|
|
final String patternkey = getPatternKey(prefix, newFilename);
|
|
filename= replacePattern(patternkey, pattern, dflt);
|
|
}
|
|
if (filename.length > 0 && !java.util.Arrays.equals(filename, dflt)) {
|
|
BufferedReader br = null;
|
|
try{
|
|
//br = new BufferedReader(new InputStreamReader(new FileInputStream( filename ))); //Simple Include
|
|
br = new BufferedReader( new InputStreamReader(new FileInputStream( HTTPDFileHandler.getLocalizedFile(new String(filename,"UTF-8"))),"UTF-8") ); //YaCy (with Locales)
|
|
//Read the Include
|
|
String line = "";
|
|
while ((line = br.readLine()) != null) {
|
|
include.append(line.getBytes("UTF-8")).append(de.anomic.server.serverCore.CRLF_STRING.getBytes());
|
|
}
|
|
} catch (final IOException e) {
|
|
//file not found?
|
|
Log.logSevere("FILEHANDLER","Include Error with file " + new String(filename, "UTF-8") + ": " + e.getMessage());
|
|
} finally {
|
|
if (br != null) try { br.close(); br=null; } catch (final Exception e) {}
|
|
}
|
|
final PushbackInputStream pis2 = new PushbackInputStream(new ByteArrayInputStream(include.getBytes()));
|
|
structure.append("<fileinclude file=\"".getBytes()).append(filename).append(">\n".getBytes());
|
|
structure.append(writeTemplate(pis2, out, pattern, dflt, prefix));
|
|
structure.append("</fileinclude>\n".getBytes());
|
|
}
|
|
}
|
|
|
|
// # - no special character. This is simply a '#' without meaning
|
|
} else { //no match, but a single hash (output # + bb)
|
|
out.write(hash);
|
|
out.write(bb);
|
|
}
|
|
}
|
|
return structure.getBytes();
|
|
}
|
|
|
|
private final static byte[] replacePattern(final String key, final HashMap<String, String> pattern, final byte dflt[]) {
|
|
byte[] replacement;
|
|
Object value;
|
|
if (pattern.containsKey(key)) {
|
|
value = pattern.get(key);
|
|
try {
|
|
if (value instanceof byte[]) {
|
|
replacement = (byte[]) value;
|
|
} else if (value instanceof String) {
|
|
//replacement = ((String) value).getBytes();
|
|
replacement = ((String) value).getBytes("UTF-8");
|
|
} else {
|
|
//replacement = value.toString().getBytes();
|
|
replacement = value.toString().getBytes("UTF-8");
|
|
}
|
|
} catch (final UnsupportedEncodingException e) {
|
|
replacement = dflt;
|
|
}
|
|
} else {
|
|
replacement = dflt;
|
|
}
|
|
return replacement;
|
|
}
|
|
|
|
private final static byte[] newPrefix(final byte[] oldPrefix, final byte[] key) {
|
|
final ByteBuffer newPrefix = new ByteBuffer();
|
|
newPrefix.append(oldPrefix)
|
|
.append(key)
|
|
.append("_".getBytes());
|
|
byte[] result = newPrefix.getBytes();
|
|
try {
|
|
newPrefix.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private final static byte[] newPrefix(final byte[] oldPrefix, final byte[] multi_key, final int i) {
|
|
final ByteBuffer newPrefix = new ByteBuffer();
|
|
newPrefix.append(oldPrefix)
|
|
.append(multi_key)
|
|
.append("_".getBytes())
|
|
.append(Integer.toString(i).getBytes())
|
|
.append("_".getBytes());
|
|
try {
|
|
newPrefix.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return newPrefix.getBytes();
|
|
}
|
|
|
|
private final static String getPatternKey(final byte[] prefix, final byte[] key) {
|
|
final ByteBuffer patternKey = new ByteBuffer();
|
|
patternKey.append(prefix).append(key);
|
|
try {
|
|
return new String(patternKey.getBytes(),"UTF-8");
|
|
} catch (final UnsupportedEncodingException e) {
|
|
return null;
|
|
} finally {
|
|
try {
|
|
patternKey.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
|
|
private final static byte[] appendBytes(final byte[] b1, final byte[] b2, final byte[] b3, final byte[] b4) {
|
|
final ByteBuffer byteArray = new ByteBuffer();
|
|
byteArray.append(b1)
|
|
.append(b2);
|
|
if (b3 != null) byteArray.append(b3);
|
|
if (b4 != null) byteArray.append(b4);
|
|
final byte[] result = byteArray.getBytes();
|
|
try {
|
|
byteArray.close();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public static void main(final String[] args) {
|
|
// arg1 = test input; arg2 = replacement for pattern 'test'; arg3 = default replacement
|
|
try {
|
|
final InputStream i = new ByteArrayInputStream(args[0].getBytes("UTF-8"));
|
|
final HashMap<String, String> h = new HashMap<String, String>();
|
|
h.put("test", args[1]);
|
|
writeTemplate(new PushbackInputStream(i, 100), System.out, h, args[2].getBytes("UTF-8"));
|
|
System.out.flush();
|
|
} catch (final Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|