From dfac3414a612edd63eaaf8568ddc80271707af22 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 13 Mar 2020 09:56:31 +0100 Subject: [PATCH] Continue to remove dependencies with Spring. --- .../slc/execution/ExecutionResources.java | 46 ++ org.argeo.slc.client.ui.dist/pom.xml | 5 + org.argeo.slc.factory/pom.xml | 5 + .../slc/rpmfactory/core/BuildInMock.java | 2 +- .../core/CreateRpmDistribution.java | 2 +- .../slc/rpmfactory/core/ReleaseStaging.java | 2 +- .../slc/rpmfactory/core/RpmFactoryImpl.java | 2 +- org.argeo.slc.repo/pom.xml | 5 - .../internal/springutil/AntPathMatcher.java | 424 ++++++++++ .../repo/internal/springutil/PathMatcher.java | 91 +++ .../argeo/slc/repo/osgi/ArchiveWrapper.java | 4 +- .../org/argeo/slc/repo/osgi/BndWrapper.java | 12 +- .../slc/runtime/tasks/CloseTestResult.java | 31 + .../src/org/argeo/slc/runtime/tasks/Echo.java | 62 ++ .../src/org/argeo/slc/runtime/tasks/If.java | 64 ++ .../argeo/slc/runtime/tasks/JvmProcess.java | 245 ++++++ .../argeo/slc/runtime/tasks/SystemCall.java | 761 ++++++++++++++++++ .../tasks/SystemCallOutputListener.java | 20 + .../slc/runtime}/test/BasicTestData.java | 2 +- .../runtime}/test/BasicTestDefinition.java | 3 +- .../argeo/slc/runtime/test}/ContextUtils.java | 3 +- .../slc/runtime}/test/SimpleResultPart.java | 2 +- .../slc/runtime}/test/SimpleTestResult.java | 2 +- .../slc/runtime}/test/SimpleTestRun.java | 2 +- .../argeo/slc/runtime}/test/SlcTestUtils.java | 2 +- .../slc/runtime}/test/TestDataUtils.java | 2 +- org.argeo.slc.spring/bnd.bnd | 1 + .../AbstractExecutionFlowTestCase.java | 2 +- .../execution/BasicExecutionFlowTest.java | 2 +- .../slc/core/execution/ParameterRefTest.java | 2 +- .../argeo/slc/core/execution/listSetMap.xml | 24 +- .../core/execution/listSetMapMultipleFlow.xml | 24 +- .../argeo/slc/core/execution/multipleFlow.xml | 8 +- .../argeo/slc/core/execution/parameterRef.xml | 14 +- .../execution/placeHolders.cascading.exec.xml | 50 +- .../core/execution/placeHolders.cascading.xml | 34 +- .../slc/core/execution/specOverriding.xml | 14 +- .../org/argeo/slc/core/execution/test.xml | 10 +- .../core/execution/xml/FlowNamespaceTest.java | 2 +- .../argeo/slc/core/execution/xml/advanced.xml | 8 +- .../slc/core/execution/xml/canonic-ns-002.xml | 2 +- .../slc/core/execution/xml/canonic-ns.xml | 12 +- .../slc/core/execution/xml/containers.xml | 8 +- .../argeo/slc/core/execution/xml/tests.xml | 4 +- .../slc/core/test/context/ContextTest.java | 3 +- org.argeo.slc.spring/pom.xml | 5 + .../slc/core/execution/tasks/SystemCall.java | 2 +- .../test/context/DefaultContextTestData.java | 2 +- .../core/test/context/SimpleContextAware.java | 1 + .../context/SimpleParentContextAware.java | 1 + .../slc/spring/repo/osgi/BndWrapper.java | 20 + .../slc/spring/repo/osgi/MavenWrapper.java | 20 + .../slc/spring/repo/osgi/UriWrapper.java | 20 + .../ExecutionFlowDescriptorTestUtils.java | 2 +- 54 files changed, 1952 insertions(+), 146 deletions(-) create mode 100644 org.argeo.slc.api/src/org/argeo/slc/execution/ExecutionResources.java create mode 100644 org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/AntPathMatcher.java create mode 100644 org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/PathMatcher.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/CloseTestResult.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/Echo.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/If.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/JvmProcess.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCall.java create mode 100644 org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCallOutputListener.java rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/BasicTestData.java (92%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/BasicTestDefinition.java (93%) rename {org.argeo.slc.spring/src/org/argeo/slc/core/test/context => org.argeo.slc.runtime/src/org/argeo/slc/runtime/test}/ContextUtils.java (95%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/SimpleResultPart.java (94%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/SimpleTestResult.java (94%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/SimpleTestRun.java (95%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/SlcTestUtils.java (97%) rename {org.argeo.slc.spring/src/org/argeo/slc/core => org.argeo.slc.runtime/src/org/argeo/slc/runtime}/test/TestDataUtils.java (95%) create mode 100644 org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/BndWrapper.java create mode 100644 org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/MavenWrapper.java create mode 100644 org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/UriWrapper.java diff --git a/org.argeo.slc.api/src/org/argeo/slc/execution/ExecutionResources.java b/org.argeo.slc.api/src/org/argeo/slc/execution/ExecutionResources.java new file mode 100644 index 000000000..ea93d0589 --- /dev/null +++ b/org.argeo.slc.api/src/org/argeo/slc/execution/ExecutionResources.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.execution; + +import java.io.File; +import java.nio.file.Path; + +/** Provides write access to resources during execution */ +public interface ExecutionResources { + /** The base directory where this execution can write */ + public File getWritableBaseDir(); + + /** Allocates a local file in the writable area and return it as a resource. */ + public Path getWritableResource(String relativePath); + + /** + * Allocates a local file in the writable area and return it as a fully + * qualified OS path. + */ + public String getWritableOsPath(String relativePath); + + /** + * Allocates a local file in the writable area and return it as a {@link File}. + */ + public File getWritableOsFile(String relativePath); + + /** + * Returns the resource as a file path. If the resource is not writable it is + * copied as a file in the writable area and the path to this local file is + * returned. + */ + public String getAsOsPath(Path resource, Boolean overwrite); +} diff --git a/org.argeo.slc.client.ui.dist/pom.xml b/org.argeo.slc.client.ui.dist/pom.xml index 369f41c7a..cbed736bf 100644 --- a/org.argeo.slc.client.ui.dist/pom.xml +++ b/org.argeo.slc.client.ui.dist/pom.xml @@ -37,6 +37,11 @@ org.argeo.slc.repo 2.1.17-SNAPSHOT + + org.argeo.slc + org.argeo.slc.spring + 2.1.17-SNAPSHOT + org.argeo.slc org.argeo.slc.server.repo diff --git a/org.argeo.slc.factory/pom.xml b/org.argeo.slc.factory/pom.xml index 19e7dfdcd..3ff0ddfee 100644 --- a/org.argeo.slc.factory/pom.xml +++ b/org.argeo.slc.factory/pom.xml @@ -10,6 +10,11 @@ SLC Factory + + org.argeo.slc + org.argeo.slc.runtime + 2.1.17-SNAPSHOT + org.argeo.slc org.argeo.slc.repo diff --git a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/BuildInMock.java b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/BuildInMock.java index 1f815eac5..18ea0c183 100644 --- a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/BuildInMock.java +++ b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/BuildInMock.java @@ -28,8 +28,8 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.tasks.SystemCall; import org.argeo.slc.rpmfactory.RpmFactory; +import org.argeo.slc.runtime.tasks.SystemCall; /** Build an RPM in mock. */ public class BuildInMock implements Runnable { diff --git a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/CreateRpmDistribution.java b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/CreateRpmDistribution.java index 9fd4993cf..6f60b3d94 100644 --- a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/CreateRpmDistribution.java +++ b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/CreateRpmDistribution.java @@ -15,8 +15,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.tasks.SystemCall; import org.argeo.slc.rpmfactory.RpmFactory; +import org.argeo.slc.runtime.tasks.SystemCall; /** * Gather RPMs from various sources (local builds or third party) into a diff --git a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/ReleaseStaging.java b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/ReleaseStaging.java index 76a67005a..dcdbc9cdc 100644 --- a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/ReleaseStaging.java +++ b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/ReleaseStaging.java @@ -10,8 +10,8 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.tasks.SystemCall; import org.argeo.slc.rpmfactory.RpmFactory; +import org.argeo.slc.runtime.tasks.SystemCall; /** Releases the content of staging to a public repository. */ public class ReleaseStaging implements Runnable { diff --git a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java index 4d5df3bd4..b009551d2 100644 --- a/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java +++ b/org.argeo.slc.factory/src/org/argeo/slc/rpmfactory/core/RpmFactoryImpl.java @@ -37,11 +37,11 @@ import org.apache.commons.logging.LogFactory; import org.argeo.jcr.JcrUtils; import org.argeo.slc.SlcConstants; import org.argeo.slc.SlcException; -import org.argeo.slc.core.execution.tasks.SystemCall; import org.argeo.slc.repo.NodeIndexerVisitor; import org.argeo.slc.repo.RpmIndexer; import org.argeo.slc.rpmfactory.RpmFactory; import org.argeo.slc.rpmfactory.RpmRepository; +import org.argeo.slc.runtime.tasks.SystemCall; /** * Defines a build environment. This information is typically used by other diff --git a/org.argeo.slc.repo/pom.xml b/org.argeo.slc.repo/pom.xml index 759c61189..2c91a9aeb 100644 --- a/org.argeo.slc.repo/pom.xml +++ b/org.argeo.slc.repo/pom.xml @@ -17,11 +17,6 @@ org.argeo.slc.api 2.1.17-SNAPSHOT - - org.argeo.slc - org.argeo.slc.spring - 2.1.17-SNAPSHOT - diff --git a/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/AntPathMatcher.java b/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/AntPathMatcher.java new file mode 100644 index 000000000..20becbcb0 --- /dev/null +++ b/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/AntPathMatcher.java @@ -0,0 +1,424 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.argeo.slc.repo.internal.springutil; + +/** + * PathMatcher implementation for Ant-style path patterns. Examples are provided + * below. + * + *

+ * Part of this mapping code has been kindly borrowed from + * Apache Ant. + * + *

+ * The mapping matches URLs using the following rules:
+ *

    + *
  • ? matches one character
  • + *
  • * matches zero or more characters
  • + *
  • ** matches zero or more 'directories' in a path
  • + *
+ * + *

+ * Some examples:
+ *

    + *
  • com/t?st.jsp - matches com/test.jsp but also + * com/tast.jsp or com/txst.jsp
  • + *
  • com/*.jsp - matches all .jsp files in the + * com directory
  • + *
  • com/**/test.jsp - matches all test.jsp + * files underneath the com path
  • + *
  • org/springframework/**/*.jsp - matches all + * .jsp files underneath the org/springframework + * path
  • + *
  • org/**/servlet/bla.jsp - matches + * org/springframework/servlet/bla.jsp but also + * org/springframework/testing/servlet/bla.jsp and + * org/servlet/bla.jsp
  • + *
+ * + * @author Alef Arendsen + * @author Juergen Hoeller + * @author Rob Harrop + * @since 16.07.2003 + */ +public class AntPathMatcher implements PathMatcher { + + /** Default path separator: "/" */ + public static final String DEFAULT_PATH_SEPARATOR = "/"; + + private String pathSeparator = DEFAULT_PATH_SEPARATOR; + + /** + * Set the path separator to use for pattern parsing. Default is "/", as in Ant. + */ + public void setPathSeparator(String pathSeparator) { + this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR); + } + + public boolean isPattern(String path) { + return (path.indexOf('*') != -1 || path.indexOf('?') != -1); + } + + public boolean match(String pattern, String path) { + return doMatch(pattern, path, true); + } + + public boolean matchStart(String pattern, String path) { + return doMatch(pattern, path, false); + } + + /** + * Actually match the given path against the given + * pattern. + * + * @param pattern the pattern to match against + * @param path the path String to test + * @param fullMatch whether a full pattern match is required (else a pattern + * match as far as the given base path goes is sufficient) + * @return true if the supplied path matched, + * false if it didn't + */ + protected boolean doMatch(String pattern, String path, boolean fullMatch) { + if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) { + return false; + } + +// String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); +// String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + // mbaudier - 2020-03-13 : Use standard Java call: + String[] pattDirs = pattern.split(this.pathSeparator); + String[] pathDirs = path.split(this.pathSeparator); + + int pattIdxStart = 0; + int pattIdxEnd = pattDirs.length - 1; + int pathIdxStart = 0; + int pathIdxEnd = pathDirs.length - 1; + + // Match all elements up to the first ** + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxStart]; + if ("**".equals(patDir)) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxStart])) { + return false; + } + pattIdxStart++; + pathIdxStart++; + } + + if (pathIdxStart > pathIdxEnd) { + // Path is exhausted, only match if rest of pattern is * or **'s + if (pattIdxStart > pattIdxEnd) { + return (pattern.endsWith(this.pathSeparator) ? path.endsWith(this.pathSeparator) + : !path.endsWith(this.pathSeparator)); + } + if (!fullMatch) { + return true; + } + if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") && path.endsWith(this.pathSeparator)) { + return true; + } + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } else if (pattIdxStart > pattIdxEnd) { + // String not exhausted, but pattern is. Failure. + return false; + } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) { + // Path start definitely matches due to "**" part in pattern. + return true; + } + + // up to last '**' + while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) { + String patDir = pattDirs[pattIdxEnd]; + if (patDir.equals("**")) { + break; + } + if (!matchStrings(patDir, pathDirs[pathIdxEnd])) { + return false; + } + pattIdxEnd--; + pathIdxEnd--; + } + if (pathIdxStart > pathIdxEnd) { + // String is exhausted + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + return true; + } + + while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) { + int patIdxTmp = -1; + for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) { + if (pattDirs[i].equals("**")) { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == pattIdxStart + 1) { + // '**/**' situation, so skip one + pattIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - pattIdxStart - 1); + int strLength = (pathIdxEnd - pathIdxStart + 1); + int foundIdx = -1; + + strLoop: for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + String subPat = (String) pattDirs[pattIdxStart + j + 1]; + String subStr = (String) pathDirs[pathIdxStart + i + j]; + if (!matchStrings(subPat, subStr)) { + continue strLoop; + } + } + foundIdx = pathIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + pattIdxStart = patIdxTmp; + pathIdxStart = foundIdx + patLength; + } + + for (int i = pattIdxStart; i <= pattIdxEnd; i++) { + if (!pattDirs[i].equals("**")) { + return false; + } + } + + return true; + } + + /** + * Tests whether or not a string matches against a pattern. The pattern may + * contain two special characters:
+ * '*' means zero or more characters
+ * '?' means one and only one character + * + * @param pattern pattern to match against. Must not be null. + * @param str string which must be matched against the pattern. Must not be + * null. + * @return true if the string matches against the pattern, or + * false otherwise. + */ + private boolean matchStrings(String pattern, String str) { + char[] patArr = pattern.toCharArray(); + char[] strArr = str.toCharArray(); + int patIdxStart = 0; + int patIdxEnd = patArr.length - 1; + int strIdxStart = 0; + int strIdxEnd = strArr.length - 1; + char ch; + + boolean containsStar = false; + for (int i = 0; i < patArr.length; i++) { + if (patArr[i] == '*') { + containsStar = true; + break; + } + } + + if (!containsStar) { + // No '*'s, so we make a shortcut + if (patIdxEnd != strIdxEnd) { + return false; // Pattern and string do not have the same size + } + for (int i = 0; i <= patIdxEnd; i++) { + ch = patArr[i]; + if (ch != '?') { + if (ch != strArr[i]) { + return false;// Character mismatch + } + } + } + return true; // String matches against pattern + } + + if (patIdxEnd == 0) { + return true; // Pattern contains only '*', which matches anything + } + + // Process characters before first star + while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxStart]) { + return false;// Character mismatch + } + } + patIdxStart++; + strIdxStart++; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // Process characters after last star + while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { + if (ch != '?') { + if (ch != strArr[strIdxEnd]) { + return false;// Character mismatch + } + } + patIdxEnd--; + strIdxEnd--; + } + if (strIdxStart > strIdxEnd) { + // All characters in the string are used. Check if only '*'s are + // left in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + return true; + } + + // process pattern between stars. padIdxStart and patIdxEnd point + // always to a '*'. + while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { + int patIdxTmp = -1; + for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { + if (patArr[i] == '*') { + patIdxTmp = i; + break; + } + } + if (patIdxTmp == patIdxStart + 1) { + // Two stars next to each other, skip the first one. + patIdxStart++; + continue; + } + // Find the pattern between padIdxStart & padIdxTmp in str between + // strIdxStart & strIdxEnd + int patLength = (patIdxTmp - patIdxStart - 1); + int strLength = (strIdxEnd - strIdxStart + 1); + int foundIdx = -1; + strLoop: for (int i = 0; i <= strLength - patLength; i++) { + for (int j = 0; j < patLength; j++) { + ch = patArr[patIdxStart + j + 1]; + if (ch != '?') { + if (ch != strArr[strIdxStart + i + j]) { + continue strLoop; + } + } + } + + foundIdx = strIdxStart + i; + break; + } + + if (foundIdx == -1) { + return false; + } + + patIdxStart = patIdxTmp; + strIdxStart = foundIdx + patLength; + } + + // All characters in the string are used. Check if only '*'s are left + // in the pattern. If so, we succeeded. Otherwise failure. + for (int i = patIdxStart; i <= patIdxEnd; i++) { + if (patArr[i] != '*') { + return false; + } + } + + return true; + } + + /** + * Given a pattern and a full path, determine the pattern-mapped part. + *

+ * For example: + *

    + *
  • '/docs/cvs/commit.html' and + * '/docs/cvs/commit.html to ''
  • + *
  • '/docs/*' and '/docs/cvs/commit to + * 'cvs/commit'
  • + *
  • '/docs/cvs/*.html' and '/docs/cvs/commit.html + * to 'commit.html'
  • + *
  • '/docs/**' and '/docs/cvs/commit to + * 'cvs/commit'
  • + *
  • '/docs/**\/*.html' and '/docs/cvs/commit.html + * to 'cvs/commit.html'
  • + *
  • '/*.html' and '/docs/cvs/commit.html to + * 'docs/cvs/commit.html'
  • + *
  • '*.html' and '/docs/cvs/commit.html to + * '/docs/cvs/commit.html'
  • + *
  • '*' and '/docs/cvs/commit.html to + * '/docs/cvs/commit.html'
  • + *
+ *

+ * Assumes that {@link #match} returns true for + * 'pattern' and 'path', but does not + * enforce this. + */ + public String extractPathWithinPattern(String pattern, String path) { +// String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator); +// String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator); + // mbaudier - 2020-03-13 : Use standard Java call: + String[] patternParts = pattern.split(this.pathSeparator); + String[] pathParts = path.split(this.pathSeparator); + + StringBuffer buffer = new StringBuffer(); + + // Add any path parts that have a wildcarded pattern part. + int puts = 0; + for (int i = 0; i < patternParts.length; i++) { + String patternPart = patternParts[i]; + if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) { + if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + puts++; + } + } + + // Append any trailing path parts. + for (int i = patternParts.length; i < pathParts.length; i++) { + if (puts > 0 || i > 0) { + buffer.append(this.pathSeparator); + } + buffer.append(pathParts[i]); + } + + return buffer.toString(); + } + +} diff --git a/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/PathMatcher.java b/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/PathMatcher.java new file mode 100644 index 000000000..9fc1f226e --- /dev/null +++ b/org.argeo.slc.repo/src/org/argeo/slc/repo/internal/springutil/PathMatcher.java @@ -0,0 +1,91 @@ +/* + * Copyright 2002-2007 the original author or authors. + * + * 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 org.argeo.slc.repo.internal.springutil; + +/** + * Strategy interface for String-based path matching. + * + *

Used by org.springframework.core.io.support.PathMatchingResourcePatternResolver, + * {@link org.springframework.web.servlet.handler.AbstractUrlHandlerMapping}, + * {@link org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver}, + * and {@link org.springframework.web.servlet.mvc.WebContentInterceptor}. + * + *

The default implementation is {@link AntPathMatcher}, supporting the + * Ant-style pattern syntax. + * + * @author Juergen Hoeller + * @since 1.2 + * @see AntPathMatcher + */ +public interface PathMatcher { + + /** + * Does the given path represent a pattern that can be matched + * by an implementation of this interface? + *

If the return value is false, then the {@link #match} + * method does not have to be used because direct equality comparisons + * on the static path Strings will lead to the same result. + * @param path the path String to check + * @return true if the given path represents a pattern + */ + boolean isPattern(String path); + + /** + * Match the given path against the given pattern, + * according to this PathMatcher's matching strategy. + * @param pattern the pattern to match against + * @param path the path String to test + * @return true if the supplied path matched, + * false if it didn't + */ + boolean match(String pattern, String path); + + /** + * Match the given path against the corresponding part of the given + * pattern, according to this PathMatcher's matching strategy. + *

Determines whether the pattern at least matches as far as the given base + * path goes, assuming that a full path may then match as well. + * @param pattern the pattern to match against + * @param path the path String to test + * @return true if the supplied path matched, + * false if it didn't + */ + boolean matchStart(String pattern, String path); + + /** + * Given a pattern and a full path, determine the pattern-mapped part. + *

This method is supposed to find out which part of the path is matched + * dynamically through an actual pattern, that is, it strips off a statically + * defined leading path from the given full path, returning only the actually + * pattern-matched part of the path. + *

For example: For "myroot/*.html" as pattern and "myroot/myfile.html" + * as full path, this method should return "myfile.html". The detailed + * determination rules are specified to this PathMatcher's matching strategy. + *

A simple implementation may return the given full path as-is in case + * of an actual pattern, and the empty String in case of the pattern not + * containing any dynamic parts (i.e. the pattern parameter being + * a static path that wouldn't qualify as an actual {@link #isPattern pattern}). + * A sophisticated implementation will differentiate between the static parts + * and the dynamic parts of the given path pattern. + * @param pattern the path pattern + * @param path the full path to introspect + * @return the pattern-mapped part of the given path + * (never null) + */ + String extractPathWithinPattern(String pattern, String path); + +} diff --git a/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/ArchiveWrapper.java b/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/ArchiveWrapper.java index a6551a6e4..2a3e5b0ed 100644 --- a/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/ArchiveWrapper.java +++ b/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/ArchiveWrapper.java @@ -34,11 +34,11 @@ import org.argeo.slc.build.Distribution; import org.argeo.slc.build.License; import org.argeo.slc.repo.OsgiFactory; import org.argeo.slc.repo.RepoUtils; +import org.argeo.slc.repo.internal.springutil.AntPathMatcher; +import org.argeo.slc.repo.internal.springutil.PathMatcher; import org.argeo.slc.repo.maven.ArtifactIdComparator; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; -import org.springframework.util.AntPathMatcher; -import org.springframework.util.PathMatcher; import aQute.bnd.osgi.Jar; diff --git a/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/BndWrapper.java b/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/BndWrapper.java index ab495d219..ddb569bbd 100644 --- a/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/BndWrapper.java +++ b/org.argeo.slc.repo/src/org/argeo/slc/repo/osgi/BndWrapper.java @@ -16,14 +16,13 @@ import org.argeo.slc.build.License; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.osgi.framework.Version; -import org.springframework.beans.factory.BeanNameAware; import aQute.bnd.osgi.Builder; import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.Jar; /** Utilities around the BND library, which manipulates OSGi metadata. */ -public class BndWrapper implements Constants, CategoryNameVersion, Distribution, BeanNameAware { +public class BndWrapper implements Constants, CategoryNameVersion, Distribution { private final static Log log = LogFactory.getLog(BndWrapper.class); private String groupId; @@ -170,15 +169,6 @@ public class BndWrapper implements Constants, CategoryNameVersion, Distribution, this.bndProperties = bndProperties; } - public void setBeanName(String name) { - if (this.name == null) { - this.name = name; - } else { - if (!name.contains("#")) - log.warn("Using explicitely set name " + this.name + " and not bean name " + name); - } - } - public String getGroupId() { return groupId; } diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/CloseTestResult.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/CloseTestResult.java new file mode 100644 index 000000000..32d82556b --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/CloseTestResult.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +import org.argeo.slc.test.TestResult; + +public class CloseTestResult implements Runnable { + private TestResult testResult; + + public void run() { + testResult.close(); + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/Echo.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/Echo.java new file mode 100644 index 000000000..d3ac0b36e --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/Echo.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; + +public class Echo implements Runnable { + private final static Log defaultLog = LogFactory.getLog(Echo.class); + private Path writeTo = null; + + private Log log; + private Object message; + + public void run() { + log().info(message); + + if (writeTo != null) { + try { + File file = writeTo.toFile(); + if (log().isDebugEnabled()) + log().debug("Write to " + file); + if (message != null) + FileUtils.writeStringToFile(file, message.toString()); + } catch (IOException e) { + throw new SlcException("Could not write to " + writeTo, e); + } + } + } + + private Log log() { + return log != null ? log : defaultLog; + } + + public void setMessage(Object message) { + this.message = message; + } + + public void setWriteTo(Path writeTo) { + this.writeTo = writeTo; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/If.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/If.java new file mode 100644 index 000000000..bdcfb37b9 --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/If.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +import org.argeo.slc.SlcException; + +/** Conditional execution */ +public class If implements Runnable { + private Boolean is; + private Boolean not; + private Runnable then; + private Runnable els; + + public void run() { + if (is == null && not == null) + throw new SlcException("No condition set"); + if (is != null && not != null) + throw new SlcException("Both is and not cannot be set"); + + boolean bool = (is != null ? is : !not); + if (bool) { + if (then != null) + then.run(); + } else { + if (els != null) + els.run(); + } + + } + + public void setIs(Boolean bool) { + this.is = bool; + } + + public void setThen(Runnable then) { + this.then = then; + } + + public void setEls(Runnable els) { + this.els = els; + } + + public Boolean getNot() { + return not; + } + + public void setNot(Boolean not) { + this.not = not; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/JvmProcess.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/JvmProcess.java new file mode 100644 index 000000000..a868a1244 --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/JvmProcess.java @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.argeo.slc.SlcException; + +/** A Java Virtual Machine process. */ +public class JvmProcess extends SystemCall { + private Properties systemProperties = new Properties(); + private List classpath = new ArrayList(); + private List pBootClasspath = new ArrayList(); + private Path jvm = null; + private String mainClass; + private String mainJar; + private List jvmArgs = new ArrayList(); + private List args = new ArrayList(); + + private String systemPropertiesFileProperty = null; + private String systemPropertiesFileDir = null; + private String systemPropertiesFileName = null; + + public void init() throws Exception { + List command = new ArrayList(); + if (jvm != null) + command.add(asFile(jvm).getPath()); + else + command.add("java"); + + if (pBootClasspath.size() > 0) { + StringBuffer buf = new StringBuffer("-Xbootclasspath/p:"); + Boolean first = true; + for (Path res : pBootClasspath) { + if (first) + first = false; + else + buf.append(File.pathSeparatorChar); + + buf.append(asFile(res)); + } + command.add(buf.toString()); + } + + for (String jvmArg : jvmArgs) { + command.add(jvmArg); + } + + if (classpath.size() > 0) { + command.add("-cp"); + StringBuffer buf = new StringBuffer(""); + for (Path res : classpath) { + if (buf.length() != 0) + buf.append(File.pathSeparatorChar); + buf.append(asFile(res)); + } + command.add(buf.toString()); + } + + if (systemPropertiesFileProperty == null) { + // pass system properties as argument + for (Map.Entry entry : systemProperties.entrySet()) { + command.add("-D" + entry.getKey() + "=" + entry.getValue()); + } + } else { + // write system properties in a file to work around OS limitations + // with command line (e.g. Win XP) + String dir = systemPropertiesFileDir; + if (dir == null) + dir = getExecDirToUse(); + String fileName = systemPropertiesFileName; + if (fileName == null) + fileName = systemPropertiesFileProperty + ".properties"; + + // Write file + FileOutputStream fos = null; + File file = new File(dir + File.separator + fileName); + try { + + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + fos = new FileOutputStream(file); + systemProperties.store(fos, "Automatically generated by " + getClass()); + command.add("-D" + systemPropertiesFileProperty + "=" + file.getCanonicalPath()); + } catch (IOException e) { + throw new SlcException("Cannot write to system properties to " + file, e); + } finally { + IOUtils.closeQuietly(fos); + } + } + + // Program + if (mainClass != null) { + command.add(mainClass); + } else if (mainJar != null) { + command.add("-jar"); + command.add(mainJar); + } else { + throw new SlcException("No main class or jar defined"); + } + + for (String arg : args) { + command.add(arg); + } + + setCommand(command); + } + + protected File asFile(Path res) { + File file = res.toFile(); + if (!file.exists()) + return copyToTempFile(res); + else + return res.toFile(); + } + + protected File copyToTempFile(Path res) { + File tempFile; + FileOutputStream fos; + try { + tempFile = File.createTempFile("slcJvmProcess-", res.getFileName().toString()); + tempFile.deleteOnExit(); + fos = new FileOutputStream(tempFile); + IOUtils.copy(Files.newInputStream(res), fos); + } catch (IOException e) { + throw new SlcException("Cannot copy " + res + " to temp file.", e); + } + IOUtils.closeQuietly(fos); + return tempFile; + } + + /** Append the argument (for chaining) */ + @Override + public SystemCall arg(String arg) { + args.add(arg); + return this; + } + + /** Append the argument (for chaining) */ + @Override + public SystemCall arg(String arg, String value) { + args.add(arg); + args.add(value); + return this; + } + + public Properties getSystemProperties() { + return systemProperties; + } + + public void setSystemProperties(Properties systemProperties) { + this.systemProperties = systemProperties; + } + + public List getClasspath() { + return classpath; + } + + public void setClasspath(List classpath) { + this.classpath = classpath; + } + + public List getPBootClasspath() { + return pBootClasspath; + } + + public void setPBootClasspath(List bootClasspath) { + pBootClasspath = bootClasspath; + } + + public Path getJvm() { + return jvm; + } + + public void setJvm(Path jvm) { + this.jvm = jvm; + } + + public String getMainClass() { + return mainClass; + } + + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + public String getMainJar() { + return mainJar; + } + + public void setMainJar(String mainJar) { + this.mainJar = mainJar; + } + + public List getJvmArgs() { + return jvmArgs; + } + + public void setJvmArgs(List jvmArgs) { + this.jvmArgs = jvmArgs; + } + + public List getArgs() { + return args; + } + + public void setArgs(List args) { + this.args = args; + } + + public void setSystemPropertiesFileProperty(String systemPropertiesFilePropertyName) { + this.systemPropertiesFileProperty = systemPropertiesFilePropertyName; + } + + public void setSystemPropertiesFileDir(String systemPropertiesFileDir) { + this.systemPropertiesFileDir = systemPropertiesFileDir; + } + + public void setSystemPropertiesFileName(String systemPropertiesFileName) { + this.systemPropertiesFileName = systemPropertiesFileName; + } + +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCall.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCall.java new file mode 100644 index 000000000..c16209d9e --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCall.java @@ -0,0 +1,761 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import javax.security.auth.callback.CallbackHandler; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteResultHandler; +import org.apache.commons.exec.ExecuteStreamHandler; +import org.apache.commons.exec.ExecuteWatchdog; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.LogOutputStream; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.exec.ShutdownHookProcessDestroyer; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; +import org.argeo.slc.execution.ExecutionResources; +import org.argeo.slc.runtime.test.SimpleResultPart; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestStatus; + +/** Execute an OS specific system call. */ +public class SystemCall implements Runnable { + public final static String LOG_STDOUT = "System.out"; + + private final Log log = LogFactory.getLog(getClass()); + + private String execDir; + + private String cmd = null; + private List command = null; + + private Executor executor = new DefaultExecutor(); + private Boolean synchronous = true; + + private String stdErrLogLevel = "ERROR"; + private String stdOutLogLevel = "INFO"; + + private Path stdOutFile = null; + private Path stdErrFile = null; + + private Path stdInFile = null; + /** + * If no {@link #stdInFile} provided, writing to this stream will write to the + * stdin of the process. + */ + private OutputStream stdInSink = null; + + private Boolean redirectStdOut = false; + + private List outputListeners = Collections + .synchronizedList(new ArrayList()); + + private Map> osCommands = new HashMap>(); + private Map osCmds = new HashMap(); + private Map environmentVariables = new HashMap(); + + private Boolean logCommand = false; + private Boolean redirectStreams = true; + private Boolean exceptionOnFailed = true; + private Boolean mergeEnvironmentVariables = true; + +// private Authentication authentication; + + private String osConsole = null; + private String generateScript = null; + + /** 24 hours */ + private Long watchdogTimeout = 24 * 60 * 60 * 1000l; + + private TestResult testResult; + + private ExecutionResources executionResources; + + /** Sudo the command, as root if empty or as user if not. */ + private String sudo = null; + // TODO make it more secure and robust, test only once + private final String sudoPrompt = UUID.randomUUID().toString(); + private String askPassProgram = "/usr/libexec/openssh/ssh-askpass"; + @SuppressWarnings("unused") + private boolean firstLine = true; + @SuppressWarnings("unused") + private CallbackHandler callbackHandler; + /** Chroot to the this path (must not be empty) */ + private String chroot = null; + + // Current + /** Current watchdog, null if process is completed */ + ExecuteWatchdog currentWatchdog = null; + + /** Empty constructor */ + public SystemCall() { + + } + + /** + * Constructor based on the provided command list. + * + * @param command the command list + */ + public SystemCall(List command) { + this.command = command; + } + + /** + * Constructor based on the provided command. + * + * @param cmd the command. If the provided string contains no space a command + * list is initialized with the argument as first component (useful + * for chained construction) + */ + public SystemCall(String cmd) { + if (cmd.indexOf(' ') < 0) { + command = new ArrayList(); + command.add(cmd); + } else { + this.cmd = cmd; + } + } + + /** Executes the system call. */ + public void run() { +// authentication = SecurityContextHolder.getContext().getAuthentication(); + + // Manage streams + Writer stdOutWriter = null; + OutputStream stdOutputStream = null; + Writer stdErrWriter = null; + InputStream stdInStream = null; + if (stdOutFile != null) + if (redirectStdOut) + stdOutputStream = createOutputStream(stdOutFile); + else + stdOutWriter = createWriter(stdOutFile, true); + + if (stdErrFile != null) { + stdErrWriter = createWriter(stdErrFile, true); + } else { + if (stdOutFile != null && !redirectStdOut) + stdErrWriter = createWriter(stdOutFile, true); + } + + try { + if (stdInFile != null) + stdInStream = Files.newInputStream(stdInFile); + else { + stdInStream = new PipedInputStream(); + stdInSink = new PipedOutputStream((PipedInputStream) stdInStream); + } + } catch (IOException e2) { + throw new SlcException("Cannot open a stream for " + stdInFile, e2); + } + + if (log.isTraceEnabled()) { + log.debug("os.name=" + System.getProperty("os.name")); + log.debug("os.arch=" + System.getProperty("os.arch")); + log.debug("os.version=" + System.getProperty("os.version")); + } + + // Execution directory + File dir = new File(getExecDirToUse()); + // if (!dir.exists()) + // dir.mkdirs(); + + // Watchdog to check for lost processes + Executor executorToUse; + if (executor != null) + executorToUse = executor; + else + executorToUse = new DefaultExecutor(); + executorToUse.setWatchdog(createWatchdog()); + + if (redirectStreams) { + // Redirect standard streams + executorToUse.setStreamHandler( + createExecuteStreamHandler(stdOutWriter, stdOutputStream, stdErrWriter, stdInStream)); + } else { + // Dummy stream handler (otherwise pump is used) + executorToUse.setStreamHandler(new DummyexecuteStreamHandler()); + } + + executorToUse.setProcessDestroyer(new ShutdownHookProcessDestroyer()); + executorToUse.setWorkingDirectory(dir); + + // Command line to use + final CommandLine commandLine = createCommandLine(); + if (logCommand) + log.info("Execute command:\n" + commandLine + "\n in working directory: \n" + dir + "\n"); + + // Env variables + Map environmentVariablesToUse = null; + environmentVariablesToUse = new HashMap(); + if (mergeEnvironmentVariables) + environmentVariablesToUse.putAll(System.getenv()); + if (environmentVariables.size() > 0) + environmentVariablesToUse.putAll(environmentVariables); + + // Execute + ExecuteResultHandler executeResultHandler = createExecuteResultHandler(commandLine); + + // + // THE EXECUTION PROPER + // + try { + if (synchronous) + try { + int exitValue = executorToUse.execute(commandLine, environmentVariablesToUse); + executeResultHandler.onProcessComplete(exitValue); + } catch (ExecuteException e1) { + if (e1.getExitValue() == Executor.INVALID_EXITVALUE) { + Thread.currentThread().interrupt(); + return; + } + // Sleep 1s in order to make sure error logs are flushed + Thread.sleep(1000); + executeResultHandler.onProcessFailed(e1); + } + else + executorToUse.execute(commandLine, environmentVariablesToUse, executeResultHandler); + } catch (SlcException e) { + throw e; + } catch (Exception e) { + throw new SlcException("Could not execute command " + commandLine, e); + } finally { + IOUtils.closeQuietly(stdOutWriter); + IOUtils.closeQuietly(stdErrWriter); + IOUtils.closeQuietly(stdInStream); + IOUtils.closeQuietly(stdInSink); + } + + } + + public synchronized String function() { + final StringBuffer buf = new StringBuffer(""); + SystemCallOutputListener tempOutputListener = new SystemCallOutputListener() { + private Long lineCount = 0l; + + public void newLine(SystemCall systemCall, String line, Boolean isError) { + if (!isError) { + if (lineCount != 0l) + buf.append('\n'); + buf.append(line); + lineCount++; + } + } + }; + addOutputListener(tempOutputListener); + run(); + removeOutputListener(tempOutputListener); + return buf.toString(); + } + + public String asCommand() { + return createCommandLine().toString(); + } + + @Override + public String toString() { + return asCommand(); + } + + /** + * Build a command line based on the properties. Can be overridden by specific + * command wrappers. + */ + protected CommandLine createCommandLine() { + // Check if an OS specific command overrides + String osName = System.getProperty("os.name"); + List commandToUse = null; + if (osCommands.containsKey(osName)) + commandToUse = osCommands.get(osName); + else + commandToUse = command; + String cmdToUse = null; + if (osCmds.containsKey(osName)) + cmdToUse = osCmds.get(osName); + else + cmdToUse = cmd; + + CommandLine commandLine = null; + + // Which command definition to use + if (commandToUse == null && cmdToUse == null) + throw new SlcException("Please specify a command."); + else if (commandToUse != null && cmdToUse != null) + throw new SlcException("Specify the command either as a line or as a list."); + else if (cmdToUse != null) { + if (chroot != null && !chroot.trim().equals("")) + cmdToUse = "chroot \"" + chroot + "\" " + cmdToUse; + if (sudo != null) { + environmentVariables.put("SUDO_ASKPASS", askPassProgram); + if (!sudo.trim().equals("")) + cmdToUse = "sudo -p " + sudoPrompt + " -u " + sudo + " " + cmdToUse; + else + cmdToUse = "sudo -p " + sudoPrompt + " " + cmdToUse; + } + + // GENERATE COMMAND LINE + commandLine = CommandLine.parse(cmdToUse); + } else if (commandToUse != null) { + if (commandToUse.size() == 0) + throw new SlcException("Command line is empty."); + + if (chroot != null && sudo != null) { + commandToUse.add(0, "chroot"); + commandToUse.add(1, chroot); + } + + if (sudo != null) { + environmentVariables.put("SUDO_ASKPASS", askPassProgram); + commandToUse.add(0, "sudo"); + commandToUse.add(1, "-p"); + commandToUse.add(2, sudoPrompt); + if (!sudo.trim().equals("")) { + commandToUse.add(3, "-u"); + commandToUse.add(4, sudo); + } + } + + // GENERATE COMMAND LINE + commandLine = new CommandLine(commandToUse.get(0).toString()); + + for (int i = 1; i < commandToUse.size(); i++) { + if (log.isTraceEnabled()) + log.debug(commandToUse.get(i)); + commandLine.addArgument(commandToUse.get(i).toString()); + } + } else { + // all cases covered previously + throw new UnsupportedException(); + } + + if (generateScript != null) { + File scriptFile = new File(getExecDirToUse() + File.separator + generateScript); + try { + FileUtils.writeStringToFile(scriptFile, + (osConsole != null ? osConsole + " " : "") + commandLine.toString()); + } catch (IOException e) { + throw new SlcException("Could not generate script " + scriptFile, e); + } + commandLine = new CommandLine(scriptFile); + } else { + if (osConsole != null) + commandLine = CommandLine.parse(osConsole + " " + commandLine.toString()); + } + + return commandLine; + } + + /** + * Creates a {@link PumpStreamHandler} which redirects streams to the custom + * logging mechanism. + */ + protected ExecuteStreamHandler createExecuteStreamHandler(final Writer stdOutWriter, + final OutputStream stdOutputStream, final Writer stdErrWriter, final InputStream stdInStream) { + + // Log writers + OutputStream stdout = stdOutputStream != null ? stdOutputStream : new LogOutputStream() { + protected void processLine(String line, int level) { + // if (firstLine) { + // if (sudo != null && callbackHandler != null + // && line.startsWith(sudoPrompt)) { + // try { + // PasswordCallback pc = new PasswordCallback( + // "sudo password", false); + // Callback[] cbs = { pc }; + // callbackHandler.handle(cbs); + // char[] pwd = pc.getPassword(); + // char[] arr = Arrays.copyOf(pwd, + // pwd.length + 1); + // arr[arr.length - 1] = '\n'; + // IOUtils.write(arr, stdInSink); + // stdInSink.flush(); + // } catch (Exception e) { + // throw new SlcException( + // "Cannot retrieve sudo password", e); + // } + // } + // firstLine = false; + // } + + if (line != null && !line.trim().equals("")) + logStdOut(line); + + if (stdOutWriter != null) + appendLineToFile(stdOutWriter, line); + } + }; + + OutputStream stderr = new LogOutputStream() { + protected void processLine(String line, int level) { + if (line != null && !line.trim().equals("")) + logStdErr(line); + if (stdErrWriter != null) + appendLineToFile(stdErrWriter, line); + } + }; + + PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdout, stderr, stdInStream) { + + @Override + public void stop() throws IOException { + // prevents the method to block when joining stdin + if (stdInSink != null) + IOUtils.closeQuietly(stdInSink); + + super.stop(); + } + }; + return pumpStreamHandler; + } + + /** Creates the default {@link ExecuteResultHandler}. */ + protected ExecuteResultHandler createExecuteResultHandler(final CommandLine commandLine) { + return new ExecuteResultHandler() { + + public void onProcessComplete(int exitValue) { + String msg = "System call '" + commandLine + "' properly completed."; + if (log.isTraceEnabled()) + log.trace(msg); + if (testResult != null) { + forwardPath(testResult); + testResult.addResultPart(new SimpleResultPart(TestStatus.PASSED, msg)); + } + releaseWatchdog(); + } + + public void onProcessFailed(ExecuteException e) { + + String msg = "System call '" + commandLine + "' failed."; + if (testResult != null) { + forwardPath(testResult); + testResult.addResultPart(new SimpleResultPart(TestStatus.ERROR, msg, e)); + } else { + if (exceptionOnFailed) + throw new SlcException(msg, e); + else + log.error(msg, e); + } + releaseWatchdog(); + } + }; + } + + @Deprecated + protected void forwardPath(TestResult testResult) { + // TODO: allocate a TreeSPath + } + + /** + * Shortcut method getting the execDir to use + */ + protected String getExecDirToUse() { + try { + if (execDir != null) { + return execDir; + } + return System.getProperty("user.dir"); + } catch (Exception e) { + throw new SlcException("Cannot find exec dir", e); + } + } + + protected void logStdOut(String line) { + for (SystemCallOutputListener outputListener : outputListeners) + outputListener.newLine(this, line, false); + log(stdOutLogLevel, line); + } + + protected void logStdErr(String line) { + for (SystemCallOutputListener outputListener : outputListeners) + outputListener.newLine(this, line, true); + log(stdErrLogLevel, line); + } + + /** Log from the underlying streams. */ + protected void log(String logLevel, String line) { + // TODO optimize +// if (SecurityContextHolder.getContext().getAuthentication() == null) { +// SecurityContextHolder.getContext() +// .setAuthentication(authentication); +// } + + if ("ERROR".equals(logLevel)) + log.error(line); + else if ("WARN".equals(logLevel)) + log.warn(line); + else if ("INFO".equals(logLevel)) + log.info(line); + else if ("DEBUG".equals(logLevel)) + log.debug(line); + else if ("TRACE".equals(logLevel)) + log.trace(line); + else if (LOG_STDOUT.equals(logLevel)) + System.out.println(line); + else if ("System.err".equals(logLevel)) + System.err.println(line); + else + throw new SlcException("Unknown log level " + logLevel); + } + + /** Append line to a log file. */ + protected void appendLineToFile(Writer writer, String line) { + try { + writer.append(line).append('\n'); + } catch (IOException e) { + log.error("Cannot write to log file", e); + } + } + + /** Creates the writer for the output/err files. */ + protected Writer createWriter(Path target, Boolean append) { + FileWriter writer = null; + try { + + final File file; + if (executionResources != null) + file = new File(executionResources.getAsOsPath(target, true)); + else + file = target.toFile(); + writer = new FileWriter(file, append); + } catch (IOException e) { + log.error("Cannot get file for " + target, e); + IOUtils.closeQuietly(writer); + } + return writer; + } + + /** Creates an outputstream for the output/err files. */ + protected OutputStream createOutputStream(Path target) { + FileOutputStream out = null; + try { + + final File file; + if (executionResources != null) + file = new File(executionResources.getAsOsPath(target, true)); + else + file = target.toFile(); + out = new FileOutputStream(file, false); + } catch (IOException e) { + log.error("Cannot get file for " + target, e); + IOUtils.closeQuietly(out); + } + return out; + } + + /** Append the argument (for chaining) */ + public SystemCall arg(String arg) { + if (command == null) + command = new ArrayList(); + command.add(arg); + return this; + } + + /** Append the argument (for chaining) */ + public SystemCall arg(String arg, String value) { + if (command == null) + command = new ArrayList(); + command.add(arg); + command.add(value); + return this; + } + + // CONTROL + public synchronized Boolean isRunning() { + return currentWatchdog != null; + } + + private synchronized ExecuteWatchdog createWatchdog() { +// if (currentWatchdog != null) +// throw new SlcException("A process is already being monitored"); + currentWatchdog = new ExecuteWatchdog(watchdogTimeout); + return currentWatchdog; + } + + private synchronized void releaseWatchdog() { + currentWatchdog = null; + } + + public synchronized void kill() { + if (currentWatchdog != null) + currentWatchdog.destroyProcess(); + } + + /** */ + public void setCmd(String command) { + this.cmd = command; + } + + public void setCommand(List command) { + this.command = command; + } + + public void setExecDir(String execdir) { + this.execDir = execdir; + } + + public void setStdErrLogLevel(String stdErrLogLevel) { + this.stdErrLogLevel = stdErrLogLevel; + } + + public void setStdOutLogLevel(String stdOutLogLevel) { + this.stdOutLogLevel = stdOutLogLevel; + } + + public void setSynchronous(Boolean synchronous) { + this.synchronous = synchronous; + } + + public void setOsCommands(Map> osCommands) { + this.osCommands = osCommands; + } + + public void setOsCmds(Map osCmds) { + this.osCmds = osCmds; + } + + public void setEnvironmentVariables(Map environmentVariables) { + this.environmentVariables = environmentVariables; + } + + public Map getEnvironmentVariables() { + return environmentVariables; + } + + public void setWatchdogTimeout(Long watchdogTimeout) { + this.watchdogTimeout = watchdogTimeout; + } + + public void setStdOutFile(Path stdOutFile) { + this.stdOutFile = stdOutFile; + } + + public void setStdErrFile(Path stdErrFile) { + this.stdErrFile = stdErrFile; + } + + public void setStdInFile(Path stdInFile) { + this.stdInFile = stdInFile; + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + + public void setLogCommand(Boolean logCommand) { + this.logCommand = logCommand; + } + + public void setRedirectStreams(Boolean redirectStreams) { + this.redirectStreams = redirectStreams; + } + + public void setExceptionOnFailed(Boolean exceptionOnFailed) { + this.exceptionOnFailed = exceptionOnFailed; + } + + public void setMergeEnvironmentVariables(Boolean mergeEnvironmentVariables) { + this.mergeEnvironmentVariables = mergeEnvironmentVariables; + } + + public void setOsConsole(String osConsole) { + this.osConsole = osConsole; + } + + public void setGenerateScript(String generateScript) { + this.generateScript = generateScript; + } + + public void setExecutionResources(ExecutionResources executionResources) { + this.executionResources = executionResources; + } + + public void setRedirectStdOut(Boolean redirectStdOut) { + this.redirectStdOut = redirectStdOut; + } + + public void addOutputListener(SystemCallOutputListener outputListener) { + outputListeners.add(outputListener); + } + + public void removeOutputListener(SystemCallOutputListener outputListener) { + outputListeners.remove(outputListener); + } + + public void setOutputListeners(List outputListeners) { + this.outputListeners = outputListeners; + } + + public void setExecutor(Executor executor) { + this.executor = executor; + } + + public void setSudo(String sudo) { + this.sudo = sudo; + } + + public void setCallbackHandler(CallbackHandler callbackHandler) { + this.callbackHandler = callbackHandler; + } + + public void setChroot(String chroot) { + this.chroot = chroot; + } + + private class DummyexecuteStreamHandler implements ExecuteStreamHandler { + + public void setProcessErrorStream(InputStream is) throws IOException { + } + + public void setProcessInputStream(OutputStream os) throws IOException { + } + + public void setProcessOutputStream(InputStream is) throws IOException { + } + + public void start() throws IOException { + } + + public void stop() { + } + + } +} diff --git a/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCallOutputListener.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCallOutputListener.java new file mode 100644 index 000000000..f10e52a15 --- /dev/null +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/tasks/SystemCallOutputListener.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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 org.argeo.slc.runtime.tasks; + +public interface SystemCallOutputListener { + public void newLine(SystemCall systemCall, String line, Boolean isError); +} diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestData.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestData.java similarity index 92% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestData.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestData.java index 39a97f290..4ff120aa2 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestData.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestData.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import org.argeo.slc.test.TestData; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestDefinition.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestDefinition.java similarity index 93% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestDefinition.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestDefinition.java index 6b92135e8..009714125 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/BasicTestDefinition.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/BasicTestDefinition.java @@ -13,10 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import org.argeo.slc.SlcException; -import org.argeo.slc.core.test.context.ContextUtils; import org.argeo.slc.test.IncompatibleTestDataException; import org.argeo.slc.test.TestData; import org.argeo.slc.test.TestDefinition; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/ContextUtils.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/ContextUtils.java similarity index 95% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/context/ContextUtils.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/ContextUtils.java index f62fb5ca3..663e1ed46 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/ContextUtils.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/ContextUtils.java @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test.context; +package org.argeo.slc.runtime.test; import java.util.Map; import java.util.TreeMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.test.SimpleResultPart; import org.argeo.slc.test.TestResult; import org.argeo.slc.test.TestStatus; import org.argeo.slc.test.context.ContextAware; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleResultPart.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleResultPart.java similarity index 94% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleResultPart.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleResultPart.java index 8ad81af1c..2c7726fcd 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleResultPart.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleResultPart.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import java.io.Serializable; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestResult.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestResult.java similarity index 94% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestResult.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestResult.java index 93306a5b4..b4437d71f 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestResult.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestResult.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import java.util.Date; import java.util.List; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestRun.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestRun.java similarity index 95% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestRun.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestRun.java index 4f6a12f81..a00c48dfa 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SimpleTestRun.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SimpleTestRun.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import java.util.UUID; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SlcTestUtils.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SlcTestUtils.java similarity index 97% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/SlcTestUtils.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SlcTestUtils.java index c926a691d..fe38620ad 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/SlcTestUtils.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/SlcTestUtils.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import org.argeo.slc.SlcException; import org.argeo.slc.test.TestStatus; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/TestDataUtils.java b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/TestDataUtils.java similarity index 95% rename from org.argeo.slc.spring/src/org/argeo/slc/core/test/TestDataUtils.java rename to org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/TestDataUtils.java index b32da3801..b2d74a7c9 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/TestDataUtils.java +++ b/org.argeo.slc.runtime/src/org/argeo/slc/runtime/test/TestDataUtils.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.argeo.slc.core.test; +package org.argeo.slc.runtime.test; import org.argeo.slc.UnsupportedException; import org.argeo.slc.test.TestData; diff --git a/org.argeo.slc.spring/bnd.bnd b/org.argeo.slc.spring/bnd.bnd index 7d7a35cfd..bc4d0cd86 100644 --- a/org.argeo.slc.spring/bnd.bnd +++ b/org.argeo.slc.spring/bnd.bnd @@ -1,6 +1,7 @@ Import-Package: javax.jcr.nodetype,\ javax.jcr.security,\ org.argeo.api,\ +aQute.bnd.osgi,\ org.apache.tools.ant.*;resolution:="optional",\ junit.framework;resolution:="optional",\ org.osgi.*;version=0.0.0,\ diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java index 004605cab..edb383cb5 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/AbstractExecutionFlowTestCase.java @@ -19,9 +19,9 @@ import junit.framework.TestCase; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.argeo.slc.core.test.SimpleTestResult; import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.runtime.test.SimpleTestResult; import org.argeo.slc.test.TestResultPart; import org.argeo.slc.test.TestStatus; import org.springframework.context.ConfigurableApplicationContext; diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java index 06df80547..c2ecd09dc 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/BasicExecutionFlowTest.java @@ -18,9 +18,9 @@ package org.argeo.slc.core.execution; import java.util.HashMap; import java.util.Map; -import org.argeo.slc.core.test.SimpleTestResult; import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.runtime.test.SimpleTestResult; import org.argeo.slc.test.TestStatus; import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.ConfigurableApplicationContext; diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java index 35df7eb53..af7769078 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/ParameterRefTest.java @@ -15,8 +15,8 @@ */ package org.argeo.slc.core.execution; -import org.argeo.slc.core.test.SimpleTestResult; import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.runtime.test.SimpleTestResult; import org.argeo.slc.test.TestStatus; import org.springframework.context.ConfigurableApplicationContext; diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMap.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMap.xml index 8cf72e354..8aaed845a 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMap.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMap.xml @@ -24,7 +24,7 @@ - + @@ -80,7 +80,7 @@ - + @@ -93,7 +93,7 @@ - + @@ -124,7 +124,7 @@ - + myValue @@ -139,7 +139,7 @@ - + @@ -160,7 +160,7 @@ - + myValue @@ -175,7 +175,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -213,7 +213,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -295,7 +295,7 @@ - + @@ -304,6 +304,6 @@ value="testKey=@{testKey}" /> - + \ No newline at end of file diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml index b8626f851..94ddd35dc 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/listSetMapMultipleFlow.xml @@ -24,7 +24,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -110,7 +110,7 @@ - + @@ -141,7 +141,7 @@ - + myValue @@ -156,7 +156,7 @@ - + @@ -177,7 +177,7 @@ - + myValue @@ -192,7 +192,7 @@ - + @@ -213,7 +213,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -312,7 +312,7 @@ - + @@ -321,6 +321,6 @@ value="testKey=@{testKey}" /> - + \ No newline at end of file diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/multipleFlow.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/multipleFlow.xml index 58a43e418..69b3efe4d 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/multipleFlow.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/multipleFlow.xml @@ -24,11 +24,11 @@ - + - + - + @@ -56,7 +56,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/parameterRef.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/parameterRef.xml index 98cc14d3d..e9e389a69 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/parameterRef.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/parameterRef.xml @@ -36,11 +36,11 @@ p:isParameter="true" p:isFrozen="true" /> - - @@ -92,13 +92,13 @@ - + - + @@ -113,13 +113,13 @@ - + - - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml index a36b4a167..6481d962f 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.exec.xml @@ -24,15 +24,15 @@ - + - + - + @@ -80,7 +80,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -98,7 +98,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -116,7 +116,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -199,7 +199,7 @@ - + @@ -208,7 +208,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -226,7 +226,7 @@ - + @@ -237,7 +237,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -257,7 +257,7 @@ - + @@ -267,7 +267,7 @@ - + @@ -277,7 +277,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -302,7 +302,7 @@ - + @@ -312,7 +312,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml index 893768be3..ba72f88bf 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/placeHolders.cascading.xml @@ -24,15 +24,15 @@ - + - + - + @@ -80,7 +80,7 @@ - + @@ -89,7 +89,7 @@ - + @@ -98,7 +98,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -116,7 +116,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -199,7 +199,7 @@ - + @@ -208,7 +208,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -226,7 +226,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/specOverriding.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/specOverriding.xml index de1dc8504..7a70f71b3 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/specOverriding.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/specOverriding.xml @@ -24,11 +24,11 @@ - + - + - + @@ -41,7 +41,7 @@ p:type="integer" /> - @@ -73,7 +73,7 @@ - + @@ -87,7 +87,7 @@ - @@ -107,7 +107,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/test.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/test.xml index d8bec3df0..5ae7501a2 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/test.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/test.xml @@ -26,11 +26,11 @@ - + - + - + @@ -43,7 +43,7 @@ p:type="integer" /> - @@ -80,7 +80,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java index c60014e3d..e72800124 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/FlowNamespaceTest.java @@ -16,9 +16,9 @@ package org.argeo.slc.core.execution.xml; import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase; -import org.argeo.slc.core.test.SimpleTestResult; import org.argeo.slc.execution.ExecutionContext; import org.argeo.slc.execution.ExecutionFlow; +import org.argeo.slc.runtime.test.SimpleTestResult; import org.springframework.context.ConfigurableApplicationContext; public abstract class FlowNamespaceTest extends AbstractExecutionFlowTestCase { diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/advanced.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/advanced.xml index 49b6f7e1d..c316de6dd 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/advanced.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/advanced.xml @@ -27,11 +27,11 @@ - + - + - + @@ -58,7 +58,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml index ac5f085eb..6668e67b8 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns-002.xml @@ -30,7 +30,7 @@ + class="org.argeo.slc.runtime.test.BasicTestData" /> diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml index facb27761..67bf01233 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/canonic-ns.xml @@ -43,13 +43,13 @@ isParameter="true" type="integer" /> - - - + - + @@ -68,13 +68,13 @@ - + - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/containers.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/containers.xml index 61bfa0703..518e5f775 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/containers.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/containers.xml @@ -28,11 +28,11 @@ - + - + - + @@ -76,7 +76,7 @@ - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/tests.xml b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/tests.xml index ee58a1869..501572520 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/tests.xml +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/execution/xml/tests.xml @@ -24,9 +24,9 @@ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd"> - + - + diff --git a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/test/context/ContextTest.java b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/test/context/ContextTest.java index 694851c82..75d4b9349 100644 --- a/org.argeo.slc.spring/ext/test/org/argeo/slc/core/test/context/ContextTest.java +++ b/org.argeo.slc.spring/ext/test/org/argeo/slc/core/test/context/ContextTest.java @@ -17,7 +17,8 @@ package org.argeo.slc.core.test.context; import java.util.List; -import org.argeo.slc.core.test.SimpleTestResult; +import org.argeo.slc.runtime.test.ContextUtils; +import org.argeo.slc.runtime.test.SimpleTestResult; import org.argeo.slc.test.TestResultPart; import org.argeo.slc.test.TestStatus; import org.argeo.slc.test.context.ContextAware; diff --git a/org.argeo.slc.spring/pom.xml b/org.argeo.slc.spring/pom.xml index 456edb030..368124cc2 100644 --- a/org.argeo.slc.spring/pom.xml +++ b/org.argeo.slc.spring/pom.xml @@ -57,6 +57,11 @@ org.argeo.slc.jcr 2.1.17-SNAPSHOT + + org.argeo.slc + org.argeo.slc.repo + 2.1.17-SNAPSHOT + diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/tasks/SystemCall.java b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/tasks/SystemCall.java index 27cc59d60..4237c5752 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/execution/tasks/SystemCall.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -50,7 +50,7 @@ import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.UnsupportedException; import org.argeo.slc.core.execution.ExecutionResources; -import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.runtime.test.SimpleResultPart; import org.argeo.slc.test.TestResult; import org.argeo.slc.test.TestStatus; import org.springframework.core.io.Resource; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/DefaultContextTestData.java b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/DefaultContextTestData.java index ca0bf5ffb..3c7f44ae2 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/DefaultContextTestData.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/DefaultContextTestData.java @@ -15,7 +15,7 @@ */ package org.argeo.slc.core.test.context; -import org.argeo.slc.core.test.TestDataUtils; +import org.argeo.slc.runtime.test.TestDataUtils; import org.argeo.slc.test.TestData; import org.argeo.slc.test.TestDataProvider; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleContextAware.java b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleContextAware.java index f10be5659..7980e3768 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleContextAware.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleContextAware.java @@ -19,6 +19,7 @@ import java.util.Map; import java.util.TreeMap; import org.argeo.slc.SlcException; +import org.argeo.slc.runtime.test.ContextUtils; import org.argeo.slc.test.context.ContextAware; import org.argeo.slc.test.context.ParentContextAware; import org.springframework.beans.factory.InitializingBean; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java index b8abf7fde..fc214ea1a 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/core/test/context/SimpleParentContextAware.java @@ -19,6 +19,7 @@ import java.util.Collection; import java.util.List; import java.util.Vector; +import org.argeo.slc.runtime.test.ContextUtils; import org.argeo.slc.test.context.ContextAware; import org.argeo.slc.test.context.ParentContextAware; import org.springframework.beans.factory.InitializingBean; diff --git a/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/BndWrapper.java b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/BndWrapper.java new file mode 100644 index 000000000..8b52c9a35 --- /dev/null +++ b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/BndWrapper.java @@ -0,0 +1,20 @@ +package org.argeo.slc.spring.repo.osgi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanNameAware; + +public class BndWrapper extends org.argeo.slc.repo.osgi.BndWrapper implements BeanNameAware { + private final static Log log = LogFactory.getLog(BndWrapper.class); + + @Override + public void setBeanName(String name) { + if (getName() == null) { + setName(name); + } else { + if (!name.contains("#")) + log.warn("Using explicitely set name " + getName() + " and not bean name " + name); + } + } + +} diff --git a/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/MavenWrapper.java b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/MavenWrapper.java new file mode 100644 index 000000000..f351a5b84 --- /dev/null +++ b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/MavenWrapper.java @@ -0,0 +1,20 @@ +package org.argeo.slc.spring.repo.osgi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanNameAware; + +public class MavenWrapper extends org.argeo.slc.repo.osgi.MavenWrapper implements BeanNameAware { + private final static Log log = LogFactory.getLog(MavenWrapper.class); + + @Override + public void setBeanName(String name) { + if (getName() == null) { + setName(name); + } else { + if (!name.contains("#")) + log.warn("Using explicitely set name " + getName() + " and not bean name " + name); + } + } + +} diff --git a/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/UriWrapper.java b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/UriWrapper.java new file mode 100644 index 000000000..1b5edd12e --- /dev/null +++ b/org.argeo.slc.spring/src/org/argeo/slc/spring/repo/osgi/UriWrapper.java @@ -0,0 +1,20 @@ +package org.argeo.slc.spring.repo.osgi; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanNameAware; + +public class UriWrapper extends org.argeo.slc.repo.osgi.UriWrapper implements BeanNameAware { + private final static Log log = LogFactory.getLog(UriWrapper.class); + + @Override + public void setBeanName(String name) { + if (getName() == null) { + setName(name); + } else { + if (!name.contains("#")) + log.warn("Using explicitely set name " + getName() + " and not bean name " + name); + } + } + +} diff --git a/org.argeo.slc.spring/src/org/argeo/slc/spring/unit/ExecutionFlowDescriptorTestUtils.java b/org.argeo.slc.spring/src/org/argeo/slc/spring/unit/ExecutionFlowDescriptorTestUtils.java index a78662f97..f85849267 100644 --- a/org.argeo.slc.spring/src/org/argeo/slc/spring/unit/ExecutionFlowDescriptorTestUtils.java +++ b/org.argeo.slc.spring/src/org/argeo/slc/spring/unit/ExecutionFlowDescriptorTestUtils.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.Map; import org.argeo.slc.core.execution.DefaultExecutionSpec; -import org.argeo.slc.core.test.BasicTestData; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionSpecAttribute; import org.argeo.slc.execution.RefSpecAttribute; @@ -29,6 +28,7 @@ import org.argeo.slc.execution.RefValueChoice; import org.argeo.slc.primitive.PrimitiveAccessor; import org.argeo.slc.primitive.PrimitiveSpecAttribute; import org.argeo.slc.primitive.PrimitiveValue; +import org.argeo.slc.runtime.test.BasicTestData; public class ExecutionFlowDescriptorTestUtils { public static ExecutionFlowDescriptor createSimpleExecutionFlowDescriptor() { -- 2.39.2