Package org.apache.clerezza.platform.typerendering

Source Code of org.apache.clerezza.platform.typerendering.GenericGraphNodeMBW

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.apache.clerezza.platform.typerendering;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import java.util.Set;

import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.clerezza.rdf.core.BNode;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.utils.GraphNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
* Generates output based on the rendering mode passed as query parameter ("mode")
* and the rdf type of the given GraphNode.
*
* @author daniel, mir, rbn
*/
@Component
@Service(Object.class)
@Property(name = "javax.ws.rs", boolValue = true)
@Reference(name = "contextProvider", referenceInterface = UserContextProvider.class,
cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
policy = ReferencePolicy.DYNAMIC)
@Provider
@Produces({"application/xhtml+xml", "*/*"})
public class GenericGraphNodeMBW implements MessageBodyWriter<GraphNode> {

  public static final String MODE = "mode";
 
  @Reference
  RendererFactory rendererFactory;

  private static final Logger logger = LoggerFactory.getLogger(GenericGraphNodeMBW.class);
  private UriInfo uriInfo = null;
  private HttpHeaders headers = null;
  private final Set<UserContextProvider> contextProviders =
      Collections.synchronizedSet(new HashSet<UserContextProvider>());
  private final DocumentBuilder documentBuilder;
  private TransformerFactory transformerFactory = TransformerFactory.newInstance();

  {
    try {
      final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
      builderFactory.setValidating(false);
      builderFactory.setNamespaceAware(true);
      builderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
      documentBuilder = builderFactory.newDocumentBuilder();
    } catch (ParserConfigurationException ex) {
      throw new RuntimeException(ex);
    }
  }

  @Context
  public void setUriInfo(UriInfo uriInfo) {
    this.uriInfo = uriInfo;
  }


  @Context
  public void setHttpHeaders(HttpHeaders headers) {
    this.headers = headers;
  }

  @Override
  public long getSize(GraphNode node, Class<?> type, Type genericType,
      Annotation[] annotations, MediaType mediaType) {
    return -1;
  }

  @Override
  public boolean isWriteable(Class<?> type, Type genericType,
      Annotation[] annotations, MediaType mediaType) {
    return GraphNode.class.isAssignableFrom(type);
  }

  @Override
  public void writeTo(GraphNode node, Class<?> type, Type genericType,
      Annotation[] annotations, MediaType mediaType,
      MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream)
      throws IOException, WebApplicationException {
    String mode = getRenderingMode();

    Renderer renderer = rendererFactory.createRenderer(node, mode,
        headers.getAcceptableMediaTypes());

    if (renderer == null) {
      throw new WebApplicationException(
          Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity("No suitable renderer found").build());
    }
    final MediaType rendererMediaType = renderer.getMediaType();
    Map<String, Object> sharedRenderingValues = new HashMap<String, Object>();
    ResultDocModifier.init();
    if (!(rendererMediaType.getType().equals("application") && rendererMediaType.getSubtype().equals("xhtml+xml"))) {
      httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, rendererMediaType);
      renderer.render(node, getUserContext(), mode, uriInfo, headers, httpHeaders, sharedRenderingValues, entityStream);
    } else {
      final MediaType mediaTypeWithCharset = MediaType.valueOf(MediaType.APPLICATION_XHTML_XML+";charset=UTF-8");
      httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, mediaTypeWithCharset);
      try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        renderer.render(node, getUserContext(), mode, uriInfo, headers, httpHeaders, sharedRenderingValues, baos);
        final byte[] bytes = baos.toByteArray();
        if (!ResultDocModifier.getInstance().isModified()) {
          entityStream.write(bytes);
          return;
        }
        Document document;
        try {
          synchronized(documentBuilder) {
            document = documentBuilder.parse(new ByteArrayInputStream(bytes));
          }
        } catch (SAXException ex) {
          logger.error("Error parsing XHTML", ex);
          entityStream.write(bytes);
          return;
        }
        ResultDocModifier.getInstance().addToDocument(document);
        Transformer transformer;
        try {
          transformer = transformerFactory.newTransformer();
        } catch (TransformerConfigurationException ex) {
          throw new RuntimeException(ex);
        }
        DOMSource source = new DOMSource(document);
        StreamResult result = new StreamResult(entityStream);
        try {
          transformer.setOutputProperty("omit-xml-declaration","yes");
          transformer.transform(source, result);
        } catch (TransformerException ex) {
          throw new RuntimeException(ex);
        }
      } finally {
        ResultDocModifier.dispose();
      }
    }
  }

  private String getRenderingMode() {
    if (uriInfo == null) {
      return null;
    }
    MultivaluedMap<String, String> queryParams = uriInfo.getQueryParameters();
    List<String> modes = queryParams.get(MODE);
    if ((modes == null) || (modes.size() == 0)) {
      return null;
    }
    return modes.get(0);
  }

  protected void bindContextProvider(UserContextProvider provider) {
    contextProviders.add(provider);
  }

  protected void unbindContextProvider(UserContextProvider provider) {
    contextProviders.remove(provider);
  }

  private GraphNode getUserContext() {
    GraphNode contextNode = new GraphNode(new BNode(), new SimpleMGraph());
    synchronized(contextProviders) {
      Iterator<UserContextProvider> providersIter = contextProviders.iterator();
      while (providersIter.hasNext()) {
        UserContextProvider userContextProvider = providersIter.next();
        contextNode = userContextProvider.addUserContext(contextNode);
      }
    }
    return contextNode;
  }
}
TOP

Related Classes of org.apache.clerezza.platform.typerendering.GenericGraphNodeMBW

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.