package ch.entwine.weblounge.test.harness.rest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import ch.entwine.weblounge.common.content.image.ImageStyle;
import ch.entwine.weblounge.common.impl.content.image.ImageStyleImpl;
import ch.entwine.weblounge.common.impl.content.image.ImageStyleUtils;
import ch.entwine.weblounge.common.impl.testing.IntegrationTestBase;
import ch.entwine.weblounge.common.impl.util.TestUtils;
import ch.entwine.weblounge.common.impl.util.xml.XPathHelper;
import ch.entwine.weblounge.common.site.ImageScalingMode;
import ch.entwine.weblounge.common.url.UrlUtils;
import ch.entwine.weblounge.test.util.TestSiteUtils;
import com.sun.media.jai.codec.MemoryCacheSeekableStream;
import com.sun.media.jai.codec.SeekableStream;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import javax.servlet.http.HttpServletResponse;
/**
* Integration test to test the content repository's <code>restful</code>
* previews api.
*/
public class PreviewsEndpointTest extends IntegrationTestBase {
/** The logger */
private static final Logger logger = LoggerFactory.getLogger(PreviewsEndpointTest.class);
/** The scaling modes to test */
private static final List<ImageStyle> styles = new ArrayList<ImageStyle>();
/** The endpoint's url */
private static final String baseURL = "system/weblounge/previews";
/** The original image's width */
private static final int originalWidth = 1000;
/** The original image's height */
private static final int originalHeight = 666;
/** File name of the English version */
private static final String filename = "porsche.jpg";
/** The style's width */
private static final int BOX_WIDTH = 250;
/** The style's height */
private static final int BOX_HEIGHT = 250;
/** The style's width */
private static final int PREVIEW_WIDTH = 300;
/** The style's height */
private static final int PREVIEW_HEIGHT = 200;
/** Mime type of the English version */
private static final String mimetypeJpeg = "image/jpeg";
/** Mime type of the English version */
private static final String mimetypePng = "image/png";
/** Image resource identifier */
private static final String imageId = "5bc19990-8f99-4873-a813-71b6dfac22ad";
/** Image resource identifier */
private static final String pageId = "4bb19980-8f98-4873-a813-000000000001";
/** Modification date parser */
private static final SimpleDateFormat lastModifiedDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
static {
styles.add(new ImageStyleImpl("box", BOX_WIDTH, BOX_HEIGHT, ImageScalingMode.Box, false, false));
styles.add(new ImageStyleImpl("cover", BOX_WIDTH, BOX_HEIGHT, ImageScalingMode.Cover, false, false));
styles.add(new ImageStyleImpl("fill", BOX_WIDTH, BOX_HEIGHT, ImageScalingMode.Fill, false, false));
styles.add(new ImageStyleImpl("width", BOX_WIDTH, -1, ImageScalingMode.Width, false, false));
styles.add(new ImageStyleImpl("height", -1, BOX_HEIGHT, ImageScalingMode.Height, false, false));
styles.add(new ImageStyleImpl("none", -1, -1, ImageScalingMode.None, false, false));
styles.add(new ImageStyleImpl("weblounge-ui-preview", PREVIEW_WIDTH, PREVIEW_HEIGHT, ImageScalingMode.Cover, false, false));
}
public PreviewsEndpointTest() {
super("Previews Endpoint Test", WEBLOUNGE_ENDPOINT_TEST_GROUP);
}
/**
* {@inheritDoc}
*
* @see ch.entwine.weblounge.testing.kernel.IntegrationTest#execute(java.lang.String)
*/
@Override
public void execute(String serverUrl) throws Exception {
logger.info("Preparing test of previews endpoint");
String requestUrl = UrlUtils.concat(serverUrl, baseURL);
testGetImageStyles(requestUrl);
testGetImageStyle(requestUrl);
// Test to preview a image
for (ImageStyle style : styles) {
testImagePreview(requestUrl, imageId, style);
}
// Test to preview a page
for (ImageStyle style : styles) {
testPagePreview(requestUrl, pageId, style);
}
// Test for non exist resource
testNoneExist(requestUrl, styles.get(0));
}
/**
* Tests the <code>/styles</code> method of the endpoint.
*
* @param serverUrl
* the base url
* @throws Exception
* if an exception occurs
*/
private void testGetImageStyles(String serverUrl) throws Exception {
String url = UrlUtils.concat(serverUrl, "styles");
logger.info("");
logger.info("Testing image styles");
logger.info("");
HttpGet getStylesRequest = new HttpGet(url);
HttpClient httpClient = new DefaultHttpClient();
try {
logger.debug("Requesting list of image styles");
HttpResponse response = TestUtils.request(httpClient, getStylesRequest, null);
assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
assertTrue("Endpoint returned no content", response.getEntity().getContentLength() > 0);
Document stylesXml = TestUtils.parseXMLResponse(response);
assertEquals(12, Integer.parseInt(XPathHelper.valueOf(stylesXml, "count(//imagestyle)")));
} finally {
httpClient.getConnectionManager().shutdown();
}
}
/**
* Tests the <code>/style/{style}</code> method of the endpoint.
*
* @param serverUrl
* the base url
* @throws Exception
* if an exception occurs
*/
private void testGetImageStyle(String serverUrl) throws Exception {
HttpClient httpClient = null;
logger.info("");
logger.info("Testing single image styles");
logger.info("");
for (ImageStyle style : styles) {
String styleId = style.getScalingMode().toString().toLowerCase();
String url = UrlUtils.concat(serverUrl, "styles", styleId);
HttpGet getStyleRequest = new HttpGet(url);
httpClient = new DefaultHttpClient();
try {
logger.info("Requesting image style definition '{}'", styleId);
HttpResponse response = TestUtils.request(httpClient, getStyleRequest, null);
assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
assertTrue("Endpoint returned no content", response.getEntity().getContentLength() > 0);
Document styleXml = TestUtils.parseXMLResponse(response);
assertEquals(1, Integer.parseInt(XPathHelper.valueOf(styleXml, "count(//imagestyle)")));
assertNotNull(styleId, XPathHelper.valueOf(styleXml, "//imagestyle/@id"));
} finally {
httpClient.getConnectionManager().shutdown();
}
}
}
@SuppressWarnings("cast")
private void testImagePreview(String serverUrl, String resourceId,
ImageStyle imageStyle) throws Exception {
String requestUrl = UrlUtils.concat(serverUrl, resourceId, "locales", "en", "styles", imageStyle.getIdentifier());
HttpGet getPreviewRequest = new HttpGet(requestUrl);
HttpClient httpClient = new DefaultHttpClient();
String eTagValue = null;
Date modificationDate = null;
String[][] params = new String[][] { { "force", "true" } };
logger.info("Requesting image preview at {}", requestUrl);
try {
HttpResponse response = TestUtils.request(httpClient, getPreviewRequest, params);
assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
assertTrue("No content received", response.getEntity().getContentLength() > 0);
// Test general headers
assertEquals(mimetypeJpeg, response.getHeaders("Content-Type")[0].getValue());
assertEquals(1, response.getHeaders("Content-Type").length);
assertEquals(1, response.getHeaders("Content-Disposition").length);
SeekableStream seekableInputStream = null;
try {
// Test file size
if (!ImageScalingMode.None.equals(imageStyle.getScalingMode())) {
float scale = ImageStyleUtils.getScale(originalWidth, originalHeight, imageStyle);
int scaledWidth = (int) Math.round(originalWidth * scale) - (int) ImageStyleUtils.getCropX(Math.round(originalWidth * scale), Math.round(originalHeight * scale), imageStyle);
int scaledHeight = (int) Math.round(originalHeight * scale) - (int) ImageStyleUtils.getCropY(Math.round(originalWidth * scale), Math.round(originalHeight * scale), imageStyle);
// Load the image from the given input stream
seekableInputStream = new MemoryCacheSeekableStream(response.getEntity().getContent());
RenderedOp image = JAI.create("stream", seekableInputStream);
if (image == null)
throw new IOException("Error reading image from input stream");
// Get the original image size
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
assertTrue((int) (scaledHeight) == imageHeight || (int) (scaledHeight) + 1 == imageHeight || (int) (scaledHeight) - 1 == imageHeight);
assertTrue((int) (scaledWidth) == imageWidth || (int) (scaledWidth) + 1 == imageWidth || (int) (scaledWidth) - 1 == imageWidth);
} else {
response.getEntity().consumeContent();
}
} finally {
IOUtils.closeQuietly(seekableInputStream);
}
// Test filename
String contentDisposition = response.getHeaders("Content-Disposition")[0].getValue();
assertTrue(contentDisposition.startsWith("inline; filename=" + filename.toString()));
// Test ETag header
Header eTagHeader = response.getFirstHeader("ETag");
assertNotNull(eTagHeader);
assertNotNull(eTagHeader.getValue());
eTagValue = eTagHeader.getValue();
// Test Last-Modified header
Header modifiedHeader = response.getFirstHeader("Last-Modified");
assertNotNull(modifiedHeader);
modificationDate = lastModifiedDateFormat.parse(modifiedHeader.getValue());
} finally {
httpClient.getConnectionManager().shutdown();
}
TestSiteUtils.testETagHeader(getPreviewRequest, eTagValue, logger, null);
TestSiteUtils.testModifiedHeader(getPreviewRequest, modificationDate, logger, null);
}
private void testPagePreview(String serverUrl, String resourceId,
ImageStyle imageStyle) throws Exception {
String requestUrl = UrlUtils.concat(serverUrl, resourceId, "locales", "fr", "styles", imageStyle.getIdentifier());
HttpGet getPreviewRequest = new HttpGet(requestUrl);
HttpClient httpClient = new DefaultHttpClient();
String eTagValue = null;
Date modificationDate = null;
logger.info("Requesting image preview at {}", requestUrl);
String[][] params = new String[][] { { "force", "true" } };
HttpResponse response = TestUtils.request(httpClient, getPreviewRequest, params);
if (ImageScalingMode.None.equals(imageStyle.getScalingMode())) {
assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatusLine().getStatusCode());
assertTrue("No content received", response.getEntity().getContentLength() < 1);
response.getEntity().consumeContent();
} else {
try {
assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode());
assertTrue("No content received", response.getEntity().getContentLength() > 0);
// Test general headers
assertEquals(mimetypePng, response.getHeaders("Content-Type")[0].getValue());
assertEquals(1, response.getHeaders("Content-Type").length);
assertEquals(1, response.getHeaders("Content-Disposition").length);
// Test filename
StringBuilder fileName = new StringBuilder(pageId).append("-").append(imageStyle.getIdentifier()).append(".png");
String contentDisposition = response.getHeaders("Content-Disposition")[0].getValue();
assertTrue(contentDisposition.startsWith("inline; filename=" + fileName.toString()));
// Test ETag header
Header eTagHeader = response.getFirstHeader("ETag");
assertNotNull(eTagHeader);
assertNotNull(eTagHeader.getValue());
eTagValue = eTagHeader.getValue();
// Test Last-Modified header
Header modifiedHeader = response.getFirstHeader("Last-Modified");
assertNotNull(modifiedHeader);
modificationDate = lastModifiedDateFormat.parse(modifiedHeader.getValue());
} finally {
httpClient.getConnectionManager().shutdown();
}
TestSiteUtils.testETagHeader(getPreviewRequest, eTagValue, logger, null);
TestSiteUtils.testModifiedHeader(getPreviewRequest, modificationDate, logger, null);
}
}
private void testNoneExist(String serverUrl, ImageStyle imageStyle)
throws Exception {
String requestUrl = UrlUtils.concat(serverUrl, "121083183-adf032", "locales", "en", "styles", imageStyle.getIdentifier());
HttpGet getPreviewRequest = new HttpGet(requestUrl);
HttpClient httpClient = new DefaultHttpClient();
logger.info("Requesting non existing resource preview at {}", requestUrl);
try {
HttpResponse response = TestUtils.request(httpClient, getPreviewRequest, null);
assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatusLine().getStatusCode());
} finally {
httpClient.getConnectionManager().shutdown();
}
}
}