/* (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.converters; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.geoserver.platform.ExtensionPriority; import org.geoserver.rest.RequestInfo; import org.geoserver.rest.wrapper.RestWrapper; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import freemarker.template.Template; import freemarker.template.TemplateException; /** * Message converter for Freemarker-generated HTML output */ public class FreemarkerHTMLMessageConverter extends BaseMessageConverter<RestWrapper<?>> { /** * Encoding (null for default) */ protected String encoding; public FreemarkerHTMLMessageConverter() { super(MediaType.TEXT_HTML); } public FreemarkerHTMLMessageConverter(String encoding) { this(); this.encoding = encoding; } @Override protected boolean supports(Class<?> clazz) { return RestWrapper.class.isAssignableFrom(clazz); } @Override protected boolean canRead(MediaType mediaType) { return false; // reading not supported } @Override protected RestWrapper<?> readInternal(Class<? extends RestWrapper<?>> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { throw new UnsupportedOperationException(); } /** * Write an given object to the given output message as HTML, invoked from {@link #write}. * @param wrapper The wrapped object write to the output message * @param outputMessage the HTTP output message to write to * @throws IOException in case of I/O errors * @throws HttpMessageNotWritableException in case of conversion errors */ @Override protected void writeInternal(RestWrapper<?> wrapper, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { MediaType contentType = outputMessage.getHeaders().getContentType(); Writer templateWriter = null; wrapper.configureFreemarker(this); try { Object object = wrapper.getObject(); Template template = wrapper.getTemplate(); OutputStream outputStream = outputMessage.getBody(); Charset charSet = contentType.getCharset(); if (charSet != null) { templateWriter = new BufferedWriter( new OutputStreamWriter(outputStream, charSet.name())); } else { templateWriter = new BufferedWriter( new OutputStreamWriter(outputStream, template.getEncoding())); } template.process(object, templateWriter); templateWriter.flush(); } catch (TemplateException te) { throw new IOException("Template processing error " + te.getMessage()); } finally { if (templateWriter != null) { templateWriter.close(); } } } public int getPriority() { // If no extension or content-type provided, return HTML; return ExtensionPriority.LOWEST - 1; } public List<URL> createCollectionLink(String link) { // TODO Auto-generated method stub try { String href = href(link); URL url2 = new URL(href); return Collections.singletonList(url2); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return new ArrayList<>(); } protected String href(String link) { final RequestInfo pg = RequestInfo.get(); link += ".html"; // encode as relative or absolute depending on the link type if (link.startsWith("/")) { // absolute, encode from "root" return pg.servletURI(link); } else { // encode as relative return pg.pageURI(link); } } }