/**
Copyright (C) 2012 Delcyon, Inc.
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 3 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, see <http://www.gnu.org/licenses/>.
*/
package com.delcyon.capo.datastream;
import java.io.ByteArrayOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import com.delcyon.capo.server.CapoServer;
/**
* @author jeremiah
*
*/
public class TriggerFilterOutputStream extends FilterOutputStream
{
private static final int SYMBOL_COUNT = 6;
private int max_buffer_size = 50;
private int symbol = '@';
private ByteArrayOutputStream buffer = new ByteArrayOutputStream();
private int symbolCount = 0;
private String varname;
private String replacement;
public TriggerFilterOutputStream(OutputStream outputStream, String varname,String replacement )
{
super(outputStream);
this.varname = varname;
this.replacement = replacement;
this.max_buffer_size = varname.length()+SYMBOL_COUNT;
}
public TriggerFilterOutputStream(OutputStream outputStream, String varname,String replacement, char symbol )
{
super(outputStream);
this.varname = varname;
this.replacement = replacement;
this.max_buffer_size = varname.length()+SYMBOL_COUNT;
this.symbol = (int)symbol;
}
/**
* override write method
*/
@Override
public void write(int b) throws IOException {
if (b == symbol) //this could be a variable declaration, so start counting
{
if (symbolCount == 0)//gotten our first symbol, so increment the symbolCount se we start counting @'s
{
symbolCount++;
}
else if (symbolCount == 1) //got another symbol, so increment the symbolCount, and prep the buffer
{
buffer.reset();
symbolCount++;
}
else if (symbolCount == 2) //got another symbol, so increment the symbolCount, we are on the other side of the trigger now
{
symbolCount++;
}
else if (symbolCount == 3) //we've gotten a full variable declaration now, so see if it's something we know about
{
//trigger matches so output the new value, and then reset
if (varname.equals(buffer.toString()))
{
byte[] replacement = this.replacement.getBytes();
CapoServer.logger.log(Level.FINER, "Replacing '"+(char)symbol+(char)symbol+varname+(char)symbol+(char)symbol+"' with '"+this.replacement+"'");
out.write(replacement);
symbolCount = 0;
}
else //trigger doesn't match, so reset
{
out.write(symbol);
out.write(symbol);
out.write(buffer.toByteArray());
out.write(symbol);
out.write(b);
symbolCount = 0;
}
}
}
else if (symbolCount == 1) //should have gotten another @ symbol, so reset
{
out.write(symbol);
out.write(b);
symbolCount = 0;
}
else if (symbolCount == 2) //start buffering things
{
buffer.write(b);
if (b == '\n') //hit a new line, so reset
{
out.write(symbol);
out.write(symbol);
out.write(buffer.toByteArray());
symbolCount = 0;
CapoServer.logger.log(Level.FINER, "Reached newline flushing buffer");
}
else if (buffer.size() >= max_buffer_size)
{
out.write(symbol);
out.write(symbol);
out.write(buffer.toByteArray());
symbolCount = 0;
CapoServer.logger.log(Level.FINER, "Reached max buffer size :"+max_buffer_size+" flushing buffer");
}
}
else if (symbolCount == 3) //should have gotten another @ symbol, so reset
{
out.write(symbol);
out.write(symbol);
out.write(buffer.toByteArray());
out.write(symbol);
out.write(b);
symbolCount = 0;
}
else //normal char, just write it out
{
out.write(b);
}
}
/**
* override write method
*/
@Override
public void write(byte[] data, int offset, int length) throws IOException
{
for (int i = offset; i < offset + length; i++)
{
this.write(data[i]);
}
}
/**
* override write method
*/
@Override
public void write(byte[] b) throws IOException
{
write(b, 0, b.length);
}
}