/*
* Copyright (c) 2002-2012 Alibaba Group Holding Limited.
* All rights reserved.
*
* Licensed 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 com.alibaba.citrus.springext.support.context;
import static com.alibaba.citrus.test.TestEnvStatic.*;
import static com.alibaba.citrus.test.TestUtil.*;
import static com.alibaba.citrus.util.ArrayUtil.*;
import static com.alibaba.citrus.util.CollectionUtil.*;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Set;
import javax.servlet.ServletContext;
import com.alibaba.citrus.springext.ResourceLoadingExtendable;
import com.alibaba.citrus.test.runner.Prototyped;
import com.alibaba.citrus.test.runner.Prototyped.Prototypes;
import com.alibaba.citrus.test.runner.Prototyped.TestData;
import com.alibaba.citrus.test.runner.Prototyped.TestName;
import com.alibaba.citrus.util.internal.InterfaceImplementorBuilder;
import com.meterware.servletunit.ServletRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.ResourcePatternResolver;
@RunWith(Prototyped.class)
public class ResourceLoadingExtendableTests implements Cloneable {
private ResourceLoadingExtendable context;
private Resource resource1;
private boolean defaultServletResource;
@Prototypes
public static TestData<ResourceLoadingExtendableTests> data() throws Exception {
TestData<ResourceLoadingExtendableTests> data = TestData.getInstance(ResourceLoadingExtendableTests.class);
ResourceLoadingExtendableTests prototype;
// XmlApplicationContext
prototype = data.newPrototype();
prototype.context = new XmlApplicationContext(new FileSystemResource(new File(srcdir, "beans.xml")));
prototype.defaultServletResource = false;
// XmlWebApplicationContext
prototype = data.newPrototype();
XmlWebApplicationContext factory = new XmlWebApplicationContext();
factory.setConfigLocation("beans.xml");
factory.setServletContext(createServletContextWrapper(new ServletRunner(new File(srcdir, "WEB-INF/web.xml"), "")
.newClient().newInvocation("http://localhost/servlet").getServlet().getServletConfig()
.getServletContext()));
factory.refresh();
prototype.context = factory;
prototype.defaultServletResource = true;
return data;
}
@TestName
public String testName() {
return context.getClass().getSimpleName();
}
@Before
public void init() {
resource1 = new UrlResource(getClass().getClassLoader().getResource("java/util/List.class"));
}
@Test
public void noExtender() throws Exception {
// classpath前缀
assertResource("classpath:java/lang/String.class", "jar:", "java/lang/String.class");
// 无classpath前缀
assertResource("java/lang/String.class", contextResourceType(), "java/lang/String.class");
// resource pattern
if (defaultServletResource) {
assertResources("WEB-INF/*", "web.xml", "web_withRedirect.xml"); // 用spring servlet context resolver
} else {
assertResources("WEB-INF/*"); // 用 class resolver,not found
}
}
@Test
public void extender_returnsNull() throws Exception {
MyResourceLoadingExtender loader = new MyResourceLoadingExtender();
context.setResourceLoadingExtender(loader);
// classpath前缀
assertResource("classpath:java/lang/String.class", "jar:", "java/lang/String.class");
// 无classpath前缀
assertResource("java/lang/String.class", contextResourceType(), "java/lang/String.class");
// resource pattern
if (defaultServletResource) {
assertResources("WEB-INF/*", "web.xml", "web_withRedirect.xml"); // 用spring servlet context resolver
} else {
assertResources("WEB-INF/*"); // 用 class resolver,not found
}
}
@Test
public void extender_returnsNotNull() throws Exception {
MyResourceLoadingExtender loader = new MyResourceLoadingExtender();
context.setResourceLoadingExtender(loader);
loader.setResource(resource1);
// classpath前缀:永远返回原来的值
assertResource("classpath:java/lang/String.class", "jar:", "java/lang/String.class");
// 无classpath前缀
assertResource("java/lang/String.class", contextResourceType(), "java/util/List.class");
// resource pattern
ResourcePatternResolver resolver = createMock(ResourcePatternResolver.class);
expect(resolver.getResources("WEB-INF/*")).andReturn(
new Resource[] { new FileSystemResource(new File(srcdir, "beans.xml")) }).anyTimes();
replay(resolver);
loader.setResolver(resolver);
assertResources("WEB-INF/*", "beans.xml");
}
@Test
public void extender_listener() {
AbstractApplicationContext ac = (AbstractApplicationContext) context;
// set loader2
MyResourceLoadingExtender2 loader2 = new MyResourceLoadingExtender2();
context.setResourceLoadingExtender(loader2);
// check listener
assertTrue(new GetApplicationListeners(ac).invoke().contains(loader2));
// listener be notified
ac.refresh();
assertTrue(loader2.contextRefreshed);
}
@Test
public void extender_reset() {
AbstractApplicationContext ac = (AbstractApplicationContext) context;
// set loader
MyResourceLoadingExtender loader = new MyResourceLoadingExtender();
context.setResourceLoadingExtender(loader);
assertFalse(new GetApplicationListeners(ac).invoke().contains(loader));
// set loader2
MyResourceLoadingExtender2 loader2 = new MyResourceLoadingExtender2();
context.setResourceLoadingExtender(loader2);
assertTrue(new GetApplicationListeners(ac).invoke().contains(loader2));
// set loader2
MyResourceLoadingExtender2 loader3 = new MyResourceLoadingExtender2();
context.setResourceLoadingExtender(loader3);
assertFalse(new GetApplicationListeners(ac).invoke().contains(loader2));
assertTrue(new GetApplicationListeners(ac).invoke().contains(loader3));
// listener be notified
ac.refresh();
assertFalse(loader2.contextRefreshed);
assertTrue(loader3.contextRefreshed);
}
private String contextResourceType() {
return defaultServletResource ? "file:" : "jar:";
}
private void assertResource(String resourceName, String... strings) throws Exception {
Resource resource = context.getResource(resourceName);
assertThat(resource.getURL().toString(), containsAll(strings));
}
private void assertResources(String resourceName, String... regexps) throws Exception {
Resource[] resources;
try {
resources = context.getResources(resourceName);
} catch (IOException e) {
resources = new Resource[0];
}
assertEquals(regexps.length, resources.length);
Set<String> regexpSet = createHashSet(regexps);
for (int i = 0; i < resources.length; i++) {
for (int j = 0; j < regexps.length; j++) {
String regexp = regexps[j];
try {
assertThat(resources[i].getURL().toString(), containsRegex(regexp));
regexpSet.remove(regexp);
} catch (AssertionError e) {
}
}
}
assertTrue(regexpSet.isEmpty());
}
/**
* httpunit未实现getResourcePaths方法。
* 以下实现可在servlet 2.5/3.0上执行。
*/
private static ServletContext createServletContextWrapper(final ServletContext servletContext) {
return (ServletContext) new InterfaceImplementorBuilder().addInterface(ServletContext.class).toObject(new Object() {
public Set<String> getResourcePaths(String path) {
try {
URL baseURL = servletContext.getResource(path);
File basedir = null;
if (baseURL != null) {
basedir = new File(baseURL.toURI());
} else {
return null;
}
String[] names = basedir.list();
if (isEmptyArray(names)) {
return null;
}
Set<String> nameSet = createHashSet();
if (!path.endsWith("/")) {
path += "/";
}
for (String name : names) {
File file = new File(basedir, name);
nameSet.add(path + name + (file.isDirectory() ? "/" : ""));
}
return nameSet;
} catch (Exception e) {
return null;
}
}
}, servletContext);
}
}