Drop Portlet MVC support
This commit also removes the corresponding deprecated Servlet MVC variant and updates DispatcherServlet.properties to point to RequestMappingHandlerMapping/Adapter by default. Issue: SPR-14129
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -27,8 +27,7 @@ import org.springframework.util.StringUtils;
|
||||
* of specified config locations. Serves as base class for XML-based application
|
||||
* context implementations such as {@link ClassPathXmlApplicationContext} and
|
||||
* {@link FileSystemXmlApplicationContext}, as well as
|
||||
* {@link org.springframework.web.context.support.XmlWebApplicationContext} and
|
||||
* {@link org.springframework.web.portlet.context.XmlPortletApplicationContext}.
|
||||
* {@link org.springframework.web.context.support.XmlWebApplicationContext}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -27,16 +27,14 @@ import org.springframework.util.Assert;
|
||||
* Implementation of {@link java.util.Map} for use when building model data for use
|
||||
* with UI tools. Supports chained calls and generation of model attribute names.
|
||||
*
|
||||
* <p>This class serves as generic model holder for both Servlet and Portlet MVC,
|
||||
* but is not tied to either of those. Check out the {@link Model} interface for
|
||||
* a Java-5-based interface variant that serves the same purpose.
|
||||
* <p>This class serves as generic model holder for Servlet MVC but is not tied to it.
|
||||
* Check out the {@link Model} interface for an interface variant.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see Conventions#getVariableName
|
||||
* @see org.springframework.web.servlet.ModelAndView
|
||||
* @see org.springframework.web.portlet.ModelAndView
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ModelMap extends LinkedHashMap<String, Object> {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -92,8 +92,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* <p>This generic data binder can be used in any kind of environment.
|
||||
* It is typically used by Spring web MVC controllers, via the web-specific
|
||||
* subclasses {@link org.springframework.web.bind.ServletRequestDataBinder}
|
||||
* and {@link org.springframework.web.portlet.bind.PortletRequestDataBinder}.
|
||||
* subclass {@link org.springframework.web.bind.ServletRequestDataBinder}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -18,15 +18,14 @@ package org.springframework.core.io;
|
||||
|
||||
/**
|
||||
* Extended interface for a resource that is loaded from an enclosing
|
||||
* 'context', e.g. from a {@link javax.servlet.ServletContext} or a
|
||||
* {@link javax.portlet.PortletContext} but also from plain classpath paths
|
||||
* or relative file system paths (specified without an explicit prefix,
|
||||
* hence applying relative to the local {@link ResourceLoader}'s context).
|
||||
* 'context', e.g. from a {@link javax.servlet.ServletContext} but also
|
||||
* from plain classpath paths or relative file system paths (specified
|
||||
* without an explicit prefix, hence applying relative to the local
|
||||
* {@link ResourceLoader}'s context).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5
|
||||
* @see org.springframework.web.context.support.ServletContextResource
|
||||
* @see org.springframework.web.portlet.context.PortletContextResource
|
||||
*/
|
||||
public interface ContextResource extends Resource {
|
||||
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.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 MockClientDataRequest implements ActionRequest {
|
||||
|
||||
/**
|
||||
* Create a new MockActionRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @see org.springframework.mock.web.portlet.MockPortalContext
|
||||
* @see org.springframework.mock.web.portlet.MockPortletContext
|
||||
*/
|
||||
public MockActionRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockActionRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @param actionName the name of the action to trigger
|
||||
*/
|
||||
public MockActionRequest(String actionName) {
|
||||
super();
|
||||
setParameter(ActionRequest.ACTION_NAME, actionName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getLifecyclePhase() {
|
||||
return ACTION_PHASE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.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;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.ActionResponse} interface.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MockActionResponse extends MockStateAwareResponse implements ActionResponse {
|
||||
|
||||
private boolean redirectAllowed = true;
|
||||
|
||||
private String redirectedUrl;
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setWindowState(WindowState windowState) throws WindowStateException {
|
||||
if (this.redirectedUrl != null) {
|
||||
throw new IllegalStateException("Cannot set WindowState after sendRedirect has been called");
|
||||
}
|
||||
super.setWindowState(windowState);
|
||||
this.redirectAllowed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletMode(PortletMode portletMode) throws PortletModeException {
|
||||
if (this.redirectedUrl != null) {
|
||||
throw new IllegalStateException("Cannot set PortletMode after sendRedirect has been called");
|
||||
}
|
||||
super.setPortletMode(portletMode);
|
||||
this.redirectAllowed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameters(Map<String, String[]> parameters) {
|
||||
if (this.redirectedUrl != null) {
|
||||
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called");
|
||||
}
|
||||
super.setRenderParameters(parameters);
|
||||
this.redirectAllowed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameter(String key, String value) {
|
||||
if (this.redirectedUrl != null) {
|
||||
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called");
|
||||
}
|
||||
super.setRenderParameter(key, value);
|
||||
this.redirectAllowed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameter(String key, String[] values) {
|
||||
if (this.redirectedUrl != null) {
|
||||
throw new IllegalStateException("Cannot set render parameters after sendRedirect has been called");
|
||||
}
|
||||
super.setRenderParameter(key, values);
|
||||
this.redirectAllowed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException {
|
||||
if (!this.redirectAllowed) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot call sendRedirect after windowState, portletMode, or renderParameters have been set");
|
||||
}
|
||||
Assert.notNull(location, "Redirect URL must not be null");
|
||||
this.redirectedUrl = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location, String renderUrlParamName) throws IOException {
|
||||
sendRedirect(location);
|
||||
if (renderUrlParamName != null) {
|
||||
setRenderParameter(renderUrlParamName, location);
|
||||
}
|
||||
}
|
||||
|
||||
public String getRedirectedUrl() {
|
||||
return this.redirectedUrl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.portlet.BaseURL;
|
||||
import javax.portlet.PortletSecurityException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.BaseURL} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class MockBaseURL implements BaseURL {
|
||||
|
||||
public static final String URL_TYPE_RENDER = "render";
|
||||
|
||||
public static final String URL_TYPE_ACTION = "action";
|
||||
|
||||
private static final String ENCODING = "UTF-8";
|
||||
|
||||
|
||||
protected final Map<String, String[]> parameters = new LinkedHashMap<String, String[]>();
|
||||
|
||||
private boolean secure = false;
|
||||
|
||||
private final Map<String, String[]> properties = new LinkedHashMap<String, String[]>();
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// BaseURL methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
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});
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParameters(Map<String, String[]> parameters) {
|
||||
Assert.notNull(parameters, "Parameters Map must not be null");
|
||||
this.parameters.clear();
|
||||
this.parameters.putAll(parameters);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
return Collections.unmodifiableMap(this.parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSecure(boolean secure) throws PortletSecurityException {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writer out) throws IOException {
|
||||
out.write(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writer out, boolean escapeXML) throws IOException {
|
||||
out.write(toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProperty(String key, String value) {
|
||||
String[] values = this.properties.get(key);
|
||||
if (values != null) {
|
||||
this.properties.put(key, StringUtils.addStringToArray(values, value));
|
||||
}
|
||||
else {
|
||||
this.properties.put(key, new String[] {value});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(String key, String value) {
|
||||
this.properties.put(key, new String[] {value});
|
||||
}
|
||||
|
||||
public Map<String, String[]> getProperties() {
|
||||
return Collections.unmodifiableMap(this.properties);
|
||||
}
|
||||
|
||||
|
||||
protected String encodeParameter(String name, String value) {
|
||||
try {
|
||||
return URLEncoder.encode(name, ENCODING) + "=" + URLEncoder.encode(value, ENCODING);
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected 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 ? ";" : "").append(URLEncoder.encode(name, ENCODING)).append("=")
|
||||
.append(URLEncoder.encode(values[i], ENCODING));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.CacheControl;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.CacheControl} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockCacheControl implements CacheControl {
|
||||
|
||||
private int expirationTime = 0;
|
||||
|
||||
private boolean publicScope = false;
|
||||
|
||||
private String etag;
|
||||
|
||||
private boolean useCachedContent = false;
|
||||
|
||||
|
||||
@Override
|
||||
public int getExpirationTime() {
|
||||
return this.expirationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpirationTime(int time) {
|
||||
this.expirationTime = time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPublicScope() {
|
||||
return this.publicScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPublicScope(boolean publicScope) {
|
||||
this.publicScope = publicScope;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getETag() {
|
||||
return this.etag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setETag(String token) {
|
||||
this.etag = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useCachedContent() {
|
||||
return this.useCachedContent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUseCachedContent(boolean useCachedContent) {
|
||||
this.useCachedContent = useCachedContent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.ClientDataRequest;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.ClientDataRequest} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockClientDataRequest extends MockPortletRequest implements ClientDataRequest {
|
||||
|
||||
private String characterEncoding;
|
||||
|
||||
private byte[] content;
|
||||
|
||||
private String contentType;
|
||||
|
||||
private String method;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockClientDataRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @see org.springframework.mock.web.portlet.MockPortalContext
|
||||
* @see org.springframework.mock.web.portlet.MockPortletContext
|
||||
*/
|
||||
public MockClientDataRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockClientDataRequest with a default {@link MockPortalContext}.
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
*/
|
||||
public MockClientDataRequest(PortletContext portletContext) {
|
||||
super(portletContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockClientDataRequest.
|
||||
* @param portalContext the PortalContext that the request runs in
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
*/
|
||||
public MockClientDataRequest(PortalContext portalContext, PortletContext portletContext) {
|
||||
super(portalContext, portletContext);
|
||||
}
|
||||
|
||||
|
||||
public void setContent(byte[] content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getPortletInputStream() throws IOException {
|
||||
if (this.content != null) {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String characterEncoding) {
|
||||
this.characterEncoding = characterEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return this.characterEncoding;
|
||||
}
|
||||
|
||||
public void setContentType(String contentType) {
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength() {
|
||||
return (this.content != null ? content.length : -1);
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Serializable;
|
||||
import javax.portlet.Event;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.Event} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see MockEventRequest
|
||||
*/
|
||||
public class MockEvent implements Event {
|
||||
|
||||
private final QName name;
|
||||
|
||||
private final Serializable value;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockEvent with the given name.
|
||||
* @param name the name of the event
|
||||
*/
|
||||
public MockEvent(QName name) {
|
||||
this.name = name;
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockEvent with the given name and value.
|
||||
* @param name the name of the event
|
||||
* @param value the associated payload of the event
|
||||
*/
|
||||
public MockEvent(QName name, Serializable value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockEvent with the given name.
|
||||
* @param name the name of the event
|
||||
*/
|
||||
public MockEvent(String name) {
|
||||
this.name = new QName(name);
|
||||
this.value = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockEvent with the given name and value.
|
||||
* @param name the name of the event
|
||||
* @param value the associated payload of the event
|
||||
*/
|
||||
public MockEvent(String name, Serializable value) {
|
||||
this.name = new QName(name);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QName getQName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name.getLocalPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Serializable getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Event;
|
||||
import javax.portlet.EventRequest;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.EventRequest} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockEventRequest extends MockPortletRequest implements EventRequest {
|
||||
|
||||
private final Event event;
|
||||
|
||||
private String method;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockEventRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @param event the event that this request wraps
|
||||
* @see MockEvent
|
||||
*/
|
||||
public MockEventRequest(Event event) {
|
||||
super();
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockEventRequest with a default {@link MockPortalContext}.
|
||||
* @param event the event that this request wraps
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
* @see MockEvent
|
||||
*/
|
||||
public MockEventRequest(Event event, PortletContext portletContext) {
|
||||
super(portletContext);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockEventRequest.
|
||||
* @param event the event that this request wraps
|
||||
* @param portalContext the PortletContext that the request runs in
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
*/
|
||||
public MockEventRequest(Event event, PortalContext portalContext, PortletContext portletContext) {
|
||||
super(portalContext, portletContext);
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getLifecyclePhase() {
|
||||
return EVENT_PHASE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Event getEvent() {
|
||||
return this.event;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return this.method;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.EventRequest;
|
||||
import javax.portlet.EventResponse;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.EventResponse} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockEventResponse extends MockStateAwareResponse implements EventResponse {
|
||||
|
||||
@Override
|
||||
public void setRenderParameters(EventRequest request) {
|
||||
setRenderParameters(request.getParameterMap());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import javax.portlet.CacheControl;
|
||||
import javax.portlet.MimeResponse;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletURL;
|
||||
import javax.portlet.ResourceURL;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.MimeResponse} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockMimeResponse extends MockPortletResponse implements MimeResponse {
|
||||
|
||||
private PortletRequest request;
|
||||
|
||||
private String contentType;
|
||||
|
||||
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(1024);
|
||||
|
||||
private final CacheControl cacheControl = new MockCacheControl();
|
||||
|
||||
private boolean committed;
|
||||
|
||||
private String includedUrl;
|
||||
|
||||
private String forwardedUrl;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockMimeResponse with a default {@link MockPortalContext}.
|
||||
* @see org.springframework.mock.web.portlet.MockPortalContext
|
||||
*/
|
||||
public MockMimeResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockMimeResponse.
|
||||
* @param portalContext the PortalContext defining the supported
|
||||
* PortletModes and WindowStates
|
||||
*/
|
||||
public MockMimeResponse(PortalContext portalContext) {
|
||||
super(portalContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockMimeResponse.
|
||||
* @param portalContext the PortalContext defining the supported
|
||||
* PortletModes and WindowStates
|
||||
* @param request the corresponding render/resource request that this response
|
||||
* is being generated for
|
||||
*/
|
||||
public MockMimeResponse(PortalContext portalContext, PortletRequest request) {
|
||||
super(portalContext);
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// RenderResponse methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void setContentType(String contentType) {
|
||||
if (this.request != null) {
|
||||
Enumeration<String> supportedTypes = this.request.getResponseContentTypes();
|
||||
if (!CollectionUtils.contains(supportedTypes, contentType)) {
|
||||
throw new IllegalArgumentException("Content type [" + contentType + "] not in supported list: " +
|
||||
Collections.list(supportedTypes));
|
||||
}
|
||||
}
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
public void setCharacterEncoding(String characterEncoding) {
|
||||
this.characterEncoding = characterEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding() {
|
||||
return this.characterEncoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBufferSize(int bufferSize) {
|
||||
this.bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSize() {
|
||||
return this.bufferSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBuffer() {
|
||||
if (this.writer != null) {
|
||||
this.writer.flush();
|
||||
}
|
||||
try {
|
||||
this.outputStream.flush();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Could not flush OutputStream: " + ex.getMessage());
|
||||
}
|
||||
this.committed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommitted() {
|
||||
return this.committed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
resetBuffer();
|
||||
this.characterEncoding = null;
|
||||
this.contentType = null;
|
||||
this.locale = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getPortletOutputStream() throws IOException {
|
||||
return this.outputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletURL createRenderURL() {
|
||||
return new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_RENDER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletURL createActionURL() {
|
||||
return new MockPortletURL(getPortalContext(), MockPortletURL.URL_TYPE_ACTION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceURL createResourceURL() {
|
||||
return new MockResourceURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheControl getCacheControl() {
|
||||
return this.cacheControl;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Methods for MockPortletRequestDispatcher
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
public void setIncludedUrl(String includedUrl) {
|
||||
this.includedUrl = includedUrl;
|
||||
}
|
||||
|
||||
public String getIncludedUrl() {
|
||||
return this.includedUrl;
|
||||
}
|
||||
|
||||
public void setForwardedUrl(String forwardedUrl) {
|
||||
this.forwardedUrl = forwardedUrl;
|
||||
}
|
||||
|
||||
public String getForwardedUrl() {
|
||||
return this.forwardedUrl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
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
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see org.springframework.mock.web.MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest {
|
||||
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles =
|
||||
new LinkedMultiValueMap<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.add(file.getName(), file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> getFileNames() {
|
||||
return this.multipartFiles.keySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return this.multipartFiles.toSingleValueMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>(this.multipartFiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMultipartContentType(String paramOrFileName) {
|
||||
MultipartFile file = getFile(paramOrFileName);
|
||||
if (file != null) {
|
||||
return file.getContentType();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPortalInfo() {
|
||||
return "MockPortal/1.0";
|
||||
}
|
||||
|
||||
public void setProperty(String name, String value) {
|
||||
this.properties.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return this.properties.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getPropertyNames() {
|
||||
return Collections.enumeration(this.properties.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<PortletMode> getSupportedPortletModes() {
|
||||
return Collections.enumeration(this.portletModes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<WindowState> getSupportedWindowStates() {
|
||||
return Collections.enumeration(this.windowStates);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
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>();
|
||||
|
||||
private final Set<String> publicRenderParameterNames = new LinkedHashSet<String>();
|
||||
|
||||
private String defaultNamespace = XMLConstants.NULL_NS_URI;
|
||||
|
||||
private final Set<QName> publishingEventQNames = new LinkedHashSet<QName>();
|
||||
|
||||
private final Set<QName> processingEventQNames = new LinkedHashSet<QName>();
|
||||
|
||||
private final Set<Locale> supportedLocales = new LinkedHashSet<Locale>();
|
||||
|
||||
private final Map<String, String[]> containerRuntimeOptions = 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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getPortletName() {
|
||||
return this.portletName;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
return this.initParameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(this.initParameters.keySet());
|
||||
}
|
||||
|
||||
public void addPublicRenderParameterName(String name) {
|
||||
this.publicRenderParameterNames.add(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getPublicRenderParameterNames() {
|
||||
return Collections.enumeration(this.publicRenderParameterNames);
|
||||
}
|
||||
|
||||
public void setDefaultNamespace(String defaultNamespace) {
|
||||
this.defaultNamespace = defaultNamespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultNamespace() {
|
||||
return this.defaultNamespace;
|
||||
}
|
||||
|
||||
public void addPublishingEventQName(QName name) {
|
||||
this.publishingEventQNames.add(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<QName> getPublishingEventQNames() {
|
||||
return Collections.enumeration(this.publishingEventQNames);
|
||||
}
|
||||
|
||||
public void addProcessingEventQName(QName name) {
|
||||
this.processingEventQNames.add(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<QName> getProcessingEventQNames() {
|
||||
return Collections.enumeration(this.processingEventQNames);
|
||||
}
|
||||
|
||||
public void addSupportedLocale(Locale locale) {
|
||||
this.supportedLocales.add(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<Locale> getSupportedLocales() {
|
||||
return Collections.enumeration(this.supportedLocales);
|
||||
}
|
||||
|
||||
public void addContainerRuntimeOption(String key, String value) {
|
||||
this.containerRuntimeOptions.put(key, new String[] {value});
|
||||
}
|
||||
|
||||
public void addContainerRuntimeOption(String key, String[] values) {
|
||||
this.containerRuntimeOptions.put(key, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getContainerRuntimeOptions() {
|
||||
return Collections.unmodifiableMap(this.containerRuntimeOptions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,298 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.activation.FileTypeMap;
|
||||
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";
|
||||
|
||||
private Set<String> containerRuntimeOptions = new LinkedHashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerInfo() {
|
||||
return "MockPortal/1.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletRequestDispatcher getRequestDispatcher(String path) {
|
||||
if (!path.startsWith("/")) {
|
||||
throw new IllegalArgumentException(
|
||||
"PortletRequestDispatcher path at PortletContext level must start with '/'");
|
||||
}
|
||||
return new MockPortletRequestDispatcher(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletRequestDispatcher getNamedDispatcher(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType(String filePath) {
|
||||
return MimeTypeResolver.getMimeType(filePath);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name) {
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.attributes.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value) {
|
||||
if (value != null) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
else {
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
Assert.notNull(name, "Parameter name must not be null");
|
||||
return this.initParameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(this.initParameters.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message) {
|
||||
logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message, Throwable t) {
|
||||
logger.info(message, t);
|
||||
}
|
||||
|
||||
public void setPortletContextName(String portletContextName) {
|
||||
this.portletContextName = portletContextName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPortletContextName() {
|
||||
return this.portletContextName;
|
||||
}
|
||||
|
||||
public void addContainerRuntimeOption(String key) {
|
||||
this.containerRuntimeOptions.add(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getContainerRuntimeOptions() {
|
||||
return Collections.enumeration(this.containerRuntimeOptions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner factory class used to just introduce a Java Activation Framework
|
||||
* dependency when actually asked to resolve a MIME type.
|
||||
*/
|
||||
private static class MimeTypeResolver {
|
||||
|
||||
public static String getMimeType(String filePath) {
|
||||
return FileTypeMap.getDefaultFileTypeMap().getContentType(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly(String key) {
|
||||
Assert.notNull(key, "Key must not be null");
|
||||
return this.readOnly.contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, String value) throws ReadOnlyException {
|
||||
setValues(key, new String[] {value});
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getNames() {
|
||||
return Collections.enumeration(this.preferences.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getMap() {
|
||||
return Collections.unmodifiableMap(this.preferences);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void store() throws IOException, ValidatorException {
|
||||
if (this.preferencesValidator != null) {
|
||||
this.preferencesValidator.validate(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,569 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.LinkedHashSet;
|
||||
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 javax.servlet.http.Cookie;
|
||||
|
||||
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;
|
||||
|
||||
private String windowID;
|
||||
|
||||
private Cookie[] cookies;
|
||||
|
||||
private final Set<String> publicParameterNames = new HashSet<String>();
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
this.attributes.put(LIFECYCLE_PHASE, getLifecyclePhase());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Lifecycle methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Return the Portlet 2.0 lifecycle id for the current phase.
|
||||
*/
|
||||
protected String getLifecyclePhase() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public boolean isWindowStateAllowed(WindowState windowState) {
|
||||
return CollectionUtils.contains(this.portalContext.getSupportedWindowStates(), windowState);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletMode getPortletMode() {
|
||||
return this.portletMode;
|
||||
}
|
||||
|
||||
public void setWindowState(WindowState windowState) {
|
||||
Assert.notNull(windowState, "WindowState must not be null");
|
||||
this.windowState = windowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindowState() {
|
||||
return this.windowState;
|
||||
}
|
||||
|
||||
public void setPreferences(PortletPreferences preferences) {
|
||||
Assert.notNull(preferences, "PortletPreferences must not be null");
|
||||
this.portletPreferences = preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletPreferences getPreferences() {
|
||||
return this.portletPreferences;
|
||||
}
|
||||
|
||||
public void setSession(PortletSession session) {
|
||||
this.session = session;
|
||||
if (session instanceof MockPortletSession) {
|
||||
MockPortletSession mockSession = ((MockPortletSession) session);
|
||||
mockSession.access();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletSession getPortletSession() {
|
||||
return getPortletSession(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String key) {
|
||||
Assert.notNull(key, "Property key must not be null");
|
||||
List<String> list = this.properties.get(key);
|
||||
return (list != null && list.size() > 0 ? list.get(0) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getProperties(String key) {
|
||||
Assert.notNull(key, "property key must not be null");
|
||||
return Collections.enumeration(this.properties.get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getPropertyNames() {
|
||||
return Collections.enumeration(this.properties.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortalContext getPortalContext() {
|
||||
return this.portalContext;
|
||||
}
|
||||
|
||||
public void setAuthType(String authType) {
|
||||
this.authType = authType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthType() {
|
||||
return this.authType;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
public void setRemoteUser(String remoteUser) {
|
||||
this.remoteUser = remoteUser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteUser() {
|
||||
return this.remoteUser;
|
||||
}
|
||||
|
||||
public void setUserPrincipal(Principal userPrincipal) {
|
||||
this.userPrincipal = userPrincipal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return this.userPrincipal;
|
||||
}
|
||||
|
||||
public void addUserRole(String role) {
|
||||
this.userRoles.add(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return this.userRoles.contains(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name) {
|
||||
checkActive();
|
||||
return this.attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
checkActive();
|
||||
return Collections.enumeration(new LinkedHashSet<String>(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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String name) {
|
||||
String[] arr = this.parameters.get(name);
|
||||
return (arr != null && arr.length > 0 ? arr[0] : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
return Collections.enumeration(this.parameters.keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String name) {
|
||||
return this.parameters.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
return Collections.unmodifiableMap(this.parameters);
|
||||
}
|
||||
|
||||
public void setSecure(boolean secure) {
|
||||
this.secure = secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return this.secure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value) {
|
||||
checkActive();
|
||||
if (value != null) {
|
||||
this.attributes.put(name, value);
|
||||
}
|
||||
else {
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
checkActive();
|
||||
this.attributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestedSessionId() {
|
||||
PortletSession session = this.getPortletSession();
|
||||
return (session != null ? session.getId() : null);
|
||||
}
|
||||
|
||||
public void setRequestedSessionIdValid(boolean requestedSessionIdValid) {
|
||||
this.requestedSessionIdValid = requestedSessionIdValid;
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResponseContentType() {
|
||||
return this.responseContentTypes.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return this.locales.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<Locale> getLocales() {
|
||||
return Collections.enumeration(this.locales);
|
||||
}
|
||||
|
||||
public void setScheme(String scheme) {
|
||||
this.scheme = scheme;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme() {
|
||||
return this.scheme;
|
||||
}
|
||||
|
||||
public void setServerName(String serverName) {
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName() {
|
||||
return this.serverName;
|
||||
}
|
||||
|
||||
public void setServerPort(int serverPort) {
|
||||
this.serverPort = serverPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPort() {
|
||||
return this.serverPort;
|
||||
}
|
||||
|
||||
public void setWindowID(String windowID) {
|
||||
this.windowID = windowID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWindowID() {
|
||||
return this.windowID;
|
||||
}
|
||||
|
||||
public void setCookies(Cookie... cookies) {
|
||||
this.cookies = cookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie[] getCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getPrivateParameterMap() {
|
||||
if (!this.publicParameterNames.isEmpty()) {
|
||||
Map<String, String[]> filtered = new LinkedHashMap<String, String[]>();
|
||||
for (String key : this.parameters.keySet()) {
|
||||
if (!this.publicParameterNames.contains(key)) {
|
||||
filtered.put(key, this.parameters.get(key));
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
else {
|
||||
return Collections.unmodifiableMap(this.parameters);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getPublicParameterMap() {
|
||||
if (!this.publicParameterNames.isEmpty()) {
|
||||
Map<String, String[]> filtered = new LinkedHashMap<String, String[]>();
|
||||
for (String key : this.parameters.keySet()) {
|
||||
if (this.publicParameterNames.contains(key)) {
|
||||
filtered.put(key, this.parameters.get(key));
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerPublicParameter(String name) {
|
||||
this.publicParameterNames.add(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.PortletRequest;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.portlet.PortletResponse;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void include(RenderRequest request, RenderResponse response) throws PortletException, IOException {
|
||||
include((PortletRequest) request, (PortletResponse) response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(PortletRequest request, PortletResponse response) throws PortletException, IOException {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
if (!(response instanceof MockMimeResponse)) {
|
||||
throw new IllegalArgumentException("MockPortletRequestDispatcher requires MockMimeResponse");
|
||||
}
|
||||
((MockMimeResponse) response).setIncludedUrl(this.url);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("MockPortletRequestDispatcher: including URL [" + this.url + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forward(PortletRequest request, PortletResponse response) throws PortletException, IOException {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
Assert.notNull(response, "Response must not be null");
|
||||
if (!(response instanceof MockMimeResponse)) {
|
||||
throw new IllegalArgumentException("MockPortletRequestDispatcher requires MockMimeResponse");
|
||||
}
|
||||
((MockMimeResponse) response).setForwardedUrl(this.url);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("MockPortletRequestDispatcher: forwarding to URL [" + this.url + "]");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
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[]>();
|
||||
|
||||
private String namespace = "";
|
||||
|
||||
private final Set<Cookie> cookies = new LinkedHashSet<Cookie>();
|
||||
|
||||
private final Map<String, Element[]> xmlProperties = new LinkedHashMap<String, Element[]>();
|
||||
|
||||
private Document xmlDocument;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
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});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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<String> getPropertyNames() {
|
||||
return Collections.unmodifiableSet(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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeURL(String path) {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProperty(Cookie cookie) {
|
||||
Assert.notNull(cookie, "Cookie must not be null");
|
||||
this.cookies.add(cookie);
|
||||
}
|
||||
|
||||
public Cookie[] getCookies() {
|
||||
return this.cookies.toArray(new Cookie[this.cookies.size()]);
|
||||
}
|
||||
|
||||
public Cookie getCookie(String name) {
|
||||
Assert.notNull(name, "Cookie name must not be null");
|
||||
for (Cookie cookie : this.cookies) {
|
||||
if (name.equals(cookie.getName())) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addProperty(String key, Element value) {
|
||||
Assert.notNull(key, "Property key must not be null");
|
||||
Element[] oldArr = this.xmlProperties.get(key);
|
||||
if (oldArr != null) {
|
||||
Element[] newArr = new Element[oldArr.length + 1];
|
||||
System.arraycopy(oldArr, 0, newArr, 0, oldArr.length);
|
||||
newArr[oldArr.length] = value;
|
||||
this.xmlProperties.put(key, newArr);
|
||||
}
|
||||
else {
|
||||
this.xmlProperties.put(key, new Element[] {value});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getXmlPropertyNames() {
|
||||
return Collections.unmodifiableSet(this.xmlProperties.keySet());
|
||||
}
|
||||
|
||||
public Element getXmlProperty(String key) {
|
||||
Assert.notNull(key, "Property key must not be null");
|
||||
Element[] arr = this.xmlProperties.get(key);
|
||||
return (arr != null && arr.length > 0 ? arr[0] : null);
|
||||
}
|
||||
|
||||
public Element[] getXmlProperties(String key) {
|
||||
Assert.notNull(key, "Property key must not be null");
|
||||
return this.xmlProperties.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Element createElement(String tagName) throws DOMException {
|
||||
if (this.xmlDocument == null) {
|
||||
try {
|
||||
this.xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
}
|
||||
catch (ParserConfigurationException ex) {
|
||||
throw new DOMException(DOMException.INVALID_STATE_ERR, ex.toString());
|
||||
}
|
||||
}
|
||||
return this.xmlDocument.createElement(tagName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.servlet.http.HttpSessionBindingEvent;
|
||||
import javax.servlet.http.HttpSessionBindingListener;
|
||||
|
||||
import org.springframework.mock.web.MockHttpSession;
|
||||
|
||||
/**
|
||||
* 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 LinkedHashMap<String, Object>();
|
||||
|
||||
private final Map<String, Object> applicationAttributes = new LinkedHashMap<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());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name) {
|
||||
return this.portletAttributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.portletAttributes.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames(int scope) {
|
||||
if (scope == PortletSession.PORTLET_SCOPE) {
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.portletAttributes.keySet()));
|
||||
}
|
||||
else if (scope == PortletSession.APPLICATION_SCOPE) {
|
||||
return Collections.enumeration(new LinkedHashSet<String>(this.applicationAttributes.keySet()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCreationTime() {
|
||||
return this.creationTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public void access() {
|
||||
this.lastAccessedTime = System.currentTimeMillis();
|
||||
setNew(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastAccessedTime() {
|
||||
return this.lastAccessedTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxInactiveInterval() {
|
||||
return this.maxInactiveInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all of this session's attributes.
|
||||
*/
|
||||
public void clearAttributes() {
|
||||
doClearAttributes(this.portletAttributes);
|
||||
doClearAttributes(this.applicationAttributes);
|
||||
}
|
||||
|
||||
protected void doClearAttributes(Map<String, Object> attributes) {
|
||||
for (Iterator<Map.Entry<String, Object>> it = attributes.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
String name = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
it.remove();
|
||||
if (value instanceof HttpSessionBindingListener) {
|
||||
((HttpSessionBindingListener) value).valueUnbound(
|
||||
new HttpSessionBindingEvent(new MockHttpSession(), name, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidate() {
|
||||
this.invalid = true;
|
||||
clearAttributes();
|
||||
}
|
||||
|
||||
public boolean isInvalid() {
|
||||
return this.invalid;
|
||||
}
|
||||
|
||||
public void setNew(boolean value) {
|
||||
this.isNew = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNew() {
|
||||
return this.isNew;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
this.portletAttributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value) {
|
||||
if (value != null) {
|
||||
this.portletAttributes.put(name, value);
|
||||
}
|
||||
else {
|
||||
this.portletAttributes.remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxInactiveInterval(int interval) {
|
||||
this.maxInactiveInterval = interval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletContext getPortletContext() {
|
||||
return this.portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributeMap() {
|
||||
return Collections.unmodifiableMap(this.portletAttributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getAttributeMap(int scope) {
|
||||
if (scope == PortletSession.PORTLET_SCOPE) {
|
||||
return Collections.unmodifiableMap(this.portletAttributes);
|
||||
}
|
||||
else if (scope == PortletSession.APPLICATION_SCOPE) {
|
||||
return Collections.unmodifiableMap(this.applicationAttributes);
|
||||
}
|
||||
else {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Map;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletMode;
|
||||
import javax.portlet.PortletModeException;
|
||||
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 extends MockBaseURL implements PortletURL {
|
||||
|
||||
public static final String URL_TYPE_RENDER = "render";
|
||||
|
||||
public static final String URL_TYPE_ACTION = "action";
|
||||
|
||||
|
||||
private final PortalContext portalContext;
|
||||
|
||||
private final String urlType;
|
||||
|
||||
private WindowState windowState;
|
||||
|
||||
private PortletMode portletMode;
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void setWindowState(WindowState windowState) throws WindowStateException {
|
||||
if (!CollectionUtils.contains(this.portalContext.getSupportedWindowStates(), windowState)) {
|
||||
throw new WindowStateException("WindowState not supported", windowState);
|
||||
}
|
||||
this.windowState = windowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindowState() {
|
||||
return this.windowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletMode(PortletMode portletMode) throws PortletModeException {
|
||||
if (!CollectionUtils.contains(this.portalContext.getSupportedPortletModes(), portletMode)) {
|
||||
throw new PortletModeException("PortletMode not supported", portletMode);
|
||||
}
|
||||
this.portletMode = portletMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletMode getPortletMode() {
|
||||
return this.portletMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePublicRenderParameter(String name) {
|
||||
this.parameters.remove(name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
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 (isSecure() ? "https:" : "http:") +
|
||||
"//localhost/mockportlet?" + sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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;
|
||||
import javax.portlet.WindowState;
|
||||
|
||||
/**
|
||||
* 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}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @param portletMode the mode that the portlet runs in
|
||||
* @param windowState the window state to run the portlet in
|
||||
*/
|
||||
public MockRenderRequest(PortletMode portletMode, WindowState windowState) {
|
||||
super();
|
||||
setPortletMode(portletMode);
|
||||
setWindowState(windowState);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getLifecyclePhase() {
|
||||
return RENDER_PHASE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getETag() {
|
||||
return getProperty(RenderRequest.ETAG);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Collection;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletMode;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.RenderResponse} interface.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MockRenderResponse extends MockMimeResponse implements RenderResponse {
|
||||
|
||||
private String title;
|
||||
|
||||
private Collection<PortletMode> nextPossiblePortletModes;
|
||||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockRenderResponse.
|
||||
* @param portalContext the PortalContext defining the supported
|
||||
* PortletModes and WindowStates
|
||||
* @param request the corresponding render request that this response
|
||||
* is generated for
|
||||
*/
|
||||
public MockRenderResponse(PortalContext portalContext, RenderRequest request) {
|
||||
super(portalContext, request);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// RenderResponse methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNextPossiblePortletModes(Collection<PortletMode> portletModes) {
|
||||
this.nextPossiblePortletModes = portletModes;
|
||||
}
|
||||
|
||||
public Collection<PortletMode> getNextPossiblePortletModes() {
|
||||
return this.nextPossiblePortletModes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.ResourceRequest;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.ResourceRequest} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockResourceRequest extends MockClientDataRequest implements ResourceRequest {
|
||||
|
||||
private String resourceID;
|
||||
|
||||
private String cacheability;
|
||||
|
||||
private final Map<String, String[]> privateRenderParameterMap = new LinkedHashMap<String, String[]>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockResourceRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @see org.springframework.mock.web.portlet.MockPortalContext
|
||||
* @see org.springframework.mock.web.portlet.MockPortletContext
|
||||
*/
|
||||
public MockResourceRequest() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockResourceRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @param resourceID the resource id for this request
|
||||
*/
|
||||
public MockResourceRequest(String resourceID) {
|
||||
super();
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockResourceRequest with a default {@link MockPortalContext}
|
||||
* and a default {@link MockPortletContext}.
|
||||
* @param url the resource URL for this request
|
||||
*/
|
||||
public MockResourceRequest(MockResourceURL url) {
|
||||
super();
|
||||
this.resourceID = url.getResourceID();
|
||||
this.cacheability = url.getCacheability();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockResourceRequest with a default {@link MockPortalContext}.
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
*/
|
||||
public MockResourceRequest(PortletContext portletContext) {
|
||||
super(portletContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockResourceRequest.
|
||||
* @param portalContext the PortalContext that the request runs in
|
||||
* @param portletContext the PortletContext that the request runs in
|
||||
*/
|
||||
public MockResourceRequest(PortalContext portalContext, PortletContext portletContext) {
|
||||
super(portalContext, portletContext);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getLifecyclePhase() {
|
||||
return RESOURCE_PHASE;
|
||||
}
|
||||
|
||||
public void setResourceID(String resourceID) {
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResourceID() {
|
||||
return this.resourceID;
|
||||
}
|
||||
|
||||
public void setCacheability(String cacheLevel) {
|
||||
this.cacheability = cacheLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCacheability() {
|
||||
return this.cacheability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getETag() {
|
||||
return getProperty(RenderRequest.ETAG);
|
||||
}
|
||||
|
||||
public void addPrivateRenderParameter(String key, String value) {
|
||||
this.privateRenderParameterMap.put(key, new String[] {value});
|
||||
}
|
||||
|
||||
public void addPrivateRenderParameter(String key, String[] values) {
|
||||
this.privateRenderParameterMap.put(key, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getPrivateRenderParameterMap() {
|
||||
return Collections.unmodifiableMap(this.privateRenderParameterMap);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.ResourceResponse;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.ResourceResponse} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockResourceResponse extends MockMimeResponse implements ResourceResponse {
|
||||
|
||||
private int contentLength = 0;
|
||||
|
||||
|
||||
@Override
|
||||
public void setContentLength(int len) {
|
||||
this.contentLength = len;
|
||||
}
|
||||
|
||||
public int getContentLength() {
|
||||
return this.contentLength;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Map;
|
||||
import javax.portlet.ResourceURL;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.ResourceURL} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockResourceURL extends MockBaseURL implements ResourceURL {
|
||||
|
||||
private String resourceID;
|
||||
|
||||
private String cacheability;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// ResourceURL methods
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void setResourceID(String resourceID) {
|
||||
this.resourceID = resourceID;
|
||||
}
|
||||
|
||||
public String getResourceID() {
|
||||
return this.resourceID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCacheability(String cacheLevel) {
|
||||
this.cacheability = cacheLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCacheability() {
|
||||
return this.cacheability;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(encodeParameter("resourceID", this.resourceID));
|
||||
if (this.cacheability != null) {
|
||||
sb.append(";").append(encodeParameter("cacheability", this.cacheability));
|
||||
}
|
||||
for (Map.Entry<String, String[]> entry : this.parameters.entrySet()) {
|
||||
sb.append(";").append(encodeParameter("param_" + entry.getKey(), entry.getValue()));
|
||||
}
|
||||
return (isSecure() ? "https:" : "http:") +
|
||||
"//localhost/mockportlet?" + sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortalContext;
|
||||
import javax.portlet.PortletMode;
|
||||
import javax.portlet.PortletModeException;
|
||||
import javax.portlet.StateAwareResponse;
|
||||
import javax.portlet.WindowState;
|
||||
import javax.portlet.WindowStateException;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.StateAwareResponse} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public class MockStateAwareResponse extends MockPortletResponse implements StateAwareResponse {
|
||||
|
||||
private WindowState windowState;
|
||||
|
||||
private PortletMode portletMode;
|
||||
|
||||
private final Map<String, String[]> renderParameters = new LinkedHashMap<String, String[]>();
|
||||
|
||||
private final Map<QName, Serializable> events = new HashMap<QName, Serializable>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MockActionResponse with a default {@link MockPortalContext}.
|
||||
* @see org.springframework.mock.web.portlet.MockPortalContext
|
||||
*/
|
||||
public MockStateAwareResponse() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MockActionResponse.
|
||||
* @param portalContext the PortalContext defining the supported
|
||||
* PortletModes and WindowStates
|
||||
*/
|
||||
public MockStateAwareResponse(PortalContext portalContext) {
|
||||
super(portalContext);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setWindowState(WindowState windowState) throws WindowStateException {
|
||||
if (!CollectionUtils.contains(getPortalContext().getSupportedWindowStates(), windowState)) {
|
||||
throw new WindowStateException("WindowState not supported", windowState);
|
||||
}
|
||||
this.windowState = windowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowState getWindowState() {
|
||||
return this.windowState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletMode(PortletMode portletMode) throws PortletModeException {
|
||||
if (!CollectionUtils.contains(getPortalContext().getSupportedPortletModes(), portletMode)) {
|
||||
throw new PortletModeException("PortletMode not supported", portletMode);
|
||||
}
|
||||
this.portletMode = portletMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletMode getPortletMode() {
|
||||
return this.portletMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameters(Map<String, String[]> parameters) {
|
||||
Assert.notNull(parameters, "Parameters Map must not be null");
|
||||
this.renderParameters.clear();
|
||||
this.renderParameters.putAll(parameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameter(String key, String value) {
|
||||
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});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRenderParameter(String key, String[] values) {
|
||||
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 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 String[] getRenderParameterValues(String key) {
|
||||
Assert.notNull(key, "Parameter key must not be null");
|
||||
return this.renderParameters.get(key);
|
||||
}
|
||||
|
||||
public Iterator<String> getRenderParameterNames() {
|
||||
return this.renderParameters.keySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getRenderParameterMap() {
|
||||
return Collections.unmodifiableMap(this.renderParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePublicRenderParameter(String name) {
|
||||
this.renderParameters.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEvent(QName name, Serializable value) {
|
||||
this.events.put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEvent(String name, Serializable value) {
|
||||
this.events.put(new QName(name), value);
|
||||
}
|
||||
|
||||
public Iterator<QName> getEventNames() {
|
||||
return this.events.keySet().iterator();
|
||||
}
|
||||
|
||||
public Serializable getEvent(QName name) {
|
||||
return this.events.get(name);
|
||||
}
|
||||
|
||||
public Serializable getEvent(String name) {
|
||||
return this.events.get(new QName(name));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Set;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of the {@link javax.portlet.PortletContext} interface,
|
||||
* wrapping an underlying {@link javax.servlet.ServletContext}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see MockPortletContext
|
||||
*/
|
||||
public class ServletWrappingPortletContext implements PortletContext {
|
||||
|
||||
private final ServletContext servletContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletContext wrapping the given ServletContext.
|
||||
* @param servletContext the ServletContext to wrap
|
||||
*/
|
||||
public ServletWrappingPortletContext(ServletContext servletContext) {
|
||||
Assert.notNull(servletContext, "ServletContext must not be null");
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying ServletContext that this PortletContext wraps.
|
||||
*/
|
||||
public final ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getServerInfo() {
|
||||
return this.servletContext.getServerInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletRequestDispatcher getRequestDispatcher(String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletRequestDispatcher getNamedDispatcher(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String path) {
|
||||
return this.servletContext.getResourceAsStream(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType(String file) {
|
||||
return this.servletContext.getMimeType(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealPath(String path) {
|
||||
return this.servletContext.getRealPath(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getResourcePaths(String path) {
|
||||
return this.servletContext.getResourcePaths(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String path) throws MalformedURLException {
|
||||
return this.servletContext.getResource(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name) {
|
||||
return this.servletContext.getAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return this.servletContext.getAttributeNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String name) {
|
||||
return this.servletContext.getInitParameter(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return this.servletContext.getInitParameterNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String msg) {
|
||||
this.servletContext.log(msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String message, Throwable throwable) {
|
||||
this.servletContext.log(message, throwable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name) {
|
||||
this.servletContext.removeAttribute(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object object) {
|
||||
this.servletContext.setAttribute(name, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPortletContextName() {
|
||||
return this.servletContext.getServletContextName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getContainerRuntimeOptions() {
|
||||
return Collections.enumeration(Collections.<String>emptySet());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* A comprehensive set of Portlet API 2.0 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.
|
||||
*/
|
||||
package org.springframework.mock.web.portlet;
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -27,8 +27,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
/**
|
||||
* Annotation which indicates that a method parameter should be bound to an HTTP cookie.
|
||||
*
|
||||
* <p>Supported for annotated handler methods in Servlet and Portlet environments.
|
||||
*
|
||||
* <p>The method parameter may be declared as type {@link javax.servlet.http.Cookie}
|
||||
* or as cookie value type (String, int, etc.).
|
||||
*
|
||||
@@ -39,9 +37,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* @see RequestParam
|
||||
* @see RequestHeader
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -24,8 +24,7 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation for handling exceptions in specific handler classes and/or
|
||||
* handler methods. Provides consistent style between Servlet and Portlet
|
||||
* environments, with the semantics adapting to the concrete environment.
|
||||
* handler methods.
|
||||
*
|
||||
* <p>Handler methods which are annotated with this annotation are allowed to
|
||||
* have very flexible signatures. They may have parameters of the following
|
||||
@@ -34,16 +33,10 @@ import java.lang.annotation.Target;
|
||||
* <li>An exception argument: declared as a general Exception or as a more
|
||||
* specific exception. This also serves as a mapping hint if the annotation
|
||||
* itself does not narrow the exception types through its {@link #value()}.
|
||||
* <li>Request and/or response objects (Servlet API or Portlet API).
|
||||
* <li>Request and/or response objects (typically from the Servlet API).
|
||||
* You may choose any specific request/response type, e.g.
|
||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}
|
||||
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} /
|
||||
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case,
|
||||
* an explicitly declared action/render argument is also used for mapping
|
||||
* specific request types onto a handler method (in case of no other
|
||||
* information given that differentiates between action and render requests).
|
||||
* <li>Session object (Servlet API or Portlet API): either
|
||||
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}.
|
||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}.
|
||||
* <li>Session object: typically {@link javax.servlet.http.HttpSession}.
|
||||
* An argument of this type will enforce the presence of a corresponding session.
|
||||
* As a consequence, such an argument will never be {@code null}.
|
||||
* <i>Note that session access may not be thread-safe, in particular in a
|
||||
@@ -54,17 +47,17 @@ import java.lang.annotation.Target;
|
||||
* <li>{@link org.springframework.web.context.request.WebRequest} or
|
||||
* {@link org.springframework.web.context.request.NativeWebRequest}.
|
||||
* Allows for generic request parameter access as well as request/session
|
||||
* attribute access, without ties to the native Servlet/Portlet API.
|
||||
* attribute access, without ties to the native Servlet API.
|
||||
* <li>{@link java.util.Locale} for the current request locale
|
||||
* (determined by the most specific locale resolver available,
|
||||
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver}
|
||||
* in a Servlet environment and the portal locale in a Portlet environment).
|
||||
* in a Servlet environment).
|
||||
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access
|
||||
* to the request's content. This will be the raw InputStream/Reader as
|
||||
* exposed by the Servlet/Portlet API.
|
||||
* exposed by the Servlet API.
|
||||
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
|
||||
* the response's content. This will be the raw OutputStream/Writer as
|
||||
* exposed by the Servlet/Portlet API.
|
||||
* exposed by the Servlet API.
|
||||
* <li>{@link org.springframework.ui.Model} as an alternative to returning
|
||||
* a model map from the handler method. Note that the provided model is not
|
||||
* pre-populated with regular model attributes and therefore always empty,
|
||||
@@ -73,7 +66,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* <p>The following return types are supported for handler methods:
|
||||
* <ul>
|
||||
* <li>A {@code ModelAndView} object (Servlet MVC or Portlet MVC).
|
||||
* <li>A {@code ModelAndView} object (from Servlet MVC).
|
||||
* <li>A {@link org.springframework.ui.Model} object, with the view name implicitly
|
||||
* determined through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}.
|
||||
* <li>A {@link java.util.Map} object for exposing a model,
|
||||
@@ -93,30 +86,19 @@ import java.lang.annotation.Target;
|
||||
* <li>{@code void} if the method handles the response itself (by
|
||||
* writing the response content directly, declaring an argument of type
|
||||
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse}
|
||||
* / {@link javax.portlet.RenderResponse} for that purpose)
|
||||
* or if the view name is supposed to be implicitly determined through a
|
||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* (not declaring a response argument in the handler method signature;
|
||||
* only applicable in a Servlet environment).
|
||||
* for that purpose) or if the view name is supposed to be implicitly determined
|
||||
* through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* (not declaring a response argument in the handler method signature).
|
||||
* </ul>
|
||||
*
|
||||
* <p>In Servlet environments, you can combine the {@code ExceptionHandler} annotation
|
||||
* with {@link ResponseStatus @ResponseStatus}, to define the response status
|
||||
* for the HTTP response.
|
||||
*
|
||||
* <p><b>Note:</b> In Portlet environments, {@code ExceptionHandler} annotated methods
|
||||
* will only be called during the render and resource phases - just like
|
||||
* {@link org.springframework.web.portlet.HandlerExceptionResolver} beans would.
|
||||
* Exceptions carried over from the action and event phases will be invoked during
|
||||
* the render phase as well, with exception handler methods having to be present
|
||||
* on the controller class that defines the applicable <i>render</i> method.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.context.request.WebRequest
|
||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -40,8 +40,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* @see RequestMapping
|
||||
* @see RequestParam
|
||||
* @see CookieValue
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -27,34 +27,17 @@ import org.springframework.core.annotation.AliasFor;
|
||||
|
||||
/**
|
||||
* Annotation for mapping web requests onto specific handler classes and/or
|
||||
* handler methods. Provides a consistent style between Servlet and Portlet
|
||||
* environments, with the semantics adapting to the concrete environment.
|
||||
*
|
||||
* <p><b>NOTE:</b> The set of features supported for Servlets is a superset
|
||||
* of the set of features supported for Portlets. The places where this applies
|
||||
* are marked with the label "Servlet-only" in this source file. For Servlet
|
||||
* environments there are some further distinctions depending on whether an
|
||||
* application is configured with {@literal "@MVC 3.0"} or
|
||||
* {@literal "@MVC 3.1"} support classes. The places where this applies are
|
||||
* marked with {@literal "@MVC 3.1-only"} in this source file. For more
|
||||
* details see the note on the new support classes added in Spring MVC 3.1
|
||||
* further below.
|
||||
* handler methods.
|
||||
*
|
||||
* <p>Handler methods which are annotated with this annotation are allowed to
|
||||
* have very flexible signatures. They may have parameters of the following
|
||||
* types, in arbitrary order (except for validation results, which need to
|
||||
* follow right after the corresponding command object, if desired):
|
||||
* <ul>
|
||||
* <li>Request and/or response objects (Servlet API or Portlet API).
|
||||
* <li>Request and/or response objects (typically from the Servlet API).
|
||||
* You may choose any specific request/response type, e.g.
|
||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}
|
||||
* or {@link javax.portlet.PortletRequest} / {@link javax.portlet.ActionRequest} /
|
||||
* {@link javax.portlet.RenderRequest}. Note that in the Portlet case,
|
||||
* an explicitly declared action/render argument is also used for mapping
|
||||
* specific request types onto a handler method (in case of no other
|
||||
* information given that differentiates between action and render requests).
|
||||
* <li>Session object (Servlet API or Portlet API): either
|
||||
* {@link javax.servlet.http.HttpSession} or {@link javax.portlet.PortletSession}.
|
||||
* {@link javax.servlet.ServletRequest} / {@link javax.servlet.http.HttpServletRequest}.
|
||||
* <li>Session object: typically {@link javax.servlet.http.HttpSession}.
|
||||
* An argument of this type will enforce the presence of a corresponding session.
|
||||
* As a consequence, such an argument will never be {@code null}.
|
||||
* <i>Note that session access may not be thread-safe, in particular in a
|
||||
@@ -65,17 +48,17 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* <li>{@link org.springframework.web.context.request.WebRequest} or
|
||||
* {@link org.springframework.web.context.request.NativeWebRequest}.
|
||||
* Allows for generic request parameter access as well as request/session
|
||||
* attribute access, without ties to the native Servlet/Portlet API.
|
||||
* attribute access, without ties to the native Servlet API.
|
||||
* <li>{@link java.util.Locale} for the current request locale
|
||||
* (determined by the most specific locale resolver available,
|
||||
* i.e. the configured {@link org.springframework.web.servlet.LocaleResolver}
|
||||
* in a Servlet environment and the portal locale in a Portlet environment).
|
||||
* in a Servlet environment).
|
||||
* <li>{@link java.io.InputStream} / {@link java.io.Reader} for access
|
||||
* to the request's content. This will be the raw InputStream/Reader as
|
||||
* exposed by the Servlet/Portlet API.
|
||||
* exposed by the Servlet API.
|
||||
* <li>{@link java.io.OutputStream} / {@link java.io.Writer} for generating
|
||||
* the response's content. This will be the raw OutputStream/Writer as
|
||||
* exposed by the Servlet/Portlet API.
|
||||
* exposed by the Servlet API.
|
||||
* <li>{@link org.springframework.http.HttpMethod} for the HTTP request method</li>
|
||||
* <li>{@link PathVariable @PathVariable} annotated parameters (Servlet-only)
|
||||
* for access to URI template values (i.e. /hotels/{hotel}). Variable values will be
|
||||
@@ -94,13 +77,13 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* {@link java.util.Map Map<String, String>} to gain access to all
|
||||
* matrix variables in the URL or to those in a specific path variable.
|
||||
* <li>{@link RequestParam @RequestParam} annotated parameters for access to
|
||||
* specific Servlet/Portlet request parameters. Parameter values will be
|
||||
* specific Servlet request parameters. Parameter values will be
|
||||
* converted to the declared method argument type. Additionally,
|
||||
* {@code @RequestParam} can be used on a {@link java.util.Map Map<String, String>} or
|
||||
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}
|
||||
* method parameter to gain access to all request parameters.
|
||||
* <li>{@link RequestHeader @RequestHeader} annotated parameters for access to
|
||||
* specific Servlet/Portlet request HTTP headers. Parameter values will be
|
||||
* specific Servlet request HTTP headers. Parameter values will be
|
||||
* converted to the declared method argument type. Additionally,
|
||||
* {@code @RequestHeader} can be used on a {@link java.util.Map Map<String, String>},
|
||||
* {@link org.springframework.util.MultiValueMap MultiValueMap<String, String>}, or
|
||||
@@ -177,7 +160,7 @@ import org.springframework.core.annotation.AliasFor;
|
||||
*
|
||||
* <p>The following return types are supported for handler methods:
|
||||
* <ul>
|
||||
* <li>A {@code ModelAndView} object (Servlet MVC or Portlet MVC),
|
||||
* <li>A {@code ModelAndView} object (from Servlet MVC),
|
||||
* with the model implicitly enriched with command objects and the results
|
||||
* of {@link ModelAttribute @ModelAttribute} annotated reference data accessor methods.
|
||||
* <li>A {@link org.springframework.ui.Model Model} object, with the view name implicitly
|
||||
@@ -238,11 +221,9 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* <li>{@code void} if the method handles the response itself (by
|
||||
* writing the response content directly, declaring an argument of type
|
||||
* {@link javax.servlet.ServletResponse} / {@link javax.servlet.http.HttpServletResponse}
|
||||
* / {@link javax.portlet.RenderResponse} for that purpose)
|
||||
* or if the view name is supposed to be implicitly determined through a
|
||||
* {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* (not declaring a response argument in the handler method signature;
|
||||
* only applicable in a Servlet environment).
|
||||
* for that purpose) or if the view name is supposed to be implicitly determined
|
||||
* through a {@link org.springframework.web.servlet.RequestToViewNameTranslator}
|
||||
* (not declaring a response argument in the handler method signature).
|
||||
* <li>Any other return type will be considered as single model attribute
|
||||
* to be exposed to the view, using the attribute name specified through
|
||||
* {@link ModelAttribute @ModelAttribute} at the method level (or the default attribute
|
||||
@@ -253,9 +234,7 @@ import org.springframework.core.annotation.AliasFor;
|
||||
*
|
||||
* <p><b>NOTE:</b> {@code @RequestMapping} will only be processed if an
|
||||
* an appropriate {@code HandlerMapping}-{@code HandlerAdapter} pair
|
||||
* is configured. This is the case by default in both the
|
||||
* {@code DispatcherServlet} and the {@code DispatcherPortlet}.
|
||||
* However, if you are defining custom {@code HandlerMappings} or
|
||||
* is configured. If you are defining custom {@code HandlerMappings} or
|
||||
* {@code HandlerAdapters}, then you need to add
|
||||
* {@code DefaultAnnotationHandlerMapping} and
|
||||
* {@code AnnotationMethodHandlerAdapter} to your configuration.</code>.
|
||||
@@ -293,8 +272,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* @see InitBinder
|
||||
* @see org.springframework.web.context.request.WebRequest
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
* @see org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -314,11 +291,9 @@ public @interface RequestMapping {
|
||||
|
||||
/**
|
||||
* The primary mapping expressed by this annotation.
|
||||
* <p>In a Servlet environment this is an alias for {@link #path}.
|
||||
* For example {@code @RequestMapping("/foo")} is equivalent to
|
||||
* <p>This is an alias for {@link #path}. For example
|
||||
* {@code @RequestMapping("/foo")} is equivalent to
|
||||
* {@code @RequestMapping(path="/foo")}.
|
||||
* <p>In a Portlet environment this is the mapped portlet modes
|
||||
* (i.e. "EDIT", "VIEW", "HELP" or any custom modes).
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this primary mapping, narrowing it for a specific handler method.
|
||||
@@ -348,7 +323,6 @@ public @interface RequestMapping {
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this HTTP method restriction (i.e. the type-level restriction
|
||||
* gets checked before the handler method is even resolved).
|
||||
* <p>Supported for Servlet environments as well as Portlet 2.0 environments.
|
||||
*/
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
@@ -365,14 +339,10 @@ public @interface RequestMapping {
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this parameter restriction (i.e. the type-level restriction
|
||||
* gets checked before the handler method is even resolved).
|
||||
* <p>In a Servlet environment, parameter mappings are considered as restrictions
|
||||
* that are enforced at the type level. The primary path mapping (i.e. the
|
||||
* specified URI value) still has to uniquely identify the target handler, with
|
||||
* parameter mappings simply expressing preconditions for invoking the handler.
|
||||
* <p>In a Portlet environment, parameters are taken into account as mapping
|
||||
* differentiators, i.e. the primary portlet mode mapping plus the parameter
|
||||
* conditions uniquely identify the target handler. Different handlers may be
|
||||
* mapped onto the same portlet mode, as long as their parameter mappings differ.
|
||||
* <p>Parameter mappings are considered as restrictions that are enforced at
|
||||
* the type level. The primary path mapping (i.e. the specified URI value)
|
||||
* still has to uniquely identify the target handler, with parameter mappings
|
||||
* simply expressing preconditions for invoking the handler.
|
||||
*/
|
||||
String[] params() default {};
|
||||
|
||||
@@ -395,8 +365,6 @@ public @interface RequestMapping {
|
||||
* When used at the type level, all method-level mappings inherit
|
||||
* this header restriction (i.e. the type-level restriction
|
||||
* gets checked before the handler method is even resolved).
|
||||
* <p>Maps against HttpServletRequest headers in a Servlet environment,
|
||||
* and against PortletRequest properties in a Portlet 2.0 environment.
|
||||
* @see org.springframework.http.MediaType
|
||||
*/
|
||||
String[] headers() default {};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -47,9 +47,6 @@ import org.springframework.core.annotation.AliasFor;
|
||||
* @see RequestMapping
|
||||
* @see RequestHeader
|
||||
* @see CookieValue
|
||||
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
|
||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter
|
||||
*/
|
||||
@Target(ElementType.PARAMETER)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.bind.annotation.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.core.NestedRuntimeException;
|
||||
|
||||
/**
|
||||
* Exception indicating that the execution of an annotated MVC handler method failed.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.6
|
||||
* @see HandlerMethodInvoker#invokeHandlerMethod
|
||||
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("serial")
|
||||
public class HandlerMethodInvocationException extends NestedRuntimeException {
|
||||
|
||||
/**
|
||||
* Create a new HandlerMethodInvocationException for the given Method handle and cause.
|
||||
* @param handlerMethod the handler method handle
|
||||
* @param cause the cause of the invocation failure
|
||||
*/
|
||||
public HandlerMethodInvocationException(Method handlerMethod, Throwable cause) {
|
||||
super("Failed to invoke handler method [" + handlerMethod + "]", cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,901 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.bind.annotation.support;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.SynthesizingMethodParameter;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.ui.ExtendedModelMap;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.HttpMediaTypeNotSupportedException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ValueConstants;
|
||||
import org.springframework.web.bind.support.DefaultSessionAttributeStore;
|
||||
import org.springframework.web.bind.support.SessionAttributeStore;
|
||||
import org.springframework.web.bind.support.SessionStatus;
|
||||
import org.springframework.web.bind.support.SimpleSessionStatus;
|
||||
import org.springframework.web.bind.support.WebArgumentResolver;
|
||||
import org.springframework.web.bind.support.WebBindingInitializer;
|
||||
import org.springframework.web.bind.support.WebRequestDataBinder;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
|
||||
/**
|
||||
* Support class for invoking an annotated handler method. Operates on the introspection
|
||||
* results of a {@link HandlerMethodResolver} for a specific handler type.
|
||||
*
|
||||
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
|
||||
* and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.5.2
|
||||
* @see #invokeHandlerMethod
|
||||
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
|
||||
*/
|
||||
@Deprecated
|
||||
public class HandlerMethodInvoker {
|
||||
|
||||
private static final String MODEL_KEY_PREFIX_STALE = SessionAttributeStore.class.getName() + ".STALE.";
|
||||
|
||||
/** We'll create a lot of these objects, so we don't want a new logger every time. */
|
||||
private static final Log logger = LogFactory.getLog(HandlerMethodInvoker.class);
|
||||
|
||||
private final HandlerMethodResolver methodResolver;
|
||||
|
||||
private final WebBindingInitializer bindingInitializer;
|
||||
|
||||
private final SessionAttributeStore sessionAttributeStore;
|
||||
|
||||
private final ParameterNameDiscoverer parameterNameDiscoverer;
|
||||
|
||||
private final WebArgumentResolver[] customArgumentResolvers;
|
||||
|
||||
private final HttpMessageConverter<?>[] messageConverters;
|
||||
|
||||
private final SimpleSessionStatus sessionStatus = new SimpleSessionStatus();
|
||||
|
||||
|
||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver) {
|
||||
this(methodResolver, null);
|
||||
}
|
||||
|
||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer) {
|
||||
this(methodResolver, bindingInitializer, new DefaultSessionAttributeStore(), null, null, null);
|
||||
}
|
||||
|
||||
public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer,
|
||||
SessionAttributeStore sessionAttributeStore, ParameterNameDiscoverer parameterNameDiscoverer,
|
||||
WebArgumentResolver[] customArgumentResolvers, HttpMessageConverter<?>[] messageConverters) {
|
||||
|
||||
this.methodResolver = methodResolver;
|
||||
this.bindingInitializer = bindingInitializer;
|
||||
this.sessionAttributeStore = sessionAttributeStore;
|
||||
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||
this.customArgumentResolvers = customArgumentResolvers;
|
||||
this.messageConverters = messageConverters;
|
||||
}
|
||||
|
||||
|
||||
public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
|
||||
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
|
||||
|
||||
Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
|
||||
try {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
|
||||
Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
|
||||
if (attrValue != null) {
|
||||
implicitModel.addAttribute(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
|
||||
Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
|
||||
Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
|
||||
if (debug) {
|
||||
logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
|
||||
}
|
||||
String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
|
||||
if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
|
||||
continue;
|
||||
}
|
||||
ReflectionUtils.makeAccessible(attributeMethodToInvoke);
|
||||
Object attrValue = attributeMethodToInvoke.invoke(handler, args);
|
||||
if ("".equals(attrName)) {
|
||||
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
|
||||
attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
|
||||
}
|
||||
if (!implicitModel.containsAttribute(attrName)) {
|
||||
implicitModel.addAttribute(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
|
||||
if (debug) {
|
||||
logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
|
||||
}
|
||||
ReflectionUtils.makeAccessible(handlerMethodToInvoke);
|
||||
return handlerMethodToInvoke.invoke(handler, args);
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// Internal assertion failed (e.g. invalid signature):
|
||||
// throw exception with full handler method context...
|
||||
throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
// User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
|
||||
ReflectionUtils.rethrowException(ex.getTargetException());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public final void updateModelAttributes(Object handler, Map<String, Object> mavModel,
|
||||
ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {
|
||||
|
||||
if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
|
||||
for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
|
||||
this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose model attributes as session attributes, if required.
|
||||
// Expose BindingResults for all attributes, making custom editors available.
|
||||
Map<String, Object> model = (mavModel != null ? mavModel : implicitModel);
|
||||
if (model != null) {
|
||||
try {
|
||||
String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
|
||||
for (String attrName : originalAttrNames) {
|
||||
Object attrValue = model.get(attrName);
|
||||
boolean isSessionAttr = this.methodResolver.isSessionAttribute(
|
||||
attrName, (attrValue != null ? attrValue.getClass() : null));
|
||||
if (isSessionAttr) {
|
||||
if (this.sessionStatus.isComplete()) {
|
||||
implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
|
||||
}
|
||||
else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
|
||||
this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
|
||||
}
|
||||
}
|
||||
if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX) &&
|
||||
(isSessionAttr || isBindingCandidate(attrValue))) {
|
||||
String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
|
||||
if (mavModel != null && !model.containsKey(bindingResultKey)) {
|
||||
WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
|
||||
initBinder(handler, attrName, binder, webRequest);
|
||||
mavModel.put(bindingResultKey, binder.getBindingResult());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
// User-defined @InitBinder method threw an exception...
|
||||
ReflectionUtils.rethrowException(ex.getTargetException());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
|
||||
NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
|
||||
|
||||
Class<?>[] paramTypes = handlerMethod.getParameterTypes();
|
||||
Object[] args = new Object[paramTypes.length];
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
MethodParameter methodParam = new SynthesizingMethodParameter(handlerMethod, i);
|
||||
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
|
||||
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
|
||||
String paramName = null;
|
||||
String headerName = null;
|
||||
boolean requestBodyFound = false;
|
||||
String cookieName = null;
|
||||
String pathVarName = null;
|
||||
String attrName = null;
|
||||
boolean required = false;
|
||||
String defaultValue = null;
|
||||
boolean validate = false;
|
||||
Object[] validationHints = null;
|
||||
int annotationsFound = 0;
|
||||
Annotation[] paramAnns = methodParam.getParameterAnnotations();
|
||||
|
||||
for (Annotation paramAnn : paramAnns) {
|
||||
if (RequestParam.class.isInstance(paramAnn)) {
|
||||
RequestParam requestParam = (RequestParam) paramAnn;
|
||||
paramName = requestParam.name();
|
||||
required = requestParam.required();
|
||||
defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (RequestHeader.class.isInstance(paramAnn)) {
|
||||
RequestHeader requestHeader = (RequestHeader) paramAnn;
|
||||
headerName = requestHeader.name();
|
||||
required = requestHeader.required();
|
||||
defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (RequestBody.class.isInstance(paramAnn)) {
|
||||
requestBodyFound = true;
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (CookieValue.class.isInstance(paramAnn)) {
|
||||
CookieValue cookieValue = (CookieValue) paramAnn;
|
||||
cookieName = cookieValue.name();
|
||||
required = cookieValue.required();
|
||||
defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (PathVariable.class.isInstance(paramAnn)) {
|
||||
PathVariable pathVar = (PathVariable) paramAnn;
|
||||
pathVarName = pathVar.value();
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (ModelAttribute.class.isInstance(paramAnn)) {
|
||||
ModelAttribute attr = (ModelAttribute) paramAnn;
|
||||
attrName = attr.value();
|
||||
annotationsFound++;
|
||||
}
|
||||
else if (Value.class.isInstance(paramAnn)) {
|
||||
defaultValue = ((Value) paramAnn).value();
|
||||
}
|
||||
else {
|
||||
Validated validatedAnn = AnnotationUtils.getAnnotation(paramAnn, Validated.class);
|
||||
if (validatedAnn != null || paramAnn.annotationType().getSimpleName().startsWith("Valid")) {
|
||||
validate = true;
|
||||
Object hints = (validatedAnn != null ? validatedAnn.value() : AnnotationUtils.getValue(paramAnn));
|
||||
validationHints = (hints instanceof Object[] ? (Object[]) hints : new Object[]{hints});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (annotationsFound > 1) {
|
||||
throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
|
||||
"do not specify more than one such annotation on the same parameter: " + handlerMethod);
|
||||
}
|
||||
|
||||
if (annotationsFound == 0) {
|
||||
Object argValue = resolveCommonArgument(methodParam, webRequest);
|
||||
if (argValue != WebArgumentResolver.UNRESOLVED) {
|
||||
args[i] = argValue;
|
||||
}
|
||||
else if (defaultValue != null) {
|
||||
args[i] = resolveDefaultValue(defaultValue);
|
||||
}
|
||||
else {
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
|
||||
if (!paramType.isAssignableFrom(implicitModel.getClass())) {
|
||||
throw new IllegalStateException("Argument [" + paramType.getSimpleName() + "] is of type " +
|
||||
"Model or Map but is not assignable from the actual model. You may need to switch " +
|
||||
"newer MVC infrastructure classes to use this argument.");
|
||||
}
|
||||
args[i] = implicitModel;
|
||||
}
|
||||
else if (SessionStatus.class.isAssignableFrom(paramType)) {
|
||||
args[i] = this.sessionStatus;
|
||||
}
|
||||
else if (HttpEntity.class.isAssignableFrom(paramType)) {
|
||||
args[i] = resolveHttpEntityRequest(methodParam, webRequest);
|
||||
}
|
||||
else if (Errors.class.isAssignableFrom(paramType)) {
|
||||
throw new IllegalStateException("Errors/BindingResult argument declared " +
|
||||
"without preceding model attribute. Check your handler method signature!");
|
||||
}
|
||||
else if (BeanUtils.isSimpleProperty(paramType)) {
|
||||
paramName = "";
|
||||
}
|
||||
else {
|
||||
attrName = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramName != null) {
|
||||
args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
|
||||
}
|
||||
else if (headerName != null) {
|
||||
args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
|
||||
}
|
||||
else if (requestBodyFound) {
|
||||
args[i] = resolveRequestBody(methodParam, webRequest, handler);
|
||||
}
|
||||
else if (cookieName != null) {
|
||||
args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
|
||||
}
|
||||
else if (pathVarName != null) {
|
||||
args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
|
||||
}
|
||||
else if (attrName != null) {
|
||||
WebDataBinder binder =
|
||||
resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
|
||||
boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
|
||||
if (binder.getTarget() != null) {
|
||||
doBind(binder, webRequest, validate, validationHints, !assignBindingResult);
|
||||
}
|
||||
args[i] = binder.getTarget();
|
||||
if (assignBindingResult) {
|
||||
args[i + 1] = binder.getBindingResult();
|
||||
i++;
|
||||
}
|
||||
implicitModel.putAll(binder.getBindingResult().getModel());
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
if (this.bindingInitializer != null) {
|
||||
this.bindingInitializer.initBinder(binder, webRequest);
|
||||
}
|
||||
if (handler != null) {
|
||||
Set<Method> initBinderMethods = this.methodResolver.getInitBinderMethods();
|
||||
if (!initBinderMethods.isEmpty()) {
|
||||
boolean debug = logger.isDebugEnabled();
|
||||
for (Method initBinderMethod : initBinderMethods) {
|
||||
Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
|
||||
String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
|
||||
if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
|
||||
Object[] initBinderArgs =
|
||||
resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
|
||||
if (debug) {
|
||||
logger.debug("Invoking init-binder method: " + methodToInvoke);
|
||||
}
|
||||
ReflectionUtils.makeAccessible(methodToInvoke);
|
||||
Object returnValue = methodToInvoke.invoke(handler, initBinderArgs);
|
||||
if (returnValue != null) {
|
||||
throw new IllegalStateException(
|
||||
"InitBinder methods must not have a return value: " + methodToInvoke);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object[] resolveInitBinderArguments(Object handler, Method initBinderMethod,
|
||||
WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
|
||||
|
||||
Class<?>[] initBinderParams = initBinderMethod.getParameterTypes();
|
||||
Object[] initBinderArgs = new Object[initBinderParams.length];
|
||||
|
||||
for (int i = 0; i < initBinderArgs.length; i++) {
|
||||
MethodParameter methodParam = new SynthesizingMethodParameter(initBinderMethod, i);
|
||||
methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
|
||||
GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
|
||||
String paramName = null;
|
||||
boolean paramRequired = false;
|
||||
String paramDefaultValue = null;
|
||||
String pathVarName = null;
|
||||
Annotation[] paramAnns = methodParam.getParameterAnnotations();
|
||||
|
||||
for (Annotation paramAnn : paramAnns) {
|
||||
if (RequestParam.class.isInstance(paramAnn)) {
|
||||
RequestParam requestParam = (RequestParam) paramAnn;
|
||||
paramName = requestParam.name();
|
||||
paramRequired = requestParam.required();
|
||||
paramDefaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
|
||||
break;
|
||||
}
|
||||
else if (ModelAttribute.class.isInstance(paramAnn)) {
|
||||
throw new IllegalStateException(
|
||||
"@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod);
|
||||
}
|
||||
else if (PathVariable.class.isInstance(paramAnn)) {
|
||||
PathVariable pathVar = (PathVariable) paramAnn;
|
||||
pathVarName = pathVar.value();
|
||||
}
|
||||
}
|
||||
|
||||
if (paramName == null && pathVarName == null) {
|
||||
Object argValue = resolveCommonArgument(methodParam, webRequest);
|
||||
if (argValue != WebArgumentResolver.UNRESOLVED) {
|
||||
initBinderArgs[i] = argValue;
|
||||
}
|
||||
else {
|
||||
Class<?> paramType = initBinderParams[i];
|
||||
if (paramType.isInstance(binder)) {
|
||||
initBinderArgs[i] = binder;
|
||||
}
|
||||
else if (BeanUtils.isSimpleProperty(paramType)) {
|
||||
paramName = "";
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
|
||||
"] for @InitBinder method: " + initBinderMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (paramName != null) {
|
||||
initBinderArgs[i] =
|
||||
resolveRequestParam(paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null);
|
||||
}
|
||||
else if (pathVarName != null) {
|
||||
initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null);
|
||||
}
|
||||
}
|
||||
|
||||
return initBinderArgs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object resolveRequestParam(String paramName, boolean required, String defaultValue,
|
||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
|
||||
throws Exception {
|
||||
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {
|
||||
return resolveRequestParamMap((Class<? extends Map<?, ?>>) paramType, webRequest);
|
||||
}
|
||||
if (paramName.length() == 0) {
|
||||
paramName = getRequiredParameterName(methodParam);
|
||||
}
|
||||
Object paramValue = null;
|
||||
MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
|
||||
if (multipartRequest != null) {
|
||||
List<MultipartFile> files = multipartRequest.getFiles(paramName);
|
||||
if (!files.isEmpty()) {
|
||||
paramValue = (files.size() == 1 ? files.get(0) : files);
|
||||
}
|
||||
}
|
||||
if (paramValue == null) {
|
||||
String[] paramValues = webRequest.getParameterValues(paramName);
|
||||
if (paramValues != null) {
|
||||
paramValue = (paramValues.length == 1 ? paramValues[0] : paramValues);
|
||||
}
|
||||
}
|
||||
if (paramValue == null) {
|
||||
if (defaultValue != null) {
|
||||
paramValue = resolveDefaultValue(defaultValue);
|
||||
}
|
||||
else if (required) {
|
||||
raiseMissingParameterException(paramName, paramType);
|
||||
}
|
||||
paramValue = checkValue(paramName, paramValue, paramType);
|
||||
}
|
||||
WebDataBinder binder = createBinder(webRequest, null, paramName);
|
||||
initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
|
||||
return binder.convertIfNecessary(paramValue, paramType, methodParam);
|
||||
}
|
||||
|
||||
private Map<String, ?> resolveRequestParamMap(Class<? extends Map<?, ?>> mapType, NativeWebRequest webRequest) {
|
||||
Map<String, String[]> parameterMap = webRequest.getParameterMap();
|
||||
if (MultiValueMap.class.isAssignableFrom(mapType)) {
|
||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(parameterMap.size());
|
||||
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
|
||||
for (String value : entry.getValue()) {
|
||||
result.add(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Map<String, String> result = new LinkedHashMap<String, String>(parameterMap.size());
|
||||
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
|
||||
if (entry.getValue().length > 0) {
|
||||
result.put(entry.getKey(), entry.getValue()[0]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
|
||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
|
||||
throws Exception {
|
||||
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
if (Map.class.isAssignableFrom(paramType)) {
|
||||
return resolveRequestHeaderMap((Class<? extends Map<?, ?>>) paramType, webRequest);
|
||||
}
|
||||
if (headerName.length() == 0) {
|
||||
headerName = getRequiredParameterName(methodParam);
|
||||
}
|
||||
Object headerValue = null;
|
||||
String[] headerValues = webRequest.getHeaderValues(headerName);
|
||||
if (headerValues != null) {
|
||||
headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues);
|
||||
}
|
||||
if (headerValue == null) {
|
||||
if (defaultValue != null) {
|
||||
headerValue = resolveDefaultValue(defaultValue);
|
||||
}
|
||||
else if (required) {
|
||||
raiseMissingHeaderException(headerName, paramType);
|
||||
}
|
||||
headerValue = checkValue(headerName, headerValue, paramType);
|
||||
}
|
||||
WebDataBinder binder = createBinder(webRequest, null, headerName);
|
||||
initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
|
||||
return binder.convertIfNecessary(headerValue, paramType, methodParam);
|
||||
}
|
||||
|
||||
private Map<String, ?> resolveRequestHeaderMap(Class<? extends Map<?, ?>> mapType, NativeWebRequest webRequest) {
|
||||
if (MultiValueMap.class.isAssignableFrom(mapType)) {
|
||||
MultiValueMap<String, String> result;
|
||||
if (HttpHeaders.class.isAssignableFrom(mapType)) {
|
||||
result = new HttpHeaders();
|
||||
}
|
||||
else {
|
||||
result = new LinkedMultiValueMap<String, String>();
|
||||
}
|
||||
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
|
||||
String headerName = iterator.next();
|
||||
for (String headerValue : webRequest.getHeaderValues(headerName)) {
|
||||
result.add(headerName, headerValue);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
Map<String, String> result = new LinkedHashMap<String, String>();
|
||||
for (Iterator<String> iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
|
||||
String headerName = iterator.next();
|
||||
String headerValue = webRequest.getHeader(headerName);
|
||||
result.put(headerName, headerValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given {@link RequestBody @RequestBody} annotation.
|
||||
*/
|
||||
protected Object resolveRequestBody(MethodParameter methodParam, NativeWebRequest webRequest, Object handler)
|
||||
throws Exception {
|
||||
|
||||
return readWithMessageConverters(methodParam, createHttpInputMessage(webRequest), methodParam.getParameterType());
|
||||
}
|
||||
|
||||
private HttpEntity<?> resolveHttpEntityRequest(MethodParameter methodParam, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
|
||||
Class<?> paramType = getHttpEntityType(methodParam);
|
||||
Object body = readWithMessageConverters(methodParam, inputMessage, paramType);
|
||||
return new HttpEntity<Object>(body, inputMessage.getHeaders());
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class<?> paramType)
|
||||
throws Exception {
|
||||
|
||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||
if (contentType == null) {
|
||||
StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
|
||||
String paramName = methodParam.getParameterName();
|
||||
if (paramName != null) {
|
||||
builder.append(' ');
|
||||
builder.append(paramName);
|
||||
}
|
||||
throw new HttpMediaTypeNotSupportedException(
|
||||
"Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
|
||||
}
|
||||
|
||||
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
|
||||
if (this.messageConverters != null) {
|
||||
for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
|
||||
allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
|
||||
if (messageConverter.canRead(paramType, contentType)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
|
||||
+"\" using [" + messageConverter + "]");
|
||||
}
|
||||
return messageConverter.read((Class) paramType, inputMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
|
||||
}
|
||||
|
||||
private Class<?> getHttpEntityType(MethodParameter methodParam) {
|
||||
Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
|
||||
ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
|
||||
if (type.getActualTypeArguments().length == 1) {
|
||||
Type typeArgument = type.getActualTypeArguments()[0];
|
||||
if (typeArgument instanceof Class) {
|
||||
return (Class<?>) typeArgument;
|
||||
}
|
||||
else if (typeArgument instanceof GenericArrayType) {
|
||||
Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
|
||||
if (componentType instanceof Class) {
|
||||
// Surely, there should be a nicer way to do this
|
||||
Object array = Array.newInstance((Class<?>) componentType, 0);
|
||||
return array.getClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
|
||||
|
||||
}
|
||||
|
||||
private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
|
||||
MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
|
||||
throws Exception {
|
||||
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
if (cookieName.length() == 0) {
|
||||
cookieName = getRequiredParameterName(methodParam);
|
||||
}
|
||||
Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest);
|
||||
if (cookieValue == null) {
|
||||
if (defaultValue != null) {
|
||||
cookieValue = resolveDefaultValue(defaultValue);
|
||||
}
|
||||
else if (required) {
|
||||
raiseMissingCookieException(cookieName, paramType);
|
||||
}
|
||||
cookieValue = checkValue(cookieName, cookieValue, paramType);
|
||||
}
|
||||
WebDataBinder binder = createBinder(webRequest, null, cookieName);
|
||||
initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
|
||||
return binder.convertIfNecessary(cookieValue, paramType, methodParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given {@link CookieValue @CookieValue} annotation.
|
||||
* <p>Throws an UnsupportedOperationException by default.
|
||||
*/
|
||||
protected Object resolveCookieValue(String cookieName, Class<?> paramType, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
throw new UnsupportedOperationException("@CookieValue not supported");
|
||||
}
|
||||
|
||||
private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
|
||||
NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {
|
||||
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
if (pathVarName.length() == 0) {
|
||||
pathVarName = getRequiredParameterName(methodParam);
|
||||
}
|
||||
String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
|
||||
WebDataBinder binder = createBinder(webRequest, null, pathVarName);
|
||||
initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
|
||||
return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given {@link PathVariable @PathVariable} annotation.
|
||||
* <p>Throws an UnsupportedOperationException by default.
|
||||
*/
|
||||
protected String resolvePathVariable(String pathVarName, Class<?> paramType, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
throw new UnsupportedOperationException("@PathVariable not supported");
|
||||
}
|
||||
|
||||
private String getRequiredParameterName(MethodParameter methodParam) {
|
||||
String name = methodParam.getParameterName();
|
||||
if (name == null) {
|
||||
throw new IllegalStateException(
|
||||
"No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
|
||||
"], and no parameter name information found in class file either.");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
private Object checkValue(String name, Object value, Class<?> paramType) {
|
||||
if (value == null) {
|
||||
if (boolean.class == paramType) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
else if (paramType.isPrimitive()) {
|
||||
throw new IllegalStateException("Optional " + paramType + " parameter '" + name +
|
||||
"' is not present but cannot be translated into a null value due to being declared as a " +
|
||||
"primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
|
||||
ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
|
||||
|
||||
// Bind request parameter onto object...
|
||||
String name = attrName;
|
||||
if ("".equals(name)) {
|
||||
name = Conventions.getVariableNameForParameter(methodParam);
|
||||
}
|
||||
Class<?> paramType = methodParam.getParameterType();
|
||||
Object bindObject;
|
||||
if (implicitModel.containsKey(name)) {
|
||||
bindObject = implicitModel.get(name);
|
||||
}
|
||||
else if (this.methodResolver.isSessionAttribute(name, paramType)) {
|
||||
bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
|
||||
if (bindObject == null) {
|
||||
raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
|
||||
}
|
||||
}
|
||||
else {
|
||||
bindObject = BeanUtils.instantiateClass(paramType);
|
||||
}
|
||||
WebDataBinder binder = createBinder(webRequest, bindObject, name);
|
||||
initBinder(handler, name, binder, webRequest);
|
||||
return binder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether the given value qualifies as a "binding candidate", i.e. might potentially be subject to
|
||||
* bean-style data binding later on.
|
||||
*/
|
||||
protected boolean isBindingCandidate(Object value) {
|
||||
return (value != null && !value.getClass().isArray() && !(value instanceof Collection) &&
|
||||
!(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass()));
|
||||
}
|
||||
|
||||
protected void raiseMissingParameterException(String paramName, Class<?> paramType) throws Exception {
|
||||
throw new IllegalStateException("Missing parameter '" + paramName + "' of type [" + paramType.getName() + "]");
|
||||
}
|
||||
|
||||
protected void raiseMissingHeaderException(String headerName, Class<?> paramType) throws Exception {
|
||||
throw new IllegalStateException("Missing header '" + headerName + "' of type [" + paramType.getName() + "]");
|
||||
}
|
||||
|
||||
protected void raiseMissingCookieException(String cookieName, Class<?> paramType) throws Exception {
|
||||
throw new IllegalStateException(
|
||||
"Missing cookie value '" + cookieName + "' of type [" + paramType.getName() + "]");
|
||||
}
|
||||
|
||||
protected void raiseSessionRequiredException(String message) throws Exception {
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
|
||||
protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
|
||||
throws Exception {
|
||||
|
||||
return new WebRequestDataBinder(target, objectName);
|
||||
}
|
||||
|
||||
private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate,
|
||||
Object[] validationHints, boolean failOnErrors) throws Exception {
|
||||
|
||||
doBind(binder, webRequest);
|
||||
if (validate) {
|
||||
binder.validate(validationHints);
|
||||
}
|
||||
if (failOnErrors && binder.getBindingResult().hasErrors()) {
|
||||
throw new BindException(binder.getBindingResult());
|
||||
}
|
||||
}
|
||||
|
||||
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
|
||||
((WebRequestDataBinder) binder).bind(webRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
|
||||
* <p>Throws an UnsupportedOperation1Exception by default.
|
||||
*/
|
||||
protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
|
||||
throw new UnsupportedOperationException("@RequestBody not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link HttpOutputMessage} for the given {@link NativeWebRequest}.
|
||||
* <p>Throws an UnsupportedOperationException by default.
|
||||
*/
|
||||
protected HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) throws Exception {
|
||||
throw new UnsupportedOperationException("@Body not supported");
|
||||
}
|
||||
|
||||
protected String parseDefaultValueAttribute(String value) {
|
||||
return (ValueConstants.DEFAULT_NONE.equals(value) ? null : value);
|
||||
}
|
||||
|
||||
protected Object resolveDefaultValue(String value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest)
|
||||
throws Exception {
|
||||
|
||||
// Invoke custom argument resolvers if present...
|
||||
if (this.customArgumentResolvers != null) {
|
||||
for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
|
||||
Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
|
||||
if (value != WebArgumentResolver.UNRESOLVED) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolution of standard parameter types...
|
||||
Class<?> paramType = methodParameter.getParameterType();
|
||||
Object value = resolveStandardArgument(paramType, webRequest);
|
||||
if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
|
||||
throw new IllegalStateException("Standard argument type [" + paramType.getName() +
|
||||
"] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) +
|
||||
"]. Consider declaring the argument type in a less specific fashion.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
protected Object resolveStandardArgument(Class<?> parameterType, NativeWebRequest webRequest) throws Exception {
|
||||
if (WebRequest.class.isAssignableFrom(parameterType)) {
|
||||
return webRequest;
|
||||
}
|
||||
return WebArgumentResolver.UNRESOLVED;
|
||||
}
|
||||
|
||||
protected final void addReturnValueAsModelAttribute(Method handlerMethod, Class<?> handlerType,
|
||||
Object returnValue, ExtendedModelMap implicitModel) {
|
||||
|
||||
ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
|
||||
String attrName = (attr != null ? attr.value() : "");
|
||||
if ("".equals(attrName)) {
|
||||
Class<?> resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
|
||||
attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
|
||||
}
|
||||
implicitModel.addAttribute(attrName, returnValue);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.bind.annotation.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.bind.annotation.InitBinder;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.SessionAttributes;
|
||||
|
||||
/**
|
||||
* Support class for resolving web method annotations in a handler type.
|
||||
* Processes {@code @RequestMapping}, {@code @InitBinder},
|
||||
* {@code @ModelAttribute} and {@code @SessionAttributes}.
|
||||
*
|
||||
* <p>Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
|
||||
* and {@link org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.2
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
* @see org.springframework.web.bind.annotation.InitBinder
|
||||
* @see org.springframework.web.bind.annotation.ModelAttribute
|
||||
* @see org.springframework.web.bind.annotation.SessionAttributes
|
||||
* @deprecated as of 4.3, in favor of the {@code HandlerMethod}-based MVC infrastructure
|
||||
*/
|
||||
@Deprecated
|
||||
public class HandlerMethodResolver {
|
||||
|
||||
private final Set<Method> handlerMethods = new LinkedHashSet<Method>();
|
||||
|
||||
private final Set<Method> initBinderMethods = new LinkedHashSet<Method>();
|
||||
|
||||
private final Set<Method> modelAttributeMethods = new LinkedHashSet<Method>();
|
||||
|
||||
private RequestMapping typeLevelMapping;
|
||||
|
||||
private boolean sessionAttributesFound;
|
||||
|
||||
private final Set<String> sessionAttributeNames = new HashSet<String>();
|
||||
|
||||
private final Set<Class<?>> sessionAttributeTypes = new HashSet<Class<?>>();
|
||||
|
||||
private final Set<String> actualSessionAttributeNames =
|
||||
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(4));
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a new HandlerMethodResolver for the specified handler type.
|
||||
* @param handlerType the handler class to introspect
|
||||
*/
|
||||
public void init(final Class<?> handlerType) {
|
||||
Set<Class<?>> handlerTypes = new LinkedHashSet<Class<?>>();
|
||||
Class<?> specificHandlerType = null;
|
||||
if (!Proxy.isProxyClass(handlerType)) {
|
||||
handlerTypes.add(handlerType);
|
||||
specificHandlerType = handlerType;
|
||||
}
|
||||
handlerTypes.addAll(Arrays.asList(handlerType.getInterfaces()));
|
||||
for (Class<?> currentHandlerType : handlerTypes) {
|
||||
final Class<?> targetClass = (specificHandlerType != null ? specificHandlerType : currentHandlerType);
|
||||
ReflectionUtils.doWithMethods(currentHandlerType, new ReflectionUtils.MethodCallback() {
|
||||
@Override
|
||||
public void doWith(Method method) {
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(method, targetClass);
|
||||
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
if (isHandlerMethod(specificMethod) &&
|
||||
(bridgedMethod == specificMethod || !isHandlerMethod(bridgedMethod))) {
|
||||
handlerMethods.add(specificMethod);
|
||||
}
|
||||
else if (isInitBinderMethod(specificMethod) &&
|
||||
(bridgedMethod == specificMethod || !isInitBinderMethod(bridgedMethod))) {
|
||||
initBinderMethods.add(specificMethod);
|
||||
}
|
||||
else if (isModelAttributeMethod(specificMethod) &&
|
||||
(bridgedMethod == specificMethod || !isModelAttributeMethod(bridgedMethod))) {
|
||||
modelAttributeMethods.add(specificMethod);
|
||||
}
|
||||
}
|
||||
}, ReflectionUtils.USER_DECLARED_METHODS);
|
||||
}
|
||||
this.typeLevelMapping = AnnotationUtils.findAnnotation(handlerType, RequestMapping.class);
|
||||
SessionAttributes sessionAttributes = AnnotationUtils.findAnnotation(handlerType, SessionAttributes.class);
|
||||
this.sessionAttributesFound = (sessionAttributes != null);
|
||||
if (this.sessionAttributesFound) {
|
||||
this.sessionAttributeNames.addAll(Arrays.asList(sessionAttributes.names()));
|
||||
this.sessionAttributeTypes.addAll(Arrays.asList(sessionAttributes.types()));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isHandlerMethod(Method method) {
|
||||
return AnnotationUtils.findAnnotation(method, RequestMapping.class) != null;
|
||||
}
|
||||
|
||||
protected boolean isInitBinderMethod(Method method) {
|
||||
return AnnotationUtils.findAnnotation(method, InitBinder.class) != null;
|
||||
}
|
||||
|
||||
protected boolean isModelAttributeMethod(Method method) {
|
||||
return AnnotationUtils.findAnnotation(method, ModelAttribute.class) != null;
|
||||
}
|
||||
|
||||
|
||||
public final boolean hasHandlerMethods() {
|
||||
return !this.handlerMethods.isEmpty();
|
||||
}
|
||||
|
||||
public final Set<Method> getHandlerMethods() {
|
||||
return this.handlerMethods;
|
||||
}
|
||||
|
||||
public final Set<Method> getInitBinderMethods() {
|
||||
return this.initBinderMethods;
|
||||
}
|
||||
|
||||
public final Set<Method> getModelAttributeMethods() {
|
||||
return this.modelAttributeMethods;
|
||||
}
|
||||
|
||||
public boolean hasTypeLevelMapping() {
|
||||
return (this.typeLevelMapping != null);
|
||||
}
|
||||
|
||||
public RequestMapping getTypeLevelMapping() {
|
||||
return this.typeLevelMapping;
|
||||
}
|
||||
|
||||
public boolean hasSessionAttributes() {
|
||||
return this.sessionAttributesFound;
|
||||
}
|
||||
|
||||
public boolean isSessionAttribute(String attrName, Class<?> attrType) {
|
||||
if (this.sessionAttributeNames.contains(attrName) || this.sessionAttributeTypes.contains(attrType)) {
|
||||
this.actualSessionAttributeNames.add(attrName);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getActualSessionAttributeNames() {
|
||||
return this.actualSessionAttributeNames;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Support classes for web annotation processing.
|
||||
*/
|
||||
package org.springframework.web.bind.annotation.support;
|
||||
@@ -40,7 +40,6 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.5.2
|
||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomArgumentResolvers
|
||||
*/
|
||||
public interface WebArgumentResolver {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -65,12 +65,6 @@ public interface WebApplicationContext extends ApplicationContext {
|
||||
*/
|
||||
String SCOPE_SESSION = "session";
|
||||
|
||||
/**
|
||||
* Scope identifier for global session scope: "globalSession".
|
||||
* Supported in addition to the standard scopes "singleton" and "prototype".
|
||||
*/
|
||||
String SCOPE_GLOBAL_SESSION = "globalSession";
|
||||
|
||||
/**
|
||||
* Scope identifier for the global web application scope: "application".
|
||||
* Supported in addition to the standard scopes "singleton" and "prototype".
|
||||
|
||||
@@ -20,13 +20,11 @@ import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.portlet.PortletSession;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
@@ -52,9 +50,6 @@ import org.springframework.web.util.WebUtils;
|
||||
*/
|
||||
public class FacesRequestAttributes implements RequestAttributes {
|
||||
|
||||
private static final boolean portletApiPresent =
|
||||
ClassUtils.isPresent("javax.portlet.PortletSession", FacesRequestAttributes.class.getClassLoader());
|
||||
|
||||
/**
|
||||
* We'll create a lot of these objects, so we don't want a new logger every time.
|
||||
*/
|
||||
@@ -108,42 +103,22 @@ public class FacesRequestAttributes implements RequestAttributes {
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name, int scope) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
|
||||
return PortletSessionAccessor.getAttribute(name, getExternalContext());
|
||||
}
|
||||
else {
|
||||
return getAttributeMap(scope).get(name);
|
||||
}
|
||||
return getAttributeMap(scope).get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value, int scope) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
|
||||
PortletSessionAccessor.setAttribute(name, value, getExternalContext());
|
||||
}
|
||||
else {
|
||||
getAttributeMap(scope).put(name, value);
|
||||
}
|
||||
getAttributeMap(scope).put(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name, int scope) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
|
||||
PortletSessionAccessor.removeAttribute(name, getExternalContext());
|
||||
}
|
||||
else {
|
||||
getAttributeMap(scope).remove(name);
|
||||
}
|
||||
getAttributeMap(scope).remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames(int scope) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION && portletApiPresent) {
|
||||
return PortletSessionAccessor.getAttributeNames(getExternalContext());
|
||||
}
|
||||
else {
|
||||
return StringUtils.toStringArray(getAttributeMap(scope).keySet());
|
||||
}
|
||||
return StringUtils.toStringArray(getAttributeMap(scope).keySet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -237,58 +212,4 @@ public class FacesRequestAttributes implements RequestAttributes {
|
||||
return mutex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid hard-coded Portlet API dependency.
|
||||
*/
|
||||
private static class PortletSessionAccessor {
|
||||
|
||||
public static Object getAttribute(String name, ExternalContext externalContext) {
|
||||
Object session = externalContext.getSession(false);
|
||||
if (session instanceof PortletSession) {
|
||||
return ((PortletSession) session).getAttribute(name, PortletSession.APPLICATION_SCOPE);
|
||||
}
|
||||
else if (session != null) {
|
||||
return externalContext.getSessionMap().get(name);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setAttribute(String name, Object value, ExternalContext externalContext) {
|
||||
Object session = externalContext.getSession(true);
|
||||
if (session instanceof PortletSession) {
|
||||
((PortletSession) session).setAttribute(name, value, PortletSession.APPLICATION_SCOPE);
|
||||
}
|
||||
else {
|
||||
externalContext.getSessionMap().put(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeAttribute(String name, ExternalContext externalContext) {
|
||||
Object session = externalContext.getSession(false);
|
||||
if (session instanceof PortletSession) {
|
||||
((PortletSession) session).removeAttribute(name, PortletSession.APPLICATION_SCOPE);
|
||||
}
|
||||
else if (session != null) {
|
||||
externalContext.getSessionMap().remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getAttributeNames(ExternalContext externalContext) {
|
||||
Object session = externalContext.getSession(false);
|
||||
if (session instanceof PortletSession) {
|
||||
return StringUtils.toStringArray(
|
||||
((PortletSession) session).getAttributeNames(PortletSession.APPLICATION_SCOPE));
|
||||
}
|
||||
else if (session != null) {
|
||||
return StringUtils.toStringArray(externalContext.getSessionMap().keySet());
|
||||
}
|
||||
else {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -155,11 +155,6 @@ public class FacesWebRequest extends FacesRequestAttributes implements NativeWeb
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified handling not supported for portlet requests:
|
||||
* As a consequence, this method always returns {@code false}.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Override
|
||||
public boolean checkNotModified(String etag, long lastModifiedTimestamp) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -31,16 +31,12 @@ public interface NativeWebRequest extends WebRequest {
|
||||
/**
|
||||
* Return the underlying native request object, if available.
|
||||
* @see javax.servlet.http.HttpServletRequest
|
||||
* @see javax.portlet.ActionRequest
|
||||
* @see javax.portlet.RenderRequest
|
||||
*/
|
||||
Object getNativeRequest();
|
||||
|
||||
/**
|
||||
* Return the underlying native response object, if available.
|
||||
* @see javax.servlet.http.HttpServletResponse
|
||||
* @see javax.portlet.ActionResponse
|
||||
* @see javax.portlet.RenderResponse
|
||||
*/
|
||||
Object getNativeResponse();
|
||||
|
||||
@@ -50,8 +46,6 @@ public interface NativeWebRequest extends WebRequest {
|
||||
* @return the matching request object, or {@code null} if none
|
||||
* of that type is available
|
||||
* @see javax.servlet.http.HttpServletRequest
|
||||
* @see javax.portlet.ActionRequest
|
||||
* @see javax.portlet.RenderRequest
|
||||
*/
|
||||
<T> T getNativeRequest(Class<T> requiredType);
|
||||
|
||||
@@ -61,8 +55,6 @@ public interface NativeWebRequest extends WebRequest {
|
||||
* @return the matching response object, or {@code null} if none
|
||||
* of that type is available
|
||||
* @see javax.servlet.http.HttpServletResponse
|
||||
* @see javax.portlet.ActionResponse
|
||||
* @see javax.portlet.RenderResponse
|
||||
*/
|
||||
<T> T getNativeResponse(Class<T> requiredType);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -22,12 +22,11 @@ package org.springframework.web.context.request;
|
||||
* attributes, with the optional notion of a "global session".
|
||||
*
|
||||
* <p>Can be implemented for any kind of request/session mechanism,
|
||||
* in particular for servlet requests and portlet requests.
|
||||
* in particular for servlet requests.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see ServletRequestAttributes
|
||||
* @see org.springframework.web.portlet.context.PortletRequestAttributes
|
||||
*/
|
||||
public interface RequestAttributes {
|
||||
|
||||
@@ -44,14 +43,6 @@ public interface RequestAttributes {
|
||||
*/
|
||||
int SCOPE_SESSION = 1;
|
||||
|
||||
/**
|
||||
* Constant that indicates global session scope.
|
||||
* <p>This explicitly refers to a globally shared session, if such
|
||||
* a distinction is available (for example, in a Portlet environment).
|
||||
* Else, it simply refers to the common session.
|
||||
*/
|
||||
int SCOPE_GLOBAL_SESSION = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Name of the standard reference to the request object: "request".
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -31,9 +31,8 @@ import org.springframework.util.ClassUtils;
|
||||
* <p>Use {@link RequestContextListener} or
|
||||
* {@link org.springframework.web.filter.RequestContextFilter} to expose
|
||||
* the current web request. Note that
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet} and
|
||||
* {@link org.springframework.web.portlet.DispatcherPortlet} already
|
||||
* expose the current request by default.
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet}
|
||||
* already exposes the current request by default.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rod Johnson
|
||||
@@ -41,7 +40,6 @@ import org.springframework.util.ClassUtils;
|
||||
* @see RequestContextListener
|
||||
* @see org.springframework.web.filter.RequestContextFilter
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
*/
|
||||
public abstract class RequestContextHolder {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -25,11 +25,6 @@ package org.springframework.web.context.request;
|
||||
* {@link org.springframework.web.filter.RequestContextFilter} or
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet}.
|
||||
*
|
||||
* <p>This {@code Scope} will also work for Portlet environments,
|
||||
* through an alternate {@code RequestAttributes} implementation
|
||||
* (as exposed out-of-the-box by Spring's
|
||||
* {@link org.springframework.web.portlet.DispatcherPortlet}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
@@ -39,7 +34,6 @@ package org.springframework.web.context.request;
|
||||
* @see RequestContextListener
|
||||
* @see org.springframework.web.filter.RequestContextFilter
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
*/
|
||||
public class RequestScope extends AbstractRequestAttributesScope {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -27,58 +27,21 @@ import org.springframework.beans.factory.ObjectFactory;
|
||||
* {@link org.springframework.web.filter.RequestContextFilter} or
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet}.
|
||||
*
|
||||
* <p>This {@code Scope} will also work for Portlet environments,
|
||||
* through an alternate {@code RequestAttributes} implementation
|
||||
* (as exposed out-of-the-box by Spring's
|
||||
* {@link org.springframework.web.portlet.DispatcherPortlet}.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @since 2.0
|
||||
* @see RequestContextHolder#currentRequestAttributes()
|
||||
* @see RequestAttributes#SCOPE_SESSION
|
||||
* @see RequestAttributes#SCOPE_GLOBAL_SESSION
|
||||
* @see RequestContextListener
|
||||
* @see org.springframework.web.filter.RequestContextFilter
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
*/
|
||||
public class SessionScope extends AbstractRequestAttributesScope {
|
||||
|
||||
private final int scope;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new SessionScope, storing attributes in a locally
|
||||
* isolated session (or default session, if there is no distinction
|
||||
* between a global session and a component-specific session).
|
||||
*/
|
||||
public SessionScope() {
|
||||
this.scope = RequestAttributes.SCOPE_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new SessionScope, specifying whether to store attributes
|
||||
* in the global session, provided that such a distinction is available.
|
||||
* <p>This distinction is important for Portlet environments, where there
|
||||
* are two notions of a session: "portlet scope" and "application scope".
|
||||
* If this flag is on, objects will be put into the "application scope" session;
|
||||
* else they will end up in the "portlet scope" session (the typical default).
|
||||
* <p>In a Servlet environment, this flag is effectively ignored.
|
||||
* @param globalSession {@code true} in case of the global session as target;
|
||||
* {@code false} in case of a component-specific session as target
|
||||
* @see org.springframework.web.portlet.context.PortletRequestAttributes
|
||||
* @see ServletRequestAttributes
|
||||
*/
|
||||
public SessionScope(boolean globalSession) {
|
||||
this.scope = (globalSession ? RequestAttributes.SCOPE_GLOBAL_SESSION : RequestAttributes.SCOPE_SESSION);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected int getScope() {
|
||||
return this.scope;
|
||||
return RequestAttributes.SCOPE_SESSION;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -52,11 +52,6 @@ import org.springframework.ui.ModelMap;
|
||||
* @see org.springframework.web.servlet.DispatcherServlet
|
||||
* @see org.springframework.web.servlet.handler.AbstractHandlerMapping#setInterceptors
|
||||
* @see org.springframework.web.servlet.HandlerInterceptor
|
||||
* @see org.springframework.web.portlet.context.PortletWebRequest
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
|
||||
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setApplyWebRequestInterceptorsToRenderPhaseOnly
|
||||
* @see org.springframework.web.portlet.HandlerInterceptor
|
||||
*/
|
||||
public interface WebRequestInterceptor {
|
||||
|
||||
|
||||
@@ -177,8 +177,7 @@ public abstract class WebApplicationContextUtils {
|
||||
*/
|
||||
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
|
||||
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
||||
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
||||
beanFactory.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
||||
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
|
||||
if (sc != null) {
|
||||
ServletContextScope appScope = new ServletContextScope(sc);
|
||||
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -23,10 +23,8 @@ import java.util.Map;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* This interface defines the multipart request access operations
|
||||
* that are exposed for actual multipart requests. It is extended
|
||||
* by {@link MultipartHttpServletRequest} and the Portlet
|
||||
* {@link org.springframework.web.portlet.multipart.MultipartActionRequest}.
|
||||
* This interface defines the multipart request access operations that are exposed
|
||||
* for actual multipart requests. It is extended by {@link MultipartHttpServletRequest}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -47,16 +47,10 @@ import org.springframework.web.util.WebUtils;
|
||||
* as representation of uploaded files and a String-based parameter Map as
|
||||
* representation of uploaded form fields.
|
||||
*
|
||||
* <p>Subclasses implement concrete resolution strategies for Servlet or Portlet
|
||||
* environments: see CommonsMultipartResolver and CommonsPortletMultipartResolver,
|
||||
* respectively. This base class is not tied to either of those APIs, factoring
|
||||
* out common functionality.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see CommonsMultipartFile
|
||||
* @see CommonsMultipartResolver
|
||||
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver
|
||||
*/
|
||||
public abstract class CommonsFileUploadSupport {
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ import org.springframework.web.util.WebUtils;
|
||||
* @since 29.09.2003
|
||||
* @see #CommonsMultipartResolver(ServletContext)
|
||||
* @see #setResolveLazily
|
||||
* @see org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver
|
||||
* @see org.apache.commons.fileupload.servlet.ServletFileUpload
|
||||
* @see org.apache.commons.fileupload.disk.DiskFileItemFactory
|
||||
*/
|
||||
|
||||
@@ -95,31 +95,6 @@ public class ServletRequestAttributesTests {
|
||||
assertSame(VALUE, session.getAttribute(KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGlobalSessionScopedAttribute() throws Exception {
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
session.setAttribute(KEY, VALUE);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(session);
|
||||
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
|
||||
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
|
||||
assertSame(VALUE, session.getAttribute(KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setGlobalSessionScopedAttributeAfterCompletion() throws Exception {
|
||||
MockHttpSession session = new MockHttpSession();
|
||||
session.setAttribute(KEY, VALUE);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setSession(session);
|
||||
ServletRequestAttributes attrs = new ServletRequestAttributes(request);
|
||||
assertSame(VALUE, attrs.getAttribute(KEY, RequestAttributes.SCOPE_GLOBAL_SESSION));
|
||||
attrs.requestCompleted();
|
||||
request.close();
|
||||
attrs.setAttribute(KEY, VALUE, RequestAttributes.SCOPE_GLOBAL_SESSION);
|
||||
assertSame(VALUE, session.getAttribute(KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSessionScopedAttributeDoesNotForceCreationOfSession() throws Exception {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,712 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.portlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.EventRequest;
|
||||
import javax.portlet.EventResponse;
|
||||
import javax.portlet.PortletException;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.portlet.ResourceRequest;
|
||||
import javax.portlet.ResourceResponse;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.context.event.SourceFilteringListener;
|
||||
import org.springframework.context.i18n.LocaleContext;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.context.i18n.SimpleLocaleContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.portlet.context.ConfigurablePortletApplicationContext;
|
||||
import org.springframework.web.portlet.context.PortletApplicationContextUtils;
|
||||
import org.springframework.web.portlet.context.PortletRequestAttributes;
|
||||
import org.springframework.web.portlet.context.PortletRequestHandledEvent;
|
||||
import org.springframework.web.portlet.context.StandardPortletEnvironment;
|
||||
import org.springframework.web.portlet.context.XmlPortletApplicationContext;
|
||||
|
||||
/**
|
||||
* Base portlet for Spring's portlet framework. Provides integration with
|
||||
* a Spring application context, in a JavaBean-based overall solution.
|
||||
*
|
||||
* <p>This class offers the following functionality:
|
||||
* <ul>
|
||||
* <li>Manages a Portlet {@link org.springframework.context.ApplicationContext}
|
||||
* instance per portlet. The portlet's configuration is determined by beans
|
||||
* in the portlet's namespace.
|
||||
* <li>Publishes events on request processing, whether or not a request is
|
||||
* successfully handled.
|
||||
* </ul>
|
||||
*
|
||||
* <p>Subclasses must implement {@link #doActionService} and {@link #doRenderService}
|
||||
* to handle action and render requests. Because this extends {@link GenericPortletBean}
|
||||
* rather than Portlet directly, bean properties are mapped onto it. Subclasses can
|
||||
* override {@link #initFrameworkPortlet()} for custom initialization.
|
||||
*
|
||||
* <p>Regards a "contextClass" parameter at the portlet init-param level,
|
||||
* falling back to the default context class
|
||||
* ({@link org.springframework.web.portlet.context.XmlPortletApplicationContext})
|
||||
* if not found. Note that, with the default FrameworkPortlet,
|
||||
* a context class needs to implement the
|
||||
* {@link org.springframework.web.portlet.context.ConfigurablePortletApplicationContext} SPI.
|
||||
*
|
||||
* <p>Passes a "contextConfigLocation" portlet init-param to the context instance,
|
||||
* parsing it into potentially multiple file paths which can be separated by any
|
||||
* number of commas and spaces, like "test-portlet.xml, myPortlet.xml".
|
||||
* If not explicitly specified, the context implementation is supposed to build a
|
||||
* default location from the namespace of the portlet.
|
||||
*
|
||||
* <p>Note: In case of multiple config locations, later bean definitions will
|
||||
* override ones defined in earlier loaded files, at least when using one of
|
||||
* Spring's default ApplicationContext implementations. This can be leveraged
|
||||
* to deliberately override certain bean definitions via an extra XML file.
|
||||
*
|
||||
* <p>The default namespace is "'portlet-name'-portlet", e.g. "test-portlet" for a
|
||||
* portlet-name "test" (leading to a "/WEB-INF/test-portlet.xml" default location
|
||||
* with XmlPortletApplicationContext). The namespace can also be set explicitly via
|
||||
* the "namespace" portlet init-param.
|
||||
*
|
||||
* @author William G. Thompson, Jr.
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #doActionService
|
||||
* @see #doRenderService
|
||||
* @see #setContextClass
|
||||
* @see #setContextConfigLocation
|
||||
* @see #setNamespace
|
||||
*/
|
||||
public abstract class FrameworkPortlet extends GenericPortletBean
|
||||
implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
/**
|
||||
* Default context class for FrameworkPortlet.
|
||||
* @see org.springframework.web.portlet.context.XmlPortletApplicationContext
|
||||
*/
|
||||
public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlPortletApplicationContext.class;
|
||||
|
||||
/**
|
||||
* Suffix for Portlet ApplicationContext namespaces. If a portlet of this class is
|
||||
* given the name "test" in a context, the namespace used by the portlet will
|
||||
* resolve to "test-portlet".
|
||||
*/
|
||||
public static final String DEFAULT_NAMESPACE_SUFFIX = "-portlet";
|
||||
|
||||
/**
|
||||
* Prefix for the PortletContext attribute for the Portlet ApplicationContext.
|
||||
* The completion is the portlet name.
|
||||
*/
|
||||
public static final String PORTLET_CONTEXT_PREFIX = FrameworkPortlet.class.getName() + ".CONTEXT.";
|
||||
|
||||
/**
|
||||
* Default USER_INFO attribute names to search for the current username:
|
||||
* "user.login.id", "user.name".
|
||||
*/
|
||||
public static final String[] DEFAULT_USERINFO_ATTRIBUTE_NAMES = {"user.login.id", "user.name"};
|
||||
|
||||
|
||||
/** Portlet ApplicationContext implementation class to use */
|
||||
private Class<?> contextClass = DEFAULT_CONTEXT_CLASS;
|
||||
|
||||
/** Namespace for this portlet */
|
||||
private String namespace;
|
||||
|
||||
/** Explicit context config location */
|
||||
private String contextConfigLocation;
|
||||
|
||||
/** Should we publish the context as a PortletContext attribute? */
|
||||
private boolean publishContext = true;
|
||||
|
||||
/** Should we publish a PortletRequestHandledEvent at the end of each request? */
|
||||
private boolean publishEvents = true;
|
||||
|
||||
/** Expose LocaleContext and RequestAttributes as inheritable for child threads? */
|
||||
private boolean threadContextInheritable = false;
|
||||
|
||||
/** USER_INFO attributes that may contain the username of the current user */
|
||||
private String[] userinfoUsernameAttributes = DEFAULT_USERINFO_ATTRIBUTE_NAMES;
|
||||
|
||||
/** ApplicationContext for this portlet */
|
||||
private ApplicationContext portletApplicationContext;
|
||||
|
||||
/** Flag used to detect whether onRefresh has already been called */
|
||||
private boolean refreshEventReceived = false;
|
||||
|
||||
|
||||
/**
|
||||
* Set a custom context class. This class must be of type ApplicationContext;
|
||||
* when using the default FrameworkPortlet implementation, the context class
|
||||
* must also implement ConfigurablePortletApplicationContext.
|
||||
* @see #createPortletApplicationContext
|
||||
*/
|
||||
public void setContextClass(Class<?> contextClass) {
|
||||
this.contextClass = contextClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the custom context class.
|
||||
*/
|
||||
public Class<?> getContextClass() {
|
||||
return this.contextClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom namespace for this portlet,
|
||||
* to be used for building a default context config location.
|
||||
*/
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the namespace for this portlet, falling back to default scheme if
|
||||
* no custom namespace was set. (e.g. "test-portlet" for a portlet named "test")
|
||||
*/
|
||||
public String getNamespace() {
|
||||
return (this.namespace != null) ? this.namespace : getPortletName() + DEFAULT_NAMESPACE_SUFFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context config location explicitly, instead of relying on the default
|
||||
* location built from the namespace. This location string can consist of
|
||||
* multiple locations separated by any number of commas and spaces.
|
||||
*/
|
||||
public void setContextConfigLocation(String contextConfigLocation) {
|
||||
this.contextConfigLocation = contextConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the explicit context config location, if any.
|
||||
*/
|
||||
public String getContextConfigLocation() {
|
||||
return this.contextConfigLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to publish this portlet's context as a PortletContext attribute,
|
||||
* available to all objects in the web container. Default is true.
|
||||
* <p>This is especially handy during testing, although it is debatable whether
|
||||
* it's good practice to let other application objects access the context this way.
|
||||
*/
|
||||
public void setPublishContext(boolean publishContext) {
|
||||
this.publishContext = publishContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this portlet should publish a PortletRequestHandledEvent at the end
|
||||
* of each request. Default is true; can be turned off for a slight performance
|
||||
* improvement, provided that no ApplicationListeners rely on such events.
|
||||
* @see org.springframework.web.portlet.context.PortletRequestHandledEvent
|
||||
*/
|
||||
public void setPublishEvents(boolean publishEvents) {
|
||||
this.publishEvents = publishEvents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to expose the LocaleContext and RequestAttributes as inheritable
|
||||
* for child threads (using an {@link java.lang.InheritableThreadLocal}).
|
||||
* <p>Default is "false", to avoid side effects on spawned background threads.
|
||||
* Switch this to "true" to enable inheritance for custom child threads which
|
||||
* are spawned during request processing and only used for this request
|
||||
* (that is, ending after their initial task, without reuse of the thread).
|
||||
* <p><b>WARNING:</b> Do not use inheritance for child threads if you are
|
||||
* accessing a thread pool which is configured to potentially add new threads
|
||||
* on demand (e.g. a JDK {@link java.util.concurrent.ThreadPoolExecutor}),
|
||||
* since this will expose the inherited context to such a pooled thread.
|
||||
*/
|
||||
public void setThreadContextInheritable(boolean threadContextInheritable) {
|
||||
this.threadContextInheritable = threadContextInheritable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of attributes to search in the USER_INFO map when trying
|
||||
* to find the username of the current user.
|
||||
* @see #getUsernameForRequest
|
||||
*/
|
||||
public void setUserinfoUsernameAttributes(String[] userinfoUsernameAttributes) {
|
||||
this.userinfoUsernameAttributes = userinfoUsernameAttributes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden method of GenericPortletBean, invoked after any bean properties
|
||||
* have been set. Creates this portlet's ApplicationContext.
|
||||
*/
|
||||
@Override
|
||||
protected final void initPortletBean() throws PortletException {
|
||||
getPortletContext().log("Initializing Spring FrameworkPortlet '" + getPortletName() + "'");
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("FrameworkPortlet '" + getPortletName() + "': initialization started");
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
this.portletApplicationContext = initPortletApplicationContext();
|
||||
initFrameworkPortlet();
|
||||
}
|
||||
catch (PortletException ex) {
|
||||
logger.error("Context initialization failed", ex);
|
||||
throw ex;
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
logger.error("Context initialization failed", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
logger.info("FrameworkPortlet '" + getPortletName() + "': initialization completed in " + elapsedTime + " ms");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and publish the Portlet ApplicationContext for this portlet.
|
||||
* <p>Delegates to {@link #createPortletApplicationContext} for actual creation.
|
||||
* Can be overridden in subclasses.
|
||||
* @return the ApplicationContext for this portlet
|
||||
*/
|
||||
protected ApplicationContext initPortletApplicationContext() {
|
||||
ApplicationContext parent = PortletApplicationContextUtils.getWebApplicationContext(getPortletContext());
|
||||
ApplicationContext pac = createPortletApplicationContext(parent);
|
||||
|
||||
if (!this.refreshEventReceived) {
|
||||
// Apparently not a ConfigurableApplicationContext with refresh support:
|
||||
// triggering initial onRefresh manually here.
|
||||
onRefresh(pac);
|
||||
}
|
||||
|
||||
if (this.publishContext) {
|
||||
// publish the context as a portlet context attribute
|
||||
String attName = getPortletContextAttributeName();
|
||||
getPortletContext().setAttribute(attName, pac);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Published ApplicationContext of portlet '" + getPortletName() +
|
||||
"' as PortletContext attribute with name [" + attName + "]");
|
||||
}
|
||||
}
|
||||
return pac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the Portlet ApplicationContext for this portlet, either a default
|
||||
* XmlPortletApplicationContext or a custom context class if set.
|
||||
* <p>This implementation expects custom contexts to implement
|
||||
* ConfigurablePortletApplicationContext. Can be overridden in subclasses.
|
||||
* @param parent the parent ApplicationContext to use, or null if none
|
||||
* @return the Portlet ApplicationContext for this portlet
|
||||
* @see #setContextClass
|
||||
* @see org.springframework.web.portlet.context.XmlPortletApplicationContext
|
||||
*/
|
||||
protected ApplicationContext createPortletApplicationContext(ApplicationContext parent) {
|
||||
Class<?> contextClass = getContextClass();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Portlet with name '" + getPortletName() +
|
||||
"' will try to create custom ApplicationContext context of class '" +
|
||||
contextClass.getName() + "'" + ", using parent context [" + parent + "]");
|
||||
}
|
||||
if (!ConfigurablePortletApplicationContext.class.isAssignableFrom(contextClass)) {
|
||||
throw new ApplicationContextException("Fatal initialization error in portlet with name '" + getPortletName() +
|
||||
"': custom ApplicationContext class [" + contextClass.getName() +
|
||||
"] is not of type ConfigurablePortletApplicationContext");
|
||||
}
|
||||
ConfigurablePortletApplicationContext pac =
|
||||
(ConfigurablePortletApplicationContext) BeanUtils.instantiateClass(contextClass);
|
||||
|
||||
// Assign the best possible id value.
|
||||
String portletContextName = getPortletContext().getPortletContextName();
|
||||
if (portletContextName != null) {
|
||||
pac.setId(ConfigurablePortletApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + portletContextName + "." + getPortletName());
|
||||
}
|
||||
else {
|
||||
pac.setId(ConfigurablePortletApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + getPortletName());
|
||||
}
|
||||
|
||||
pac.setEnvironment(getEnvironment());
|
||||
pac.setParent(parent);
|
||||
pac.setPortletContext(getPortletContext());
|
||||
pac.setPortletConfig(getPortletConfig());
|
||||
pac.setNamespace(getNamespace());
|
||||
pac.setConfigLocation(getContextConfigLocation());
|
||||
pac.addApplicationListener(new SourceFilteringListener(pac, this));
|
||||
|
||||
// The wac environment's #initPropertySources will be called in any case when the context
|
||||
// is refreshed; do it eagerly here to ensure portlet property sources are in place for
|
||||
// use in any post-processing or initialization that occurs below prior to #refresh
|
||||
ConfigurableEnvironment env = pac.getEnvironment();
|
||||
if (env instanceof StandardPortletEnvironment) {
|
||||
((StandardPortletEnvironment) env).initPropertySources(pac.getServletContext(), getPortletContext(), getPortletConfig());
|
||||
}
|
||||
|
||||
postProcessPortletApplicationContext(pac);
|
||||
pac.refresh();
|
||||
|
||||
return pac;
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the given Portlet ApplicationContext before it is refreshed
|
||||
* and activated as context for this portlet.
|
||||
* <p>The default implementation is empty. {@code refresh()} will
|
||||
* be called automatically after this method returns.
|
||||
* @param pac the configured Portlet ApplicationContext (not refreshed yet)
|
||||
* @see #createPortletApplicationContext
|
||||
* @see ConfigurableApplicationContext#refresh()
|
||||
*/
|
||||
protected void postProcessPortletApplicationContext(ConfigurableApplicationContext pac) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PortletContext attribute name for this portlets's ApplicationContext.
|
||||
* <p>The default implementation returns PORTLET_CONTEXT_PREFIX + portlet name.
|
||||
* @see #PORTLET_CONTEXT_PREFIX
|
||||
* @see #getPortletName
|
||||
*/
|
||||
public String getPortletContextAttributeName() {
|
||||
return PORTLET_CONTEXT_PREFIX + getPortletName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this portlet's ApplicationContext.
|
||||
*/
|
||||
public final ApplicationContext getPortletApplicationContext() {
|
||||
return this.portletApplicationContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method will be invoked after any bean properties have been set and
|
||||
* the ApplicationContext has been loaded.
|
||||
* <p>The default implementation is empty; subclasses may override this method
|
||||
* to perform any initialization they require.
|
||||
* @throws PortletException in case of an initialization exception
|
||||
*/
|
||||
protected void initFrameworkPortlet() throws PortletException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh this portlet's application context, as well as the
|
||||
* dependent state of the portlet.
|
||||
* @see #getPortletApplicationContext()
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
*/
|
||||
public void refresh() {
|
||||
ApplicationContext pac = getPortletApplicationContext();
|
||||
if (!(pac instanceof ConfigurableApplicationContext)) {
|
||||
throw new IllegalStateException("Portlet ApplicationContext does not support refresh: " + pac);
|
||||
}
|
||||
((ConfigurableApplicationContext) pac).refresh();
|
||||
}
|
||||
|
||||
/**
|
||||
* ApplicationListener endpoint that receives events from this servlet's
|
||||
* WebApplicationContext.
|
||||
* <p>The default implementation calls {@link #onRefresh} in case of a
|
||||
* {@link org.springframework.context.event.ContextRefreshedEvent},
|
||||
* triggering a refresh of this servlet's context-dependent state.
|
||||
* @param event the incoming ApplicationContext event
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
this.refreshEventReceived = true;
|
||||
onRefresh(event.getApplicationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method which can be overridden to add portlet-specific refresh work.
|
||||
* Called after successful context refresh.
|
||||
* <p>This implementation is empty.
|
||||
* @param context the current Portlet ApplicationContext
|
||||
* @see #refresh()
|
||||
*/
|
||||
protected void onRefresh(ApplicationContext context) {
|
||||
// For subclasses: do nothing by default.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden for friendlier behavior in unit tests.
|
||||
*/
|
||||
@Override
|
||||
protected String getTitle(RenderRequest renderRequest) {
|
||||
try {
|
||||
return super.getTitle(renderRequest);
|
||||
}
|
||||
catch (NullPointerException ex) {
|
||||
return getPortletName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate action requests to processRequest/doActionService.
|
||||
*/
|
||||
@Override
|
||||
public final void processAction(ActionRequest request, ActionResponse response)
|
||||
throws PortletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate render requests to processRequest/doRenderService.
|
||||
*/
|
||||
@Override
|
||||
protected final void doDispatch(RenderRequest request, RenderResponse response)
|
||||
throws PortletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serveResource(ResourceRequest request, ResourceResponse response)
|
||||
throws PortletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processEvent(EventRequest request, EventResponse response)
|
||||
throws PortletException, IOException {
|
||||
|
||||
processRequest(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process this request, publishing an event regardless of the outcome.
|
||||
* The actual event handling is performed by the abstract
|
||||
* {@code doActionService()} and {@code doRenderService()} template methods.
|
||||
* @see #doActionService
|
||||
* @see #doRenderService
|
||||
*/
|
||||
protected final void processRequest(PortletRequest request, PortletResponse response)
|
||||
throws PortletException, IOException {
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
Throwable failureCause = null;
|
||||
|
||||
// Expose current LocaleResolver and request as LocaleContext.
|
||||
LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
|
||||
LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable);
|
||||
|
||||
// Expose current RequestAttributes to current thread.
|
||||
RequestAttributes previousRequestAttributes = RequestContextHolder.getRequestAttributes();
|
||||
PortletRequestAttributes requestAttributes = null;
|
||||
if (previousRequestAttributes == null ||
|
||||
PortletRequestAttributes.class == previousRequestAttributes.getClass() ||
|
||||
ServletRequestAttributes.class == previousRequestAttributes.getClass()) {
|
||||
requestAttributes = new PortletRequestAttributes(request, response);
|
||||
RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable);
|
||||
}
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Bound request context to thread: " + request);
|
||||
}
|
||||
|
||||
try {
|
||||
String phase = (String) request.getAttribute(PortletRequest.LIFECYCLE_PHASE);
|
||||
if (PortletRequest.ACTION_PHASE.equals(phase)) {
|
||||
doActionService((ActionRequest) request, (ActionResponse) response);
|
||||
}
|
||||
else if (PortletRequest.RENDER_PHASE.equals(phase)) {
|
||||
doRenderService((RenderRequest) request, (RenderResponse) response);
|
||||
}
|
||||
else if (PortletRequest.RESOURCE_PHASE.equals(phase)) {
|
||||
doResourceService((ResourceRequest) request, (ResourceResponse) response);
|
||||
}
|
||||
else if (PortletRequest.EVENT_PHASE.equals(phase)) {
|
||||
doEventService((EventRequest) request, (EventResponse) response);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Invalid portlet request phase: " + phase);
|
||||
}
|
||||
}
|
||||
catch (PortletException ex) {
|
||||
failureCause = ex;
|
||||
throw ex;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
failureCause = ex;
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
failureCause = ex;
|
||||
throw new PortletException("Request processing failed", ex);
|
||||
}
|
||||
|
||||
finally {
|
||||
// Clear request attributes and reset thread-bound context.
|
||||
LocaleContextHolder.setLocaleContext(previousLocaleContext, this.threadContextInheritable);
|
||||
if (requestAttributes != null) {
|
||||
RequestContextHolder.setRequestAttributes(previousRequestAttributes, this.threadContextInheritable);
|
||||
requestAttributes.requestCompleted();
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Cleared thread-bound resource request context: " + request);
|
||||
}
|
||||
|
||||
if (failureCause != null) {
|
||||
logger.error("Could not complete request", failureCause);
|
||||
}
|
||||
else {
|
||||
logger.debug("Successfully completed request");
|
||||
}
|
||||
if (this.publishEvents) {
|
||||
// Whether or not we succeeded, publish an event.
|
||||
long processingTime = System.currentTimeMillis() - startTime;
|
||||
this.portletApplicationContext.publishEvent(
|
||||
new PortletRequestHandledEvent(this,
|
||||
getPortletConfig().getPortletName(), request.getPortletMode().toString(),
|
||||
(request instanceof ActionRequest ? "action" : "render"),
|
||||
request.getRequestedSessionId(), getUsernameForRequest(request),
|
||||
processingTime, failureCause));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a LocaleContext for the given request, exposing the request's
|
||||
* primary locale as current locale.
|
||||
* @param request current HTTP request
|
||||
* @return the corresponding LocaleContext
|
||||
*/
|
||||
protected LocaleContext buildLocaleContext(PortletRequest request) {
|
||||
return new SimpleLocaleContext(request.getLocale());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the username for the given request.
|
||||
* <p>The default implementation first tries the UserPrincipal.
|
||||
* If that does not exist, then it checks the USER_INFO map.
|
||||
* Can be overridden in subclasses.
|
||||
* @param request current portlet request
|
||||
* @return the username, or {@code null} if none found
|
||||
* @see javax.portlet.PortletRequest#getUserPrincipal()
|
||||
* @see javax.portlet.PortletRequest#getRemoteUser()
|
||||
* @see javax.portlet.PortletRequest#USER_INFO
|
||||
* @see #setUserinfoUsernameAttributes
|
||||
*/
|
||||
protected String getUsernameForRequest(PortletRequest request) {
|
||||
// Try the principal.
|
||||
Principal userPrincipal = request.getUserPrincipal();
|
||||
if (userPrincipal != null) {
|
||||
return userPrincipal.getName();
|
||||
}
|
||||
|
||||
// Try the remote user name.
|
||||
String userName = request.getRemoteUser();
|
||||
if (userName != null) {
|
||||
return userName;
|
||||
}
|
||||
|
||||
// Try the Portlet USER_INFO map.
|
||||
Map<?, ?> userInfo = (Map<?, ?>) request.getAttribute(PortletRequest.USER_INFO);
|
||||
if (userInfo != null) {
|
||||
for (int i = 0, n = this.userinfoUsernameAttributes.length; i < n; i++) {
|
||||
userName = (String) userInfo.get(this.userinfoUsernameAttributes[i]);
|
||||
if (userName != null) {
|
||||
return userName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Nothing worked...
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to do the work of action request handling.
|
||||
* <p>The contract is essentially the same as that for the {@code processAction}
|
||||
* method of GenericPortlet.
|
||||
* <p>This class intercepts calls to ensure that exception handling and
|
||||
* event publication takes place.
|
||||
* @param request current action request
|
||||
* @param response current action response
|
||||
* @throws Exception in case of any kind of processing failure
|
||||
* @see javax.portlet.GenericPortlet#processAction
|
||||
*/
|
||||
protected abstract void doActionService(ActionRequest request, ActionResponse response)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to do the work of render request handling.
|
||||
* <p>The contract is essentially the same as that for the {@code doDispatch}
|
||||
* method of GenericPortlet.
|
||||
* <p>This class intercepts calls to ensure that exception handling and
|
||||
* event publication takes place.
|
||||
* @param request current render request
|
||||
* @param response current render response
|
||||
* @throws Exception in case of any kind of processing failure
|
||||
* @see javax.portlet.GenericPortlet#doDispatch
|
||||
*/
|
||||
protected abstract void doRenderService(RenderRequest request, RenderResponse response)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to do the work of resource request handling.
|
||||
* <p>The contract is essentially the same as that for the {@code serveResource}
|
||||
* method of GenericPortlet.
|
||||
* <p>This class intercepts calls to ensure that exception handling and
|
||||
* event publication takes place.
|
||||
* @param request current resource request
|
||||
* @param response current resource response
|
||||
* @throws Exception in case of any kind of processing failure
|
||||
* @see javax.portlet.GenericPortlet#serveResource
|
||||
*/
|
||||
protected abstract void doResourceService(ResourceRequest request, ResourceResponse response)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method to do the work of event request handling.
|
||||
* <p>The contract is essentially the same as that for the {@code processEvent}
|
||||
* method of GenericPortlet.
|
||||
* <p>This class intercepts calls to ensure that exception handling and
|
||||
* event publication takes place.
|
||||
* @param request current event request
|
||||
* @param response current event response
|
||||
* @throws Exception in case of any kind of processing failure
|
||||
* @see javax.portlet.GenericPortlet#processEvent
|
||||
*/
|
||||
protected abstract void doEventService(EventRequest request, EventResponse response)
|
||||
throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Close the ApplicationContext of this portlet.
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#close()
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
getPortletContext().log("Destroying Spring FrameworkPortlet '" + getPortletName() + "'");
|
||||
if (this.portletApplicationContext instanceof ConfigurableApplicationContext) {
|
||||
((ConfigurableApplicationContext) this.portletApplicationContext).close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.portlet.GenericPortlet;
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.PropertyValue;
|
||||
import org.springframework.beans.PropertyValues;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.EnvironmentCapable;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.portlet.context.PortletContextResourceLoader;
|
||||
import org.springframework.web.portlet.context.StandardPortletEnvironment;
|
||||
|
||||
/**
|
||||
* Simple extension of {@code javax.portlet.GenericPortlet} that treats
|
||||
* its config parameters as bean properties.
|
||||
*
|
||||
* <p>A very handy superclass for any type of portlet. Type conversion is automatic.
|
||||
* It is also possible for subclasses to specify required properties.
|
||||
*
|
||||
* <p>This portlet leaves request handling to subclasses, inheriting the default
|
||||
* behaviour of GenericPortlet ({@code doDispatch}, {@code processAction}, etc).
|
||||
*
|
||||
* <p>This portlet superclass has no dependency on a Spring application context,
|
||||
* in contrast to the FrameworkPortlet class which loads its own context.
|
||||
*
|
||||
* @author William G. Thompson, Jr.
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #addRequiredProperty
|
||||
* @see #initPortletBean
|
||||
* @see #doDispatch
|
||||
* @see #processAction
|
||||
* @see FrameworkPortlet
|
||||
*/
|
||||
public abstract class GenericPortletBean extends GenericPortlet
|
||||
implements EnvironmentCapable, EnvironmentAware {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
/**
|
||||
* Set of required properties (Strings) that must be supplied as
|
||||
* config parameters to this portlet.
|
||||
*/
|
||||
private final Set<String> requiredProperties = new HashSet<String>();
|
||||
|
||||
private ConfigurableEnvironment environment;
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses can invoke this method to specify that this property
|
||||
* (which must match a JavaBean property they expose) is mandatory,
|
||||
* and must be supplied as a config parameter. This method would
|
||||
* normally be called from a subclass constructor.
|
||||
* @param property name of the required property
|
||||
*/
|
||||
protected final void addRequiredProperty(String property) {
|
||||
this.requiredProperties.add(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map config parameters onto bean properties of this portlet, and
|
||||
* invoke subclass initialization.
|
||||
* @throws PortletException if bean properties are invalid (or required
|
||||
* properties are missing), or if subclass initialization fails.
|
||||
*/
|
||||
@Override
|
||||
public final void init() throws PortletException {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Initializing portlet '" + getPortletName() + "'");
|
||||
}
|
||||
|
||||
// Set bean properties from init parameters.
|
||||
try {
|
||||
PropertyValues pvs = new PortletConfigPropertyValues(getPortletConfig(), this.requiredProperties);
|
||||
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
|
||||
ResourceLoader resourceLoader = new PortletContextResourceLoader(getPortletContext());
|
||||
bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
|
||||
initBeanWrapper(bw);
|
||||
bw.setPropertyValues(pvs, true);
|
||||
}
|
||||
catch (BeansException ex) {
|
||||
logger.error("Failed to set bean properties on portlet '" + getPortletName() + "'", ex);
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// let subclasses do whatever initialization they like
|
||||
initPortletBean();
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Portlet '" + getPortletName() + "' configured successfully");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the BeanWrapper for this GenericPortletBean,
|
||||
* possibly with custom editors.
|
||||
* @param bw the BeanWrapper to initialize
|
||||
* @throws BeansException if thrown by BeanWrapper methods
|
||||
* @see org.springframework.beans.BeanWrapper#registerCustomEditor
|
||||
*/
|
||||
protected void initBeanWrapper(BeanWrapper bw) throws BeansException {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden method that simply returns {@code null} when no
|
||||
* PortletConfig set yet.
|
||||
* @see #getPortletConfig()
|
||||
*/
|
||||
@Override
|
||||
public final String getPortletName() {
|
||||
return (getPortletConfig() != null ? getPortletConfig().getPortletName() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden method that simply returns {@code null} when no
|
||||
* PortletConfig set yet.
|
||||
* @see #getPortletConfig()
|
||||
*/
|
||||
@Override
|
||||
public final PortletContext getPortletContext() {
|
||||
return (getPortletConfig() != null ? getPortletConfig().getPortletContext() : null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses may override this to perform custom initialization.
|
||||
* All bean properties of this portlet will have been set before this
|
||||
* method is invoked. This default implementation does nothing.
|
||||
* @throws PortletException if subclass initialization fails
|
||||
*/
|
||||
protected void initPortletBean() throws PortletException {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws IllegalArgumentException if environment is not assignable to
|
||||
* {@code ConfigurableEnvironment}.
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironment(Environment environment) {
|
||||
Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
|
||||
this.environment = (ConfigurableEnvironment)environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>If {@code null}, a new environment will be initialized via
|
||||
* {@link #createEnvironment()}.
|
||||
*/
|
||||
@Override
|
||||
public ConfigurableEnvironment getEnvironment() {
|
||||
if (this.environment == null) {
|
||||
this.environment = this.createEnvironment();
|
||||
}
|
||||
return this.environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new {@link StandardPortletEnvironment}. Subclasses may override
|
||||
* in order to configure the environment or specialize the environment type returned.
|
||||
*/
|
||||
protected ConfigurableEnvironment createEnvironment() {
|
||||
return new StandardPortletEnvironment();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* PropertyValues implementation created from PortletConfig init parameters.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class PortletConfigPropertyValues extends MutablePropertyValues {
|
||||
|
||||
/**
|
||||
* Create new PortletConfigPropertyValues.
|
||||
* @param config PortletConfig we'll use to take PropertyValues from
|
||||
* @param requiredProperties set of property names we need, where
|
||||
* we can't accept default values
|
||||
* @throws PortletException if any required properties are missing
|
||||
*/
|
||||
private PortletConfigPropertyValues(PortletConfig config, Set<String> requiredProperties)
|
||||
throws PortletException {
|
||||
|
||||
Set<String> missingProps = (requiredProperties != null && !requiredProperties.isEmpty()) ?
|
||||
new HashSet<String>(requiredProperties) : null;
|
||||
|
||||
Enumeration<String> en = config.getInitParameterNames();
|
||||
while (en.hasMoreElements()) {
|
||||
String property = en.nextElement();
|
||||
Object value = config.getInitParameter(property);
|
||||
addPropertyValue(new PropertyValue(property, value));
|
||||
if (missingProps != null) {
|
||||
missingProps.remove(property);
|
||||
}
|
||||
}
|
||||
|
||||
// fail if we are still missing properties
|
||||
if (missingProps != null && missingProps.size() > 0) {
|
||||
throw new PortletException(
|
||||
"Initialization from PortletConfig for portlet '" + config.getPortletName() +
|
||||
"' failed; the following required properties were missing: " +
|
||||
StringUtils.collectionToDelimitedString(missingProps, ", "));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.EventRequest;
|
||||
import javax.portlet.EventResponse;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.portlet.ResourceRequest;
|
||||
import javax.portlet.ResourceResponse;
|
||||
|
||||
/**
|
||||
* Portlet MVC framework SPI interface, allowing parameterization of core MVC workflow.
|
||||
*
|
||||
* <p>Interface that must be implemented for each handler type to handle a request.
|
||||
* This interface is used to allow the DispatcherPortlet to be indefinitely
|
||||
* extensible. The DispatcherPortlet accesses all installed handlers through this
|
||||
* interface, meaning that it does not contain code specific to any handler type.
|
||||
*
|
||||
* <p>Note that a handler can be of type Object. This is to enable handlers from
|
||||
* other frameworks to be integrated with this framework without custom coding.
|
||||
*
|
||||
* <p>This interface is not intended for application developers. It is available
|
||||
* to handlers who want to develop their own web workflow.
|
||||
*
|
||||
* <p>Note: Implementations can implement the Ordered interface to be able to
|
||||
* specify a sorting order and thus a priority for getting applied by
|
||||
* DispatcherPortlet. Non-Ordered instances get treated as lowest priority.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter
|
||||
*/
|
||||
public interface HandlerAdapter {
|
||||
|
||||
/**
|
||||
* Given a handler instance, return whether or not this HandlerAdapter can
|
||||
* support it. Typical HandlerAdapters will base the decision on the handler
|
||||
* type. HandlerAdapters will usually only support one handler type each.
|
||||
* <p>A typical implementation:
|
||||
* <p>{@code
|
||||
* return (handler instanceof MyHandler);
|
||||
* }
|
||||
* @param handler handler object to check
|
||||
* @return whether or not this object can use the given handler
|
||||
*/
|
||||
boolean supports(Object handler);
|
||||
|
||||
/**
|
||||
* Use the given handler to handle this action request.
|
||||
* The workflow that is required may vary widely.
|
||||
* @param request current action request
|
||||
* @param response current action response
|
||||
* @param handler handler to use. This object must have previously been passed
|
||||
* to the {@code supports} method of this interface, which must have
|
||||
* returned true.
|
||||
* @throws Exception in case of errors
|
||||
* @see javax.portlet.Portlet#processAction
|
||||
*/
|
||||
void handleAction(ActionRequest request, ActionResponse response, Object handler) throws Exception;
|
||||
|
||||
/**
|
||||
* Use the given handler to handle this render request.
|
||||
* The workflow that is required may vary widely.
|
||||
* @param request current render request
|
||||
* @param response current render response
|
||||
* @param handler handler to use. This object must have previously been passed
|
||||
* to the {@code supports} method of this interface, which must have
|
||||
* returned {@code true}.
|
||||
* @throws Exception in case of errors
|
||||
* @return ModelAndView object with the name of the view and the required
|
||||
* model data, or {@code null} if the request has been handled directly
|
||||
* @see javax.portlet.Portlet#render
|
||||
*/
|
||||
ModelAndView handleRender(RenderRequest request, RenderResponse response, Object handler) throws Exception;
|
||||
|
||||
/**
|
||||
* Use the given handler to handle this resource request.
|
||||
* The workflow that is required may vary widely.
|
||||
* @param request current render request
|
||||
* @param response current render response
|
||||
* @param handler handler to use. This object must have previously been passed
|
||||
* to the {@code supports} method of this interface, which must have
|
||||
* returned {@code true}.
|
||||
* @throws Exception in case of errors
|
||||
* @return ModelAndView object with the name of the view and the required
|
||||
* model data, or {@code null} if the request has been handled directly
|
||||
* @see javax.portlet.ResourceServingPortlet#serveResource
|
||||
*/
|
||||
ModelAndView handleResource(ResourceRequest request, ResourceResponse response, Object handler) throws Exception;
|
||||
|
||||
/**
|
||||
* Use the given handler to handle this event request.
|
||||
* The workflow that is required may vary widely.
|
||||
* @param request current action request
|
||||
* @param response current action response
|
||||
* @param handler handler to use. This object must have previously been passed
|
||||
* to the {@code supports} method of this interface, which must have
|
||||
* returned true.
|
||||
* @throws Exception in case of errors
|
||||
* @see javax.portlet.EventPortlet#processEvent
|
||||
*/
|
||||
void handleEvent(EventRequest request, EventResponse response, Object handler) throws Exception;
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.portlet.ResourceRequest;
|
||||
import javax.portlet.ResourceResponse;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects than can resolve exceptions thrown
|
||||
* during handler mapping or execution, in the typical case to error views.
|
||||
* Implementors are typically registered as beans in the application context.
|
||||
*
|
||||
* <p>Error views are analogous to the error page JSPs, but can be used with
|
||||
* any kind of exception including any checked exception, with potentially
|
||||
* fine-granular mappings for specific handlers.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface HandlerExceptionResolver {
|
||||
|
||||
/**
|
||||
* Try to resolve the given exception that got thrown during on handler execution,
|
||||
* returning a ModelAndView that represents a specific error page if appropriate.
|
||||
* @param request current portlet request
|
||||
* @param response current portlet response
|
||||
* @param handler the executed handler, or null if none chosen at the time of
|
||||
* the exception (for example, if multipart resolution failed)
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @return a corresponding ModelAndView to forward to,
|
||||
* or {@code null} for default processing
|
||||
*/
|
||||
ModelAndView resolveException(
|
||||
RenderRequest request, RenderResponse response, Object handler, Exception ex);
|
||||
|
||||
/**
|
||||
* Try to resolve the given exception that got thrown during on handler execution,
|
||||
* returning a ModelAndView that represents a specific error page if appropriate.
|
||||
* @param request current portlet request
|
||||
* @param response current portlet response
|
||||
* @param handler the executed handler, or null if none chosen at the time of
|
||||
* the exception (for example, if multipart resolution failed)
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @return a corresponding ModelAndView to forward to,
|
||||
* or {@code null} for default processing
|
||||
*/
|
||||
ModelAndView resolveException(
|
||||
ResourceRequest request, ResourceResponse response, Object handler, Exception ex);
|
||||
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Handler execution chain, consisting of handler object and any handler interceptors.
|
||||
* Returned by HandlerMapping's {@link HandlerMapping#getHandler} method.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see HandlerInterceptor
|
||||
*/
|
||||
public class HandlerExecutionChain {
|
||||
|
||||
private final Object handler;
|
||||
|
||||
private HandlerInterceptor[] interceptors;
|
||||
|
||||
private List<HandlerInterceptor> interceptorList;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new HandlerExecutionChain.
|
||||
* @param handler the handler object to execute
|
||||
*/
|
||||
public HandlerExecutionChain(Object handler) {
|
||||
this(handler, (HandlerInterceptor[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new HandlerExecutionChain.
|
||||
* @param handler the handler object to execute
|
||||
* @param interceptors the array of interceptors to apply
|
||||
* (in the given order) before the handler itself executes
|
||||
*/
|
||||
public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
|
||||
if (handler instanceof HandlerExecutionChain) {
|
||||
HandlerExecutionChain originalChain = (HandlerExecutionChain) handler;
|
||||
this.handler = originalChain.getHandler();
|
||||
this.interceptorList = new ArrayList<HandlerInterceptor>();
|
||||
CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
|
||||
CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
|
||||
}
|
||||
else {
|
||||
this.handler = handler;
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the handler object to execute.
|
||||
* @return the handler object
|
||||
*/
|
||||
public Object getHandler() {
|
||||
return this.handler;
|
||||
}
|
||||
|
||||
public void addInterceptor(HandlerInterceptor interceptor) {
|
||||
initInterceptorList().add(interceptor);
|
||||
}
|
||||
|
||||
public void addInterceptors(HandlerInterceptor... interceptors) {
|
||||
if (!ObjectUtils.isEmpty(interceptors)) {
|
||||
initInterceptorList().addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
}
|
||||
|
||||
private List<HandlerInterceptor> initInterceptorList() {
|
||||
if (this.interceptorList == null) {
|
||||
this.interceptorList = new ArrayList<HandlerInterceptor>();
|
||||
if (this.interceptors != null) {
|
||||
// An interceptor array specified through the constructor
|
||||
this.interceptorList.addAll(Arrays.asList(this.interceptors));
|
||||
}
|
||||
}
|
||||
this.interceptors = null;
|
||||
return this.interceptorList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the array of interceptors to apply (in the given order).
|
||||
* @return the array of HandlerInterceptors instances (may be {@code null})
|
||||
*/
|
||||
public HandlerInterceptor[] getInterceptors() {
|
||||
if (this.interceptors == null && this.interceptorList != null) {
|
||||
this.interceptors = this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
|
||||
}
|
||||
return this.interceptors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delegates to the handler's {@code toString()}.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(this.handler);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet;
|
||||
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.ActionResponse;
|
||||
import javax.portlet.EventRequest;
|
||||
import javax.portlet.EventResponse;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.portlet.ResourceRequest;
|
||||
import javax.portlet.ResourceResponse;
|
||||
|
||||
/**
|
||||
* Workflow interface that allows for customized handler execution chains.
|
||||
* Applications can register any number of existing or custom interceptors
|
||||
* for certain groups of handlers, to add common pre-processing behavior
|
||||
* without needing to modify each handler implementation.
|
||||
*
|
||||
* <p>A {@code HandlerInterceptor} gets called before the appropriate
|
||||
* {@link HandlerAdapter} triggers the
|
||||
* execution of the handler itself. This mechanism can be used for a large
|
||||
* field of preprocessing aspects, e.g. for authorization checks,
|
||||
* or common handler behavior like locale or theme changes. Its main purpose
|
||||
* is to permit the factoring out of otherwise repetitive handler code.
|
||||
*
|
||||
* <p>Typically an interceptor chain is defined per
|
||||
* {@link HandlerMapping} bean, sharing its
|
||||
* granularity. To be able to apply a certain interceptor chain to a group of
|
||||
* handlers, one needs to map the desired handlers via one
|
||||
* {@code HandlerMapping} bean. The interceptors themselves are defined as
|
||||
* beans in the application context, referenced by the mapping bean definition
|
||||
* via its
|
||||
* {@link org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors "interceptors"}
|
||||
* property (in XML: a <list> of <ref> elements).
|
||||
*
|
||||
* <p>A {@code HandlerInterceptor} is basically similar to a Servlet
|
||||
* {@link javax.servlet.Filter}, but in contrast to the latter it allows
|
||||
* custom pre-processing with the option to prohibit the execution of the handler
|
||||
* itself, and custom post-processing. {@code Filters} are more powerful;
|
||||
* for example they allow for exchanging the request and response objects that
|
||||
* are handed down the chain. Note that a filter gets configured in
|
||||
* {@code web.xml}, a {@code HandlerInterceptor} in the application context.
|
||||
*
|
||||
* <p>As a basic guideline, fine-grained handler-related pre-processing tasks are
|
||||
* candidates for {@code HandlerInterceptor} implementations, especially
|
||||
* factored-out common handler code and authorization checks. On the other hand,
|
||||
* a {@code Filter} is well-suited for request content and view content
|
||||
* handling, like multipart forms and GZIP compression. This typically shows when
|
||||
* one needs to map the filter to certain content types (e.g. images), or to all
|
||||
* requests.
|
||||
*
|
||||
* <p>Be aware that filters cannot be applied to portlet requests (they
|
||||
* only operate on servlet requests), so for portlet requests interceptors are
|
||||
* essential.
|
||||
*
|
||||
* <p>If we assume a "sunny day" request cycle (i.e. a request where nothing goes wrong
|
||||
* and all is well), the workflow of a {@code HandlerInterceptor} will be as
|
||||
* follows:
|
||||
*
|
||||
* <p><b>Action Request:</b><p>
|
||||
* <ol>
|
||||
* <li>{@code DispatcherPortlet} maps the action request to a particular handler and
|
||||
* assembles a handler execution chain consisting of the handler that is to be invoked
|
||||
* and all of the {@code HandlerInterceptor} instances that apply to the request.</li>
|
||||
* <li>{@link HandlerInterceptor#preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) preHandleAction(..)}
|
||||
* is called; if the invocation of this method returns {@code true} then this workflow continues.</li>
|
||||
* <li>The target handler handles the action request (via
|
||||
* {@link HandlerAdapter#handleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object) HandlerAdapter.handleAction(..)}).</li>
|
||||
* <li>{@link HandlerInterceptor#afterActionCompletion(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object, Exception) afterActionCompletion(..)}
|
||||
* is called.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p><b>Render Request:</b><p>
|
||||
* <ol>
|
||||
* <li>{@code DispatcherPortlet} maps the render request to a particular handler and
|
||||
* assembles a handler execution chain consisting of the handler that is to be invoked
|
||||
* and all of the {@code HandlerInterceptor} instances that apply to the request.</li>
|
||||
* <li>{@link HandlerInterceptor#preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) preHandleRender(..)}
|
||||
* is called; if the invocation of this method returns {@code true} then this workflow continues.</li>
|
||||
* <li>The target handler handles the render request (via
|
||||
* {@link HandlerAdapter#handleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object) HandlerAdapter.handleRender(..)}).</li>
|
||||
* <li>{@link HandlerInterceptor#postHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, ModelAndView) postHandleRender(..)}
|
||||
* is called.</li>
|
||||
* <li>If the {@code HandlerAdapter} returned a {@code ModelAndView}, then
|
||||
* {@code DispatcherPortlet} renders the view accordingly.
|
||||
* <li>{@link HandlerInterceptor#afterRenderCompletion(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object, Exception) afterRenderCompletion(..)}
|
||||
* is called.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see HandlerExecutionChain#getInterceptors
|
||||
* @see HandlerMapping
|
||||
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping#setInterceptors
|
||||
* @see HandlerExecutionChain
|
||||
*/
|
||||
public interface HandlerInterceptor {
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the action phase.
|
||||
* <p>Called after a HandlerMapping determines an appropriate handler object
|
||||
* to handle an {@link ActionRequest}, but before said HandlerAdapter actually
|
||||
* invokes the handler.
|
||||
* <p>{@link DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can decide to abort the execution chain,
|
||||
* typically throwing an exception or writing a custom response.
|
||||
* @param request current portlet action request
|
||||
* @param response current portlet action response
|
||||
* @param handler chosen handler to execute, for type and/or instance evaluation
|
||||
* @return {@code true} if the execution chain should proceed with the
|
||||
* next interceptor or the handler itself. Else, {@code DispatcherPortlet}
|
||||
* assumes that this interceptor has already dealt with the response itself
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
boolean preHandleAction(ActionRequest request, ActionResponse response, Object handler)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Callback after completion of request processing in the action phase, that is,
|
||||
* after rendering the view. Will be called on any outcome of handler execution,
|
||||
* thus allowing for proper resource cleanup.
|
||||
* <p>Note: Will only be called if this interceptor's
|
||||
* {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
|
||||
* method has successfully completed and returned {@code true}!
|
||||
* @param request current portlet action request
|
||||
* @param response current portlet action response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param ex exception thrown on handler execution, if any (only included as
|
||||
* additional context information for the case where a handler threw an exception;
|
||||
* request execution may have failed even when this argument is {@code null})
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void afterActionCompletion(ActionRequest request, ActionResponse response, Object handler, Exception ex)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the render phase.
|
||||
* <p>Called after a HandlerMapping determines an appropriate handler object
|
||||
* to handle a {@link RenderRequest}, but before said HandlerAdapter actually
|
||||
* invokes the handler.
|
||||
* <p>{@link DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can decide to abort the execution chain,
|
||||
* typically throwing an exception or writing a custom response.
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance evaluation
|
||||
* @return {@code true} if the execution chain should proceed with the
|
||||
* next interceptor or the handler itself. Else, {@code DispatcherPortlet}
|
||||
* assumes that this interceptor has already dealt with the response itself
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
boolean preHandleRender(RenderRequest request, RenderResponse response, Object handler)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the render phase.
|
||||
* <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
|
||||
* before the {@code DispatcherPortlet} renders the view. Can thus expose
|
||||
* additional model objects to the view via the given {@link ModelAndView}.
|
||||
* <p>{@code DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can post-process an execution, getting
|
||||
* applied in inverse order of the execution chain.
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param modelAndView the {@code ModelAndView} that the handler returned
|
||||
* (can also be {@code null})
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void postHandleRender(RenderRequest request, RenderResponse response, Object handler, ModelAndView modelAndView)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Callback after completion of request processing, that is, after rendering
|
||||
* the view. Will be called on any outcome of handler execution, thus allowing
|
||||
* for proper resource cleanup.
|
||||
* <p>Note: Will only be called if this interceptor's
|
||||
* {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
|
||||
* method has successfully completed and returned {@code true}!
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param ex exception thrown on handler execution, if any
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void afterRenderCompletion(RenderRequest request, RenderResponse response, Object handler, Exception ex)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the render phase.
|
||||
* <p>Called after a HandlerMapping determines an appropriate handler object
|
||||
* to handle a {@link RenderRequest}, but before said HandlerAdapter actually
|
||||
* invokes the handler.
|
||||
* <p>{@link DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can decide to abort the execution chain,
|
||||
* typically throwing an exception or writing a custom response.
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance evaluation
|
||||
* @return {@code true} if the execution chain should proceed with the
|
||||
* next interceptor or the handler itself. Else, {@code DispatcherPortlet}
|
||||
* assumes that this interceptor has already dealt with the response itself
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
boolean preHandleResource(ResourceRequest request, ResourceResponse response, Object handler)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the render phase.
|
||||
* <p>Called after a {@link HandlerAdapter} actually invoked the handler, but
|
||||
* before the {@code DispatcherPortlet} renders the view. Can thus expose
|
||||
* additional model objects to the view via the given {@link ModelAndView}.
|
||||
* <p>{@code DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can post-process an execution, getting
|
||||
* applied in inverse order of the execution chain.
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param modelAndView the {@code ModelAndView} that the handler returned
|
||||
* (can also be {@code null})
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void postHandleResource(ResourceRequest request, ResourceResponse response, Object handler, ModelAndView modelAndView)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Callback after completion of request processing, that is, after rendering
|
||||
* the view. Will be called on any outcome of handler execution, thus allowing
|
||||
* for proper resource cleanup.
|
||||
* <p>Note: Will only be called if this interceptor's
|
||||
* {@link #preHandleRender(javax.portlet.RenderRequest, javax.portlet.RenderResponse, Object)}
|
||||
* method has successfully completed and returned {@code true}!
|
||||
* @param request current portlet render request
|
||||
* @param response current portlet render response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param ex exception thrown on handler execution, if any
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void afterResourceCompletion(ResourceRequest request, ResourceResponse response, Object handler, Exception ex)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Intercept the execution of a handler in the action phase.
|
||||
* <p>Called after a HandlerMapping determines an appropriate handler object
|
||||
* to handle an {@link ActionRequest}, but before said HandlerAdapter actually
|
||||
* invokes the handler.
|
||||
* <p>{@link DispatcherPortlet} processes a handler in an execution chain,
|
||||
* consisting of any number of interceptors, with the handler itself at the end.
|
||||
* With this method, each interceptor can decide to abort the execution chain,
|
||||
* typically throwing an exception or writing a custom response.
|
||||
* @param request current portlet action request
|
||||
* @param response current portlet action response
|
||||
* @param handler chosen handler to execute, for type and/or instance evaluation
|
||||
* @return {@code true} if the execution chain should proceed with the
|
||||
* next interceptor or the handler itself. Else, {@code DispatcherPortlet}
|
||||
* assumes that this interceptor has already dealt with the response itself
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
boolean preHandleEvent(EventRequest request, EventResponse response, Object handler)
|
||||
throws Exception;
|
||||
|
||||
/**
|
||||
* Callback after completion of request processing in the action phase, that is,
|
||||
* after rendering the view. Will be called on any outcome of handler execution,
|
||||
* thus allowing for proper resource cleanup.
|
||||
* <p>Note: Will only be called if this interceptor's
|
||||
* {@link #preHandleAction(javax.portlet.ActionRequest, javax.portlet.ActionResponse, Object)}
|
||||
* method has successfully completed and returned {@code true}!
|
||||
* @param request current portlet action request
|
||||
* @param response current portlet action response
|
||||
* @param handler chosen handler to execute, for type and/or instance examination
|
||||
* @param ex exception thrown on handler execution, if any (only included as
|
||||
* additional context information for the case where a handler threw an exception;
|
||||
* request execution may have failed even when this argument is {@code null})
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
void afterEventCompletion(EventRequest request, EventResponse response, Object handler, Exception ex)
|
||||
throws Exception;
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects that define a mapping between
|
||||
* requests and handler objects.
|
||||
*
|
||||
* <p>This class can be implemented by application developers, although this is not
|
||||
* necessary, as {@link org.springframework.web.portlet.handler.PortletModeHandlerMapping},
|
||||
* {@link org.springframework.web.portlet.handler.ParameterHandlerMapping} and
|
||||
* {@link org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping}
|
||||
* are included in the framework. The first is the default if no HandlerMapping
|
||||
* bean is registered in the portlet application context.
|
||||
*
|
||||
* <p>HandlerMapping implementations can support mapped interceptors but do not
|
||||
* have to. A handler will always be wrapped in a {@link HandlerExecutionChain}
|
||||
* instance, optionally accompanied by some {@link HandlerInterceptor} instances.
|
||||
* The DispatcherPortlet will first call each HandlerInterceptor's
|
||||
* {@code preHandle} method in the given order, finally invoking the handler
|
||||
* itself if all {@code preHandle} methods have returned {@code true}.
|
||||
*
|
||||
* <p>The ability to parameterize this mapping is a powerful and unusual
|
||||
* capability of this Portlet MVC framework. For example, it is possible to
|
||||
* write a custom mapping based on session state, cookie state or many other
|
||||
* variables. No other MVC framework seems to be equally flexible.
|
||||
*
|
||||
* <p>Note: Implementations can implement the {@link org.springframework.core.Ordered}
|
||||
* interface to be able to specify a sorting order and thus a priority for getting
|
||||
* applied by DispatcherPortlet. Non-Ordered instances get treated as lowest priority.
|
||||
*
|
||||
* @author John A. Lewis
|
||||
* @author Juergen Hoeller
|
||||
* @see org.springframework.core.Ordered
|
||||
* @see org.springframework.web.portlet.handler.AbstractHandlerMapping
|
||||
* @see org.springframework.web.portlet.handler.PortletModeHandlerMapping
|
||||
* @see org.springframework.web.portlet.handler.ParameterHandlerMapping
|
||||
* @see org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping
|
||||
*/
|
||||
public interface HandlerMapping {
|
||||
|
||||
/**
|
||||
* Return a handler and any interceptors for this request. The choice may be made
|
||||
* on portlet mode, session state, or any factor the implementing class chooses.
|
||||
* <p>The returned HandlerExecutionChain contains a handler Object, rather than
|
||||
* even a tag interface, so that handlers are not constrained in any way.
|
||||
* For example, a HandlerAdapter could be written to allow another framework's
|
||||
* handler objects to be used.
|
||||
* <p>Returns {@code null} if no match was found. This is not an error.
|
||||
* The DispatcherPortlet will query all registered HandlerMapping beans to find
|
||||
* a match, and only decide there is an error if none can find a handler.
|
||||
* @param request current portlet request
|
||||
* @return a HandlerExecutionChain instance containing handler object and
|
||||
* any interceptors, or null if no mapping found
|
||||
* @throws Exception if there is an internal error
|
||||
*/
|
||||
HandlerExecutionChain getHandler(PortletRequest request) throws Exception;
|
||||
|
||||
}
|
||||
@@ -1,305 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Holder for both Model and View in the web MVC framework.
|
||||
* Note that these are entirely distinct. This class merely holds
|
||||
* both to make it possible for a controller to return both model
|
||||
* and view in a single return value.
|
||||
*
|
||||
* <p>Represents a model and view returned by a handler, to be resolved
|
||||
* by a DispatcherPortlet. The view can take the form of a String
|
||||
* view name which will need to be resolved by a ViewResolver object;
|
||||
* alternatively a view object can be specified directly. The model
|
||||
* is a Map, allowing the use of multiple objects keyed by name.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
* @see org.springframework.web.servlet.ViewResolver
|
||||
* @see org.springframework.web.portlet.HandlerAdapter
|
||||
* @see org.springframework.web.portlet.mvc.Controller
|
||||
*/
|
||||
public class ModelAndView {
|
||||
|
||||
/** View instance or view name String */
|
||||
private Object view;
|
||||
|
||||
/** Model Map */
|
||||
private ModelMap model;
|
||||
|
||||
/**
|
||||
* Indicates whether or not this instance has been cleared with a call to {@link #clear()}.
|
||||
*/
|
||||
private boolean cleared = false;
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor for bean-style usage: populating bean
|
||||
* properties instead of passing in constructor arguments.
|
||||
* @see #setView(Object)
|
||||
* @see #setViewName(String)
|
||||
*/
|
||||
public ModelAndView() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor when there is no model data to expose.
|
||||
* Can also be used in conjunction with {@code addObject}.
|
||||
* @param viewName name of the View to render, to be resolved
|
||||
* by the DispatcherPortlet's ViewResolver
|
||||
* @see #addObject
|
||||
*/
|
||||
public ModelAndView(String viewName) {
|
||||
this.view = viewName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor when there is no model data to expose.
|
||||
* Can also be used in conjunction with {@code addObject}.
|
||||
* @param view View object to render (usually a Servlet MVC View object)
|
||||
* @see #addObject
|
||||
*/
|
||||
public ModelAndView(Object view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ModelAndView given a view name and a model.
|
||||
* @param viewName name of the View to render, to be resolved
|
||||
* by the DispatcherPortlet's ViewResolver
|
||||
* @param model Map of model names (Strings) to model objects
|
||||
* (Objects). Model entries may not be {@code null}, but the
|
||||
* model Map may be {@code null} if there is no model data.
|
||||
*/
|
||||
public ModelAndView(String viewName, Map<String, ?> model) {
|
||||
this.view = viewName;
|
||||
if (model != null) {
|
||||
getModelMap().addAllAttributes(model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ModelAndView given a View object and a model.
|
||||
* @param view View object to render (usually a Servlet MVC View object)
|
||||
* @param model Map of model names (Strings) to model objects
|
||||
* (Objects). Model entries may not be {@code null}, but the
|
||||
* model Map may be {@code null} if there is no model data.
|
||||
*/
|
||||
public ModelAndView(Object view, Map<String, ?> model) {
|
||||
this.view = view;
|
||||
if (model != null) {
|
||||
getModelMap().addAllAttributes(model);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor to take a single model object.
|
||||
* @param viewName name of the View to render, to be resolved
|
||||
* by the DispatcherPortlet's ViewResolver
|
||||
* @param modelName name of the single entry in the model
|
||||
* @param modelObject the single model object
|
||||
*/
|
||||
public ModelAndView(String viewName, String modelName, Object modelObject) {
|
||||
this.view = viewName;
|
||||
addObject(modelName, modelObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient constructor to take a single model object.
|
||||
* @param view View object to render (usually a Servlet MVC View object)
|
||||
* @param modelName name of the single entry in the model
|
||||
* @param modelObject the single model object
|
||||
*/
|
||||
public ModelAndView(Object view, String modelName, Object modelObject) {
|
||||
this.view = view;
|
||||
addObject(modelName, modelObject);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a view name for this ModelAndView, to be resolved by the
|
||||
* DispatcherPortlet via a ViewResolver. Will override any
|
||||
* pre-existing view name or View.
|
||||
*/
|
||||
public void setViewName(String viewName) {
|
||||
this.view = viewName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the view name to be resolved by the DispatcherPortlet
|
||||
* via a ViewResolver, or {@code null} if we are using a view object.
|
||||
*/
|
||||
public String getViewName() {
|
||||
return (this.view instanceof String ? (String) this.view : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a View object for this ModelAndView. Will override any
|
||||
* pre-existing view name or View.
|
||||
* <p>The given View object will usually be a Servlet MVC View object.
|
||||
* This is nevertheless typed as Object to avoid a Servlet API dependency
|
||||
* in the Portlet ModelAndView class.
|
||||
*/
|
||||
public void setView(Object view) {
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the View object, or {@code null} if we are using a view name
|
||||
* to be resolved by the DispatcherPortlet via a ViewResolver.
|
||||
*/
|
||||
public Object getView() {
|
||||
return (!(this.view instanceof String) ? this.view : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether or not this {@code ModelAndView} has a view, either
|
||||
* as a view name or as a direct view instance.
|
||||
*/
|
||||
public boolean hasView() {
|
||||
return (this.view != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether we use a view reference, i.e. {@code true}
|
||||
* if the view has been specified via a name to be resolved by the
|
||||
* DispatcherPortlet via a ViewResolver.
|
||||
*/
|
||||
public boolean isReference() {
|
||||
return (this.view instanceof String);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the model map. May return {@code null}.
|
||||
* Called by DispatcherPortlet for evaluation of the model.
|
||||
*/
|
||||
protected Map<String, Object> getModelInternal() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying {@code ModelMap} instance (never {@code null}).
|
||||
*/
|
||||
public ModelMap getModelMap() {
|
||||
if (this.model == null) {
|
||||
this.model = new ModelMap();
|
||||
}
|
||||
return this.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the model map. Never returns {@code null}.
|
||||
* To be called by application code for modifying the model.
|
||||
*/
|
||||
public Map<String, Object> getModel() {
|
||||
return getModelMap();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an attribute to the model.
|
||||
* @param attributeName name of the object to add to the model
|
||||
* @param attributeValue object to add to the model (never {@code null})
|
||||
* @see ModelMap#addAttribute(String, Object)
|
||||
* @see #getModelMap()
|
||||
*/
|
||||
public ModelAndView addObject(String attributeName, Object attributeValue) {
|
||||
getModelMap().addAttribute(attributeName, attributeValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an attribute to the model using parameter name generation.
|
||||
* @param attributeValue the object to add to the model (never {@code null})
|
||||
* @see ModelMap#addAttribute(Object)
|
||||
* @see #getModelMap()
|
||||
*/
|
||||
public ModelAndView addObject(Object attributeValue) {
|
||||
getModelMap().addAttribute(attributeValue);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all attributes contained in the provided Map to the model.
|
||||
* @param modelMap a Map of attributeName -> attributeValue pairs
|
||||
* @see ModelMap#addAllAttributes(Map)
|
||||
* @see #getModelMap()
|
||||
*/
|
||||
public ModelAndView addAllObjects(Map<String, ?> modelMap) {
|
||||
getModelMap().addAllAttributes(modelMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear the state of this ModelAndView object.
|
||||
* The object will be empty afterwards.
|
||||
* <p>Can be used to suppress rendering of a given ModelAndView object
|
||||
* in the {@code postHandleRender} method of a HandlerInterceptor.
|
||||
* @see #isEmpty()
|
||||
* @see HandlerInterceptor#postHandleRender
|
||||
*/
|
||||
public void clear() {
|
||||
this.view = null;
|
||||
this.model = null;
|
||||
this.cleared = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this ModelAndView object is empty,
|
||||
* i.e. whether it does not hold any view and does not contain a model.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return (this.view == null && CollectionUtils.isEmpty(this.model));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this ModelAndView object is empty as a result of a call to {@link #clear}
|
||||
* i.e. whether it does not hold any view and does not contain a model.
|
||||
* Returns {@code false} if any additional state was added to the instance
|
||||
* <strong>after</strong> the call to {@link #clear}.
|
||||
* @see #clear()
|
||||
*/
|
||||
public boolean wasCleared() {
|
||||
return (this.cleared && isEmpty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return diagnostic information about this model and view.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder("ModelAndView: ");
|
||||
if (isReference()) {
|
||||
result.append("reference to view with name '").append(this.view).append("'");
|
||||
}
|
||||
else {
|
||||
result.append("materialized View is [").append(this.view).append(']');
|
||||
}
|
||||
result.append("; model is ").append(this.model);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import javax.portlet.PortletException;
|
||||
|
||||
/**
|
||||
* Exception to be thrown on error conditions that should forward
|
||||
* to a specific view with a specific model.
|
||||
*
|
||||
* <p>Can be thrown at any time during handler processing.
|
||||
* This includes any template methods of pre-built controllers.
|
||||
* For example, a form controller might abort to a specific error page
|
||||
* if certain parameters do not allow to proceed with the normal workflow.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class ModelAndViewDefiningException extends PortletException {
|
||||
|
||||
private ModelAndView modelAndView;
|
||||
|
||||
|
||||
/**
|
||||
* Create new ModelAndViewDefiningException with the given ModelAndView,
|
||||
* typically representing a specific error page.
|
||||
* @param modelAndView ModelAndView with view to forward to and model to expose
|
||||
*/
|
||||
public ModelAndViewDefiningException(ModelAndView modelAndView) {
|
||||
if (modelAndView == null) {
|
||||
throw new IllegalArgumentException("modelAndView must not be null in ModelAndViewDefiningException");
|
||||
}
|
||||
this.modelAndView = modelAndView;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ModelAndView that this exception contains for forwarding to.
|
||||
*/
|
||||
public ModelAndView getModelAndView() {
|
||||
return modelAndView;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet;
|
||||
|
||||
import javax.portlet.PortletException;
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.core.style.StylerUtils;
|
||||
|
||||
/**
|
||||
* Exception to be thrown if DispatcherPortlet is unable to determine
|
||||
* a corresponding handler for an incoming portlet request.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0.5
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class NoHandlerFoundException extends PortletException {
|
||||
|
||||
/**
|
||||
* Constructor for NoHandlerFoundException.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public NoHandlerFoundException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for NoHandlerFoundException.
|
||||
* @param msg the detail message
|
||||
* @param request the current portlet request,
|
||||
* for further context to be included in the exception message
|
||||
*/
|
||||
public NoHandlerFoundException(String msg, PortletRequest request) {
|
||||
super(msg + ": mode '" + request.getPortletMode() +
|
||||
"', phase '" + request.getAttribute(PortletRequest.LIFECYCLE_PHASE) +
|
||||
"', parameters " + StylerUtils.style(request.getParameterMap()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.bind;
|
||||
|
||||
/**
|
||||
* {@link PortletRequestBindingException} subclass that indicates a missing parameter.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0.2
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MissingPortletRequestParameterException extends PortletRequestBindingException {
|
||||
|
||||
private final String parameterName;
|
||||
|
||||
private final String parameterType;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor for MissingPortletRequestParameterException.
|
||||
* @param parameterName the name of the missing parameter
|
||||
* @param parameterType the expected type of the missing parameter
|
||||
*/
|
||||
public MissingPortletRequestParameterException(String parameterName, String parameterType) {
|
||||
super("");
|
||||
this.parameterName = parameterName;
|
||||
this.parameterType = parameterType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return "Required " + this.parameterType + " parameter '" + parameterName + "' is not present";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the offending parameter.
|
||||
*/
|
||||
public final String getParameterName() {
|
||||
return this.parameterName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expected type of the offending parameter.
|
||||
*/
|
||||
public final String getParameterType() {
|
||||
return this.parameterType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.bind;
|
||||
|
||||
import javax.portlet.PortletException;
|
||||
|
||||
/**
|
||||
* Fatal binding exception, thrown when we want to
|
||||
* treat binding exceptions as unrecoverable.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PortletRequestBindingException extends PortletException {
|
||||
|
||||
/**
|
||||
* Constructor for PortletRequestBindingException.
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public PortletRequestBindingException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for PortletRequestBindingException.
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause
|
||||
*/
|
||||
public PortletRequestBindingException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.bind;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.web.bind.WebDataBinder;
|
||||
import org.springframework.web.multipart.MultipartRequest;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* Special {@link org.springframework.validation.DataBinder} to perform data binding
|
||||
* from portlet request parameters to JavaBeans, including support for multipart files.
|
||||
*
|
||||
* <p>See the DataBinder/WebDataBinder superclasses for customization options,
|
||||
* which include specifying allowed/required fields, and registering custom
|
||||
* property editors.
|
||||
*
|
||||
* <p>Can also be used for manual data binding in custom web controllers:
|
||||
* for example, in a plain Portlet Controller implementation. Simply instantiate
|
||||
* a PortletRequestDataBinder for each binding process, and invoke {@code bind}
|
||||
* with the current PortletRequest as argument:
|
||||
*
|
||||
* <pre class="code">
|
||||
* MyBean myBean = new MyBean();
|
||||
* // apply binder to custom target object
|
||||
* PortletRequestDataBinder binder = new PortletRequestDataBinder(myBean);
|
||||
* // register custom editors, if desired
|
||||
* binder.registerCustomEditor(...);
|
||||
* // trigger actual binding of request parameters
|
||||
* binder.bind(request);
|
||||
* // optionally evaluate binding errors
|
||||
* Errors errors = binder.getErrors();
|
||||
* ...</pre>
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #bind(javax.portlet.PortletRequest)
|
||||
* @see #registerCustomEditor
|
||||
* @see #setAllowedFields
|
||||
* @see #setRequiredFields
|
||||
* @see #setFieldMarkerPrefix
|
||||
*/
|
||||
public class PortletRequestDataBinder extends WebDataBinder {
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestDataBinder instance, with default object name.
|
||||
* @param target the target object to bind onto (or {@code null}
|
||||
* if the binder is just used to convert a plain parameter value)
|
||||
* @see #DEFAULT_OBJECT_NAME
|
||||
*/
|
||||
public PortletRequestDataBinder(Object target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestDataBinder instance.
|
||||
* @param target the target object to bind onto (or {@code null}
|
||||
* if the binder is just used to convert a plain parameter value)
|
||||
* @param objectName the name of the target object
|
||||
*/
|
||||
public PortletRequestDataBinder(Object target, String objectName) {
|
||||
super(target, objectName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind the parameters of the given request to this binder's target,
|
||||
* also binding multipart files in case of a multipart request.
|
||||
* <p>This call can create field errors, representing basic binding
|
||||
* errors like a required field (code "required"), or type mismatch
|
||||
* between value and bean property (code "typeMismatch").
|
||||
* <p>Multipart files are bound via their parameter name, just like normal
|
||||
* HTTP parameters: i.e. "uploadedFile" to an "uploadedFile" bean property,
|
||||
* invoking a "setUploadedFile" setter method.
|
||||
* <p>The type of the target property for a multipart file can be MultipartFile,
|
||||
* byte[], or String. The latter two receive the contents of the uploaded file;
|
||||
* all metadata like original file name, content type, etc are lost in those cases.
|
||||
* @param request request with parameters to bind (can be multipart)
|
||||
* @see org.springframework.web.portlet.multipart.MultipartActionRequest
|
||||
* @see org.springframework.web.multipart.MultipartFile
|
||||
* @see #bind(org.springframework.beans.PropertyValues)
|
||||
*/
|
||||
public void bind(PortletRequest request) {
|
||||
MutablePropertyValues mpvs = new PortletRequestParameterPropertyValues(request);
|
||||
MultipartRequest multipartRequest = PortletUtils.getNativeRequest(request, MultipartRequest.class);
|
||||
if (multipartRequest != null) {
|
||||
bindMultipart(multipartRequest.getMultiFileMap(), mpvs);
|
||||
}
|
||||
doBind(mpvs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats errors as fatal.
|
||||
* <p>Use this method only if it's an error if the input isn't valid.
|
||||
* This might be appropriate if all input is from dropdowns, for example.
|
||||
* @throws PortletRequestBindingException subclass of PortletException on any binding problem
|
||||
*/
|
||||
public void closeNoCatch() throws PortletRequestBindingException {
|
||||
if (getBindingResult().hasErrors()) {
|
||||
throw new PortletRequestBindingException(
|
||||
"Errors binding onto object '" + getBindingResult().getObjectName() + "'",
|
||||
new BindException(getBindingResult()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.bind;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* PropertyValues implementation created from parameters in a PortletRequest.
|
||||
* Can look for all property values beginning with a certain prefix and
|
||||
* prefix separator (default is "_").
|
||||
*
|
||||
* <p>For example, with a prefix of "spring", "spring_param1" and
|
||||
* "spring_param2" result in a Map with "param1" and "param2" as keys.
|
||||
*
|
||||
* <p>This class is not immutable to be able to efficiently remove property
|
||||
* values that should be ignored for binding.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.portlet.util.PortletUtils#getParametersStartingWith
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PortletRequestParameterPropertyValues extends MutablePropertyValues {
|
||||
|
||||
/** Default prefix separator */
|
||||
public static final String DEFAULT_PREFIX_SEPARATOR = "_";
|
||||
|
||||
|
||||
/**
|
||||
* Create new PortletRequestPropertyValues using no prefix
|
||||
* (and hence, no prefix separator).
|
||||
* @param request portlet request
|
||||
*/
|
||||
public PortletRequestParameterPropertyValues(PortletRequest request) {
|
||||
this(request, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new PortletRequestPropertyValues using the given prefix and
|
||||
* the default prefix separator (the underscore character "_").
|
||||
* @param request portlet request
|
||||
* @param prefix the prefix for parameters (the full prefix will
|
||||
* consist of this plus the separator)
|
||||
* @see #DEFAULT_PREFIX_SEPARATOR
|
||||
*/
|
||||
public PortletRequestParameterPropertyValues(PortletRequest request, String prefix) {
|
||||
this(request, prefix, DEFAULT_PREFIX_SEPARATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new PortletRequestPropertyValues supplying both prefix and
|
||||
* prefix separator.
|
||||
* @param request portlet request
|
||||
* @param prefix the prefix for parameters (the full prefix will
|
||||
* consist of this plus the separator)
|
||||
* @param prefixSeparator separator delimiting prefix (e.g. "spring")
|
||||
* and the rest of the parameter name ("param1", "param2")
|
||||
*/
|
||||
public PortletRequestParameterPropertyValues(PortletRequest request, String prefix, String prefixSeparator) {
|
||||
super(PortletUtils.getParametersStartingWith(
|
||||
request, (prefix != null ? prefix + prefixSeparator : null)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,711 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.bind;
|
||||
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
/**
|
||||
* Parameter extraction methods, for an approach distinct from data binding,
|
||||
* in which parameters of specific types are required.
|
||||
*
|
||||
* <p>This approach is very useful for simple submissions, where binding
|
||||
* request parameters to a command object would be overkill.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Keith Donald
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class PortletRequestUtils {
|
||||
|
||||
private static final IntParser INT_PARSER = new IntParser();
|
||||
|
||||
private static final LongParser LONG_PARSER = new LongParser();
|
||||
|
||||
private static final FloatParser FLOAT_PARSER = new FloatParser();
|
||||
|
||||
private static final DoubleParser DOUBLE_PARSER = new DoubleParser();
|
||||
|
||||
private static final BooleanParser BOOLEAN_PARSER = new BooleanParser();
|
||||
|
||||
private static final StringParser STRING_PARSER = new StringParser();
|
||||
|
||||
|
||||
/**
|
||||
* Get an Integer parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the Integer value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static Integer getIntParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return getRequiredIntParameter(request, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an int parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value as default to enable checks of whether it was supplied.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static int getIntParameter(PortletRequest request, String name, int defaultVal) {
|
||||
if (request.getParameter(name) == null) {
|
||||
return defaultVal;
|
||||
}
|
||||
try {
|
||||
return getRequiredIntParameter(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of int parameters, return an empty array if not found.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static int[] getIntParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredIntParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new int[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an int parameter, throwing an exception if it isn't found or isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static int getRequiredIntParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return INT_PARSER.parseInt(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of int parameters, throwing an exception if not found or one is not a number..
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static int[] getRequiredIntParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return INT_PARSER.parseInts(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Long parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the Long value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static Long getLongParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return getRequiredLongParameter(request, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a long parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value as default to enable checks of whether it was supplied.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static long getLongParameter(PortletRequest request, String name, long defaultVal) {
|
||||
if (request.getParameter(name) == null) {
|
||||
return defaultVal;
|
||||
}
|
||||
try {
|
||||
return getRequiredLongParameter(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of long parameters, return an empty array if not found.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static long[] getLongParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredLongParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new long[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a long parameter, throwing an exception if it isn't found or isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static long getRequiredLongParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return LONG_PARSER.parseLong(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of long parameters, throwing an exception if not found or one is not a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static long[] getRequiredLongParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return LONG_PARSER.parseLongs(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Float parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the Float value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static Float getFloatParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return getRequiredFloatParameter(request, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a float parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value as default to enable checks of whether it was supplied.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static float getFloatParameter(PortletRequest request, String name, float defaultVal) {
|
||||
if (request.getParameter(name) == null) {
|
||||
return defaultVal;
|
||||
}
|
||||
try {
|
||||
return getRequiredFloatParameter(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of float parameters, return an empty array if not found.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static float[] getFloatParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredFloatParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new float[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a float parameter, throwing an exception if it isn't found or isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static float getRequiredFloatParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return FLOAT_PARSER.parseFloat(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of float parameters, throwing an exception if not found or one is not a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static float[] getRequiredFloatParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return FLOAT_PARSER.parseFloats(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Double parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the Double value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static Double getDoubleParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return getRequiredDoubleParameter(request, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a double parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value as default to enable checks of whether it was supplied.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static double getDoubleParameter(PortletRequest request, String name, double defaultVal) {
|
||||
if (request.getParameter(name) == null) {
|
||||
return defaultVal;
|
||||
}
|
||||
try {
|
||||
return getRequiredDoubleParameter(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of double parameters, return an empty array if not found.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static double[] getDoubleParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredDoubleParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new double[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a double parameter, throwing an exception if it isn't found or isn't a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static double getRequiredDoubleParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return DOUBLE_PARSER.parseDouble(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of double parameters, throwing an exception if not found or one is not a number.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static double[] getRequiredDoubleParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return DOUBLE_PARSER.parseDoubles(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a Boolean parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value isn't a boolean.
|
||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true;
|
||||
* treats every other non-empty value as false (i.e. parses leniently).
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the Boolean value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static Boolean getBooleanParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return (getRequiredBooleanParameter(request, name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value as default to enable checks of whether it was supplied.
|
||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true;
|
||||
* treats every other non-empty value as false (i.e. parses leniently).
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static boolean getBooleanParameter(PortletRequest request, String name, boolean defaultVal) {
|
||||
if (request.getParameter(name) == null) {
|
||||
return defaultVal;
|
||||
}
|
||||
try {
|
||||
return getRequiredBooleanParameter(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return defaultVal;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of boolean parameters, return an empty array if not found.
|
||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true;
|
||||
* treats every other non-empty value as false (i.e. parses leniently).
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static boolean[] getBooleanParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredBooleanParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new boolean[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a boolean parameter, throwing an exception if it isn't found
|
||||
* or isn't a boolean.
|
||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true;
|
||||
* treats every other non-empty value as false (i.e. parses leniently).
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static boolean getRequiredBooleanParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return BOOLEAN_PARSER.parseBoolean(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of boolean parameters, throwing an exception if not found
|
||||
* or one isn't a boolean.
|
||||
* <p>Accepts "true", "on", "yes" (any case) and "1" as values for true;
|
||||
* treats every other non-empty value as false (i.e. parses leniently).
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static boolean[] getRequiredBooleanParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return BOOLEAN_PARSER.parseBooleans(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a String parameter, or {@code null} if not present.
|
||||
* Throws an exception if it the parameter value is empty.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @return the String value, or {@code null} if not present
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static String getStringParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (request.getParameter(name) == null) {
|
||||
return null;
|
||||
}
|
||||
return getRequiredStringParameter(request, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a String parameter, with a fallback value. Never throws an exception.
|
||||
* Can pass a distinguished value to default to enable checks of whether it was supplied.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @param defaultVal the default value to use as fallback
|
||||
*/
|
||||
public static String getStringParameter(PortletRequest request, String name, String defaultVal) {
|
||||
String val = request.getParameter(name);
|
||||
return (val != null ? val : defaultVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of String parameters, return an empty array if not found.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter with multiple possible values
|
||||
*/
|
||||
public static String[] getStringParameters(PortletRequest request, String name) {
|
||||
try {
|
||||
return getRequiredStringParameters(request, name);
|
||||
}
|
||||
catch (PortletRequestBindingException ex) {
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a String parameter, throwing an exception if it isn't found or is empty.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static String getRequiredStringParameter(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return STRING_PARSER.validateRequiredString(name, request.getParameter(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of String parameters, throwing an exception if not found or one is empty.
|
||||
* @param request current portlet request
|
||||
* @param name the name of the parameter
|
||||
* @throws PortletRequestBindingException a subclass of PortletException,
|
||||
* so it doesn't need to be caught
|
||||
*/
|
||||
public static String[] getRequiredStringParameters(PortletRequest request, String name)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
return STRING_PARSER.validateRequiredStrings(name, request.getParameterValues(name));
|
||||
}
|
||||
|
||||
|
||||
private abstract static class ParameterParser<T> {
|
||||
|
||||
protected final T parse(String name, String parameter) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, parameter);
|
||||
try {
|
||||
return doParse(parameter);
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
throw new PortletRequestBindingException(
|
||||
"Required " + getType() + " parameter '" + name + "' with value of '" +
|
||||
parameter + "' is not a valid number", ex);
|
||||
}
|
||||
}
|
||||
|
||||
protected final void validateRequiredParameter(String name, Object parameter)
|
||||
throws PortletRequestBindingException {
|
||||
|
||||
if (parameter == null) {
|
||||
throw new MissingPortletRequestParameterException(name, getType());
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getType();
|
||||
|
||||
protected abstract T doParse(String parameter) throws NumberFormatException;
|
||||
}
|
||||
|
||||
|
||||
private static class IntParser extends ParameterParser<Integer> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "int";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doParse(String s) throws NumberFormatException {
|
||||
return Integer.valueOf(s);
|
||||
}
|
||||
|
||||
public int parseInt(String name, String parameter) throws PortletRequestBindingException {
|
||||
return parse(name, parameter);
|
||||
}
|
||||
|
||||
public int[] parseInts(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
int[] parameters = new int[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
parameters[i] = parseInt(name, values[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class LongParser extends ParameterParser<Long> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "long";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long doParse(String parameter) throws NumberFormatException {
|
||||
return Long.valueOf(parameter);
|
||||
}
|
||||
|
||||
public long parseLong(String name, String parameter) throws PortletRequestBindingException {
|
||||
return parse(name, parameter);
|
||||
}
|
||||
|
||||
public long[] parseLongs(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
long[] parameters = new long[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
parameters[i] = parseLong(name, values[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class FloatParser extends ParameterParser<Float> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "float";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Float doParse(String parameter) throws NumberFormatException {
|
||||
return Float.valueOf(parameter);
|
||||
}
|
||||
|
||||
public float parseFloat(String name, String parameter) throws PortletRequestBindingException {
|
||||
return parse(name, parameter);
|
||||
}
|
||||
|
||||
public float[] parseFloats(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
float[] parameters = new float[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
parameters[i] = parseFloat(name, values[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DoubleParser extends ParameterParser<Double> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Double doParse(String parameter) throws NumberFormatException {
|
||||
return Double.valueOf(parameter);
|
||||
}
|
||||
|
||||
public double parseDouble(String name, String parameter) throws PortletRequestBindingException {
|
||||
return parse(name, parameter);
|
||||
}
|
||||
|
||||
public double[] parseDoubles(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
double[] parameters = new double[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
parameters[i] = parseDouble(name, values[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class BooleanParser extends ParameterParser<Boolean> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "boolean";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doParse(String parameter) throws NumberFormatException {
|
||||
return (parameter.equalsIgnoreCase("true") || parameter.equalsIgnoreCase("on") ||
|
||||
parameter.equalsIgnoreCase("yes") || parameter.equals("1"));
|
||||
}
|
||||
|
||||
public boolean parseBoolean(String name, String parameter) throws PortletRequestBindingException {
|
||||
return parse(name, parameter);
|
||||
}
|
||||
|
||||
public boolean[] parseBooleans(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
boolean[] parameters = new boolean[values.length];
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
parameters[i] = parseBoolean(name, values[i]);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class StringParser extends ParameterParser<String> {
|
||||
|
||||
@Override
|
||||
protected String getType() {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doParse(String parameter) throws NumberFormatException {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public String validateRequiredString(String name, String value) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public String[] validateRequiredStrings(String name, String[] values) throws PortletRequestBindingException {
|
||||
validateRequiredParameter(name, values);
|
||||
for (String value : values) {
|
||||
validateRequiredParameter(name, value);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.portlet.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.Mapping;
|
||||
|
||||
/**
|
||||
* Annotation for mapping Portlet action requests onto handler methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping
|
||||
public @interface ActionMapping {
|
||||
|
||||
/**
|
||||
* Alias for {@link #name}.
|
||||
*/
|
||||
@AliasFor("name")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* The name of the action, according to the Portlet 2.0
|
||||
* {@code javax.portlet.action} parameter.
|
||||
* <p>If not specified, the annotated method will be used as a default
|
||||
* handler: i.e. for action requests where no specific action mapping
|
||||
* was found.
|
||||
* <p>Note that all such annotated action methods only apply within the
|
||||
* {@code @RequestMapping} constraints of the containing handler class.
|
||||
* @since 4.2
|
||||
* @see javax.portlet.ActionRequest#ACTION_NAME
|
||||
* @see #value
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* The parameters of the mapped request, narrowing the primary mapping.
|
||||
* <p>Same format for any environment: a sequence of {@code "myParam=myValue"}
|
||||
* style expressions, with a request only mapped if each such parameter is found
|
||||
* to have the given value. {@code "myParam"} style expressions are also supported,
|
||||
* with such parameters having to be present in the request (allowed to have
|
||||
* any value). Finally, {@code "!myParam"} style expressions indicate that the
|
||||
* specified parameter is <i>not</i> supposed to be present in the request.
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#params()
|
||||
*/
|
||||
String[] params() default {};
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.web.portlet.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.web.bind.annotation.Mapping;
|
||||
|
||||
/**
|
||||
* Annotation for mapping Portlet event requests onto handler methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping()
|
||||
public @interface EventMapping {
|
||||
|
||||
/**
|
||||
* The name of the event to be handled.
|
||||
* This name uniquely identifies an event within a portlet mode.
|
||||
* <p>Typically the local name of the event, but fully qualified names
|
||||
* with a "{...}" namespace part will be mapped correctly as well.
|
||||
* <p>If not specified, the handler method will be invoked for any
|
||||
* event request within its general mapping.
|
||||
* @see javax.portlet.EventRequest#getEvent()
|
||||
* @see javax.portlet.Event#getName()
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.portlet.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.core.annotation.AliasFor;
|
||||
import org.springframework.web.bind.annotation.Mapping;
|
||||
|
||||
/**
|
||||
* Annotation for mapping Portlet render requests onto handler methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping
|
||||
public @interface RenderMapping {
|
||||
|
||||
/**
|
||||
* Alias for {@link #windowState}.
|
||||
*/
|
||||
@AliasFor("windowState")
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* The window state that the annotated render method applies for.
|
||||
* <p>If not specified, the render method will be invoked for any
|
||||
* window state within its general mapping.
|
||||
* <p>Standard Portlet specification values are supported: {@code "NORMAL"},
|
||||
* {@code "MAXIMIZED"}, {@code "MINIMIZED"}.
|
||||
* <p>Custom window states can be used as well, as supported by the portal.
|
||||
* @since 4.2
|
||||
* @see #value
|
||||
* @see javax.portlet.PortletRequest#getWindowState()
|
||||
*/
|
||||
@AliasFor("value")
|
||||
String windowState() default "";
|
||||
|
||||
/**
|
||||
* The parameters of the mapped request, narrowing the primary mapping.
|
||||
* <p>Same format for any environment: a sequence of {@code "myParam=myValue"}
|
||||
* style expressions, with a request only mapped if each such parameter is found
|
||||
* to have the given value. {@code "myParam"} style expressions are also supported,
|
||||
* with such parameters having to be present in the request (allowed to have
|
||||
* any value). Finally, {@code "!myParam"} style expressions indicate that the
|
||||
* specified parameter is <i>not</i> supposed to be present in the request.
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#params()
|
||||
*/
|
||||
String[] params() default {};
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.web.portlet.bind.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.web.bind.annotation.Mapping;
|
||||
|
||||
/**
|
||||
* Annotation for mapping Portlet resource requests onto handler methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping
|
||||
*/
|
||||
@Target({ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Mapping()
|
||||
public @interface ResourceMapping {
|
||||
|
||||
/**
|
||||
* The id of the resource to be handled.
|
||||
* This id uniquely identifies a resource within a portlet mode.
|
||||
* <p>If not specified, the handler method will be invoked for any
|
||||
* resource request within its general mapping.
|
||||
* @see javax.portlet.ResourceRequest#getResourceID()
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Annotations for binding portlet requests to handler methods.
|
||||
*/
|
||||
package org.springframework.web.portlet.bind.annotation;
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Provides Portlet-specific data binding functionality.
|
||||
*/
|
||||
package org.springframework.web.portlet.bind;
|
||||
@@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.ServletContextAwareProcessor;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.context.support.AbstractRefreshableApplicationContext}
|
||||
* subclass which implements the {@link ConfigurablePortletApplicationContext}
|
||||
* interface for portlet environments. Provides a "configLocations" property,
|
||||
* to be populated through the ConfigurablePortletApplicationContext interface
|
||||
* on portlet application startup.
|
||||
*
|
||||
* <p>This class is as easy to subclass as AbstractRefreshableApplicationContext:
|
||||
* All you need to implements is the {@link #loadBeanDefinitions} method;
|
||||
* see the superclass javadoc for details. Note that implementations are supposed
|
||||
* to load bean definitions from the files specified by the locations returned
|
||||
* by the {@link #getConfigLocations} method.
|
||||
*
|
||||
* <p>Interprets resource paths as servlet context resources, i.e. as paths beneath
|
||||
* the web application root. Absolute paths, e.g. for files outside the web app root,
|
||||
* can be accessed via "file:" URLs, as implemented by
|
||||
* {@link org.springframework.core.io.DefaultResourceLoader}.
|
||||
*
|
||||
* <p><b>This is the portlet context to be subclassed for a different bean definition format.</b>
|
||||
* Such a context implementation can be specified as "contextClass" init-param
|
||||
* for FrameworkPortlet, replacing the default {@link XmlPortletApplicationContext}.
|
||||
* It will then automatically receive the "contextConfigLocation" init-param.
|
||||
*
|
||||
* <p>Note that Portlet-based context implementations are generally supposed
|
||||
* to configure themselves based on the configuration received through the
|
||||
* {@link ConfigurablePortletApplicationContext} interface. In contrast, a standalone
|
||||
* application context might allow for configuration in custom startup code
|
||||
* (for example, {@link org.springframework.context.support.GenericApplicationContext}).
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #loadBeanDefinitions
|
||||
* @see org.springframework.web.portlet.context.ConfigurablePortletApplicationContext#setConfigLocations
|
||||
* @see XmlPortletApplicationContext
|
||||
*/
|
||||
public abstract class AbstractRefreshablePortletApplicationContext extends AbstractRefreshableConfigApplicationContext
|
||||
implements WebApplicationContext, ConfigurablePortletApplicationContext {
|
||||
|
||||
/** Servlet context that this context runs in */
|
||||
private ServletContext servletContext;
|
||||
|
||||
/** Portlet context that this context runs in */
|
||||
private PortletContext portletContext;
|
||||
|
||||
/** Portlet config that this context runs in */
|
||||
private PortletConfig portletConfig;
|
||||
|
||||
/** Namespace of this context, or null if root */
|
||||
private String namespace;
|
||||
|
||||
|
||||
public AbstractRefreshablePortletApplicationContext() {
|
||||
setDisplayName("Root PortletApplicationContext");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>The parent {@linkplain #getEnvironment() environment} is
|
||||
* delegated to this (child) context if the parent is a
|
||||
* {@link org.springframework.context.ConfigurableApplicationContext} implementation.
|
||||
* <p>The parent {@linkplain #getServletContext() servlet context} is
|
||||
* delegated to this (child) context if the parent is a {@link WebApplicationContext}
|
||||
* implementation.
|
||||
*/
|
||||
@Override
|
||||
public void setParent(ApplicationContext parent) {
|
||||
super.setParent(parent);
|
||||
if (parent instanceof WebApplicationContext) {
|
||||
this.servletContext = ((WebApplicationContext) parent).getServletContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletContext(PortletContext portletContext) {
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletContext getPortletContext() {
|
||||
return this.portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletConfig(PortletConfig portletConfig) {
|
||||
this.portletConfig = portletConfig;
|
||||
if (portletConfig != null && this.portletContext == null) {
|
||||
this.portletContext = portletConfig.getPortletContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletConfig getPortletConfig() {
|
||||
return this.portletConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
if (namespace != null) {
|
||||
setDisplayName("PortletApplicationContext for namespace '" + namespace + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getConfigLocations() {
|
||||
return super.getConfigLocations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getApplicationName() {
|
||||
if (this.portletContext == null) {
|
||||
return "";
|
||||
}
|
||||
String name = this.portletContext.getPortletContextName();
|
||||
return (name != null ? name : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new {@link StandardPortletEnvironment}.
|
||||
*/
|
||||
@Override
|
||||
protected ConfigurableEnvironment createEnvironment() {
|
||||
return new StandardPortletEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register request/session scopes, a {@link PortletContextAwareProcessor}, etc.
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
|
||||
beanFactory.addBeanPostProcessor(new PortletContextAwareProcessor(this.portletContext, this.portletConfig));
|
||||
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
|
||||
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
||||
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
||||
|
||||
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory, this.portletContext);
|
||||
PortletApplicationContextUtils.registerEnvironmentBeans(
|
||||
beanFactory, this.servletContext, this.portletContext, this.portletConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports file paths beneath the root of the PortletContext.
|
||||
* @see PortletContextResource
|
||||
*/
|
||||
@Override
|
||||
protected Resource getResourceByPath(String path) {
|
||||
return new PortletContextResource(this.portletContext, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports pattern matching in unexpanded WARs too.
|
||||
* @see PortletContextResourcePatternResolver
|
||||
*/
|
||||
@Override
|
||||
protected ResourcePatternResolver getResourcePatternResolver() {
|
||||
return new PortletContextResourcePatternResolver(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
|
||||
super.customizeBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by configurable portlet application contexts.
|
||||
* Supported by {@link org.springframework.web.portlet.FrameworkPortlet}.
|
||||
*
|
||||
* <p>Note: The setters of this interface need to be called before an
|
||||
* invocation of the {@link #refresh} method inherited from
|
||||
* {@link org.springframework.context.ConfigurableApplicationContext}.
|
||||
* They do not cause an initialization of the context on their own.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author William G. Thompson, Jr.
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #refresh
|
||||
* @see org.springframework.web.context.ContextLoader#createWebApplicationContext
|
||||
* @see org.springframework.web.portlet.FrameworkPortlet#createPortletApplicationContext
|
||||
* @see org.springframework.web.context.ConfigurableWebApplicationContext
|
||||
*/
|
||||
public interface ConfigurablePortletApplicationContext
|
||||
extends WebApplicationContext, ConfigurableApplicationContext {
|
||||
|
||||
/**
|
||||
* Prefix for ApplicationContext ids that refer to portlet name.
|
||||
*/
|
||||
String APPLICATION_CONTEXT_ID_PREFIX = WebApplicationContext.class.getName() + ":";
|
||||
|
||||
/**
|
||||
* Name of the PortletContext environment bean in the factory.
|
||||
* @see javax.portlet.PortletContext
|
||||
*/
|
||||
String PORTLET_CONTEXT_BEAN_NAME = "portletContext";
|
||||
|
||||
/**
|
||||
* Name of the PortletConfig environment bean in the factory.
|
||||
* @see javax.portlet.PortletConfig
|
||||
*/
|
||||
String PORTLET_CONFIG_BEAN_NAME = "portletConfig";
|
||||
|
||||
|
||||
/**
|
||||
* Set the PortletContext for this portlet application context.
|
||||
* <p>Does not cause an initialization of the context: refresh needs to be
|
||||
* called after the setting of all configuration properties.
|
||||
* @see #refresh()
|
||||
*/
|
||||
void setPortletContext(PortletContext portletContext);
|
||||
|
||||
/**
|
||||
* Return the standard Portlet API PortletContext for this application.
|
||||
*/
|
||||
PortletContext getPortletContext();
|
||||
|
||||
/**
|
||||
* Set the PortletConfig for this portlet application context.
|
||||
* @see #refresh()
|
||||
*/
|
||||
void setPortletConfig(PortletConfig portletConfig);
|
||||
|
||||
/**
|
||||
* Return the PortletConfig for this portlet application context, if any.
|
||||
*/
|
||||
PortletConfig getPortletConfig();
|
||||
|
||||
/**
|
||||
* Set the namespace for this portlet application context,
|
||||
* to be used for building a default context config location.
|
||||
*/
|
||||
void setNamespace(String namespace);
|
||||
|
||||
/**
|
||||
* Return the namespace for this web application context, if any.
|
||||
*/
|
||||
String getNamespace();
|
||||
|
||||
/**
|
||||
* Set the config locations for this portlet application context in init-param style,
|
||||
* i.e. with distinct locations separated by commas, semicolons or whitespace.
|
||||
* <p>If not set, the implementation is supposed to use a default for the
|
||||
* given namespace.
|
||||
*/
|
||||
void setConfigLocation(String configLocation);
|
||||
|
||||
/**
|
||||
* Set the config locations for this portlet application context.
|
||||
* <p>If not set, the implementation is supposed to use a default for the
|
||||
* given namespace.
|
||||
*/
|
||||
void setConfigLocations(String... configLocations);
|
||||
|
||||
/**
|
||||
* Return the config locations for this web application context,
|
||||
* or {@code null} if none specified.
|
||||
*/
|
||||
String[] getConfigLocations();
|
||||
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.web.portlet.context;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.RequestScope;
|
||||
import org.springframework.web.context.request.SessionScope;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
/**
|
||||
* Convenience methods for retrieving the root {@link WebApplicationContext} for
|
||||
* a given {@link PortletContext}. This is useful for programmatically accessing
|
||||
* a Spring application context from within custom Portlet implementations.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.context.ContextLoader
|
||||
* @see org.springframework.web.context.support.WebApplicationContextUtils
|
||||
* @see org.springframework.web.portlet.FrameworkPortlet
|
||||
* @see org.springframework.web.portlet.DispatcherPortlet
|
||||
*/
|
||||
public abstract class PortletApplicationContextUtils {
|
||||
|
||||
/**
|
||||
* Find the root {@link WebApplicationContext} for this web app, typically
|
||||
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
|
||||
* <p>Will rethrow an exception that happened on root context startup,
|
||||
* to differentiate between a failed context startup and no context at all.
|
||||
* @param pc PortletContext to find the web application context for
|
||||
* @return the root WebApplicationContext for this web app, or {@code null} if none
|
||||
* (typed to ApplicationContext to avoid a Servlet API dependency; can usually
|
||||
* be casted to WebApplicationContext, but there shouldn't be a need to)
|
||||
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
|
||||
*/
|
||||
public static ApplicationContext getWebApplicationContext(PortletContext pc) {
|
||||
Assert.notNull(pc, "PortletContext must not be null");
|
||||
Object attr = pc.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
|
||||
if (attr == null) {
|
||||
return null;
|
||||
}
|
||||
if (attr instanceof RuntimeException) {
|
||||
throw (RuntimeException) attr;
|
||||
}
|
||||
if (attr instanceof Error) {
|
||||
throw (Error) attr;
|
||||
}
|
||||
if (!(attr instanceof ApplicationContext)) {
|
||||
throw new IllegalStateException("Root context attribute is not of type WebApplicationContext: " + attr);
|
||||
}
|
||||
return (ApplicationContext) attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the root {@link WebApplicationContext} for this web app, typically
|
||||
* loaded via {@link org.springframework.web.context.ContextLoaderListener}.
|
||||
* <p>Will rethrow an exception that happened on root context startup,
|
||||
* to differentiate between a failed context startup and no context at all.
|
||||
* @param pc PortletContext to find the web application context for
|
||||
* @return the root WebApplicationContext for this web app
|
||||
* (typed to ApplicationContext to avoid a Servlet API dependency; can usually
|
||||
* be casted to WebApplicationContext, but there shouldn't be a need to)
|
||||
* @throws IllegalStateException if the root WebApplicationContext could not be found
|
||||
* @see org.springframework.web.context.WebApplicationContext#ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
|
||||
*/
|
||||
public static ApplicationContext getRequiredWebApplicationContext(PortletContext pc) throws IllegalStateException {
|
||||
ApplicationContext wac = getWebApplicationContext(pc);
|
||||
if (wac == null) {
|
||||
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?");
|
||||
}
|
||||
return wac;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register web-specific scopes ("request", "session", "globalSession")
|
||||
* with the given BeanFactory, as used by the Portlet ApplicationContext.
|
||||
* @param bf the BeanFactory to configure
|
||||
* @param pc the PortletContext that we're running within
|
||||
*/
|
||||
static void registerPortletApplicationScopes(ConfigurableListableBeanFactory bf, PortletContext pc) {
|
||||
bf.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
|
||||
bf.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope(false));
|
||||
bf.registerScope(WebApplicationContext.SCOPE_GLOBAL_SESSION, new SessionScope(true));
|
||||
if (pc != null) {
|
||||
PortletContextScope appScope = new PortletContextScope(pc);
|
||||
bf.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
|
||||
// Register as PortletContext attribute, for ContextCleanupListener to detect it.
|
||||
pc.setAttribute(PortletContextScope.class.getName(), appScope);
|
||||
}
|
||||
|
||||
bf.registerResolvableDependency(PortletRequest.class, new RequestObjectFactory());
|
||||
bf.registerResolvableDependency(PortletResponse.class, new ResponseObjectFactory());
|
||||
bf.registerResolvableDependency(PortletSession.class, new SessionObjectFactory());
|
||||
bf.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register web-specific environment beans ("contextParameters", "contextAttributes")
|
||||
* with the given BeanFactory, as used by the Portlet ApplicationContext.
|
||||
* @param bf the BeanFactory to configure
|
||||
* @param servletContext the ServletContext that we're running within
|
||||
* @param portletContext the PortletContext that we're running within
|
||||
* @param portletConfig the PortletConfig of the containing Portlet
|
||||
*/
|
||||
static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext servletContext,
|
||||
PortletContext portletContext, PortletConfig portletConfig) {
|
||||
|
||||
if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
|
||||
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
|
||||
}
|
||||
|
||||
if (portletContext != null && !bf.containsBean(ConfigurablePortletApplicationContext.PORTLET_CONTEXT_BEAN_NAME)) {
|
||||
bf.registerSingleton(ConfigurablePortletApplicationContext.PORTLET_CONTEXT_BEAN_NAME, portletContext);
|
||||
}
|
||||
|
||||
if (portletConfig != null && !bf.containsBean(ConfigurablePortletApplicationContext.PORTLET_CONFIG_BEAN_NAME)) {
|
||||
bf.registerSingleton(ConfigurablePortletApplicationContext.PORTLET_CONFIG_BEAN_NAME, portletConfig);
|
||||
}
|
||||
|
||||
if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
|
||||
Map<String, String> parameterMap = new HashMap<String, String>();
|
||||
if (portletContext != null) {
|
||||
Enumeration<String> paramNameEnum = portletContext.getInitParameterNames();
|
||||
while (paramNameEnum.hasMoreElements()) {
|
||||
String paramName = paramNameEnum.nextElement();
|
||||
parameterMap.put(paramName, portletContext.getInitParameter(paramName));
|
||||
}
|
||||
}
|
||||
if (portletConfig != null) {
|
||||
Enumeration<String> paramNameEnum = portletConfig.getInitParameterNames();
|
||||
while (paramNameEnum.hasMoreElements()) {
|
||||
String paramName = paramNameEnum.nextElement();
|
||||
parameterMap.put(paramName, portletConfig.getInitParameter(paramName));
|
||||
}
|
||||
}
|
||||
bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME,
|
||||
Collections.unmodifiableMap(parameterMap));
|
||||
}
|
||||
|
||||
if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
|
||||
Map<String, Object> attributeMap = new HashMap<String, Object>();
|
||||
if (portletContext != null) {
|
||||
Enumeration<String> attrNameEnum = portletContext.getAttributeNames();
|
||||
while (attrNameEnum.hasMoreElements()) {
|
||||
String attrName = attrNameEnum.nextElement();
|
||||
attributeMap.put(attrName, portletContext.getAttribute(attrName));
|
||||
}
|
||||
}
|
||||
bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME,
|
||||
Collections.unmodifiableMap(attributeMap));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace {@code Servlet}- and {@code Portlet}-based {@link
|
||||
* org.springframework.core.env.PropertySource.StubPropertySource stub property
|
||||
* sources} with actual instances populated with the given {@code servletContext},
|
||||
* {@code portletContext} and {@code portletConfig} objects.
|
||||
* <p>This method is idempotent with respect to the fact it may be called any number
|
||||
* of times but will perform replacement of stub property sources with their
|
||||
* corresponding actual property sources once and only once.
|
||||
* @param propertySources the {@link MutablePropertySources} to initialize (must not be {@code null})
|
||||
* @param servletContext the current {@link ServletContext} (ignored if {@code null}
|
||||
* or if the {@link org.springframework.web.context.support.StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME
|
||||
* servlet context property source} has already been initialized)
|
||||
* @param portletContext the current {@link PortletContext} (ignored if {@code null}
|
||||
* or if the {@link StandardPortletEnvironment#PORTLET_CONTEXT_PROPERTY_SOURCE_NAME
|
||||
* portlet context property source} has already been initialized)
|
||||
* @param portletConfig the current {@link PortletConfig} (ignored if {@code null}
|
||||
* or if the {@link StandardPortletEnvironment#PORTLET_CONFIG_PROPERTY_SOURCE_NAME
|
||||
* portlet config property source} has already been initialized)
|
||||
* @see org.springframework.core.env.PropertySource.StubPropertySource
|
||||
* @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources(MutablePropertySources, ServletContext)
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment#getPropertySources()
|
||||
*/
|
||||
public static void initPortletPropertySources(MutablePropertySources propertySources, ServletContext servletContext,
|
||||
PortletContext portletContext, PortletConfig portletConfig) {
|
||||
|
||||
Assert.notNull(propertySources, "'propertySources' must not be null");
|
||||
WebApplicationContextUtils.initServletPropertySources(propertySources, servletContext);
|
||||
|
||||
if (portletContext != null && propertySources.contains(StandardPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME)) {
|
||||
propertySources.replace(StandardPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME,
|
||||
new PortletContextPropertySource(StandardPortletEnvironment.PORTLET_CONTEXT_PROPERTY_SOURCE_NAME, portletContext));
|
||||
}
|
||||
if (portletConfig != null && propertySources.contains(StandardPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME)) {
|
||||
propertySources.replace(StandardPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME,
|
||||
new PortletConfigPropertySource(StandardPortletEnvironment.PORTLET_CONFIG_PROPERTY_SOURCE_NAME, portletConfig));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current RequestAttributes instance as PortletRequestAttributes.
|
||||
* @see RequestContextHolder#currentRequestAttributes()
|
||||
*/
|
||||
private static PortletRequestAttributes currentRequestAttributes() {
|
||||
RequestAttributes requestAttr = RequestContextHolder.currentRequestAttributes();
|
||||
if (!(requestAttr instanceof PortletRequestAttributes)) {
|
||||
throw new IllegalStateException("Current request is not a portlet request");
|
||||
}
|
||||
return (PortletRequestAttributes) requestAttr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory that exposes the current request object on demand.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class RequestObjectFactory implements ObjectFactory<PortletRequest>, Serializable {
|
||||
|
||||
@Override
|
||||
public PortletRequest getObject() {
|
||||
return currentRequestAttributes().getRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Current PortletRequest";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory that exposes the current response object on demand.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class ResponseObjectFactory implements ObjectFactory<PortletResponse>, Serializable {
|
||||
|
||||
@Override
|
||||
public PortletResponse getObject() {
|
||||
PortletResponse response = currentRequestAttributes().getResponse();
|
||||
if (response == null) {
|
||||
throw new IllegalStateException("Current portlet response not available");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Current PortletResponse";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory that exposes the current session object on demand.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class SessionObjectFactory implements ObjectFactory<PortletSession>, Serializable {
|
||||
|
||||
@Override
|
||||
public PortletSession getObject() {
|
||||
return currentRequestAttributes().getRequest().getPortletSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Current PortletSession";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Factory that exposes the current WebRequest object on demand.
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
private static class WebRequestObjectFactory implements ObjectFactory<WebRequest>, Serializable {
|
||||
|
||||
@Override
|
||||
public WebRequest getObject() {
|
||||
PortletRequestAttributes requestAttr = currentRequestAttributes();
|
||||
return new PortletWebRequest(requestAttr.getRequest(), requestAttr.getResponse());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Current PortletWebRequest";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import java.io.File;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.context.support.ApplicationObjectSupport;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* Convenient superclass for application objects running in a Portlet ApplicationContext.
|
||||
* Provides getApplicationContext, getServletContext, and getTempDir methods.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class PortletApplicationObjectSupport extends ApplicationObjectSupport
|
||||
implements PortletContextAware {
|
||||
|
||||
private PortletContext portletContext;
|
||||
|
||||
|
||||
@Override
|
||||
public void setPortletContext(PortletContext portletContext) {
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overrides the base class behavior to enforce running in an ApplicationContext.
|
||||
* All accessors will throw IllegalStateException if not running in a context.
|
||||
* @see #getApplicationContext()
|
||||
* @see #getMessageSourceAccessor()
|
||||
* @see #getPortletContext()
|
||||
* @see #getTempDir()
|
||||
*/
|
||||
@Override
|
||||
protected boolean isContextRequired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current PortletContext.
|
||||
* @throws IllegalStateException if not running within a PortletContext
|
||||
*/
|
||||
protected final PortletContext getPortletContext() throws IllegalStateException {
|
||||
if (this.portletContext == null) {
|
||||
throw new IllegalStateException(
|
||||
"PortletApplicationObjectSupport instance [" + this + "] does not run within a PortletContext");
|
||||
}
|
||||
return this.portletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the temporary directory for the current web application,
|
||||
* as provided by the servlet container.
|
||||
* @return the File representing the temporary directory
|
||||
* @throws IllegalStateException if not running within a PortletContext
|
||||
* @see org.springframework.web.portlet.util.PortletUtils#getTempDir(javax.portlet.PortletContext)
|
||||
*/
|
||||
protected final File getTempDir() throws IllegalStateException {
|
||||
return PortletUtils.getTempDir(getPortletContext());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be notified
|
||||
* of the PortletConfig (typically determined by the PortletApplicationContext)
|
||||
* that it runs in.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Chris Beams
|
||||
* @since 2.0
|
||||
* @see PortletContextAware
|
||||
*/
|
||||
public interface PortletConfigAware extends Aware {
|
||||
|
||||
/**
|
||||
* Set the PortletConfigthat this object runs in.
|
||||
* <p>Invoked after population of normal bean properties but before an init
|
||||
* callback like InitializingBean's afterPropertiesSet or a custom init-method.
|
||||
* Invoked after ApplicationContextAware's setApplicationContext.
|
||||
* @param portletConfig PortletConfig object to be used by this object
|
||||
*/
|
||||
void setPortletConfig(PortletConfig portletConfig);
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link PropertySource} that reads init parameters from a {@link PortletConfig} object.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see PortletContextPropertySource
|
||||
*/
|
||||
public class PortletConfigPropertySource extends EnumerablePropertySource<PortletConfig> {
|
||||
|
||||
public PortletConfigPropertySource(String name, PortletConfig portletConfig) {
|
||||
super(name, portletConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPropertyNames() {
|
||||
return StringUtils.toStringArray(this.source.getInitParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return this.source.getInitParameter(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.beans.factory.Aware;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by any object that wishes to be notified
|
||||
* of the PortletContext (typically determined by the PortletApplicationContext)
|
||||
* that it runs in.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author William G. Thompson, Jr.
|
||||
* @author Chris Beams
|
||||
* @since 2.0
|
||||
* @see PortletConfigAware
|
||||
*/
|
||||
public interface PortletContextAware extends Aware {
|
||||
|
||||
/**
|
||||
* Set the PortletContext that this object runs in.
|
||||
* <p>Invoked after population of normal bean properties but before an init
|
||||
* callback like InitializingBean's afterPropertiesSet or a custom init-method.
|
||||
* Invoked after ApplicationContextAware's setApplicationContext.
|
||||
* @param portletContext PortletContext object to be used by this object
|
||||
*/
|
||||
void setPortletContext(PortletContext portletContext);
|
||||
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.config.BeanPostProcessor}
|
||||
* implementation that passes the PortletContext to beans that implement
|
||||
* the {@link PortletContextAware} interface.
|
||||
*
|
||||
* <p>Portlet application contexts will automatically register this with their
|
||||
* underlying bean factory. Applications do not use this directly.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.portlet.context.PortletContextAware
|
||||
* @see org.springframework.web.portlet.context.XmlPortletApplicationContext#postProcessBeanFactory
|
||||
*/
|
||||
public class PortletContextAwareProcessor implements BeanPostProcessor {
|
||||
|
||||
private PortletContext portletContext;
|
||||
|
||||
private PortletConfig portletConfig;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletContextAwareProcessor for the given context.
|
||||
*/
|
||||
public PortletContextAwareProcessor(PortletContext portletContext) {
|
||||
this(portletContext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletContextAwareProcessor for the given config.
|
||||
*/
|
||||
public PortletContextAwareProcessor(PortletConfig portletConfig) {
|
||||
this(null, portletConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletContextAwareProcessor for the given context and config.
|
||||
*/
|
||||
public PortletContextAwareProcessor(PortletContext portletContext, PortletConfig portletConfig) {
|
||||
this.portletContext = portletContext;
|
||||
this.portletConfig = portletConfig;
|
||||
if (portletContext == null && portletConfig != null) {
|
||||
this.portletContext = portletConfig.getPortletContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (this.portletContext != null && bean instanceof PortletContextAware) {
|
||||
((PortletContextAware) bean).setPortletContext(this.portletContext);
|
||||
}
|
||||
if (this.portletConfig != null && bean instanceof PortletConfigAware) {
|
||||
((PortletConfigAware) bean).setPortletConfig(this.portletConfig);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link PropertySource} that reads init parameters from a {@link PortletContext} object.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see PortletConfigPropertySource
|
||||
*/
|
||||
public class PortletContextPropertySource extends EnumerablePropertySource<PortletContext> {
|
||||
|
||||
public PortletContextPropertySource(String name, PortletContext portletContext) {
|
||||
super(name, portletContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getPropertyNames() {
|
||||
return StringUtils.toStringArray(this.source.getInitParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
return this.source.getInitParameter(name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.core.io.AbstractFileResolvingResource;
|
||||
import org.springframework.core.io.ContextResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.core.io.Resource} implementation for
|
||||
* {@link javax.portlet.PortletContext} resources, interpreting
|
||||
* relative paths within the portlet application root directory.
|
||||
*
|
||||
* <p>Always supports stream access and URL access, but only allows
|
||||
* {@code java.io.File} access when the portlet application archive
|
||||
* is expanded.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see javax.portlet.PortletContext#getResourceAsStream
|
||||
* @see javax.portlet.PortletContext#getRealPath
|
||||
*/
|
||||
public class PortletContextResource extends AbstractFileResolvingResource implements ContextResource {
|
||||
|
||||
private final PortletContext portletContext;
|
||||
|
||||
private final String path;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletContextResource.
|
||||
* <p>The Portlet spec requires that resource paths start with a slash,
|
||||
* even if many containers accept paths without leading slash too.
|
||||
* Consequently, the given path will be prepended with a slash if it
|
||||
* doesn't already start with one.
|
||||
* @param portletContext the PortletContext to load from
|
||||
* @param path the path of the resource
|
||||
*/
|
||||
public PortletContextResource(PortletContext portletContext, String path) {
|
||||
// check PortletContext
|
||||
Assert.notNull(portletContext, "Cannot resolve PortletContextResource without PortletContext");
|
||||
this.portletContext = portletContext;
|
||||
|
||||
// check path
|
||||
Assert.notNull(path, "Path is required");
|
||||
String pathToUse = StringUtils.cleanPath(path);
|
||||
if (!pathToUse.startsWith("/")) {
|
||||
pathToUse = "/" + pathToUse;
|
||||
}
|
||||
this.path = pathToUse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PortletContext for this resource.
|
||||
*/
|
||||
public final PortletContext getPortletContext() {
|
||||
return this.portletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path for this resource.
|
||||
*/
|
||||
public final String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation checks {@code PortletContext.getResource}.
|
||||
* @see javax.portlet.PortletContext#getResource(String)
|
||||
*/
|
||||
@Override
|
||||
public boolean exists() {
|
||||
try {
|
||||
URL url = this.portletContext.getResource(this.path);
|
||||
return (url != null);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to {@code PortletContext.getResourceAsStream},
|
||||
* which returns {@code null} in case of a non-readable resource (e.g. a directory).
|
||||
* @see javax.portlet.PortletContext#getResourceAsStream(String)
|
||||
*/
|
||||
@Override
|
||||
public boolean isReadable() {
|
||||
InputStream is = this.portletContext.getResourceAsStream(this.path);
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to {@code PortletContext.getResourceAsStream},
|
||||
* but throws a FileNotFoundException if not found.
|
||||
* @see javax.portlet.PortletContext#getResourceAsStream(String)
|
||||
*/
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
InputStream is = this.portletContext.getResourceAsStream(this.path);
|
||||
if (is == null) {
|
||||
throw new FileNotFoundException("Could not open " + getDescription());
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation delegates to {@code PortletContext.getResource},
|
||||
* but throws a FileNotFoundException if no resource found.
|
||||
* @see javax.portlet.PortletContext#getResource(String)
|
||||
*/
|
||||
@Override
|
||||
public URL getURL() throws IOException {
|
||||
URL url = this.portletContext.getResource(this.path);
|
||||
if (url == null) {
|
||||
throw new FileNotFoundException(
|
||||
getDescription() + " cannot be resolved to URL because it does not exist");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation resolves "file:" URLs or alternatively delegates to
|
||||
* {@code PortletContext.getRealPath}, throwing a FileNotFoundException
|
||||
* if not found or not resolvable.
|
||||
* @see javax.portlet.PortletContext#getResource(String)
|
||||
* @see javax.portlet.PortletContext#getRealPath(String)
|
||||
*/
|
||||
@Override
|
||||
public File getFile() throws IOException {
|
||||
URL url = getURL();
|
||||
if (ResourceUtils.isFileURL(url)) {
|
||||
// Proceed with file system resolution...
|
||||
return super.getFile();
|
||||
}
|
||||
else {
|
||||
String realPath = PortletUtils.getRealPath(this.portletContext, this.path);
|
||||
return new File(realPath);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resource createRelative(String relativePath) {
|
||||
String pathToUse = StringUtils.applyRelativePath(this.path, relativePath);
|
||||
return new PortletContextResource(this.portletContext, pathToUse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return StringUtils.getFilename(this.path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "PortletContext resource [" + this.path + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathWithinContext() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof PortletContextResource) {
|
||||
PortletContextResource otherRes = (PortletContextResource) obj;
|
||||
return (this.portletContext.equals(otherRes.portletContext) && this.path.equals(otherRes.path));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.path.hashCode();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
/**
|
||||
* ResourceLoader implementation that resolves paths as PortletContext
|
||||
* resources, for use outside a Portlet ApplicationContext (for example,
|
||||
* in a GenericPortletBean subclass).
|
||||
*
|
||||
* <p>Within a WebApplicationContext, resource paths are automatically
|
||||
* resolved as PortletContext resources by the context implementation.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #getResourceByPath
|
||||
* @see PortletContextResource
|
||||
* @see org.springframework.web.portlet.GenericPortletBean
|
||||
*/
|
||||
public class PortletContextResourceLoader extends DefaultResourceLoader {
|
||||
|
||||
private final PortletContext portletContext;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletContextResourceLoader.
|
||||
* @param portletContext the PortletContext to load resources with
|
||||
*/
|
||||
public PortletContextResourceLoader(PortletContext portletContext) {
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports file paths beneath the root of the web application.
|
||||
* @see PortletContextResource
|
||||
*/
|
||||
@Override
|
||||
protected Resource getResourceByPath(String path) {
|
||||
return new PortletContextResource(this.portletContext, path);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* PortletContext-aware subclass of {@link PathMatchingResourcePatternResolver},
|
||||
* able to find matching resources below the web application root directory
|
||||
* via Portlet API's {@code PortletContext.getResourcePaths}.
|
||||
* Falls back to the superclass' file system checking for other resources.
|
||||
*
|
||||
* <p>The advantage of using {@code PortletContext.getResourcePaths} to
|
||||
* find matching files is that it will work in a WAR file which has not been
|
||||
* expanded too.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PortletContextResourcePatternResolver extends PathMatchingResourcePatternResolver {
|
||||
|
||||
/**
|
||||
* Create a new PortletContextResourcePatternResolver.
|
||||
* @param portletContext the PortletContext to load resources with
|
||||
* @see PortletContextResourceLoader#PortletContextResourceLoader(javax.portlet.PortletContext)
|
||||
*/
|
||||
public PortletContextResourcePatternResolver(PortletContext portletContext) {
|
||||
super(new PortletContextResourceLoader(portletContext));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletContextResourcePatternResolver.
|
||||
* @param resourceLoader the ResourceLoader to load root directories and
|
||||
* actual resources with
|
||||
*/
|
||||
public PortletContextResourcePatternResolver(ResourceLoader resourceLoader) {
|
||||
super(resourceLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden version which checks for PortletContextResource
|
||||
* and uses {@code PortletContext.getResourcePaths} to find
|
||||
* matching resources below the web application root directory.
|
||||
* In case of other resources, delegates to the superclass version.
|
||||
* @see #doRetrieveMatchingPortletContextResources
|
||||
* @see PortletContextResource
|
||||
* @see javax.portlet.PortletContext#getResourcePaths
|
||||
*/
|
||||
@Override
|
||||
protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern) throws IOException {
|
||||
if (rootDirResource instanceof PortletContextResource) {
|
||||
PortletContextResource pcResource = (PortletContextResource) rootDirResource;
|
||||
PortletContext pc = pcResource.getPortletContext();
|
||||
String fullPattern = pcResource.getPath() + subPattern;
|
||||
Set<Resource> result = new HashSet<Resource>();
|
||||
doRetrieveMatchingPortletContextResources(pc, fullPattern, pcResource.getPath(), result);
|
||||
return result;
|
||||
}
|
||||
return super.doFindPathMatchingFileResources(rootDirResource, subPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively retrieve PortletContextResources that match the given pattern,
|
||||
* adding them to the given result set.
|
||||
* @param portletContext the PortletContext to work on
|
||||
* @param fullPattern the pattern to match against,
|
||||
* with preprended root directory path
|
||||
* @param dir the current directory
|
||||
* @param result the Set of matching Resources to add to
|
||||
* @throws IOException if directory contents could not be retrieved
|
||||
* @see org.springframework.web.portlet.context.PortletContextResource
|
||||
* @see javax.portlet.PortletContext#getResourcePaths
|
||||
*/
|
||||
protected void doRetrieveMatchingPortletContextResources(
|
||||
PortletContext portletContext, String fullPattern, String dir, Set<Resource> result) throws IOException {
|
||||
|
||||
Set<String> candidates = portletContext.getResourcePaths(dir);
|
||||
if (candidates != null) {
|
||||
boolean dirDepthNotFixed = fullPattern.contains("**");
|
||||
for (Iterator<String> it = candidates.iterator(); it.hasNext();) {
|
||||
String currPath = it.next();
|
||||
if (currPath.endsWith("/") &&
|
||||
(dirDepthNotFixed ||
|
||||
StringUtils.countOccurrencesOf(currPath, "/") <= StringUtils.countOccurrencesOf(fullPattern, "/"))) {
|
||||
doRetrieveMatchingPortletContextResources(portletContext, fullPattern, currPath, result);
|
||||
}
|
||||
if (getPathMatcher().match(fullPattern, currPath)) {
|
||||
result.add(new PortletContextResource(portletContext, currPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortletContext;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.beans.factory.config.Scope;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link Scope} wrapper for a PortletContext, i.e. for global web application attributes.
|
||||
*
|
||||
* <p>This differs from traditional Spring singletons in that it exposes attributes in the
|
||||
* PortletContext. Those attributes will get destroyed whenever the entire application
|
||||
* shuts down, which might be earlier or later than the shutdown of the containing Spring
|
||||
* ApplicationContext.
|
||||
*
|
||||
* <p>The associated destruction mechanism relies on a
|
||||
* {@link org.springframework.web.context.ContextCleanupListener} being registered in
|
||||
* {@code web.xml}. Note that {@link org.springframework.web.context.ContextLoaderListener}
|
||||
* includes ContextCleanupListener's functionality.
|
||||
*
|
||||
* <p>This scope is registered as default scope with key
|
||||
* {@link org.springframework.web.context.WebApplicationContext#SCOPE_APPLICATION "application"}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
* @see org.springframework.web.context.ContextCleanupListener
|
||||
*/
|
||||
public class PortletContextScope implements Scope, DisposableBean {
|
||||
|
||||
private final PortletContext portletContext;
|
||||
|
||||
private final Map<String, Runnable> destructionCallbacks = new LinkedHashMap<String, Runnable>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a new Scope wrapper for the given PortletContext.
|
||||
* @param portletContext the PortletContext to wrap
|
||||
*/
|
||||
public PortletContextScope(PortletContext portletContext) {
|
||||
Assert.notNull(portletContext, "PortletContext must not be null");
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object get(String name, ObjectFactory<?> objectFactory) {
|
||||
Object scopedObject = this.portletContext.getAttribute(name);
|
||||
if (scopedObject == null) {
|
||||
scopedObject = objectFactory.getObject();
|
||||
this.portletContext.setAttribute(name, scopedObject);
|
||||
}
|
||||
return scopedObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object remove(String name) {
|
||||
Object scopedObject = this.portletContext.getAttribute(name);
|
||||
if (scopedObject != null) {
|
||||
this.portletContext.removeAttribute(name);
|
||||
this.destructionCallbacks.remove(name);
|
||||
return scopedObject;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDestructionCallback(String name, Runnable callback) {
|
||||
this.destructionCallbacks.put(name, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveContextualObject(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConversationId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invoke all registered destruction callbacks.
|
||||
* To be called on ServletContext shutdown.
|
||||
* @see org.springframework.web.context.ContextCleanupListener
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
for (Runnable runnable : this.destructionCallbacks.values()) {
|
||||
runnable.run();
|
||||
}
|
||||
this.destructionCallbacks.clear();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 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.web.portlet.context;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.AbstractRequestAttributes;
|
||||
import org.springframework.web.context.request.DestructionCallbackBindingListener;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* Portlet-based implementation of the
|
||||
* {@link org.springframework.web.context.request.RequestAttributes} interface.
|
||||
*
|
||||
* <p>Accesses objects from portlet request and portlet session scope,
|
||||
* with a distinction between "session" (the PortletSession's "portlet scope")
|
||||
* and "global session" (the PortletSession's "application scope").
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see javax.portlet.PortletRequest#getAttribute
|
||||
* @see javax.portlet.PortletSession#getAttribute
|
||||
* @see javax.portlet.PortletSession#PORTLET_SCOPE
|
||||
* @see javax.portlet.PortletSession#APPLICATION_SCOPE
|
||||
* @see RequestAttributes#SCOPE_SESSION
|
||||
* @see RequestAttributes#SCOPE_GLOBAL_SESSION
|
||||
*/
|
||||
public class PortletRequestAttributes extends AbstractRequestAttributes {
|
||||
|
||||
/**
|
||||
* Constant identifying the {@link String} prefixed to the name of a
|
||||
* destruction callback when it is stored in a {@link PortletSession}.
|
||||
*/
|
||||
public static final String DESTRUCTION_CALLBACK_NAME_PREFIX =
|
||||
PortletRequestAttributes.class.getName() + ".DESTRUCTION_CALLBACK.";
|
||||
|
||||
|
||||
private final PortletRequest request;
|
||||
|
||||
private PortletResponse response;
|
||||
|
||||
private volatile PortletSession session;
|
||||
|
||||
private final Map<String, Object> sessionAttributesToUpdate = new ConcurrentHashMap<String, Object>(1);
|
||||
|
||||
private final Map<String, Object> globalSessionAttributesToUpdate = new ConcurrentHashMap<String, Object>(1);
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestAttributes instance for the given request.
|
||||
* @param request current portlet request
|
||||
*/
|
||||
public PortletRequestAttributes(PortletRequest request) {
|
||||
Assert.notNull(request, "Request must not be null");
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestAttributes instance for the given request.
|
||||
* @param request current portlet request
|
||||
* @param response current portlet response (for optional exposure)
|
||||
*/
|
||||
public PortletRequestAttributes(PortletRequest request, PortletResponse response) {
|
||||
this(request);
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Exposes the native {@link PortletRequest} that we're wrapping.
|
||||
*/
|
||||
public final PortletRequest getRequest() {
|
||||
return this.request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the native {@link PortletResponse} that we're wrapping (if any).
|
||||
*/
|
||||
public final PortletResponse getResponse() {
|
||||
return this.response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the {@link PortletSession} that we're wrapping.
|
||||
* @param allowCreate whether to allow creation of a new session if none exists yet
|
||||
*/
|
||||
protected final PortletSession getSession(boolean allowCreate) {
|
||||
if (isRequestActive()) {
|
||||
PortletSession session = this.request.getPortletSession(allowCreate);
|
||||
this.session = session;
|
||||
return session;
|
||||
}
|
||||
else {
|
||||
// Access through stored session reference, if any...
|
||||
PortletSession session = this.session;
|
||||
if (session == null) {
|
||||
if (allowCreate) {
|
||||
throw new IllegalStateException(
|
||||
"No session found and request already completed - cannot create new session!");
|
||||
}
|
||||
else {
|
||||
session = this.request.getPortletSession(false);
|
||||
this.session = session;
|
||||
}
|
||||
}
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name, int scope) {
|
||||
if (scope == SCOPE_REQUEST) {
|
||||
if (!isRequestActive()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot ask for request attribute - request is not active anymore!");
|
||||
}
|
||||
return this.request.getAttribute(name);
|
||||
}
|
||||
else {
|
||||
PortletSession session = getSession(false);
|
||||
if (session != null) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION) {
|
||||
Object value = session.getAttribute(name, PortletSession.APPLICATION_SCOPE);
|
||||
if (value != null) {
|
||||
this.globalSessionAttributesToUpdate.put(name, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
Object value = session.getAttribute(name);
|
||||
if (value != null) {
|
||||
this.sessionAttributesToUpdate.put(name, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String name, Object value, int scope) {
|
||||
if (scope == SCOPE_REQUEST) {
|
||||
if (!isRequestActive()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot set request attribute - request is not active anymore!");
|
||||
}
|
||||
this.request.setAttribute(name, value);
|
||||
}
|
||||
else {
|
||||
PortletSession session = getSession(true);
|
||||
if (scope == SCOPE_GLOBAL_SESSION) {
|
||||
session.setAttribute(name, value, PortletSession.APPLICATION_SCOPE);
|
||||
this.globalSessionAttributesToUpdate.remove(name);
|
||||
}
|
||||
else {
|
||||
session.setAttribute(name, value);
|
||||
this.sessionAttributesToUpdate.remove(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String name, int scope) {
|
||||
if (scope == SCOPE_REQUEST) {
|
||||
if (isRequestActive()) {
|
||||
this.request.removeAttribute(name);
|
||||
removeRequestDestructionCallback(name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PortletSession session = getSession(false);
|
||||
if (session != null) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION) {
|
||||
session.removeAttribute(name, PortletSession.APPLICATION_SCOPE);
|
||||
this.globalSessionAttributesToUpdate.remove(name);
|
||||
}
|
||||
else {
|
||||
session.removeAttribute(name);
|
||||
this.sessionAttributesToUpdate.remove(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames(int scope) {
|
||||
if (scope == SCOPE_REQUEST) {
|
||||
if (!isRequestActive()) {
|
||||
throw new IllegalStateException(
|
||||
"Cannot ask for request attributes - request is not active anymore!");
|
||||
}
|
||||
return StringUtils.toStringArray(this.request.getAttributeNames());
|
||||
}
|
||||
else {
|
||||
PortletSession session = getSession(false);
|
||||
if (session != null) {
|
||||
if (scope == SCOPE_GLOBAL_SESSION) {
|
||||
return StringUtils.toStringArray(session.getAttributeNames(PortletSession.APPLICATION_SCOPE));
|
||||
}
|
||||
else {
|
||||
return StringUtils.toStringArray(session.getAttributeNames());
|
||||
}
|
||||
}
|
||||
return new String[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDestructionCallback(String name, Runnable callback, int scope) {
|
||||
if (scope == SCOPE_REQUEST) {
|
||||
registerRequestDestructionCallback(name, callback);
|
||||
}
|
||||
else {
|
||||
registerSessionDestructionCallback(name, callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveReference(String key) {
|
||||
if (REFERENCE_REQUEST.equals(key)) {
|
||||
return this.request;
|
||||
}
|
||||
else if (REFERENCE_SESSION.equals(key)) {
|
||||
return getSession(true);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSessionId() {
|
||||
return getSession(true).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSessionMutex() {
|
||||
return PortletUtils.getSessionMutex(getSession(true));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update all accessed session attributes through {@code session.setAttribute}
|
||||
* calls, explicitly indicating to the container that they might have been modified.
|
||||
*/
|
||||
@Override
|
||||
protected void updateAccessedSessionAttributes() {
|
||||
if (!this.sessionAttributesToUpdate.isEmpty() || !this.globalSessionAttributesToUpdate.isEmpty()) {
|
||||
PortletSession session = getSession(false);
|
||||
if (session != null) {
|
||||
try {
|
||||
for (Map.Entry<String, Object> entry : this.sessionAttributesToUpdate.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
Object newValue = entry.getValue();
|
||||
Object oldValue = session.getAttribute(name);
|
||||
if (oldValue == newValue) {
|
||||
session.setAttribute(name, newValue);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : this.globalSessionAttributesToUpdate.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
Object newValue = entry.getValue();
|
||||
Object oldValue = session.getAttribute(name, PortletSession.APPLICATION_SCOPE);
|
||||
if (oldValue == newValue) {
|
||||
session.setAttribute(name, newValue, PortletSession.APPLICATION_SCOPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
// Session invalidated - shouldn't usually happen.
|
||||
}
|
||||
}
|
||||
this.sessionAttributesToUpdate.clear();
|
||||
this.globalSessionAttributesToUpdate.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given callback as to be executed after session termination.
|
||||
* <p>Note: The callback object should be serializable in order to survive
|
||||
* web app restarts.
|
||||
* @param name the name of the attribute to register the callback for
|
||||
* @param callback the callback to be executed for destruction
|
||||
*/
|
||||
protected void registerSessionDestructionCallback(String name, Runnable callback) {
|
||||
PortletSession session = getSession(true);
|
||||
session.setAttribute(DESTRUCTION_CALLBACK_NAME_PREFIX + name,
|
||||
new DestructionCallbackBindingListener(callback));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.request.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.context;
|
||||
|
||||
import org.springframework.web.context.support.RequestHandledEvent;
|
||||
|
||||
/**
|
||||
* Portlet-specific subclass of RequestHandledEvent,
|
||||
* adding portlet-specific context information.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see org.springframework.web.portlet.FrameworkPortlet
|
||||
* @see org.springframework.context.ApplicationContext#publishEvent
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PortletRequestHandledEvent extends RequestHandledEvent {
|
||||
|
||||
/** Name of the portlet that handled the request */
|
||||
private final String portletName;
|
||||
|
||||
/** PortletMode of the request */
|
||||
private final String portletMode;
|
||||
|
||||
/** Type of Portlet Request */
|
||||
private final String requestType;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestHandledEvent.
|
||||
* @param source the component that published the event
|
||||
* @param portletName the name of the portlet that handled the request
|
||||
* @param portletMode the PortletMode of the request (usually 'view', 'edit', or 'help')
|
||||
* @param requestType the type of Portlet request ('action' or 'render')
|
||||
* @param sessionId the id of the HTTP session, if any
|
||||
* @param userName the name of the user that was associated with the
|
||||
* request, if any (usually the UserPrincipal)
|
||||
* @param processingTimeMillis the processing time of the request in milliseconds
|
||||
*/
|
||||
public PortletRequestHandledEvent(Object source, String portletName,
|
||||
String portletMode, String requestType, String sessionId,
|
||||
String userName, long processingTimeMillis) {
|
||||
|
||||
super(source, sessionId, userName, processingTimeMillis);
|
||||
this.portletName = portletName;
|
||||
this.portletMode = portletMode;
|
||||
this.requestType = requestType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletRequestHandledEvent.
|
||||
* @param source the component that published the event
|
||||
* @param portletName the name of the portlet that handled the request
|
||||
* @param portletMode the PortletMode of the request (usually 'view', 'edit', or 'help')
|
||||
* @param requestType the type of Portlet request ('action' or 'render')
|
||||
* @param sessionId the id of the HTTP session, if any
|
||||
* @param userName the name of the user that was associated with the
|
||||
* request, if any (usually the UserPrincipal)
|
||||
* @param processingTimeMillis the processing time of the request in milliseconds
|
||||
* @param failureCause the cause of failure, if any
|
||||
*/
|
||||
public PortletRequestHandledEvent(Object source, String portletName,
|
||||
String portletMode, String requestType, String sessionId,
|
||||
String userName, long processingTimeMillis, Throwable failureCause) {
|
||||
|
||||
super(source, sessionId, userName, processingTimeMillis, failureCause);
|
||||
this.portletName = portletName;
|
||||
this.portletMode = portletMode;
|
||||
this.requestType = requestType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the portlet that handled the request.
|
||||
*/
|
||||
public String getPortletName() {
|
||||
return this.portletName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mode of the portlet request (usually 'view', 'edit', or 'help').
|
||||
*/
|
||||
public String getPortletMode() {
|
||||
return this.portletMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of Portlet Request ('action' or 'render').
|
||||
*/
|
||||
public String getRequestType() {
|
||||
return this.requestType;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getShortDescription() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("portlet=[").append(this.portletName).append("]; ");
|
||||
sb.append(super.getShortDescription());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("portlet=[").append(this.portletName).append("]; ");
|
||||
sb.append("mode=[").append(this.portletMode).append("]; ");
|
||||
sb.append("type=[").append(this.requestType).append("]; ");
|
||||
sb.append(super.getDescription());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PortletRequestHandledEvent: " + getDescription();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.portlet.context;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletResponse;
|
||||
import javax.portlet.PortletSession;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.portlet.util.PortletUtils;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.web.context.request.WebRequest} adapter
|
||||
* for a {@link javax.portlet.PortletRequest}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PortletWebRequest extends PortletRequestAttributes implements NativeWebRequest {
|
||||
|
||||
/**
|
||||
* Create a new PortletWebRequest instance for the given request.
|
||||
* @param request current portlet request
|
||||
*/
|
||||
public PortletWebRequest(PortletRequest request) {
|
||||
super(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new PortletWebRequest instance for the given request/response pair.
|
||||
* @param request current portlet request
|
||||
* @param response current portlet response
|
||||
*/
|
||||
public PortletWebRequest(PortletRequest request, PortletResponse response) {
|
||||
super(request, response);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object getNativeRequest() {
|
||||
return getRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getNativeResponse() {
|
||||
return getResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getNativeRequest(Class<T> requiredType) {
|
||||
return PortletUtils.getNativeRequest(getRequest(), requiredType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getNativeResponse(Class<T> requiredType) {
|
||||
return PortletUtils.getNativeResponse(getResponse(), requiredType);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getHeader(String headerName) {
|
||||
return getRequest().getProperty(headerName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getHeaderValues(String headerName) {
|
||||
String[] headerValues = StringUtils.toStringArray(getRequest().getProperties(headerName));
|
||||
return (!ObjectUtils.isEmpty(headerValues) ? headerValues : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> getHeaderNames() {
|
||||
return CollectionUtils.toIterator(getRequest().getPropertyNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String paramName) {
|
||||
return getRequest().getParameter(paramName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String paramName) {
|
||||
return getRequest().getParameterValues(paramName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<String> getParameterNames() {
|
||||
return CollectionUtils.toIterator(getRequest().getParameterNames());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
return getRequest().getParameterMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return getRequest().getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath() {
|
||||
return getRequest().getContextPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteUser() {
|
||||
return getRequest().getRemoteUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return getRequest().getUserPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String role) {
|
||||
return getRequest().isUserInRole(role);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return getRequest().isSecure();
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified handling not supported for portlet requests:
|
||||
* As a consequence, this method always returns {@code false}.
|
||||
*/
|
||||
@Override
|
||||
public boolean checkNotModified(long lastModifiedTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified handling not supported for portlet requests:
|
||||
* As a consequence, this method always returns {@code false}.
|
||||
*/
|
||||
@Override
|
||||
public boolean checkNotModified(String eTag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last-modified handling not supported for portlet requests:
|
||||
* As a consequence, this method always returns {@code false}.
|
||||
* @since 4.2
|
||||
*/
|
||||
@Override
|
||||
public boolean checkNotModified(String etag, long lastModifiedTimestamp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription(boolean includeClientInfo) {
|
||||
PortletRequest request = getRequest();
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append("context=").append(request.getContextPath());
|
||||
if (includeClientInfo) {
|
||||
PortletSession session = request.getPortletSession(false);
|
||||
if (session != null) {
|
||||
result.append(";session=").append(session.getId());
|
||||
}
|
||||
String user = getRequest().getRemoteUser();
|
||||
if (StringUtils.hasLength(user)) {
|
||||
result.append(";user=").append(user);
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PortletWebRequest: " + getDescription(true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.PropertySource.StubPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.jndi.JndiLocatorDelegate;
|
||||
import org.springframework.jndi.JndiPropertySource;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
|
||||
/**
|
||||
* {@link Environment} implementation to be used by {@code Servlet}-based web
|
||||
* applications. All Portlet-related {@code ApplicationContext} classes
|
||||
* initialize an instance by default.
|
||||
*
|
||||
* <p>Contributes {@code ServletContext}, {@code PortletContext},
|
||||
* {@code PortletConfig} and JNDI-based {@link PropertySource} instances.
|
||||
* See the {@link #customizePropertySources} method for details.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
* @see StandardEnvironment
|
||||
* @see StandardServletEnvironment
|
||||
*/
|
||||
public class StandardPortletEnvironment extends StandardEnvironment {
|
||||
|
||||
/** Portlet context init parameters property source name: {@value} */
|
||||
public static final String PORTLET_CONTEXT_PROPERTY_SOURCE_NAME = "portletContextInitParams";
|
||||
|
||||
/** Portlet config init parameters property source name: {@value} */
|
||||
public static final String PORTLET_CONFIG_PROPERTY_SOURCE_NAME = "portletConfigInitParams";
|
||||
|
||||
|
||||
/**
|
||||
* Customize the set of property sources with those contributed by superclasses as
|
||||
* well as those appropriate for standard portlet-based environments:
|
||||
* <ul>
|
||||
* <li>{@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME}
|
||||
* <li>{@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME}
|
||||
* <li>{@linkplain StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME "servletContextInitParams"}
|
||||
* <li>{@linkplain StandardServletEnvironment#JNDI_PROPERTY_SOURCE_NAME "jndiProperties"}
|
||||
* </ul>
|
||||
* <p>Properties present in {@value #PORTLET_CONFIG_PROPERTY_SOURCE_NAME} will
|
||||
* take precedence over those in {@value #PORTLET_CONTEXT_PROPERTY_SOURCE_NAME},
|
||||
* which takes precedence over those in {@linkplain
|
||||
* StandardServletEnvironment#SERVLET_CONTEXT_PROPERTY_SOURCE_NAME "servletContextInitParams"}
|
||||
* and so on.
|
||||
* <p>Properties in any of the above will take precedence over system properties and
|
||||
* environment variables contributed by the {@link StandardEnvironment} superclass.
|
||||
* <p>The property sources are added as stubs for now, and will be
|
||||
* {@linkplain PortletApplicationContextUtils#initPortletPropertySources fully
|
||||
* initialized} once the actual {@link PortletConfig}, {@link PortletContext}, and
|
||||
* {@link ServletContext} objects are available.
|
||||
* @see StandardEnvironment#customizePropertySources
|
||||
* @see org.springframework.core.env.AbstractEnvironment#customizePropertySources
|
||||
* @see PortletConfigPropertySource
|
||||
* @see PortletContextPropertySource
|
||||
* @see PortletApplicationContextUtils#initPortletPropertySources
|
||||
*/
|
||||
@Override
|
||||
protected void customizePropertySources(MutablePropertySources propertySources) {
|
||||
propertySources.addLast(new StubPropertySource(PORTLET_CONFIG_PROPERTY_SOURCE_NAME));
|
||||
propertySources.addLast(new StubPropertySource(PORTLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||
propertySources.addLast(new StubPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
|
||||
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
|
||||
propertySources.addLast(new JndiPropertySource(StandardServletEnvironment.JNDI_PROPERTY_SOURCE_NAME));
|
||||
}
|
||||
super.customizePropertySources(propertySources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any {@linkplain
|
||||
* org.springframework.core.env.PropertySource.StubPropertySource stub property source}
|
||||
* instances acting as placeholders with real portlet context/config property sources
|
||||
* using the given parameters.
|
||||
* @param servletContext the {@link ServletContext} (may be {@code null})
|
||||
* @param portletContext the {@link PortletContext} (may not be {@code null})
|
||||
* @param portletConfig the {@link PortletConfig} ({@code null} if not available)
|
||||
* @see org.springframework.web.portlet.context.PortletApplicationContextUtils#initPortletPropertySources(
|
||||
* org.springframework.core.env.MutablePropertySources, ServletContext, PortletContext, PortletConfig)
|
||||
*/
|
||||
public void initPropertySources(ServletContext servletContext, PortletContext portletContext, PortletConfig portletConfig) {
|
||||
PortletApplicationContextUtils.initPortletPropertySources(getPropertySources(), servletContext, portletContext, portletConfig);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.context;
|
||||
|
||||
import javax.portlet.PortletConfig;
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePatternResolver;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.ServletContextAwareProcessor;
|
||||
|
||||
/**
|
||||
* Static Portlet-based {@link org.springframework.context.ApplicationContext}
|
||||
* implementation for testing. Not intended for use in production applications.
|
||||
*
|
||||
* <p>Implements the
|
||||
* {@link org.springframework.web.portlet.context.ConfigurablePortletApplicationContext}
|
||||
* interface to allow for direct replacement of an {@link XmlPortletApplicationContext},
|
||||
* despite not actually supporting external configuration files.
|
||||
*
|
||||
* <p>Interprets resource paths as portlet context resources, that is, as paths
|
||||
* beneath the portlet application root. Absolute paths, for example for files
|
||||
* outside the portlet app root, can be accessed via "file:" URLs, as implemented
|
||||
* by {@link org.springframework.core.io.DefaultResourceLoader}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class StaticPortletApplicationContext extends StaticApplicationContext
|
||||
implements ConfigurablePortletApplicationContext {
|
||||
|
||||
private ServletContext servletContext;
|
||||
|
||||
private PortletContext portletContext;
|
||||
|
||||
private PortletConfig portletConfig;
|
||||
|
||||
private String namespace;
|
||||
|
||||
|
||||
public StaticPortletApplicationContext() {
|
||||
setDisplayName("Root Portlet ApplicationContext");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a new {@link StandardPortletEnvironment}
|
||||
*/
|
||||
@Override
|
||||
protected ConfigurableEnvironment createEnvironment() {
|
||||
return new StandardPortletEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>Replace {@code Portlet}- and {@code Servlet}-related property sources.
|
||||
*/
|
||||
@Override
|
||||
protected void initPropertySources() {
|
||||
PortletApplicationContextUtils.initPortletPropertySources(getEnvironment().getPropertySources(),
|
||||
this.servletContext, this.portletContext, this.portletConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>The parent {@linkplain #getEnvironment() environment} is
|
||||
* delegated to this (child) context if the parent is a
|
||||
* {@link org.springframework.context.ConfigurableApplicationContext} implementation.
|
||||
* <p>The parent {@linkplain #getServletContext() servlet context} is
|
||||
* delegated to this (child) context if the parent is a {@link WebApplicationContext}
|
||||
* implementation.
|
||||
*/
|
||||
@Override
|
||||
public void setParent(ApplicationContext parent) {
|
||||
super.setParent(parent);
|
||||
if (parent instanceof WebApplicationContext) {
|
||||
this.servletContext = ((WebApplicationContext) parent).getServletContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return this.servletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletContext(PortletContext portletContext) {
|
||||
this.portletContext = portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletContext getPortletContext() {
|
||||
return this.portletContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortletConfig(PortletConfig portletConfig) {
|
||||
this.portletConfig = portletConfig;
|
||||
if (portletConfig != null && this.portletContext == null) {
|
||||
this.portletContext = portletConfig.getPortletContext();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PortletConfig getPortletConfig() {
|
||||
return this.portletConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
if (namespace != null) {
|
||||
setDisplayName("Portlet ApplicationContext for namespace '" + namespace + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link StaticPortletApplicationContext} class does not support this method.
|
||||
* @throws UnsupportedOperationException <b>always</b>
|
||||
*/
|
||||
@Override
|
||||
public void setConfigLocation(String configLocation) {
|
||||
if (configLocation != null) {
|
||||
throw new UnsupportedOperationException("StaticPortletApplicationContext does not support config locations");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link StaticPortletApplicationContext} class does not support this method.
|
||||
* @throws UnsupportedOperationException <b>always</b>
|
||||
*/
|
||||
@Override
|
||||
public void setConfigLocations(String... configLocations) {
|
||||
if (configLocations != null) {
|
||||
throw new UnsupportedOperationException("StaticPortletApplicationContext does not support config locations");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getConfigLocations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register request/session scopes, a {@link PortletContextAwareProcessor}, etc.
|
||||
*/
|
||||
@Override
|
||||
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
|
||||
beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
|
||||
beanFactory.addBeanPostProcessor(new PortletContextAwareProcessor(this.portletContext, this.portletConfig));
|
||||
beanFactory.ignoreDependencyInterface(PortletContextAware.class);
|
||||
beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
|
||||
|
||||
PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory, this.portletContext);
|
||||
PortletApplicationContextUtils.registerEnvironmentBeans(
|
||||
beanFactory, this.servletContext, this.portletContext, this.portletConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports file paths beneath the root of the PortletContext.
|
||||
* @see PortletContextResource
|
||||
*/
|
||||
@Override
|
||||
protected Resource getResourceByPath(String path) {
|
||||
return new PortletContextResource(this.portletContext, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation supports pattern matching in unexpanded WARs too.
|
||||
* @see PortletContextResourcePatternResolver
|
||||
*/
|
||||
@Override
|
||||
protected ResourcePatternResolver getResourcePatternResolver() {
|
||||
return new PortletContextResourcePatternResolver(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.web.portlet.context;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.xml.ResourceEntityResolver;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
|
||||
/**
|
||||
* Portlet-based {@link org.springframework.web.context.WebApplicationContext}
|
||||
* implementation which takes its configuration from XML documents, understood
|
||||
* by an {@link org.springframework.beans.factory.xml.XmlBeanDefinitionReader}.
|
||||
* This is essentially the equivalent of
|
||||
* {@link org.springframework.context.support.AbstractXmlApplicationContext}
|
||||
* for a portlet environment.
|
||||
*
|
||||
* <p>By default, the configuration will be taken from "/WEB-INF/applicationContext.xml"
|
||||
* for the root context, and "/WEB-INF/test-portlet.xml" for a context with the namespace
|
||||
* "test-portlet" (like for a DispatcherPortlet instance with the portlet-name "test").
|
||||
*
|
||||
* <p>The config location defaults can be overridden via the "contextConfigLocation"
|
||||
* portlet init-param of {@link org.springframework.web.portlet.FrameworkPortlet}.
|
||||
* Config locations can either denote concrete files like "/WEB-INF/context.xml"
|
||||
* or Ant-style patterns like "/WEB-INF/*-context.xml" (see
|
||||
* {@link org.springframework.util.PathMatcher} javadoc for pattern details).
|
||||
*
|
||||
* <p>Note: In case of multiple config locations, later bean definitions will
|
||||
* override ones defined in earlier loaded files. This can be leveraged to
|
||||
* deliberately override certain bean definitions via an extra XML file.
|
||||
*
|
||||
* <p><b>For a Portlet-based context that reads in a different bean definition format,
|
||||
* create an analogous subclass of {@link AbstractRefreshablePortletApplicationContext}.</b>
|
||||
* Such a context implementation can be specified as "contextClass" init-param
|
||||
* for a FrameworkPortlet instance.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #setNamespace
|
||||
* @see #setConfigLocations
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
|
||||
* @see org.springframework.web.portlet.FrameworkPortlet#initPortletApplicationContext
|
||||
*/
|
||||
public class XmlPortletApplicationContext extends AbstractRefreshablePortletApplicationContext {
|
||||
|
||||
/** Default config location for the root context */
|
||||
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
|
||||
|
||||
/** Default prefix for building a config location for a namespace */
|
||||
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
|
||||
|
||||
/** Default suffix for building a config location for a namespace */
|
||||
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
|
||||
|
||||
|
||||
/**
|
||||
* Loads the bean definitions via an XmlBeanDefinitionReader.
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
|
||||
* @see #initBeanDefinitionReader
|
||||
* @see #loadBeanDefinitions
|
||||
*/
|
||||
@Override
|
||||
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
|
||||
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
|
||||
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
|
||||
|
||||
// Configure the bean definition reader with this context's
|
||||
// resource loading environment.
|
||||
beanDefinitionReader.setEnvironment(this.getEnvironment());
|
||||
beanDefinitionReader.setResourceLoader(this);
|
||||
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
|
||||
|
||||
// Allow a subclass to provide custom initialization of the reader,
|
||||
// then proceed with actually loading the bean definitions.
|
||||
initBeanDefinitionReader(beanDefinitionReader);
|
||||
loadBeanDefinitions(beanDefinitionReader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the bean definition reader used for loading the bean
|
||||
* definitions of this context. Default implementation is empty.
|
||||
* <p>Can be overridden in subclasses, e.g. for turning off XML validation
|
||||
* or using a different XmlBeanDefinitionParser implementation.
|
||||
* @param beanDefinitionReader the bean definition reader used by this context
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setValidationMode
|
||||
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
|
||||
*/
|
||||
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the bean definitions with the given XmlBeanDefinitionReader.
|
||||
* <p>The lifecycle of the bean factory is handled by the refreshBeanFactory method;
|
||||
* therefore this method is just supposed to load and/or register bean definitions.
|
||||
* <p>Delegates to a ResourcePatternResolver for resolving location patterns
|
||||
* into Resource instances.
|
||||
* @throws org.springframework.beans.BeansException in case of bean registration errors
|
||||
* @throws java.io.IOException if the required XML document isn't found
|
||||
* @see #refreshBeanFactory
|
||||
* @see #getConfigLocations
|
||||
* @see #getResources
|
||||
* @see #getResourcePatternResolver
|
||||
*/
|
||||
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
|
||||
String[] configLocations = getConfigLocations();
|
||||
if (configLocations != null) {
|
||||
for (int i = 0; i < configLocations.length; i++) {
|
||||
reader.loadBeanDefinitions(configLocations[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The default location for the root context is "/WEB-INF/applicationContext.xml",
|
||||
* and "/WEB-INF/test-portlet.xml" for a context with the namespace "test-portlet"
|
||||
* (like for a DispatcherPortlet instance with the portlet-name "test").
|
||||
*/
|
||||
@Override
|
||||
protected String[] getDefaultConfigLocations() {
|
||||
if (getNamespace() != null) {
|
||||
return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
|
||||
}
|
||||
else {
|
||||
return new String[] {DEFAULT_CONFIG_LOCATION};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Support for Spring's application context concept in a portlet environment,
|
||||
* including ApplicationContext implementations and various utility classes.
|
||||
*/
|
||||
package org.springframework.web.portlet.context;
|
||||
@@ -1,224 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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.web.portlet.handler;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.portlet.MimeResponse;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.portlet.ResourceRequest;
|
||||
import javax.portlet.ResourceResponse;
|
||||
import javax.portlet.WindowState;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.portlet.HandlerExceptionResolver;
|
||||
import org.springframework.web.portlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link HandlerExceptionResolver} implementations.
|
||||
*
|
||||
* <p>Provides a set of mapped handlers that the resolver should map to,
|
||||
* and the {@link Ordered} implementation.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class AbstractHandlerExceptionResolver implements HandlerExceptionResolver, Ordered {
|
||||
|
||||
/** Logger available to subclasses */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
private Set<?> mappedHandlers;
|
||||
|
||||
private Class<?>[] mappedHandlerClasses;
|
||||
|
||||
private Log warnLogger;
|
||||
|
||||
private boolean renderWhenMinimized = false;
|
||||
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the set of handlers that this exception resolver should apply to.
|
||||
* <p>The exception mappings and the default error view will only apply to the specified handlers.
|
||||
* <p>If no handlers or handler classes are set, the exception mappings and the default error
|
||||
* view will apply to all handlers. This means that a specified default error view will be used
|
||||
* as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
|
||||
* ignored in this case.
|
||||
*/
|
||||
public void setMappedHandlers(Set<?> mappedHandlers) {
|
||||
this.mappedHandlers = mappedHandlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the set of classes that this exception resolver should apply to.
|
||||
* <p>The exception mappings and the default error view will only apply to handlers of the
|
||||
* specified types; the specified types may be interfaces or superclasses of handlers as well.
|
||||
* <p>If no handlers or handler classes are set, the exception mappings and the default error
|
||||
* view will apply to all handlers. This means that a specified default error view will be used
|
||||
* as a fallback for all exceptions; any further HandlerExceptionResolvers in the chain will be
|
||||
* ignored in this case.
|
||||
*/
|
||||
public void setMappedHandlerClasses(Class<?>... mappedHandlerClasses) {
|
||||
this.mappedHandlerClasses = mappedHandlerClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the log category for warn logging. The name will be passed to the underlying logger
|
||||
* implementation through Commons Logging, getting interpreted as a log category according
|
||||
* to the logger's configuration.
|
||||
* <p>Default is no warn logging. Specify this setting to activate warn logging into a specific
|
||||
* category. Alternatively, override the {@link #logException} method for custom logging.
|
||||
* @see org.apache.commons.logging.LogFactory#getLog(String)
|
||||
* @see org.apache.log4j.Logger#getLogger(String)
|
||||
* @see java.util.logging.Logger#getLogger(String)
|
||||
*/
|
||||
public void setWarnLogCategory(String loggerName) {
|
||||
this.warnLogger = LogFactory.getLog(loggerName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the resolver should render a view when the portlet is in
|
||||
* a minimized window. The default is "false".
|
||||
* @see javax.portlet.RenderRequest#getWindowState()
|
||||
* @see javax.portlet.WindowState#MINIMIZED
|
||||
*/
|
||||
public void setRenderWhenMinimized(boolean renderWhenMinimized) {
|
||||
this.renderWhenMinimized = renderWhenMinimized;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether this resolver is supposed to apply (i.e. the handler
|
||||
* matches in case of "mappedHandlers" having been specified), then
|
||||
* delegates to the {@link #doResolveException} template method.
|
||||
*/
|
||||
@Override
|
||||
public ModelAndView resolveException(RenderRequest request, RenderResponse response, Object handler, Exception ex) {
|
||||
if (shouldApplyTo(request, handler)) {
|
||||
return doResolveException(request, response, handler, ex);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelAndView resolveException(ResourceRequest request, ResourceResponse response, Object handler, Exception ex) {
|
||||
if (shouldApplyTo(request, handler)) {
|
||||
return doResolveException(request, response, handler, ex);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether this resolver is supposed to apply to the given handler.
|
||||
* <p>The default implementation checks against the specified mapped handlers
|
||||
* and handler classes, if any, and also checks the window state (according
|
||||
* to the "renderWhenMinimize" property).
|
||||
* @param request current portlet request
|
||||
* @param handler the executed handler, or {@code null} if none chosen at the
|
||||
* time of the exception (for example, if multipart resolution failed)
|
||||
* @return whether this resolved should proceed with resolving the exception
|
||||
* for the given request and handler
|
||||
* @see #setMappedHandlers
|
||||
* @see #setMappedHandlerClasses
|
||||
*/
|
||||
protected boolean shouldApplyTo(PortletRequest request, Object handler) {
|
||||
// If the portlet is minimized and we don't want to render then return null.
|
||||
if (WindowState.MINIMIZED.equals(request.getWindowState()) && !this.renderWhenMinimized) {
|
||||
return false;
|
||||
}
|
||||
// Check mapped handlers...
|
||||
if (handler != null) {
|
||||
if (this.mappedHandlers != null && this.mappedHandlers.contains(handler)) {
|
||||
return true;
|
||||
}
|
||||
if (this.mappedHandlerClasses != null) {
|
||||
for (Class<?> mappedClass : this.mappedHandlerClasses) {
|
||||
if (mappedClass.isInstance(handler)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Else only apply if there are no explicit handler mappings.
|
||||
return (this.mappedHandlers == null && this.mappedHandlerClasses == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given exception at warn level, provided that warn logging has been
|
||||
* activated through the {@link #setWarnLogCategory "warnLogCategory"} property.
|
||||
* <p>Calls {@link #buildLogMessage} in order to determine the concrete message to log.
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @param request current portlet request (useful for obtaining metadata)
|
||||
* @see #setWarnLogCategory
|
||||
* @see #buildLogMessage
|
||||
* @see org.apache.commons.logging.Log#warn(Object, Throwable)
|
||||
*/
|
||||
protected void logException(Exception ex, PortletRequest request) {
|
||||
if (this.warnLogger != null && this.warnLogger.isWarnEnabled()) {
|
||||
this.warnLogger.warn(buildLogMessage(ex, request));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a log message for the given exception, occurred during processing the given request.
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @param request current portlet request (useful for obtaining metadata)
|
||||
* @return the log message to use
|
||||
*/
|
||||
protected String buildLogMessage(Exception ex, PortletRequest request) {
|
||||
return "Handler execution resulted in exception: " + ex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Actually resolve the given exception that got thrown during on handler execution,
|
||||
* returning a ModelAndView that represents a specific error page if appropriate.
|
||||
* <p>Must be overridden in subclasses, in order to apply specific exception checks.
|
||||
* Note that this template method will be invoked <i>after</i> checking whether this
|
||||
* resolved applies ("mappedHandlers" etc), so an implementation may simply proceed
|
||||
* with its actual exception handling.
|
||||
* @param request current portlet request
|
||||
* @param response current portlet response
|
||||
* @param handler the executed handler, or null if none chosen at the time of
|
||||
* the exception (for example, if multipart resolution failed)
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @return a corresponding ModelAndView to forward to, or null for default processing
|
||||
*/
|
||||
protected abstract ModelAndView doResolveException(PortletRequest request, MimeResponse response,
|
||||
Object handler, Exception ex);
|
||||
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.web.portlet.handler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.support.ApplicationObjectSupport;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.context.request.WebRequestInterceptor;
|
||||
import org.springframework.web.portlet.HandlerExecutionChain;
|
||||
import org.springframework.web.portlet.HandlerInterceptor;
|
||||
import org.springframework.web.portlet.HandlerMapping;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link org.springframework.web.portlet.HandlerMapping}
|
||||
* implementations. Supports ordering, a default handler, and handler interceptors.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author John A. Lewis
|
||||
* @since 2.0
|
||||
* @see #getHandlerInternal
|
||||
* @see #setDefaultHandler
|
||||
* @see #setInterceptors
|
||||
* @see org.springframework.web.portlet.HandlerInterceptor
|
||||
*/
|
||||
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport implements HandlerMapping, Ordered {
|
||||
|
||||
private int order = Integer.MAX_VALUE; // default: same as non-Ordered
|
||||
|
||||
private Object defaultHandler;
|
||||
|
||||
private final List<Object> interceptors = new ArrayList<Object>();
|
||||
|
||||
private boolean applyWebRequestInterceptorsToRenderPhaseOnly = true;
|
||||
|
||||
private HandlerInterceptor[] adaptedInterceptors;
|
||||
|
||||
|
||||
/**
|
||||
* Specify the order value for this HandlerMapping bean.
|
||||
* <p>Default value is {@code Integer.MAX_VALUE}, meaning that it's non-ordered.
|
||||
* @see org.springframework.core.Ordered#getOrder()
|
||||
*/
|
||||
public final void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default handler for this handler mapping.
|
||||
* This handler will be returned if no specific mapping was found.
|
||||
* <p>Default is {@code null}, indicating no default handler.
|
||||
*/
|
||||
public void setDefaultHandler(Object defaultHandler) {
|
||||
this.defaultHandler = defaultHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default handler for this handler mapping,
|
||||
* or {@code null} if none.
|
||||
*/
|
||||
public Object getDefaultHandler() {
|
||||
return this.defaultHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the interceptors to apply for all handlers mapped by this handler mapping.
|
||||
* <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
|
||||
* Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
|
||||
* @param interceptors array of handler interceptors, or {@code null} if none
|
||||
* @see #adaptInterceptor
|
||||
* @see org.springframework.web.portlet.HandlerInterceptor
|
||||
* @see org.springframework.web.context.request.WebRequestInterceptor
|
||||
*/
|
||||
public void setInterceptors(Object[] interceptors) {
|
||||
this.interceptors.addAll(Arrays.asList(interceptors));
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether to apply WebRequestInterceptors to the Portlet render phase
|
||||
* only ("true", or whether to apply them to the Portlet action phase as well
|
||||
* ("false").
|
||||
* <p>Default is "true", since WebRequestInterceptors are usually built for
|
||||
* MVC-style handler execution plus rendering process (which is, for example,
|
||||
* the primary target scenario for "Open Session in View" interceptors,
|
||||
* offering lazy loading of persistent objects during view rendering).
|
||||
* Set this to "false" to have WebRequestInterceptors apply to the action
|
||||
* phase as well (for example, in case of an "Open Session in View" interceptor,
|
||||
* to allow for lazy loading outside of a transaction during the action phase).
|
||||
* @see #setInterceptors
|
||||
* @see org.springframework.web.context.request.WebRequestInterceptor
|
||||
* @see WebRequestHandlerInterceptorAdapter#WebRequestHandlerInterceptorAdapter(WebRequestInterceptor, boolean)
|
||||
* @see org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor
|
||||
*/
|
||||
public void setApplyWebRequestInterceptorsToRenderPhaseOnly(boolean applyWebRequestInterceptorsToRenderPhaseOnly) {
|
||||
this.applyWebRequestInterceptorsToRenderPhaseOnly = applyWebRequestInterceptorsToRenderPhaseOnly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the interceptors.
|
||||
* @see #extendInterceptors(java.util.List)
|
||||
* @see #initInterceptors()
|
||||
*/
|
||||
@Override
|
||||
protected void initApplicationContext() throws BeansException {
|
||||
extendInterceptors(this.interceptors);
|
||||
initInterceptors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension hook that subclasses can override to register additional interceptors,
|
||||
* given the configured interceptors (see {@link #setInterceptors}).
|
||||
* <p>Will be invoked before {@link #initInterceptors()} adapts the specified
|
||||
* interceptors into {@link HandlerInterceptor} instances.
|
||||
* <p>The default implementation is empty.
|
||||
* @param interceptors the configured interceptor List (never {@code null}),
|
||||
* allowing to add further interceptors before as well as after the existing
|
||||
* interceptors
|
||||
*/
|
||||
protected void extendInterceptors(List<?> interceptors) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the specified interceptors, adapting them where necessary.
|
||||
* @see #setInterceptors
|
||||
* @see #adaptInterceptor
|
||||
*/
|
||||
protected void initInterceptors() {
|
||||
if (!this.interceptors.isEmpty()) {
|
||||
this.adaptedInterceptors = new HandlerInterceptor[this.interceptors.size()];
|
||||
for (int i = 0; i < this.interceptors.size(); i++) {
|
||||
Object interceptor = this.interceptors.get(i);
|
||||
if (interceptor == null) {
|
||||
throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");
|
||||
}
|
||||
this.adaptedInterceptors[i] = adaptInterceptor(interceptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapt the given interceptor object to the HandlerInterceptor interface.
|
||||
* <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
|
||||
* Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
|
||||
* Can be overridden in subclasses.
|
||||
* @param interceptor the specified interceptor object
|
||||
* @return the interceptor wrapped as HandlerInterceptor
|
||||
* @see #setApplyWebRequestInterceptorsToRenderPhaseOnly
|
||||
* @see org.springframework.web.portlet.HandlerInterceptor
|
||||
* @see org.springframework.web.context.request.WebRequestInterceptor
|
||||
* @see WebRequestHandlerInterceptorAdapter
|
||||
*/
|
||||
protected HandlerInterceptor adaptInterceptor(Object interceptor) {
|
||||
if (interceptor instanceof HandlerInterceptor) {
|
||||
return (HandlerInterceptor) interceptor;
|
||||
}
|
||||
else if (interceptor instanceof WebRequestInterceptor) {
|
||||
return new WebRequestHandlerInterceptorAdapter(
|
||||
(WebRequestInterceptor) interceptor, this.applyWebRequestInterceptorsToRenderPhaseOnly);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the adapted interceptors as HandlerInterceptor array.
|
||||
* @return the array of HandlerInterceptors, or {@code null} if none
|
||||
*/
|
||||
protected final HandlerInterceptor[] getAdaptedInterceptors() {
|
||||
return this.adaptedInterceptors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Look up a handler for the given request, falling back to the default
|
||||
* handler if no specific one is found.
|
||||
* @param request current portlet request
|
||||
* @return the corresponding handler instance, or the default handler
|
||||
* @see #getHandlerInternal
|
||||
*/
|
||||
@Override
|
||||
public final HandlerExecutionChain getHandler(PortletRequest request) throws Exception {
|
||||
Object handler = getHandlerInternal(request);
|
||||
if (handler == null) {
|
||||
handler = getDefaultHandler();
|
||||
}
|
||||
if (handler == null) {
|
||||
return null;
|
||||
}
|
||||
// Bean name or resolved handler?
|
||||
if (handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
handler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
return getHandlerExecutionChain(handler, request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a handler for the given request, returning {@code null} if no
|
||||
* specific one is found. This method is called by {@link #getHandler};
|
||||
* a {@code null} return value will lead to the default handler, if one is set.
|
||||
* <p>Note: This method may also return a pre-built {@link HandlerExecutionChain},
|
||||
* combining a handler object with dynamically determined interceptors.
|
||||
* Statically specified interceptors will get merged into such an existing chain.
|
||||
* @param request current portlet request
|
||||
* @return the corresponding handler instance, or {@code null} if none found
|
||||
* @throws Exception if there is an internal error
|
||||
* @see #getHandler
|
||||
*/
|
||||
protected abstract Object getHandlerInternal(PortletRequest request) throws Exception;
|
||||
|
||||
/**
|
||||
* Build a HandlerExecutionChain for the given handler, including applicable interceptors.
|
||||
* <p>The default implementation simply builds a standard HandlerExecutionChain with
|
||||
* the given handler and this handler mapping's common interceptors. Subclasses may
|
||||
* override this in order to extend/rearrange the list of interceptors.
|
||||
* <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a pre-built
|
||||
* HandlerExecutionChain. This method should handle those two cases explicitly,
|
||||
* either building a new HandlerExecutionChain or extending the existing chain.
|
||||
* <p>For simply adding an interceptor, consider calling {@code super.getHandlerExecutionChain}
|
||||
* and invoking {@link HandlerExecutionChain#addInterceptor} on the returned chain object.
|
||||
* @param handler the resolved handler instance (never {@code null})
|
||||
* @param request current portlet request
|
||||
* @return the HandlerExecutionChain (never {@code null})
|
||||
* @see #getAdaptedInterceptors()
|
||||
*/
|
||||
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, PortletRequest request) {
|
||||
if (handler instanceof HandlerExecutionChain) {
|
||||
HandlerExecutionChain chain = (HandlerExecutionChain) handler;
|
||||
chain.addInterceptors(getAdaptedInterceptors());
|
||||
return chain;
|
||||
}
|
||||
else {
|
||||
return new HandlerExecutionChain(handler, getAdaptedInterceptors());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.web.portlet.handler;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.portlet.PortletException;
|
||||
import javax.portlet.PortletRequest;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link org.springframework.web.portlet.HandlerMapping}
|
||||
* implementations that rely on a map which caches handler objects per lookup key.
|
||||
* Supports arbitrary lookup keys, and automatically resolves handler bean names
|
||||
* into handler bean instances.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
* @see #getLookupKey(javax.portlet.PortletRequest)
|
||||
* @see #registerHandler(Object, Object)
|
||||
*/
|
||||
public abstract class AbstractMapBasedHandlerMapping<K> extends AbstractHandlerMapping {
|
||||
|
||||
private boolean lazyInitHandlers = false;
|
||||
|
||||
private final Map<K, Object> handlerMap = new HashMap<K, Object>();
|
||||
|
||||
|
||||
/**
|
||||
* Set whether to lazily initialize handlers. Only applicable to
|
||||
* singleton handlers, as prototypes are always lazily initialized.
|
||||
* Default is false, as eager initialization allows for more efficiency
|
||||
* through referencing the handler objects directly.
|
||||
* <p>If you want to allow your handlers to be lazily initialized,
|
||||
* make them "lazy-init" and set this flag to true. Just making them
|
||||
* "lazy-init" will not work, as they are initialized through the
|
||||
* references from the handler mapping in this case.
|
||||
*/
|
||||
public void setLazyInitHandlers(boolean lazyInitHandlers) {
|
||||
this.lazyInitHandlers = lazyInitHandlers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines a handler for the computed lookup key for the given request.
|
||||
* @see #getLookupKey
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Object getHandlerInternal(PortletRequest request) throws Exception {
|
||||
K lookupKey = getLookupKey(request);
|
||||
Object handler = this.handlerMap.get(lookupKey);
|
||||
if (handler != null && logger.isDebugEnabled()) {
|
||||
logger.debug("Key [" + lookupKey + "] -> handler [" + handler + "]");
|
||||
}
|
||||
if (handler instanceof Map) {
|
||||
Map<PortletRequestMappingPredicate, Object> predicateMap =
|
||||
(Map<PortletRequestMappingPredicate, Object>) handler;
|
||||
List<PortletRequestMappingPredicate> filtered = new LinkedList<PortletRequestMappingPredicate>();
|
||||
for (PortletRequestMappingPredicate predicate : predicateMap.keySet()) {
|
||||
if (predicate.match(request)) {
|
||||
filtered.add(predicate);
|
||||
}
|
||||
}
|
||||
if (filtered.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Collections.sort(filtered);
|
||||
PortletRequestMappingPredicate predicate = filtered.get(0);
|
||||
predicate.validate(request);
|
||||
return predicateMap.get(predicate);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a lookup key for the given request.
|
||||
* @param request current portlet request
|
||||
* @return the lookup key (never {@code null})
|
||||
* @throws Exception if key computation failed
|
||||
*/
|
||||
protected abstract K getLookupKey(PortletRequest request) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Register all handlers specified in the Portlet mode map for the corresponding modes.
|
||||
* @param handlerMap Map with lookup keys as keys and handler beans or bean names as values
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
*/
|
||||
protected void registerHandlers(Map<K, ?> handlerMap) throws BeansException {
|
||||
Assert.notNull(handlerMap, "Handler Map must not be null");
|
||||
for (Map.Entry<K, ?> entry : handlerMap.entrySet()) {
|
||||
registerHandler(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given handler instance for the given parameter value.
|
||||
* @param lookupKey the key to map the handler onto
|
||||
* @param handler the handler instance or handler bean name String
|
||||
* (a bean name will automatically be resolved into the corresponding handler bean)
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
protected void registerHandler(K lookupKey, Object handler) throws BeansException, IllegalStateException {
|
||||
registerHandler(lookupKey, handler, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the given handler instance for the given parameter value.
|
||||
* @param lookupKey the key to map the handler onto
|
||||
* @param handler the handler instance or handler bean name String
|
||||
* (a bean name will automatically be resolved into the corresponding handler bean)
|
||||
* @param predicate a predicate object for this handler (may be {@code null}),
|
||||
* determining a match with the primary lookup key
|
||||
* @throws BeansException if the handler couldn't be registered
|
||||
* @throws IllegalStateException if there is a conflicting handler registered
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void registerHandler(K lookupKey, Object handler, PortletRequestMappingPredicate predicate)
|
||||
throws BeansException, IllegalStateException {
|
||||
|
||||
Assert.notNull(lookupKey, "Lookup key must not be null");
|
||||
Assert.notNull(handler, "Handler object must not be null");
|
||||
Object resolvedHandler = handler;
|
||||
|
||||
// Eagerly resolve handler if referencing singleton via name.
|
||||
if (!this.lazyInitHandlers && handler instanceof String) {
|
||||
String handlerName = (String) handler;
|
||||
if (getApplicationContext().isSingleton(handlerName)) {
|
||||
resolvedHandler = getApplicationContext().getBean(handlerName);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for duplicate mapping.
|
||||
Object mappedHandler = this.handlerMap.get(lookupKey);
|
||||
if (mappedHandler != null && !(mappedHandler instanceof Map)) {
|
||||
if (mappedHandler != resolvedHandler) {
|
||||
throw new IllegalStateException("Cannot map handler [" + handler + "] to key [" + lookupKey +
|
||||
"]: There's already handler [" + mappedHandler + "] mapped.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (predicate != null) {
|
||||
// Add the handler to the predicate map.
|
||||
Map<PortletRequestMappingPredicate, Object> predicateMap =
|
||||
(Map<PortletRequestMappingPredicate, Object>) mappedHandler;
|
||||
if (predicateMap == null) {
|
||||
predicateMap = new LinkedHashMap<PortletRequestMappingPredicate, Object>();
|
||||
this.handlerMap.put(lookupKey, predicateMap);
|
||||
}
|
||||
predicateMap.put(predicate, resolvedHandler);
|
||||
}
|
||||
else {
|
||||
// Add the single handler to the map.
|
||||
this.handlerMap.put(lookupKey, resolvedHandler);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Mapped key [" + lookupKey + "] onto handler [" + resolvedHandler + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Predicate interface for determining a match with a given request.
|
||||
*/
|
||||
protected interface PortletRequestMappingPredicate extends Comparable<PortletRequestMappingPredicate> {
|
||||
|
||||
/**
|
||||
* Determine whether the given request matches this predicate.
|
||||
* @param request current portlet request
|
||||
*/
|
||||
boolean match(PortletRequest request);
|
||||
|
||||
/**
|
||||
* Validate this predicate's mapping against the current request.
|
||||
* @param request current portlet request
|
||||
* @throws PortletException if validation failed
|
||||
*/
|
||||
void validate(PortletRequest request) throws PortletException;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user