org.callimachusproject.fluid.consumers.HttpJavaScriptResponseWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.callimachusproject.fluid.consumers.HttpJavaScriptResponseWriter.java

Source

/*
 * Copyright (c) 2013 3 Round Stones Inc., Some Rights Reserved
 *
 * 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 org.callimachusproject.fluid.consumers;

import java.io.IOException;
import java.net.URL;
import java.nio.channels.ReadableByteChannel;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.http.HttpResponse;
import org.callimachusproject.fluid.Consumer;
import org.callimachusproject.fluid.Fluid;
import org.callimachusproject.fluid.FluidBuilder;
import org.callimachusproject.fluid.FluidException;
import org.callimachusproject.fluid.FluidType;
import org.callimachusproject.fluid.Vapor;

public class HttpJavaScriptResponseWriter implements Consumer<Object> {
    private static final String BUILD_HTTP_RESPONSE = "buildHttpResponse";
    private static final String SCRIPT = "function " + BUILD_HTTP_RESPONSE + "(resp, systemId){\n"
            + "var contentType = null;\n" + "var charset = 'UTF-8';\n" + "var status = resp.status;\n"
            + "var message = resp.message;\n" + "if (typeof status != 'number') {\n" + "   status = 200;\n" + "}\n"
            + "if (typeof message != 'string') {\n" + "   message = '' + status;\n" + "}\n"
            + "var http11 = org.apache.http.HttpVersion.HTTP_1_1;\n"
            + "var response = new org.apache.http.message.BasicHttpResponse(http11, status, message);\n"
            + "if (typeof resp.headers == 'object') {\n" + "   contentType = resp.headers['content-type'];\n"
            + "   for (var name in resp.headers) {\n" + "      var value = resp.headers[name];\n"
            + "      if (typeof value == 'string') {\n" + "         response.addHeader(name.toString(), value);\n"
            + "      } else if (value && value.length && value.join) {\n"
            + "         response.addHeader(name.toString(), value.join(','));\n" + "      }\n" + "   }\n" + "}\n"
            + "if (contentType && contentType.indexOf('charset=') > 0) {\n"
            + "   charset = new javax.activation.MimeType(contentType).getParameter('charset');\n" + "}\n"
            + "if (typeof resp.body == 'string') {"
            + "   response.setEntity(new org.apache.http.entity.StringEntity(resp.body, contentType, charset));\n"
            + "} else if (resp.body && resp.body.length && resp.body.join) {\n"
            + "   response.setEntity(new org.apache.http.entity.StringEntity(resp.body.join(''), contentType, charset));\n"
            + "} else if (resp.body && typeof resp.body.getClass == 'function' && resp.body.getClass() instanceof java.lang.Class) {\n"
            + "   var factory = org.callimachusproject.fluid.FluidFactory.getInstance();\n"
            + "   var media = contentType ? [contentType] : [];\n"
            + "   var fluid = factory.builder().consume(resp.body, systemId, resp.body.getClass(), media);\n"
            + "   response.setEntity(fluid.asHttpEntity(media));\n" + "}\n" + "return response;\n" + "}\n";
    private final Invocable engine;
    private final HttpMessageWriter delegate;

    public HttpJavaScriptResponseWriter() throws ScriptException {
        String systemId = getSystemId("SCRIPT");
        ScriptEngineManager man = new ScriptEngineManager();
        ScriptEngine engine = man.getEngineByName("rhino");
        engine.put(ScriptEngine.FILENAME, systemId);
        engine.eval(SCRIPT);
        this.engine = (Invocable) engine;
        this.delegate = new HttpMessageWriter();
    }

    @Override
    public boolean isConsumable(FluidType ftype, FluidBuilder builder) {
        return ftype.is(Object.class) && (ftype.is("message/http") || ftype.is("message/x-response"));
    }

    @Override
    public Fluid consume(final Object result, final String base, final FluidType ftype,
            final FluidBuilder builder) {
        return new Vapor() {

            @Override
            public String getSystemId() {
                return base;
            }

            @Override
            public FluidType getFluidType() {
                return ftype;
            }

            @Override
            public void asVoid() throws IOException, FluidException {
                // do nothing
            }

            @Override
            protected String toHttpResponseMedia(FluidType media) {
                return ftype.as(media).preferred();
            }

            @Override
            protected HttpResponse asHttpResponse(FluidType media) throws Exception {
                return (HttpResponse) engine.invokeFunction(BUILD_HTTP_RESPONSE, result, base);
            }

            @Override
            protected String toChannelMedia(FluidType media) {
                return toHttpResponseMedia(media);
            }

            @Override
            protected ReadableByteChannel asChannel(FluidType media) throws Exception {
                return delegate.consume(asHttpResponse(media), base, ftype, builder).asChannel(media.media());
            }
        };
    }

    private String getSystemId(String frag) {
        Class<?> dclass = this.getClass();
        String name = dclass.getSimpleName() + ".class";
        URL url = dclass.getResource(name);
        if (url != null)
            return url.toExternalForm() + "#" + frag;
        return "java:" + dclass.getName() + "#" + frag;
    }

}