/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.wicket.request.resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import org.apache.wicket.Application;
import org.apache.wicket.ThreadContext;
import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
import org.apache.wicket.protocol.http.mock.MockHttpServletResponse;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Response;
import org.apache.wicket.request.resource.AbstractResource.ContentRangeType;
import org.apache.wicket.request.resource.IResource.Attributes;
import org.apache.wicket.request.resource.ResourceReference.UrlAttributes;
import org.apache.wicket.response.ByteArrayResponse;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.tester.WicketTestCase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* @author Pedro Santos
*/
public class PackageResourceReferenceTest extends WicketTestCase
{
private static Class<PackageResourceReferenceTest> scope = PackageResourceReferenceTest.class;
private static Locale[] locales = { null, new Locale("en"), new Locale("en", "US") };
private static String[] styles = { null, "style" };
private static String[] variations = { null, "var" };
/**
* @throws Exception
*/
@Before
public void before() throws Exception
{
// some locale outside those in locales array
tester.getSession().setLocale(Locale.CHINA);
}
/**
*
*/
@Test
public void resourceResolution()
{
for (Locale locale : locales)
{
for (String style : styles)
{
for (String variation : variations)
{
ResourceReference reference = new PackageResourceReference(scope,
"resource.txt", locale, style, variation);
UrlAttributes urlAttributes = reference.getUrlAttributes();
assertEquals(locale, urlAttributes.getLocale());
assertEquals(style, urlAttributes.getStyle());
assertEquals(variation, urlAttributes.getVariation());
ByteArrayResponse byteResponse = new ByteArrayResponse();
Attributes mockAttributes = new Attributes(tester.getRequestCycle()
.getRequest(), byteResponse);
reference.getResource().respond(mockAttributes);
String fileContent = new String(byteResponse.getBytes());
if (locale != null)
{
assertTrue(fileContent.contains(locale.getLanguage()));
if (locale.getCountry() != null)
{
assertTrue(fileContent.contains(locale.getCountry()));
}
}
if (style != null)
{
assertTrue(fileContent.contains(style));
}
if (variation != null)
{
assertTrue(fileContent.contains(variation));
}
}
}
}
}
/**
*
*/
@Test
public void resourceResponse()
{
for (Locale locale : locales)
{
for (String style : styles)
{
for (String variation : variations)
{
ResourceReference reference = new PackageResourceReference(scope,
"resource.txt", locale, style, variation);
ByteArrayResponse byteResponse = new ByteArrayResponse();
Attributes mockAttributes = new Attributes(tester.getRequestCycle()
.getRequest(), byteResponse);
reference.getResource().respond(mockAttributes);
String fileContent = new String(byteResponse.getBytes());
if (locale != null)
{
assertTrue(fileContent.contains(locale.getLanguage()));
if (locale.getCountry() != null)
{
assertTrue(fileContent.contains(locale.getCountry()));
}
}
if (style != null)
{
assertTrue(fileContent.contains(style));
}
if (variation != null)
{
assertTrue(fileContent.contains(variation));
}
}
}
}
}
/**
* Asserting if user did not set any locale or style, those from session get used if any
*/
@Test
public void sessionAttributesRelevance()
{
for (Locale locale : new Locale[] { new Locale("en"), new Locale("en", "US") })
{
tester.getSession().setLocale(locale);
for (String style : styles)
{
tester.getSession().setStyle(style);
for (String variation : variations)
{
ResourceReference reference = new PackageResourceReference(scope,
"resource.txt", null, null, variation);
UrlAttributes urlAttributes = reference.getUrlAttributes();
assertEquals(tester.getSession().getLocale(), urlAttributes.getLocale());
assertEquals(tester.getSession().getStyle(), urlAttributes.getStyle());
assertEquals(variation, urlAttributes.getVariation());
}
}
}
}
/**
* Assert preference for specified locale and style over session ones
*/
@Test
public void userAttributesPreference()
{
tester.getSession().setLocale(new Locale("en"));
tester.getSession().setStyle("style");
Locale[] userLocales = { null, new Locale("pt"), new Locale("pt", "BR") };
String userStyle = "style2";
for (Locale userLocale : userLocales)
{
for (String variation : variations)
{
ResourceReference reference = new PackageResourceReference(scope, "resource.txt",
userLocale, userStyle, variation);
UrlAttributes urlAttributes = reference.getUrlAttributes();
assertEquals(userLocale, urlAttributes.getLocale());
assertEquals(userStyle, urlAttributes.getStyle());
assertEquals(variation, urlAttributes.getVariation());
}
}
}
/**
* see WICKET-5251 : Proper detection of already minified resources
*/
@Test
public void testMinifiedNameDetectMinInName()
{
final PackageResourceReference html5minjs = new PackageResourceReference("html5.min.js");
Assert.assertEquals("html5.min.js", html5minjs.getMinifiedName());
final PackageResourceReference html5notminjs = new PackageResourceReference("html5.notmin.js");
Assert.assertEquals("html5.notmin.min.js", html5notminjs.getMinifiedName());
final PackageResourceReference html5notmin = new PackageResourceReference("html5notmin");
Assert.assertEquals("html5notmin.min", html5notmin.getMinifiedName());
final PackageResourceReference html5min = new PackageResourceReference("html5.min");
Assert.assertEquals("html5.min", html5min.getMinifiedName());
}
/**
* see WICKET-5250 - for JavaScriptResourceReference
*/
@Test
public void testJavaScriptResourceReferenceRespectsMinifiedResourcesDetection()
{
Application.get().getResourceSettings().setUseMinifiedResources(true);
final JavaScriptResourceReference notMinified = new JavaScriptResourceReference(PackageResourceReferenceTest.class, "a.js");
final JavaScriptPackageResource notMinifiedResource = notMinified.getResource();
Assert.assertTrue("Not minified resource should got its compress flag set to true", notMinifiedResource.getCompress());
final JavaScriptResourceReference alreadyMinified = new JavaScriptResourceReference(PackageResourceReferenceTest.class, "b.min.js");
final JavaScriptPackageResource alreadyMinifiedResource = alreadyMinified.getResource();
Assert.assertFalse("Already minified resource should got its compress flag set to false", alreadyMinifiedResource.getCompress());
}
/**
* see WICKET-5250 - for CSSResourceReference
*/
@Test
public void testCSSResourceReferenceRespectsMinifiedResourcesDetection()
{
Application.get().getResourceSettings().setUseMinifiedResources(true);
final CssResourceReference notMinified = new CssResourceReference(PackageResourceReferenceTest.class, "a.css");
final CssPackageResource notMinifiedResource = notMinified.getResource();
Assert.assertTrue("Not minified resource should got its compress flag set to true", notMinifiedResource.getCompress());
final CssResourceReference alreadyMinified = new CssResourceReference(PackageResourceReferenceTest.class, "b.min.css");
final CssPackageResource alreadyMinifiedResource = alreadyMinified.getResource();
Assert.assertFalse("Already minified resource should got its compress flag set to false", alreadyMinifiedResource.getCompress());
}
/**
* See WICKET-5819 - Media tags
*/
@Test
public void testContentRange()
{
// Test range
Assert.assertEquals("resource", makeRangeRequest("bytes=0-7"));
Assert.assertEquals("ource", makeRangeRequest("bytes=3-7"));
Assert.assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=0-"));
Assert.assertEquals("var_style_en.txt", makeRangeRequest("bytes=9-"));
Assert.assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=-"));
Assert.assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=-25"));
}
private String makeRangeRequest(String range)
{
ResourceReference reference = new PackageResourceReference(scope, "resource.txt",
locales[1], styles[1], variations[1]);
ByteArrayResponse byteResponse = new ByteArrayResponse();
Request request = tester.getRequestCycle().getRequest();
MockHttpServletRequest mockHttpServletRequest = (MockHttpServletRequest)request.getContainerRequest();
mockHttpServletRequest.setHeader("range", range);
Attributes mockAttributes = new Attributes(request, byteResponse);
reference.getResource().respond(mockAttributes);
return new String(byteResponse.getBytes());
}
/**
* See WICKET-5819 - Media tags
*
* @throws IOException
*/
@Test
public void testContentRangeLarge() throws IOException
{
InputStream resourceAsStream = null;
try
{
resourceAsStream = PackageResourceReference.class.getResourceAsStream("resource_gt_4096.txt");
String content = new String(IOUtils.toByteArray(resourceAsStream));
// Check buffer comprehensive range request
String bytes4094_4105 = makeRangeRequestToBigResource("bytes=4094-4105");
assertEquals(12, bytes4094_4105.length());
assertEquals("River Roller", bytes4094_4105);
// Check buffer exceeding range request
String bytes1000_4999 = makeRangeRequestToBigResource("bytes=1000-4999");
assertEquals(4000, bytes1000_4999.length());
assertEquals(content.substring(1000, 5000), bytes1000_4999);
// Check buffer exceeding range request until end of content
String bytes1000_end = makeRangeRequestToBigResource("bytes=1000-");
assertEquals(4529, bytes1000_end.length());
assertEquals(content.substring(1000, content.length()), bytes1000_end);
// Check complete range request
assertEquals(content.length(), makeRangeRequestToBigResource("bytes=-").length());
}
finally
{
IOUtils.closeQuietly(resourceAsStream);
}
}
private String makeRangeRequestToBigResource(String range)
{
ResourceReference reference = new PackageResourceReference(scope, "resource_gt_4096.txt",
null, null, null);
ByteArrayResponse byteResponse = new ByteArrayResponse();
Request request = tester.getRequestCycle().getRequest();
MockHttpServletRequest mockHttpServletRequest = (MockHttpServletRequest)request.getContainerRequest();
mockHttpServletRequest.setHeader("range", range);
Attributes mockAttributes = new Attributes(request, byteResponse);
reference.getResource().respond(mockAttributes);
return new String(byteResponse.getBytes());
}
/**
* See WICKET-5819 - Media tags
*/
@Test
public void testContentRangeHeaders()
{
// Test header fields
ResourceReference reference = new PackageResourceReference(scope, "resource.txt",
locales[1], styles[1], variations[1]);
Request request = tester.getRequestCycle().getRequest();
Response response = tester.getRequestCycle().getResponse();
MockHttpServletResponse mockHttpServletResponse = (MockHttpServletResponse)response.getContainerResponse();
Attributes mockAttributes = new Attributes(request, response);
reference.getResource().respond(mockAttributes);
Assert.assertEquals(ContentRangeType.BYTES.getTypeName(),
mockHttpServletResponse.getHeader("Accept-Range"));
// For normal: If a resource supports content range no content is delivered
// if no "Range" header is given, but we have to deliver it, because
// other resources then media should get the content. (e.g. CSS, JS, etc.) Browsers
// detecting media requests and automatically add the "Range" header for
// partial content and they don't make an initial request to detect if a media
// resource supports Content-Range (by the Accept-Range header)
Assert.assertEquals("resource_var_style_en.txt",
new String(mockHttpServletResponse.getBinaryContent()));
}
/**
* https://issues.apache.org/jira/browse/WICKET-6031
*/
@Test
public void noRequestCycle()
{
ThreadContext.setRequestCycle(null);
PackageResourceReference reference = new PackageResourceReference(scope, "resource.txt",
locales[1], styles[1], variations[1]);
PackageResource resource = reference.getResource();
assertNotNull(resource);
assertEquals(locales[1], resource.getResourceStream().getLocale());
assertEquals(styles[1], resource.getResourceStream().getStyle());
assertEquals(variations[1], resource.getResourceStream().getVariation());
}
}