jaroslav@370: /** jaroslav@370: * Back 2 Browser Bytecode Translator jaroslav@370: * Copyright (C) 2012 Jaroslav Tulach jaroslav@370: * jaroslav@370: * This program is free software: you can redistribute it and/or modify jaroslav@370: * it under the terms of the GNU General Public License as published by jaroslav@370: * the Free Software Foundation, version 2 of the License. jaroslav@370: * jaroslav@370: * This program is distributed in the hope that it will be useful, jaroslav@370: * but WITHOUT ANY WARRANTY; without even the implied warranty of jaroslav@370: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the jaroslav@370: * GNU General Public License for more details. jaroslav@370: * jaroslav@370: * You should have received a copy of the GNU General Public License jaroslav@370: * along with this program. Look for COPYING file in the top folder. jaroslav@370: * If not, see http://opensource.org/licenses/GPL-2.0. jaroslav@370: */ jaroslav@370: package org.apidesign.bck2brwsr.launcher; jaroslav@370: jaroslav@622: import java.io.IOException; jaroslav@626: import java.io.InputStream; jaroslav@1186: import java.net.URI; jaroslav@667: import java.util.ArrayList; jaroslav@667: import java.util.List; jaroslav@371: import java.util.concurrent.CountDownLatch; jaroslav@371: import java.util.concurrent.TimeUnit; jaroslav@371: jaroslav@622: /** Represents individual method invocation, its context and its result. jaroslav@370: * jaroslav@370: * @author Jaroslav Tulach jaroslav@370: */ jaroslav@622: public final class InvocationContext { jaroslav@371: final CountDownLatch wait = new CountDownLatch(1); jaroslav@622: final Class clazz; jaroslav@370: final String methodName; jaroslav@622: private final Launcher launcher; jaroslav@371: private String result; jaroslav@385: private Throwable exception; jaroslav@622: String html; jaroslav@667: final List resources = new ArrayList<>(); jaroslav@370: jaroslav@622: InvocationContext(Launcher launcher, Class clazz, String methodName) { jaroslav@622: this.launcher = launcher; jaroslav@622: this.clazz = clazz; jaroslav@370: this.methodName = methodName; jaroslav@622: } jaroslav@622: jaroslav@622: /** An HTML fragment to be available for the execution. Useful primarily when jaroslav@622: * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}. jaroslav@622: * @param html the html fragment jaroslav@622: */ jaroslav@622: public void setHtmlFragment(String html) { jaroslav@526: this.html = html; jaroslav@370: } jaroslav@371: jaroslav@622: /** HTTP resource to be available during execution. An invocation may jaroslav@622: * perform an HTTP query and obtain a resource relative to the page. jaroslav@622: */ jaroslav@954: public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) { jaroslav@954: if (relativePath == null || mimeType == null || content == null || parameters == null) { jaroslav@623: throw new NullPointerException(); jaroslav@623: } jaroslav@954: resources.add(new Resource(content, mimeType, relativePath, parameters)); jaroslav@622: } jaroslav@622: jaroslav@622: /** Invokes the associated method. jaroslav@622: * @return the textual result of the invocation jaroslav@622: */ jaroslav@622: public String invoke() throws IOException { jaroslav@622: launcher.runMethod(this); jaroslav@622: return toString(); jaroslav@622: } jaroslav@622: jaroslav@622: /** Obtains textual result of the invocation. jaroslav@622: * @return text representing the exception or result value jaroslav@622: */ jaroslav@622: @Override jaroslav@622: public String toString() { jaroslav@622: if (exception != null) { jaroslav@622: return exception.toString(); jaroslav@622: } jaroslav@622: return result; jaroslav@622: } jaroslav@622: jaroslav@622: /** jaroslav@622: * @param timeOut jaroslav@622: * @throws InterruptedException jaroslav@622: */ jaroslav@371: void await(long timeOut) throws InterruptedException { jaroslav@371: wait.await(timeOut, TimeUnit.MILLISECONDS); jaroslav@371: } jaroslav@371: jaroslav@385: void result(String r, Throwable e) { jaroslav@371: this.result = r; jaroslav@371: this.exception = e; jaroslav@371: wait.countDown(); jaroslav@371: } jaroslav@370: jaroslav@1186: private static RegisterResource RR; jaroslav@1186: static void register(RegisterResource rr) { jaroslav@1186: RR = rr; jaroslav@1186: } jaroslav@1186: /** A running {@link InvocationContext test} can register additional jaroslav@1186: * resources to the associated browser (if any). jaroslav@1186: * jaroslav@1186: * @param content the stream to deliver content from jaroslav@1186: * @param mimeType mime type for the HTTP reply jaroslav@1186: * @param path suggested path in the server to use jaroslav@1186: * @param parameters additional parameters jaroslav@1186: * @return the URI the resource is made available at jaroslav@1186: * @throws NullPointerException if there is no {@link InvocationContext test} jaroslav@1186: * currently running jaroslav@1186: * @since 0.8 jaroslav@1186: */ jaroslav@1186: public static URI register( jaroslav@1186: InputStream content, String mimeType, String path, String[] parameters jaroslav@1186: ) { jaroslav@1186: final Resource r = new Resource(content, mimeType, path, parameters); jaroslav@1186: return RR.registerResource(r); jaroslav@1186: } jaroslav@1186: static interface RegisterResource { jaroslav@1186: public URI registerResource(Resource r); jaroslav@1186: } jaroslav@667: jaroslav@667: static final class Resource { jaroslav@667: final InputStream httpContent; jaroslav@667: final String httpType; jaroslav@667: final String httpPath; jaroslav@954: final String[] parameters; jaroslav@667: jaroslav@954: Resource(InputStream httpContent, String httpType, String httpPath, jaroslav@954: String[] parameters jaroslav@954: ) { jaroslav@946: httpContent.mark(Integer.MAX_VALUE); jaroslav@667: this.httpContent = httpContent; jaroslav@667: this.httpType = httpType; jaroslav@667: this.httpPath = httpPath; jaroslav@954: this.parameters = parameters; jaroslav@667: } jaroslav@667: } jaroslav@370: }