/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.rest.catalog;
import java.lang.reflect.Type;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.geoserver.config.util.XStreamPersister;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.ModuleStatus;
import org.geoserver.platform.ModuleStatusImpl;
import org.geoserver.platform.RenderingEngineStatus;
import org.geoserver.rest.RestBaseController;
import org.geoserver.rest.RestException;
import org.geoserver.rest.converters.XStreamMessageConverter;
import org.geoserver.rest.wrapper.RestWrapper;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.thoughtworks.xstream.XStream;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.CollectionModel;
import freemarker.template.ObjectWrapper;
import freemarker.template.SimpleHash;
import freemarker.template.TemplateModel;
import freemarker.template.TemplateModelException;
@RestController
@RequestMapping(path = RestBaseController.ROOT_PATH + "/about/status",
produces = { MediaType.TEXT_HTML_VALUE, MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public class AboutStatusController extends RestBaseController {
@GetMapping
protected RestWrapper<ModuleStatus> statusGet() throws Exception {
List<ModuleStatus> applicationStatus = GeoServerExtensions.extensions(ModuleStatus.class)
.stream().map(ModuleStatusImpl::new).collect(Collectors.toList());
return wrapList(applicationStatus, ModuleStatus.class);
}
@GetMapping(value = "/{target}")
protected RestWrapper<ModuleStatus> statusGet(@PathVariable String target) throws Exception {
List<ModuleStatus> applicationStatus = GeoServerExtensions.extensions(ModuleStatus.class)
.stream().map(ModuleStatusImpl::new).filter(getModule(target))
.collect(Collectors.toList());
if (applicationStatus.isEmpty()) {
throw new RestException("No such module: " + target, HttpStatus.NOT_FOUND);
}
return wrapList(applicationStatus, ModuleStatus.class);
}
protected static Predicate<ModuleStatus> getModule(String target) {
return m -> m.getModule().equalsIgnoreCase(target);
}
@Override
public void configurePersister(XStreamPersister persister, XStreamMessageConverter converter) {
XStream xs = persister.getXStream();
xs.processAnnotations(ModuleStatus.class);
xs.allowTypes(new Class[] { ModuleStatus.class });
xs.alias("about", List.class);
xs.alias("status", ModuleStatus.class);
xs.addDefaultImplementation(ModuleStatusImpl.class, ModuleStatus.class);
xs.addDefaultImplementation(RenderingEngineStatus.class, ModuleStatus.class);
}
@Override
protected String getTemplateName(Object object) {
return "ModuleStatusImpl";
}
@Override
public boolean supports(MethodParameter methodParameter, Type targetType,
Class<? extends HttpMessageConverter<?>> converterType) {
return ModuleStatus.class.isAssignableFrom(methodParameter.getParameterType());
}
@Override
protected <T> ObjectWrapper createObjectWrapper(Class<T> clazz) {
return new BeansWrapper() {
@Override
public TemplateModel wrap(Object obj) throws TemplateModelException {
if (obj instanceof List) { // we expect List of ModuleStatus
List<?> list = (List<?>) obj;
SimpleHash hash = new SimpleHash();
hash.put("values", new CollectionModel(list, new BeansWrapper() {
public TemplateModel wrap(Object object) throws TemplateModelException {
if (object instanceof ModuleStatus) {
ModuleStatus status = (ModuleStatus) object;
SimpleHash hash = new SimpleHash();
hash.put("module", status.getModule());
hash.put("name", status.getName());
hash.put("isAvailable", Boolean.toString(status.isAvailable()));
hash.put("isEnabled", Boolean.toString(status.isEnabled()));
status.getComponent().ifPresent(component -> hash.put("component", component));
status.getVersion().ifPresent(version -> hash.put("version", version));
status.getMessage().ifPresent(message -> hash.put("message", message.replace("\n", "<br/>")));
return hash;
}
return super.wrap(object);
}
}));
return hash;
}
return super.wrap(obj);
}
};
}
}