Skip to content

Commit

Permalink
refactor CodecPrintWriter
Browse files Browse the repository at this point in the history
  • Loading branch information
lhotari committed Apr 4, 2013
1 parent 0a5b557 commit 0b78484
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 39 deletions.
Expand Up @@ -3,7 +3,7 @@
import java.io.IOException;
import java.io.Writer;

public class EncodedAppenderWriter extends Writer {
public class EncodedAppenderWriter extends Writer implements EncoderAware {
protected EncodedAppender encodedAppender;
protected Encoder encoder;
protected EncodingStateRegistry encodingStateRegistry;
Expand Down Expand Up @@ -64,4 +64,12 @@ public EncodedAppender getEncodedAppender() {
public Encoder getEncoder() {
return encoder;
}

public void setEncoder(Encoder encoder) {
this.encoder=encoder;
}

public boolean isEncoderAware() {
return true;
}
}
@@ -0,0 +1,7 @@
package org.codehaus.groovy.grails.support.encoding;

public interface EncoderAware {
public boolean isEncoderAware();
public void setEncoder(Encoder encoder);
public Encoder getEncoder();
}
@@ -0,0 +1,7 @@
package org.codehaus.groovy.grails.support.encoding;

import java.io.Writer;

public interface EncoderAwareWriterFactory {
public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry);
}
Expand Up @@ -13,9 +13,13 @@
import org.codehaus.groovy.grails.commons.DefaultGrailsCodecClass;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsClass;
import org.codehaus.groovy.grails.commons.GrailsCodecClass;
import org.codehaus.groovy.grails.plugins.codecs.HTMLCodec;
import org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest;
import org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse;
import org.codehaus.groovy.grails.support.encoding.DefaultEncodingStateRegistry;
import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncodingStateRegistry;
import org.codehaus.groovy.grails.web.pages.FastStringWriter;
import org.codehaus.groovy.grails.web.pages.GroovyPageOutputStack;
import org.codehaus.groovy.grails.web.servlet.GrailsApplicationAttributes;
Expand All @@ -26,27 +30,37 @@
import org.springframework.web.context.request.RequestContextHolder;

public class CodecPrintWriterTest {
EncodingStateRegistry registry=new DefaultEncodingStateRegistry();

private Encoder getEncoder(GrailsApplication grailsApplication, Class<?> codecClass) {
Encoder encoder=null;
if (grailsApplication != null && codecClass != null) {
GrailsCodecClass codecArtefact = (GrailsCodecClass) grailsApplication.getArtefact("Codec", codecClass.getName());
encoder = codecArtefact.getEncoder();
}
return encoder;
}

@Test
public void testPrintString() {
FastStringWriter stringwriter=new FastStringWriter();
CodecPrintWriter writer=new CodecPrintWriter(new MockGrailsApplication(), stringwriter, HTMLCodec.class);
CodecPrintWriter writer=new CodecPrintWriter(stringwriter, getEncoder(new MockGrailsApplication(), HTMLCodec.class), registry);
writer.print("&&");
assertEquals("&amp;&amp;", stringwriter.getValue());
}

@Test
public void testPrintStringWithClosure() {
FastStringWriter stringwriter=new FastStringWriter();
CodecPrintWriter writer=new CodecPrintWriter(new MockGrailsApplication(), stringwriter, CodecWithClosureProperties.class);
CodecPrintWriter writer=new CodecPrintWriter(stringwriter, getEncoder(new MockGrailsApplication(), CodecWithClosureProperties.class), registry);
writer.print("hello");
assertEquals("-> hello <-", stringwriter.getValue());
}

@Test
public void testPrintStreamCharBuffer() throws IOException {
FastStringWriter stringwriter=new FastStringWriter();
CodecPrintWriter writer=new CodecPrintWriter(new MockGrailsApplication(), stringwriter, HTMLCodec.class);
CodecPrintWriter writer=new CodecPrintWriter(stringwriter, getEncoder(new MockGrailsApplication(), HTMLCodec.class), registry);
StreamCharBuffer buf=new StreamCharBuffer();
buf.getWriter().write("&&");
writer.write(buf);
Expand All @@ -56,7 +70,7 @@ public void testPrintStreamCharBuffer() throws IOException {
@Test
public void testPrintStreamCharBufferWithClosure() throws IOException {
FastStringWriter stringwriter=new FastStringWriter();
CodecPrintWriter writer=new CodecPrintWriter(new MockGrailsApplication(), stringwriter, CodecWithClosureProperties.class);
CodecPrintWriter writer=new CodecPrintWriter(stringwriter, getEncoder(new MockGrailsApplication(), CodecWithClosureProperties.class), registry);
StreamCharBuffer buf=new StreamCharBuffer();
buf.getWriter().write("hola");
writer.write(buf);
Expand All @@ -73,7 +87,7 @@ public void testCodecAndNoCodecGRAILS8405() throws IOException {
GroovyPageOutputStack outputStack = GroovyPageOutputStack.currentStack(true, target, false, true);
GrailsPrintWriter out = outputStack.getProxyWriter();
webRequest.setOut(out);
GrailsPrintWriter codecOut = new CodecPrintWriter(new MockGrailsApplication(), out, CodecWithClosureProperties.class);
GrailsPrintWriter codecOut = new CodecPrintWriter(out, getEncoder(new MockGrailsApplication(), CodecWithClosureProperties.class), registry);

// print some output
codecOut.print("hola");
Expand Down
Expand Up @@ -9,6 +9,8 @@ import org.codehaus.groovy.grails.plugins.CodecsGrailsPlugin
import org.codehaus.groovy.grails.plugins.codecs.HTML4Codec
import org.codehaus.groovy.grails.plugins.codecs.HTMLCodec
import org.codehaus.groovy.grails.plugins.codecs.RawCodec
import org.codehaus.groovy.grails.support.encoding.DefaultEncodingStateRegistry;
import org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest.DefaultEncodingStateRegistryLookup;

import spock.lang.Specification

Expand All @@ -35,7 +37,7 @@ class StreamCharBufferSpec extends Specification {
configureCodecMethods(html4CodecClass)
configureCodecMethods(rawCodecClass)
}
codecOut=new CodecPrintWriter(grailsApplication, out, HTMLCodec)
codecOut=new CodecPrintWriter(out, htmlCodecClass.encoder, DefaultGrailsCodecClass.getEncodingStateRegistryLookup().lookup())
}

def "stream char buffer should support encoding"() {
Expand Down
Expand Up @@ -32,7 +32,12 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.commons.DefaultGrailsCodecClass;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsCodecClass;
import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncoderAwareWriterFactory;
import org.codehaus.groovy.grails.support.encoding.EncodingStateRegistry;
import org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver;
import org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException;
import org.codehaus.groovy.grails.web.pages.ext.jsp.JspTag;
Expand All @@ -47,6 +52,7 @@
import org.codehaus.groovy.grails.web.taglib.exceptions.GrailsTagException;
import org.codehaus.groovy.grails.web.util.CodecPrintWriter;
import org.codehaus.groovy.grails.web.util.GrailsPrintWriter;
import org.codehaus.groovy.grails.web.util.GrailsWrappedWriter;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;

/**
Expand Down Expand Up @@ -193,11 +199,35 @@ public void initRun(Writer target, GrailsWebRequest grailsWebRequest, GrailsAppl
request = grailsWebRequest.getCurrentRequest();
}
setVariableDirectly(OUT, out);
if (codecClass != null) {
codecOut = new CodecPrintWriter(grailsApplication, out, codecClass);

Encoder encoder=null;
if (grailsApplication != null && codecClass != null) {
GrailsCodecClass codecArtefact = (GrailsCodecClass) grailsApplication.getArtefact("Codec", codecClass.getName());
encoder = codecArtefact.getEncoder();
}

Writer realTarget = target;
while (realTarget instanceof GrailsWrappedWriter) {
GrailsWrappedWriter gpr = ((GrailsWrappedWriter)realTarget);
if (gpr.isAllowUnwrappingOut()) {
realTarget = gpr.unwrap();
} else {
break;
}
}

EncodingStateRegistry encodingStateRegistry = DefaultGrailsCodecClass.getEncodingStateRegistryLookup() != null ? DefaultGrailsCodecClass.getEncodingStateRegistryLookup().lookup() : null;
if(realTarget instanceof EncoderAwareWriterFactory) {
Writer codecWriter = ((EncoderAwareWriterFactory)realTarget).getWriterForEncoder(encoder, encodingStateRegistry);
if(codecWriter instanceof GrailsPrintWriter) {
codecOut=(GrailsPrintWriter)codecWriter;
} else if (codecWriter != null) {
codecOut=new GrailsPrintWriter(codecWriter);
}
} else {
codecOut = out;
codecOut=new CodecPrintWriter(realTarget, encoder, encodingStateRegistry);
}

setVariableDirectly(CODEC_OUT, codecOut);
}

Expand Down
Expand Up @@ -14,6 +14,8 @@
*/
package org.codehaus.groovy.grails.web.taglib;

import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncoderAware;
import org.codehaus.groovy.grails.web.pages.FastStringWriter;

/**
Expand All @@ -23,7 +25,7 @@
* @author Graeme Rocher
* @since 0.5
*/
public class GroovyPageTagWriter extends FastStringWriter {
public class GroovyPageTagWriter extends FastStringWriter implements EncoderAware {

private static final int DEFAULT_CHUNK_SIZE = Integer.getInteger("groovypagetagwriter.chunksize", 512);

Expand All @@ -40,4 +42,15 @@ protected void initOut() {
setOut(streamBuffer.getWriterForEncoder());
}

public void setEncoder(Encoder encoder) {
((EncoderAware)getOut()).setEncoder(encoder);
}

public Encoder getEncoder() {
return ((EncoderAware)getOut()).getEncoder();
}

public boolean isEncoderAware() {
return true;
}
}
Expand Up @@ -5,24 +5,23 @@
import java.io.IOException;
import java.io.Writer;

import org.codehaus.groovy.grails.commons.DefaultGrailsCodecClass;
import org.codehaus.groovy.grails.commons.GrailsApplication;
import org.codehaus.groovy.grails.commons.GrailsCodecClass;
import org.codehaus.groovy.grails.support.encoding.EncodedAppender;
import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncoderAware;
import org.codehaus.groovy.grails.support.encoding.EncodingState;
import org.codehaus.groovy.grails.support.encoding.EncodingStateRegistry;
import org.codehaus.groovy.grails.support.encoding.StreamEncodeable;
import org.codehaus.groovy.runtime.GStringImpl;

public class CodecPrintWriter extends GrailsPrintWriter {
public class CodecPrintWriter extends GrailsPrintWriter implements EncoderAware {
private Encoder encoder;

public CodecPrintWriter(GrailsApplication grailsApplication, Writer out, Class<?> codecClass) {
private EncodingStateRegistry encodingStateRegistry=null;

public CodecPrintWriter(Writer out, Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
super(out);
allowUnwrappingOut = false;

initEncode(grailsApplication, codecClass);
this.encoder = encoder;
this.encodingStateRegistry = encodingStateRegistry;
}

@Override
Expand All @@ -40,13 +39,6 @@ protected Writer findStreamCharBufferTarget(boolean markUsed) {
return unwrapWriter(getOut());
}

private void initEncode(GrailsApplication grailsApplication, Class<?> codecClass) {
if (grailsApplication != null && codecClass != null) {
GrailsCodecClass codecArtefact = (GrailsCodecClass) grailsApplication.getArtefact("Codec", codecClass.getName());
encoder = codecArtefact.getEncoder();
}
}

private Object encodeObject(Object o) {
if (encoder == null) return o;
try {
Expand All @@ -71,15 +63,6 @@ public void print(final Object obj) {
encodeAndPrint(obj);
}

private EncodingStateRegistry encodingStateRegistry=null;

private EncodingStateRegistry lookupEncodingStateRegistry() {
if(encodingStateRegistry==null) {
encodingStateRegistry=DefaultGrailsCodecClass.getEncodingStateRegistryLookup() != null ? DefaultGrailsCodecClass.getEncodingStateRegistryLookup().lookup() : null;
}
return encodingStateRegistry;
}

private final void encodeAndPrint(final Object obj) {
if (trouble || obj == null) {
usageFlag = true;
Expand All @@ -95,7 +78,6 @@ private final void encodeAndPrint(final Object obj) {
return;
} else if (clazz == GStringImpl.class || clazz == String.class || obj instanceof CharSequence) {
CharSequence source=(CharSequence)obj;
EncodingStateRegistry encodingStateRegistry=lookupEncodingStateRegistry();
EncodingState encodingState=null;
if(encodingStateRegistry != null) {
encodingState=encodingStateRegistry.getEncodingStateFor(source);
Expand Down Expand Up @@ -282,4 +264,16 @@ public void write(final Writable writable) {
handleIOException(e);
}
}

public Encoder getEncoder() {
return encoder;
}

public void setEncoder(Encoder encoder) {
this.encoder = encoder;
}

public boolean isEncoderAware() {
return true;
}
}
Expand Up @@ -23,6 +23,10 @@

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncoderAware;
import org.codehaus.groovy.grails.support.encoding.EncoderAwareWriterFactory;
import org.codehaus.groovy.grails.support.encoding.EncodingStateRegistry;
import org.codehaus.groovy.grails.web.util.StreamCharBuffer.StreamCharBufferWriter;
import org.codehaus.groovy.runtime.GStringImpl;
import org.codehaus.groovy.runtime.InvokerHelper;
Expand All @@ -34,7 +38,7 @@
*
* @author Lari Hotari, Sagire Software Oy
*/
public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter {
public class GrailsPrintWriter extends Writer implements GrailsWrappedWriter, EncoderAwareWriterFactory {
protected static final Log LOG = LogFactory.getLog(GrailsPrintWriter.class);
protected static final char CRLF[] = { '\r', '\n' };
protected boolean trouble = false;
Expand Down Expand Up @@ -579,4 +583,23 @@ public Object asType(Class<?> clazz) {
public PrintWriter asPrintWriter() {
return new GrailsPrintWriterAdapter(this);
}

public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
Writer target = null;
if(this instanceof EncoderAware) {
target=getOut();
if(target instanceof GrailsWrappedWriter) {
target=((GrailsWrappedWriter)target).unwrap();
}
} else {
target = findStreamCharBufferTarget(false);
}
if (target instanceof EncoderAwareWriterFactory) {
return ((EncoderAwareWriterFactory)target).getWriterForEncoder(encoder, encodingStateRegistry);
} else if (target != null) {
return new CodecPrintWriter(target, encoder, encodingStateRegistry);
} else {
return null;
}
}
}
Expand Up @@ -43,6 +43,7 @@
import org.codehaus.groovy.grails.support.encoding.EncodedAppender;
import org.codehaus.groovy.grails.support.encoding.EncodedAppenderWriter;
import org.codehaus.groovy.grails.support.encoding.Encoder;
import org.codehaus.groovy.grails.support.encoding.EncoderAwareWriterFactory;
import org.codehaus.groovy.grails.support.encoding.EncodingState;
import org.codehaus.groovy.grails.support.encoding.EncodingStateImpl;
import org.codehaus.groovy.grails.support.encoding.EncodingStateRegistry;
Expand Down Expand Up @@ -231,7 +232,7 @@
*
* @author Lari Hotari, Sagire Software Oy
*/
public class StreamCharBuffer implements Writable, CharSequence, Externalizable, Encodeable, StreamEncodeable {
public class StreamCharBuffer implements Writable, CharSequence, Externalizable, Encodeable, StreamEncodeable, EncoderAwareWriterFactory {
static final long serialVersionUID = 5486972234419632945L;
private static final Log log=LogFactory.getLog(StreamCharBuffer.class);

Expand Down Expand Up @@ -860,7 +861,7 @@ protected static final void arrayCopy(char[] src, int srcPos, char[] dest, int d
*
* @author Lari Hotari, Sagire Software Oy
*/
public final class StreamCharBufferWriter extends Writer implements EncodedAppender {
public final class StreamCharBufferWriter extends Writer implements EncodedAppender, EncoderAwareWriterFactory {
boolean closed = false;
int writerUsedCounter = 0;
boolean increaseCounter = true;
Expand Down Expand Up @@ -1157,6 +1158,10 @@ public void append(Encoder encoder, char character) throws IOException {
allocateSpace(new EncodingStateImpl(Collections.singleton(encoder)));
allocBuffer.write(character);
}

public Writer getWriterForEncoder(Encoder encoder, EncodingStateRegistry encodingStateRegistry) {
return StreamCharBuffer.this.getWriterForEncoder(encoder, encodingStateRegistry);
}
}

/**
Expand Down

0 comments on commit 0b78484

Please sign in to comment.