() {
38 | @Override
39 | public int compare(RemoteTestNGFactory o1, RemoteTestNGFactory o2) {
40 | // the newest first
41 | return o2.getOrder() - o1.getOrder();
42 | }
43 | });
44 |
45 | return factories.get(0);
46 | }
47 |
48 | public static RemoteTestNGFactory getFirstQuietly(String version) {
49 | return getFirstQuietly(Version.parseVersion(version));
50 | }
51 |
52 | /**
53 | * Get the first RemoteTestNGFactory on classpath.
54 | *
55 | * this implementation is diff with {@link #getFirst(Version)} that
56 | * it scans the JARs on the classpath, and parse the services file manually.
57 | *
58 | * @param version
59 | * @return
60 | * @throws TestNGException if not found
61 | */
62 | public static RemoteTestNGFactory getFirstQuietly(Version version) {
63 | ClassLoader cl = RemoteTestNGFactory.class.getClassLoader();
64 | if (cl instanceof URLClassLoader) {
65 | for (URL url : ((URLClassLoader) cl).getURLs()) {
66 | File f = new File(url.getFile());
67 | // only check for jar file name starts with 'testng-remote'
68 | if (f.isFile() && f.getName().startsWith("testng-remote")) {
69 | try (JarFile jarFile = new JarFile(f)) {
70 | JarEntry entry = jarFile.getJarEntry("META-INF/services/" + RemoteTestNGFactory.class.getName());
71 | if (entry != null) {
72 | ArrayList names = new ArrayList<>();
73 |
74 | try (BufferedReader r = new BufferedReader(
75 | new InputStreamReader(jarFile.getInputStream(entry), "utf-8"))) {
76 | int lc = 1;
77 | while ((lc = parseLine(RemoteTestNGFactory.class, url, r, lc, names)) >= 0) {
78 | // noop
79 | }
80 |
81 | for (String name : names) {
82 | Class> c = Class.forName(name, false, cl);
83 | RemoteTestNGFactory factory = (RemoteTestNGFactory) c.newInstance();
84 | if (factory.accept(version)) {
85 | return factory;
86 | }
87 | }
88 | }
89 | }
90 | } catch (TestNGException ex) {
91 | throw ex;
92 | } catch (Exception ex) {
93 | if (RemoteTestNG.isDebug()) {
94 | ex.printStackTrace();
95 | }
96 | }
97 | }
98 | }
99 | }
100 |
101 | throw new TestNGException(version + " is not a supported TestNG version");
102 | }
103 |
104 | // Parse a single line from the given configuration file, adding the name
105 | // on the line to the names list.
106 | //
107 | private static int parseLine(Class> service, URL u, BufferedReader r, int lc, List names)
108 | throws IOException, ServiceConfigurationError {
109 | String ln = r.readLine();
110 | if (ln == null) {
111 | return -1;
112 | }
113 | int ci = ln.indexOf('#');
114 | if (ci >= 0) {
115 | ln = ln.substring(0, ci);
116 | }
117 | ln = ln.trim();
118 | int n = ln.length();
119 | if (n != 0) {
120 | if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0)) {
121 | fail(service, u, lc, "Illegal configuration-file syntax");
122 | }
123 | int cp = ln.codePointAt(0);
124 | if (!Character.isJavaIdentifierStart(cp)) {
125 | fail(service, u, lc, "Illegal provider-class name: " + ln);
126 | }
127 | for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
128 | cp = ln.codePointAt(i);
129 | if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) {
130 | fail(service, u, lc, "Illegal provider-class name: " + ln);
131 | }
132 | }
133 | if (!names.contains(ln)) {
134 | names.add(ln);
135 | }
136 | }
137 | return lc + 1;
138 | }
139 |
140 | private static void fail(Class> service, String msg) throws ServiceConfigurationError {
141 | throw new ServiceConfigurationError(service.getName() + ": " + msg);
142 | }
143 |
144 | private static void fail(Class> service, URL u, int line, String msg) throws ServiceConfigurationError {
145 | fail(service, u + ":" + line + ": " + msg);
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/remote/src/main/java/org/testng/remote/AbstractRemoteTestNG.java:
--------------------------------------------------------------------------------
1 | package org.testng.remote;
2 |
3 | import org.testng.CommandLineArgs;
4 | import org.testng.ISuite;
5 | import org.testng.ISuiteListener;
6 | import org.testng.ITestNGListener;
7 | import org.testng.ITestRunnerFactory;
8 | import org.testng.TestNG;
9 | import org.testng.remote.strprotocol.*;
10 | import org.testng.xml.XmlSuite;
11 |
12 | /**
13 | * Extension of TestNG registering a remote TestListener.
14 | *
15 | * @author Cedric Beust
16 | */
17 | public abstract class AbstractRemoteTestNG extends TestNG implements IRemoteTestNG {
18 | private static final String LOCALHOST = "localhost";
19 |
20 | protected ITestRunnerFactory m_customTestRunnerFactory;
21 | private String m_host;
22 |
23 | /** Port used for the string protocol */
24 | private Integer m_port = null;
25 |
26 | /** Port used for the serialized protocol */
27 | private Integer m_serPort = null;
28 |
29 | /** Protocol used for inter-communication */
30 | private String m_protocol;
31 |
32 | private boolean m_debug;
33 |
34 | private boolean m_dontExit;
35 |
36 | private boolean m_ack;
37 |
38 | @Override
39 | public void dontExit(boolean dontExit) {
40 | m_dontExit = dontExit;
41 | }
42 |
43 | @Override
44 | public void setDebug(boolean debug) {
45 | m_debug = debug;
46 | }
47 |
48 | @Override
49 | public void setAck(boolean ack) {
50 | m_ack = ack;
51 | }
52 |
53 | @Override
54 | public void setHost(String host) {
55 | m_host = defaultIfStringEmpty(host, LOCALHOST);
56 | }
57 |
58 | @Override
59 | public void setSerPort(Integer serPort) {
60 | m_serPort = serPort;
61 | }
62 |
63 | @Override
64 | public void setProtocol(String protocol) {
65 | m_protocol = protocol;
66 | }
67 |
68 | @Override
69 | public void setPort(Integer port) {
70 | m_port = port;
71 | }
72 |
73 | @Override
74 | public void configure(CommandLineArgs cla) {
75 | super.configure(cla);
76 | }
77 |
78 | public static void validateCommandLineParameters(CommandLineArgs args) {
79 | TestNG.validateCommandLineParameters(args);
80 | }
81 |
82 | public static String defaultIfStringEmpty(String s, String defaultValue) {
83 | return isStringEmpty(s) ? defaultValue : s;
84 | }
85 |
86 | public static boolean isStringEmpty(String s) {
87 | return s == null || "".equals(s);
88 | }
89 |
90 | @Override
91 | public void run() {
92 | IMessageSender sender = getMessageSender();
93 | final MessageHub msh = new MessageHub(sender);
94 | msh.setDebug(m_debug);
95 | try {
96 | msh.connect();
97 |
98 | initialize();
99 |
100 | if (canRun()) {
101 | int testCount = 0;
102 |
103 | for (XmlSuite suite : m_suites) {
104 | testCount += suite.getTests().size();
105 | }
106 |
107 | GenericMessage gm = new GenericMessage();
108 | gm.setSuiteCount(m_suites.size());
109 | gm.setTestCount(testCount);
110 | msh.sendMessage(gm);
111 |
112 | super.addListener((ITestNGListener) new RemoteSuiteListener(msh));
113 | setTestRunnerFactory(createDelegatingTestRunnerFactory(buildTestRunnerFactory(), msh));
114 |
115 | super.run();
116 | }
117 | else {
118 | System.err.println("No test suite found. Nothing to run");
119 | }
120 | }
121 | catch(Throwable cause) {
122 | cause.printStackTrace(System.err);
123 | }
124 | finally {
125 | // System.out.println("RemoteTestNG finishing: " + (getEnd() - getStart()) + " ms");
126 | msh.shutDown();
127 | if (! m_debug && ! m_dontExit) {
128 | System.exit(0);
129 | }
130 | }
131 | }
132 |
133 | protected void initialize() {
134 | // We couldn't do this until now in debug mode since the .xml file didn't exist yet.
135 | // Now that we have connected with the Eclipse client, we know that it created the .xml
136 | // file so we can proceed with the initialization
137 | initializeSuitesAndJarFile();
138 | }
139 |
140 | /**
141 | * run after {@link #initialize()}, tell if it's ready for running the test
142 | *
143 | * @return {@code true} for ready.
144 | */
145 | protected boolean canRun() {
146 | return m_suites.size() > 0;
147 | }
148 |
149 | private IMessageSender getMessageSender() {
150 | if (m_protocol != null) {
151 | switch (m_protocol) {
152 | case "object":
153 | return new SerializedMessageSender(m_host, m_serPort, m_ack);
154 | case "string":
155 | return new StringMessageSender(m_host, m_port);
156 | case "json":
157 | return new JsonMessageSender(m_host, m_serPort, m_ack);
158 | case "stdout":
159 | return new StdoutMessageSender();
160 | default:
161 | throw new IllegalArgumentException("unrecognized protocol: " + m_protocol);
162 | }
163 | }
164 |
165 | // fall back to original behaviour
166 | return m_serPort != null
167 | ? new SerializedMessageSender(m_host, m_serPort, m_ack)
168 | : new StringMessageSender(m_host, m_port);
169 | }
170 |
171 | /**
172 | * Override by the plugin if you need to configure differently the TestRunner
173 | * (usually this is needed if different listeners/reporters are needed).
174 | * Note: you don't need to worry about the wiring listener, because it is added
175 | * automatically.
176 | */
177 | protected abstract ITestRunnerFactory buildTestRunnerFactory();
178 |
179 | protected String getHost() {
180 | return m_host;
181 | }
182 |
183 | protected int getPort() {
184 | return m_port;
185 | }
186 |
187 | /** A ISuiteListener wiring the results using the internal string-based protocol. */
188 | private static class RemoteSuiteListener implements ISuiteListener {
189 | private final MessageHub m_messageSender;
190 |
191 | RemoteSuiteListener(MessageHub smsh) {
192 | m_messageSender= smsh;
193 | }
194 |
195 | @Override
196 | public void onFinish(ISuite suite) {
197 | m_messageSender.sendMessage(new SuiteMessage(suite, false /*start*/));
198 | }
199 |
200 | @Override
201 | public void onStart(ISuite suite) {
202 | m_messageSender.sendMessage(new SuiteMessage(suite, true /*start*/));
203 | }
204 | }
205 |
206 | protected abstract ITestRunnerFactory createDelegatingTestRunnerFactory(ITestRunnerFactory trf, MessageHub smsh);
207 | }
208 |
--------------------------------------------------------------------------------
/remote/src/main/java/org/testng/xml/ResultContentHandler.java:
--------------------------------------------------------------------------------
1 | package org.testng.xml;
2 |
3 | import static org.testng.reporters.XMLReporterConfig.ATTR_DESC;
4 | import static org.testng.reporters.XMLReporterConfig.ATTR_DURATION_MS;
5 | import static org.testng.reporters.XMLReporterConfig.ATTR_NAME;
6 | import static org.testng.reporters.XMLReporterConfig.ATTR_STATUS;
7 | import static org.testng.reporters.XMLReporterConfig.TAG_CLASS;
8 | import static org.testng.reporters.XMLReporterConfig.TAG_PARAMS;
9 | import static org.testng.reporters.XMLReporterConfig.TAG_SUITE;
10 | import static org.testng.reporters.XMLReporterConfig.TAG_TEST;
11 | import static org.testng.reporters.XMLReporterConfig.TAG_TEST_METHOD;
12 |
13 | import java.util.List;
14 |
15 | import org.testng.ITestResult;
16 | import org.testng.collections.Lists;
17 | import org.testng.remote.strprotocol.GenericMessage;
18 | import org.testng.remote.strprotocol.IRemoteSuiteListener;
19 | import org.testng.remote.strprotocol.IRemoteTestListener;
20 | import org.testng.remote.strprotocol.SuiteMessage;
21 | import org.testng.remote.strprotocol.TestMessage;
22 | import org.testng.remote.strprotocol.TestResultMessage;
23 | import org.testng.reporters.XMLReporterConfig;
24 | import org.xml.sax.Attributes;
25 | import org.xml.sax.helpers.DefaultHandler;
26 |
27 | /**
28 | * Parses testng-result.xml, create TestResultMessages and send them back to the listener
29 | * as we encounter them.
30 | *
31 | * @author Cedric Beust
32 | */
33 | public class ResultContentHandler extends DefaultHandler {
34 | private int m_suiteMethodCount = 0;
35 | private int m_testMethodCount = 0;
36 | private SuiteMessage m_currentSuite;
37 | private TestMessage m_currentTest;
38 | private String m_className;
39 | private int m_passed;
40 | private int m_failed;
41 | private int m_skipped;
42 | private int m_invocationCount;
43 | private int m_currentInvocationCount;
44 | private TestResultMessage m_currentTestResult;
45 | private IRemoteSuiteListener m_suiteListener;
46 | private IRemoteTestListener m_testListener;
47 | private List m_params = null;
48 |
49 | public ResultContentHandler(IRemoteSuiteListener suiteListener,
50 | IRemoteTestListener testListener, boolean resolveClasses /* ignored */) {
51 | m_suiteListener = suiteListener;
52 | m_testListener = testListener;
53 | }
54 |
55 | @Override
56 | public void startElement (String uri, String localName,
57 | String qName, Attributes attributes) {
58 | p("Start " + qName);
59 | if (TAG_SUITE.equals(qName)) {
60 | m_suiteListener.onInitialization(new GenericMessage());
61 | m_suiteMethodCount = 0;
62 | m_currentSuite = new SuiteMessage(attributes.getValue(ATTR_NAME),
63 | true /* start */, m_suiteMethodCount);
64 | m_suiteListener.onStart(m_currentSuite);
65 | } else if (TAG_TEST.equals(qName)) {
66 | m_passed = m_failed = m_skipped = 0;
67 | m_currentTest = new TestMessage(true /* start */, m_currentSuite.getSuiteName(),
68 | attributes.getValue(ATTR_NAME), m_testMethodCount,
69 | m_passed, m_failed, m_skipped, 0);
70 | m_testListener.onStart(m_currentTest);
71 | } else if (TAG_CLASS.equals(qName)) {
72 | m_className = attributes.getValue(ATTR_NAME);
73 | } else if (TAG_TEST_METHOD.equals(qName)) {
74 | Integer status = XMLReporterConfig.getStatus(attributes.getValue(ATTR_STATUS));
75 | m_currentTestResult = new TestResultMessage(status, m_currentSuite.getSuiteName(),
76 | m_currentTest.getTestName(), m_className, attributes.getValue(ATTR_NAME),
77 | attributes.getValue(ATTR_DESC),
78 | attributes.getValue(ATTR_DESC),
79 | new String[0], /* no parameters, filled later */
80 | 0, Long.parseLong(attributes.getValue(ATTR_DURATION_MS)),
81 | "" /* stack trace, filled later */,
82 | m_invocationCount, m_currentInvocationCount);
83 | m_suiteMethodCount++;
84 | m_testMethodCount++;
85 | if (status == ITestResult.SUCCESS) m_passed++;
86 | else if (status == ITestResult.FAILURE) m_failed++;
87 | else if (status == ITestResult.SKIP) m_skipped++;
88 | } else if (TAG_PARAMS.equals(qName)) {
89 | m_params = Lists.newArrayList();
90 | }
91 | }
92 |
93 | @Override
94 | public void characters(char[] ch, int start, int length) {
95 | if (m_params != null) {
96 | String string = new String(ch, start, length);
97 | String parameter = string;
98 | if (parameter.trim().length() != 0) {
99 | m_params.add(parameter);
100 | }
101 | }
102 | }
103 |
104 | @Override
105 | public void endElement (String uri, String localName, String qName) {
106 | if (TAG_SUITE.equals(qName)) {
107 | m_suiteListener.onFinish(new SuiteMessage(null, false /* end */, m_suiteMethodCount));
108 | m_currentSuite = null;
109 | } else if (TAG_TEST.equals(qName)) {
110 | m_currentTest = new TestMessage(false /* start */, m_currentSuite.getSuiteName(),
111 | null, m_testMethodCount,
112 | m_passed, m_failed, m_skipped, 0);
113 | m_testMethodCount = 0;
114 | m_testListener.onFinish(m_currentTest);
115 | } else if (TAG_CLASS.equals(qName)) {
116 | m_className = null;
117 | } else if (TAG_TEST_METHOD.equals(qName)) {
118 | switch(m_currentTestResult.getResult()) {
119 | case ITestResult.SUCCESS:
120 | m_testListener.onTestSuccess(m_currentTestResult);
121 | break;
122 | case ITestResult.FAILURE:
123 | m_testListener.onTestFailure(m_currentTestResult);
124 | break;
125 | case ITestResult.SKIP:
126 | m_testListener.onTestSkipped(m_currentTestResult);
127 | break;
128 | default:
129 | p("Ignoring test status:" + m_currentTestResult.getResult());
130 | }
131 | }
132 | else if (TAG_PARAMS.equals(qName)) {
133 | String[] params = new String[m_params.size()];
134 | for (int i = 0; i < m_params.size(); i++) {
135 | // The parameters are encoded as type:value. Since we only care about the
136 | // value (and we don't receive the type anyway), use a dummy character in
137 | // its place
138 | params[i] = "@:" + m_params.get(i);
139 | }
140 | m_currentTestResult.setParameters(params);
141 | m_params = null;
142 | }
143 | }
144 |
145 | private static void p(String string) {
146 | if (false) {
147 | System.out.println("[ResultContentHandler] " + string);
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
50 | if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
124 |
125 | FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% ^
162 | %JVM_CONFIG_MAVEN_PROPS% ^
163 | %MAVEN_OPTS% ^
164 | %MAVEN_DEBUG_OPTS% ^
165 | -classpath %WRAPPER_JAR% ^
166 | "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
167 | %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
168 | if ERRORLEVEL 1 goto error
169 | goto end
170 |
171 | :error
172 | set ERROR_CODE=1
173 |
174 | :end
175 | @endlocal & set ERROR_CODE=%ERROR_CODE%
176 |
177 | if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
178 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
179 | if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
180 | if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
181 | :skipRcPost
182 |
183 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
184 | if "%MAVEN_BATCH_PAUSE%"=="on" pause
185 |
186 | if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
187 |
188 | cmd /C exit /B %ERROR_CODE%
189 |
--------------------------------------------------------------------------------
/remote/src/main/java/org/testng/remote/strprotocol/AbstractRemoteTestRunnerClient.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2000, 2004 IBM Corporation and others.
3 | * All rights reserved. This program and the accompanying materials
4 | * are made available under the terms of the Common Public License v1.0
5 | * which accompanies this distribution, and is available at
6 | * http://www.eclipse.org/legal/cpl-v10.html
7 | *
8 | * Contributors:
9 | * IBM Corporation - initial API and implementation
10 | * Julien Ruaux: jruaux@octo.com
11 | * Vincent Massol: vmassol@octo.com
12 | *
13 | * Adapted by:
14 | * Alexandru Popescu: the_mindstorm@evolva.ro
15 | ******************************************************************************/
16 | package org.testng.remote.strprotocol;
17 |
18 |
19 | import org.testng.TestNGException;
20 |
21 | import java.io.IOException;
22 | import java.net.ServerSocket;
23 | import java.net.Socket;
24 |
25 | /**
26 | * The client side of the RemoteTestRunner. Handles the
27 | * marshaling of the different messages.
28 | */
29 | public abstract class AbstractRemoteTestRunnerClient {
30 | /**
31 | * An array of listeners that are informed about test events.
32 | */
33 | protected IRemoteSuiteListener[] m_suiteListeners;
34 | protected IRemoteTestListener[] m_testListeners;
35 |
36 | /**
37 | * The server socket
38 | */
39 | private ServerSocket fServerSocket;
40 | private Socket fSocket;
41 | private ServerConnection m_serverConnection;
42 | // private PrintWriter m_outputWriter;
43 | // private BufferedReader m_inputReader;
44 |
45 | /**
46 | * Start listening to a test run. Start a server connection that
47 | * the RemoteTestRunner can connect to.
48 | */
49 | public synchronized void startListening(IRemoteSuiteListener[] suiteListeners,
50 | IRemoteTestListener[] testListeners,
51 | ServerConnection serverConnection) {
52 | m_suiteListeners= suiteListeners;
53 | m_testListeners= testListeners;
54 | m_serverConnection = serverConnection;
55 |
56 | serverConnection.start();
57 | }
58 |
59 | public IRemoteSuiteListener[] getSuiteListeners() {
60 | return m_suiteListeners;
61 | }
62 |
63 | public IRemoteTestListener[] getTestListeners() {
64 | return m_testListeners;
65 | }
66 |
67 | private synchronized void shutdown() {
68 | // if(m_outputWriter != null) {
69 | // m_outputWriter.close();
70 | // m_outputWriter = null;
71 | // }
72 | // try {
73 | // if(m_inputReader != null) {
74 | // m_inputReader.close();
75 | // m_inputReader = null;
76 | // }
77 | // }
78 | // catch(IOException e) {
79 | // e.printStackTrace();
80 | // }
81 | try {
82 | if(fSocket != null) {
83 | fSocket.close();
84 | fSocket = null;
85 | }
86 | }
87 | catch(IOException e) {
88 | e.printStackTrace();
89 | }
90 | try {
91 | if(fServerSocket != null) {
92 | fServerSocket.close();
93 | fServerSocket = null;
94 | }
95 | }
96 | catch(IOException e) {
97 | e.printStackTrace();
98 | }
99 | }
100 |
101 | public boolean isRunning() {
102 | return m_serverConnection.getMessageSender() != null;
103 | }
104 |
105 | /**
106 | * Requests to stop the remote test run.
107 | */
108 | public synchronized void stopTest() {
109 | if(isRunning()) {
110 | m_serverConnection.getMessageSender().sendStop();
111 | shutdown();
112 | }
113 | }
114 |
115 | // private String readMessage(BufferedReader in) throws IOException {
116 | // return in.readLine();
117 | // }
118 | //
119 | // private void receiveMessage(String message) {
120 | // int messageType = MessageHelper.getMessageType(message);
121 | //
122 | // try {
123 | // if(messageType < MessageHelper.SUITE) {
124 | // // Generic message
125 | // GenericMessage gm = MessageHelper.unmarshallGenericMessage(message);
126 | // notifyStart(gm);
127 | // }
128 | // else if(messageType < MessageHelper.TEST) {
129 | // // Suite message
130 | // SuiteMessage sm = MessageHelper.createSuiteMessage(message);
131 | // notifySuiteEvents(sm);
132 | // }
133 | // else if(messageType < MessageHelper.TEST_RESULT) {
134 | // // Test message
135 | // TestMessage tm = MessageHelper.createTestMessage(message);
136 | // notifyTestEvents(tm);
137 | // }
138 | // else {
139 | // // TestResult message
140 | // TestResultMessage trm = MessageHelper.unmarshallTestResultMessage(message);
141 | // notifyResultEvents(trm);
142 | // }
143 | // }
144 | // finally {
145 | // if(isRunning() && (null != m_outputWriter)) {
146 | // m_outputWriter.println(MessageHelper.ACK_MSG);
147 | // m_outputWriter.flush();
148 | // }
149 | // }
150 | // }
151 |
152 | protected abstract void notifyStart(final GenericMessage genericMessage);
153 |
154 | protected abstract void notifySuiteEvents(final SuiteMessage suiteMessage);
155 |
156 | protected abstract void notifyTestEvents(final TestMessage testMessage);
157 |
158 | protected abstract void notifyResultEvents(final TestResultMessage testResultMessage);
159 |
160 |
161 | /**
162 | * Reads the message stream from the RemoteTestRunner
163 | */
164 | public abstract class ServerConnection extends Thread {
165 | private MessageHub m_messageHub;
166 |
167 | public ServerConnection(IMessageSender messageMarshaller) {
168 | super("TestNG - ServerConnection"); //$NON-NLS-1$
169 | m_messageHub = new MessageHub(messageMarshaller);
170 | }
171 |
172 | IMessageSender getMessageSender() {
173 | return m_messageHub != null ? m_messageHub.getMessageSender() : null;
174 | }
175 |
176 | @Override
177 | public void run() {
178 | try {
179 | IMessage message = m_messageHub.receiveMessage();
180 | while (message != null) {
181 | switch (message.getType()) {
182 | case GENERIC:
183 | notifyStart((GenericMessage) message);
184 | break;
185 | case SUITE:
186 | notifySuiteEvents((SuiteMessage) message);
187 | break;
188 | case TEST:
189 | notifyTestEvents((TestMessage) message);
190 | break;
191 | case TEST_RESULT:
192 | notifyResultEvents((TestResultMessage) message);
193 | break;
194 | default:
195 | throw new TestNGException("Unknown message type:" + message);
196 | }
197 | // if (isRunning()) {
198 | // m_messageMarshaller.sendAck();
199 | // }
200 | message = m_messageHub.receiveMessage();
201 | }
202 | }
203 | finally {
204 | m_messageHub.shutDown();
205 | m_messageHub = null;
206 | }
207 | // try {
208 | // fServerSocket = new ServerSocket(fServerPort);
209 | // fSocket = fServerSocket.accept();
210 | // try {
211 | // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream(),
212 | // "UTF-8")); //$NON-NLS-1$
213 | // }
214 | // catch(UnsupportedEncodingException e) {
215 | // m_inputReader = new BufferedReader(new InputStreamReader(fSocket.getInputStream()));
216 | // }
217 | // try {
218 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream(), "UTF-8"),
219 | // true);
220 | // }
221 | // catch(UnsupportedEncodingException e1) {
222 | // m_outputWriter = new PrintWriter(new OutputStreamWriter(fSocket.getOutputStream()), true);
223 | // }
224 | // String message;
225 | // while((m_inputReader != null) && ((message = readMessage(m_inputReader)) != null)) {
226 | // receiveMessage(message);
227 | // }
228 | // }
229 | // catch(SocketException e) {
230 | // handleThrowable(e);
231 | // }
232 | // catch(IOException e) {
233 | // handleThrowable(e);
234 | // }
235 | // finally {
236 | // shutdown();
237 | // }
238 | }
239 |
240 | protected abstract void handleThrowable(Throwable cause);
241 | }
242 |
243 | }
244 |
--------------------------------------------------------------------------------
/remote-test/src/test/groovy/Tester.groovy:
--------------------------------------------------------------------------------
1 | @Grab(group = 'org.osgi', module = 'osgi.core', version = '6.0.0')
2 | @Grab(group = 'org.testng.testng-remote', module = 'testng-remote', version = '1.5.1')
3 |
4 | import org.osgi.framework.Version
5 | import org.testng.remote.strprotocol.JsonMessageSender
6 |
7 | //
8 | // global var
9 | //
10 |
11 | // need to download the classifier jar for versions <= 5.11
12 | classifierVer = new Version("5.11")
13 |
14 | groovyVer = System.getProperty("GROOVY_VERSION") ?: "2.3.11"
15 | ivyVer = System.getProperty("IVY_VERSION") ?: "2.3.0"
16 | testngRemoteVer = System.getProperty("PROJECT_VERSION") ?: "1.5.1"
17 | jcmdVer = "1.48"
18 | slf4jVer = "1.7.32"
19 |
20 | workingDir = new File(System.getProperty("user.dir"))
21 | if (System.getProperty("PROJECT_BASEDIR")) {
22 | workingDir = new File(System.getProperty("PROJECT_BASEDIR"))
23 | }
24 |
25 | println "\t:::"
26 | println "\t::: workingDir: ${workingDir}"
27 | println "\t::: testng remote version: ${testngRemoteVer}"
28 | println "\t::: groovy version: ${groovyVer}"
29 | println "\t::: ivy version: ${ivyVer}"
30 | println "\t:::"
31 |
32 | scriptDir = new File(workingDir.absolutePath + "/src/test/groovy")
33 |
34 | mvnRepoDir = System.getenv("HOME") + "/.m2/repository"
35 |
36 | groovyJar = "${mvnRepoDir}/org/codehaus/groovy/groovy-all/${groovyVer}/groovy-all-${groovyVer}.jar"
37 | // ivy is required for groovy @Grab annotation
38 | ivyJar = "${mvnRepoDir}/org/apache/ivy/ivy/${ivyVer}/ivy-${ivyVer}.jar"
39 |
40 | grapeRepoDir = System.getenv("HOME") + "/.groovy/grapes"
41 |
42 | remoteTestngJar = "${grapeRepoDir}/org.testng.testng-remote/testng-remote-dist/jars/testng-remote-dist-${testngRemoteVer}-shaded.jar"
43 | jcmdJar = "${grapeRepoDir}/com.beust/jcommander/jars/jcommander-${jcmdVer}.jar"
44 | slf4jJar = "${grapeRepoDir}/org.slf4j/slf4j-api/jars/slf4j-api-${slf4jVer}.jar"
45 |
46 | resultSet = new HashMap()
47 |
48 | //~~
49 |
50 |
51 | def startTime = System.currentTimeMillis()
52 | def metadata = new XmlSlurper().parse("https://repo1.maven.org/maven2/org/testng/testng/maven-metadata.xml")
53 |
54 | def versionBlackList = ['6.12', '6.13', '6.14.0-RC2', '6.14.0-RC3', '7.0.0-beta2', '7.0.0-beta4', '7.1.0', '7.1.1']
55 | if (System.getProperty('java.version').startsWith('1.7')) {
56 | versionBlackList.add('7.*')
57 | }
58 |
59 | metadata.versioning.versions.version.each { version ->
60 | println ">>>>>"
61 | println ">>>>> Testing ${version}"
62 | println ">>>>>"
63 |
64 | // skip invalid testng jar
65 | for (def bver : versionBlackList) {
66 | if (version.toString().matches(bver)) {
67 | println "skip testing ${version} \n"
68 | return
69 | }
70 | }
71 |
72 | def exitValue = runTestNGTest(version)
73 | def rset = resultSet[exitValue]
74 | if (rset == null) {
75 | rset = new ArrayList()
76 | resultSet[exitValue] = rset
77 | }
78 | rset << version
79 |
80 | println "<<<<<"
81 | println ">>>>> Tested ${version}: result=${exitValue}"
82 | println "<<<<<\n"
83 | }
84 |
85 | println "\nCompleted in " + (System.currentTimeMillis() - startTime) + " (ms)"
86 |
87 |
88 | println "\nSummary report:"
89 | resultSet.each {
90 | switch (it.key) {
91 | case 0:
92 | println it.key + " - PASSED:"
93 | break;
94 | case 1:
95 | println it.key + " - unsupported version detected:"
96 | break;
97 | case 2:
98 | println it.key + " - NoClassDefFoundError:"
99 | break;
100 | default:
101 | println it.key + " - OTHERS:"
102 | }
103 |
104 | println "\t" + it.value
105 | }
106 | println ""
107 |
108 | // failed if there's any OTHER failures
109 | assert resultSet[-1] == null
110 |
111 | def minVer = new Version("6.0")
112 | resultSet[1].each {
113 | // no version >= 6.0 will get error 'unsupported version detected'
114 | assert (toVersion(it.toString()).compareTo(minVer) < 0)
115 | }
116 | resultSet[2].each {
117 | // no version >= 6.5.1 will get error 'NoClassDefFoundError'
118 | assert (toVersion(it.toString()).compareTo(minVer) < 0)
119 | }
120 |
121 | /**
122 | * run the testng test with groovy in a separate process
123 | *
124 | * @param ver the testng version
125 | * @return 0 - success; 1 - unsupported version detected; 2 - NoClassDefFoundError; -1 - others;
126 | */
127 | def runTestNGTest(ver) {
128 | if (downloadTestNG(ver) != 0) {
129 | println "failed to download jars for ${ver}, skip testing"
130 | return -1
131 | }
132 |
133 | def port = 12345
134 | def msgHub = new JsonMessageSender("localhost", port)
135 | Thread.start {
136 | msgHub.initReceiver()
137 | }
138 |
139 | try {
140 | def testngJar = "${grapeRepoDir}/org.testng/testng/jars/testng-${ver}.jar"
141 | if (toVersion(ver.toString()).compareTo(classifierVer) <= 0) {
142 | testngJar = "${grapeRepoDir}/org.testng/testng/jars/testng-${ver}-jdk15.jar"
143 | }
144 |
145 | println "classpath: ${groovyJar}:${ivyJar}:${remoteTestngJar}:${testngJar}:${jcmdJar}:${slf4jJar}\n"
146 |
147 | def scriptFile = new File(scriptDir, "TestNGTest.groovy")
148 | // run the groovy script via Java executable rather than groovy executable, because:
149 | // 1) groovy has RootLoader loads groovy distributed testng jar, which is in prior to our own jar;
150 | // 2) groovy @Grad can't specify the order of the jar on the classpath,
151 | // while testng-remote need to be on front of testng
152 | // (since some older version of testng jar contains older version of RemoteTestNG)
153 | def output = new StringBuilder()
154 | def process = new ProcessBuilder(
155 | "java",
156 | "-classpath", "${groovyJar}:${ivyJar}:${remoteTestngJar}:${testngJar}:${jcmdJar}:${slf4jJar}",
157 | "-Dtestng.eclipse.verbose",
158 | "-Dtestng.eclipse.debug",
159 | "groovy.ui.GroovyMain",
160 | scriptFile.absolutePath,
161 | "json", "" + port)
162 | .directory(workingDir).redirectErrorStream(true).start()
163 | process.inputStream.eachLine { println it; output << it.toString() }
164 | process.waitFor();
165 | def exitValue = process.exitValue()
166 | if (exitValue == 0) {
167 | return 0
168 | } else {
169 | if (output.contains("is not a supported TestNG version")) {
170 | return 1
171 | } else if (output.contains("java.lang.NoClassDefFoundError")) {
172 | return 2;
173 | } else {
174 | return -1
175 | }
176 | }
177 | } finally {
178 | msgHub.stopReceiver()
179 | }
180 | }
181 |
182 | /**
183 | * start a new process to download the dep jars,
184 | * since @Grad can't specify the order of the jars on the classpath
185 | * while we do want to make testng-remote on front of testng jar
186 | * that's why we not put @Grab in the TestNGTest.groovy
187 | *
188 | * @param ver the testng version
189 | * @return 0 - success, otherwise - failure
190 | */
191 | def downloadTestNG(ver) {
192 | def grabScriptFile = new File(scriptDir, "grabJar_${ver}.groovy")
193 |
194 | grabScriptFile.withWriter { w ->
195 | w << "@GrabResolver(name = 'jcenter', root = 'http://jcenter.bintray.com/')" + "\n"
196 |
197 | if (toVersion(ver.toString()).compareTo(classifierVer) > 0) {
198 | w << "@Grab(group = 'org.testng', module = 'testng', version = '${ver}')" + "\n"
199 | } else {
200 | w << "@Grab(group = 'org.testng', module = 'testng', version = '${ver}', classifier = 'jdk15')" + "\n"
201 | }
202 |
203 | w << "@GrabExclude('com.google.guava:guava')" + "\n"
204 |
205 | w << "@Grab(group = 'com.beust', module = 'jcommander', version = '${jcmdVer}')" + "\n"
206 | w << "@Grab(group = 'org.slf4j', module = 'slf4j-api', version = '${slf4jVer}')" + "\n"
207 | w << "@Grab(group = 'org.testng.testng-remote', module = 'testng-remote-dist', version = '${testngRemoteVer}', classifier = 'shaded')" + "\n"
208 |
209 | w << "import org.testng.annotations.Test;" + "\n"
210 | }
211 |
212 | try {
213 | def grapeProc = new ProcessBuilder(
214 | "java",
215 | "-classpath", "${groovyJar}:${ivyJar}",
216 | "groovy.ui.GroovyMain",
217 | grabScriptFile.absolutePath)
218 | .directory(workingDir).redirectErrorStream(true).start()
219 | grapeProc.inputStream.eachLine { println it }
220 | grapeProc.waitFor();
221 | return grapeProc.exitValue()
222 | } finally {
223 | grabScriptFile.delete()
224 | }
225 | }
226 |
227 | def Version toVersion(String ver) {
228 | if ("5.5.m".equals(ver)) {
229 | ver = "5.5"
230 | }
231 | def idx = ver.indexOf("-")
232 | if (idx > 0) {
233 | ver = ver.substring(0, idx)
234 | }
235 | return new Version(ver)
236 | }
237 |
--------------------------------------------------------------------------------
/remote/src/main/java/org/testng/remote/strprotocol/BaseMessageSender.java:
--------------------------------------------------------------------------------
1 | package org.testng.remote.strprotocol;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.BufferedWriter;
5 | import java.io.Closeable;
6 | import java.io.IOException;
7 | import java.io.InputStream;
8 | import java.io.InputStreamReader;
9 | import java.io.OutputStream;
10 | import java.io.OutputStreamWriter;
11 | import java.io.PrintWriter;
12 | import java.io.UnsupportedEncodingException;
13 | import java.net.ConnectException;
14 | import java.net.InetSocketAddress;
15 | import java.net.ServerSocket;
16 | import java.net.Socket;
17 | import java.net.SocketTimeoutException;
18 |
19 | import org.testng.TestNGException;
20 |
21 | import static org.testng.remote.RemoteTestNG.isVerbose;
22 | import static org.testng.remote.RemoteTestNG.isDebug;
23 |
24 | abstract public class BaseMessageSender implements IMessageSender {
25 | protected Socket m_clientSocket;
26 | private String m_host;
27 | private int m_port;
28 | protected Object m_ackLock = new Object();
29 |
30 | private boolean m_requestStopReceiver;
31 | private ServerSocket m_serverSocket;
32 | /** Outgoing message stream. */
33 | protected OutputStream m_outStream;
34 | /** Used to send ACK and STOP */
35 | private PrintWriter m_outWriter;
36 |
37 | /** Incoming message stream. */
38 | protected volatile InputStream m_inStream;
39 | /** Used to receive ACK and STOP */
40 | protected volatile BufferedReader m_inReader;
41 |
42 | private ReaderThread m_readerThread;
43 | private boolean m_ack;
44 | // protected InputStream m_receiverInputStream;
45 |
46 | public BaseMessageSender(String host, int port, boolean ack) {
47 | m_host = host;
48 | m_port = port;
49 | m_ack = ack;
50 | }
51 |
52 | /**
53 | * Starts the connection.
54 | *
55 | * @throws TestNGException if an exception occurred while establishing the connection
56 | */
57 | @Override
58 | public void connect() throws IOException {
59 | p("Waiting for Eclipse client on " + m_host + ":" + m_port);
60 | while (true) {
61 | try {
62 | m_clientSocket = new Socket();
63 | m_clientSocket.connect(new InetSocketAddress(m_host, m_port), 60 * 1000);
64 | p("Received a connection from Eclipse on " + m_host + ":" + m_port);
65 |
66 | // Output streams
67 | m_outStream = m_clientSocket.getOutputStream();
68 | m_outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(m_outStream)));
69 |
70 | // Input streams
71 | m_inStream = m_clientSocket.getInputStream();
72 | try {
73 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream,
74 | "UTF-8")); //$NON-NLS-1$
75 | }
76 | catch(UnsupportedEncodingException ueex) {
77 | // Should never happen
78 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream));
79 | }
80 |
81 | p("Connection established, starting reader thread");
82 | m_readerThread = new ReaderThread();
83 | m_readerThread.start();
84 | return;
85 | }
86 | catch(SocketTimeoutException | ConnectException ex) {
87 | p("connect failed: " + ex.toString());
88 | // ignore and retry
89 | try {
90 | Thread.sleep(4000);
91 | }
92 | catch(InterruptedException handled) {
93 | Thread.currentThread().interrupt();
94 | }
95 | }
96 | }
97 | }
98 |
99 | private void sendAdminMessage(String message) {
100 | m_outWriter.println(message);
101 | m_outWriter.flush();
102 | }
103 |
104 | private int m_serial = 0;
105 |
106 | @Override
107 | public void sendAck() {
108 | p("Sending ACK " + m_serial);
109 | // Note: adding the serial at the end of this message causes a lock up if interacting
110 | // with TestNG 5.14 and older (reported by JetBrains). The following git commit:
111 | // 5730bdfb33ec7a8bf4104852cd4a5f2875ba8267
112 | // changed equals() to startsWith().
113 | // It's ok to add this serial back for debugging, but don't commit it until JetBrains
114 | // confirms they no longer need backward compatibility with 5.14.
115 | sendAdminMessage(MessageHelper.ACK_MSG); // + m_serial++);
116 | }
117 |
118 | @Override
119 | public void sendStop() {
120 | sendAdminMessage(MessageHelper.STOP_MSG);
121 | }
122 |
123 | @Override
124 | public void initReceiver() throws SocketTimeoutException {
125 | if (m_inStream != null) {
126 | p("Receiver already initialized");
127 | }
128 | try {
129 | p("initReceiver on port " + m_port);
130 | m_serverSocket = new ServerSocket(m_port);
131 | m_serverSocket.setSoTimeout(5000);
132 |
133 | Socket socket = null;
134 | while (!m_requestStopReceiver) {
135 | try {
136 | if (isDebug()) {
137 | p("polling the client connection");
138 | }
139 | socket = m_serverSocket.accept();
140 | // break the loop once the first client connected
141 | break;
142 | }
143 | catch (IOException ioe) {
144 | try {
145 | Thread.sleep(100L);
146 | }
147 | catch (InterruptedException ie) {
148 | // Do nothing.
149 | }
150 | }
151 | }
152 | if (socket != null) {
153 | m_inStream = socket.getInputStream();
154 | m_inReader = new BufferedReader(new InputStreamReader(m_inStream));
155 | m_outStream = socket.getOutputStream();
156 | m_outWriter = new PrintWriter(new OutputStreamWriter(m_outStream));
157 | }
158 | }
159 | catch(SocketTimeoutException ste) {
160 | throw ste;
161 | }
162 | catch (IOException ioe) {
163 | closeQuietly(m_serverSocket);
164 | }
165 | }
166 |
167 | public void stopReceiver() {
168 | m_requestStopReceiver = true;
169 | try {
170 | if (!m_serverSocket.isClosed()) {
171 | m_serverSocket.close();
172 | }
173 | } catch (IOException e) {
174 | if (isDebug()) {
175 | e.printStackTrace();
176 | }
177 | }
178 | p("Stopped receiver");
179 | }
180 |
181 | @Override
182 | public void shutDown() {
183 | closeQuietly(m_outStream);
184 | m_outStream = null;
185 |
186 | if (null != m_readerThread) {
187 | m_readerThread.interrupt();
188 | }
189 |
190 | closeQuietly(m_inReader);
191 | m_inReader = null;
192 |
193 | closeQuietly(m_clientSocket);
194 | m_clientSocket = null;
195 | }
196 |
197 | private void closeQuietly(Closeable c) {
198 | if (c != null) {
199 | try {
200 | c.close();
201 | } catch (IOException e) {
202 | if (isDebug()) {
203 | e.printStackTrace();
204 | }
205 | }
206 | }
207 | }
208 |
209 | private String m_latestAck;
210 |
211 | protected void waitForAck() {
212 | if (m_ack) {
213 | try {
214 | p("Message sent, waiting for ACK...");
215 | synchronized(m_ackLock) {
216 | m_ackLock.wait();
217 | }
218 | p("... ACK received:" + m_latestAck);
219 | }
220 | catch(InterruptedException handled) {
221 | Thread.currentThread().interrupt();
222 | }
223 | }
224 | }
225 |
226 | private static void p(String msg) {
227 | if (isVerbose()) {
228 | System.out.println("[BaseMessageSender] " + msg); //$NON-NLS-1$
229 | }
230 | }
231 |
232 | /**
233 | * Reader thread that processes messages from the client.
234 | */
235 | private class ReaderThread extends Thread {
236 |
237 | public ReaderThread() {
238 | super("ReaderThread"); //$NON-NLS-1$
239 | }
240 |
241 | @Override
242 | public void run() {
243 | try {
244 | p("ReaderThread waiting for an admin message");
245 | String message = m_inReader.readLine();
246 | p("ReaderThread received admin message:" + message);
247 | while (message != null) {
248 | if (isDebug()) {
249 | p("Admin message:" + message); //$NON-NLS-1$
250 | }
251 | boolean acknowledge = message.startsWith(MessageHelper.ACK_MSG);
252 | boolean stop = MessageHelper.STOP_MSG.equals(message);
253 | if(acknowledge || stop) {
254 | if (acknowledge) {
255 | p("Received ACK:" + message);
256 | m_latestAck = message;
257 | }
258 | synchronized(m_ackLock) {
259 | m_ackLock.notifyAll();
260 | }
261 | if (stop) {
262 | break;
263 | }
264 | } else {
265 | p("Received unknown message: '" + message + "'");
266 | }
267 | message = m_inReader != null ? m_inReader.readLine() : null;
268 | }
269 | // while((m_reader != null) && (message = m_reader.readLine()) != null) {
270 | // if (m_debug) {
271 | // p("Admin message:" + message); //$NON-NLS-1$
272 | // }
273 | // boolean acknowledge = MessageHelper.ACK_MSG.equals(message);
274 | // boolean stop = MessageHelper.STOP_MSG.equals(message);
275 | // if(acknowledge || stop) {
276 | // synchronized(m_lock) {
277 | // m_lock.notifyAll();
278 | // }
279 | // if (stop) {
280 | // break;
281 | // }
282 | // }
283 | // }
284 | }
285 | catch(IOException ioe) {
286 | if (isVerbose()) {
287 | ioe.printStackTrace();
288 | }
289 | }
290 | }
291 | }
292 | }
293 |
--------------------------------------------------------------------------------
/remote/src/main/java/org/testng/remote/strprotocol/MessageHelper.java:
--------------------------------------------------------------------------------
1 | package org.testng.remote.strprotocol;
2 |
3 |
4 | import org.testng.ITestResult;
5 | import org.testng.collections.Lists;
6 |
7 | import java.util.List;
8 | import java.util.regex.Pattern;
9 |
10 |
11 | /**
12 | * Marshal/unmarshal tool for IStringMessages.
13 | *
14 | * @author Alexandru Popescu
15 | */
16 | public class MessageHelper {
17 | public static final char DELIMITER = '\u0001';
18 | public static final char PARAM_DELIMITER = '\u0004';
19 | private static final char LINE_SEP_DELIMITER_1 = '\u0002';
20 | private static final char LINE_SEP_DELIMITER_2 = '\u0003';
21 |
22 | public static final int GENERIC_SUITE_COUNT = 1;
23 |
24 | public static final int SUITE = 10;
25 | public static final int SUITE_START = 11;
26 | public static final int SUITE_FINISH = 12;
27 |
28 | public static final int TEST = 100;
29 | public static final int TEST_START = 101;
30 | public static final int TEST_FINISH = 102;
31 |
32 | public static final int TEST_RESULT = 1000;
33 | public static final int PASSED_TEST = TEST_RESULT + ITestResult.SUCCESS;
34 | public static final int FAILED_TEST = TEST_RESULT + ITestResult.FAILURE;
35 | public static final int SKIPPED_TEST = TEST_RESULT + ITestResult.SKIP;
36 | public static final int FAILED_ON_PERCENTAGE_TEST = TEST_RESULT + ITestResult.SUCCESS_PERCENTAGE_FAILURE;
37 | public static final int TEST_STARTED = TEST_RESULT + ITestResult.STARTED;
38 |
39 | public static final String STOP_MSG = ">STOP";
40 | public static final String ACK_MSG = ">ACK";
41 |
42 | public static int getMessageType(final String message) {
43 | int idx = message.indexOf(DELIMITER);
44 |
45 | return idx == -1 ? Integer.parseInt(message) : Integer.parseInt(message.substring(0, idx));
46 | }
47 |
48 | public static GenericMessage unmarshallGenericMessage(final String message) {
49 | String[] messageParts = parseMessage(message);
50 | if(messageParts.length == 1) {
51 | return new GenericMessage(MessageType.fromValue(messageParts[0]));
52 | }
53 | else {
54 | GenericMessage result = new GenericMessage(MessageType.fromValue(messageParts[0]));
55 |
56 | for(int i = 1; i < messageParts.length; i+=2) {
57 | if ("testCount".equals(messageParts[i])) {
58 | result.setTestCount(Integer.parseInt(messageParts[i + 1]));
59 | } else if ("suiteCount".equals(messageParts[i])) {
60 | result.setSuiteCount(Integer.parseInt(messageParts[i + 1]));
61 | }
62 | }
63 |
64 | return result;
65 | }
66 | }
67 |
68 | public static SuiteMessage createSuiteMessage(final String message) {
69 | int type = getMessageType(message);
70 | String[] messageParts = parseMessage(message);
71 |
72 | SuiteMessage result = new SuiteMessage(messageParts[1],
73 | MessageHelper.SUITE_START == type,
74 | Integer.parseInt(messageParts[2]));
75 | // Any excluded methods?
76 | if (messageParts.length > 3) {
77 | int count = Integer.parseInt(messageParts[3]);
78 | if (count > 0) {
79 | List methods = Lists.newArrayList();
80 | int i = 4;
81 | while (count-- > 0) {
82 | methods.add(messageParts[i++]);
83 | }
84 | result.setExcludedMethods(methods);
85 | }
86 | }
87 |
88 | return result;
89 | }
90 |
91 | public static TestMessage createTestMessage(final String message) {
92 | int type = getMessageType(message);
93 | String[] messageParts = parseMessage(message);
94 |
95 | return new TestMessage(MessageHelper.TEST_START == type,
96 | messageParts[1],
97 | messageParts[2],
98 | Integer.parseInt(messageParts[3]),
99 | Integer.parseInt(messageParts[4]),
100 | Integer.parseInt(messageParts[5]),
101 | Integer.parseInt(messageParts[6]),
102 | Integer.parseInt(messageParts[7]));
103 | }
104 |
105 | public static TestResultMessage unmarshallTestResultMessage(final String message) {
106 | String[] messageParts = parseMessage(message);
107 |
108 | String parametersFragment= null;
109 | String startTimestampFragment= null;
110 | String stopTimestampFragment= null;
111 | String stackTraceFragment= null;
112 | String testDescriptor= null;
113 | switch(messageParts.length) {
114 | case 10:
115 | {
116 | parametersFragment= messageParts[5];
117 | startTimestampFragment= messageParts[6];
118 | stopTimestampFragment= messageParts[7];
119 | stackTraceFragment= messageParts[8];
120 | testDescriptor= messageParts[9];
121 | }
122 | break;
123 | case 9:
124 | {
125 | parametersFragment= messageParts[5];
126 | startTimestampFragment= messageParts[6];
127 | stopTimestampFragment= messageParts[7];
128 | stackTraceFragment= messageParts[8];
129 | }
130 | break;
131 | default:
132 | {
133 | // HINT: old protocol without parameters
134 | parametersFragment= null;
135 | startTimestampFragment= messageParts[5];
136 | stopTimestampFragment= messageParts[6];
137 | stackTraceFragment= messageParts[7];
138 | }
139 | }
140 | return new TestResultMessage(Integer.parseInt(messageParts[0]),
141 | messageParts[1],
142 | messageParts[2],
143 | messageParts[3],
144 | messageParts[4],
145 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)),
146 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(testDescriptor)),
147 | parseParameters(parametersFragment),
148 | Long.parseLong(startTimestampFragment),
149 | Long.parseLong(stopTimestampFragment),
150 | replaceAsciiCharactersWithUnicode(replaceNewLineReplacer(stackTraceFragment)),
151 | 0, 0 /* invocation counts not supported by this protocol */
152 | );
153 | }
154 |
155 | public static String replaceNewLine(String message) {
156 | if(null == message) {
157 | return message;
158 | }
159 |
160 | return message.replace('\n', LINE_SEP_DELIMITER_1).replace('\r', LINE_SEP_DELIMITER_2);
161 | }
162 |
163 | public static String replaceUnicodeCharactersWithAscii(String message) {
164 | if(null == message) {
165 | return message;
166 | }
167 |
168 | return replace(
169 | replace(
170 | replace(
171 | replace(message, "\u0004", "\\u0004"),
172 | "\u0003", "\\u0003"),
173 | "\u0002", "\\u0002"),
174 | "\u0001", "\\u0001");
175 | }
176 |
177 | public static String replaceAsciiCharactersWithUnicode(String message) {
178 | if(null == message) {
179 | return message;
180 | }
181 |
182 | return replace(
183 | replace(
184 | replace(
185 | replace(message, "\\u0004", "\u0004"),
186 | "\\u0003", "\u0003"),
187 | "\\u0002", "\u0002"),
188 | "\\u0001", "\u0001");
189 | }
190 |
191 | public static String replaceNewLineReplacer(String message) {
192 | if(null == message) {
193 | return message;
194 | }
195 |
196 | return message.replace(LINE_SEP_DELIMITER_1, '\n').replace(LINE_SEP_DELIMITER_2, '\r');
197 | }
198 |
199 | private static String[] parseParameters(final String messagePart) {
200 | return tokenize(messagePart, PARAM_DELIMITER);
201 | }
202 |
203 | private static String[] parseMessage(final String message) {
204 | return tokenize(message, DELIMITER);
205 | }
206 |
207 | private static String[] tokenize(final String message, final char separator) {
208 | if(null == message) {
209 | return new String[0];
210 | }
211 |
212 | List tokens = Lists.newArrayList();
213 | int start = 0;
214 | for(int i = 0; i < message.length(); i++) {
215 | if(separator == message.charAt(i)) {
216 | tokens.add(message.substring(start, i));
217 | start = i + 1;
218 | }
219 | }
220 | if(start < message.length()) {
221 | tokens.add(message.substring(start, message.length()));
222 | }
223 |
224 | return tokens.toArray(new String[tokens.size()]);
225 | }
226 |
227 | /**
228 | * Implementation according to JDK5 String.replace(CharSequence,CharSequence)
229 | */
230 | private static final String replace(String original, CharSequence target, CharSequence replacement) {
231 | return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(original)
232 | .replaceAll(quoteReplacement(replacement.toString()));
233 | }
234 |
235 | /**
236 | * Implementation according to JDK5 String.replace(CharSequence,CharSequence)
237 | */
238 | private static String quoteReplacement(String s) {
239 | if ((s.indexOf('\\') == -1) && (s.indexOf('$') == -1)) {
240 | return s;
241 | }
242 | StringBuffer sb = new StringBuffer();
243 | for (int i=0; i \(.*\)$'`
87 | if expr "$link" : '/.*' > /dev/null; then
88 | PRG="$link"
89 | else
90 | PRG="`dirname "$PRG"`/$link"
91 | fi
92 | done
93 |
94 | saveddir=`pwd`
95 |
96 | M2_HOME=`dirname "$PRG"`/..
97 |
98 | # make it fully qualified
99 | M2_HOME=`cd "$M2_HOME" && pwd`
100 |
101 | cd "$saveddir"
102 | # echo Using m2 at $M2_HOME
103 | fi
104 |
105 | # For Cygwin, ensure paths are in UNIX format before anything is touched
106 | if $cygwin ; then
107 | [ -n "$M2_HOME" ] &&
108 | M2_HOME=`cygpath --unix "$M2_HOME"`
109 | [ -n "$JAVA_HOME" ] &&
110 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
111 | [ -n "$CLASSPATH" ] &&
112 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
113 | fi
114 |
115 | # For Mingw, ensure paths are in UNIX format before anything is touched
116 | if $mingw ; then
117 | [ -n "$M2_HOME" ] &&
118 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
121 | fi
122 |
123 | if [ -z "$JAVA_HOME" ]; then
124 | javaExecutable="`which javac`"
125 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
126 | # readlink(1) is not available as standard on Solaris 10.
127 | readLink=`which readlink`
128 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
129 | if $darwin ; then
130 | javaHome="`dirname \"$javaExecutable\"`"
131 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
132 | else
133 | javaExecutable="`readlink -f \"$javaExecutable\"`"
134 | fi
135 | javaHome="`dirname \"$javaExecutable\"`"
136 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
137 | JAVA_HOME="$javaHome"
138 | export JAVA_HOME
139 | fi
140 | fi
141 | fi
142 |
143 | if [ -z "$JAVACMD" ] ; then
144 | if [ -n "$JAVA_HOME" ] ; then
145 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
146 | # IBM's JDK on AIX uses strange locations for the executables
147 | JAVACMD="$JAVA_HOME/jre/sh/java"
148 | else
149 | JAVACMD="$JAVA_HOME/bin/java"
150 | fi
151 | else
152 | JAVACMD="`\\unset -f command; \\command -v java`"
153 | fi
154 | fi
155 |
156 | if [ ! -x "$JAVACMD" ] ; then
157 | echo "Error: JAVA_HOME is not defined correctly." >&2
158 | echo " We cannot execute $JAVACMD" >&2
159 | exit 1
160 | fi
161 |
162 | if [ -z "$JAVA_HOME" ] ; then
163 | echo "Warning: JAVA_HOME environment variable is not set."
164 | fi
165 |
166 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
167 |
168 | # traverses directory structure from process work directory to filesystem root
169 | # first directory with .mvn subdirectory is considered project base directory
170 | find_maven_basedir() {
171 |
172 | if [ -z "$1" ]
173 | then
174 | echo "Path not specified to find_maven_basedir"
175 | return 1
176 | fi
177 |
178 | basedir="$1"
179 | wdir="$1"
180 | while [ "$wdir" != '/' ] ; do
181 | if [ -d "$wdir"/.mvn ] ; then
182 | basedir=$wdir
183 | break
184 | fi
185 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
186 | if [ -d "${wdir}" ]; then
187 | wdir=`cd "$wdir/.."; pwd`
188 | fi
189 | # end of workaround
190 | done
191 | echo "${basedir}"
192 | }
193 |
194 | # concatenates all lines of a file
195 | concat_lines() {
196 | if [ -f "$1" ]; then
197 | echo "$(tr -s '\n' ' ' < "$1")"
198 | fi
199 | }
200 |
201 | BASE_DIR=`find_maven_basedir "$(pwd)"`
202 | if [ -z "$BASE_DIR" ]; then
203 | exit 1;
204 | fi
205 |
206 | ##########################################################################################
207 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
208 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
209 | ##########################################################################################
210 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
211 | if [ "$MVNW_VERBOSE" = true ]; then
212 | echo "Found .mvn/wrapper/maven-wrapper.jar"
213 | fi
214 | else
215 | if [ "$MVNW_VERBOSE" = true ]; then
216 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
217 | fi
218 | if [ -n "$MVNW_REPOURL" ]; then
219 | jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
220 | else
221 | jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
222 | fi
223 | while IFS="=" read key value; do
224 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
225 | esac
226 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
227 | if [ "$MVNW_VERBOSE" = true ]; then
228 | echo "Downloading from: $jarUrl"
229 | fi
230 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
231 | if $cygwin; then
232 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
233 | fi
234 |
235 | if command -v wget > /dev/null; then
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Found wget ... using wget"
238 | fi
239 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
240 | wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
241 | else
242 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
243 | fi
244 | elif command -v curl > /dev/null; then
245 | if [ "$MVNW_VERBOSE" = true ]; then
246 | echo "Found curl ... using curl"
247 | fi
248 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
249 | curl -o "$wrapperJarPath" "$jarUrl" -f
250 | else
251 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
252 | fi
253 |
254 | else
255 | if [ "$MVNW_VERBOSE" = true ]; then
256 | echo "Falling back to using Java to download"
257 | fi
258 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
259 | # For Cygwin, switch paths to Windows format before running javac
260 | if $cygwin; then
261 | javaClass=`cygpath --path --windows "$javaClass"`
262 | fi
263 | if [ -e "$javaClass" ]; then
264 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
265 | if [ "$MVNW_VERBOSE" = true ]; then
266 | echo " - Compiling MavenWrapperDownloader.java ..."
267 | fi
268 | # Compiling the Java class
269 | ("$JAVA_HOME/bin/javac" "$javaClass")
270 | fi
271 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
272 | # Running the downloader
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Running MavenWrapperDownloader.java ..."
275 | fi
276 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
277 | fi
278 | fi
279 | fi
280 | fi
281 | ##########################################################################################
282 | # End of extension
283 | ##########################################################################################
284 |
285 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
286 | if [ "$MVNW_VERBOSE" = true ]; then
287 | echo $MAVEN_PROJECTBASEDIR
288 | fi
289 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
290 |
291 | # For Cygwin, switch paths to Windows format before running java
292 | if $cygwin; then
293 | [ -n "$M2_HOME" ] &&
294 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
295 | [ -n "$JAVA_HOME" ] &&
296 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
297 | [ -n "$CLASSPATH" ] &&
298 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
299 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
300 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
301 | fi
302 |
303 | # Provide a "standardized" way to retrieve the CLI args that will
304 | # work with both Windows and non-Windows executions.
305 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
306 | export MAVEN_CMD_LINE_ARGS
307 |
308 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
309 |
310 | exec "$JAVACMD" \
311 | $MAVEN_OPTS \
312 | $MAVEN_DEBUG_OPTS \
313 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
314 | "-Dmaven.home=${M2_HOME}" \
315 | "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
316 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
317 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------