HalDocsServlet.java

  1. /*
  2.  * #%L
  3.  * wcm.io
  4.  * %%
  5.  * Copyright (C) 2015 wcm.io
  6.  * %%
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *      http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  * #L%
  19.  */
  20. package io.wcm.caravan.hal.docs.impl;

  21. import java.io.IOException;

  22. import javax.servlet.Servlet;
  23. import javax.servlet.ServletConfig;
  24. import javax.servlet.ServletException;
  25. import javax.servlet.ServletRequest;
  26. import javax.servlet.ServletResponse;
  27. import javax.servlet.http.HttpServlet;
  28. import javax.servlet.http.HttpServletRequest;
  29. import javax.servlet.http.HttpServletResponse;

  30. import org.apache.commons.lang3.CharEncoding;
  31. import org.apache.commons.lang3.StringUtils;
  32. import org.apache.felix.scr.annotations.Activate;
  33. import org.apache.felix.scr.annotations.Component;
  34. import org.apache.felix.scr.annotations.Deactivate;
  35. import org.apache.felix.scr.annotations.Reference;
  36. import org.apache.felix.scr.annotations.Service;
  37. import org.osgi.framework.Bundle;
  38. import org.osgi.service.component.ComponentContext;
  39. import org.slf4j.Logger;
  40. import org.slf4j.LoggerFactory;

  41. import io.wcm.caravan.hal.docs.impl.model.LinkRelation;
  42. import io.wcm.caravan.hal.docs.impl.reader.ServiceModelReader;

  43. /**
  44.  * Serves HAL documentation pages generated from JSON service documentation models with handlebars.
  45.  */
  46. @Component(factory = HalDocsServlet.FACTORY)
  47. @Service(Servlet.class)
  48. public class HalDocsServlet extends HttpServlet {

  49.   private static final long serialVersionUID = 1L;

  50.   static final String FACTORY = "caravan.haldocs.servlet.factory";
  51.   static final String PROPERTY_BUNDLE = "caravan.haldocs.relatedBundle";

  52.   private io.wcm.caravan.hal.docs.impl.model.Service serviceModel;

  53.   @Reference
  54.   private TemplateRenderer templateRenderer;

  55.   private static final Logger log = LoggerFactory.getLogger(HalDocsServlet.class);

  56.   @Activate
  57.   void activate(ComponentContext componentContext) {
  58.     // bundle which contains the JAX-RS services
  59.     Bundle bundle = (Bundle)componentContext.getProperties().get(PROPERTY_BUNDLE);
  60.     serviceModel = ServiceModelReader.read(bundle);
  61.   }

  62.   @Deactivate
  63.   void deactivate(ComponentContext componentContext) {
  64.     serviceModel = null;
  65.   }

  66.   @Override
  67.   public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
  68.     HttpServletRequest request = (HttpServletRequest)servletRequest;
  69.     HttpServletResponse response = (HttpServletResponse)servletResponse;

  70.     if (serviceModel != null) {
  71.       try {
  72.         String uri = StringUtils.defaultString(request.getPathInfo());
  73.         if (StringUtils.equals(uri, "/")) {
  74.           sendMarkup(templateRenderer.renderServiceHtml(serviceModel), response);
  75.           return;
  76.         }
  77.         else {
  78.           String rel = StringUtils.substringAfter(uri, "/");
  79.           LinkRelation linkRelation = serviceModel.getLinkRelations().stream()
  80.               .filter(item -> StringUtils.equals(item.getRel(), rel))
  81.               .findFirst().orElse(null);
  82.           if (linkRelation != null) {
  83.             sendMarkup(templateRenderer.renderLinkRelationHtml(serviceModel, linkRelation), response);
  84.             return;
  85.           }
  86.         }
  87.       }
  88.       catch (Throwable ex) {
  89.         log.error("Error rendering HAL docs for " + serviceModel.getServiceId() + ": " + request.getPathInfo(), ex);
  90.         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex.getMessage());
  91.       }
  92.     }

  93.     response.sendError(HttpServletResponse.SC_NOT_FOUND);
  94.   }

  95.   private void sendMarkup(String markup, HttpServletResponse response) throws IOException {
  96.     byte[] data = markup.getBytes(CharEncoding.UTF_8);
  97.     response.setContentType(HttpContextWrapper.MIMETYPE_HTML);
  98.     response.setContentLength(data.length);
  99.     response.getOutputStream().write(data);
  100.   }

  101.   @Override
  102.   public void init() throws ServletException {
  103.     // nothing to do
  104.   }

  105.   @Override
  106.   public void init(ServletConfig config) throws ServletException {
  107.     // nothing to do
  108.   }

  109.   @Override
  110.   public void destroy() {
  111.     // nothing to do
  112.   }

  113. }