<commit_before>package com.bkahlert.nebula.widgets.browser.runner;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;

import com.bkahlert.nebula.utils.CompletedFuture;
import com.bkahlert.nebula.utils.ExecUtils;
import com.bkahlert.nebula.utils.IConverter;
import com.bkahlert.nebula.utils.OffWorker;
import com.bkahlert.nebula.utils.StringUtils;
import com.bkahlert.nebula.widgets.browser.BrowserUtils;
import com.bkahlert.nebula.widgets.browser.exception.BrowserTimeoutException;
import com.bkahlert.nebula.widgets.browser.exception.BrowserUninitializedException;
import com.bkahlert.nebula.widgets.browser.exception.JavaScriptException;
import com.bkahlert.nebula.widgets.browser.exception.ScriptExecutionException;
import com.bkahlert.nebula.widgets.browser.exception.UnexpectedBrowserStateException;

/**
 * This is the default implementation of {@link IBrowserScriptRunner}.
 * 
 * @author bkahlert
 * 
 */
public class BrowserScriptRunner implements IBrowserScriptRunner {

	/**
	 * Relevant statuses a browser can have in terms of script execution.
	 * 
	 * @author bkahlert
	 * 
	 */
	public static enum BrowserStatus {
		/**
		 * The browser is initializing, meaning no resource had been loaded,
		 * yet.
		 */
		INITIALIZING,

		/**
		 * The browser is currently loading a resource.
		 */
		LOADING,

		/**
		 * The browser has successfully loaded a resource.
		 */
		LOADED,

		/**
		 * The browser timed out.
		 */
		TIMEDOUT,

		/**
		 * The browser is currently disposing or already disposed.
		 */
		DISPOSED
	}

	/**
	 * Instances of this class can handle asynchronous
	 * {@link JavaScriptException}s, that are exceptions raised by the
	 * {@link Browser} itself and not provoked by Java invocations.
	 * 
	 * @author bkahlert
	 * 
	 */
	public static interface JavaScriptExceptionListener {
		public void thrown(JavaScriptException javaScriptException);
	}

	private static final Logger LOGGER = Logger
			.getLogger(BrowserScriptRunner.class);

	private static <DEST> Callable<DEST> createScriptRunner(
			final BrowserScriptRunner browserScriptRunner, final String script,
			final IConverter<Object, DEST> converter) {
		final String label = StringUtils.shorten(script);
		return ExecUtils.createThreadLabelingCode(new Callable<DEST>() {
			@Override
			public DEST call() throws Exception {
				if (browserScriptRunner.browser == null
						|| browserScriptRunner.browser.isDisposed()) {
					return null;
				}
				LOGGER.info("Running " + label);
				try {
					browserScriptRunner.scriptAboutToBeSentToBrowser(script);
					Object returnValue = browserScriptRunner.browser
							.evaluate(BrowserUtils
									.getExecutionReturningScript(script));

					BrowserUtils.assertException(script, returnValue);

					browserScriptRunner.scriptReturnValueReceived(returnValue);
					DEST rs = converter.convert(returnValue);
					LOGGER.info("Returned " + rs);
					return rs;
				} catch (SWTException e) {
					throw e;
				} catch (JavaScriptException e) {
					LOGGER.error(e);
					throw e;
				} catch (Exception e) {
					LOGGER.error(e);<commit_msg>[FIX] When a scripts runs at a moment the browser was already disposed null was returned. Now a ScriptExecutionException is thrown.<commit_after>package com.bkahlert.nebula.widgets.browser.runner;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;

import com.bkahlert.nebula.utils.CompletedFuture;
import com.bkahlert.nebula.utils.ExecUtils;
import com.bkahlert.nebula.utils.IConverter;
import com.bkahlert.nebula.utils.OffWorker;
import com.bkahlert.nebula.utils.StringUtils;
import com.bkahlert.nebula.widgets.browser.BrowserUtils;
import com.bkahlert.nebula.widgets.browser.exception.BrowserTimeoutException;
import com.bkahlert.nebula.widgets.browser.exception.BrowserUninitializedException;
import com.bkahlert.nebula.widgets.browser.exception.JavaScriptException;
import com.bkahlert.nebula.widgets.browser.exception.ScriptExecutionException;
import com.bkahlert.nebula.widgets.browser.exception.UnexpectedBrowserStateException;

/**
 * This is the default implementation of {@link IBrowserScriptRunner}.
 * 
 * @author bkahlert
 * 
 */
public class BrowserScriptRunner implements IBrowserScriptRunner {

	/**
	 * Relevant statuses a browser can have in terms of script execution.
	 * 
	 * @author bkahlert
	 * 
	 */
	public static enum BrowserStatus {
		/**
		 * The browser is initializing, meaning no resource had been loaded,
		 * yet.
		 */
		INITIALIZING,

		/**
		 * The browser is currently loading a resource.
		 */
		LOADING,

		/**
		 * The browser has successfully loaded a resource.
		 */
		LOADED,

		/**
		 * The browser timed out.
		 */
		TIMEDOUT,

		/**
		 * The browser is currently disposing or already disposed.
		 */
		DISPOSED
	}

	/**
	 * Instances of this class can handle asynchronous
	 * {@link JavaScriptException}s, that are exceptions raised by the
	 * {@link Browser} itself and not provoked by Java invocations.
	 * 
	 * @author bkahlert
	 * 
	 */
	public static interface JavaScriptExceptionListener {
		public void thrown(JavaScriptException javaScriptException);
	}

	private static final Logger LOGGER = Logger
			.getLogger(BrowserScriptRunner.class);

	private static <DEST> Callable<DEST> createScriptRunner(
			final BrowserScriptRunner browserScriptRunner, final String script,
			final IConverter<Object, DEST> converter) {
		final String label = StringUtils.shorten(script);
		return ExecUtils.createThreadLabelingCode(new Callable<DEST>() {
			@Override
			public DEST call() throws Exception {
				if (browserScriptRunner.browser == null
						|| browserScriptRunner.browser.isDisposed()) {
					throw new ScriptExecutionException(script,
							new SWTException(SWT.ERROR_WIDGET_DISPOSED));
				}
				LOGGER.info("Running " + label);
				try {
					browserScriptRunner.scriptAboutToBeSentToBrowser(script);
					Object returnValue = browserScriptRunner.browser
							.evaluate(BrowserUtils
									.getExecutionReturningScript(script));

					BrowserUtils.assertException(script, returnValue);

					browserScriptRunner.scriptReturnValueReceived(returnValue);
					DEST rs = converter.convert(returnValue);
					LOGGER.info("Returned " + rs);
					return rs;
				} catch (SWTException e) {
					throw e;
				} catch (JavaScriptException e) {
					LOGGER.error(e);
					throw e;
				} catch (Exception e) {
					LOGGER.error(e);
{'fraction_non_alphanumeric': 0.09536529985307866, 'fraction_numerical': 0.00026712969146520634, 'mean_word_length': 4.236363636363636, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '419950', 'n_tokens_mistral': 2541, 'n_tokens_neox': 2127, 'n_words': 504}