53 changed files with 5876 additions and 6 deletions
@ -0,0 +1,182 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.beans.factory.access; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.springframework.beans.factory.BeanFactory; |
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Colin Sampaleanu |
||||||
|
* @author Chris Beams |
||||||
|
*/ |
||||||
|
public class SingletonBeanFactoryLocatorTests { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBasicFunctionality() { |
||||||
|
SingletonBeanFactoryLocator facLoc = new SingletonBeanFactoryLocator( |
||||||
|
"classpath*:" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml")); |
||||||
|
|
||||||
|
basicFunctionalityTest(facLoc); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Worker method so subclass can use it too. |
||||||
|
*/ |
||||||
|
protected void basicFunctionalityTest(SingletonBeanFactoryLocator facLoc) { |
||||||
|
BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort"); |
||||||
|
BeanFactory fac = bfr.getFactory(); |
||||||
|
BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr2.getFactory(); |
||||||
|
// verify that the same instance is returned
|
||||||
|
TestBean tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("beans1.bean1")); |
||||||
|
tb.setName("was beans1.bean1"); |
||||||
|
BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr3.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias"); |
||||||
|
fac = bfr4.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
// Now verify that we can call release in any order.
|
||||||
|
// Unfortunately this doesn't validate complete release after the last one.
|
||||||
|
bfr2.release(); |
||||||
|
bfr3.release(); |
||||||
|
bfr.release(); |
||||||
|
bfr4.release(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This test can run multiple times, but due to static keyed lookup of the locators, |
||||||
|
* 2nd and subsequent calls will actuall get back same locator instance. This is not |
||||||
|
* an issue really, since the contained beanfactories will still be loaded and released. |
||||||
|
*/ |
||||||
|
@Test |
||||||
|
public void testGetInstance() { |
||||||
|
// Try with and without 'classpath*:' prefix, and with 'classpath:' prefix.
|
||||||
|
BeanFactoryLocator facLoc = SingletonBeanFactoryLocator.getInstance( |
||||||
|
ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml")); |
||||||
|
getInstanceTest1(facLoc); |
||||||
|
|
||||||
|
facLoc = SingletonBeanFactoryLocator.getInstance( |
||||||
|
"classpath*:/" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml")); |
||||||
|
getInstanceTest2(facLoc); |
||||||
|
|
||||||
|
// This will actually get another locator instance, as the key is the resource name.
|
||||||
|
facLoc = SingletonBeanFactoryLocator.getInstance( |
||||||
|
"classpath:" + ClassUtils.addResourcePathToPackagePath(getClass(), "ref1.xml")); |
||||||
|
getInstanceTest3(facLoc); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Worker method so subclass can use it too |
||||||
|
*/ |
||||||
|
protected void getInstanceTest1(BeanFactoryLocator facLoc) { |
||||||
|
BeanFactoryReference bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort"); |
||||||
|
BeanFactory fac = bfr.getFactory(); |
||||||
|
BeanFactoryReference bfr2 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr2.getFactory(); |
||||||
|
// verify that the same instance is returned
|
||||||
|
TestBean tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("beans1.bean1")); |
||||||
|
tb.setName("was beans1.bean1"); |
||||||
|
BeanFactoryReference bfr3 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr3.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
|
||||||
|
BeanFactoryReference bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias"); |
||||||
|
fac = bfr4.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
|
||||||
|
bfr.release(); |
||||||
|
bfr3.release(); |
||||||
|
bfr2.release(); |
||||||
|
bfr4.release(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Worker method so subclass can use it too |
||||||
|
*/ |
||||||
|
protected void getInstanceTest2(BeanFactoryLocator facLoc) { |
||||||
|
BeanFactoryReference bfr; |
||||||
|
BeanFactory fac; |
||||||
|
BeanFactoryReference bfr2; |
||||||
|
TestBean tb; |
||||||
|
BeanFactoryReference bfr3; |
||||||
|
BeanFactoryReference bfr4; |
||||||
|
bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort"); |
||||||
|
fac = bfr.getFactory(); |
||||||
|
bfr2 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr2.getFactory(); |
||||||
|
// verify that the same instance is returned
|
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("beans1.bean1")); |
||||||
|
tb.setName("was beans1.bean1"); |
||||||
|
bfr3 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr3.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias"); |
||||||
|
fac = bfr4.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
bfr.release(); |
||||||
|
bfr2.release(); |
||||||
|
bfr4.release(); |
||||||
|
bfr3.release(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Worker method so subclass can use it too |
||||||
|
*/ |
||||||
|
protected void getInstanceTest3(BeanFactoryLocator facLoc) { |
||||||
|
BeanFactoryReference bfr; |
||||||
|
BeanFactory fac; |
||||||
|
BeanFactoryReference bfr2; |
||||||
|
TestBean tb; |
||||||
|
BeanFactoryReference bfr3; |
||||||
|
BeanFactoryReference bfr4; |
||||||
|
bfr = facLoc.useBeanFactory("a.qualified.name.of.some.sort"); |
||||||
|
fac = bfr.getFactory(); |
||||||
|
bfr2 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr2.getFactory(); |
||||||
|
// verify that the same instance is returned
|
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("beans1.bean1")); |
||||||
|
tb.setName("was beans1.bean1"); |
||||||
|
bfr3 = facLoc.useBeanFactory("another.qualified.name"); |
||||||
|
fac = bfr3.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
bfr4 = facLoc.useBeanFactory("a.qualified.name.which.is.an.alias"); |
||||||
|
fac = bfr4.getFactory(); |
||||||
|
tb = (TestBean) fac.getBean("beans1.bean1"); |
||||||
|
assertTrue(tb.getName().equals("was beans1.bean1")); |
||||||
|
bfr4.release(); |
||||||
|
bfr3.release(); |
||||||
|
bfr2.release(); |
||||||
|
bfr.release(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,75 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2005 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.beans.factory.access; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Scrap bean for use in tests. |
||||||
|
* |
||||||
|
* @author Colin Sampaleanu |
||||||
|
*/ |
||||||
|
public class TestBean { |
||||||
|
|
||||||
|
private String name; |
||||||
|
|
||||||
|
private List list; |
||||||
|
|
||||||
|
private Object objRef; |
||||||
|
|
||||||
|
/** |
||||||
|
* @return Returns the name. |
||||||
|
*/ |
||||||
|
public String getName() { |
||||||
|
return name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param name The name to set. |
||||||
|
*/ |
||||||
|
public void setName(String name) { |
||||||
|
this.name = name; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return Returns the list. |
||||||
|
*/ |
||||||
|
public List getList() { |
||||||
|
return list; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param list The list to set. |
||||||
|
*/ |
||||||
|
public void setList(List list) { |
||||||
|
this.list = list; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @return Returns the object. |
||||||
|
*/ |
||||||
|
public Object getObjRef() { |
||||||
|
return objRef; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param object The object to set. |
||||||
|
*/ |
||||||
|
public void setObjRef(Object object) { |
||||||
|
this.objRef = object; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- $Id: beans1.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ --> |
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> |
||||||
|
|
||||||
|
<beans> |
||||||
|
|
||||||
|
<bean id="beans1.bean1" class="org.springframework.beans.factory.access.TestBean"> |
||||||
|
<property name="name"><value>beans1.bean1</value></property> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean id="beans1.bean2" class="org.springframework.beans.factory.access.TestBean"> |
||||||
|
<property name="name"><value>bean2</value></property> |
||||||
|
<property name="objRef"><ref bean="beans1.bean2"/></property> |
||||||
|
</bean> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -0,0 +1,16 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- $Id: beans2.xml,v 1.3 2006/08/20 19:08:40 jhoeller Exp $ --> |
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> |
||||||
|
|
||||||
|
<beans> |
||||||
|
|
||||||
|
<bean id="beans2.bean1" class="org.springframework.beans.factory.access.TestBean"> |
||||||
|
<property name="name"><value>beans2.bean1</value></property> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<bean id="beans2.bean2" class="org.springframework.beans.factory.access.TestBean"> |
||||||
|
<property name="name"><value>beans2.bean2</value></property> |
||||||
|
<property name="objRef"><ref bean="beans1.bean1"/></property> |
||||||
|
</bean> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd"> |
||||||
|
|
||||||
|
<!-- We are only using one definition file for the purposes of this test, since we do not have multiple |
||||||
|
classloaders available in the environment to allow combining multiple files of the same name, but |
||||||
|
of course the contents within could be spread out across multiple files of the same name withing |
||||||
|
different jars --> |
||||||
|
|
||||||
|
<beans> |
||||||
|
|
||||||
|
<!-- this definition could be inside one beanRefFactory.xml file --> |
||||||
|
<bean id="a.qualified.name.of.some.sort" |
||||||
|
class="org.springframework.beans.factory.xml.XmlBeanFactory"> |
||||||
|
<constructor-arg value="org/springframework/beans/factory/access/beans1.xml"/> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<!-- while the following two could be inside another, also on the classpath, |
||||||
|
perhaps coming from another component jar --> |
||||||
|
|
||||||
|
<bean id="another.qualified.name" |
||||||
|
class="org.springframework.beans.factory.xml.XmlBeanFactory"> |
||||||
|
<constructor-arg value="org/springframework/beans/factory/access/beans1.xml"/> |
||||||
|
<constructor-arg ref="a.qualified.name.of.some.sort"/> <!-- parent bean factory --> |
||||||
|
</bean> |
||||||
|
|
||||||
|
<alias name="another.qualified.name" alias="a.qualified.name.which.is.an.alias"/> |
||||||
|
|
||||||
|
</beans> |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
import javax.naming.NamingException; |
||||||
|
|
||||||
|
import org.springframework.core.CollectionFactory; |
||||||
|
import org.springframework.jndi.JndiTemplate; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple extension of the JndiTemplate class that always returns |
||||||
|
* a given object. Very useful for testing. Effectively a mock object. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
public class ExpectedLookupTemplate extends JndiTemplate { |
||||||
|
|
||||||
|
private final Map<String, Object> jndiObjects = new ConcurrentHashMap<String, Object>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new JndiTemplate that will always return given objects |
||||||
|
* for given names. To be populated through <code>addObject</code> calls. |
||||||
|
* @see #addObject(String, Object) |
||||||
|
*/ |
||||||
|
public ExpectedLookupTemplate() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new JndiTemplate that will always return the |
||||||
|
* given object, but honour only requests for the given name. |
||||||
|
* @param name the name the client is expected to look up |
||||||
|
* @param object the object that will be returned |
||||||
|
*/ |
||||||
|
public ExpectedLookupTemplate(String name, Object object) { |
||||||
|
addObject(name, object); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add the given object to the list of JNDI objects that this |
||||||
|
* template will expose. |
||||||
|
* @param name the name the client is expected to look up |
||||||
|
* @param object the object that will be returned |
||||||
|
*/ |
||||||
|
public void addObject(String name, Object object) { |
||||||
|
this.jndiObjects.put(name, object); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* If the name is the expected name specified in the constructor, |
||||||
|
* return the object provided in the constructor. If the name is |
||||||
|
* unexpected, a respective NamingException gets thrown. |
||||||
|
*/ |
||||||
|
public Object lookup(String name) throws NamingException { |
||||||
|
Object object = this.jndiObjects.get(name); |
||||||
|
if (object == null) { |
||||||
|
throw new NamingException("Unexpected JNDI name '" + name + "': expecting " + this.jndiObjects.keySet()); |
||||||
|
} |
||||||
|
return object; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,345 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Hashtable; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
import javax.naming.Binding; |
||||||
|
import javax.naming.Context; |
||||||
|
import javax.naming.Name; |
||||||
|
import javax.naming.NameClassPair; |
||||||
|
import javax.naming.NameNotFoundException; |
||||||
|
import javax.naming.NameParser; |
||||||
|
import javax.naming.NamingEnumeration; |
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.naming.OperationNotSupportedException; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple implementation of a JNDI naming context. |
||||||
|
* Only supports binding plain Objects to String names. |
||||||
|
* Mainly for test environments, but also usable for standalone applications. |
||||||
|
* |
||||||
|
* <p>This class is not intended for direct usage by applications, although it |
||||||
|
* can be used for example to override JndiTemplate's <code>createInitialContext</code> |
||||||
|
* method in unit tests. Typically, SimpleNamingContextBuilder will be used to |
||||||
|
* set up a JVM-level JNDI environment. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder |
||||||
|
* @see org.springframework.jndi.JndiTemplate#createInitialContext |
||||||
|
*/ |
||||||
|
public class SimpleNamingContext implements Context { |
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final String root; |
||||||
|
|
||||||
|
private final Hashtable<String, Object> boundObjects; |
||||||
|
|
||||||
|
private final Hashtable<String, Object> environment = new Hashtable<String, Object>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext() { |
||||||
|
this(""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context with the given naming root. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext(String root) { |
||||||
|
this.root = root; |
||||||
|
this.boundObjects = new Hashtable<String, Object>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context with the given naming root, |
||||||
|
* the given name/object map, and the JNDI environment entries. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext(String root, Hashtable<String, Object> boundObjects, Hashtable<String, Object> env) { |
||||||
|
this.root = root; |
||||||
|
this.boundObjects = boundObjects; |
||||||
|
if (env != null) { |
||||||
|
this.environment.putAll(env); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Actual implementations of Context methods follow
|
||||||
|
|
||||||
|
public NamingEnumeration<NameClassPair> list(String root) throws NamingException { |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Listing name/class pairs under [" + root + "]"); |
||||||
|
} |
||||||
|
return new NameClassPairEnumeration(this, root); |
||||||
|
} |
||||||
|
|
||||||
|
public NamingEnumeration<Binding> listBindings(String root) throws NamingException { |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Listing bindings under [" + root + "]"); |
||||||
|
} |
||||||
|
return new BindingEnumeration(this, root); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Look up the object with the given name. |
||||||
|
* <p>Note: Not intended for direct use by applications. |
||||||
|
* Will be used by any standard InitialContext JNDI lookups. |
||||||
|
* @throws javax.naming.NameNotFoundException if the object could not be found |
||||||
|
*/ |
||||||
|
public Object lookup(String lookupName) throws NameNotFoundException { |
||||||
|
String name = this.root + lookupName; |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Static JNDI lookup: [" + name + "]"); |
||||||
|
} |
||||||
|
if ("".equals(name)) { |
||||||
|
return new SimpleNamingContext(this.root, this.boundObjects, this.environment); |
||||||
|
} |
||||||
|
Object found = this.boundObjects.get(name); |
||||||
|
if (found == null) { |
||||||
|
if (!name.endsWith("/")) { |
||||||
|
name = name + "/"; |
||||||
|
} |
||||||
|
for (String boundName : this.boundObjects.keySet()) { |
||||||
|
if (boundName.startsWith(name)) { |
||||||
|
return new SimpleNamingContext(name, this.boundObjects, this.environment); |
||||||
|
} |
||||||
|
} |
||||||
|
throw new NameNotFoundException( |
||||||
|
"Name [" + this.root + lookupName + "] not bound; " + this.boundObjects.size() + " bindings: [" + |
||||||
|
StringUtils.collectionToDelimitedString(this.boundObjects.keySet(), ",") + "]"); |
||||||
|
} |
||||||
|
return found; |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookupLink(String name) throws NameNotFoundException { |
||||||
|
return lookup(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Bind the given object to the given name. |
||||||
|
* Note: Not intended for direct use by applications |
||||||
|
* if setting up a JVM-level JNDI environment. |
||||||
|
* Use SimpleNamingContextBuilder to set up JNDI bindings then. |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder#bind |
||||||
|
*/ |
||||||
|
public void bind(String name, Object obj) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI binding: [" + this.root + name + "] = [" + obj + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.put(this.root + name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public void unbind(String name) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI remove: [" + this.root + name + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.remove(this.root + name); |
||||||
|
} |
||||||
|
|
||||||
|
public void rebind(String name, Object obj) { |
||||||
|
bind(name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public void rename(String oldName, String newName) throws NameNotFoundException { |
||||||
|
Object obj = lookup(oldName); |
||||||
|
unbind(oldName); |
||||||
|
bind(newName, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public Context createSubcontext(String name) { |
||||||
|
String subcontextName = this.root + name; |
||||||
|
if (!subcontextName.endsWith("/")) { |
||||||
|
subcontextName += "/"; |
||||||
|
} |
||||||
|
Context subcontext = new SimpleNamingContext(subcontextName, this.boundObjects, this.environment); |
||||||
|
bind(name, subcontext); |
||||||
|
return subcontext; |
||||||
|
} |
||||||
|
|
||||||
|
public void destroySubcontext(String name) { |
||||||
|
unbind(name); |
||||||
|
} |
||||||
|
|
||||||
|
public String composeName(String name, String prefix) { |
||||||
|
return prefix + name; |
||||||
|
} |
||||||
|
|
||||||
|
public Hashtable<String, Object> getEnvironment() { |
||||||
|
return this.environment; |
||||||
|
} |
||||||
|
|
||||||
|
public Object addToEnvironment(String propName, Object propVal) { |
||||||
|
return this.environment.put(propName, propVal); |
||||||
|
} |
||||||
|
|
||||||
|
public Object removeFromEnvironment(String propName) { |
||||||
|
return this.environment.remove(propName); |
||||||
|
} |
||||||
|
|
||||||
|
public void close() { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Unsupported methods follow: no support for javax.naming.Name
|
||||||
|
|
||||||
|
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookup(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookupLink(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void bind(Name name, Object obj) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void unbind(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void rebind(Name name, Object obj) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void rename(Name oldName, Name newName) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Context createSubcontext(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void destroySubcontext(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public String getNameInNamespace() throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NameParser getNameParser(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NameParser getNameParser(String name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Name composeName(Name name, Name prefix) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static abstract class AbstractNamingEnumeration<T> implements NamingEnumeration<T> { |
||||||
|
|
||||||
|
private Iterator<T> iterator; |
||||||
|
|
||||||
|
private AbstractNamingEnumeration(SimpleNamingContext context, String proot) throws NamingException { |
||||||
|
if (!"".equals(proot) && !proot.endsWith("/")) { |
||||||
|
proot = proot + "/"; |
||||||
|
} |
||||||
|
String root = context.root + proot; |
||||||
|
Map<String, T> contents = new HashMap<String, T>(); |
||||||
|
for (String boundName : context.boundObjects.keySet()) { |
||||||
|
if (boundName.startsWith(root)) { |
||||||
|
int startIndex = root.length(); |
||||||
|
int endIndex = boundName.indexOf('/', startIndex); |
||||||
|
String strippedName = |
||||||
|
(endIndex != -1 ? boundName.substring(startIndex, endIndex) : boundName.substring(startIndex)); |
||||||
|
if (!contents.containsKey(strippedName)) { |
||||||
|
try { |
||||||
|
contents.put(strippedName, createObject(strippedName, context.lookup(proot + strippedName))); |
||||||
|
} |
||||||
|
catch (NameNotFoundException ex) { |
||||||
|
// cannot happen
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (contents.size() == 0) { |
||||||
|
throw new NamingException("Invalid root: [" + context.root + proot + "]"); |
||||||
|
} |
||||||
|
this.iterator = contents.values().iterator(); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract T createObject(String strippedName, Object obj); |
||||||
|
|
||||||
|
public boolean hasMore() { |
||||||
|
return this.iterator.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
public T next() { |
||||||
|
return this.iterator.next(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean hasMoreElements() { |
||||||
|
return this.iterator.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
public T nextElement() { |
||||||
|
return this.iterator.next(); |
||||||
|
} |
||||||
|
|
||||||
|
public void close() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class NameClassPairEnumeration extends AbstractNamingEnumeration<NameClassPair> { |
||||||
|
|
||||||
|
private NameClassPairEnumeration(SimpleNamingContext context, String root) throws NamingException { |
||||||
|
super(context, root); |
||||||
|
} |
||||||
|
|
||||||
|
protected NameClassPair createObject(String strippedName, Object obj) { |
||||||
|
return new NameClassPair(strippedName, obj.getClass().getName()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class BindingEnumeration extends AbstractNamingEnumeration<Binding> { |
||||||
|
|
||||||
|
private BindingEnumeration(SimpleNamingContext context, String root) throws NamingException { |
||||||
|
super(context, root); |
||||||
|
} |
||||||
|
|
||||||
|
protected Binding createObject(String strippedName, Object obj) { |
||||||
|
return new Binding(strippedName, obj); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,234 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.Hashtable; |
||||||
|
|
||||||
|
import javax.naming.Context; |
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.naming.spi.InitialContextFactory; |
||||||
|
import javax.naming.spi.InitialContextFactoryBuilder; |
||||||
|
import javax.naming.spi.NamingManager; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple implementation of a JNDI naming context builder. |
||||||
|
* |
||||||
|
* <p>Mainly targeted at test environments, where each test case can |
||||||
|
* configure JNDI appropriately, so that <code>new InitialContext()</code> |
||||||
|
* will expose the required objects. Also usable for standalone applications, |
||||||
|
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be |
||||||
|
* able to use traditional J2EE data access code outside of a J2EE container. |
||||||
|
* |
||||||
|
* <p>There are various choices for DataSource implementations: |
||||||
|
* <ul> |
||||||
|
* <li>SingleConnectionDataSource (using the same Connection for all getConnection calls); |
||||||
|
* <li>DriverManagerDataSource (creating a new Connection on each getConnection call); |
||||||
|
* <li>Apache's Jakarta Commons DBCP offers BasicDataSource (a real pool). |
||||||
|
* </ul> |
||||||
|
* |
||||||
|
* <p>Typical usage in bootstrap code: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); |
||||||
|
* DataSource ds = new DriverManagerDataSource(...); |
||||||
|
* builder.bind("java:comp/env/jdbc/myds", ds); |
||||||
|
* builder.activate();</pre> |
||||||
|
* |
||||||
|
* Note that it's impossible to activate multiple builders within the same JVM, |
||||||
|
* due to JNDI restrictions. Thus to configure a fresh builder repeatedly, use |
||||||
|
* the following code to get a reference to either an already activated builder |
||||||
|
* or a newly activated one: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder(); |
||||||
|
* DataSource ds = new DriverManagerDataSource(...); |
||||||
|
* builder.bind("java:comp/env/jdbc/myds", ds);</pre> |
||||||
|
* |
||||||
|
* Note that you <i>should not</i> call <code>activate()</code> on a builder from |
||||||
|
* this factory method, as there will already be an activated one in any case. |
||||||
|
* |
||||||
|
* <p>An instance of this class is only necessary at setup time. |
||||||
|
* An application does not need to keep a reference to it after activation. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @author Rod Johnson |
||||||
|
* @see #emptyActivatedContextBuilder() |
||||||
|
* @see #bind(String, Object) |
||||||
|
* @see #activate() |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContext |
||||||
|
* @see org.springframework.jdbc.datasource.SingleConnectionDataSource |
||||||
|
* @see org.springframework.jdbc.datasource.DriverManagerDataSource |
||||||
|
* @see org.apache.commons.dbcp.BasicDataSource |
||||||
|
*/ |
||||||
|
public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder { |
||||||
|
|
||||||
|
/** An instance of this class bound to JNDI */ |
||||||
|
private static volatile SimpleNamingContextBuilder activated; |
||||||
|
|
||||||
|
private static boolean initialized = false; |
||||||
|
|
||||||
|
private static final Object initializationLock = new Object(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if a SimpleNamingContextBuilder is active. |
||||||
|
* @return the current SimpleNamingContextBuilder instance, |
||||||
|
* or <code>null</code> if none |
||||||
|
*/ |
||||||
|
public static SimpleNamingContextBuilder getCurrentContextBuilder() { |
||||||
|
return activated; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* If no SimpleNamingContextBuilder is already configuring JNDI, |
||||||
|
* create and activate one. Otherwise take the existing activate |
||||||
|
* SimpleNamingContextBuilder, clear it and return it. |
||||||
|
* <p>This is mainly intended for test suites that want to |
||||||
|
* reinitialize JNDI bindings from scratch repeatedly. |
||||||
|
* @return an empty SimpleNamingContextBuilder that can be used |
||||||
|
* to control JNDI bindings |
||||||
|
*/ |
||||||
|
public static SimpleNamingContextBuilder emptyActivatedContextBuilder() throws NamingException { |
||||||
|
if (activated != null) { |
||||||
|
// Clear already activated context builder.
|
||||||
|
activated.clear(); |
||||||
|
} |
||||||
|
else { |
||||||
|
// Create and activate new context builder.
|
||||||
|
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); |
||||||
|
// The activate() call will cause an assigment to the activated variable.
|
||||||
|
builder.activate(); |
||||||
|
} |
||||||
|
return activated; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final Hashtable boundObjects = new Hashtable(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Register the context builder by registering it with the JNDI NamingManager. |
||||||
|
* Note that once this has been done, <code>new InitialContext()</code> will always |
||||||
|
* return a context from this factory. Use the <code>emptyActivatedContextBuilder()</code> |
||||||
|
* static method to get an empty context (for example, in test methods). |
||||||
|
* @throws IllegalStateException if there's already a naming context builder |
||||||
|
* registered with the JNDI NamingManager |
||||||
|
*/ |
||||||
|
public void activate() throws IllegalStateException, NamingException { |
||||||
|
logger.info("Activating simple JNDI environment"); |
||||||
|
synchronized (initializationLock) { |
||||||
|
if (!initialized) { |
||||||
|
if (NamingManager.hasInitialContextFactoryBuilder()) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " + |
||||||
|
"Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " + |
||||||
|
"with no reset option. As a consequence, a JNDI provider must only be registered once per JVM."); |
||||||
|
} |
||||||
|
NamingManager.setInitialContextFactoryBuilder(this); |
||||||
|
initialized = true; |
||||||
|
} |
||||||
|
} |
||||||
|
activated = this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Temporarily deactivate this context builder. It will remain registered with |
||||||
|
* the JNDI NamingManager but will delegate to the standard JNDI InitialContextFactory |
||||||
|
* (if configured) instead of exposing its own bound objects. |
||||||
|
* <p>Call <code>activate()</code> again in order to expose this contexz builder's own |
||||||
|
* bound objects again. Such activate/deactivate sequences can be applied any number |
||||||
|
* of times (e.g. within a larger integration test suite running in the same VM). |
||||||
|
* @see #activate() |
||||||
|
*/ |
||||||
|
public void deactivate() { |
||||||
|
logger.info("Deactivating simple JNDI environment"); |
||||||
|
activated = null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clear all bindings in this context builder, while keeping it active. |
||||||
|
*/ |
||||||
|
public void clear() { |
||||||
|
this.boundObjects.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Bind the given object under the given name, for all naming contexts |
||||||
|
* that this context builder will generate. |
||||||
|
* @param name the JNDI name of the object (e.g. "java:comp/env/jdbc/myds") |
||||||
|
* @param obj the object to bind (e.g. a DataSource implementation) |
||||||
|
*/ |
||||||
|
public void bind(String name, Object obj) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI binding: [" + name + "] = [" + obj + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.put(name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Simple InitialContextFactoryBuilder implementation, |
||||||
|
* creating a new SimpleNamingContext instance. |
||||||
|
* @see SimpleNamingContext |
||||||
|
*/ |
||||||
|
public InitialContextFactory createInitialContextFactory(Hashtable environment) { |
||||||
|
if (activated == null && environment != null) { |
||||||
|
Object icf = environment.get(Context.INITIAL_CONTEXT_FACTORY); |
||||||
|
if (icf != null) { |
||||||
|
Class icfClass = null; |
||||||
|
if (icf instanceof Class) { |
||||||
|
icfClass = (Class) icf; |
||||||
|
} |
||||||
|
else if (icf instanceof String) { |
||||||
|
icfClass = ClassUtils.resolveClassName((String) icf, getClass().getClassLoader()); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new IllegalArgumentException("Invalid value type for environment key [" + |
||||||
|
Context.INITIAL_CONTEXT_FACTORY + "]: " + icf.getClass().getName()); |
||||||
|
} |
||||||
|
if (!InitialContextFactory.class.isAssignableFrom(icfClass)) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Specified class does not implement [" + InitialContextFactory.class.getName() + "]: " + icf); |
||||||
|
} |
||||||
|
try { |
||||||
|
return (InitialContextFactory) icfClass.newInstance(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
IllegalStateException ise = |
||||||
|
new IllegalStateException("Cannot instantiate specified InitialContextFactory: " + icf); |
||||||
|
ise.initCause(ex); |
||||||
|
throw ise; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Default case...
|
||||||
|
return new InitialContextFactory() { |
||||||
|
public Context getInitialContext(Hashtable environment) { |
||||||
|
return new SimpleNamingContext("", boundObjects, environment); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
<html> |
||||||
|
<body> |
||||||
|
|
||||||
|
The simplest implementation of the JNDI SPI that could possibly work. |
||||||
|
|
||||||
|
<p>Useful for setting up a simple JNDI environment for test suites |
||||||
|
or standalone applications. If e.g. JDBC DataSources get bound to the |
||||||
|
same JNDI names as within a J2EE container, both application code and |
||||||
|
configuration can me reused without changes. |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
||||||
@ -0,0 +1,35 @@ |
|||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
package example.aspects; |
||||||
|
|
||||||
|
import org.aspectj.lang.annotation.Around; |
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
import org.aspectj.lang.annotation.Before; |
||||||
|
import org.springframework.core.Ordered; |
||||||
|
|
||||||
|
@Aspect("pertarget(execution(* *.getSpouse()))") |
||||||
|
public class PerTargetAspect implements Ordered { |
||||||
|
|
||||||
|
public int count; |
||||||
|
|
||||||
|
private int order = Ordered.LOWEST_PRECEDENCE; |
||||||
|
|
||||||
|
@Around("execution(int *.getAge())") |
||||||
|
public int returnCountAsAge() { |
||||||
|
return count++; |
||||||
|
} |
||||||
|
|
||||||
|
@Before("execution(void *.set*(int))") |
||||||
|
public void countSetter() { |
||||||
|
++count; |
||||||
|
} |
||||||
|
|
||||||
|
public int getOrder() { |
||||||
|
return this.order; |
||||||
|
} |
||||||
|
|
||||||
|
public void setOrder(int order) { |
||||||
|
this.order = order; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2005 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.aspects; |
||||||
|
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||||
|
import org.aspectj.lang.annotation.Around; |
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
|
||||||
|
@Aspect("perthis(execution(* getAge()))") |
||||||
|
public class PerThisAspect { |
||||||
|
|
||||||
|
private int invocations = 0; |
||||||
|
|
||||||
|
public int getInvocations() { |
||||||
|
return this.invocations; |
||||||
|
} |
||||||
|
|
||||||
|
@Around("execution(* getAge())") |
||||||
|
public int changeAge(ProceedingJoinPoint pjp) throws Throwable { |
||||||
|
return invocations++; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,24 @@ |
|||||||
|
/** |
||||||
|
* |
||||||
|
*/ |
||||||
|
package example.aspects; |
||||||
|
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint; |
||||||
|
import org.aspectj.lang.annotation.Around; |
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
import org.aspectj.lang.annotation.Before; |
||||||
|
|
||||||
|
@Aspect |
||||||
|
public class TwoAdviceAspect { |
||||||
|
private int totalCalls; |
||||||
|
|
||||||
|
@Around("execution(* getAge())") |
||||||
|
public int returnCallCount(ProceedingJoinPoint pjp) throws Exception { |
||||||
|
return totalCalls; |
||||||
|
} |
||||||
|
|
||||||
|
@Before("execution(* setAge(int)) && args(newAge)") |
||||||
|
public void countSet(int newAge) throws Exception { |
||||||
|
++totalCalls; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import javax.annotation.PostConstruct; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
public class AutowiredQualifierFooService implements FooService { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
@Qualifier("testing") |
||||||
|
private FooDao fooDao; |
||||||
|
|
||||||
|
private boolean initCalled = false; |
||||||
|
|
||||||
|
@PostConstruct |
||||||
|
private void init() { |
||||||
|
if (this.initCalled) { |
||||||
|
throw new IllegalStateException("Init already called"); |
||||||
|
} |
||||||
|
this.initCalled = true; |
||||||
|
} |
||||||
|
|
||||||
|
public String foo(int id) { |
||||||
|
return this.fooDao.findFoo(id); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isInitCalled() { |
||||||
|
return this.initCalled; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import java.lang.annotation.ElementType; |
||||||
|
import java.lang.annotation.Inherited; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
import java.lang.annotation.Target; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
@Target(ElementType.TYPE) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Inherited |
||||||
|
public @interface CustomComponent { |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import java.lang.annotation.ElementType; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
import java.lang.annotation.Target; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
@Target(ElementType.TYPE) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
@Component |
||||||
|
public @interface CustomStereotype { |
||||||
|
|
||||||
|
String value() default "thoreau"; |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
@CustomStereotype |
||||||
|
public class DefaultNamedComponent { |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
public interface FooDao { |
||||||
|
|
||||||
|
String findFoo(int id); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
public interface FooService { |
||||||
|
|
||||||
|
String foo(int id); |
||||||
|
|
||||||
|
boolean isInitCalled(); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,80 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import javax.annotation.PostConstruct; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.BeanFactory; |
||||||
|
import org.springframework.beans.factory.ListableBeanFactory; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.context.ApplicationContext; |
||||||
|
import org.springframework.context.ApplicationEventPublisher; |
||||||
|
import org.springframework.context.ConfigurableApplicationContext; |
||||||
|
import org.springframework.context.MessageSource; |
||||||
|
import org.springframework.context.support.AbstractApplicationContext; |
||||||
|
import org.springframework.core.io.ResourceLoader; |
||||||
|
import org.springframework.core.io.support.ResourcePatternResolver; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class FooServiceImpl implements FooService { |
||||||
|
|
||||||
|
@Autowired private FooDao fooDao; |
||||||
|
|
||||||
|
@Autowired public BeanFactory beanFactory; |
||||||
|
|
||||||
|
@Autowired public List<ListableBeanFactory> listableBeanFactory; |
||||||
|
|
||||||
|
@Autowired public ResourceLoader resourceLoader; |
||||||
|
|
||||||
|
@Autowired public ResourcePatternResolver resourcePatternResolver; |
||||||
|
|
||||||
|
@Autowired public ApplicationEventPublisher eventPublisher; |
||||||
|
|
||||||
|
@Autowired public MessageSource messageSource; |
||||||
|
|
||||||
|
@Autowired public ApplicationContext context; |
||||||
|
|
||||||
|
@Autowired public ConfigurableApplicationContext[] configurableContext; |
||||||
|
|
||||||
|
@Autowired public AbstractApplicationContext genericContext; |
||||||
|
|
||||||
|
private boolean initCalled = false; |
||||||
|
|
||||||
|
@PostConstruct |
||||||
|
private void init() { |
||||||
|
if (this.initCalled) { |
||||||
|
throw new IllegalStateException("Init already called"); |
||||||
|
} |
||||||
|
this.initCalled = true; |
||||||
|
} |
||||||
|
|
||||||
|
public String foo(int id) { |
||||||
|
return this.fooDao.findFoo(id); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isInitCalled() { |
||||||
|
return this.initCalled; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
@CustomComponent |
||||||
|
public class MessageBean { |
||||||
|
|
||||||
|
private String message; |
||||||
|
|
||||||
|
public MessageBean() { |
||||||
|
this.message = "DEFAULT MESSAGE"; |
||||||
|
} |
||||||
|
|
||||||
|
public MessageBean(String message) { |
||||||
|
this.message = message; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMessage() { |
||||||
|
return this.message; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
@Component("myNamedComponent") |
||||||
|
public class NamedComponent { |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Repository; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
@Repository("myNamedDao") |
||||||
|
public class NamedStubDao { |
||||||
|
|
||||||
|
public String find(int id) { |
||||||
|
return "bar"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import org.springframework.context.annotation.Scope; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
@Scope("myScope") |
||||||
|
public class ScopedProxyTestBean implements FooService { |
||||||
|
|
||||||
|
public String foo(int id) { |
||||||
|
return "bar"; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isInitCalled() { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import org.aspectj.lang.annotation.Aspect; |
||||||
|
import org.aspectj.lang.annotation.Before; |
||||||
|
import org.aspectj.lang.annotation.Pointcut; |
||||||
|
|
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
@Component |
||||||
|
@Aspect |
||||||
|
public class ServiceInvocationCounter { |
||||||
|
|
||||||
|
private int useCount; |
||||||
|
|
||||||
|
@Pointcut("execution(* example.scannable.FooService+.*(..))") |
||||||
|
public void serviceExecution() {} |
||||||
|
|
||||||
|
@Before("serviceExecution()") |
||||||
|
public void countUse() { |
||||||
|
this.useCount++; |
||||||
|
} |
||||||
|
|
||||||
|
public int getCount() { |
||||||
|
return this.useCount; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 example.scannable; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier; |
||||||
|
import org.springframework.stereotype.Repository; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Mark Fisher |
||||||
|
*/ |
||||||
|
@Repository |
||||||
|
@Qualifier("testing") |
||||||
|
public class StubFooDao implements FooDao { |
||||||
|
|
||||||
|
public String findFoo(int id) { |
||||||
|
return "bar"; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,849 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.Reader; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.security.Principal; |
||||||
|
import java.util.Collection; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Date; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.Hashtable; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.Vector; |
||||||
|
|
||||||
|
import javax.servlet.RequestDispatcher; |
||||||
|
import javax.servlet.ServletContext; |
||||||
|
import javax.servlet.ServletInputStream; |
||||||
|
import javax.servlet.http.Cookie; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpSession; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.servlet.http.HttpServletRequest} |
||||||
|
* interface. Supports the Servlet 2.4 API level. |
||||||
|
* |
||||||
|
* <p>Used for testing the web framework; also useful for testing |
||||||
|
* application controllers. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Rick Evans |
||||||
|
* @author Mark Fisher |
||||||
|
* @since 1.0.2 |
||||||
|
*/ |
||||||
|
public class MockHttpServletRequest implements HttpServletRequest { |
||||||
|
|
||||||
|
/** |
||||||
|
* The default protocol: 'http'. |
||||||
|
*/ |
||||||
|
public static final String DEFAULT_PROTOCOL = "http"; |
||||||
|
|
||||||
|
/** |
||||||
|
* The default server address: '127.0.0.1'. |
||||||
|
*/ |
||||||
|
public static final String DEFAULT_SERVER_ADDR = "127.0.0.1"; |
||||||
|
|
||||||
|
/** |
||||||
|
* The default server name: 'localhost'. |
||||||
|
*/ |
||||||
|
public static final String DEFAULT_SERVER_NAME = "localhost"; |
||||||
|
|
||||||
|
/** |
||||||
|
* The default server port: '80'. |
||||||
|
*/ |
||||||
|
public static final int DEFAULT_SERVER_PORT = 80; |
||||||
|
|
||||||
|
/** |
||||||
|
* The default remote address: '127.0.0.1'. |
||||||
|
*/ |
||||||
|
public static final String DEFAULT_REMOTE_ADDR = "127.0.0.1"; |
||||||
|
|
||||||
|
/** |
||||||
|
* The default remote host: 'localhost'. |
||||||
|
*/ |
||||||
|
public static final String DEFAULT_REMOTE_HOST = "localhost"; |
||||||
|
|
||||||
|
|
||||||
|
private boolean active = true; |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// ServletRequest properties
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
private final Hashtable attributes = new Hashtable(); |
||||||
|
|
||||||
|
private String characterEncoding; |
||||||
|
|
||||||
|
private byte[] content; |
||||||
|
|
||||||
|
private String contentType; |
||||||
|
|
||||||
|
private final Map<String, String[]> parameters = new LinkedHashMap<String, String[]>(16); |
||||||
|
|
||||||
|
private String protocol = DEFAULT_PROTOCOL; |
||||||
|
|
||||||
|
private String scheme = DEFAULT_PROTOCOL; |
||||||
|
|
||||||
|
private String serverName = DEFAULT_SERVER_NAME; |
||||||
|
|
||||||
|
private int serverPort = DEFAULT_SERVER_PORT; |
||||||
|
|
||||||
|
private String remoteAddr = DEFAULT_REMOTE_ADDR; |
||||||
|
|
||||||
|
private String remoteHost = DEFAULT_REMOTE_HOST; |
||||||
|
|
||||||
|
/** List of locales in descending order */ |
||||||
|
private final Vector locales = new Vector(); |
||||||
|
|
||||||
|
private boolean secure = false; |
||||||
|
|
||||||
|
private final ServletContext servletContext; |
||||||
|
|
||||||
|
private int remotePort = DEFAULT_SERVER_PORT; |
||||||
|
|
||||||
|
private String localName = DEFAULT_SERVER_NAME; |
||||||
|
|
||||||
|
private String localAddr = DEFAULT_SERVER_ADDR; |
||||||
|
|
||||||
|
private int localPort = DEFAULT_SERVER_PORT; |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// HttpServletRequest properties
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
private String authType; |
||||||
|
|
||||||
|
private Cookie[] cookies; |
||||||
|
|
||||||
|
/** |
||||||
|
* The key is the lowercase header name; the value is a {@link HeaderValueHolder} object. |
||||||
|
*/ |
||||||
|
private final Hashtable headers = new Hashtable(); |
||||||
|
|
||||||
|
private String method; |
||||||
|
|
||||||
|
private String pathInfo; |
||||||
|
|
||||||
|
private String contextPath = ""; |
||||||
|
|
||||||
|
private String queryString; |
||||||
|
|
||||||
|
private String remoteUser; |
||||||
|
|
||||||
|
private final Set userRoles = new HashSet(); |
||||||
|
|
||||||
|
private Principal userPrincipal; |
||||||
|
|
||||||
|
private String requestURI; |
||||||
|
|
||||||
|
private String servletPath = ""; |
||||||
|
|
||||||
|
private HttpSession session; |
||||||
|
|
||||||
|
private boolean requestedSessionIdValid = true; |
||||||
|
|
||||||
|
private boolean requestedSessionIdFromCookie = true; |
||||||
|
|
||||||
|
private boolean requestedSessionIdFromURL = false; |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Constructors
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockHttpServletRequest with a default |
||||||
|
* {@link MockServletContext}. |
||||||
|
* @see MockServletContext |
||||||
|
*/ |
||||||
|
public MockHttpServletRequest() { |
||||||
|
this(null, "", ""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockHttpServletRequest with a default |
||||||
|
* {@link MockServletContext}. |
||||||
|
* @param method the request method (may be <code>null</code>) |
||||||
|
* @param requestURI the request URI (may be <code>null</code>) |
||||||
|
* @see #setMethod |
||||||
|
* @see #setRequestURI |
||||||
|
* @see MockServletContext |
||||||
|
*/ |
||||||
|
public MockHttpServletRequest(String method, String requestURI) { |
||||||
|
this(null, method, requestURI); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockHttpServletRequest. |
||||||
|
* @param servletContext the ServletContext that the request runs in |
||||||
|
* (may be <code>null</code> to use a default MockServletContext) |
||||||
|
* @see MockServletContext |
||||||
|
*/ |
||||||
|
public MockHttpServletRequest(ServletContext servletContext) { |
||||||
|
this(servletContext, "", ""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockHttpServletRequest. |
||||||
|
* @param servletContext the ServletContext that the request runs in |
||||||
|
* (may be <code>null</code> to use a default MockServletContext) |
||||||
|
* @param method the request method (may be <code>null</code>) |
||||||
|
* @param requestURI the request URI (may be <code>null</code>) |
||||||
|
* @see #setMethod |
||||||
|
* @see #setRequestURI |
||||||
|
* @see MockServletContext |
||||||
|
*/ |
||||||
|
public MockHttpServletRequest(ServletContext servletContext, String method, String requestURI) { |
||||||
|
this.servletContext = (servletContext != null ? servletContext : new MockServletContext()); |
||||||
|
this.method = method; |
||||||
|
this.requestURI = requestURI; |
||||||
|
this.locales.add(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Lifecycle methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return the ServletContext that this request is associated with. |
||||||
|
* (Not available in the standard HttpServletRequest interface for some reason.) |
||||||
|
*/ |
||||||
|
public ServletContext getServletContext() { |
||||||
|
return this.servletContext; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return whether this request is still active (that is, not completed yet). |
||||||
|
*/ |
||||||
|
public boolean isActive() { |
||||||
|
return this.active; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Mark this request as completed, keeping its state. |
||||||
|
*/ |
||||||
|
public void close() { |
||||||
|
this.active = false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Invalidate this request, clearing its state. |
||||||
|
*/ |
||||||
|
public void invalidate() { |
||||||
|
close(); |
||||||
|
clearAttributes(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check whether this request is still active (that is, not completed yet), |
||||||
|
* throwing an IllegalStateException if not active anymore. |
||||||
|
*/ |
||||||
|
protected void checkActive() throws IllegalStateException { |
||||||
|
if (!this.active) { |
||||||
|
throw new IllegalStateException("Request is not active anymore"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// ServletRequest interface
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public Object getAttribute(String name) { |
||||||
|
checkActive(); |
||||||
|
return this.attributes.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getAttributeNames() { |
||||||
|
checkActive(); |
||||||
|
return this.attributes.keys(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getCharacterEncoding() { |
||||||
|
return this.characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCharacterEncoding(String characterEncoding) { |
||||||
|
this.characterEncoding = characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public void setContent(byte[] content) { |
||||||
|
this.content = content; |
||||||
|
} |
||||||
|
|
||||||
|
public int getContentLength() { |
||||||
|
return (this.content != null ? this.content.length : -1); |
||||||
|
} |
||||||
|
|
||||||
|
public void setContentType(String contentType) { |
||||||
|
this.contentType = contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public String getContentType() { |
||||||
|
return this.contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public ServletInputStream getInputStream() { |
||||||
|
if (this.content != null) { |
||||||
|
return new DelegatingServletInputStream(new ByteArrayInputStream(this.content)); |
||||||
|
} |
||||||
|
else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a single value for the specified HTTP parameter. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* parameter name, they will be replaced. |
||||||
|
*/ |
||||||
|
public void setParameter(String name, String value) { |
||||||
|
setParameter(name, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set an array of values for the specified HTTP parameter. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* parameter name, they will be replaced. |
||||||
|
*/ |
||||||
|
public void setParameter(String name, String[] values) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
this.parameters.put(name, values); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets all provided parameters <emphasis>replacing</emphasis> any |
||||||
|
* existing values for the provided parameter names. To add without |
||||||
|
* replacing existing values, use {@link #addParameters(java.util.Map)}. |
||||||
|
*/ |
||||||
|
public void setParameters(Map params) { |
||||||
|
Assert.notNull(params, "Parameter map must not be null"); |
||||||
|
for (Object key : params.keySet()) { |
||||||
|
Assert.isInstanceOf(String.class, key, |
||||||
|
"Parameter map key must be of type [" + String.class.getName() + "]"); |
||||||
|
Object value = params.get(key); |
||||||
|
if (value instanceof String) { |
||||||
|
this.setParameter((String) key, (String) value); |
||||||
|
} |
||||||
|
else if (value instanceof String[]) { |
||||||
|
this.setParameter((String) key, (String[]) value); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Parameter map value must be single value " + " or array of type [" + String.class.getName() + |
||||||
|
"]"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a single value for the specified HTTP parameter. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* parameter name, the given value will be added to the end of the list. |
||||||
|
*/ |
||||||
|
public void addParameter(String name, String value) { |
||||||
|
addParameter(name, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add an array of values for the specified HTTP parameter. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* parameter name, the given values will be added to the end of the list. |
||||||
|
*/ |
||||||
|
public void addParameter(String name, String[] values) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
String[] oldArr = this.parameters.get(name); |
||||||
|
if (oldArr != null) { |
||||||
|
String[] newArr = new String[oldArr.length + values.length]; |
||||||
|
System.arraycopy(oldArr, 0, newArr, 0, oldArr.length); |
||||||
|
System.arraycopy(values, 0, newArr, oldArr.length, values.length); |
||||||
|
this.parameters.put(name, newArr); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.parameters.put(name, values); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Adds all provided parameters <emphasis>without</emphasis> replacing |
||||||
|
* any existing values. To replace existing values, use |
||||||
|
* {@link #setParameters(java.util.Map)}. |
||||||
|
*/ |
||||||
|
public void addParameters(Map params) { |
||||||
|
Assert.notNull(params, "Parameter map must not be null"); |
||||||
|
for (Object key : params.keySet()) { |
||||||
|
Assert.isInstanceOf(String.class, key, |
||||||
|
"Parameter map key must be of type [" + String.class.getName() + "]"); |
||||||
|
Object value = params.get(key); |
||||||
|
if (value instanceof String) { |
||||||
|
this.addParameter((String) key, (String) value); |
||||||
|
} |
||||||
|
else if (value instanceof String[]) { |
||||||
|
this.addParameter((String) key, (String[]) value); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new IllegalArgumentException("Parameter map value must be single value " + |
||||||
|
" or array of type [" + String.class.getName() + "]"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove already registered values for the specified HTTP parameter, if any. |
||||||
|
*/ |
||||||
|
public void removeParameter(String name) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
this.parameters.remove(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Removes all existing parameters. |
||||||
|
*/ |
||||||
|
public void removeAllParameters() { |
||||||
|
this.parameters.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getParameter(String name) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
String[] arr = this.parameters.get(name); |
||||||
|
return (arr != null && arr.length > 0 ? arr[0] : null); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getParameterNames() { |
||||||
|
return Collections.enumeration(this.parameters.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getParameterValues(String name) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
return this.parameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Map getParameterMap() { |
||||||
|
return Collections.unmodifiableMap(this.parameters); |
||||||
|
} |
||||||
|
|
||||||
|
public void setProtocol(String protocol) { |
||||||
|
this.protocol = protocol; |
||||||
|
} |
||||||
|
|
||||||
|
public String getProtocol() { |
||||||
|
return this.protocol; |
||||||
|
} |
||||||
|
|
||||||
|
public void setScheme(String scheme) { |
||||||
|
this.scheme = scheme; |
||||||
|
} |
||||||
|
|
||||||
|
public String getScheme() { |
||||||
|
return this.scheme; |
||||||
|
} |
||||||
|
|
||||||
|
public void setServerName(String serverName) { |
||||||
|
this.serverName = serverName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getServerName() { |
||||||
|
return this.serverName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setServerPort(int serverPort) { |
||||||
|
this.serverPort = serverPort; |
||||||
|
} |
||||||
|
|
||||||
|
public int getServerPort() { |
||||||
|
return this.serverPort; |
||||||
|
} |
||||||
|
|
||||||
|
public BufferedReader getReader() throws UnsupportedEncodingException { |
||||||
|
if (this.content != null) { |
||||||
|
InputStream sourceStream = new ByteArrayInputStream(this.content); |
||||||
|
Reader sourceReader = (this.characterEncoding != null) ? |
||||||
|
new InputStreamReader(sourceStream, this.characterEncoding) : new InputStreamReader(sourceStream); |
||||||
|
return new BufferedReader(sourceReader); |
||||||
|
} |
||||||
|
else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setRemoteAddr(String remoteAddr) { |
||||||
|
this.remoteAddr = remoteAddr; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRemoteAddr() { |
||||||
|
return this.remoteAddr; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRemoteHost(String remoteHost) { |
||||||
|
this.remoteHost = remoteHost; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRemoteHost() { |
||||||
|
return this.remoteHost; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(String name, Object value) { |
||||||
|
checkActive(); |
||||||
|
Assert.notNull(name, "Attribute name must not be null"); |
||||||
|
if (value != null) { |
||||||
|
this.attributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void removeAttribute(String name) { |
||||||
|
checkActive(); |
||||||
|
Assert.notNull(name, "Attribute name must not be null"); |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clear all of this request's attributes. |
||||||
|
*/ |
||||||
|
public void clearAttributes() { |
||||||
|
this.attributes.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a new preferred locale, before any existing locales. |
||||||
|
*/ |
||||||
|
public void addPreferredLocale(Locale locale) { |
||||||
|
Assert.notNull(locale, "Locale must not be null"); |
||||||
|
this.locales.add(0, locale); |
||||||
|
} |
||||||
|
|
||||||
|
public Locale getLocale() { |
||||||
|
return (Locale) this.locales.get(0); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getLocales() { |
||||||
|
return this.locales.elements(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSecure(boolean secure) { |
||||||
|
this.secure = secure; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSecure() { |
||||||
|
return this.secure; |
||||||
|
} |
||||||
|
|
||||||
|
public RequestDispatcher getRequestDispatcher(String path) { |
||||||
|
return new MockRequestDispatcher(path); |
||||||
|
} |
||||||
|
|
||||||
|
public String getRealPath(String path) { |
||||||
|
return this.servletContext.getRealPath(path); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRemotePort(int remotePort) { |
||||||
|
this.remotePort = remotePort; |
||||||
|
} |
||||||
|
|
||||||
|
public int getRemotePort() { |
||||||
|
return this.remotePort; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLocalName(String localName) { |
||||||
|
this.localName = localName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getLocalName() { |
||||||
|
return this.localName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLocalAddr(String localAddr) { |
||||||
|
this.localAddr = localAddr; |
||||||
|
} |
||||||
|
|
||||||
|
public String getLocalAddr() { |
||||||
|
return this.localAddr; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLocalPort(int localPort) { |
||||||
|
this.localPort = localPort; |
||||||
|
} |
||||||
|
|
||||||
|
public int getLocalPort() { |
||||||
|
return this.localPort; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// HttpServletRequest interface
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void setAuthType(String authType) { |
||||||
|
this.authType = authType; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAuthType() { |
||||||
|
return this.authType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCookies(Cookie[] cookies) { |
||||||
|
this.cookies = cookies; |
||||||
|
} |
||||||
|
|
||||||
|
public Cookie[] getCookies() { |
||||||
|
return this.cookies; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a header entry for the given name. |
||||||
|
* <p>If there was no entry for that header name before, |
||||||
|
* the value will be used as-is. In case of an existing entry, |
||||||
|
* a String array will be created, adding the given value (more |
||||||
|
* specifically, its toString representation) as further element. |
||||||
|
* <p>Multiple values can only be stored as list of Strings, |
||||||
|
* following the Servlet spec (see <code>getHeaders</code> accessor). |
||||||
|
* As alternative to repeated <code>addHeader</code> calls for |
||||||
|
* individual elements, you can use a single call with an entire |
||||||
|
* array or Collection of values as parameter. |
||||||
|
* @see #getHeaderNames |
||||||
|
* @see #getHeader |
||||||
|
* @see #getHeaders |
||||||
|
* @see #getDateHeader |
||||||
|
* @see #getIntHeader |
||||||
|
*/ |
||||||
|
public void addHeader(String name, Object value) { |
||||||
|
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); |
||||||
|
Assert.notNull(value, "Header value must not be null"); |
||||||
|
if (header == null) { |
||||||
|
header = new HeaderValueHolder(); |
||||||
|
this.headers.put(name, header); |
||||||
|
} |
||||||
|
if (value instanceof Collection) { |
||||||
|
header.addValues((Collection) value); |
||||||
|
} |
||||||
|
else if (value.getClass().isArray()) { |
||||||
|
header.addValueArray(value); |
||||||
|
} |
||||||
|
else { |
||||||
|
header.addValue(value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public long getDateHeader(String name) { |
||||||
|
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); |
||||||
|
Object value = (header != null ? header.getValue() : null); |
||||||
|
if (value instanceof Date) { |
||||||
|
return ((Date) value).getTime(); |
||||||
|
} |
||||||
|
else if (value instanceof Number) { |
||||||
|
return ((Number) value).longValue(); |
||||||
|
} |
||||||
|
else if (value != null) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Value for header '" + name + "' is neither a Date nor a Number: " + value); |
||||||
|
} |
||||||
|
else { |
||||||
|
return -1L; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getHeader(String name) { |
||||||
|
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); |
||||||
|
return (header != null ? header.getValue().toString() : null); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getHeaders(String name) { |
||||||
|
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); |
||||||
|
return Collections.enumeration(header != null ? header.getValues() : Collections.EMPTY_LIST); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration getHeaderNames() { |
||||||
|
return this.headers.keys(); |
||||||
|
} |
||||||
|
|
||||||
|
public int getIntHeader(String name) { |
||||||
|
HeaderValueHolder header = HeaderValueHolder.getByName(this.headers, name); |
||||||
|
Object value = (header != null ? header.getValue() : null); |
||||||
|
if (value instanceof Number) { |
||||||
|
return ((Number) value).intValue(); |
||||||
|
} |
||||||
|
else if (value instanceof String) { |
||||||
|
return Integer.parseInt((String) value); |
||||||
|
} |
||||||
|
else if (value != null) { |
||||||
|
throw new NumberFormatException("Value for header '" + name + "' is not a Number: " + value); |
||||||
|
} |
||||||
|
else { |
||||||
|
return -1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setMethod(String method) { |
||||||
|
this.method = method; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMethod() { |
||||||
|
return this.method; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPathInfo(String pathInfo) { |
||||||
|
this.pathInfo = pathInfo; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPathInfo() { |
||||||
|
return this.pathInfo; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPathTranslated() { |
||||||
|
return (this.pathInfo != null ? getRealPath(this.pathInfo) : null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setContextPath(String contextPath) { |
||||||
|
this.contextPath = contextPath; |
||||||
|
} |
||||||
|
|
||||||
|
public String getContextPath() { |
||||||
|
return this.contextPath; |
||||||
|
} |
||||||
|
|
||||||
|
public void setQueryString(String queryString) { |
||||||
|
this.queryString = queryString; |
||||||
|
} |
||||||
|
|
||||||
|
public String getQueryString() { |
||||||
|
return this.queryString; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRemoteUser(String remoteUser) { |
||||||
|
this.remoteUser = remoteUser; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRemoteUser() { |
||||||
|
return this.remoteUser; |
||||||
|
} |
||||||
|
|
||||||
|
public void addUserRole(String role) { |
||||||
|
this.userRoles.add(role); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isUserInRole(String role) { |
||||||
|
return this.userRoles.contains(role); |
||||||
|
} |
||||||
|
|
||||||
|
public void setUserPrincipal(Principal userPrincipal) { |
||||||
|
this.userPrincipal = userPrincipal; |
||||||
|
} |
||||||
|
|
||||||
|
public Principal getUserPrincipal() { |
||||||
|
return this.userPrincipal; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRequestedSessionId() { |
||||||
|
HttpSession session = getSession(); |
||||||
|
return (session != null ? session.getId() : null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRequestURI(String requestURI) { |
||||||
|
this.requestURI = requestURI; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRequestURI() { |
||||||
|
return this.requestURI; |
||||||
|
} |
||||||
|
|
||||||
|
public StringBuffer getRequestURL() { |
||||||
|
StringBuffer url = new StringBuffer(this.scheme); |
||||||
|
url.append("://").append(this.serverName).append(':').append(this.serverPort); |
||||||
|
url.append(getRequestURI()); |
||||||
|
return url; |
||||||
|
} |
||||||
|
|
||||||
|
public void setServletPath(String servletPath) { |
||||||
|
this.servletPath = servletPath; |
||||||
|
} |
||||||
|
|
||||||
|
public String getServletPath() { |
||||||
|
return this.servletPath; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSession(HttpSession session) { |
||||||
|
this.session = session; |
||||||
|
if (session instanceof MockHttpSession) { |
||||||
|
MockHttpSession mockSession = ((MockHttpSession) session); |
||||||
|
mockSession.access(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public HttpSession getSession(boolean create) { |
||||||
|
checkActive(); |
||||||
|
// Reset session if invalidated.
|
||||||
|
if (this.session instanceof MockHttpSession && ((MockHttpSession) this.session).isInvalid()) { |
||||||
|
this.session = null; |
||||||
|
} |
||||||
|
// Create new session if necessary.
|
||||||
|
if (this.session == null && create) { |
||||||
|
this.session = new MockHttpSession(this.servletContext); |
||||||
|
} |
||||||
|
return this.session; |
||||||
|
} |
||||||
|
|
||||||
|
public HttpSession getSession() { |
||||||
|
return getSession(true); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRequestedSessionIdValid(boolean requestedSessionIdValid) { |
||||||
|
this.requestedSessionIdValid = requestedSessionIdValid; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRequestedSessionIdValid() { |
||||||
|
return this.requestedSessionIdValid; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRequestedSessionIdFromCookie(boolean requestedSessionIdFromCookie) { |
||||||
|
this.requestedSessionIdFromCookie = requestedSessionIdFromCookie; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRequestedSessionIdFromCookie() { |
||||||
|
return this.requestedSessionIdFromCookie; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRequestedSessionIdFromURL(boolean requestedSessionIdFromURL) { |
||||||
|
this.requestedSessionIdFromURL = requestedSessionIdFromURL; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRequestedSessionIdFromURL() { |
||||||
|
return this.requestedSessionIdFromURL; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRequestedSessionIdFromUrl() { |
||||||
|
return isRequestedSessionIdFromURL(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,82 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
import javax.naming.NamingException; |
||||||
|
|
||||||
|
import org.springframework.core.CollectionFactory; |
||||||
|
import org.springframework.jndi.JndiTemplate; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple extension of the JndiTemplate class that always returns |
||||||
|
* a given object. Very useful for testing. Effectively a mock object. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
*/ |
||||||
|
public class ExpectedLookupTemplate extends JndiTemplate { |
||||||
|
|
||||||
|
private final Map<String, Object> jndiObjects = new ConcurrentHashMap<String, Object>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new JndiTemplate that will always return given objects |
||||||
|
* for given names. To be populated through <code>addObject</code> calls. |
||||||
|
* @see #addObject(String, Object) |
||||||
|
*/ |
||||||
|
public ExpectedLookupTemplate() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new JndiTemplate that will always return the |
||||||
|
* given object, but honour only requests for the given name. |
||||||
|
* @param name the name the client is expected to look up |
||||||
|
* @param object the object that will be returned |
||||||
|
*/ |
||||||
|
public ExpectedLookupTemplate(String name, Object object) { |
||||||
|
addObject(name, object); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add the given object to the list of JNDI objects that this |
||||||
|
* template will expose. |
||||||
|
* @param name the name the client is expected to look up |
||||||
|
* @param object the object that will be returned |
||||||
|
*/ |
||||||
|
public void addObject(String name, Object object) { |
||||||
|
this.jndiObjects.put(name, object); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* If the name is the expected name specified in the constructor, |
||||||
|
* return the object provided in the constructor. If the name is |
||||||
|
* unexpected, a respective NamingException gets thrown. |
||||||
|
*/ |
||||||
|
public Object lookup(String name) throws NamingException { |
||||||
|
Object object = this.jndiObjects.get(name); |
||||||
|
if (object == null) { |
||||||
|
throw new NamingException("Unexpected JNDI name '" + name + "': expecting " + this.jndiObjects.keySet()); |
||||||
|
} |
||||||
|
return object; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,345 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Hashtable; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.Map; |
||||||
|
import javax.naming.Binding; |
||||||
|
import javax.naming.Context; |
||||||
|
import javax.naming.Name; |
||||||
|
import javax.naming.NameClassPair; |
||||||
|
import javax.naming.NameNotFoundException; |
||||||
|
import javax.naming.NameParser; |
||||||
|
import javax.naming.NamingEnumeration; |
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.naming.OperationNotSupportedException; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple implementation of a JNDI naming context. |
||||||
|
* Only supports binding plain Objects to String names. |
||||||
|
* Mainly for test environments, but also usable for standalone applications. |
||||||
|
* |
||||||
|
* <p>This class is not intended for direct usage by applications, although it |
||||||
|
* can be used for example to override JndiTemplate's <code>createInitialContext</code> |
||||||
|
* method in unit tests. Typically, SimpleNamingContextBuilder will be used to |
||||||
|
* set up a JVM-level JNDI environment. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder |
||||||
|
* @see org.springframework.jndi.JndiTemplate#createInitialContext |
||||||
|
*/ |
||||||
|
public class SimpleNamingContext implements Context { |
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final String root; |
||||||
|
|
||||||
|
private final Hashtable<String, Object> boundObjects; |
||||||
|
|
||||||
|
private final Hashtable<String, Object> environment = new Hashtable<String, Object>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext() { |
||||||
|
this(""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context with the given naming root. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext(String root) { |
||||||
|
this.root = root; |
||||||
|
this.boundObjects = new Hashtable<String, Object>(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new naming context with the given naming root, |
||||||
|
* the given name/object map, and the JNDI environment entries. |
||||||
|
*/ |
||||||
|
public SimpleNamingContext(String root, Hashtable<String, Object> boundObjects, Hashtable<String, Object> env) { |
||||||
|
this.root = root; |
||||||
|
this.boundObjects = boundObjects; |
||||||
|
if (env != null) { |
||||||
|
this.environment.putAll(env); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Actual implementations of Context methods follow
|
||||||
|
|
||||||
|
public NamingEnumeration<NameClassPair> list(String root) throws NamingException { |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Listing name/class pairs under [" + root + "]"); |
||||||
|
} |
||||||
|
return new NameClassPairEnumeration(this, root); |
||||||
|
} |
||||||
|
|
||||||
|
public NamingEnumeration<Binding> listBindings(String root) throws NamingException { |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Listing bindings under [" + root + "]"); |
||||||
|
} |
||||||
|
return new BindingEnumeration(this, root); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Look up the object with the given name. |
||||||
|
* <p>Note: Not intended for direct use by applications. |
||||||
|
* Will be used by any standard InitialContext JNDI lookups. |
||||||
|
* @throws javax.naming.NameNotFoundException if the object could not be found |
||||||
|
*/ |
||||||
|
public Object lookup(String lookupName) throws NameNotFoundException { |
||||||
|
String name = this.root + lookupName; |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Static JNDI lookup: [" + name + "]"); |
||||||
|
} |
||||||
|
if ("".equals(name)) { |
||||||
|
return new SimpleNamingContext(this.root, this.boundObjects, this.environment); |
||||||
|
} |
||||||
|
Object found = this.boundObjects.get(name); |
||||||
|
if (found == null) { |
||||||
|
if (!name.endsWith("/")) { |
||||||
|
name = name + "/"; |
||||||
|
} |
||||||
|
for (String boundName : this.boundObjects.keySet()) { |
||||||
|
if (boundName.startsWith(name)) { |
||||||
|
return new SimpleNamingContext(name, this.boundObjects, this.environment); |
||||||
|
} |
||||||
|
} |
||||||
|
throw new NameNotFoundException( |
||||||
|
"Name [" + this.root + lookupName + "] not bound; " + this.boundObjects.size() + " bindings: [" + |
||||||
|
StringUtils.collectionToDelimitedString(this.boundObjects.keySet(), ",") + "]"); |
||||||
|
} |
||||||
|
return found; |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookupLink(String name) throws NameNotFoundException { |
||||||
|
return lookup(name); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Bind the given object to the given name. |
||||||
|
* Note: Not intended for direct use by applications |
||||||
|
* if setting up a JVM-level JNDI environment. |
||||||
|
* Use SimpleNamingContextBuilder to set up JNDI bindings then. |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContextBuilder#bind |
||||||
|
*/ |
||||||
|
public void bind(String name, Object obj) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI binding: [" + this.root + name + "] = [" + obj + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.put(this.root + name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public void unbind(String name) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI remove: [" + this.root + name + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.remove(this.root + name); |
||||||
|
} |
||||||
|
|
||||||
|
public void rebind(String name, Object obj) { |
||||||
|
bind(name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public void rename(String oldName, String newName) throws NameNotFoundException { |
||||||
|
Object obj = lookup(oldName); |
||||||
|
unbind(oldName); |
||||||
|
bind(newName, obj); |
||||||
|
} |
||||||
|
|
||||||
|
public Context createSubcontext(String name) { |
||||||
|
String subcontextName = this.root + name; |
||||||
|
if (!subcontextName.endsWith("/")) { |
||||||
|
subcontextName += "/"; |
||||||
|
} |
||||||
|
Context subcontext = new SimpleNamingContext(subcontextName, this.boundObjects, this.environment); |
||||||
|
bind(name, subcontext); |
||||||
|
return subcontext; |
||||||
|
} |
||||||
|
|
||||||
|
public void destroySubcontext(String name) { |
||||||
|
unbind(name); |
||||||
|
} |
||||||
|
|
||||||
|
public String composeName(String name, String prefix) { |
||||||
|
return prefix + name; |
||||||
|
} |
||||||
|
|
||||||
|
public Hashtable<String, Object> getEnvironment() { |
||||||
|
return this.environment; |
||||||
|
} |
||||||
|
|
||||||
|
public Object addToEnvironment(String propName, Object propVal) { |
||||||
|
return this.environment.put(propName, propVal); |
||||||
|
} |
||||||
|
|
||||||
|
public Object removeFromEnvironment(String propName) { |
||||||
|
return this.environment.remove(propName); |
||||||
|
} |
||||||
|
|
||||||
|
public void close() { |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Unsupported methods follow: no support for javax.naming.Name
|
||||||
|
|
||||||
|
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookup(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Object lookupLink(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void bind(Name name, Object obj) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void unbind(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void rebind(Name name, Object obj) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void rename(Name oldName, Name newName) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Context createSubcontext(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public void destroySubcontext(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public String getNameInNamespace() throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NameParser getNameParser(Name name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public NameParser getNameParser(String name) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
public Name composeName(Name name, Name prefix) throws NamingException { |
||||||
|
throw new OperationNotSupportedException("SimpleNamingContext does not support [javax.naming.Name]"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static abstract class AbstractNamingEnumeration<T> implements NamingEnumeration<T> { |
||||||
|
|
||||||
|
private Iterator<T> iterator; |
||||||
|
|
||||||
|
private AbstractNamingEnumeration(SimpleNamingContext context, String proot) throws NamingException { |
||||||
|
if (!"".equals(proot) && !proot.endsWith("/")) { |
||||||
|
proot = proot + "/"; |
||||||
|
} |
||||||
|
String root = context.root + proot; |
||||||
|
Map<String, T> contents = new HashMap<String, T>(); |
||||||
|
for (String boundName : context.boundObjects.keySet()) { |
||||||
|
if (boundName.startsWith(root)) { |
||||||
|
int startIndex = root.length(); |
||||||
|
int endIndex = boundName.indexOf('/', startIndex); |
||||||
|
String strippedName = |
||||||
|
(endIndex != -1 ? boundName.substring(startIndex, endIndex) : boundName.substring(startIndex)); |
||||||
|
if (!contents.containsKey(strippedName)) { |
||||||
|
try { |
||||||
|
contents.put(strippedName, createObject(strippedName, context.lookup(proot + strippedName))); |
||||||
|
} |
||||||
|
catch (NameNotFoundException ex) { |
||||||
|
// cannot happen
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (contents.size() == 0) { |
||||||
|
throw new NamingException("Invalid root: [" + context.root + proot + "]"); |
||||||
|
} |
||||||
|
this.iterator = contents.values().iterator(); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract T createObject(String strippedName, Object obj); |
||||||
|
|
||||||
|
public boolean hasMore() { |
||||||
|
return this.iterator.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
public T next() { |
||||||
|
return this.iterator.next(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean hasMoreElements() { |
||||||
|
return this.iterator.hasNext(); |
||||||
|
} |
||||||
|
|
||||||
|
public T nextElement() { |
||||||
|
return this.iterator.next(); |
||||||
|
} |
||||||
|
|
||||||
|
public void close() { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class NameClassPairEnumeration extends AbstractNamingEnumeration<NameClassPair> { |
||||||
|
|
||||||
|
private NameClassPairEnumeration(SimpleNamingContext context, String root) throws NamingException { |
||||||
|
super(context, root); |
||||||
|
} |
||||||
|
|
||||||
|
protected NameClassPair createObject(String strippedName, Object obj) { |
||||||
|
return new NameClassPair(strippedName, obj.getClass().getName()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class BindingEnumeration extends AbstractNamingEnumeration<Binding> { |
||||||
|
|
||||||
|
private BindingEnumeration(SimpleNamingContext context, String root) throws NamingException { |
||||||
|
super(context, root); |
||||||
|
} |
||||||
|
|
||||||
|
protected Binding createObject(String strippedName, Object obj) { |
||||||
|
return new Binding(strippedName, obj); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,234 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.jndi; |
||||||
|
|
||||||
|
import java.util.Hashtable; |
||||||
|
|
||||||
|
import javax.naming.Context; |
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.naming.spi.InitialContextFactory; |
||||||
|
import javax.naming.spi.InitialContextFactoryBuilder; |
||||||
|
import javax.naming.spi.NamingManager; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.util.ClassUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple implementation of a JNDI naming context builder. |
||||||
|
* |
||||||
|
* <p>Mainly targeted at test environments, where each test case can |
||||||
|
* configure JNDI appropriately, so that <code>new InitialContext()</code> |
||||||
|
* will expose the required objects. Also usable for standalone applications, |
||||||
|
* e.g. for binding a JDBC DataSource to a well-known JNDI location, to be |
||||||
|
* able to use traditional J2EE data access code outside of a J2EE container. |
||||||
|
* |
||||||
|
* <p>There are various choices for DataSource implementations: |
||||||
|
* <ul> |
||||||
|
* <li>SingleConnectionDataSource (using the same Connection for all getConnection calls); |
||||||
|
* <li>DriverManagerDataSource (creating a new Connection on each getConnection call); |
||||||
|
* <li>Apache's Jakarta Commons DBCP offers BasicDataSource (a real pool). |
||||||
|
* </ul> |
||||||
|
* |
||||||
|
* <p>Typical usage in bootstrap code: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); |
||||||
|
* DataSource ds = new DriverManagerDataSource(...); |
||||||
|
* builder.bind("java:comp/env/jdbc/myds", ds); |
||||||
|
* builder.activate();</pre> |
||||||
|
* |
||||||
|
* Note that it's impossible to activate multiple builders within the same JVM, |
||||||
|
* due to JNDI restrictions. Thus to configure a fresh builder repeatedly, use |
||||||
|
* the following code to get a reference to either an already activated builder |
||||||
|
* or a newly activated one: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder(); |
||||||
|
* DataSource ds = new DriverManagerDataSource(...); |
||||||
|
* builder.bind("java:comp/env/jdbc/myds", ds);</pre> |
||||||
|
* |
||||||
|
* Note that you <i>should not</i> call <code>activate()</code> on a builder from |
||||||
|
* this factory method, as there will already be an activated one in any case. |
||||||
|
* |
||||||
|
* <p>An instance of this class is only necessary at setup time. |
||||||
|
* An application does not need to keep a reference to it after activation. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @author Rod Johnson |
||||||
|
* @see #emptyActivatedContextBuilder() |
||||||
|
* @see #bind(String, Object) |
||||||
|
* @see #activate() |
||||||
|
* @see org.springframework.mock.jndi.SimpleNamingContext |
||||||
|
* @see org.springframework.jdbc.datasource.SingleConnectionDataSource |
||||||
|
* @see org.springframework.jdbc.datasource.DriverManagerDataSource |
||||||
|
* @see org.apache.commons.dbcp.BasicDataSource |
||||||
|
*/ |
||||||
|
public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder { |
||||||
|
|
||||||
|
/** An instance of this class bound to JNDI */ |
||||||
|
private static volatile SimpleNamingContextBuilder activated; |
||||||
|
|
||||||
|
private static boolean initialized = false; |
||||||
|
|
||||||
|
private static final Object initializationLock = new Object(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Checks if a SimpleNamingContextBuilder is active. |
||||||
|
* @return the current SimpleNamingContextBuilder instance, |
||||||
|
* or <code>null</code> if none |
||||||
|
*/ |
||||||
|
public static SimpleNamingContextBuilder getCurrentContextBuilder() { |
||||||
|
return activated; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* If no SimpleNamingContextBuilder is already configuring JNDI, |
||||||
|
* create and activate one. Otherwise take the existing activate |
||||||
|
* SimpleNamingContextBuilder, clear it and return it. |
||||||
|
* <p>This is mainly intended for test suites that want to |
||||||
|
* reinitialize JNDI bindings from scratch repeatedly. |
||||||
|
* @return an empty SimpleNamingContextBuilder that can be used |
||||||
|
* to control JNDI bindings |
||||||
|
*/ |
||||||
|
public static SimpleNamingContextBuilder emptyActivatedContextBuilder() throws NamingException { |
||||||
|
if (activated != null) { |
||||||
|
// Clear already activated context builder.
|
||||||
|
activated.clear(); |
||||||
|
} |
||||||
|
else { |
||||||
|
// Create and activate new context builder.
|
||||||
|
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); |
||||||
|
// The activate() call will cause an assigment to the activated variable.
|
||||||
|
builder.activate(); |
||||||
|
} |
||||||
|
return activated; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final Hashtable boundObjects = new Hashtable(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Register the context builder by registering it with the JNDI NamingManager. |
||||||
|
* Note that once this has been done, <code>new InitialContext()</code> will always |
||||||
|
* return a context from this factory. Use the <code>emptyActivatedContextBuilder()</code> |
||||||
|
* static method to get an empty context (for example, in test methods). |
||||||
|
* @throws IllegalStateException if there's already a naming context builder |
||||||
|
* registered with the JNDI NamingManager |
||||||
|
*/ |
||||||
|
public void activate() throws IllegalStateException, NamingException { |
||||||
|
logger.info("Activating simple JNDI environment"); |
||||||
|
synchronized (initializationLock) { |
||||||
|
if (!initialized) { |
||||||
|
if (NamingManager.hasInitialContextFactoryBuilder()) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " + |
||||||
|
"Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " + |
||||||
|
"with no reset option. As a consequence, a JNDI provider must only be registered once per JVM."); |
||||||
|
} |
||||||
|
NamingManager.setInitialContextFactoryBuilder(this); |
||||||
|
initialized = true; |
||||||
|
} |
||||||
|
} |
||||||
|
activated = this; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Temporarily deactivate this context builder. It will remain registered with |
||||||
|
* the JNDI NamingManager but will delegate to the standard JNDI InitialContextFactory |
||||||
|
* (if configured) instead of exposing its own bound objects. |
||||||
|
* <p>Call <code>activate()</code> again in order to expose this contexz builder's own |
||||||
|
* bound objects again. Such activate/deactivate sequences can be applied any number |
||||||
|
* of times (e.g. within a larger integration test suite running in the same VM). |
||||||
|
* @see #activate() |
||||||
|
*/ |
||||||
|
public void deactivate() { |
||||||
|
logger.info("Deactivating simple JNDI environment"); |
||||||
|
activated = null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Clear all bindings in this context builder, while keeping it active. |
||||||
|
*/ |
||||||
|
public void clear() { |
||||||
|
this.boundObjects.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Bind the given object under the given name, for all naming contexts |
||||||
|
* that this context builder will generate. |
||||||
|
* @param name the JNDI name of the object (e.g. "java:comp/env/jdbc/myds") |
||||||
|
* @param obj the object to bind (e.g. a DataSource implementation) |
||||||
|
*/ |
||||||
|
public void bind(String name, Object obj) { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Static JNDI binding: [" + name + "] = [" + obj + "]"); |
||||||
|
} |
||||||
|
this.boundObjects.put(name, obj); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Simple InitialContextFactoryBuilder implementation, |
||||||
|
* creating a new SimpleNamingContext instance. |
||||||
|
* @see SimpleNamingContext |
||||||
|
*/ |
||||||
|
public InitialContextFactory createInitialContextFactory(Hashtable environment) { |
||||||
|
if (activated == null && environment != null) { |
||||||
|
Object icf = environment.get(Context.INITIAL_CONTEXT_FACTORY); |
||||||
|
if (icf != null) { |
||||||
|
Class icfClass = null; |
||||||
|
if (icf instanceof Class) { |
||||||
|
icfClass = (Class) icf; |
||||||
|
} |
||||||
|
else if (icf instanceof String) { |
||||||
|
icfClass = ClassUtils.resolveClassName((String) icf, getClass().getClassLoader()); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new IllegalArgumentException("Invalid value type for environment key [" + |
||||||
|
Context.INITIAL_CONTEXT_FACTORY + "]: " + icf.getClass().getName()); |
||||||
|
} |
||||||
|
if (!InitialContextFactory.class.isAssignableFrom(icfClass)) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Specified class does not implement [" + InitialContextFactory.class.getName() + "]: " + icf); |
||||||
|
} |
||||||
|
try { |
||||||
|
return (InitialContextFactory) icfClass.newInstance(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
IllegalStateException ise = |
||||||
|
new IllegalStateException("Cannot instantiate specified InitialContextFactory: " + icf); |
||||||
|
ise.initCause(ex); |
||||||
|
throw ise; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Default case...
|
||||||
|
return new InitialContextFactory() { |
||||||
|
public Context getInitialContext(Hashtable environment) { |
||||||
|
return new SimpleNamingContext("", boundObjects, environment); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,131 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.BufferedReader; |
||||||
|
import java.io.ByteArrayInputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.io.Reader; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
|
||||||
|
import javax.portlet.ActionRequest; |
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.ActionRequest} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockActionRequest extends MockPortletRequest implements ActionRequest { |
||||||
|
|
||||||
|
private String characterEncoding; |
||||||
|
|
||||||
|
private byte[] content; |
||||||
|
|
||||||
|
private String contentType; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionRequest with a default {@link MockPortalContext} |
||||||
|
* and a default {@link MockPortletContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
* @see MockPortletContext |
||||||
|
*/ |
||||||
|
public MockActionRequest() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionRequest with a default {@link MockPortalContext} |
||||||
|
* and a default {@link MockPortletContext}. |
||||||
|
* @param portletMode the mode that the portlet runs in |
||||||
|
*/ |
||||||
|
public MockActionRequest(PortletMode portletMode) { |
||||||
|
super(); |
||||||
|
setPortletMode(portletMode); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionRequest with a default {@link MockPortalContext}. |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
*/ |
||||||
|
public MockActionRequest(PortletContext portletContext) { |
||||||
|
super(portletContext); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionRequest. |
||||||
|
* @param portalContext the PortalContext that the request runs in |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
*/ |
||||||
|
public MockActionRequest(PortalContext portalContext, PortletContext portletContext) { |
||||||
|
super(portalContext, portletContext); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void setContent(byte[] content) { |
||||||
|
this.content = content; |
||||||
|
} |
||||||
|
|
||||||
|
public InputStream getPortletInputStream() throws IOException { |
||||||
|
if (this.content != null) { |
||||||
|
return new ByteArrayInputStream(this.content); |
||||||
|
} |
||||||
|
else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setCharacterEncoding(String characterEncoding) { |
||||||
|
this.characterEncoding = characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public BufferedReader getReader() throws UnsupportedEncodingException { |
||||||
|
if (this.content != null) { |
||||||
|
InputStream sourceStream = new ByteArrayInputStream(this.content); |
||||||
|
Reader sourceReader = (this.characterEncoding != null) ? |
||||||
|
new InputStreamReader(sourceStream, this.characterEncoding) : new InputStreamReader(sourceStream); |
||||||
|
return new BufferedReader(sourceReader); |
||||||
|
} |
||||||
|
else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getCharacterEncoding() { |
||||||
|
return characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public void setContentType(String contentType) { |
||||||
|
this.contentType = contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public String getContentType() { |
||||||
|
return contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public int getContentLength() { |
||||||
|
return (this.content != null ? content.length : -1); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,163 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import javax.portlet.ActionResponse; |
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
import javax.portlet.PortletModeException; |
||||||
|
import javax.portlet.WindowState; |
||||||
|
import javax.portlet.WindowStateException; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.ActionResponse} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockActionResponse extends MockPortletResponse implements ActionResponse { |
||||||
|
|
||||||
|
private WindowState windowState; |
||||||
|
|
||||||
|
private PortletMode portletMode; |
||||||
|
|
||||||
|
private String redirectedUrl; |
||||||
|
|
||||||
|
private final Map<String, String[]> renderParameters = new LinkedHashMap<String, String[]>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionResponse with a default {@link MockPortalContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
*/ |
||||||
|
public MockActionResponse() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockActionResponse. |
||||||
|
* @param portalContext the PortalContext defining the supported |
||||||
|
* PortletModes and WindowStates |
||||||
|
*/ |
||||||
|
public MockActionResponse(PortalContext portalContext) { |
||||||
|
super(portalContext); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void setWindowState(WindowState windowState) throws WindowStateException { |
||||||
|
if (this.redirectedUrl != null) { |
||||||
|
throw new IllegalStateException("Cannot set WindowState after sendRedirect has been called"); |
||||||
|
} |
||||||
|
if (!CollectionUtils.contains(getPortalContext().getSupportedWindowStates(), windowState)) { |
||||||
|
throw new WindowStateException("WindowState not supported", windowState); |
||||||
|
} |
||||||
|
this.windowState = windowState; |
||||||
|
} |
||||||
|
|
||||||
|
public WindowState getWindowState() { |
||||||
|
return windowState; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPortletMode(PortletMode portletMode) throws PortletModeException { |
||||||
|
if (this.redirectedUrl != null) { |
||||||
|
throw new IllegalStateException("Cannot set PortletMode after sendRedirect has been called"); |
||||||
|
} |
||||||
|
if (!CollectionUtils.contains(getPortalContext().getSupportedPortletModes(), portletMode)) { |
||||||
|
throw new PortletModeException("PortletMode not supported", portletMode); |
||||||
|
} |
||||||
|
this.portletMode = portletMode; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletMode getPortletMode() { |
||||||
|
return portletMode; |
||||||
|
} |
||||||
|
|
||||||
|
public void sendRedirect(String url) throws IOException { |
||||||
|
if (this.windowState != null || this.portletMode != null || !this.renderParameters.isEmpty()) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Cannot call sendRedirect after windowState, portletMode, or renderParameters have been set"); |
||||||
|
} |
||||||
|
Assert.notNull(url, "Redirect URL must not be null"); |
||||||
|
this.redirectedUrl = url; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRedirectedUrl() { |
||||||
|
return redirectedUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRenderParameters(Map parameters) { |
||||||
|
if (this.redirectedUrl != null) { |
||||||
|
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called"); |
||||||
|
} |
||||||
|
Assert.notNull(parameters, "Parameters Map must not be null"); |
||||||
|
this.renderParameters.clear(); |
||||||
|
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { |
||||||
|
Map.Entry entry = (Map.Entry) it.next(); |
||||||
|
Assert.isTrue(entry.getKey() instanceof String, "Key must be of type String"); |
||||||
|
Assert.isTrue(entry.getValue() instanceof String[], "Value must be of type String[]"); |
||||||
|
this.renderParameters.put((String) entry.getKey(), (String[]) entry.getValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setRenderParameter(String key, String value) { |
||||||
|
if (this.redirectedUrl != null) { |
||||||
|
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called"); |
||||||
|
} |
||||||
|
Assert.notNull(key, "Parameter key must not be null"); |
||||||
|
Assert.notNull(value, "Parameter value must not be null"); |
||||||
|
this.renderParameters.put(key, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public String getRenderParameter(String key) { |
||||||
|
Assert.notNull(key, "Parameter key must not be null"); |
||||||
|
String[] arr = this.renderParameters.get(key); |
||||||
|
return (arr != null && arr.length > 0 ? arr[0] : null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRenderParameter(String key, String[] values) { |
||||||
|
if (this.redirectedUrl != null) { |
||||||
|
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called"); |
||||||
|
} |
||||||
|
Assert.notNull(key, "Parameter key must not be null"); |
||||||
|
Assert.notNull(values, "Parameter values must not be null"); |
||||||
|
this.renderParameters.put(key, values); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getRenderParameterValues(String key) { |
||||||
|
Assert.notNull(key, "Parameter key must not be null"); |
||||||
|
return this.renderParameters.get(key); |
||||||
|
} |
||||||
|
|
||||||
|
public Iterator getRenderParameterNames() { |
||||||
|
return this.renderParameters.keySet().iterator(); |
||||||
|
} |
||||||
|
|
||||||
|
public Map getRenderParameterMap() { |
||||||
|
return Collections.unmodifiableMap(this.renderParameters); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.web.multipart.MultipartFile; |
||||||
|
import org.springframework.web.portlet.multipart.MultipartActionRequest; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the |
||||||
|
* {@link org.springframework.web.portlet.multipart.MultipartActionRequest} interface. |
||||||
|
* |
||||||
|
* <p>Useful for testing application controllers that access multipart uploads. |
||||||
|
* The {@link org.springframework.mock.web.MockMultipartFile} can be used to |
||||||
|
* populate these mock requests with files. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
* @see org.springframework.mock.web.MockMultipartFile |
||||||
|
*/ |
||||||
|
public class MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest { |
||||||
|
|
||||||
|
private final Map<String, MultipartFile> multipartFiles = new LinkedHashMap<String, MultipartFile>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add a file to this request. The parameter name from the multipart |
||||||
|
* form is taken from the {@link org.springframework.web.multipart.MultipartFile#getName()}. |
||||||
|
* @param file multipart file to be added |
||||||
|
*/ |
||||||
|
public void addFile(MultipartFile file) { |
||||||
|
Assert.notNull(file, "MultipartFile must not be null"); |
||||||
|
this.multipartFiles.put(file.getName(), file); |
||||||
|
} |
||||||
|
|
||||||
|
public Iterator<String> getFileNames() { |
||||||
|
return getFileMap().keySet().iterator(); |
||||||
|
} |
||||||
|
|
||||||
|
public MultipartFile getFile(String name) { |
||||||
|
return this.multipartFiles.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, MultipartFile> getFileMap() { |
||||||
|
return Collections.unmodifiableMap(this.multipartFiles); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
import javax.portlet.WindowState; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortalContext} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortalContext implements PortalContext { |
||||||
|
|
||||||
|
private final Map<String, String> properties = new HashMap<String, String>(); |
||||||
|
|
||||||
|
private final List<PortletMode> portletModes; |
||||||
|
|
||||||
|
private final List<WindowState> windowStates; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortalContext |
||||||
|
* with default PortletModes (VIEW, EDIT, HELP) |
||||||
|
* and default WindowStates (NORMAL, MAXIMIZED, MINIMIZED). |
||||||
|
* @see javax.portlet.PortletMode |
||||||
|
* @see javax.portlet.WindowState |
||||||
|
*/ |
||||||
|
public MockPortalContext() { |
||||||
|
this.portletModes = new ArrayList<PortletMode>(3); |
||||||
|
this.portletModes.add(PortletMode.VIEW); |
||||||
|
this.portletModes.add(PortletMode.EDIT); |
||||||
|
this.portletModes.add(PortletMode.HELP); |
||||||
|
|
||||||
|
this.windowStates = new ArrayList<WindowState>(3); |
||||||
|
this.windowStates.add(WindowState.NORMAL); |
||||||
|
this.windowStates.add(WindowState.MAXIMIZED); |
||||||
|
this.windowStates.add(WindowState.MINIMIZED); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortalContext with the given PortletModes and WindowStates. |
||||||
|
* @param supportedPortletModes the List of supported PortletMode instances |
||||||
|
* @param supportedWindowStates the List of supported WindowState instances |
||||||
|
* @see javax.portlet.PortletMode |
||||||
|
* @see javax.portlet.WindowState |
||||||
|
*/ |
||||||
|
public MockPortalContext(List<PortletMode> supportedPortletModes, List<WindowState> supportedWindowStates) { |
||||||
|
this.portletModes = new ArrayList<PortletMode>(supportedPortletModes); |
||||||
|
this.windowStates = new ArrayList<WindowState>(supportedWindowStates); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String getPortalInfo() { |
||||||
|
return "MockPortal/1.0"; |
||||||
|
} |
||||||
|
|
||||||
|
public void setProperty(String name, String value) { |
||||||
|
this.properties.put(name, value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getProperty(String name) { |
||||||
|
return this.properties.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getPropertyNames() { |
||||||
|
return Collections.enumeration(this.properties.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<PortletMode> getSupportedPortletModes() { |
||||||
|
return Collections.enumeration(this.portletModes); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<WindowState> getSupportedWindowStates() { |
||||||
|
return Collections.enumeration(this.windowStates); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,116 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Properties; |
||||||
|
import java.util.ResourceBundle; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Collections; |
||||||
|
import javax.portlet.PortletConfig; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletConfig} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletConfig implements PortletConfig { |
||||||
|
|
||||||
|
private final PortletContext portletContext; |
||||||
|
|
||||||
|
private final String portletName; |
||||||
|
|
||||||
|
private final Map<Locale, ResourceBundle> resourceBundles = new HashMap<Locale, ResourceBundle>(); |
||||||
|
|
||||||
|
private final Map<String, String> initParameters = new LinkedHashMap<String, String>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletConfig with a default {@link MockPortletContext}. |
||||||
|
*/ |
||||||
|
public MockPortletConfig() { |
||||||
|
this(null, ""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletConfig with a default {@link MockPortletContext}. |
||||||
|
* @param portletName the name of the portlet |
||||||
|
*/ |
||||||
|
public MockPortletConfig(String portletName) { |
||||||
|
this(null, portletName); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletConfig. |
||||||
|
* @param portletContext the PortletContext that the portlet runs in |
||||||
|
*/ |
||||||
|
public MockPortletConfig(PortletContext portletContext) { |
||||||
|
this(portletContext, ""); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletConfig. |
||||||
|
* @param portletContext the PortletContext that the portlet runs in |
||||||
|
* @param portletName the name of the portlet |
||||||
|
*/ |
||||||
|
public MockPortletConfig(PortletContext portletContext, String portletName) { |
||||||
|
this.portletContext = (portletContext != null ? portletContext : new MockPortletContext()); |
||||||
|
this.portletName = portletName; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String getPortletName() { |
||||||
|
return this.portletName; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletContext getPortletContext() { |
||||||
|
return this.portletContext; |
||||||
|
} |
||||||
|
|
||||||
|
public void setResourceBundle(Locale locale, ResourceBundle resourceBundle) { |
||||||
|
Assert.notNull(locale, "Locale must not be null"); |
||||||
|
this.resourceBundles.put(locale, resourceBundle); |
||||||
|
} |
||||||
|
|
||||||
|
public ResourceBundle getResourceBundle(Locale locale) { |
||||||
|
Assert.notNull(locale, "Locale must not be null"); |
||||||
|
return this.resourceBundles.get(locale); |
||||||
|
} |
||||||
|
|
||||||
|
public void addInitParameter(String name, String value) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
this.initParameters.put(name, value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getInitParameter(String name) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
return this.initParameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getInitParameterNames() { |
||||||
|
return Collections.enumeration(this.initParameters.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,254 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.net.MalformedURLException; |
||||||
|
import java.net.URL; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
import javax.portlet.PortletRequestDispatcher; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader; |
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
import org.springframework.core.io.ResourceLoader; |
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.web.util.WebUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletContext} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletContext implements PortletContext { |
||||||
|
|
||||||
|
private static final String TEMP_DIR_SYSTEM_PROPERTY = "java.io.tmpdir"; |
||||||
|
|
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final String resourceBasePath; |
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader; |
||||||
|
|
||||||
|
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>(); |
||||||
|
|
||||||
|
private final Map<String, String> initParameters = new LinkedHashMap<String, String>(); |
||||||
|
|
||||||
|
private String portletContextName = "MockPortletContext"; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletContext with no base path and a |
||||||
|
* DefaultResourceLoader (i.e. the classpath root as WAR root). |
||||||
|
* @see org.springframework.core.io.DefaultResourceLoader |
||||||
|
*/ |
||||||
|
public MockPortletContext() { |
||||||
|
this("", null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletContext using a DefaultResourceLoader. |
||||||
|
* @param resourceBasePath the WAR root directory (should not end with a slash) |
||||||
|
* @see org.springframework.core.io.DefaultResourceLoader |
||||||
|
*/ |
||||||
|
public MockPortletContext(String resourceBasePath) { |
||||||
|
this(resourceBasePath, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletContext, using the specified ResourceLoader |
||||||
|
* and no base path. |
||||||
|
* @param resourceLoader the ResourceLoader to use (or null for the default) |
||||||
|
*/ |
||||||
|
public MockPortletContext(ResourceLoader resourceLoader) { |
||||||
|
this("", resourceLoader); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletContext. |
||||||
|
* @param resourceBasePath the WAR root directory (should not end with a slash) |
||||||
|
* @param resourceLoader the ResourceLoader to use (or null for the default) |
||||||
|
*/ |
||||||
|
public MockPortletContext(String resourceBasePath, ResourceLoader resourceLoader) { |
||||||
|
this.resourceBasePath = (resourceBasePath != null ? resourceBasePath : ""); |
||||||
|
this.resourceLoader = (resourceLoader != null ? resourceLoader : new DefaultResourceLoader()); |
||||||
|
|
||||||
|
// Use JVM temp dir as PortletContext temp dir.
|
||||||
|
String tempDir = System.getProperty(TEMP_DIR_SYSTEM_PROPERTY); |
||||||
|
if (tempDir != null) { |
||||||
|
this.attributes.put(WebUtils.TEMP_DIR_CONTEXT_ATTRIBUTE, new File(tempDir)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Build a full resource location for the given path, |
||||||
|
* prepending the resource base path of this MockPortletContext. |
||||||
|
* @param path the path as specified |
||||||
|
* @return the full resource path |
||||||
|
*/ |
||||||
|
protected String getResourceLocation(String path) { |
||||||
|
if (!path.startsWith("/")) { |
||||||
|
path = "/" + path; |
||||||
|
} |
||||||
|
return this.resourceBasePath + path; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String getServerInfo() { |
||||||
|
return "MockPortal/1.0"; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletRequestDispatcher getRequestDispatcher(String path) { |
||||||
|
if (!path.startsWith("/")) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"PortletRequestDispatcher path at PortletContext level must start with '/'"); |
||||||
|
} |
||||||
|
return new MockPortletRequestDispatcher(path); |
||||||
|
} |
||||||
|
|
||||||
|
public PortletRequestDispatcher getNamedDispatcher(String path) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public InputStream getResourceAsStream(String path) { |
||||||
|
Resource resource = this.resourceLoader.getResource(getResourceLocation(path)); |
||||||
|
try { |
||||||
|
return resource.getInputStream(); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
logger.info("Couldn't open InputStream for " + resource, ex); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int getMajorVersion() { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
public int getMinorVersion() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
public String getMimeType(String filePath) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRealPath(String path) { |
||||||
|
Resource resource = this.resourceLoader.getResource(getResourceLocation(path)); |
||||||
|
try { |
||||||
|
return resource.getFile().getAbsolutePath(); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
logger.info("Couldn't determine real path of resource " + resource, ex); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Set<String> getResourcePaths(String path) { |
||||||
|
Resource resource = this.resourceLoader.getResource(getResourceLocation(path)); |
||||||
|
try { |
||||||
|
File file = resource.getFile(); |
||||||
|
String[] fileList = file.list(); |
||||||
|
String prefix = (path.endsWith("/") ? path : path + "/"); |
||||||
|
Set<String> resourcePaths = new HashSet<String>(fileList.length); |
||||||
|
for (String fileEntry : fileList) { |
||||||
|
resourcePaths.add(prefix + fileEntry); |
||||||
|
} |
||||||
|
return resourcePaths; |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
logger.info("Couldn't get resource paths for " + resource, ex); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public URL getResource(String path) throws MalformedURLException { |
||||||
|
Resource resource = this.resourceLoader.getResource(getResourceLocation(path)); |
||||||
|
try { |
||||||
|
return resource.getURL(); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
logger.info("Couldn't get URL for " + resource, ex); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Object getAttribute(String name) { |
||||||
|
return this.attributes.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getAttributeNames() { |
||||||
|
return Collections.enumeration(this.attributes.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(String name, Object value) { |
||||||
|
if (value != null) { |
||||||
|
this.attributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void removeAttribute(String name) { |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
|
||||||
|
public void addInitParameter(String name, String value) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
this.initParameters.put(name, value); |
||||||
|
} |
||||||
|
|
||||||
|
public String getInitParameter(String name) { |
||||||
|
Assert.notNull(name, "Parameter name must not be null"); |
||||||
|
return this.initParameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getInitParameterNames() { |
||||||
|
return Collections.enumeration(this.initParameters.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public void log(String message) { |
||||||
|
logger.info(message); |
||||||
|
} |
||||||
|
|
||||||
|
public void log(String message, Throwable t) { |
||||||
|
logger.info(message, t); |
||||||
|
} |
||||||
|
|
||||||
|
public void setPortletContextName(String portletContextName) { |
||||||
|
this.portletContextName = portletContextName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getPortletContextName() { |
||||||
|
return portletContextName; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,115 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import javax.portlet.PortletPreferences; |
||||||
|
import javax.portlet.PreferencesValidator; |
||||||
|
import javax.portlet.ReadOnlyException; |
||||||
|
import javax.portlet.ValidatorException; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletPreferences} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletPreferences implements PortletPreferences { |
||||||
|
|
||||||
|
private PreferencesValidator preferencesValidator; |
||||||
|
|
||||||
|
private final Map<String, String[]> preferences = new LinkedHashMap<String, String[]>(); |
||||||
|
|
||||||
|
private final Set<String> readOnly = new HashSet<String>(); |
||||||
|
|
||||||
|
|
||||||
|
public void setReadOnly(String key, boolean readOnly) { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
if (readOnly) { |
||||||
|
this.readOnly.add(key); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.readOnly.remove(key); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isReadOnly(String key) { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
return this.readOnly.contains(key); |
||||||
|
} |
||||||
|
|
||||||
|
public String getValue(String key, String def) { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
String[] values = this.preferences.get(key); |
||||||
|
return (values != null && values.length > 0 ? values[0] : def); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getValues(String key, String[] def) { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
String[] values = this.preferences.get(key); |
||||||
|
return (values != null && values.length > 0 ? values : def); |
||||||
|
} |
||||||
|
|
||||||
|
public void setValue(String key, String value) throws ReadOnlyException { |
||||||
|
setValues(key, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public void setValues(String key, String[] values) throws ReadOnlyException { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
if (isReadOnly(key)) { |
||||||
|
throw new ReadOnlyException("Preference '" + key + "' is read-only"); |
||||||
|
} |
||||||
|
this.preferences.put(key, values); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getNames() { |
||||||
|
return Collections.enumeration(this.preferences.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, String[]> getMap() { |
||||||
|
return Collections.unmodifiableMap(this.preferences); |
||||||
|
} |
||||||
|
|
||||||
|
public void reset(String key) throws ReadOnlyException { |
||||||
|
Assert.notNull(key, "Key must not be null"); |
||||||
|
if (isReadOnly(key)) { |
||||||
|
throw new ReadOnlyException("Preference '" + key + "' is read-only"); |
||||||
|
} |
||||||
|
this.preferences.remove(key); |
||||||
|
} |
||||||
|
|
||||||
|
public void setPreferencesValidator(PreferencesValidator preferencesValidator) { |
||||||
|
this.preferencesValidator = preferencesValidator; |
||||||
|
} |
||||||
|
|
||||||
|
public void store() throws IOException, ValidatorException { |
||||||
|
if (this.preferencesValidator != null) { |
||||||
|
this.preferencesValidator.validate(this); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,462 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.security.Principal; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Locale; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
import javax.portlet.PortletPreferences; |
||||||
|
import javax.portlet.PortletRequest; |
||||||
|
import javax.portlet.PortletSession; |
||||||
|
import javax.portlet.WindowState; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletRequest} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletRequest implements PortletRequest { |
||||||
|
|
||||||
|
private boolean active = true; |
||||||
|
|
||||||
|
private final PortalContext portalContext; |
||||||
|
|
||||||
|
private final PortletContext portletContext; |
||||||
|
|
||||||
|
private PortletSession session; |
||||||
|
|
||||||
|
private WindowState windowState = WindowState.NORMAL; |
||||||
|
|
||||||
|
private PortletMode portletMode = PortletMode.VIEW; |
||||||
|
|
||||||
|
private PortletPreferences portletPreferences = new MockPortletPreferences(); |
||||||
|
|
||||||
|
private final Map<String, List<String>> properties = new LinkedHashMap<String, List<String>>(); |
||||||
|
|
||||||
|
private final Map<String, Object> attributes = new LinkedHashMap<String, Object>(); |
||||||
|
|
||||||
|
private final Map<String, String[]> parameters = new LinkedHashMap<String, String[]>(); |
||||||
|
|
||||||
|
private String authType = null; |
||||||
|
|
||||||
|
private String contextPath = ""; |
||||||
|
|
||||||
|
private String remoteUser = null; |
||||||
|
|
||||||
|
private Principal userPrincipal = null; |
||||||
|
|
||||||
|
private final Set<String> userRoles = new HashSet<String>(); |
||||||
|
|
||||||
|
private boolean secure = false; |
||||||
|
|
||||||
|
private boolean requestedSessionIdValid = true; |
||||||
|
|
||||||
|
private final List<String> responseContentTypes = new LinkedList<String>(); |
||||||
|
|
||||||
|
private final List<Locale> locales = new LinkedList<Locale>(); |
||||||
|
|
||||||
|
private String scheme = "http"; |
||||||
|
|
||||||
|
private String serverName = "localhost"; |
||||||
|
|
||||||
|
private int serverPort = 80; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletRequest with a default {@link MockPortalContext} |
||||||
|
* and a default {@link MockPortletContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
* @see MockPortletContext |
||||||
|
*/ |
||||||
|
public MockPortletRequest() { |
||||||
|
this(null, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletRequest with a default {@link MockPortalContext}. |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
* @see MockPortalContext |
||||||
|
*/ |
||||||
|
public MockPortletRequest(PortletContext portletContext) { |
||||||
|
this(null, portletContext); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletRequest. |
||||||
|
* @param portalContext the PortalContext that the request runs in |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
*/ |
||||||
|
public MockPortletRequest(PortalContext portalContext, PortletContext portletContext) { |
||||||
|
this.portalContext = (portalContext != null ? portalContext : new MockPortalContext()); |
||||||
|
this.portletContext = (portletContext != null ? portletContext : new MockPortletContext()); |
||||||
|
this.responseContentTypes.add("text/html"); |
||||||
|
this.locales.add(Locale.ENGLISH); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Lifecycle methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return whether this request is still active (that is, not completed yet). |
||||||
|
*/ |
||||||
|
public boolean isActive() { |
||||||
|
return this.active; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Mark this request as completed. |
||||||
|
*/ |
||||||
|
public void close() { |
||||||
|
this.active = false; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Check whether this request is still active (that is, not completed yet), |
||||||
|
* throwing an IllegalStateException if not active anymore. |
||||||
|
*/ |
||||||
|
protected void checkActive() throws IllegalStateException { |
||||||
|
if (!this.active) { |
||||||
|
throw new IllegalStateException("Request is not active anymore"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// PortletRequest methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public boolean isWindowStateAllowed(WindowState windowState) { |
||||||
|
return CollectionUtils.contains(this.portalContext.getSupportedWindowStates(), windowState); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isPortletModeAllowed(PortletMode portletMode) { |
||||||
|
return CollectionUtils.contains(this.portalContext.getSupportedPortletModes(), portletMode); |
||||||
|
} |
||||||
|
|
||||||
|
public void setPortletMode(PortletMode portletMode) { |
||||||
|
Assert.notNull(portletMode, "PortletMode must not be null"); |
||||||
|
this.portletMode = portletMode; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletMode getPortletMode() { |
||||||
|
return this.portletMode; |
||||||
|
} |
||||||
|
|
||||||
|
public void setWindowState(WindowState windowState) { |
||||||
|
Assert.notNull(windowState, "WindowState must not be null"); |
||||||
|
this.windowState = windowState; |
||||||
|
} |
||||||
|
|
||||||
|
public WindowState getWindowState() { |
||||||
|
return this.windowState; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPreferences(PortletPreferences preferences) { |
||||||
|
Assert.notNull(preferences, "PortletPreferences must not be null"); |
||||||
|
this.portletPreferences = preferences; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletPreferences getPreferences() { |
||||||
|
return this.portletPreferences; |
||||||
|
} |
||||||
|
|
||||||
|
public void setSession(PortletSession session) { |
||||||
|
this.session = session; |
||||||
|
if (session instanceof MockPortletSession) { |
||||||
|
MockPortletSession mockSession = ((MockPortletSession) session); |
||||||
|
mockSession.access(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public PortletSession getPortletSession() { |
||||||
|
return getPortletSession(true); |
||||||
|
} |
||||||
|
|
||||||
|
public PortletSession getPortletSession(boolean create) { |
||||||
|
checkActive(); |
||||||
|
// Reset session if invalidated.
|
||||||
|
if (this.session instanceof MockPortletSession && ((MockPortletSession) this.session).isInvalid()) { |
||||||
|
this.session = null; |
||||||
|
} |
||||||
|
// Create new session if necessary.
|
||||||
|
if (this.session == null && create) { |
||||||
|
this.session = new MockPortletSession(this.portletContext); |
||||||
|
} |
||||||
|
return this.session; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a single value for the specified property. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* property key, they will be replaced. |
||||||
|
*/ |
||||||
|
public void setProperty(String key, String value) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
List<String> list = new LinkedList<String>(); |
||||||
|
list.add(value); |
||||||
|
this.properties.put(key, list); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a single value for the specified property. |
||||||
|
* <p>If there are already one or more values registered for the given |
||||||
|
* property key, the given value will be added to the end of the list. |
||||||
|
*/ |
||||||
|
public void addProperty(String key, String value) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
List<String> oldList = this.properties.get(key); |
||||||
|
if (oldList != null) { |
||||||
|
oldList.add(value); |
||||||
|
} |
||||||
|
else { |
||||||
|
List<String> list = new LinkedList<String>(); |
||||||
|
list.add(value); |
||||||
|
this.properties.put(key, list); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getProperty(String key) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
List list = this.properties.get(key); |
||||||
|
return (list != null && list.size() > 0 ? (String) list.get(0) : null); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getProperties(String key) { |
||||||
|
Assert.notNull(key, "property key must not be null"); |
||||||
|
return Collections.enumeration(this.properties.get(key)); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getPropertyNames() { |
||||||
|
return Collections.enumeration(this.properties.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public PortalContext getPortalContext() { |
||||||
|
return this.portalContext; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAuthType(String authType) { |
||||||
|
this.authType = authType; |
||||||
|
} |
||||||
|
|
||||||
|
public String getAuthType() { |
||||||
|
return this.authType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setContextPath(String contextPath) { |
||||||
|
this.contextPath = contextPath; |
||||||
|
} |
||||||
|
|
||||||
|
public String getContextPath() { |
||||||
|
return this.contextPath; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRemoteUser(String remoteUser) { |
||||||
|
this.remoteUser = remoteUser; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRemoteUser() { |
||||||
|
return this.remoteUser; |
||||||
|
} |
||||||
|
|
||||||
|
public void setUserPrincipal(Principal userPrincipal) { |
||||||
|
this.userPrincipal = userPrincipal; |
||||||
|
} |
||||||
|
|
||||||
|
public Principal getUserPrincipal() { |
||||||
|
return this.userPrincipal; |
||||||
|
} |
||||||
|
|
||||||
|
public void addUserRole(String role) { |
||||||
|
this.userRoles.add(role); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isUserInRole(String role) { |
||||||
|
return this.userRoles.contains(role); |
||||||
|
} |
||||||
|
|
||||||
|
public Object getAttribute(String name) { |
||||||
|
checkActive(); |
||||||
|
return this.attributes.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getAttributeNames() { |
||||||
|
checkActive(); |
||||||
|
return Collections.enumeration(this.attributes.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameters(Map<String, String[]> parameters) { |
||||||
|
Assert.notNull(parameters, "Parameters Map must not be null"); |
||||||
|
this.parameters.clear(); |
||||||
|
this.parameters.putAll(parameters); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameter(String key, String value) { |
||||||
|
Assert.notNull(key, "Parameter key must be null"); |
||||||
|
Assert.notNull(value, "Parameter value must not be null"); |
||||||
|
this.parameters.put(key, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameter(String key, String[] values) { |
||||||
|
Assert.notNull(key, "Parameter key must be null"); |
||||||
|
Assert.notNull(values, "Parameter values must not be null"); |
||||||
|
this.parameters.put(key, values); |
||||||
|
} |
||||||
|
|
||||||
|
public void addParameter(String name, String value) { |
||||||
|
addParameter(name, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public void addParameter(String name, String[] values) { |
||||||
|
String[] oldArr = this.parameters.get(name); |
||||||
|
if (oldArr != null) { |
||||||
|
String[] newArr = new String[oldArr.length + values.length]; |
||||||
|
System.arraycopy(oldArr, 0, newArr, 0, oldArr.length); |
||||||
|
System.arraycopy(values, 0, newArr, oldArr.length, values.length); |
||||||
|
this.parameters.put(name, newArr); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.parameters.put(name, values); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public String getParameter(String name) { |
||||||
|
String[] arr = this.parameters.get(name); |
||||||
|
return (arr != null && arr.length > 0 ? arr[0] : null); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getParameterNames() { |
||||||
|
return Collections.enumeration(this.parameters.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getParameterValues(String name) { |
||||||
|
return this.parameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Map getParameterMap() { |
||||||
|
return Collections.unmodifiableMap(this.parameters); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSecure(boolean secure) { |
||||||
|
this.secure = secure; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSecure() { |
||||||
|
return this.secure; |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(String name, Object value) { |
||||||
|
checkActive(); |
||||||
|
if (value != null) { |
||||||
|
this.attributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void removeAttribute(String name) { |
||||||
|
checkActive(); |
||||||
|
this.attributes.remove(name); |
||||||
|
} |
||||||
|
|
||||||
|
public String getRequestedSessionId() { |
||||||
|
PortletSession session = this.getPortletSession(); |
||||||
|
return (session != null ? session.getId() : null); |
||||||
|
} |
||||||
|
|
||||||
|
public void setRequestedSessionIdValid(boolean requestedSessionIdValid) { |
||||||
|
this.requestedSessionIdValid = requestedSessionIdValid; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isRequestedSessionIdValid() { |
||||||
|
return this.requestedSessionIdValid; |
||||||
|
} |
||||||
|
|
||||||
|
public void addResponseContentType(String responseContentType) { |
||||||
|
this.responseContentTypes.add(responseContentType); |
||||||
|
} |
||||||
|
|
||||||
|
public void addPreferredResponseContentType(String responseContentType) { |
||||||
|
this.responseContentTypes.add(0, responseContentType); |
||||||
|
} |
||||||
|
|
||||||
|
public String getResponseContentType() { |
||||||
|
return this.responseContentTypes.get(0); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getResponseContentTypes() { |
||||||
|
return Collections.enumeration(this.responseContentTypes); |
||||||
|
} |
||||||
|
|
||||||
|
public void addLocale(Locale locale) { |
||||||
|
this.locales.add(locale); |
||||||
|
} |
||||||
|
|
||||||
|
public void addPreferredLocale(Locale locale) { |
||||||
|
this.locales.add(0, locale); |
||||||
|
} |
||||||
|
|
||||||
|
public Locale getLocale() { |
||||||
|
return this.locales.get(0); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<Locale> getLocales() { |
||||||
|
return Collections.enumeration(this.locales); |
||||||
|
} |
||||||
|
|
||||||
|
public void setScheme(String scheme) { |
||||||
|
this.scheme = scheme; |
||||||
|
} |
||||||
|
|
||||||
|
public String getScheme() { |
||||||
|
return this.scheme; |
||||||
|
} |
||||||
|
|
||||||
|
public void setServerName(String serverName) { |
||||||
|
this.serverName = serverName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getServerName() { |
||||||
|
return this.serverName; |
||||||
|
} |
||||||
|
|
||||||
|
public void setServerPort(int serverPort) { |
||||||
|
this.serverPort = serverPort; |
||||||
|
} |
||||||
|
|
||||||
|
public int getServerPort() { |
||||||
|
return this.serverPort; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2006 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import javax.portlet.PortletException; |
||||||
|
import javax.portlet.PortletRequestDispatcher; |
||||||
|
import javax.portlet.RenderRequest; |
||||||
|
import javax.portlet.RenderResponse; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletRequestDispatcher} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletRequestDispatcher implements PortletRequestDispatcher { |
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private final String url; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletRequestDispatcher for the given URL. |
||||||
|
* @param url the URL to dispatch to. |
||||||
|
*/ |
||||||
|
public MockPortletRequestDispatcher(String url) { |
||||||
|
Assert.notNull(url, "URL must not be null"); |
||||||
|
this.url = url; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void include(RenderRequest request, RenderResponse response) throws PortletException, IOException { |
||||||
|
Assert.notNull(request, "Request must not be null"); |
||||||
|
Assert.notNull(response, "Response must not be null"); |
||||||
|
if (!(response instanceof MockRenderResponse)) { |
||||||
|
throw new IllegalArgumentException("MockPortletRequestDispatcher requires MockRenderResponse"); |
||||||
|
} |
||||||
|
((MockRenderResponse) response).setIncludedUrl(this.url); |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("MockPortletRequestDispatcher: including URL [" + this.url + "]"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,110 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletResponse; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletResponse} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletResponse implements PortletResponse { |
||||||
|
|
||||||
|
private final PortalContext portalContext; |
||||||
|
|
||||||
|
private final Map<String, String[]> properties = new LinkedHashMap<String, String[]>(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletResponse with a default {@link MockPortalContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
*/ |
||||||
|
public MockPortletResponse() { |
||||||
|
this(null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletResponse. |
||||||
|
* @param portalContext the PortalContext defining the supported |
||||||
|
* PortletModes and WindowStates |
||||||
|
*/ |
||||||
|
public MockPortletResponse(PortalContext portalContext) { |
||||||
|
this.portalContext = (portalContext != null ? portalContext : new MockPortalContext()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the PortalContext that this MockPortletResponse runs in, |
||||||
|
* defining the supported PortletModes and WindowStates. |
||||||
|
*/ |
||||||
|
public PortalContext getPortalContext() { |
||||||
|
return this.portalContext; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// PortletResponse methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void addProperty(String key, String value) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
String[] oldArr = this.properties.get(key); |
||||||
|
if (oldArr != null) { |
||||||
|
String[] newArr = new String[oldArr.length + 1]; |
||||||
|
System.arraycopy(oldArr, 0, newArr, 0, oldArr.length); |
||||||
|
newArr[oldArr.length] = value; |
||||||
|
this.properties.put(key, newArr); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.properties.put(key, new String[] {value}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setProperty(String key, String value) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
this.properties.put(key, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public Set getPropertyNames() { |
||||||
|
return this.properties.keySet(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getProperty(String key) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
String[] arr = this.properties.get(key); |
||||||
|
return (arr != null && arr.length > 0 ? arr[0] : null); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getProperties(String key) { |
||||||
|
Assert.notNull(key, "Property key must not be null"); |
||||||
|
return this.properties.get(key); |
||||||
|
} |
||||||
|
|
||||||
|
public String encodeURL(String path) { |
||||||
|
return path; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,190 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Enumeration; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
import javax.portlet.PortletSession; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletSession} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletSession implements PortletSession { |
||||||
|
|
||||||
|
private static int nextId = 1; |
||||||
|
|
||||||
|
|
||||||
|
private final String id = Integer.toString(nextId++); |
||||||
|
|
||||||
|
private final long creationTime = System.currentTimeMillis(); |
||||||
|
|
||||||
|
private int maxInactiveInterval; |
||||||
|
|
||||||
|
private long lastAccessedTime = System.currentTimeMillis(); |
||||||
|
|
||||||
|
private final PortletContext portletContext; |
||||||
|
|
||||||
|
private final Map<String, Object> portletAttributes = new HashMap<String, Object>(); |
||||||
|
|
||||||
|
private final Map<String, Object> applicationAttributes = new HashMap<String, Object>(); |
||||||
|
|
||||||
|
private boolean invalid = false; |
||||||
|
|
||||||
|
private boolean isNew = true; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletSession with a default {@link MockPortletContext}. |
||||||
|
* @see MockPortletContext |
||||||
|
*/ |
||||||
|
public MockPortletSession() { |
||||||
|
this(null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletSession. |
||||||
|
* @param portletContext the PortletContext that the session runs in |
||||||
|
*/ |
||||||
|
public MockPortletSession(PortletContext portletContext) { |
||||||
|
this.portletContext = (portletContext != null ? portletContext : new MockPortletContext()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public Object getAttribute(String name) { |
||||||
|
return this.portletAttributes.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Object getAttribute(String name, int scope) { |
||||||
|
if (scope == PortletSession.PORTLET_SCOPE) { |
||||||
|
return this.portletAttributes.get(name); |
||||||
|
} |
||||||
|
else if (scope == PortletSession.APPLICATION_SCOPE) { |
||||||
|
return this.applicationAttributes.get(name); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getAttributeNames() { |
||||||
|
return Collections.enumeration(this.portletAttributes.keySet()); |
||||||
|
} |
||||||
|
|
||||||
|
public Enumeration<String> getAttributeNames(int scope) { |
||||||
|
if (scope == PortletSession.PORTLET_SCOPE) { |
||||||
|
return Collections.enumeration(this.portletAttributes.keySet()); |
||||||
|
} |
||||||
|
else if (scope == PortletSession.APPLICATION_SCOPE) { |
||||||
|
return Collections.enumeration(this.applicationAttributes.keySet()); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
public long getCreationTime() { |
||||||
|
return this.creationTime; |
||||||
|
} |
||||||
|
|
||||||
|
public String getId() { |
||||||
|
return this.id; |
||||||
|
} |
||||||
|
|
||||||
|
public void access() { |
||||||
|
this.lastAccessedTime = System.currentTimeMillis(); |
||||||
|
setNew(false); |
||||||
|
} |
||||||
|
|
||||||
|
public long getLastAccessedTime() { |
||||||
|
return this.lastAccessedTime; |
||||||
|
} |
||||||
|
|
||||||
|
public int getMaxInactiveInterval() { |
||||||
|
return this.maxInactiveInterval; |
||||||
|
} |
||||||
|
|
||||||
|
public void invalidate() { |
||||||
|
this.invalid = true; |
||||||
|
this.portletAttributes.clear(); |
||||||
|
this.applicationAttributes.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isInvalid() { |
||||||
|
return invalid; |
||||||
|
} |
||||||
|
|
||||||
|
public void setNew(boolean value) { |
||||||
|
this.isNew = value; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isNew() { |
||||||
|
return this.isNew; |
||||||
|
} |
||||||
|
|
||||||
|
public void removeAttribute(String name) { |
||||||
|
this.portletAttributes.remove(name); |
||||||
|
} |
||||||
|
|
||||||
|
public void removeAttribute(String name, int scope) { |
||||||
|
if (scope == PortletSession.PORTLET_SCOPE) { |
||||||
|
this.portletAttributes.remove(name); |
||||||
|
} |
||||||
|
else if (scope == PortletSession.APPLICATION_SCOPE) { |
||||||
|
this.applicationAttributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(String name, Object value) { |
||||||
|
if (value != null) { |
||||||
|
this.portletAttributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.portletAttributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setAttribute(String name, Object value, int scope) { |
||||||
|
if (scope == PortletSession.PORTLET_SCOPE) { |
||||||
|
if (value != null) { |
||||||
|
this.portletAttributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.portletAttributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (scope == PortletSession.APPLICATION_SCOPE) { |
||||||
|
if (value != null) { |
||||||
|
this.applicationAttributes.put(name, value); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.applicationAttributes.remove(name); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setMaxInactiveInterval(int interval) { |
||||||
|
this.maxInactiveInterval = interval; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletContext getPortletContext() { |
||||||
|
return portletContext; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,190 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2008 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.Iterator; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
import javax.portlet.PortletModeException; |
||||||
|
import javax.portlet.PortletSecurityException; |
||||||
|
import javax.portlet.PortletURL; |
||||||
|
import javax.portlet.WindowState; |
||||||
|
import javax.portlet.WindowStateException; |
||||||
|
|
||||||
|
import org.springframework.util.Assert; |
||||||
|
import org.springframework.util.CollectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.PortletURL} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockPortletURL implements PortletURL { |
||||||
|
|
||||||
|
public static final String URL_TYPE_RENDER = "render"; |
||||||
|
|
||||||
|
public static final String URL_TYPE_ACTION = "action"; |
||||||
|
|
||||||
|
private static final String ENCODING = "UTF-8"; |
||||||
|
|
||||||
|
|
||||||
|
private final PortalContext portalContext; |
||||||
|
|
||||||
|
private final String urlType; |
||||||
|
|
||||||
|
private WindowState windowState; |
||||||
|
|
||||||
|
private PortletMode portletMode; |
||||||
|
|
||||||
|
private final Map<String, String[]> parameters = new LinkedHashMap<String, String[]>(); |
||||||
|
|
||||||
|
private boolean secure = false; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockPortletURL for the given URL type. |
||||||
|
* @param portalContext the PortalContext defining the supported |
||||||
|
* PortletModes and WindowStates |
||||||
|
* @param urlType the URL type, for example "render" or "action" |
||||||
|
* @see #URL_TYPE_RENDER |
||||||
|
* @see #URL_TYPE_ACTION |
||||||
|
*/ |
||||||
|
public MockPortletURL(PortalContext portalContext, String urlType) { |
||||||
|
Assert.notNull(portalContext, "PortalContext is required"); |
||||||
|
this.portalContext = portalContext; |
||||||
|
this.urlType = urlType; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// PortletURL methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void setWindowState(WindowState windowState) throws WindowStateException { |
||||||
|
if (!CollectionUtils.contains(this.portalContext.getSupportedWindowStates(), windowState)) { |
||||||
|
throw new WindowStateException("WindowState not supported", windowState); |
||||||
|
} |
||||||
|
this.windowState = windowState; |
||||||
|
} |
||||||
|
|
||||||
|
public void setPortletMode(PortletMode portletMode) throws PortletModeException { |
||||||
|
if (!CollectionUtils.contains(this.portalContext.getSupportedPortletModes(), portletMode)) { |
||||||
|
throw new PortletModeException("PortletMode not supported", portletMode); |
||||||
|
} |
||||||
|
this.portletMode = portletMode; |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameter(String key, String value) { |
||||||
|
Assert.notNull(key, "Parameter key must be null"); |
||||||
|
Assert.notNull(value, "Parameter value must not be null"); |
||||||
|
this.parameters.put(key, new String[] {value}); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameter(String key, String[] values) { |
||||||
|
Assert.notNull(key, "Parameter key must be null"); |
||||||
|
Assert.notNull(values, "Parameter values must not be null"); |
||||||
|
this.parameters.put(key, values); |
||||||
|
} |
||||||
|
|
||||||
|
public void setParameters(Map parameters) { |
||||||
|
Assert.notNull(parameters, "Parameters Map must not be null"); |
||||||
|
this.parameters.clear(); |
||||||
|
for (Iterator it = parameters.entrySet().iterator(); it.hasNext();) { |
||||||
|
Map.Entry entry = (Map.Entry) it.next(); |
||||||
|
Assert.isTrue(entry.getKey() instanceof String, "Key must be of type String"); |
||||||
|
Assert.isTrue(entry.getValue() instanceof String[], "Value must be of type String[]"); |
||||||
|
this.parameters.put((String) entry.getKey(), (String[]) entry.getValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Set<String> getParameterNames() { |
||||||
|
return this.parameters.keySet(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getParameter(String name) { |
||||||
|
String[] arr = this.parameters.get(name); |
||||||
|
return (arr != null && arr.length > 0 ? arr[0] : null); |
||||||
|
} |
||||||
|
|
||||||
|
public String[] getParameterValues(String name) { |
||||||
|
return this.parameters.get(name); |
||||||
|
} |
||||||
|
|
||||||
|
public Map<String, String[]> getParameterMap() { |
||||||
|
return Collections.unmodifiableMap(this.parameters); |
||||||
|
} |
||||||
|
|
||||||
|
public void setSecure(boolean secure) throws PortletSecurityException { |
||||||
|
this.secure = secure; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isSecure() { |
||||||
|
return this.secure; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private String encodeParameter(String name, String value) { |
||||||
|
try { |
||||||
|
return URLEncoder.encode(name, ENCODING) + "=" + URLEncoder.encode(value, ENCODING); |
||||||
|
} |
||||||
|
catch (UnsupportedEncodingException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private String encodeParameter(String name, String[] values) { |
||||||
|
try { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
for (int i = 0, n = values.length; i < n; i++) { |
||||||
|
sb.append((i > 0 ? ";" : "") + |
||||||
|
URLEncoder.encode(name, ENCODING) + "=" + |
||||||
|
URLEncoder.encode(values[i], ENCODING)); |
||||||
|
} |
||||||
|
return sb.toString(); |
||||||
|
} |
||||||
|
catch (UnsupportedEncodingException ex) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public String toString() { |
||||||
|
StringBuilder sb = new StringBuilder(); |
||||||
|
sb.append(encodeParameter("urlType", this.urlType)); |
||||||
|
if (this.windowState != null) { |
||||||
|
sb.append(";").append(encodeParameter("windowState", this.windowState.toString())); |
||||||
|
} |
||||||
|
if (this.portletMode != null) { |
||||||
|
sb.append(";").append(encodeParameter("portletMode", this.portletMode.toString())); |
||||||
|
} |
||||||
|
for (Map.Entry<String, String[]> entry : this.parameters.entrySet()) { |
||||||
|
sb.append(";").append(encodeParameter("param_" + entry.getKey(), entry.getValue())); |
||||||
|
} |
||||||
|
return (this.secure ? "https:" : "http:") + |
||||||
|
"//localhost/mockportlet?" + sb.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,70 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2007 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletContext; |
||||||
|
import javax.portlet.PortletMode; |
||||||
|
import javax.portlet.RenderRequest; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.RenderRequest} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockRenderRequest extends MockPortletRequest implements RenderRequest { |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderRequest with a default {@link MockPortalContext} |
||||||
|
* and a default {@link MockPortletContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
* @see MockPortletContext |
||||||
|
*/ |
||||||
|
public MockRenderRequest() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderRequest with a default {@link MockPortalContext} |
||||||
|
* and a default {@link MockPortletContext}. |
||||||
|
* @param portletMode the mode that the portlet runs in |
||||||
|
*/ |
||||||
|
public MockRenderRequest(PortletMode portletMode) { |
||||||
|
super(); |
||||||
|
setPortletMode(portletMode); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderRequest with a default {@link MockPortalContext}. |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
*/ |
||||||
|
public MockRenderRequest(PortletContext portletContext) { |
||||||
|
super(portletContext); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderRequest. |
||||||
|
* @param portalContext the PortletContext that the request runs in |
||||||
|
* @param portletContext the PortletContext that the request runs in |
||||||
|
*/ |
||||||
|
public MockRenderRequest(PortalContext portalContext, PortletContext portletContext) { |
||||||
|
super(portalContext, portletContext); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,216 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2006 the original author or authors. |
||||||
|
* |
||||||
|
* 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 org.springframework.mock.web.portlet; |
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.OutputStream; |
||||||
|
import java.io.OutputStreamWriter; |
||||||
|
import java.io.PrintWriter; |
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.io.Writer; |
||||||
|
import java.util.Locale; |
||||||
|
|
||||||
|
import javax.portlet.PortalContext; |
||||||
|
import javax.portlet.PortletURL; |
||||||
|
import javax.portlet.RenderResponse; |
||||||
|
|
||||||
|
import org.springframework.web.util.WebUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Mock implementation of the {@link javax.portlet.RenderResponse} interface. |
||||||
|
* |
||||||
|
* @author John A. Lewis |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class MockRenderResponse extends MockPortletResponse implements RenderResponse { |
||||||
|
|
||||||
|
private String contentType; |
||||||
|
|
||||||
|
private String namespace = "MockPortlet"; |
||||||
|
|
||||||
|
private String title; |
||||||
|
|
||||||
|
private String characterEncoding = WebUtils.DEFAULT_CHARACTER_ENCODING; |
||||||
|
|
||||||
|
private PrintWriter writer; |
||||||
|
|
||||||
|
private Locale locale = Locale.getDefault(); |
||||||
|
|
||||||
|
private int bufferSize = 4096; |
||||||
|
|
||||||
|
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
||||||
|
|
||||||
|
private boolean committed; |
||||||
|
|
||||||
|
private String includedUrl; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderResponse with a default {@link MockPortalContext}. |
||||||
|
* @see MockPortalContext |
||||||
|
*/ |
||||||
|
public MockRenderResponse() { |
||||||
|
super(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MockRenderResponse. |
||||||
|
* @param portalContext the PortalContext defining the supported |
||||||
|
* PortletModes and WindowStates |
||||||
|
*/ |
||||||
|
public MockRenderResponse(PortalContext portalContext) { |
||||||
|
super(portalContext); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// RenderResponse methods
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public String getContentType() { |
||||||
|
return this.contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletURL createRenderURL() { |
||||||
|
PortletURL url = new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_RENDER); |
||||||
|
return url; |
||||||
|
} |
||||||
|
|
||||||
|
public PortletURL createActionURL() { |
||||||
|
PortletURL url = new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_ACTION); |
||||||
|
return url; |
||||||
|
} |
||||||
|
|
||||||
|
public String getNamespace() { |
||||||
|
return this.namespace; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTitle(String title) { |
||||||
|
this.title = title; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTitle() { |
||||||
|
return title; |
||||||
|
} |
||||||
|
|
||||||
|
public void setContentType(String contentType) { |
||||||
|
this.contentType = contentType; |
||||||
|
} |
||||||
|
|
||||||
|
public void setCharacterEncoding(String characterEncoding) { |
||||||
|
this.characterEncoding = characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCharacterEncoding() { |
||||||
|
return this.characterEncoding; |
||||||
|
} |
||||||
|
|
||||||
|
public PrintWriter getWriter() throws UnsupportedEncodingException { |
||||||
|
if (this.writer == null) { |
||||||
|
Writer targetWriter = (this.characterEncoding != null |
||||||
|
? new OutputStreamWriter(this.outputStream, this.characterEncoding) |
||||||
|
: new OutputStreamWriter(this.outputStream)); |
||||||
|
this.writer = new PrintWriter(targetWriter); |
||||||
|
} |
||||||
|
return this.writer; |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] getContentAsByteArray() { |
||||||
|
flushBuffer(); |
||||||
|
return this.outputStream.toByteArray(); |
||||||
|
} |
||||||
|
|
||||||
|
public String getContentAsString() throws UnsupportedEncodingException { |
||||||
|
flushBuffer(); |
||||||
|
return (this.characterEncoding != null) |
||||||
|
? this.outputStream.toString(this.characterEncoding) |
||||||
|
: this.outputStream.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setLocale(Locale locale) { |
||||||
|
this.locale = locale; |
||||||
|
} |
||||||
|
|
||||||
|
public Locale getLocale() { |
||||||
|
return this.locale; |
||||||
|
} |
||||||
|
|
||||||
|
public void setBufferSize(int bufferSize) { |
||||||
|
this.bufferSize = bufferSize; |
||||||
|
} |
||||||
|
|
||||||
|
public int getBufferSize() { |
||||||
|
return this.bufferSize; |
||||||
|
} |
||||||
|
|
||||||
|
public void flushBuffer() { |
||||||
|
if (this.writer != null) { |
||||||
|
this.writer.flush(); |
||||||
|
} |
||||||
|
if (this.outputStream != null) { |
||||||
|
try { |
||||||
|
this.outputStream.flush(); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new IllegalStateException("Could not flush OutputStream: " + ex.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
this.committed = true; |
||||||
|
} |
||||||
|
|
||||||
|
public void resetBuffer() { |
||||||
|
if (this.committed) { |
||||||
|
throw new IllegalStateException("Cannot reset buffer - response is already committed"); |
||||||
|
} |
||||||
|
this.outputStream.reset(); |
||||||
|
} |
||||||
|
|
||||||
|
public void setCommitted(boolean committed) { |
||||||
|
this.committed = committed; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean isCommitted() { |
||||||
|
return this.committed; |
||||||
|
} |
||||||
|
|
||||||
|
public void reset() { |
||||||
|
resetBuffer(); |
||||||
|
this.characterEncoding = null; |
||||||
|
this.contentType = null; |
||||||
|
this.locale = null; |
||||||
|
} |
||||||
|
|
||||||
|
public OutputStream getPortletOutputStream() throws IOException { |
||||||
|
return this.outputStream; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Methods for MockPortletRequestDispatcher
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
public void setIncludedUrl(String includedUrl) { |
||||||
|
this.includedUrl = includedUrl; |
||||||
|
} |
||||||
|
|
||||||
|
public String getIncludedUrl() { |
||||||
|
return includedUrl; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
<html> |
||||||
|
<body> |
||||||
|
|
||||||
|
A comprehensive set of Portlet API mock objects, |
||||||
|
targeted at usage with Spring's web MVC framework. |
||||||
|
Useful for testing web contexts and controllers. |
||||||
|
|
||||||
|
<p>More convenient to use than dynamic mock objects |
||||||
|
(<a href="http://www.easymock.org">EasyMock</a>) or |
||||||
|
existing Portlet API mock objects. |
||||||
|
|
||||||
|
</body> |
||||||
|
</html> |
||||||
Binary file not shown.
@ -0,0 +1,185 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- Created using JasperAssistant (http://www.jasperassistant.com) --> |
||||||
|
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd"> |
||||||
|
|
||||||
|
<jasperReport name="DataSourceReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50"> |
||||||
|
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<parameter name="ReportTitle" class="java.lang.String"> |
||||||
|
</parameter> |
||||||
|
<parameter name="DataFile" class="java.lang.String"> |
||||||
|
</parameter> |
||||||
|
<field name="id" class="java.lang.Integer"> |
||||||
|
</field> |
||||||
|
<field name="name" class="java.lang.String"> |
||||||
|
</field> |
||||||
|
<field name="street" class="java.lang.String"> |
||||||
|
</field> |
||||||
|
<field name="city" class="java.lang.String"> |
||||||
|
</field> |
||||||
|
<variable name="CityNumber" class="java.lang.Integer" resetType="Group" resetGroup="CityGroup" calculation="System"> |
||||||
|
<initialValueExpression><![CDATA[($V{CityNumber} != null)?(new Integer($V{CityNumber}.intValue() + 1)):(new Integer(1))]]></initialValueExpression> |
||||||
|
</variable> |
||||||
|
<group name="CityGroup" minHeightToStartNewPage="60"> |
||||||
|
<groupExpression><![CDATA[$F{city}]]></groupExpression> |
||||||
|
<groupHeader> |
||||||
|
<band height="20"> |
||||||
|
<rectangle> |
||||||
|
<reportElement x="0" y="4" width="515" height="15" forecolor="#c0c0c0" backcolor="#c0c0c0"/> |
||||||
|
<graphicElement/> |
||||||
|
</rectangle> |
||||||
|
<textField> |
||||||
|
<reportElement mode="Opaque" x="0" y="4" width="515" height="15" backcolor="#c0c0c0"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{CityNumber}) + ". " + String.valueOf($F{city})]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="19" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
</band> |
||||||
|
</groupHeader> |
||||||
|
<groupFooter> |
||||||
|
<band height="20"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="-1" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<staticText> |
||||||
|
<reportElement x="400" y="1" width="60" height="15"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Count :]]></text> |
||||||
|
</staticText> |
||||||
|
<textField> |
||||||
|
<reportElement x="460" y="1" width="30" height="15"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{CityGroup_COUNT}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</groupFooter> |
||||||
|
</group> |
||||||
|
<title> |
||||||
|
<band height="70"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="0" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<textField isBlankWhenNull="true"> |
||||||
|
<reportElement x="0" y="10" width="515" height="30"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Normal" size="22"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$P{ReportTitle}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isBlankWhenNull="true"> |
||||||
|
<reportElement x="0" y="40" width="515" height="20"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Normal" size="14"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$P{DataFile}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</title> |
||||||
|
<pageHeader> |
||||||
|
<band height="20"> |
||||||
|
<rectangle> |
||||||
|
<reportElement x="0" y="5" width="515" height="15" forecolor="#333333" backcolor="#333333"/> |
||||||
|
<graphicElement/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="0" y="5" width="55" height="15" forecolor="#ffffff" backcolor="#333333"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[ID]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="55" y="5" width="205" height="15" forecolor="#ffffff" backcolor="#333333"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Name]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="260" y="5" width="255" height="15" forecolor="#ffffff" backcolor="#333333"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Street]]></text> |
||||||
|
</staticText> |
||||||
|
</band> |
||||||
|
</pageHeader> |
||||||
|
<detail> |
||||||
|
<band height="20"> |
||||||
|
<textField> |
||||||
|
<reportElement x="0" y="4" width="50" height="15"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isStretchWithOverflow="true"> |
||||||
|
<reportElement positionType="Float" x="55" y="4" width="200" height="15"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isStretchWithOverflow="true"> |
||||||
|
<reportElement positionType="Float" x="260" y="4" width="255" height="15"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$F{street}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<line> |
||||||
|
<reportElement positionType="Float" x="0" y="19" width="515" height="1" forecolor="#808080"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
</band> |
||||||
|
</detail> |
||||||
|
<pageFooter> |
||||||
|
<band height="40"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="10" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<textField> |
||||||
|
<reportElement x="200" y="20" width="80" height="15"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField evaluationTime="Report"> |
||||||
|
<reportElement x="280" y="20" width="75" height="15"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</pageFooter> |
||||||
|
<lastPageFooter> |
||||||
|
<band height="60"> |
||||||
|
<textField> |
||||||
|
<reportElement x="0" y="10" width="515" height="15"/> |
||||||
|
<textElement textAlignment="Center"/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA["There were " + |
||||||
|
String.valueOf($V{REPORT_COUNT}) + |
||||||
|
" address records on this report."]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="30" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<textField> |
||||||
|
<reportElement x="200" y="40" width="80" height="15"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField evaluationTime="Report"> |
||||||
|
<reportElement x="280" y="40" width="75" height="15"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</lastPageFooter> |
||||||
|
</jasperReport> |
||||||
@ -0,0 +1 @@ |
|||||||
|
page=MeineSeite |
||||||
Binary file not shown.
@ -0,0 +1,227 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- Created using JasperAssistant (http://www.jasperassistant.com) --> |
||||||
|
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd"> |
||||||
|
|
||||||
|
<jasperReport name="ProductReport" columnCount="2" pageWidth="325" pageHeight="842" columnWidth="160" columnSpacing="5" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0"> |
||||||
|
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="8" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="8" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="8" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<parameter name="City" class="java.lang.String"/> |
||||||
|
<field name="id" class="java.lang.Integer"> |
||||||
|
</field> |
||||||
|
<field name="name" class="java.lang.String"> |
||||||
|
</field> |
||||||
|
<field name="quantity" class="java.lang.Float"> |
||||||
|
</field> |
||||||
|
<field name="price" class="java.lang.Float"> |
||||||
|
</field> |
||||||
|
<variable name="QuantityProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum"> |
||||||
|
<variableExpression><![CDATA[$F{quantity}]]></variableExpression> |
||||||
|
</variable> |
||||||
|
<variable name="PriceProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum"> |
||||||
|
<variableExpression><![CDATA[$F{price}]]></variableExpression> |
||||||
|
</variable> |
||||||
|
<variable name="QuantitySum" class="java.lang.Float" calculation="Sum"> |
||||||
|
<variableExpression><![CDATA[$F{quantity}]]></variableExpression> |
||||||
|
</variable> |
||||||
|
<variable name="PriceSum" class="java.lang.Float" calculation="Sum"> |
||||||
|
<variableExpression><![CDATA[$F{price}]]></variableExpression> |
||||||
|
</variable> |
||||||
|
<variable name="ProductCount" class="java.lang.Integer" resetType="Group" resetGroup="ProductGroup" calculation="System"> |
||||||
|
<initialValueExpression><![CDATA[($V{ProductCount} != null)?(new Integer($V{ProductCount}.intValue() + 1)):(new Integer(1))]]></initialValueExpression> |
||||||
|
</variable> |
||||||
|
<group name="ProductGroup"> |
||||||
|
<groupExpression><![CDATA[$F{id}]]></groupExpression> |
||||||
|
<groupHeader> |
||||||
|
<band height="14"> |
||||||
|
<textField> |
||||||
|
<reportElement x="0" y="2" width="15" height="10"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isStretchWithOverflow="true"> |
||||||
|
<reportElement positionType="Float" x="20" y="2" width="80" height="10"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0"> |
||||||
|
<reportElement positionType="Float" x="105" y="2" width="20" height="10"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantityProductSum}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0.00"> |
||||||
|
<reportElement positionType="Float" x="130" y="2" width="30" height="10"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceProductSum}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</groupHeader> |
||||||
|
<groupFooter> |
||||||
|
<band> |
||||||
|
</band> |
||||||
|
</groupFooter> |
||||||
|
</group> |
||||||
|
<title> |
||||||
|
<band height="14"> |
||||||
|
<staticText> |
||||||
|
<reportElement x="0" y="2" width="60" height="10"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Title]]></text> |
||||||
|
</staticText> |
||||||
|
<textField> |
||||||
|
<reportElement x="0" y="2" width="325" height="10"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA["Products ordered by people in " + $P{City}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</title> |
||||||
|
<pageHeader> |
||||||
|
<band height="14"> |
||||||
|
<rectangle> |
||||||
|
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/> |
||||||
|
<graphicElement pen="Thin"/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Page Header]]></text> |
||||||
|
</staticText> |
||||||
|
</band> |
||||||
|
</pageHeader> |
||||||
|
<columnHeader> |
||||||
|
<band height="14"> |
||||||
|
<rectangle> |
||||||
|
<reportElement x="0" y="2" width="160" height="10" forecolor="#ffff99" backcolor="#ffff99"/> |
||||||
|
<graphicElement/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="0" y="2" width="20" height="10" backcolor="#ffff99"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[ID]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="20" y="2" width="85" height="10" backcolor="#ffff99"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Name]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="105" y="2" width="20" height="10" backcolor="#ffff99"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Qty]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="125" y="2" width="35" height="10" backcolor="#ffff99"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Price]]></text> |
||||||
|
</staticText> |
||||||
|
</band> |
||||||
|
</columnHeader> |
||||||
|
<columnFooter> |
||||||
|
<band height="14"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="1" width="160" height="1"/> |
||||||
|
<graphicElement pen="Thin"/> |
||||||
|
</line> |
||||||
|
<staticText> |
||||||
|
<reportElement x="0" y="2" width="60" height="10"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Column Footer]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement x="70" y="2" width="30" height="10"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Total :]]></text> |
||||||
|
</staticText> |
||||||
|
<textField pattern="#0"> |
||||||
|
<reportElement x="105" y="2" width="20" height="10"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantitySum}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField pattern="#0.00"> |
||||||
|
<reportElement x="130" y="2" width="30" height="10"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceSum}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</columnFooter> |
||||||
|
<pageFooter> |
||||||
|
<band height="14"> |
||||||
|
<rectangle> |
||||||
|
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/> |
||||||
|
<graphicElement pen="Thin"/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Page Footer]]></text> |
||||||
|
</staticText> |
||||||
|
<textField> |
||||||
|
<reportElement x="150" y="2" width="100" height="10" forecolor="#808000"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of "]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField evaluationTime="Report"> |
||||||
|
<reportElement x="250" y="2" width="50" height="10" forecolor="#808000"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</pageFooter> |
||||||
|
<summary> |
||||||
|
<band height="14"> |
||||||
|
<rectangle> |
||||||
|
<reportElement x="0" y="2" width="325" height="10" forecolor="#808000" backcolor="#808000"/> |
||||||
|
<graphicElement pen="Thin"/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="0" y="2" width="230" height="10" backcolor="#808000"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Italic"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Summary]]></text> |
||||||
|
</staticText> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="230" y="2" width="55" height="10" backcolor="#808000"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Count :]]></text> |
||||||
|
</staticText> |
||||||
|
<textField pattern="#0"> |
||||||
|
<reportElement mode="Opaque" x="285" y="2" width="40" height="10" backcolor="#808000"/> |
||||||
|
<textElement textAlignment="Right"> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{ProductCount}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</summary> |
||||||
|
</jasperReport> |
||||||
Binary file not shown.
@ -0,0 +1,103 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!-- Created using JasperAssistant (http://www.jasperassistant.com) --> |
||||||
|
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd"> |
||||||
|
|
||||||
|
<jasperReport name="MasterReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50"> |
||||||
|
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/> |
||||||
|
<parameter name="ProductsSubReport" class="net.sf.jasperreports.engine.JasperReport"/> |
||||||
|
<parameter name="SubReportData" class="net.sf.jasperreports.engine.JRDataSource"/> |
||||||
|
<field name="city" class="java.lang.String"> |
||||||
|
</field> |
||||||
|
<title> |
||||||
|
<band height="50"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="0" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<staticText> |
||||||
|
<reportElement x="0" y="10" width="515" height="30"/> |
||||||
|
<textElement textAlignment="Center"> |
||||||
|
<font reportFont="Arial_Normal" size="22"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[Master Report]]></text> |
||||||
|
</staticText> |
||||||
|
</band> |
||||||
|
</title> |
||||||
|
<pageHeader> |
||||||
|
<band height="21"> |
||||||
|
<rectangle> |
||||||
|
<reportElement x="0" y="5" width="515" height="15" backcolor="#333333"/> |
||||||
|
<graphicElement pen="None"/> |
||||||
|
</rectangle> |
||||||
|
<staticText> |
||||||
|
<reportElement mode="Opaque" x="0" y="5" width="515" height="15" forecolor="#ffffff" backcolor="#333333"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[City List]]></text> |
||||||
|
</staticText> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="20" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
</band> |
||||||
|
</pageHeader> |
||||||
|
<detail> |
||||||
|
<band height="50"> |
||||||
|
<textField> |
||||||
|
<reportElement x="5" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[$F{city}]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<staticText> |
||||||
|
<reportElement isPrintRepeatedValues="false" x="110" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/> |
||||||
|
<textElement> |
||||||
|
<font reportFont="Arial_Bold"/> |
||||||
|
</textElement> |
||||||
|
<text><![CDATA[(continued)]]></text> |
||||||
|
</staticText> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="20" width="515" height="1" isPrintWhenDetailOverflows="true"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<subreport> |
||||||
|
<reportElement isPrintRepeatedValues="false" x="5" y="25" width="325" height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/> |
||||||
|
<subreportParameter name="City"> |
||||||
|
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression> |
||||||
|
</subreportParameter> |
||||||
|
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression> |
||||||
|
<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{ProductsSubReport}]]></subreportExpression> |
||||||
|
</subreport> |
||||||
|
<!--<subreport> |
||||||
|
<reportElement positionType="Float" x="335" y="25" width="175" height="20" isRemoveLineWhenBlank="true" backcolor="#99ccff"/> |
||||||
|
<subreportParameter name="City"> |
||||||
|
<subreportParameterExpression><![CDATA[$F{City}]]></subreportParameterExpression> |
||||||
|
</subreportParameter> |
||||||
|
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression> |
||||||
|
<subreportExpression class="java.lang.String"><![CDATA["AddressReport.jasper"]]></subreportExpression> |
||||||
|
</subreport> --> |
||||||
|
</band> |
||||||
|
</detail> |
||||||
|
<pageFooter> |
||||||
|
<band height="40"> |
||||||
|
<line> |
||||||
|
<reportElement x="0" y="10" width="515" height="1"/> |
||||||
|
<graphicElement/> |
||||||
|
</line> |
||||||
|
<textField> |
||||||
|
<reportElement x="200" y="20" width="80" height="15"/> |
||||||
|
<textElement textAlignment="Right"/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
<textField evaluationTime="Report"> |
||||||
|
<reportElement x="280" y="20" width="75" height="15"/> |
||||||
|
<textElement/> |
||||||
|
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression> |
||||||
|
</textField> |
||||||
|
</band> |
||||||
|
</pageFooter> |
||||||
|
</jasperReport> |
||||||
Loading…
Reference in new issue