/etlunit-execute/src/main/java/org/bitbucket/bradleysmithllc/etlunit/feature/execute/JavaExecutor.java
Java | 221 lines | 154 code | 42 blank | 25 comment | 23 complexity | bcc0ba67d904bd5d44b4c6bdb1db7dee MD5 | raw file
- package org.bitbucket.bradleysmithllc.etlunit.feature.execute;
- /*
- * #%L
- * etlunit-execute
- * %%
- * Copyright (C) 2010 - 2014 bradleysmithllc
- * %%
- * 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.
- * #L%
- */
- import org.bitbucket.bradleysmithllc.etlunit.*;
- import org.bitbucket.bradleysmithllc.etlunit.context.VariableContext;
- import org.bitbucket.bradleysmithllc.etlunit.feature.execute.json.java_executor.execute.ExecuteHandler;
- import org.bitbucket.bradleysmithllc.etlunit.feature.execute.json.java_executor.execute.ExecuteRequest;
- import org.bitbucket.bradleysmithllc.etlunit.feature.execute.json.java_executor.execute.SystemProperties;
- import org.bitbucket.bradleysmithllc.etlunit.feature.logging.LogFileManager;
- import org.bitbucket.bradleysmithllc.etlunit.io.JavaForker;
- import org.bitbucket.bradleysmithllc.etlunit.listener.NullClassListener;
- import org.bitbucket.bradleysmithllc.etlunit.metadata.MetaDataArtifact;
- import org.bitbucket.bradleysmithllc.etlunit.metadata.MetaDataContext;
- import org.bitbucket.bradleysmithllc.etlunit.metadata.MetaDataManager;
- import org.bitbucket.bradleysmithllc.etlunit.metadata.MetaDataPackageContext;
- import org.bitbucket.bradleysmithllc.etlunit.parser.ETLTestMethod;
- import org.bitbucket.bradleysmithllc.etlunit.parser.ETLTestOperation;
- import org.bitbucket.bradleysmithllc.etlunit.parser.ETLTestValueObject;
- import org.codehaus.plexus.util.FileUtils;
- import org.codehaus.plexus.util.io.InputStreamFacade;
- import javax.inject.Inject;
- import java.io.File;
- import java.io.IOException;
- import java.io.InputStream;
- import java.lang.reflect.Method;
- import java.lang.reflect.Modifier;
- import java.util.List;
- import java.util.Map;
- import java.util.regex.Pattern;
- public class JavaExecutor extends NullClassListener implements ExecuteHandler {
- private RuntimeSupport runtimeSupport;
- private LogFileManager logFileManager;
- private MetaDataManager metaDataManager;
- private MetaDataContext javaMetaContext;
- @Inject
- public void receiveRuntimeSupport(RuntimeSupport support) {
- runtimeSupport = support;
- }
- @Inject
- public void receiveLogFileManager(LogFileManager manager) {
- logFileManager = manager;
- }
- @Inject
- public void receiveMetaDataManager(MetaDataManager manager)
- {
- metaDataManager = manager;
- javaMetaContext = metaDataManager.getMetaData().getOrCreateContext("java");
- }
- @Override
- public action_code execute(ExecuteRequest request, ETLTestMethod mt, ETLTestOperation testOperation, ETLTestValueObject valueObject, VariableContext variableContext, ExecutionContext executionContext)
- throws TestAssertionFailure, TestExecutionError, TestWarning {
- String className = request.getJavaClass();
- try {
- Class cl = Thread.currentThread().getContextClassLoader().loadClass(className);
- MetaDataPackageContext pc = javaMetaContext.createPackageContextForCurrentTest(MetaDataPackageContext.path_type.external_source);
- MetaDataArtifact art = pc.createArtifact("java-classpath", runtimeSupport.getTempDirectory());
- art.createContent(className).referencedByCurrentTest("java-main-class");
- Method mth = cl.getDeclaredMethod("main", new Class[]{String[].class});
- int mods = mth.getModifiers();
- if (!Modifier.isPublic(mods)) {
- throw new TestExecutionError("Java class has main method, but it isn't public: " + mth, ExecuteConstants.ERR_JAVA_MAIN_NOT_PUBLIC);
- }
- if (!Modifier.isStatic(mods)) {
- throw new TestExecutionError("Java class has public main method, but it isn't static: " + mth, ExecuteConstants.ERR_JAVA_MAIN_NOT_STATIC);
- }
- List<String> requestArguments = request.getArguments();
- String[] args;
- JavaForker javaForker = new JavaForker(runtimeSupport);
- // use the temp folder as the working dir
- javaForker.setWorkingDirectory(runtimeSupport.getTempDirectory());
- javaForker.setMainClassName(className);
- // set a debug token in the system properties to identify this test
- javaForker.addSystemProperty("etlunit.active", "true");
- javaForker.addSystemProperty("etlunit.test.class", testOperation.getTestClass().getQualifiedName());
- javaForker.addSystemProperty("etlunit.test.method", testOperation.getTestMethod().getName());
- javaForker.addSystemProperty("etlunit.test.method.qualified", testOperation.getTestMethod().getQualifiedName());
- javaForker.addSystemProperty("etlunit.test.operation", testOperation.getOperationName());
- javaForker.addSystemProperty("etlunit.test.operation.ordinal", String.valueOf(testOperation.getOrdinal()));
- javaForker.addSystemProperty("etlunit.test.operation.qualified", testOperation.getQualifiedName());
- // adjust the classpath if running in maven
- String property = System.getProperty("etlunit.maven.plugin.classpath");
- if (property != null) {
- String[] pathElements = property.split(Pattern.quote(File.pathSeparator));
- for (String pathElement : pathElements) {
- javaForker.addClasspathEntry(new File(pathElement));
- }
- }
- if (requestArguments != null && requestArguments.size() != 0) {
- args = new String[requestArguments.size()];
- for (int i = 0; i < args.length; i++) {
- String argument = requestArguments.get(i);
- // wrap with velocity
- javaForker.addArgument(variableContext.contextualize(argument));
- args[i] = argument;
- }
- }
- SystemProperties properties = request.getSystemProperties();
- if (properties != null) {
- Map<String, String> additionalProperties = properties.getAdditionalProperties();
- if (additionalProperties != null) {
- for (Map.Entry<String, String> addProperty : additionalProperties.entrySet()) {
- javaForker.addSystemProperty(
- addProperty.getKey(),
- variableContext.contextualize(addProperty.getValue())
- );
- }
- }
- }
- String runId = className + "_" + testOperation.getQualifiedName();
- if (request.getRunId() != null) {
- runId = request.getRunId();
- }
- final ProcessFacade proc = javaForker.startProcess();
- proc.waitForCompletion();
- // make sure the stream threads get caught up
- proc.waitForOutputStreamsToComplete();
- File out = runtimeSupport.createGeneratedSourceFile("java-executor", runId + ".out");
- // stream the standard out and standard err into the logs
- FileUtils.copyStreamToFile(new InputStreamFacade() {
- @Override
- public InputStream getInputStream() throws IOException {
- return proc.getInputStream();
- }
- }, out);
- File err = runtimeSupport.createGeneratedSourceFile("java-executor", runId + ".err");
- FileUtils.copyStreamToFile(new InputStreamFacade() {
- @Override
- public InputStream getInputStream() throws IOException {
- return proc.getErrorStream();
- }
- }, err);
- if (mt != null)
- {
- logFileManager.addLogFile(mt, testOperation, out, "standard-out");
- logFileManager.addLogFile(mt, testOperation, err, "standard-err");
- }
- else
- {
- logFileManager.addLogFile(testOperation, out, "standard-out");
- logFileManager.addLogFile(testOperation, err, "standard-err");
- }
- if (request.getExitCode() != null) {
- int ret = proc.getCompletionCode();
- int exp = request.getExitCode().intValue();
- if (ret != exp) {
- throw new TestExecutionError("Unexpected process exit code. [" + exp + "] expected, [" + ret + "] observed.", ExecuteConstants.ERR_JAVA_EXECUTION_ERROR_BAD_RETURN_CODE);
- }
- }
- } catch (ClassNotFoundException e) {
- throw new TestExecutionError("Java class not found: " + className, ExecuteConstants.ERR_JAVA_CLASS_NOT_FOUND, e);
- } catch (NoSuchMethodException e) {
- throw new TestExecutionError("Java class found, but it does not have a main method: " + className, ExecuteConstants.ERR_JAVA_MAIN_METHOD_NOT_FOUND, e);
- } catch (IOException e) {
- throw new TestExecutionError("Java execution failure: " + className, ExecuteConstants.ERR_JAVA_EXECUTION_ERROR, e);
- } catch (TestExecutionError e) {
- throw e;
- } catch (Exception e) {
- throw new TestExecutionError("Java execution prepare failure: " + className, ExecuteConstants.ERR_JAVA_EXECUTION_ERROR, e);
- }
- return action_code.handled;
- }
- }