/*
* JBoss, Home of Professional Open Source
* Copyright 2013, Red Hat, Inc. and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This 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.1 of
* the License, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.richfaces.resource;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import javax.faces.application.Resource;
import javax.faces.context.FacesContext;
import org.jboss.test.faces.AbstractFacesTest;
/**
* @author Nick Belaevski
* @since 4.0
*/
public class CachedResourceImplTest extends AbstractFacesTest {
/**
*
*/
private static final String CACHE_CONTROL = "Cache-Control";
/**
*
*/
private static final String EXPIRES = "Expires";
/**
*
*/
private static final String LAST_MODIFIED = "Last-Modified";
@Override
public void setUp() throws Exception {
super.setUp();
setupFacesRequest();
}
@Override
public void tearDown() throws Exception {
super.tearDown();
}
private CachedResourceImpl createCachedResource() throws IOException {
return createCachedResource(createTestHeaders());
}
private CachedResourceImpl createCachedResource(Map<String, String> headers) throws IOException {
return createCachedResource(headers, null);
}
private CachedResourceImpl createCachedResource(Map<String, String> headers, InputStream stream) throws IOException {
MockHeadersResourceImpl mockResource = new MockHeadersResourceImpl(headers, stream);
CachedResourceImpl cachedResource = new MockCachedResourceImpl();
cachedResource.initialize(mockResource);
return cachedResource;
}
private Map<String, String> createTestHeaders() {
Map<String, String> headers = new HashMap<String, String>();
headers.put("ETag", "W/\"123\"");
headers.put(LAST_MODIFIED, "Tue, 21 Jul 2009 12:45:09 GMT");
headers.put(EXPIRES, "Tue, 28 Jul 2009 12:45:09 GMT");
headers.put(CACHE_CONTROL, "public, max-age=86400");
return headers;
}
private Calendar createBaseDateCalendar() {
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.clear();
calendar.set(2009, Calendar.JULY, 21, 12, 45, 9);
return calendar;
}
public void testInitialize() throws Exception {
CachedResourceImpl cachedResource = createCachedResource();
Calendar calendar = createBaseDateCalendar();
Date baseDate = calendar.getTime();
assertEquals("W/\"123\"", cachedResource.getEntityTag(facesContext));
assertEquals(baseDate, cachedResource.getLastModified(facesContext));
assertEquals(createTestHeaders(), cachedResource.getResponseHeaders());
assertEquals("image/png", cachedResource.getContentType());
Date expired = cachedResource.getExpired(facesContext);
assertNotNull(expired);
assertTrue(expired.after(baseDate));
calendar.add(Calendar.DATE, 1);
assertFalse(calendar.getTime().before(expired));
}
public void testInitializeExpires() throws Exception {
Map<String, String> headers = createTestHeaders();
headers.remove(CACHE_CONTROL);
CachedResourceImpl cachedResource = createCachedResource(headers);
Date expired = cachedResource.getExpired(facesContext);
assertNotNull(expired);
Calendar calendar = createBaseDateCalendar();
assertTrue(expired.after(calendar.getTime()));
calendar.add(Calendar.DATE, 1);
assertFalse(expired.before(calendar.getTime()));
calendar.add(Calendar.DATE, 6);
assertTrue(expired.before(calendar.getTime()));
}
public void testInitializeMaxAge() throws Exception {
Map<String, String> headers = createTestHeaders();
headers.remove(EXPIRES);
CachedResourceImpl cachedResource = createCachedResource(headers);
Date expired = cachedResource.getExpired(facesContext);
assertNotNull(expired);
Calendar calendar = createBaseDateCalendar();
assertTrue(expired.after(calendar.getTime()));
calendar.add(Calendar.DATE, 1);
assertTrue(expired.before(calendar.getTime()));
}
public void testInitializeSMaxAge() throws Exception {
Map<String, String> headers = createTestHeaders();
headers.put(CACHE_CONTROL, "public, max-age=86400, s-maxage=172800");
CachedResourceImpl cachedResource = createCachedResource(headers);
Date expired = cachedResource.getExpired(facesContext);
assertNotNull(expired);
Calendar calendar = createBaseDateCalendar();
assertTrue(expired.after(calendar.getTime()));
calendar.add(Calendar.DATE, 1);
assertFalse(expired.before(calendar.getTime()));
calendar.add(Calendar.DATE, 1);
assertTrue(expired.before(calendar.getTime()));
}
public void testGetStream() throws Exception {
ByteArrayInputStream testStream = new ByteArrayInputStream("test".getBytes("US-ASCII"));
CachedResourceImpl cachedResource = createCachedResource(createTestHeaders(), testStream);
InputStream stream = cachedResource.getInputStream();
assertNotNull(stream);
BufferedReader reader = new BufferedReader(new InputStreamReader(stream, "US-ASCII"));
assertEquals("test", reader.readLine());
assertNull(reader.readLine());
reader.close();
}
public void testGetBigStream() throws Exception {
byte[] bs = new byte[127123];
new Random().nextBytes(bs);
ByteArrayInputStream bigStream = new ByteArrayInputStream(bs);
CachedResourceImpl cachedResource = createCachedResource(createTestHeaders(), bigStream);
InputStream stream = cachedResource.getInputStream();
byte[] testBs = new byte[bs.length];
assertEquals(testBs.length, stream.read(testBs));
assertTrue(Arrays.equals(testBs, bs));
assertEquals(-1, stream.read());
stream.close();
}
public void testCacheable() throws Exception {
CachedResourceImpl cachedResource = createCachedResource();
assertTrue(cachedResource.isCacheable(facesContext));
}
public void testDefaults() throws Exception {
CachedResourceImpl cachedResource = createCachedResource();
try {
cachedResource.getURL();
fail();
} catch (UnsupportedOperationException e) {
// ok
}
try {
cachedResource.getRequestPath();
fail();
} catch (UnsupportedOperationException e) {
// ok
}
}
public void testUserAgentNeedsUpdate() throws Exception {
CachedResourceImpl cachedResource = createCachedResource();
this.connection.addRequestHeaders(Collections.singletonMap("If-Modified-Since", "Tue, 21 Jul 2009 14:45:09 GMT"));
assertFalse(cachedResource.userAgentNeedsUpdate(facesContext));
}
public void testUserAgentNeedsUpdate2() throws Exception {
CachedResourceImpl cachedResource = createCachedResource();
this.connection.addRequestHeaders(Collections.singletonMap("If-Modified-Since", "Tue, 21 Jul 2009 09:45:09 GMT"));
assertTrue(cachedResource.userAgentNeedsUpdate(facesContext));
}
private class MockCachedResourceImpl extends CachedResourceImpl {
private final long currentTime;
public MockCachedResourceImpl() {
super();
this.currentTime = createBaseDateCalendar().getTimeInMillis();
}
@Override
long getCurrentTime() {
return currentTime;
}
}
private class MockHeadersResourceImpl extends Resource {
private Map<String, String> headers;
private InputStream stream;
public MockHeadersResourceImpl(Map<String, String> headers, InputStream stream) {
super();
setResourceName(getClass().getName());
setContentType("image/png");
this.headers = headers;
this.stream = stream != null ? stream : new ByteArrayInputStream(new byte[0]);
}
@Override
public Map<String, String> getResponseHeaders() {
return headers;
}
@Override
public InputStream getInputStream() throws IOException {
return stream;
}
@Override
public String getRequestPath() {
throw new UnsupportedOperationException();
}
@Override
public URL getURL() {
throw new UnsupportedOperationException();
}
@Override
public boolean userAgentNeedsUpdate(FacesContext context) {
throw new UnsupportedOperationException();
}
}
;
}