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:
Juergen Hoeller
2016-07-04 23:33:45 +02:00
parent ae0b7c26c5
commit 2b3445df81
235 changed files with 94 additions and 39747 deletions

View File

@@ -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

View File

@@ -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> {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}

View File

@@ -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 + "]");
}
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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));
}
}

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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&lt;String, String&gt;} 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&lt;String, String&gt;} or
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}
* 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&lt;String, String&gt;},
* {@link org.springframework.util.MultiValueMap MultiValueMap&lt;String, String&gt;}, 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 {};

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -1,4 +0,0 @@
/**
* Support classes for web annotation processing.
*/
package org.springframework.web.bind.annotation.support;

View File

@@ -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 {

View File

@@ -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".

View File

@@ -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];
}
}
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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".

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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

View File

@@ -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 {

View File

@@ -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
*/

View File

@@ -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);

View File

@@ -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();
}
}
}

View File

@@ -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, ", "));
}
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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 &lt;list&gt; of &lt;ref&gt; 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;
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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()));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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()));
}
}
}

View File

@@ -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)));
}
}

View File

@@ -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;
}
}
}

View File

@@ -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 {};
}

View File

@@ -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 "";
}

View File

@@ -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 {};
}

View File

@@ -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 "";
}

View File

@@ -1,4 +0,0 @@
/**
* Annotations for binding portlet requests to handler methods.
*/
package org.springframework.web.portlet.bind.annotation;

View File

@@ -1,4 +0,0 @@
/**
* Provides Portlet-specific data binding functionality.
*/
package org.springframework.web.portlet.bind;

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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";
}
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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));
}
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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};
}
}
}

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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());
}
}
}

View File

@@ -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