Java tutorial
/* * Weblounge: Web Content Management System * Copyright (c) 2003 - 2011 The Weblounge Team * http://entwinemedia.com/weblounge * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package ch.entwine.weblounge.test.harness.content; import static junit.framework.Assert.assertFalse; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import ch.entwine.weblounge.common.content.page.Page; import ch.entwine.weblounge.common.impl.content.page.PageReader; import ch.entwine.weblounge.common.impl.language.LanguageUtils; import ch.entwine.weblounge.common.impl.testing.IntegrationTestBase; import ch.entwine.weblounge.common.impl.util.TestUtils; import ch.entwine.weblounge.common.language.Language; import ch.entwine.weblounge.common.url.UrlUtils; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPut; import org.apache.http.impl.client.DefaultHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; import javax.servlet.http.HttpServletResponse; /** * Integration test for the response cache. */ public class CacheTest extends IntegrationTestBase { /** The logger */ private static final Logger logger = LoggerFactory.getLogger(CacheTest.class); /** The paths to test */ private static final String contentTestPage = "/test/pagecontent"; /** The paths to test */ private static final String modificationTestPage = "/test/modificationDate"; /** The id of the page that is hosting the modification date pagelet */ private static final String modificationTestPageId = "4bb19980-8f98-4873-a813-000000000015"; /** The paths to host page */ private static final String hostPage = "/test/host"; /** The id of the page that is linked to by the host page */ private static final String linkedPageId = "4bb19980-8f98-4873-a813-a00000000002"; /** The request language */ private static final Language language = LanguageUtils.getLanguage(Locale.GERMAN); /** * Creates a new instance of the <code>HTML</code> page test. */ public CacheTest() { super("Response Cache Test", WEBLOUNGE_CONTENT_TEST_GROUP); } /** * {@inheritDoc} * * @see ch.entwine.weblounge.testing.kernel.IntegrationTest#execute(java.lang.String) */ @Override public void execute(String serverUrl) throws Exception { logger.info("Testing if response cache is activated"); // Test if the cache is active logger.info("Sending request to determine cache status to {}", serverUrl); HttpGet request = new HttpGet(serverUrl); request.addHeader("X-Cache-Debug", "yes"); String[][] params = new String[][] { {} }; // Send and the request and examine the response twice to make sure to get // a cached response is available boolean cacheIsActive = false; for (int i = 0; i < 2; i++) { HttpClient httpClient = new DefaultHttpClient(); try { HttpResponse response = TestUtils.request(httpClient, request, params); cacheIsActive = response.getHeaders("X-Cache-Key").length > 0; } finally { httpClient.getConnectionManager().shutdown(); } } if (!cacheIsActive) { logger.warn("Response cache is not available and won't be tested"); return; } logger.warn("Response cache is active"); testCacheHeaders(serverUrl); testInheritedModifcation(serverUrl); testPageletModifcationDate(serverUrl); } /** * Test if the cache is returning proper header to enable caching on the * client side, such as <code>Last-Modified</code>, <code>Expires</code> or * <code>ETag</code>. * * @param serverUrl * the server url * @throws Exception * if the test fails */ private void testCacheHeaders(String serverUrl) throws Exception { logger.info("Preparing test of response caching"); DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); df.setTimeZone(TimeZone.getTimeZone("GMT")); // Prepare the request logger.info("Testing response cache"); String requestUrl = UrlUtils.concat(serverUrl, contentTestPage, language.getIdentifier()); logger.info("Sending request to the {} version of {}", language.getLocale().getDisplayName(), requestUrl); HttpGet request = new HttpGet(requestUrl); request.addHeader("X-Cache-Debug", "yes"); String[][] params = new String[][] { { "language", language.getIdentifier() } }; // Send and the request and examine the response. The first request might // not come out of the cache logger.debug("Sending request to {}", request.getURI()); HttpClient httpClient = new DefaultHttpClient(); try { HttpResponse response = TestUtils.request(httpClient, request, params); int statusCode = response.getStatusLine().getStatusCode(); boolean okOrNotModified = statusCode == HttpServletResponse.SC_OK || statusCode == HttpServletResponse.SC_NOT_MODIFIED; assertTrue(okOrNotModified); // Get the ETag header assertNotNull(response.getHeaders("ETag")); assertEquals(1, response.getHeaders("ETag").length); String eTag = response.getHeaders("ETag")[0].getValue(); // Get the Expires header assertNotNull(response.getHeaders("Expires")); assertEquals(1, response.getHeaders("Expires").length); Date expires = df.parse(response.getHeaders("Expires")[0].getValue()); // Prepare the second request response.getEntity().consumeContent(); httpClient.getConnectionManager().shutdown(); // Give the cache time to persist the entry Thread.sleep(1000); httpClient = new DefaultHttpClient(); request.setHeader("If-None-Match", eTag); request.setHeader("If-Modified-Since", df.format(System.currentTimeMillis())); response = TestUtils.request(httpClient, request, params); assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatusLine().getStatusCode()); // Get the Expires header assertNotNull(response.getHeaders("Expires")); assertEquals(1, response.getHeaders("Expires").length); // We are explicitly not checking for equality with the previously // received value, since on first request, that value is not yet correct // Get the ETag header assertNotNull(response.getHeaders("ETag")); assertEquals(0, response.getHeaders("ETag").length); // Test the Cache header assertNotNull(response.getHeaders("X-Cache-Key")); assertEquals(1, response.getHeaders("X-Cache-Key").length); // Test the expires header Date newExpires = df.parse(response.getHeaders("Expires")[0].getValue()); assertTrue(expires.before(newExpires) || expires.equals(newExpires)); } finally { httpClient.getConnectionManager().shutdown(); } } /** * Tests if the modification date matches that of the most recent element on a * page rather than the page's modification date. * * @param serverUrl * the server url * @throws Exception * if the test fails */ private void testInheritedModifcation(String serverUrl) throws Exception { logger.info("Preparing test of cache headers influenced by inherited updated content"); DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); df.setTimeZone(TimeZone.getTimeZone("GMT")); // Prepare the request logger.info("Gathering original modification date"); String requestUrl = UrlUtils.concat(serverUrl, hostPage, language.getIdentifier()); logger.info("Sending request to {}", requestUrl); HttpGet request = new HttpGet(requestUrl); request.addHeader("X-Cache-Debug", "yes"); String[][] params = new String[][] { {} }; // Send and the request and examine the response. Keep the modification // date. HttpClient httpClient = new DefaultHttpClient(); try { HttpResponse response = TestUtils.request(httpClient, request, params); int statusCode = response.getStatusLine().getStatusCode(); boolean okOrNotModified = statusCode == HttpServletResponse.SC_OK || statusCode == HttpServletResponse.SC_NOT_MODIFIED; assertTrue(okOrNotModified); // Get the ETag header assertNotNull(response.getHeaders("ETag")); assertEquals(1, response.getHeaders("ETag").length); String hostOrignalETag = response.getHeaders("ETag")[0].getValue(); // Get the Modified header assertNotNull(response.getHeaders("Last-Modified")); assertEquals(1, response.getHeaders("Last-Modified").length); Date hostModified = df.parse(response.getHeaders("Last-Modified")[0].getValue()); response.getEntity().consumeContent(); httpClient.getConnectionManager().shutdown(); logger.info("Updating linked page"); update(serverUrl, linkedPageId); // Give the cache time to persist the entry Thread.sleep(1000); httpClient = new DefaultHttpClient(); // Test using ETag and modified header request.setHeader("If-None-Match", hostOrignalETag); request.setHeader("If-Modified-Since", df.format(hostModified)); response = TestUtils.request(httpClient, request, params); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); // Get the Expires header assertNotNull(response.getHeaders("Expires")); assertEquals(1, response.getHeaders("Expires").length); // We are explicitly not checking for equality with the previously // received value, since on first request, that value is not yet correct // Get the ETag header and make sure it has been updated assertNotNull(response.getHeaders("ETag")); assertEquals(1, response.getHeaders("ETag").length); assertFalse(hostOrignalETag.equals(response.getHeaders("ETag")[0].getValue())); // Test the modified header and make sure it has been updated assertNotNull(response.getHeaders("Last-Modified")); assertEquals(1, response.getHeaders("Last-Modified").length); Date newModified = df.parse(response.getHeaders("Last-Modified")[0].getValue()); assertTrue(hostModified.before(newModified)); } finally { httpClient.getConnectionManager().shutdown(); } } /** * Tests if the modification date of a page can properly be adjusted by a * pagelet that is using the <code><modified></code> tag. * * @param serverUrl * the server url * @throws Exception * if the test fails */ private void testPageletModifcationDate(String serverUrl) throws Exception { logger.info("Preparing test of cache headers influenced by the 'modified' tag"); // Load the page's modification date String requestUrl = UrlUtils.concat(serverUrl, "system/weblounge/pages", modificationTestPageId); HttpGet getPageRequest = new HttpGet(requestUrl); HttpClient httpClient = new DefaultHttpClient(); Page page = null; logger.info("Requesting the page's modification date at {}", requestUrl); try { HttpResponse response = TestUtils.request(httpClient, getPageRequest, null); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); PageReader reader = new PageReader(); page = reader.read(response.getEntity().getContent(), site); } finally { httpClient.getConnectionManager().shutdown(); } DateFormat df = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); df.setTimeZone(TimeZone.getTimeZone("GMT")); // Regularly load the page requestUrl = UrlUtils.concat(serverUrl, modificationTestPage); logger.info("Sending request to {}", requestUrl); HttpGet request = new HttpGet(requestUrl); request.addHeader("X-Cache-Debug", "yes"); String[][] params = new String[][] { {} }; // Send and the request and examine the response. Keep the modification // date. httpClient = new DefaultHttpClient(); try { HttpResponse response = TestUtils.request(httpClient, request, params); int statusCode = response.getStatusLine().getStatusCode(); boolean okOrNotModified = statusCode == HttpServletResponse.SC_OK || statusCode == HttpServletResponse.SC_NOT_MODIFIED; assertTrue(okOrNotModified); // Get the Modified header assertNotNull(response.getHeaders("Last-Modified")); assertEquals(1, response.getHeaders("Last-Modified").length); Date hostModified = df.parse(response.getHeaders("Last-Modified")[0].getValue()); response.getEntity().consumeContent(); // Make sure the page is advertised as being more recent than the page's // modification date assertTrue(hostModified.after(page.getModificationDate())); } finally { httpClient.getConnectionManager().shutdown(); } } /** * Updates the page with the given identifier. * * @param serverUrl * the server url * @param id * the page identifier * @throws Exception * if updating the page fails */ private void update(String serverUrl, String id) throws Exception { String requestUrl = UrlUtils.concat(serverUrl, "system/weblounge/pages"); // Lock the page HttpPut lockPageRequest = new HttpPut(UrlUtils.concat(requestUrl, id, "lock")); HttpClient httpClient = new DefaultHttpClient(); logger.info("Locking the page at {}", requestUrl); try { HttpResponse response = TestUtils.request(httpClient, lockPageRequest, null); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); } finally { httpClient.getConnectionManager().shutdown(); } // Publish it HttpPut publishPageRequest = new HttpPut(UrlUtils.concat(requestUrl, id, "publish")); httpClient = new DefaultHttpClient(); String[][] params = new String[][] { { "modified", "true" } }; logger.info("Publishing the page at {}", requestUrl); try { HttpResponse response = TestUtils.request(httpClient, publishPageRequest, params); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); } finally { httpClient.getConnectionManager().shutdown(); } // Unlock the page HttpDelete unlockRequest = new HttpDelete(UrlUtils.concat(requestUrl, id, "lock")); httpClient = new DefaultHttpClient(); logger.info("Unlocking the page at {}", requestUrl); try { HttpResponse response = TestUtils.request(httpClient, unlockRequest, null); assertEquals(HttpServletResponse.SC_OK, response.getStatusLine().getStatusCode()); } finally { httpClient.getConnectionManager().shutdown(); } } }