IN PROGRESS - issue SWF-720: Multiple checkboxes to Collection mapping

http://jira.springframework.org/browse/SWF-720
This commit is contained in:
Keith Donald
2008-06-30 23:35:15 +00:00
parent 2962d438be
commit 5bf58dd1f5
6 changed files with 77 additions and 13 deletions

View File

@@ -24,12 +24,15 @@ import org.springframework.util.ClassUtils;
*/
public class StringToClass extends StringToObject {
public StringToClass() {
private ClassLoader classLoader;
public StringToClass(ClassLoader classLoader) {
super(Class.class);
this.classLoader = classLoader;
}
public Object toObject(String string, Class objectClass) throws Exception {
return ClassUtils.forName(string);
return ClassUtils.forName(string, classLoader);
}
public String toString(Object object) throws Exception {

View File

@@ -20,6 +20,7 @@ import java.math.BigInteger;
import java.util.Date;
import java.util.Locale;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.convert.converters.StringToBigDecimal;
import org.springframework.binding.convert.converters.StringToBigInteger;
@@ -36,6 +37,7 @@ import org.springframework.binding.convert.converters.StringToLocale;
import org.springframework.binding.convert.converters.StringToLong;
import org.springframework.binding.convert.converters.StringToShort;
import org.springframework.core.enums.LabeledEnum;
import org.springframework.util.ClassUtils;
/**
* Default, local implementation of a conversion service. Will automatically register <i>from string</i> converters for
@@ -43,13 +45,15 @@ import org.springframework.core.enums.LabeledEnum;
*
* @author Keith Donald
*/
public class DefaultConversionService extends GenericConversionService {
public class DefaultConversionService extends GenericConversionService implements BeanClassLoaderAware {
/**
* A singleton shared instance. Should never be modified.
*/
private static DefaultConversionService SHARED_INSTANCE;
private ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
/**
* Creates a new default conversion service, installing the default converters.
*/
@@ -72,7 +76,7 @@ public class DefaultConversionService extends GenericConversionService {
addConverter(new StringToDouble());
addConverter(new StringToBigInteger());
addConverter(new StringToBigDecimal());
addConverter(new StringToClass());
addConverter(new StringToClass(classLoader));
addConverter(new StringToLocale());
addConverter(new StringToDate());
addConverter(new StringToLabeledEnum());
@@ -96,6 +100,10 @@ public class DefaultConversionService extends GenericConversionService {
addAlias("labeledEnum", LabeledEnum.class);
}
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
/**
* Returns the shared {@link DefaultConversionService} instance.
*/

View File

@@ -19,6 +19,7 @@ import java.util.Iterator;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.ConversionExecutor;
@@ -27,6 +28,7 @@ import org.springframework.binding.convert.service.DefaultConversionService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.conversation.ConversationManager;
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
import org.springframework.webflow.core.collection.AttributeMap;
@@ -56,7 +58,7 @@ import org.springframework.webflow.mvc.builder.MvcEnvironment;
* @author Keith Donald
* @author Erwin Vervaet
*/
class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, InitializingBean {
class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, BeanClassLoaderAware, InitializingBean {
private static final String ALWAYS_REDIRECT_ON_PAUSE = "alwaysRedirectOnPause";
@@ -76,6 +78,8 @@ class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, I
private MvcEnvironment environment;
private ClassLoader classLoader;
/**
* Sets the flow definition locator that will locate flow definitions needed for execution. Typically also a
* {@link FlowDefinitionRegistry}. Required.
@@ -123,6 +127,12 @@ class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, I
environment = MvcEnvironment.environmentFor(applicationContext);
}
// implement BeanClassLoaderAware
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
// implementing InitializingBean
public void afterPropertiesSet() throws Exception {
@@ -219,6 +229,16 @@ class FlowExecutorFactoryBean implements FactoryBean, ApplicationContextAware, I
}
private Class fromStringToClass(String name) {
return conversionService.getClassForAlias(name);
Class clazz = conversionService.getClassForAlias(name);
if (clazz != null) {
return clazz;
} else {
try {
return ClassUtils.forName(name, classLoader);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to load class '" + name + "'");
}
}
}
}

View File

@@ -19,6 +19,7 @@ import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.binding.convert.ConversionExecutor;
@@ -53,7 +54,7 @@ import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
* @author Keith Donald
* @author Jeremy Grelle
*/
class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
class FlowRegistryFactoryBean implements FactoryBean, BeanClassLoaderAware, InitializingBean {
private FlowLocation[] flowLocations;
@@ -65,6 +66,8 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
private FlowDefinitionRegistry parent;
private ClassLoader classLoader;
/**
* The definition registry produced by this factory bean.
*/
@@ -117,6 +120,12 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
this.parent = parent;
}
// implement BeanClassLoaderAware
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public void afterPropertiesSet() throws Exception {
flowResourceFactory = new FlowDefinitionResourceFactory(flowBuilderServices.getApplicationContext());
flowRegistry = new FlowDefinitionRegistryImpl();
@@ -236,20 +245,33 @@ class FlowRegistryFactoryBean implements FactoryBean, InitializingBean {
}
}
private Class fromStringToClass(String type) {
return flowBuilderServices.getConversionService().getClassForAlias(type);
private Class fromStringToClass(String name) {
Class clazz = flowBuilderServices.getConversionService().getClassForAlias(name);
if (clazz != null) {
return clazz;
} else {
return loadClass(name);
}
}
private Class loadClass(String name) {
try {
return ClassUtils.forName(name, classLoader);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to load class '" + name + "'");
}
}
private FlowDefinition buildFlowDefinition(FlowBuilderInfo builderInfo) {
try {
Class flowBuilderClass = ClassUtils.forName(builderInfo.getClassName());
Class flowBuilderClass = loadClass(builderInfo.getClassName());
FlowBuilder builder = (FlowBuilder) flowBuilderClass.newInstance();
AttributeMap flowAttributes = getFlowAttributes(builderInfo.getAttributes());
FlowBuilderContext builderContext = new FlowBuilderContextImpl(builderInfo.getId(), flowAttributes,
flowRegistry, flowBuilderServices);
FlowAssembler assembler = new FlowAssembler(builder, builderContext);
return assembler.assembleFlow();
} catch (ClassNotFoundException e) {
} catch (IllegalArgumentException e) {
throw new FlowDefinitionConstructionException(builderInfo.getId(), e);
} catch (InstantiationException e) {
throw new FlowDefinitionConstructionException(builderInfo.getId(), e);

View File

@@ -43,6 +43,7 @@ import org.springframework.context.support.ReloadableResourceBundleMessageSource
import org.springframework.core.JdkVersion;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestScope;
@@ -910,7 +911,17 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
}
private Class toClass(String name) {
return getLocalContext().getConversionService().getClassForAlias(name);
Class clazz = getLocalContext().getConversionService().getClassForAlias(name);
if (clazz != null) {
return clazz;
} else {
try {
ClassLoader classLoader = getLocalContext().getApplicationContext().getClassLoader();
return ClassUtils.forName(name, classLoader);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Unable to load class '" + name + "'");
}
}
}
private static class FlowRelativeResourceLoader implements ResourceLoader {

View File

@@ -66,7 +66,7 @@ public class BindingModel extends AbstractErrors {
* @param objectName the name of the bound model object
* @param boundObject the bound model object
* @param expressionParser the expression parser used to access model object properties
* @param formatterRegistry the formatter registry used to access formatters for formatting properties
* @param conversionService the registry used to access converters for formatting properties
* @param messageContext the message context containing flow messages to display
*/
public BindingModel(String objectName, Object boundObject, ExpressionParser expressionParser,