/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.portals.bridges.frameworks.spring;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
import org.apache.commons.validator.Validator;
import org.apache.commons.validator.ValidatorException;
import org.apache.commons.validator.ValidatorResources;
import org.apache.commons.validator.ValidatorResults;
import org.apache.portals.bridges.frameworks.ExternalComponentSupport;
import org.apache.portals.bridges.frameworks.Lookup;
import org.apache.portals.bridges.frameworks.model.ModelBean;
import org.apache.portals.bridges.frameworks.model.PortletApplicationModel;
import org.apache.portals.bridges.frameworks.spring.ModelBeanImpl;
/**
* PortletApplicationModelImpl
*
* @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
* @version $Id: PortletApplicationModelImpl.java 564106 2007-08-09 06:02:51Z woonsan $
*/
public class PortletApplicationModelImpl implements PortletApplicationModel
{
/**
* Spring configuration: view to bean name map
*/
private static final String PORTLET_VIEW_BEAN_MAP = "portlet-view-bean-map";
/**
* Spring configuration: view to validator name map
*/
private static final String PORTLET_VIEW_VALIDATOR_MAP = "portlet-view-validator-map";
/**
* logical view to template map
*/
private static final String PORTLET_LOGICAL_VIEW_MAP = "portlet-views";
/**
* map for action forward definitions (success, failure)
*/
private static final String PORTLET_ACTION_FORWARD_MAP = "portlet-action-forward-map";
/**
* Spring Factory
*/
private XmlBeanFactory springFactory = null;
/**
* View Bean Map
*/
private Map viewBeanMap = null;
/**
* Validation resources
*/
private ValidatorResources validations = null;
/**
* View Validation Map
*/
private Map viewValidatorMap = null;
/**
* Map from logical views to templates
*/
private Map logicalViewMap = null;
/**
* Map from view:status to view
*/
private Map actionForwardMap = null;
private Map modelBeanMap = new HashMap();
private Map externalSupportMap = new HashMap();
private static Object semaphore = new Object();
private String springConfig;
private String validatorConfig = null;
public PortletApplicationModelImpl(String springConfig, String validatorConfig)
{
this.springConfig = springConfig;
this.validatorConfig = validatorConfig;
}
public void setExternalSupport(Map map)
{
this.externalSupportMap = map;
}
public void init(PortletConfig config)
throws PortletException
{
// load Spring
try
{
synchronized (semaphore)
{
if (null == springFactory)
{
springFactory = new XmlBeanFactory(new FileSystemResource(config.getPortletContext().getRealPath(springConfig)));
}
}
}
catch (Exception e)
{
throw new PortletException("Failed to load spring configuration.", e);
}
// load validator
synchronized (semaphore)
{
if (validatorConfig != null && null == validations)
{
InputStream is = null;
try
{
// TODO: support extensible user-defined validator resources
//is = this.getClass().getResourceAsStream("/org/apache/portals/bridges/velocity/validation/default-portlet-validation.xml");
is = config.getPortletContext().getResourceAsStream(validatorConfig);
validations = new ValidatorResources(is);
}
catch (Exception e)
{
throw new PortletException("Failed to load validator configuration.", e);
}
finally
{
// Make sure we close the input stream.
if (is != null)
{
try
{
is.close();
}
catch (Exception e)
{}
}
}
}
}
// Logical Views to templates
synchronized (semaphore)
{
logicalViewMap = (Map)springFactory.getBean(PORTLET_LOGICAL_VIEW_MAP);
if (logicalViewMap == null)
{
logicalViewMap = new HashMap();
}
}
// View to Validator Map
synchronized (semaphore)
{
viewValidatorMap = (Map)springFactory.getBean(PORTLET_VIEW_VALIDATOR_MAP);
if (viewValidatorMap == null)
{
viewValidatorMap = new HashMap();
}
}
// View to Bean Map
synchronized (semaphore)
{
viewBeanMap = (Map)springFactory.getBean(PORTLET_VIEW_BEAN_MAP);
if (viewBeanMap == null)
{
viewBeanMap = new HashMap();
}
}
// Action Forward map
synchronized (semaphore)
{
actionForwardMap = (Map)springFactory.getBean(PORTLET_ACTION_FORWARD_MAP);
if (actionForwardMap == null)
{
actionForwardMap = new HashMap();
}
}
}
public ModelBean getModelBean(String view)
{
ModelBean modelBean;
String beanName = (String)viewBeanMap.get(view);
if (beanName != null)
{
modelBean = (ModelBean)modelBeanMap.get(beanName);
if (modelBean == null)
{
BeanDefinition bd = springFactory.getBeanDefinition(beanName);
Object bean = springFactory.getBean(beanName);
if (bd == null || bean == null)
{
return new ModelBeanImpl(beanName, ModelBean.POJO);
}
String lookup = null;
boolean requiresExternalSupport = false;
PropertyValue propValue = bd.getPropertyValues().getPropertyValue("lookupKey");
if (propValue != null)
{
Object value = propValue.getValue();
if (value instanceof TypedStringValue)
{
lookup = ((TypedStringValue) value).getValue();
}
else
{
lookup = (String) value;
}
}
if (bean instanceof ExternalComponentSupport)
{
requiresExternalSupport = true;
}
modelBean = new ModelBeanImpl(beanName, ModelBean.POJO, lookup, requiresExternalSupport);
modelBeanMap.put(beanName, modelBean);
}
}
else
{
modelBean = new ModelBeanImpl(beanName, ModelBean.PREFS_MAP);
}
return modelBean;
}
public String getTemplate(String view)
{
return (String)logicalViewMap.get(view);
}
public Object lookupBean(ModelBean mb, String key)
{
Object bean = springFactory.getBean(mb.getBeanName());
if (bean != null)
{
if (mb.isRequiresExternalSupport())
{
ExternalComponentSupport ecs = (ExternalComponentSupport)bean;
ecs.setExternalSupport(externalSupportMap.get(mb.getBeanName()));
}
if (mb.isRequiresLookup())
{
((Lookup)bean).lookup(key);
}
}
return bean;
}
public Object createBean(ModelBean mb)
{
Object bean = springFactory.getBean(mb.getBeanName());
if (bean != null)
{
if (mb.isRequiresExternalSupport())
{
ExternalComponentSupport ecs = (ExternalComponentSupport)bean;
ecs.setExternalSupport(externalSupportMap.get(mb.getBeanName()));
}
}
return bean;
}
public Map createPrefsBean(ModelBean mb, Map original)
{
Map prefs = new HashMap();
Iterator it = original.entrySet().iterator();
while (it.hasNext())
{
Map.Entry entry = (Map.Entry)it.next();
String key = (String)entry.getKey();
Object value = entry.getValue();
if (value instanceof String)
{
prefs.put(key, value);
}
else if (value instanceof String[])
{
prefs.put(key, ((String[])value)[0]);
}
}
return prefs;
}
public Map validate(Object bean, String view, ResourceBundle bundle)
throws PortletException
{
Map result = new HashMap();
if (validations == null)
{
return result; // no validation configured
}
// Get the bean name from the bean-view map
String validatorFormName = (String)viewValidatorMap.get(view);
if (validatorFormName == null)
{
return result; // no validation for this bean
}
Validator validator = new Validator(validations, validatorFormName);
// Tell the validator which bean to validate against.
validator.setParameter(Validator.BEAN_PARAM, bean);
// Parameters used by our validators
validator.setParameter("java.util.Map", result);
validator.setParameter("java.util.ResourceBundle", bundle);
ValidatorResults results = null;
try
{
validator.setOnlyReturnErrors(true);
results = validator.validate();
if (results.isEmpty())
{
return result;
}
}
catch (ValidatorException e)
{
throw new PortletException("Error in processing validation: ", e);
}
return result;
}
public String getForward(String view, String status)
{
return (String)actionForwardMap.get(view + ":" + status);
}
public String getForward(String view)
{
return (String)actionForwardMap.get(view);
}
}