[
https://issues.apache.org/jira/browse/IO-218?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12753115#action_12753115
]
haruhiko nishi edited comment on IO-218 at 9/9/09 8:15 AM:
-----------------------------------------------------------
Hi I'm also working on a Stream that can handle pattern replacement.
usage:
PatternList list=new PatternList();
list.add("src=\"".getBytes("UTF-8"),"\"".getBytes("UTF-8"),new
SrcHrefReplacer("UTF8"),Integer.MAX_VALUE);
list.add("href=\"".getBytes("UTF-8"),"\"".getBytes("UTF-8"),new
SrcHrefReplacer("UTF-8"),Integer.MAX_VALUE);
ByteArrayReplaceInputStream in=new
ByteArrayReplaceInputStream(someByteArray,list);
int bytesRead;
byte[] buf=new byte[4096];
while((bytesRead=in.read(buf,0,buf.length))!=-1)
out.write(buf,0,bytesRead);
in.close();
{code:title=ByteArrayReplaceInputStream.java|borderStyle=solid}
public class ByteArrayReplaceInputStream extends InputStream {
private byte[] buf;
private int count;
private PatternList.PatternListIterator itr;
private Map<PatternList.PatternEntry,Integer> counter=new
IdentityHashMap<PatternList.PatternEntry,Integer>();
private int pos;
private int mark=0;
public ByteArrayReplaceInputStream(byte[] buf,PatternList list) {
this.itr=list.iterator();
this.buf=new byte[buf.length];
ByteBuffer byteBuffer=ByteBuffer.wrap(buf,0,buf.length);
itr.readLock();
try{
match(byteBuffer,itr.next(),0,byteBuffer.limit());
}finally{
itr.readUnlock();
}
}
private void write(ByteBuffer buffer){
byte[] byteArray=new byte[buffer.remaining()];
buffer.get(byteArray);
write(byteArray);
}
private void write(byte[] b){
int newcount=count+b.length;
if(newcount > buf.length){
byte newbuf[]=new byte[Math.max(buf.length<<1,newcount)];
System.arraycopy(buf,0,newbuf,0,count);
buf=newbuf;
}
System.arraycopy(b,0,buf,count,b.length);
count=newcount;
}
private final void match(ByteBuffer src,PatternList.PatternEntry
pattern,int start,int end) {
if(pattern.isSingle())
single(src,pattern,start,end);
else
around(src,pattern,start,end);
}
private int count(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
count=counter.put(pattern,1);
else
count=counter.put(pattern,count+1);
return count==null ? 0 : count;
}
private boolean isPatternValid(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
return 0<=pattern.getMaxOccurence();
else
return count<pattern.getMaxOccurence();
}
private final void around(ByteBuffer src,PatternList.PatternEntry
patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int mark=0;
boolean flag=false;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
if(flag=!flag){
j=mark=cur+pattern.length();
pattern=pattern.swap();
}else{
src.position(pos).limit(mark);
j=cur+pattern.length();
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
pattern=pattern.swap();
src.position(mark).limit(cur);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
array=patternEntry.replace(count(patternEntry),array);
write(array);
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
private void single(ByteBuffer src,PatternList.PatternEntry
patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
src.position(pos).limit(cur);
j=cur+pattern.length();
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
src.position(cur).limit(j);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
write(patternEntry.replace(count(patternEntry),array));
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
@Override
public synchronized int read(){
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
@Override
public synchronized int read(byte b[], int off, int len){
if (b == null)
throw new NullPointerException();
else if(off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
if (pos >= count)
return -1;
if(pos + len > count)
len=count - pos;
if (len <= 0)
return 0;
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public synchronized long skip(long n){
if(pos +n>count){
n=count - pos;
}
if(n<0)
return 0;
pos +=n;
return n;
}
public synchronized int avaiable(){
return count - pos;
}
public boolean markSupported(){
return true;
}
public synchronized void mark(int readAheadLimit){
mark=pos;
}
public synchronized void reset(){
pos=mark;
}
public void close() throws IOException{
}
}
{code}
{code:title=Pattern.java|borderStyle=solid}
abstract class Pattern {
abstract int length();
abstract int get(int pos);
abstract int skip(int value);
abstract Pattern swap();
}
{code}
{code:title=PatternList.java|borderStyle=solid}
public class PatternList {
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
private Lock readLock=lock.readLock();
private Lock writeLock=lock.writeLock();
private PatternEntry head=new PatternEntry(null,-1,null,null,null);
public PatternList(){
head.next=head.previous=head;
}
public void add(byte[] bBegin,byte[] bEnd,PatternReplacer handler, int
maxOccurence){
add(new BeginPattern(new PatternTable(bBegin),new
PatternTable(bEnd)),maxOccurence,handler);
}
public void add(byte[] p,PatternReplacer handler, int maxOccurence){
add(new SinglePattern(new PatternTable(p)),maxOccurence,handler);
}
PatternListIterator iterator(){
return new PatternListIterator(head.previous);
}
private void add(Pattern pattern,int maxOccurence,PatternReplacer handler){
writeLock.lock();
try{
for(PatternEntry tmp=head;;tmp=tmp.next)
if(tmp.pattern==null||tmp.compareTo(pattern)<=0){
PatternEntry newEntry=new
PatternEntry(handler,maxOccurence,pattern,tmp,tmp.previous);
newEntry.previous.next=newEntry;
newEntry.next.previous=newEntry;
if(tmp==head)
head=newEntry;
break;
}
}finally{
writeLock.unlock();
}
}
class PatternListIterator{
private PatternEntry copyHead;
PatternListIterator(PatternEntry head){
this.copyHead=head;
}
public PatternEntry next(){
copyHead=copyHead.next;
return copyHead;
}
public PatternEntry previous(){
copyHead=copyHead.previous;
return copyHead;
}
public boolean hasNext(){
return copyHead.next.pattern!=null;
}
void readLock(){
readLock.lock();
}
void readUnlock(){
readLock.unlock();
}
}
static class PatternEntry implements Comparable<Pattern>{
Pattern pattern;
PatternEntry next;
PatternEntry previous;
PatternReplacer handler;
int maxOccurence;
private PatternEntry(PatternReplacer handler,int maxOccurence,Pattern
element,PatternEntry next, PatternEntry previous){
this.handler=handler;
this.pattern=element;
this.next=next;
this.previous=previous;
this.maxOccurence=maxOccurence;
}
byte[] replace(int pos,byte[] match){
return handler.replace(pos,match);
}
int getMaxOccurence() {
return maxOccurence;
}
Pattern getPattern(){
return pattern;
}
public int compareTo(Pattern other) {
if(this.pattern instanceof SinglePattern && other instanceof
BeginPattern)
return -1;
else if(this.pattern instanceof BeginPattern && other instanceof
SinglePattern)
return 1;
else{
return
((ComparablePattern)this.pattern).size-((ComparablePattern)other).size;
}
}
boolean isSingle(){
return pattern instanceof SinglePattern;
}
}
private static abstract class ComparablePattern extends Pattern{
int size;
ComparablePattern(int size){
this.size=size;
}
}
private static class SinglePattern extends ComparablePattern {
PatternTable pattern;
private SinglePattern(PatternTable pattern){
super(pattern.length());
this.pattern=pattern;
}
@Override
int length() {
return pattern.length();
}
@Override
int get(int pos) {
return pattern.get(pos);
}
@Override
int skip(int value) {
return pattern.skip(value);
}
@Override
protected Pattern swap() {
throw new UnsupportedOperationException("single pattern cannot be
swapped.");
}
}
private static class EndPattern extends Pattern {
PatternTable end;
Pattern nextMatcher;
private EndPattern(PatternTable end,Pattern nextMatcher){
this.end=end;
this.nextMatcher=nextMatcher;
}
@Override
int length() {
return end.length();
}
@Override
int get(int pos) {
return end.get(pos);
}
@Override
int skip(int value) {
return end.skip(value);
}
@Override
protected Pattern swap() {
return nextMatcher;
}
}
private static class BeginPattern extends ComparablePattern{
PatternTable begin;
Pattern nextMatcher;
private BeginPattern(PatternTable begin,PatternTable end){
super(begin.length()+end.length());
this.begin=begin;
nextMatcher=new EndPattern(end,this);
}
@Override
int length() {
return begin.length();
}
@Override
int get(int pos) {
return begin.get(pos);
}
@Override
int skip(int value) {
return begin.skip(value);
}
@Override
protected Pattern swap() {
return nextMatcher;
}
}
private static class PatternTable {
private final int[] pattern;
private int[] skip;
PatternTable(byte[] target){
pattern=new int[target.length];
for(int i=0;i<target.length;i++)
pattern[i]=target[i] & 0xff;
this.skip=getSkipArray(target);
}
int length(){
return pattern.length;
}
int get(int i){
return pattern[i];
}
int skip(int i){
return skip[i];
}
private static int[] getSkipArray(byte[] pattern){
int[] skip=new int[256];
int i;
for(i=0; i<skip.length;i++)
skip[i]=pattern.length+1;
for(i=0; i<pattern.length;i++)
skip[pattern[i] & 0xff]=pattern.length -i;
return skip;
}
}
}
{code}
{code:title=PatternReplacer.java|borderStyle=solid}
public interface PatternReplacer {
byte[] replace(int pos,final byte[] matched);
}
{code}
{code:title=StringPatternReplacer.java|borderStyle=solid}
public abstract class StringPatternReplacer implements PatternReplacer{
private String charset;
protected StringPatternReplacer(String charset){
this.charset=charset;
}
public final byte[] replace(int pos, byte[] matched) {
String replaced;
try {
replaced = replace(pos,new String(matched,charset));
if(replaced!=null)
return replaced.getBytes(charset);
} catch (UnsupportedEncodingException e) {
}
return null;
}
protected abstract String replace(int pos,String matched);
}
{code}
{code:title=SrcHrefReplacer.java|borderStyle=solid}
public class SrcHrefReplacer extends StringPatternReplacer {
public SrcHrefReplacer(String charset){
super(charset);
}
public String replace(int pos, String matched) {
if(matched.endsWith(".jpg")||matched.endsWith(".gif"))
return matched;
if(matched.contains("somedomain.com"))
return matched;
return matched.replaceAll("somedomain.com","mydomain.com");
}
}
{code}
was (Author: hanishi):
Hi I'm also working on a Stream that can handle pattern replacement.
usage:
PatternList list=new PatternList();
list.add("src=\"".getBytes("UTF-8"),"\"".getBytes("UTF-8"),new
SrcHrefReplacer("UTF8"),Integer.MAX_VALUE);
list.add("href=\"".getBytes("UTF-8"),"\"".getBytes("UTF-8"),new
SrcHrefReplacer("UTF-8"),Integer.MAX_VALUE);
ByteArrayReplaceInputStream in=new
ByteArrayReplaceInputStream(someByteArray,list);
int bytesRead;
byte[] buf=new byte[4096];
while((bytesRead=in.read(buf,0,buf.length))!=-1)
out.write(buf,0,bytesRead);
in.close();
{code:title=ByteArrayInputStream.java|borderStyle=solid}
public class ByteArrayReplaceInputStream extends InputStream {
private byte[] buf;
private int count;
private PatternList.PatternListIterator itr;
private Map<PatternList.PatternEntry,Integer> counter=new
IdentityHashMap<PatternList.PatternEntry,Integer>();
private int pos;
private int mark=0;
public ByteArrayReplaceInputStream(byte[] buf,PatternList list) {
this.itr=list.iterator();
this.buf=new byte[buf.length];
ByteBuffer byteBuffer=ByteBuffer.wrap(buf,0,buf.length);
itr.readLock();
try{
match(byteBuffer,itr.next(),0,byteBuffer.limit());
}finally{
itr.readUnlock();
}
}
private void write(ByteBuffer buffer){
byte[] byteArray=new byte[buffer.remaining()];
buffer.get(byteArray);
write(byteArray);
}
private void write(byte[] b){
int newcount=count+b.length;
if(newcount > buf.length){
byte newbuf[]=new byte[Math.max(buf.length<<1,newcount)];
System.arraycopy(buf,0,newbuf,0,count);
buf=newbuf;
}
System.arraycopy(b,0,buf,count,b.length);
count=newcount;
}
private final void match(ByteBuffer src,PatternList.PatternEntry
pattern,int start,int end) {
if(pattern.isSingle())
single(src,pattern,start,end);
else
around(src,pattern,start,end);
}
private int count(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
count=counter.put(pattern,1);
else
count=counter.put(pattern,count+1);
return count==null ? 0 : count;
}
private boolean isPatternValid(PatternList.PatternEntry pattern){
Integer count=counter.get(pattern);
if(count==null)
return 0<=pattern.getMaxOccurence();
else
return count<pattern.getMaxOccurence();
}
private final void around(ByteBuffer src,PatternList.PatternEntry
patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int mark=0;
boolean flag=false;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
if(flag=!flag){
j=mark=cur+pattern.length();
pattern=pattern.swap();
}else{
src.position(pos).limit(mark);
j=cur+pattern.length();
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
pattern=pattern.swap();
src.position(mark).limit(cur);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
array=patternEntry.replace(count(patternEntry),array);
write(array);
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
match(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
private void single(ByteBuffer src,PatternList.PatternEntry
patternEntry,int start,int end){
if(start<0 || start>end || end>src.limit())
throw new IndexOutOfBoundsException("start:"+start+" end:"+end);
int pos=start;
int limit_org=end;
int j=pos;
Pattern pattern=patternEntry.getPattern();
while(isPatternValid(patternEntry) && j<=limit_org-pattern.length()) {
boolean found=true;
int cur=j;
for(int i=0;i<pattern.length();i++){
if(src.get(cur+i)!=pattern.get(i)){
found=false;
break;
}
}
if(found){
src.position(pos).limit(cur);
j=cur+pattern.length();
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
src.position(cur).limit(j);
if(src.remaining()>0){
ByteBuffer target=src.slice();
int size=target.remaining();
byte[] array=new byte[size];
target.get(array);
write(patternEntry.replace(count(patternEntry),array));
}
pos=src.position(src.limit()).position();
src.limit(limit_org);
}
if(!found){
int k=cur+pattern.length();
if(k>=src.limit())
break;
j +=pattern.skip(src.get(k) & 0xff);
}
}
src.position(pos);
if(itr.hasNext())
single(src,itr.next(),pos,src.limit());
else
write(src);
itr.previous();
}
@Override
public synchronized int read(){
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
@Override
public synchronized int read(byte b[], int off, int len){
if (b == null)
throw new NullPointerException();
else if(off < 0 || len < 0 || len > b.length - off)
throw new IndexOutOfBoundsException();
if (pos >= count)
return -1;
if(pos + len > count)
len=count - pos;
if (len <= 0)
return 0;
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}
public synchronized long skip(long n){
if(pos +n>count){
n=count - pos;
}
if(n<0)
return 0;
pos +=n;
return n;
}
public synchronized int avaiable(){
return count - pos;
}
public boolean markSupported(){
return true;
}
public synchronized void mark(int readAheadLimit){
mark=pos;
}
public synchronized void reset(){
pos=mark;
}
public void close() throws IOException{
}
}
{code}
{code:title=Pattern.java|borderStyle=solid}
abstract class Pattern {
abstract int length();
abstract int get(int pos);
abstract int skip(int value);
abstract Pattern swap();
}
{code}
{code:title=PatternList.java|borderStyle=solid}
public class PatternList {
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
private Lock readLock=lock.readLock();
private Lock writeLock=lock.writeLock();
private PatternEntry head=new PatternEntry(null,-1,null,null,null);
public PatternList(){
head.next=head.previous=head;
}
public void add(byte[] bBegin,byte[] bEnd,PatternReplacer handler, int
maxOccurence){
add(new BeginPattern(new PatternTable(bBegin),new
PatternTable(bEnd)),maxOccurence,handler);
}
public void add(byte[] p,PatternReplacer handler, int maxOccurence){
add(new SinglePattern(new PatternTable(p)),maxOccurence,handler);
}
PatternListIterator iterator(){
return new PatternListIterator(head.previous);
}
private void add(Pattern pattern,int maxOccurence,PatternReplacer handler){
writeLock.lock();
try{
for(PatternEntry tmp=head;;tmp=tmp.next)
if(tmp.pattern==null||tmp.compareTo(pattern)<=0){
PatternEntry newEntry=new
PatternEntry(handler,maxOccurence,pattern,tmp,tmp.previous);
newEntry.previous.next=newEntry;
newEntry.next.previous=newEntry;
if(tmp==head)
head=newEntry;
break;
}
}finally{
writeLock.unlock();
}
}
class PatternListIterator{
private PatternEntry copyHead;
PatternListIterator(PatternEntry head){
this.copyHead=head;
}
public PatternEntry next(){
copyHead=copyHead.next;
return copyHead;
}
public PatternEntry previous(){
copyHead=copyHead.previous;
return copyHead;
}
public boolean hasNext(){
return copyHead.next.pattern!=null;
}
void readLock(){
readLock.lock();
}
void readUnlock(){
readLock.unlock();
}
}
static class PatternEntry implements Comparable<Pattern>{
Pattern pattern;
PatternEntry next;
PatternEntry previous;
PatternReplacer handler;
int maxOccurence;
private PatternEntry(PatternReplacer handler,int maxOccurence,Pattern
element,PatternEntry next, PatternEntry previous){
this.handler=handler;
this.pattern=element;
this.next=next;
this.previous=previous;
this.maxOccurence=maxOccurence;
}
byte[] replace(int pos,byte[] match){
return handler.replace(pos,match);
}
int getMaxOccurence() {
return maxOccurence;
}
Pattern getPattern(){
return pattern;
}
public int compareTo(Pattern other) {
if(this.pattern instanceof SinglePattern && other instanceof
BeginPattern)
return -1;
else if(this.pattern instanceof BeginPattern && other instanceof
SinglePattern)
return 1;
else{
return
((ComparablePattern)this.pattern).size-((ComparablePattern)other).size;
}
}
boolean isSingle(){
return pattern instanceof SinglePattern;
}
}
private static abstract class ComparablePattern extends Pattern{
int size;
ComparablePattern(int size){
this.size=size;
}
}
private static class SinglePattern extends ComparablePattern {
PatternTable pattern;
private SinglePattern(PatternTable pattern){
super(pattern.length());
this.pattern=pattern;
}
@Override
int length() {
return pattern.length();
}
@Override
int get(int pos) {
return pattern.get(pos);
}
@Override
int skip(int value) {
return pattern.skip(value);
}
@Override
protected Pattern swap() {
throw new UnsupportedOperationException("single pattern cannot be
swapped.");
}
}
private static class EndPattern extends Pattern {
PatternTable end;
Pattern nextMatcher;
private EndPattern(PatternTable end,Pattern nextMatcher){
this.end=end;
this.nextMatcher=nextMatcher;
}
@Override
int length() {
return end.length();
}
@Override
int get(int pos) {
return end.get(pos);
}
@Override
int skip(int value) {
return end.skip(value);
}
@Override
protected Pattern swap() {
return nextMatcher;
}
}
private static class BeginPattern extends ComparablePattern{
PatternTable begin;
Pattern nextMatcher;
private BeginPattern(PatternTable begin,PatternTable end){
super(begin.length()+end.length());
this.begin=begin;
nextMatcher=new EndPattern(end,this);
}
@Override
int length() {
return begin.length();
}
@Override
int get(int pos) {
return begin.get(pos);
}
@Override
int skip(int value) {
return begin.skip(value);
}
@Override
protected Pattern swap() {
return nextMatcher;
}
}
private static class PatternTable {
private final int[] pattern;
private int[] skip;
PatternTable(byte[] target){
pattern=new int[target.length];
for(int i=0;i<target.length;i++)
pattern[i]=target[i] & 0xff;
this.skip=getSkipArray(target);
}
int length(){
return pattern.length;
}
int get(int i){
return pattern[i];
}
int skip(int i){
return skip[i];
}
private static int[] getSkipArray(byte[] pattern){
int[] skip=new int[256];
int i;
for(i=0; i<skip.length;i++)
skip[i]=pattern.length+1;
for(i=0; i<pattern.length;i++)
skip[pattern[i] & 0xff]=pattern.length -i;
return skip;
}
}
}
{code}
{code:title=PatternReplacer.java|borderStyle=solid}
public interface PatternReplacer {
byte[] replace(int pos,final byte[] matched);
}
{code}
{code:title=StringPatternReplacer.java|borderStyle=solid}
public abstract class StringPatternReplacer implements PatternReplacer{
private String charset;
protected StringPatternReplacer(String charset){
this.charset=charset;
}
public final byte[] replace(int pos, byte[] matched) {
String replaced;
try {
replaced = replace(pos,new String(matched,charset));
if(replaced!=null)
return replaced.getBytes(charset);
} catch (UnsupportedEncodingException e) {
}
return null;
}
protected abstract String replace(int pos,String matched);
}
{code}
{code:title=SrcHrefReplacer.java|borderStyle=solid}
public class SrcHrefReplacer extends StringPatternReplacer {
public SrcHrefReplacer(String charset){
super(charset);
}
public String replace(int pos, String matched) {
if(matched.endsWith(".jpg")||matched.endsWith(".gif"))
return matched;
if(matched.contains("somedomain.com"))
return matched;
return matched.replaceAll("somedomain.com","mydomain.com");
}
}
{code}
> Introduce new filter input stream with replacement facilities
> -------------------------------------------------------------
>
> Key: IO-218
> URL: https://issues.apache.org/jira/browse/IO-218
> Project: Commons IO
> Issue Type: Improvement
> Components: Filters
> Affects Versions: 1.4
> Environment: all environments
> Reporter: Denis Zhdanov
> Fix For: 1.4, 2.0
>
> Attachments: ReplaceFilterInputStream.java,
> ReplaceFilterInputStreamTest.java
>
> Original Estimate: 120h
> Remaining Estimate: 120h
>
> It seems convenient to have a FilterInputStream that allows to apply
> predefined repalcement rules against the read data.
> For example we may want to configure the following replacements:
> {noformat}
> {1, } -> {7, 8}
> {1} -> {9}
> {3, 2} -> {}
> {noformat}
> and apply them to the input like
> {noformat}
> {4, 3, 2, 1, 2, 1, 3}
> {noformat}
> in order to get a result like
> {noformat}
> {4, 7, 8, 9, 3}
> {noformat}
> I created the class that allows to do that and attached it to this ticket.
> Unit test class at junit4 format is attached as well.
> So, the task is to review the provided classes, consider if it's worth to add
> them to commons-io distribution and perform the inclusion in the case of
> possible result.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.