All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.airlift.rack.RackServlet Maven / Gradle / Ivy

There is a newer version: 0.73
Show newest version
/*
 * Copyright 2010 Proofpoint, Inc.
 *
 * 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 io.airlift.rack;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Resources;
import org.jruby.Ruby;
import org.jruby.RubyHash;
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyObjectAdapter;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;

import javax.inject.Inject;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;

import static org.jruby.javasupport.JavaEmbedUtils.javaToRuby;

public class RackServlet
        implements Servlet
{
    private final IRubyObject rackApplication;
    private final Ruby runtime;
    private final RubyObjectAdapter adapter = JavaEmbedUtils.newObjectAdapter();

    //Servlet config to support the convention of getServletConfig/init
    private ServletConfig servletConfig = null;

    @Inject
    public RackServlet(RackServletConfig config)
            throws IOException
    {
        Preconditions.checkNotNull(config);

        File rackScriptFile = new File(config.getRackConfigPath());

        Preconditions.checkArgument(rackScriptFile.canRead(), "Could not find rack script specified by [" + config.getRackConfigPath()
                + "] and resolved to [" + rackScriptFile.getAbsolutePath() + "]");

        runtime = JavaEmbedUtils.initialize(ImmutableList.of(rackScriptFile.getParentFile().getCanonicalPath()), createRuntimeConfig());

        // don't inherit system settings for gems
        RubyHash env = runtime.evalScriptlet("ENV").convertToHash();
        env.remove("GEM_HOME");
        env.remove("GEM_PATH");

        InputStream stream = Resources.getResource("io/airlift/rack.rb").openStream();
        try {
            runtime.loadFile("rack.rb", stream, false);
        }
        finally {
            stream.close();
        }

        IRubyObject builder = runtime.evalScriptlet("Airlift::RackServer::Builder.new");

        rackApplication = adapter.callMethod(builder, "build", new IRubyObject[] {
                javaToRuby(runtime, rackScriptFile.getCanonicalPath())
        });
    }

    private RubyInstanceConfig createRuntimeConfig()
    {
        RubyInstanceConfig config = new RubyInstanceConfig();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader == null) {
            classLoader = ClassLoader.getSystemClassLoader();
        }
        config.setClassCache(JavaEmbedUtils.createClassCache(classLoader));

        URL resource = RubyInstanceConfig.class.getResource("/META-INF/jruby.home");
        if (resource != null && resource.getProtocol().equals("jar")) {
            try { // http://weblogs.java.net/blog/2007/04/25/how-convert-javaneturl-javaiofile
                config.setJRubyHome(resource.toURI().getSchemeSpecificPart());
            }
            catch (URISyntaxException e) {
                config.setJRubyHome(resource.getPath());
            }
        }

        return config;
    }

    @Override
    public void init(ServletConfig servletConfig)
            throws ServletException
    {
        this.servletConfig = servletConfig;
    }

    @Override
    public void service(ServletRequest request, ServletResponse response)
            throws ServletException, IOException
    {
        Preconditions.checkNotNull(request);
        Preconditions.checkNotNull(response);

        Preconditions.checkArgument((request instanceof HttpServletRequest), "Expected a servlet request that implements HttpServletRequest, this servlet only supports Http(s)");
        Preconditions.checkArgument((response instanceof HttpServletResponse), "Expected a servlet response that implements HttpServletResponse, this servlet only supports Http(s)");

        adapter.callMethod(rackApplication, "call",
                new IRubyObject[] {
                        javaToRuby(runtime, request),
                        javaToRuby(runtime, response)
                });
    }

    @Override
    public ServletConfig getServletConfig()
    {
        return servletConfig;
    }

    @Override
    public String getServletInfo()
    {
        return "RackServlet, a servlet for running rack applications.  Copyright 2010 Proofpoint, Inc.";
    }

    @Override
    public void destroy()
    {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy