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

io.soluble.pjb.bridge.JavaBridgeRunner Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2003-2007 Jost Boekemeier
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

package io.soluble.pjb.bridge;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;

import io.soluble.pjb.bridge.http.ChunkedInputStream;
import io.soluble.pjb.bridge.http.ChunkedOutputStream;
import io.soluble.pjb.bridge.http.ContextFactory;
import io.soluble.pjb.bridge.http.ContextServer;
import io.soluble.pjb.bridge.http.HttpRequest;
import io.soluble.pjb.bridge.http.HttpResponse;
import io.soluble.pjb.bridge.http.HttpServer;
import io.soluble.pjb.bridge.http.RemoteHttpContextFactory;

/**
 * This is the main entry point for the PHP/Java Bridge library.
 * Example:
* public MyClass {
*   public static void main(String s[]) {
*      JavaBridgeRunner runner = JavaBridgeRunner.getInstance();
*      // connect to port 9267 and send protocol requests ...
*     runner.destroy();
*   }
* }
* * @author jostb * @see io.soluble.pjb.script.PhpScriptContext */ public class JavaBridgeRunner extends HttpServer { protected static JavaBridgeRunner runner; protected final ContextServer contextServer; private boolean directoryIndexEnabled = true; protected JavaBridgeRunner(String serverPort, boolean isSecure) throws IOException { super(serverPort, isSecure); contextServer = new ContextServer(ContextFactory.EMPTY_CONTEXT_NAME, Util.JAVABRIDGE_PROMISCUOUS); } protected JavaBridgeRunner(String serverPort) throws IOException { this(serverPort, false); } /** * Create a new JavaBridgeRunner and ContextServer. * * @throws IOException * @see ContextServer */ protected JavaBridgeRunner() throws IOException { this(null); } /** * Return the ContextServer * * @return the ContextServer */ public ContextServer getContextServer() { return contextServer; } /** * Return a instance. * * @param serverPort The server port name * @param isSecure use https instead of http * @return a standalone runner * @throws IOException */ public static synchronized JavaBridgeRunner getRequiredInstance(String serverPort, boolean isSecure) throws IOException { if (runner != null) return runner; runner = new JavaBridgeRunner(serverPort, isSecure); return runner; } /** * Return a instance. * * @param serverPort The server port name * @param isSecure use https instead of http * @return a standalone runner */ public static synchronized JavaBridgeRunner getInstance(String serverPort, boolean isSecure) { if (runner != null) return runner; try { runner = new JavaBridgeRunner(serverPort, isSecure); } catch (IOException e) { Util.printStackTrace(e); } return runner; } /** * Return a instance. * * @param serverPort The server port name * @return a standalone runner * @throws IOException */ public static synchronized JavaBridgeRunner getRequiredInstance(String serverPort) throws IOException { if (runner != null) return runner; runner = new JavaBridgeRunner(serverPort); return runner; } /** * Return a instance. * * @param serverPort The server port name * @return a standalone runner */ public static synchronized JavaBridgeRunner getInstance(String serverPort) { if (runner != null) return runner; try { runner = new JavaBridgeRunner(serverPort); } catch (IOException e) { Util.printStackTrace(e); } return runner; } /** * Return a instance. * * @return a standalone runner * @throws IOException */ public static synchronized JavaBridgeRunner getRequiredInstance() throws IOException { if (runner != null) return runner; runner = new JavaBridgeRunner(); return runner; } /** * Enable listing of directory index, if a directory is served. */ public void enableDirectoryIndex() { directoryIndexEnabled = true; } /** * Disable listing of directory index, if a directory is served. */ public void disableDirectoryIndex() { directoryIndexEnabled = false; } /** * Create a server socket. * * @param addr The host address, either INET:port or INET_LOCAL:port * @return The server socket. * @throws IOException */ @Override public ISocketFactory bind(String addr) throws IOException { socket = JavaBridge.bind(addr); return socket; } /** * Create a server socket. * * @param addr The host address, either INET:port or INET_LOCAL:port * @return The server socket. * @throws IOException */ @Override public ISocketFactory bindSecure(String addr) throws IOException { boolean isLocal = true; if (addr.startsWith("INET_LOCAL:")) { addr = addr.substring(11); } else if (addr.startsWith("INET:")) { isLocal = false; addr = addr.substring(5); } return SSLServerSocketHelper.bind(Integer.parseInt(addr), Util.BACKLOG, isLocal); } private static String getHeader(String key, HttpRequest req) { String val = req.getHeader(key); if (val == null) return null; if (val.length() == 0) val = null; return val; } /** * Handles both, override-redirect and redirect, see * see io.soluble.pjb.servlet.PhpJavaServlet#handleSocketConnection(HttpServletRequest, HttpServletResponse, String, boolean) * see io.soluble.pjb.servlet.PhpJavaServlet#handleRedirectConnection(HttpServletRequest, HttpServletResponse) * @param req * @param res * @throws java.io.IOException */ @Override protected void doPut(HttpRequest req, HttpResponse res) throws IOException { ChunkedInputStream sin; ChunkedOutputStream sout; String transferEncoding = getHeader("Transfer-Encoding", req); boolean isChunked = "chunked".equals(transferEncoding); if (!isChunked) throw new IllegalStateException("Please use a JEE server or servlet engine."); sin = new ChunkedInputStream(req.getInputStream()); sout = new ChunkedOutputStream(res.getOutputStream()); RemoteHttpContextFactory ctx = new RemoteHttpContextFactory(req, res); res.setHeader(Util.X_JAVABRIDGE_CONTEXT, ctx.getId()); res.setHeader("Pragma", "no-cache"); res.setHeader("Keep-Alive", "timeout=-1, max=-1"); try { ctx.getBridge().handleRequests(sin, sout); sin.eof(); sout.eof(); } finally { ctx.destroy(); } } /** * Return the current directory to the browser * * @param fullName The full name of the file * @param f The full name as a file * @param length The length of the file * @param req The HTTP request object * @param res The HTTP response object * @return true if the runner could show the directory, false otherwise * @throws IOException */ protected boolean showDirectory(String fullName, File f, int length, HttpRequest req, HttpResponse res) throws IOException { // assert f.isDirectory() ByteArrayOutputStream xout = new ByteArrayOutputStream(); try (PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(xout, Util.UTF8)))) { out.println(""); out.println(""); out.println("Directory Listing for " + fullName + "/"); out.println(" "); File parentFile = f.getParentFile(); String parentName = parentFile == null ? "/" : parentFile.getName(); out.println("

Directory Listing for " + fullName + " - Up To " + parentName + "


"); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); out.println(""); File[] dir = f.listFiles(); int count = 0; StringBuilder b = new StringBuilder(); for (File file : dir) { if (file.isHidden()) continue; boolean even = count++ % 2 == 0; if (even) out.println(""); else out.println(""); // mozilla replaces everything after the last slash: // foo/bar baz becomes foo/baz and foo/bar/ baz becomes foo/bar/baz if (fullName.length() != 0 && !fullName.endsWith("/")) { b.append(f.getName()); b.append("/"); } b.append(file.getName()); if (file.isDirectory()) b.append("/"); out.println(""); out.println(""); } else { out.println("" + file.getName() + ""); out.println(""); } out.println(""); out.println(""); out.println(""); b.setLength(0); } out.println("
FilenameTypeSizeLast Modified
  "); if (file.isDirectory()) { out.println("" + file.getName() + "/  "); out.println("directory  "); out.println("file" + file.length() + "" + Util.formatDateTime(file.lastModified()) + "
"); out.println("

Simple JSR 223 enabled web server version 0.0.1

"); out.println("

Available script engines

    "); try { Class c = Class.forName("javax.script.ScriptEngineManager"); Object o = c.newInstance(); Method ex = c.getMethod("getEngineByExtension", new Class[]{String.class}); if (ex.invoke(o, (Object[]) new String[]{"php"}) == null) { out.println("Warning: php-script.jar not found. Please copy it to the directory containing JavaBridge.jar before starting JavaBridge.

    "); } Method e = c.getMethod("getEngineFactories", new Class[]{}); List factories = (List) e.invoke(o, new Object[]{}); StringBuffer buf = new StringBuffer(); for (Iterator ii = factories.iterator(); ii.hasNext(); ) { o = ii.next(); Method getName = o.getClass().getMethod("getEngineName", new Class[]{}); Method getVersion = o.getClass().getMethod("getEngineVersion", new Class[]{}); Method getNames = o.getClass().getMethod("getNames", new Class[]{}); Method getExtensions = o.getClass().getMethod("getExtensions", new Class[]{}); buf.append("
  • "); buf.append(getName.invoke(o, new Object[]{})); buf.append(", "); buf.append("ver.: "); buf.append(getVersion.invoke(o, new Object[]{})); buf.append(", "); buf.append("alias: "); buf.append(getNames.invoke(o, new Object[]{})); buf.append(", "); buf.append(".ext: "); buf.append(getExtensions.invoke(o, new Object[]{})); buf.append("
  • "); out.println(buf); buf.setLength(0); } } catch (Exception e) { e.printStackTrace(); } out.println("
"); out.println(""); out.println(""); res.addHeader("Content-Type", "text/html; charset=UTF-8"); res.addHeader("Last-Modified", Util.formatDateTime(f.lastModified())); } int outLength = xout.size(); res.setContentLength(outLength); xout.writeTo(res.getOutputStream()); return true; } /** * Evaluate the script engine. The engine is searched through the discovery mechanism. Add the "php-script.jar" or some other * JSR223 script engine to the java ext dirs (usually /usr/share/java/ext or /usr/java/packages/lib/ext) and start the HTTP server: * java -jar JavaBridge.jar HTTP_LOCAL:8080. Browse to http://localhost:8080/test.php. * * @param name * @param f The full name as a file * @param params The request parameter * @param length The length of the file * @param req The HTTP request object * @param res The HTTP response object * @return true if the runner could evaluate the script, false otherwise. * @throws IOException */ protected boolean handleScriptContent(String name, String params, File f, int length, HttpRequest req, HttpResponse res) throws IOException { return true; } /** * Display a simple text file. * * @param name * @param f The full name as a file * @param params The request parameter * @param length The length of the file * @param req The HTTP request object * @param res The HTTP response object * @param show * @throws IOException */ protected void showTextFile(String name, String params, File f, int length, HttpRequest req, HttpResponse res, boolean show) throws IOException { byte[] buf; OutputStream out; int c; if (Util.logLevel > 4) Util.logDebug("web server: show text file:" + name); res.addHeader("Last-Modified", Util.formatDateTime(f.lastModified())); if (show) res.addHeader("Content-Type", "text/plain"); res.setContentLength(length); try (InputStream in = new FileInputStream(f)) { buf = new byte[Util.BUF_SIZE]; out = res.getOutputStream(); while ((c = in.read(buf)) != -1) out.write(buf, 0, c); } } /** * Handle doGet requests. For example java_require("http://localhost:8080/JavaBridge/java/Java.inc"); *

* Since each script may also consume a HttpServer continuation (PUT ...), there * cannot be more than THREAD_POOL_MAX_SIZE/2 GET requests. * * @param req The HttpRequest * @param res The HttpResponse * @throws java.io.IOException */ @Override protected void doGet(HttpRequest req, HttpResponse res) throws IOException { handleDoGet(req, res); } private byte[] cache; /** * Handle doGet requests. For example java_require("http://localhost:8080/JavaBridge/java/Java.inc"); * * @param req The HttpRequest * @param res The HttpResponse * @throws java.io.IOException */ protected void handleDoGet(HttpRequest req, HttpResponse res) throws IOException { byte[] buf; OutputStream out; int c; String name = req.getRequestURI(); if (name == null) { super.doGet(req, res); return; } if (!name.startsWith("/JavaBridge")) { if (name.startsWith("/")) name = name.substring(1); String params = null; int idx = name.indexOf('?'); if (idx != -1) { params = name.substring(idx + 1); name = name.substring(0, idx); } File f = Standalone.getCanonicalWindowsFile(name); if (f == null || !f.exists()) f = new File(Util.HOME_DIR, name); if (!f.exists()) return; if (f.isHidden()) return; long l = f.length(); if (l >= Integer.MAX_VALUE) throw new IOException("file " + name + " too large"); int length = (int) l; if (f.isDirectory()) { if (directoryIndexEnabled) { showDirectory(name, f, length, req, res); } else { // TODO: What now? 404? 403? setStatus is not implemented in the HttpResponse object // of this internal http server } return; } else { // assert !f.isDirectory() // TODO: Here comes a BUG: handleScriptContent(...) does nothing but return true, // hence showTextFile(...) is never called; will comment it out for now // if (handleScriptContent(name, params, f, length, req, res)) return; showTextFile(name, params, f, length, req, res, (!name.endsWith(".html")) || "show".equals(params)); return; } } if (cache != null && name.endsWith("Java.inc")) { res.setContentLength(cache.length); res.getOutputStream().write(cache); return; } if (Util.JAVA_INC != null && name.endsWith("Java.inc")) { try { Field f = Util.JAVA_INC.getField("bytes"); cache = buf = (byte[]) f.get(Util.JAVA_INC); res.setContentLength(buf.length); out = res.getOutputStream(); out.write(buf); return; } catch (SecurityException e) {/*ignore*/ } catch (IOException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException e) { Util.printStackTrace(e); } } name = name.replaceFirst("/JavaBridge", "META-INF"); InputStream in = JavaBridgeRunner.class.getClassLoader().getResourceAsStream(name); if (in == null) { // Java.inc may not exist in the source download, use JavaBridge.inc instead. name = name.replaceFirst("Java\\.inc", "JavaBridge.inc"); in = JavaBridgeRunner.class.getClassLoader().getResourceAsStream(name); if (in == null) { res.setContentLength(ERROR.length); res.getOutputStream().write(ERROR); return; } else { if (Util.logLevel > 4) Util.logDebug("Java.inc not found, using JavaBridge.inc instead"); } } try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); buf = new byte[Util.BUF_SIZE]; while ((c = in.read(buf)) > 0) bout.write(buf, 0, c); res.addHeader("Last-Modified", "Wed, 17 Jan 2007 19:52:43 GMT"); // bogus res.setContentLength(bout.size()); out = res.getOutputStream(); out.write(bout.toByteArray()); } catch (IOException e) { /* may happen when the client is not interested, see require_once() */ } finally { try { in.close(); } catch (IOException e) {/*ignore*/} } } /** * Wait for the runner to finish * * @throws InterruptedException */ public void waitFor() throws InterruptedException { runner.httpServer.join(); } /** * Destroy the JavaBridgeRunner instance */ public static void destroyRunner() { if (runner != null) runner.destroy(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy