mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 03:25:28 -04:00
Servlet changes for 3.0.
This commit is contained in:
parent
aafdb31a8c
commit
a1f9e979b9
@ -50,10 +50,10 @@ import java.util.Enumeration;
|
|||||||
* <p/
|
* <p/
|
||||||
* {@code GenericFilter} has an auto-init system, that automatically invokes
|
* {@code GenericFilter} has an auto-init system, that automatically invokes
|
||||||
* the method matching the signature {@code void setX(<Type>)},
|
* the method matching the signature {@code void setX(<Type>)},
|
||||||
* for every init-parameter {@code x}. Both camelCase and lisp-style paramter
|
* for every init-parameter {@code x}. Both camelCase and lisp-style parameter
|
||||||
* naming is supported, lisp-style names will be converted to camelCase.
|
* naming is supported, lisp-style names will be converted to camelCase.
|
||||||
* Parameter values are automatically converted from string represenation to
|
* Parameter values are automatically converted from string representation to
|
||||||
* most basic types, if neccessary.
|
* most basic types, if necessary.
|
||||||
* <p/>
|
* <p/>
|
||||||
* To write a generic filter, you need only override the abstract
|
* To write a generic filter, you need only override the abstract
|
||||||
* {@link #doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)} doFilterImpl} method.
|
* {@link #doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)} doFilterImpl} method.
|
||||||
@ -67,6 +67,7 @@ import java.util.Enumeration;
|
|||||||
* @see FilterConfig
|
* @see FilterConfig
|
||||||
*/
|
*/
|
||||||
public abstract class GenericFilter implements Filter, FilterConfig, Serializable {
|
public abstract class GenericFilter implements Filter, FilterConfig, Serializable {
|
||||||
|
// TODO: Rewrite to use ServletConfigurator instead of BeanUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The filter config.
|
* The filter config.
|
||||||
@ -76,32 +77,29 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
|||||||
/**
|
/**
|
||||||
* Makes sure the filter runs once per request
|
* Makes sure the filter runs once per request
|
||||||
* <p/>
|
* <p/>
|
||||||
* see #isRunOnce
|
* @see #isRunOnce
|
||||||
*
|
* @see #ATTRIB_RUN_ONCE_VALUE
|
||||||
* @see #oncePerRequest
|
* @see #oncePerRequest
|
||||||
* see #ATTRIB_RUN_ONCE_VALUE
|
|
||||||
*/
|
*/
|
||||||
private final static String ATTRIB_RUN_ONCE_EXT = ".REQUEST_HANDLED";
|
private final static String ATTRIB_RUN_ONCE_EXT = ".REQUEST_HANDLED";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure the filter runs once per request.
|
* Makes sure the filter runs once per request.
|
||||||
* Must be configured through init method, as the filter name is not
|
* Must be configured through init method, as the filter name is not
|
||||||
* available before we have a FitlerConfig object.
|
* available before we have a {@code FilterConfig} object.
|
||||||
* <p/>
|
* <p/>
|
||||||
* see #isRunOnce
|
* @see #isRunOnce
|
||||||
*
|
* @see #ATTRIB_RUN_ONCE_VALUE
|
||||||
* @see #oncePerRequest
|
* @see #oncePerRequest
|
||||||
* see #ATTRIB_RUN_ONCE_VALUE
|
|
||||||
*/
|
*/
|
||||||
private String attribRunOnce = null;
|
private String attribRunOnce = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure the filter runs once per request
|
* Makes sure the filter runs once per request
|
||||||
* <p/>
|
* <p/>
|
||||||
* see #isRunOnce
|
* @see #isRunOnce
|
||||||
*
|
* @see #ATTRIB_RUN_ONCE_EXT
|
||||||
* @see #oncePerRequest
|
* @see #oncePerRequest
|
||||||
* see #ATTRIB_RUN_ONCE_EXT
|
|
||||||
*/
|
*/
|
||||||
private static final Object ATTRIB_RUN_ONCE_VALUE = new Object();
|
private static final Object ATTRIB_RUN_ONCE_VALUE = new Object();
|
||||||
|
|
||||||
@ -213,16 +211,16 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
|||||||
* and returns false.
|
* and returns false.
|
||||||
* A return value of false, indicates that the filter has not yet run.
|
* A return value of false, indicates that the filter has not yet run.
|
||||||
* A return value of true, indicates that the filter has run for this
|
* A return value of true, indicates that the filter has run for this
|
||||||
* request, and processing should not contine.
|
* request, and processing should not continue.
|
||||||
* <P/>
|
* <P/>
|
||||||
* Note that the method will mark the request as filtered on first
|
* Note that the method will mark the request as filtered on first
|
||||||
* invocation.
|
* invocation.
|
||||||
* <p/>
|
* <p/>
|
||||||
* see #ATTRIB_RUN_ONCE_EXT
|
* @see #ATTRIB_RUN_ONCE_EXT
|
||||||
* see #ATTRIB_RUN_ONCE_VALUE
|
* @see #ATTRIB_RUN_ONCE_VALUE
|
||||||
*
|
*
|
||||||
* @param pRequest the servlet request
|
* @param pRequest the servlet request
|
||||||
* @return {@code true} if the request is allready filtered, otherwise
|
* @return {@code true} if the request is already filtered, otherwise
|
||||||
* {@code false}.
|
* {@code false}.
|
||||||
*/
|
*/
|
||||||
private boolean isRunOnce(final ServletRequest pRequest) {
|
private boolean isRunOnce(final ServletRequest pRequest) {
|
||||||
@ -233,6 +231,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
|||||||
|
|
||||||
// Set attribute and return false (continue)
|
// Set attribute and return false (continue)
|
||||||
pRequest.setAttribute(attribRunOnce, ATTRIB_RUN_ONCE_VALUE);
|
pRequest.setAttribute(attribRunOnce, ATTRIB_RUN_ONCE_VALUE);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +285,6 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
|||||||
* @see ServletContext
|
* @see ServletContext
|
||||||
*/
|
*/
|
||||||
public ServletContext getServletContext() {
|
public ServletContext getServletContext() {
|
||||||
// TODO: Create a servlet context wrapper that lets you log to a log4j appender?
|
|
||||||
return filterConfig.getServletContext();
|
return filterConfig.getServletContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -347,6 +345,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
|||||||
*
|
*
|
||||||
* @deprecated For compatibility only, use {@link #init init} instead.
|
* @deprecated For compatibility only, use {@link #init init} instead.
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public void setFilterConfig(final FilterConfig pFilterConfig) {
|
public void setFilterConfig(final FilterConfig pFilterConfig) {
|
||||||
try {
|
try {
|
||||||
init(pFilterConfig);
|
init(pFilterConfig);
|
||||||
|
@ -39,7 +39,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
* <p/>
|
* <p/>
|
||||||
* {@code GenericServlet} has an auto-init system, that automatically invokes
|
* {@code GenericServlet} has an auto-init system, that automatically invokes
|
||||||
* the method matching the signature {@code void setX(<Type>)},
|
* the method matching the signature {@code void setX(<Type>)},
|
||||||
* for every init-parameter {@code x}. Both camelCase and lisp-style paramter
|
* for every init-parameter {@code x}. Both camelCase and lisp-style parameter
|
||||||
* naming is supported, lisp-style names will be converted to camelCase.
|
* naming is supported, lisp-style names will be converted to camelCase.
|
||||||
* Parameter values are automatically converted from string representation to
|
* Parameter values are automatically converted from string representation to
|
||||||
* most basic types, if necessary.
|
* most basic types, if necessary.
|
||||||
@ -50,6 +50,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
* @version $Id: GenericServlet.java#1 $
|
* @version $Id: GenericServlet.java#1 $
|
||||||
*/
|
*/
|
||||||
public abstract class GenericServlet extends javax.servlet.GenericServlet {
|
public abstract class GenericServlet extends javax.servlet.GenericServlet {
|
||||||
|
// TODO: Rewrite to use ServletConfigurator instead of BeanUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the web container to indicate to a servlet that it is being
|
* Called by the web container to indicate to a servlet that it is being
|
||||||
|
@ -39,7 +39,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
* <p/>
|
* <p/>
|
||||||
* {@code HttpServlet} has an auto-init system, that automatically invokes
|
* {@code HttpServlet} has an auto-init system, that automatically invokes
|
||||||
* the method matching the signature {@code void setX(<Type>)},
|
* the method matching the signature {@code void setX(<Type>)},
|
||||||
* for every init-parameter {@code x}. Both camelCase and lisp-style paramter
|
* for every init-parameter {@code x}. Both camelCase and lisp-style parameter
|
||||||
* naming is supported, lisp-style names will be converted to camelCase.
|
* naming is supported, lisp-style names will be converted to camelCase.
|
||||||
* Parameter values are automatically converted from string representation to
|
* Parameter values are automatically converted from string representation to
|
||||||
* most basic types, if necessary.
|
* most basic types, if necessary.
|
||||||
@ -50,6 +50,7 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
* @version $Id: HttpServlet.java#1 $
|
* @version $Id: HttpServlet.java#1 $
|
||||||
*/
|
*/
|
||||||
public abstract class HttpServlet extends javax.servlet.http.HttpServlet {
|
public abstract class HttpServlet extends javax.servlet.http.HttpServlet {
|
||||||
|
// TODO: Rewrite to use ServletConfigurator instead of BeanUtil
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the web container to indicate to a servlet that it is being
|
* Called by the web container to indicate to a servlet that it is being
|
||||||
|
@ -28,17 +28,20 @@
|
|||||||
|
|
||||||
package com.twelvemonkeys.servlet;
|
package com.twelvemonkeys.servlet;
|
||||||
|
|
||||||
import com.twelvemonkeys.lang.Validate;
|
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.ServletResponse;
|
import javax.servlet.ServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.OutputStream;
|
|
||||||
|
import static com.twelvemonkeys.lang.Validate.notNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A delegate for handling stream support in wrapped servlet responses.
|
* A delegate for handling stream support in wrapped servlet responses.
|
||||||
|
* <p/>
|
||||||
|
* Client code should delegate {@code getOutputStream}, {@code getWriter},
|
||||||
|
* {@code flushBuffer} and {@code resetBuffer} methods from the servlet response.
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @author last modified by $Author: haku $
|
* @author last modified by $Author: haku $
|
||||||
@ -48,35 +51,33 @@ public class ServletResponseStreamDelegate {
|
|||||||
private Object out = null;
|
private Object out = null;
|
||||||
protected final ServletResponse response;
|
protected final ServletResponse response;
|
||||||
|
|
||||||
public ServletResponseStreamDelegate(ServletResponse pResponse) {
|
public ServletResponseStreamDelegate(final ServletResponse pResponse) {
|
||||||
response = Validate.notNull(pResponse, "response");
|
response = notNull(pResponse, "response");
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Intentionally NOT threadsafe, as one request/response should be
|
// NOTE: Intentionally NOT thread safe, as one request/response should be handled by one thread ONLY.
|
||||||
// handled by one thread ONLY.
|
|
||||||
public final ServletOutputStream getOutputStream() throws IOException {
|
public final ServletOutputStream getOutputStream() throws IOException {
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
OutputStream out = createOutputStream();
|
OutputStream out = createOutputStream();
|
||||||
this.out = out instanceof ServletOutputStream ? out : new OutputStreamAdapter(out);
|
this.out = out instanceof ServletOutputStream ? out : new OutputStreamAdapter(out);
|
||||||
}
|
}
|
||||||
else if (out instanceof PrintWriter) {
|
else if (out instanceof PrintWriter) {
|
||||||
throw new IllegalStateException("getWriter() allready called.");
|
throw new IllegalStateException("getWriter() already called.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ServletOutputStream) out;
|
return (ServletOutputStream) out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Intentionally NOT threadsafe, as one request/response should be
|
// NOTE: Intentionally NOT thread safe, as one request/response should be handled by one thread ONLY.
|
||||||
// handled by one thread ONLY.
|
|
||||||
public final PrintWriter getWriter() throws IOException {
|
public final PrintWriter getWriter() throws IOException {
|
||||||
if (out == null) {
|
if (out == null) {
|
||||||
// NOTE: getCharacterEncoding may should not return null
|
// NOTE: getCharacterEncoding may/should not return null
|
||||||
OutputStream out = createOutputStream();
|
OutputStream out = createOutputStream();
|
||||||
String charEncoding = response.getCharacterEncoding();
|
String charEncoding = response.getCharacterEncoding();
|
||||||
this.out = new PrintWriter(charEncoding != null ? new OutputStreamWriter(out, charEncoding) : new OutputStreamWriter(out));
|
this.out = new PrintWriter(charEncoding != null ? new OutputStreamWriter(out, charEncoding) : new OutputStreamWriter(out));
|
||||||
}
|
}
|
||||||
else if (out instanceof ServletOutputStream) {
|
else if (out instanceof ServletOutputStream) {
|
||||||
throw new IllegalStateException("getOutputStream() allready called.");
|
throw new IllegalStateException("getOutputStream() already called.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (PrintWriter) out;
|
return (PrintWriter) out;
|
||||||
@ -84,8 +85,9 @@ public class ServletResponseStreamDelegate {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@code OutputStream}.
|
* Returns the {@code OutputStream}.
|
||||||
* Override this method to provide a decoreated outputstream.
|
* Subclasses should override this method to provide a decorated output stream.
|
||||||
* This method is guaranteed to be invoked only once for a request/response.
|
* This method is guaranteed to be invoked only once for a request/response
|
||||||
|
* (unless {@code resetBuffer} is invoked).
|
||||||
* <P/>
|
* <P/>
|
||||||
* This implementation simply returns the output stream from the wrapped
|
* This implementation simply returns the output stream from the wrapped
|
||||||
* response.
|
* response.
|
||||||
@ -107,7 +109,6 @@ public class ServletResponseStreamDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void resetBuffer() {
|
public void resetBuffer() {
|
||||||
// TODO: Is this okay? Probably not... :-)
|
|
||||||
out = null;
|
out = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,17 +63,15 @@ import java.util.Iterator;
|
|||||||
* The response also automatically handles writing the image back to the underlying response stream
|
* The response also automatically handles writing the image back to the underlying response stream
|
||||||
* in the preferred format, when the response is flushed.
|
* in the preferred format, when the response is flushed.
|
||||||
* <p>
|
* <p>
|
||||||
*
|
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @version $Id: ImageServletResponseImpl.java#10 $
|
* @version $Id: ImageServletResponseImpl.java#10 $
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
// TODO: Refactor out HTTP specifics (if possible).
|
// TODO: Refactor out HTTP specifics (if possible).
|
||||||
// TODO: Is it a good ide to throw IIOException?
|
// TODO: Is it a good ide to throw IIOException?
|
||||||
// TODO: This implementation has a problem if two filters does scaling, as the second will overwrite the SIZE attribute
|
// TODO: This implementation has a problem if two filters does scaling, as the second will overwrite the SIZE attribute
|
||||||
// TODO: Allow different scaling algorithm based on input image (use case: IndexColorModel does not scale well using default, smooth may be slow for large images)
|
// TODO: Allow different scaling algorithm based on input image (use case: IndexColorModel does not scale well using default, smooth may be slow for large images)
|
||||||
|
// TODO: Support pluggable pre- and post-processing steps
|
||||||
class ImageServletResponseImpl extends HttpServletResponseWrapper implements ImageServletResponse {
|
class ImageServletResponseImpl extends HttpServletResponseWrapper implements ImageServletResponse {
|
||||||
|
|
||||||
private ServletRequest originalRequest;
|
private ServletRequest originalRequest;
|
||||||
private final ServletContext context;
|
private final ServletContext context;
|
||||||
private final ServletResponseStreamDelegate streamDelegate;
|
private final ServletResponseStreamDelegate streamDelegate;
|
||||||
@ -223,6 +221,9 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
|||||||
|
|
||||||
// The default JPEG quality is not good enough, so always adjust compression/quality
|
// The default JPEG quality is not good enough, so always adjust compression/quality
|
||||||
if ((requestQuality != null || "jpeg".equalsIgnoreCase(getFormatNameSafe(writer))) && param.canWriteCompressed()) {
|
if ((requestQuality != null || "jpeg".equalsIgnoreCase(getFormatNameSafe(writer))) && param.canWriteCompressed()) {
|
||||||
|
// TODO: See http://blog.apokalyptik.com/2009/09/16/quality-time-with-your-jpegs/ for better adjusting the (default) JPEG quality
|
||||||
|
// OR: Use the metadata of the original image
|
||||||
|
|
||||||
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||||
|
|
||||||
// WORKAROUND: Known bug in GIFImageWriter in certain JDK versions, compression type is not set by default
|
// WORKAROUND: Known bug in GIFImageWriter in certain JDK versions, compression type is not set by default
|
||||||
@ -234,10 +235,13 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ("gif".equalsIgnoreCase(getFormatNameSafe(writer)) && !(image.getColorModel() instanceof IndexColorModel)
|
if ("gif".equalsIgnoreCase(getFormatNameSafe(writer)) && !(image.getColorModel() instanceof IndexColorModel)
|
||||||
&& image.getColorModel().getTransparency() != Transparency.OPAQUE) {
|
/*&& image.getColorModel().getTransparency() != Transparency.OPAQUE*/) {
|
||||||
// WORKAROUND: Bug in GIFImageWriter may throw NPE if transparent pixels
|
// WORKAROUND: Bug in GIFImageWriter may throw NPE if transparent pixels
|
||||||
// See: http://bugs.sun.com/view_bug.do?bug_id=6287936
|
// See: http://bugs.sun.com/view_bug.do?bug_id=6287936
|
||||||
image = ImageUtil.createIndexed(ImageUtil.toBuffered(image), 256, null, ImageUtil.TRANSPARENCY_BITMASK | ImageUtil.DITHER_DIFFUSION_ALTSCANS);
|
image = ImageUtil.createIndexed(
|
||||||
|
ImageUtil.toBuffered(image), 256, null,
|
||||||
|
(image.getColorModel().getTransparency() == Transparency.OPAQUE ? ImageUtil.TRANSPARENCY_OPAQUE : ImageUtil.TRANSPARENCY_BITMASK) | ImageUtil.DITHER_DIFFUSION_ALTSCANS
|
||||||
|
);
|
||||||
}
|
}
|
||||||
//////////////////
|
//////////////////
|
||||||
ImageOutputStream stream = ImageIO.createImageOutputStream(out);
|
ImageOutputStream stream = ImageIO.createImageOutputStream(out);
|
||||||
@ -425,18 +429,29 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
|||||||
if (image != null && size != null && (image.getWidth() != size.width || image.getHeight() != size.height)) {
|
if (image != null && size != null && (image.getWidth() != size.width || image.getHeight() != size.height)) {
|
||||||
int resampleAlgorithm = getResampleAlgorithmFromRequest();
|
int resampleAlgorithm = getResampleAlgorithmFromRequest();
|
||||||
|
|
||||||
|
// TODO: One possibility is to NOT handle index color here, and only handle it later, IF NEEDED (read: GIF,
|
||||||
|
// possibly also for PNG) when we know the output format (flush method).
|
||||||
|
// This will make the filter faster (and better quality, possibly at the expense of more bytes being sent
|
||||||
|
// over the wire) in the general case. Who uses GIF nowadays anyway?
|
||||||
|
// Also, this means we could either keep the original IndexColorModel in the filter, or go through the
|
||||||
|
// expensive operation of re-calculating the optimal palette for the new image (the latter might improve quality).
|
||||||
|
|
||||||
// NOTE: Only use createScaled if IndexColorModel, as it's more expensive due to color conversion
|
// NOTE: Only use createScaled if IndexColorModel, as it's more expensive due to color conversion
|
||||||
if (image.getColorModel() instanceof IndexColorModel) {
|
/* if (image.getColorModel() instanceof IndexColorModel) {
|
||||||
return ImageUtil.createScaled(image, size.width, size.height, resampleAlgorithm);
|
// return ImageUtil.createScaled(image, size.width, size.height, resampleAlgorithm);
|
||||||
|
BufferedImage resampled = ImageUtil.createResampled(image, size.width, size.height, resampleAlgorithm);
|
||||||
|
return ImageUtil.createIndexed(resampled, (IndexColorModel) image.getColorModel(), null, ImageUtil.DITHER_NONE | ImageUtil.TRANSPARENCY_BITMASK);
|
||||||
|
// return ImageUtil.createIndexed(resampled, 256, null, ImageUtil.COLOR_SELECTION_QUALITY | ImageUtil.DITHER_NONE | ImageUtil.TRANSPARENCY_BITMASK);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
*/
|
||||||
return ImageUtil.createResampled(image, size.width, size.height, resampleAlgorithm);
|
return ImageUtil.createResampled(image, size.width, size.height, resampleAlgorithm);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getResampleAlgorithmFromRequest() {
|
int getResampleAlgorithmFromRequest() {
|
||||||
Object algorithm = originalRequest.getAttribute(ATTRIB_IMAGE_RESAMPLE_ALGORITHM);
|
Object algorithm = originalRequest.getAttribute(ATTRIB_IMAGE_RESAMPLE_ALGORITHM);
|
||||||
if (algorithm instanceof Integer && ((Integer) algorithm == Image.SCALE_SMOOTH || (Integer) algorithm == Image.SCALE_FAST || (Integer) algorithm == Image.SCALE_DEFAULT)) {
|
if (algorithm instanceof Integer && ((Integer) algorithm == Image.SCALE_SMOOTH || (Integer) algorithm == Image.SCALE_FAST || (Integer) algorithm == Image.SCALE_DEFAULT)) {
|
||||||
return (Integer) algorithm;
|
return (Integer) algorithm;
|
||||||
@ -445,6 +460,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
|||||||
if (algorithm != null) {
|
if (algorithm != null) {
|
||||||
context.log("WARN: Illegal image resampling algorithm: " + algorithm);
|
context.log("WARN: Illegal image resampling algorithm: " + algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BufferedImage.SCALE_DEFAULT;
|
return BufferedImage.SCALE_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,13 @@ package com.twelvemonkeys.servlet.image;
|
|||||||
|
|
||||||
import com.twelvemonkeys.image.BufferedImageIcon;
|
import com.twelvemonkeys.image.BufferedImageIcon;
|
||||||
import com.twelvemonkeys.image.ImageUtil;
|
import com.twelvemonkeys.image.ImageUtil;
|
||||||
|
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||||
import com.twelvemonkeys.io.FileUtil;
|
import com.twelvemonkeys.io.FileUtil;
|
||||||
import com.twelvemonkeys.servlet.OutputStreamAdapter;
|
import com.twelvemonkeys.servlet.OutputStreamAdapter;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
import javax.imageio.ImageIO;
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
@ -15,8 +18,8 @@ import javax.servlet.http.HttpServletResponse;
|
|||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.IndexColorModel;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@ -30,7 +33,7 @@ import static org.mockito.Mockito.*;
|
|||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @author last modified by $Author: haku $
|
* @author last modified by $Author: haku $
|
||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/test/java/com/twelvemonkeys/servlet/image/ImageServletResponseImplTestCase.java#6 $
|
* @version $Id: twelvemonkeys-servlet/src/test/java/com/twelvemonkeys/servlet/image/ImageServletResponseImplTestCase.java#6 $
|
||||||
*/
|
*/
|
||||||
public class ImageServletResponseImplTestCase {
|
public class ImageServletResponseImplTestCase {
|
||||||
private static final String CONTENT_TYPE_BMP = "image/bmp";
|
private static final String CONTENT_TYPE_BMP = "image/bmp";
|
||||||
@ -42,9 +45,13 @@ public class ImageServletResponseImplTestCase {
|
|||||||
|
|
||||||
private static final String IMAGE_NAME_PNG = "12monkeys-splash.png";
|
private static final String IMAGE_NAME_PNG = "12monkeys-splash.png";
|
||||||
private static final String IMAGE_NAME_GIF = "tux.gif";
|
private static final String IMAGE_NAME_GIF = "tux.gif";
|
||||||
|
private static final String IMAGE_NAME_PNG_INDEXED = "star.png";
|
||||||
|
|
||||||
private static final Dimension IMAGE_DIMENSION_PNG = new Dimension(300, 410);
|
private static final Dimension IMAGE_DIMENSION_PNG = new Dimension(300, 410);
|
||||||
private static final Dimension IMAGE_DIMENSION_GIF = new Dimension(250, 250);
|
private static final Dimension IMAGE_DIMENSION_GIF = new Dimension(250, 250);
|
||||||
|
private static final Dimension IMAGE_DIMENSION_PNG_INDEXED = new Dimension(199, 192);
|
||||||
|
|
||||||
|
private static final int STREAM_DEFAULT_SIZE = 2000;
|
||||||
|
|
||||||
private HttpServletRequest request;
|
private HttpServletRequest request;
|
||||||
private ServletContext context;
|
private ServletContext context;
|
||||||
@ -58,12 +65,19 @@ public class ImageServletResponseImplTestCase {
|
|||||||
context = mock(ServletContext.class);
|
context = mock(ServletContext.class);
|
||||||
when(context.getResource("/" + IMAGE_NAME_PNG)).thenReturn(getClass().getResource(IMAGE_NAME_PNG));
|
when(context.getResource("/" + IMAGE_NAME_PNG)).thenReturn(getClass().getResource(IMAGE_NAME_PNG));
|
||||||
when(context.getResource("/" + IMAGE_NAME_GIF)).thenReturn(getClass().getResource(IMAGE_NAME_GIF));
|
when(context.getResource("/" + IMAGE_NAME_GIF)).thenReturn(getClass().getResource(IMAGE_NAME_GIF));
|
||||||
|
when(context.getResource("/" + IMAGE_NAME_PNG_INDEXED)).thenReturn(getClass().getResource(IMAGE_NAME_PNG_INDEXED));
|
||||||
when(context.getMimeType("file.bmp")).thenReturn(CONTENT_TYPE_BMP);
|
when(context.getMimeType("file.bmp")).thenReturn(CONTENT_TYPE_BMP);
|
||||||
when(context.getMimeType("file.foo")).thenReturn(CONTENT_TYPE_FOO);
|
when(context.getMimeType("file.foo")).thenReturn(CONTENT_TYPE_FOO);
|
||||||
when(context.getMimeType("file.gif")).thenReturn(CONTENT_TYPE_GIF);
|
when(context.getMimeType("file.gif")).thenReturn(CONTENT_TYPE_GIF);
|
||||||
when(context.getMimeType("file.jpeg")).thenReturn(CONTENT_TYPE_JPEG);
|
when(context.getMimeType("file.jpeg")).thenReturn(CONTENT_TYPE_JPEG);
|
||||||
when(context.getMimeType("file.png")).thenReturn(CONTENT_TYPE_PNG);
|
when(context.getMimeType("file.png")).thenReturn(CONTENT_TYPE_PNG);
|
||||||
when(context.getMimeType("file.txt")).thenReturn(CONTENT_TYPE_TEXT);
|
when(context.getMimeType("file.txt")).thenReturn(CONTENT_TYPE_TEXT);
|
||||||
|
|
||||||
|
MockLogger mockLogger = new MockLogger();
|
||||||
|
doAnswer(mockLogger).when(context).log(anyString());
|
||||||
|
doAnswer(mockLogger).when(context).log(anyString(), any(Throwable.class));
|
||||||
|
//noinspection deprecation
|
||||||
|
doAnswer(mockLogger).when(context).log(any(Exception.class), anyString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fakeResponse(HttpServletRequest pRequest, ImageServletResponseImpl pImageResponse) throws IOException {
|
private void fakeResponse(HttpServletRequest pRequest, ImageServletResponseImpl pImageResponse) throws IOException {
|
||||||
@ -98,7 +112,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBasicResponse() throws IOException {
|
public void testBasicResponse() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
@ -118,7 +132,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -133,7 +147,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNoOpResponse() throws IOException {
|
public void testNoOpResponse() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
@ -157,7 +171,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
// Transcode original PNG to JPEG with no other changes
|
// Transcode original PNG to JPEG with no other changes
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeResponsePNGToJPEG() throws IOException {
|
public void testTranscodeResponsePNGToJPEG() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
@ -173,6 +187,12 @@ public class ImageServletResponseImplTestCase {
|
|||||||
|
|
||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
|
// Assert JPEG
|
||||||
|
ByteArrayInputStream input = out.createInputStream();
|
||||||
|
assertEquals(0xFF, input.read());
|
||||||
|
assertEquals(0xD8, input.read());
|
||||||
|
assertEquals(0xFF, input.read());
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
/*
|
/*
|
||||||
File tempFile = File.createTempFile("imageservlet-test-", ".jpeg");
|
File tempFile = File.createTempFile("imageservlet-test-", ".jpeg");
|
||||||
@ -182,7 +202,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
System.err.println("open " + tempFile);
|
System.err.println("open " + tempFile);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
||||||
@ -208,43 +228,53 @@ public class ImageServletResponseImplTestCase {
|
|||||||
// (even if there's only one possible compression mode/type combo; MODE_EXPLICIT/"LZW")
|
// (even if there's only one possible compression mode/type combo; MODE_EXPLICIT/"LZW")
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeResponsePNGToGIFWithQuality() throws IOException {
|
public void testTranscodeResponsePNGToGIFWithQuality() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
when(request.getAttribute(ImageServletResponse.ATTRIB_OUTPUT_QUALITY)).thenReturn(.5f); // Force quality setting in param
|
when(request.getAttribute(ImageServletResponse.ATTRIB_OUTPUT_QUALITY)).thenReturn(.5f); // Force quality setting in param
|
||||||
|
|
||||||
ImageServletResponseImpl imageResponse = new ImageServletResponseImpl(request, response, context);
|
ImageServletResponseImpl imageResponse = new ImageServletResponseImpl(request, response, context);
|
||||||
fakeResponse(request, imageResponse);
|
fakeResponse(request, imageResponse);
|
||||||
|
|
||||||
// Force transcode to GIF
|
// Force transcode to GIF
|
||||||
imageResponse.setOutputContentType("image/gif");
|
imageResponse.setOutputContentType("image/gif");
|
||||||
|
|
||||||
// Flush image to wrapped response
|
// Flush image to wrapped response
|
||||||
imageResponse.flush();
|
imageResponse.flush();
|
||||||
|
|
||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Assert GIF
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
ByteArrayInputStream stream = out.createInputStream();
|
||||||
assertNotNull(outImage);
|
assertEquals('G', stream.read());
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
assertEquals('I', stream.read());
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
assertEquals('F', stream.read());
|
||||||
|
assertEquals('8', stream.read());
|
||||||
|
assertEquals('9', stream.read());
|
||||||
|
assertEquals('a', stream.read());
|
||||||
|
|
||||||
BufferedImage image = ImageIO.read(context.getResource("/" + IMAGE_NAME_PNG));
|
// Test that image data is still readable
|
||||||
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
|
assertNotNull(outImage);
|
||||||
|
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
||||||
|
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
||||||
|
|
||||||
// Should keep transparency, but is now binary
|
BufferedImage image = ImageIO.read(context.getResource("/" + IMAGE_NAME_PNG));
|
||||||
assertSimilarImageTransparent(image, outImage, 120f);
|
|
||||||
|
|
||||||
verify(response).setContentType(CONTENT_TYPE_GIF);
|
// Should keep transparency, but is now binary
|
||||||
verify(response).getOutputStream();
|
// showIt(image, outImage, null);
|
||||||
}
|
assertSimilarImageTransparent(image, outImage, 50f);
|
||||||
|
|
||||||
|
verify(response).setContentType(CONTENT_TYPE_GIF);
|
||||||
|
verify(response).getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
// WORKAROUND: Bug in GIFImageWriter may throw NPE if transparent pixels
|
// WORKAROUND: Bug in GIFImageWriter may throw NPE if transparent pixels
|
||||||
// See: http://bugs.sun.com/view_bug.do?bug_id=6287936
|
// See: http://bugs.sun.com/view_bug.do?bug_id=6287936
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeResponsePNGToGIF() throws IOException {
|
public void testTranscodeResponsePNGToGIF() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -260,7 +290,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
assertEquals(IMAGE_DIMENSION_PNG.width, outImage.getWidth());
|
||||||
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
assertEquals(IMAGE_DIMENSION_PNG.height, outImage.getHeight());
|
||||||
@ -268,7 +298,8 @@ public class ImageServletResponseImplTestCase {
|
|||||||
BufferedImage image = ImageIO.read(context.getResource("/" + IMAGE_NAME_PNG));
|
BufferedImage image = ImageIO.read(context.getResource("/" + IMAGE_NAME_PNG));
|
||||||
|
|
||||||
// Should keep transparency, but is now binary
|
// Should keep transparency, but is now binary
|
||||||
assertSimilarImageTransparent(image, outImage, 120f);
|
// showIt(image, outImage, null);
|
||||||
|
assertSimilarImageTransparent(image, outImage, 50f);
|
||||||
|
|
||||||
verify(response).setContentType(CONTENT_TYPE_GIF);
|
verify(response).setContentType(CONTENT_TYPE_GIF);
|
||||||
verify(response).getOutputStream();
|
verify(response).getOutputStream();
|
||||||
@ -297,13 +328,13 @@ public class ImageServletResponseImplTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTranscodeResponseIndexedCM() throws IOException {
|
public void testTranscodeResponseIndexColorModelGIFToJPEG() throws IOException {
|
||||||
// Custom setup
|
// Custom setup
|
||||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_GIF);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_GIF);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -318,8 +349,14 @@ public class ImageServletResponseImplTestCase {
|
|||||||
|
|
||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
|
// Assert JPEG
|
||||||
|
ByteArrayInputStream stream = out.createInputStream();
|
||||||
|
assertEquals(0xFF, stream.read());
|
||||||
|
assertEquals(0xD8, stream.read());
|
||||||
|
assertEquals(0xFF, stream.read());
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(IMAGE_DIMENSION_GIF.width, outImage.getWidth());
|
assertEquals(IMAGE_DIMENSION_GIF.width, outImage.getWidth());
|
||||||
assertEquals(IMAGE_DIMENSION_GIF.height, outImage.getHeight());
|
assertEquals(IMAGE_DIMENSION_GIF.height, outImage.getHeight());
|
||||||
@ -329,6 +366,59 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertSimilarImage(image, outImage, 96f);
|
assertSimilarImage(image, outImage, 96f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// TODO: Insert bug id/reference here for regression tracking
|
||||||
|
public void testIndexedColorModelResizePNG() throws IOException {
|
||||||
|
// Results differ with algorithm, so we test each algorithm by itself
|
||||||
|
int[] algorithms = new int[] {Image.SCALE_DEFAULT, Image.SCALE_FAST, Image.SCALE_SMOOTH, Image.SCALE_REPLICATE, Image.SCALE_AREA_AVERAGING, 77};
|
||||||
|
|
||||||
|
for (int algorithm : algorithms) {
|
||||||
|
Dimension size = new Dimension(100, 100);
|
||||||
|
|
||||||
|
// Custom setup
|
||||||
|
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||||
|
when(request.getAttribute(ImageServletResponse.ATTRIB_SIZE)).thenReturn(size);
|
||||||
|
when(request.getAttribute(ImageServletResponse.ATTRIB_SIZE_UNIFORM)).thenReturn(false);
|
||||||
|
when(request.getAttribute(ImageServletResponse.ATTRIB_IMAGE_RESAMPLE_ALGORITHM)).thenReturn(algorithm);
|
||||||
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG_INDEXED);
|
||||||
|
|
||||||
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
|
ImageServletResponseImpl imageResponse = new ImageServletResponseImpl(request, response, context);
|
||||||
|
fakeResponse(request, imageResponse);
|
||||||
|
|
||||||
|
imageResponse.getImage();
|
||||||
|
|
||||||
|
// Flush image to wrapped response
|
||||||
|
imageResponse.flush();
|
||||||
|
|
||||||
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
|
// Assert format is still PNG
|
||||||
|
ByteArrayInputStream inputStream = out.createInputStream();
|
||||||
|
assertEquals(0x89, inputStream.read());
|
||||||
|
assertEquals('P', inputStream.read());
|
||||||
|
assertEquals('N', inputStream.read());
|
||||||
|
assertEquals('G', inputStream.read());
|
||||||
|
|
||||||
|
// Test that image data is still readable
|
||||||
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
|
assertNotNull(outImage);
|
||||||
|
assertEquals(size.width, outImage.getWidth());
|
||||||
|
assertEquals(size.height, outImage.getHeight());
|
||||||
|
|
||||||
|
BufferedImage read = ImageIO.read(context.getResource("/" + IMAGE_NAME_PNG_INDEXED));
|
||||||
|
BufferedImage image = ImageUtil.createResampled(read, size.width, size.height, imageResponse.getResampleAlgorithmFromRequest());
|
||||||
|
|
||||||
|
// showIt(image, outImage, null);
|
||||||
|
|
||||||
|
assertSimilarImageTransparent(image, outImage, 10f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static BufferedImage flatten(final BufferedImage pImage, final Color pBackgroundColor) {
|
private static BufferedImage flatten(final BufferedImage pImage, final Color pBackgroundColor) {
|
||||||
BufferedImage image = ImageUtil.toBuffered(pImage, BufferedImage.TYPE_INT_ARGB);
|
BufferedImage image = ImageUtil.toBuffered(pImage, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
@ -369,32 +459,64 @@ public class ImageServletResponseImplTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void assertSimilarImageTransparent(final BufferedImage pExpected, final BufferedImage pActual, final float pArtifactThreshold) {
|
private void assertSimilarImageTransparent(final BufferedImage pExpected, final BufferedImage pActual, final float pArtifactThreshold) {
|
||||||
|
IndexColorModel icm = pActual.getColorModel() instanceof IndexColorModel ? (IndexColorModel) pActual.getColorModel() : null;
|
||||||
|
Object pixel = null;
|
||||||
|
|
||||||
for (int y = 0; y < pExpected.getHeight(); y++) {
|
for (int y = 0; y < pExpected.getHeight(); y++) {
|
||||||
for (int x = 0; x < pExpected.getWidth(); x++) {
|
for (int x = 0; x < pExpected.getWidth(); x++) {
|
||||||
int expected = pExpected.getRGB(x, y);
|
int expected = pExpected.getRGB(x, y);
|
||||||
int actual = pActual.getRGB(x, y);
|
int actual = pActual.getRGB(x, y);
|
||||||
|
|
||||||
int alpha = (expected >> 24) & 0xff;
|
if (icm != null) {
|
||||||
|
// Look up, using ICM
|
||||||
|
|
||||||
boolean transparent = alpha < 0x40;
|
int alpha = (expected >> 24) & 0xff;
|
||||||
|
boolean transparent = alpha < 0x40;
|
||||||
|
|
||||||
// Multiply out alpha for each component
|
if (transparent) {
|
||||||
int expectedR = (int) ((((expected >> 16) & 0xff) * alpha) / 255f);
|
int expectedLookedUp = icm.getRGB(icm.getTransparentPixel());
|
||||||
int expectedG = (int) ((((expected >> 8 ) & 0xff) * alpha) / 255f);
|
assertRGBEquals(x, y, expectedLookedUp & 0xff000000, actual & 0xff000000, 0);
|
||||||
int expectedB = (int) ((( expected & 0xff) * alpha) / 255f);
|
}
|
||||||
|
else {
|
||||||
|
pixel = icm.getDataElements(expected, pixel);
|
||||||
|
int expectedLookedUp = icm.getRGB(pixel);
|
||||||
|
assertRGBEquals(x, y, expectedLookedUp & 0xffffff, actual & 0xffffff, pArtifactThreshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Multiply out alpha for each component if pre-multiplied
|
||||||
|
// int expectedR = (int) ((((expected >> 16) & 0xff) * alpha) / 255f);
|
||||||
|
// int expectedG = (int) ((((expected >> 8) & 0xff) * alpha) / 255f);
|
||||||
|
// int expectedB = (int) (((expected & 0xff) * alpha) / 255f);
|
||||||
|
|
||||||
|
assertRGBEquals(x, y, expected, actual, pArtifactThreshold);
|
||||||
assertEquals("a(" + x + "," + y + ")", transparent ? 0 : 0xff, (actual >> 24) & 0xff);
|
}
|
||||||
assertEquals("R(" + x + "," + y + ")", expectedR, (actual >> 16) & 0xff, pArtifactThreshold);
|
|
||||||
assertEquals("G(" + x + "," + y + ")", expectedG, (actual >> 8) & 0xff, pArtifactThreshold);
|
|
||||||
assertEquals("B(" + x + "," + y + ")", expectedB, actual & 0xff, pArtifactThreshold);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertRGBEquals(int x, int y, int expected, int actual, float pArtifactThreshold) {
|
||||||
|
int expectedA = (expected >> 24) & 0xff;
|
||||||
|
int expectedR = (expected >> 16) & 0xff;
|
||||||
|
int expectedG = (expected >> 8) & 0xff;
|
||||||
|
int expectedB = expected & 0xff;
|
||||||
|
|
||||||
|
try {
|
||||||
|
assertEquals("Alpha", expectedA, (actual >> 24) & 0xff, pArtifactThreshold);
|
||||||
|
assertEquals("RGB", 0, (Math.abs(expectedR - ((actual >> 16) & 0xff)) +
|
||||||
|
Math.abs(expectedG - ((actual >> 8) & 0xff)) +
|
||||||
|
Math.abs(expectedB - ((actual) & 0xff))) / 3.0, pArtifactThreshold);
|
||||||
|
}
|
||||||
|
catch (AssertionError e) {
|
||||||
|
AssertionError assertionError = new AssertionError(String.format("@[%d,%d] expected: 0x%08x but was: 0x%08x", x, y, expected, actual));
|
||||||
|
assertionError.initCause(e);
|
||||||
|
throw assertionError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testReplaceResponse() throws IOException {
|
public void testReplaceResponse() throws IOException {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -418,7 +540,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -527,7 +649,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -546,7 +668,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -564,7 +686,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
|
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
@ -584,7 +706,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -605,7 +727,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -645,7 +767,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -666,7 +788,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -729,7 +851,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -748,7 +870,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -777,7 +899,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -796,7 +918,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -815,7 +937,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -836,7 +958,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -865,7 +987,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -886,7 +1008,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -905,7 +1027,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -927,7 +1049,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -964,7 +1086,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -986,7 +1108,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -1027,7 +1149,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -1049,7 +1171,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
when(request.getContextPath()).thenReturn("/ape");
|
when(request.getContextPath()).thenReturn("/ape");
|
||||||
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
when(request.getRequestURI()).thenReturn("/ape/" + IMAGE_NAME_PNG);
|
||||||
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
FastByteArrayOutputStream out = new FastByteArrayOutputStream(STREAM_DEFAULT_SIZE);
|
||||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||||
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
when(response.getOutputStream()).thenReturn(new OutputStreamAdapter(out));
|
||||||
|
|
||||||
@ -1070,7 +1192,7 @@ public class ImageServletResponseImplTestCase {
|
|||||||
assertTrue("Content has no data", out.size() > 0);
|
assertTrue("Content has no data", out.size() > 0);
|
||||||
|
|
||||||
// Test that image data is still readable
|
// Test that image data is still readable
|
||||||
BufferedImage outImage = ImageIO.read(new ByteArrayInputStream(out.toByteArray()));
|
BufferedImage outImage = ImageIO.read(out.createInputStream());
|
||||||
assertNotNull(outImage);
|
assertNotNull(outImage);
|
||||||
assertEquals(image.getWidth(), outImage.getWidth());
|
assertEquals(image.getWidth(), outImage.getWidth());
|
||||||
assertEquals(image.getHeight(), outImage.getHeight());
|
assertEquals(image.getHeight(), outImage.getHeight());
|
||||||
@ -1401,6 +1523,9 @@ public class ImageServletResponseImplTestCase {
|
|||||||
// TODO: Test getSize()...
|
// TODO: Test getSize()...
|
||||||
|
|
||||||
private static class BlackLabel extends JLabel {
|
private static class BlackLabel extends JLabel {
|
||||||
|
private final Paint checkeredBG;
|
||||||
|
private boolean opaque = true;
|
||||||
|
|
||||||
public BlackLabel(final String text, final BufferedImage outImage) {
|
public BlackLabel(final String text, final BufferedImage outImage) {
|
||||||
super(text, new BufferedImageIcon(outImage), JLabel.CENTER);
|
super(text, new BufferedImageIcon(outImage), JLabel.CENTER);
|
||||||
setOpaque(true);
|
setOpaque(true);
|
||||||
@ -1409,6 +1534,71 @@ public class ImageServletResponseImplTestCase {
|
|||||||
setVerticalAlignment(JLabel.CENTER);
|
setVerticalAlignment(JLabel.CENTER);
|
||||||
setVerticalTextPosition(JLabel.BOTTOM);
|
setVerticalTextPosition(JLabel.BOTTOM);
|
||||||
setHorizontalTextPosition(JLabel.CENTER);
|
setHorizontalTextPosition(JLabel.CENTER);
|
||||||
|
|
||||||
|
checkeredBG = createTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOpaque() {
|
||||||
|
return opaque && super.isOpaque();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintComponent(Graphics graphics) {
|
||||||
|
Graphics2D g = (Graphics2D) graphics;
|
||||||
|
|
||||||
|
int iconHeight = getIcon() == null ? 0 : getIcon().getIconHeight() + getIconTextGap();
|
||||||
|
|
||||||
|
// Paint checkered bg behind icon
|
||||||
|
g.setPaint(checkeredBG);
|
||||||
|
g.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
// Paint black bg behind text
|
||||||
|
g.setColor(getBackground());
|
||||||
|
g.fillRect(0, iconHeight, getWidth(), getHeight() - iconHeight);
|
||||||
|
|
||||||
|
try {
|
||||||
|
opaque = false;
|
||||||
|
super.paintComponent(g);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
opaque = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Paint createTexture() {
|
||||||
|
GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
|
||||||
|
BufferedImage pattern = graphicsConfiguration.createCompatibleImage(20, 20);
|
||||||
|
Graphics2D g = pattern.createGraphics();
|
||||||
|
try {
|
||||||
|
g.setColor(Color.LIGHT_GRAY);
|
||||||
|
g.fillRect(0, 0, pattern.getWidth(), pattern.getHeight());
|
||||||
|
g.setColor(Color.GRAY);
|
||||||
|
g.fillRect(0, 0, pattern.getWidth() / 2, pattern.getHeight() / 2);
|
||||||
|
g.fillRect(pattern.getWidth() / 2, pattern.getHeight() / 2, pattern.getWidth() / 2, pattern.getHeight() / 2);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
g.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TexturePaint(pattern, new Rectangle(pattern.getWidth(), pattern.getHeight()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MockLogger implements Answer<Void> {
|
||||||
|
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||||
|
// either log(String), log(String, Throwable) or log(Exception, String)
|
||||||
|
Object[] arguments = invocation.getArguments();
|
||||||
|
|
||||||
|
String msg = (String) (arguments[0] instanceof String ? arguments[0] : arguments[1]);
|
||||||
|
Throwable t = (Throwable) (arguments[0] instanceof Exception ? arguments[0] : arguments.length > 1 ? arguments[1] : null);
|
||||||
|
|
||||||
|
System.out.println("mock-context: " + msg);
|
||||||
|
if (t != null) {
|
||||||
|
t.printStackTrace(System.out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
After Width: | Height: | Size: 5.8 KiB |
Loading…
x
Reference in New Issue
Block a user