001/* 002 * Copyright 2002-2016 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.portlet.handler; 018 019import java.util.Collections; 020import java.util.Enumeration; 021import java.util.Locale; 022import java.util.Map; 023import java.util.ResourceBundle; 024import javax.portlet.Portlet; 025import javax.portlet.PortletConfig; 026import javax.portlet.PortletContext; 027import javax.portlet.PortletException; 028import javax.xml.XMLConstants; 029import javax.xml.namespace.QName; 030 031import org.springframework.beans.BeansException; 032import org.springframework.beans.factory.BeanInitializationException; 033import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; 034import org.springframework.web.portlet.context.PortletConfigAware; 035import org.springframework.web.portlet.context.PortletContextAware; 036 037/** 038 * {@link org.springframework.beans.factory.config.BeanPostProcessor} 039 * that applies initialization and destruction callbacks to beans that 040 * implement the {@link javax.portlet.Portlet} interface. 041 * 042 * <p>After initialization of the bean instance, the Portlet {@code init} 043 * method will be called with a PortletConfig that contains the bean name 044 * of the Portlet and the PortletContext that it is running in. 045 * 046 * <p>Before destruction of the bean instance, the Portlet {@code destroy} 047 * will be called. 048 * 049 * <p><b>Note that this post-processor does not support Portlet initialization 050 * parameters.</b> Bean instances that implement the Portlet interface are 051 * supposed to be configured like any other Spring bean, that is, through 052 * constructor arguments or bean properties. 053 * 054 * <p>For reuse of a Portlet implementation in a plain Portlet container 055 * and as a bean in a Spring context, consider deriving from Spring's 056 * {@link org.springframework.web.portlet.GenericPortletBean} base class that 057 * applies Portlet initialization parameters as bean properties, supporting 058 * both the standard Portlet and the Spring bean initialization style. 059 * 060 * <p><b>Alternatively, consider wrapping a Portlet with Spring's 061 * {@link org.springframework.web.portlet.mvc.PortletWrappingController}.</b> 062 * This is particularly appropriate for existing Portlet classes, 063 * allowing to specify Portlet initialization parameters etc. 064 * 065 * @author Juergen Hoeller 066 * @author John A. Lewis 067 * @since 2.0 068 * @see javax.portlet.Portlet 069 * @see javax.portlet.PortletConfig 070 * @see SimplePortletHandlerAdapter 071 * @see org.springframework.web.portlet.GenericPortletBean 072 * @see org.springframework.web.portlet.mvc.PortletWrappingController 073 */ 074public class SimplePortletPostProcessor 075 implements DestructionAwareBeanPostProcessor, PortletContextAware, PortletConfigAware { 076 077 private boolean useSharedPortletConfig = true; 078 079 private PortletContext portletContext; 080 081 private PortletConfig portletConfig; 082 083 084 /** 085 * Set whether to use the shared PortletConfig object passed in 086 * through {@code setPortletConfig}, if available. 087 * <p>Default is "true". Turn this setting to "false" to pass in 088 * a mock PortletConfig object with the bean name as portlet name, 089 * holding the current PortletContext. 090 * @see #setPortletConfig 091 */ 092 public void setUseSharedPortletConfig(boolean useSharedPortletConfig) { 093 this.useSharedPortletConfig = useSharedPortletConfig; 094 } 095 096 @Override 097 public void setPortletContext(PortletContext portletContext) { 098 this.portletContext = portletContext; 099 } 100 101 @Override 102 public void setPortletConfig(PortletConfig portletConfig) { 103 this.portletConfig = portletConfig; 104 } 105 106 107 @Override 108 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 109 return bean; 110 } 111 112 @Override 113 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 114 if (bean instanceof Portlet) { 115 PortletConfig config = this.portletConfig; 116 if (config == null || !this.useSharedPortletConfig) { 117 config = new DelegatingPortletConfig(beanName, this.portletContext, this.portletConfig); 118 } 119 try { 120 ((Portlet) bean).init(config); 121 } 122 catch (PortletException ex) { 123 throw new BeanInitializationException("Portlet.init threw exception", ex); 124 } 125 } 126 return bean; 127 } 128 129 @Override 130 public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { 131 if (bean instanceof Portlet) { 132 ((Portlet) bean).destroy(); 133 } 134 } 135 136 @Override 137 public boolean requiresDestruction(Object bean) { 138 return (bean instanceof Portlet); 139 } 140 141 142 /** 143 * Internal implementation of the PortletConfig interface, to be passed 144 * to the wrapped servlet. 145 */ 146 private static class DelegatingPortletConfig implements PortletConfig { 147 148 private final String portletName; 149 150 private final PortletContext portletContext; 151 152 private final PortletConfig portletConfig; 153 154 public DelegatingPortletConfig(String portletName, PortletContext portletContext, PortletConfig portletConfig) { 155 this.portletName = portletName; 156 this.portletContext = portletContext; 157 this.portletConfig = portletConfig; 158 } 159 160 @Override 161 public String getPortletName() { 162 return this.portletName; 163 } 164 165 @Override 166 public PortletContext getPortletContext() { 167 return this.portletContext; 168 } 169 170 @Override 171 public String getInitParameter(String paramName) { 172 return null; 173 } 174 175 @Override 176 public Enumeration<String> getInitParameterNames() { 177 return Collections.enumeration(Collections.<String>emptySet()); 178 } 179 180 @Override 181 public ResourceBundle getResourceBundle(Locale locale) { 182 return (this.portletConfig != null ? this.portletConfig.getResourceBundle(locale) : null); 183 } 184 185 @Override 186 public Enumeration<String> getPublicRenderParameterNames() { 187 return Collections.enumeration(Collections.<String>emptySet()); 188 } 189 190 @Override 191 public String getDefaultNamespace() { 192 return XMLConstants.NULL_NS_URI; 193 } 194 195 @Override 196 public Enumeration<QName> getPublishingEventQNames() { 197 return Collections.enumeration(Collections.<QName>emptySet()); 198 } 199 200 @Override 201 public Enumeration<QName> getProcessingEventQNames() { 202 return Collections.enumeration(Collections.<QName>emptySet()); 203 } 204 205 @Override 206 public Enumeration<Locale> getSupportedLocales() { 207 return Collections.enumeration(Collections.<Locale>emptySet()); 208 } 209 210 @Override 211 public Map<String, String[]> getContainerRuntimeOptions() { 212 return (this.portletConfig != null ? this.portletConfig.getContainerRuntimeOptions() : null); 213 } 214 } 215 216}