io.neba.core.mvc.SlingServletView Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of io.neba.neba-core Show documentation
Show all versions of io.neba.neba-core Show documentation
Contains the entire NEBA core implementation, i.e. the framework that interprets the
NEBA API annotations and provides implementations for the service and lifecycle callback
interfaces provided in the NEBA API. This package must not export anything as
its implementation details are entirely private.
/*
Copyright 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 io.neba.core.mvc;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.SyntheticResource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.springframework.web.servlet.View;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* Resolves a resource path to a {@link Servlet} representing a {@link org.apache.sling.api.scripting.SlingScript}
* and invokes the script to {@link #render(Map, HttpServletRequest, HttpServletResponse) render} the view.
*
* @author Olaf Otto
*/
public class SlingServletView implements View {
private final String resourceType;
private final Servlet servlet;
/**
* @param resourceType must not be null
.
* @param servlet must not be null
.
*/
public SlingServletView(String resourceType, Servlet servlet) {
if (resourceType == null) {
throw new IllegalArgumentException("Method argument resourceType must not be null.");
}
if (servlet == null) {
throw new IllegalArgumentException("Method argument servlet must not be null.");
}
this.resourceType = resourceType;
this.servlet = servlet;
}
@Override
public String getContentType() {
return null;
}
/**
* @param model can be null
.
* @param request must not be null
.
* @param response must not be null
.
*/
@Override
public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
final ResourceResolver resourceResolver = slingRequest.getResourceResolver();
final String resourcePath = request.getPathInfo();
final Resource resource = new SpringControllerModelResource(resourceResolver, resourcePath, this.resourceType, model);
final SlingHttpServletRequest wrapped = new MvcResourceRequest(slingRequest, resource);
if (model != null) {
for (Map.Entry entry : model.entrySet()) {
wrapped.setAttribute(entry.getKey(), entry.getValue());
}
}
servlet.service(wrapped, response);
}
/**
* Wraps the original controller request to override the
* {@link #getResource() request's resource}.
*
* @author Olaf Otto
*/
static class MvcResourceRequest extends SlingHttpServletRequestWrapper {
private final Resource resource;
MvcResourceRequest(SlingHttpServletRequest slingRequest, Resource resource) {
super(slingRequest);
this.resource = resource;
}
@Override
public Resource getResource() {
return resource;
}
}
/**
* Represents the result of a spring controller invocation as a {@link Resource}. The underlying
* {@link org.springframework.ui.Model model} is provided via the {@link Resource {@link #getValueMap()} value map representation}
* of this resource.
*
* @author Olaf Otto
*/
private static class SpringControllerModelResource extends SyntheticResource {
private final Map model;
SpringControllerModelResource(ResourceResolver resourceResolver, String resourcePath, String resourceType, Map model) {
super(resourceResolver, resourcePath, resourceType);
this.model = model;
}
@Override
public ValueMap getValueMap() {
ValueMap properties = new ValueMapDecorator(new HashMap<>());
if (this.model != null) {
properties.putAll(this.model);
}
return properties;
}
@Override
@SuppressWarnings("unchecked")
public AdapterType adaptTo(Class type) {
if (type.isAssignableFrom(ValueMap.class)) {
return (AdapterType) getValueMap();
}
return super.adaptTo(type);
}
}
}