This is related to . I'm trying to dynamically add the maven-ant-tasks jars with Grape, simulating this:
<taskdef uri="antlib:org.apache.maven.artifact.ant"
resource="org/apache/maven/artifact/ant/antlib.xml"
classpathref="ant.classpath" />
I've tried to use Grape.grab() to make maven-ant-tasks available to AntBuilder like this:
import groovy.grape.Grape
println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9')
println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )
but that doesn't work because Grape adds the modules to a different ClassLoader from the one that ANT engine is using. So, I took the advice from this AntBuilder classpath question and made Grape use the root ClassLoader:
import groovy.grape.Grape
println "grab..."
Grape.grab(group:'ant', module:'ant', version:'1.7.0', classLoader:this.class.classLoader.rootLoader)
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.0.9', classLoader: this.class.classLoader.rootLoader)
println "ant taskdef..."
def ant = new AntBuilder()
ant.taskdef (resource: "org/apache/maven/artifact/ant/antlib.xml" )
Now it throws a LinkageError:
Caught: : java.lang.LinkageError: loader constraint violation: when resolving overridden method "org.apache.tools.ant.helper.ProjectHelper2$RootHandler.setDocumentLocator(Lorg/xml/sax/Locator;)V" the class loader (instance of org/codehaus/groovy/tools/RootLoader) of the current class, org/apache/tools/ant/helper/ProjectHelper2$RootHandler, and its superclass loader (instance of <bootloader>), have different Class objects for the type org/xml/sax/Locator used in the signature
at test.mavenanttasks.run(mavenanttasks.groovy:11)
Any hints on getting this to work? Or, is the whole thing a bad idea?
I found this: http://groovy.codehaus.org/Using+Ant+Libraries+with+AntBuilder
First, put maven-ant-tasks in the root classloader with:
#Grapes([
#Grab(group = 'org.apache.maven', module = 'maven-ant-tasks', version = '2.1.3'),
#GrabConfig(systemClassLoader = true)
])
Alternatively, for older versions of Groovy:
Grape.grab(group: 'org.apache.maven', module: 'maven-ant-tasks', version: '2.1.3', classLoader: this.class.classLoader.rootLoader)
The Maven ANT tasks are an 'AntLib', and they can be loaded like this:
import groovy.xml.NamespaceBuilder
def ant = new AntBuilder()
def mvn = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.maven.artifact.ant')
We can create ant path(classpath) using java.net.URLClassLoader or it's subclass
eg:
<!-- language: groovy -->
#Grapes([
#Grab(group='org.jacoco', module='org.jacoco.ant', version= '0.7.4.201502262128'),
#Grab(group='org.jacoco', module='org.jacoco.core', version= '0.7.4.201502262128'),
#Grab('org.jacoco:org.jacoco.report:0.7.4.201502262128'),
])
class Tool {
def dump(args){
println "do dump...:$args"
println "DumpTask:"+org.jacoco.ant.DumpTask.classLoader;
def ant = new AntBuilder();
def path1 = ant.path{
org.jacoco.ant.DumpTask.classLoader.getURLs().each {
ant.pathelement(location:it.getFile())
}
}
println "path11:$path1";
// classname way
// ant.taskdef(name:"dump",classname:"org.jacoco.ant.DumpTask",classpath:path1);
// ant.dump(args);
//namespace way
ant.taskdef(uri:'antlib:org.jacoco.ant',resource:'org/jacoco/ant/antlib.xml',classpath:path1);
def jacoco=groovy.xml.NamespaceBuilder.newInstance(ant, 'antlib:org.jacoco.ant')
jacoco.dump(args);
}
}
Related
Here is simple request I try to do and watch response
def httpReq = new HTTPBuilder("http://${url}")
httpReq.request(Method.GET, ContentType.JSON) {
response.success = { resp ->
println("Ok " + resp.status.toString())
}
response.failure = { resp ->
println("Not ok" + resp.status.toString())
}
This returns an Error:
java.lang.ClassNotFoundException: org.apache.commons.collections.iterators.ArrayIterator
I think that ArrayIterator defined in jdk. I added manually org.apache.commons:commons-collections4:4.4 but it doesn't help.
TL;DR
Don't waste your time by gathering deps. Use a build tool like Gradle
or Maven - or use Groovys Grapes if only a script is needed and Groovy
is installed (or easily installable) on your target.
Using grape
You have to pick up all the transitive dependencies (this means the correct packages with the correct versions). E.g. with #Grab:
#Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7.1')
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder('http://www.google.com')
def html = http.get( path : '/search', query : [q:'Groovy'] )
If you really want to gather all the deps manually grape can also
help. It can tell you, what jars are needed:
% grape resolve org.codehaus.groovy.modules.http-builder http-builder 0.7.1
$HOME/.groovy/grapes/org.codehaus.groovy.modules.http-builder/http-builder/jars/http-builder-0.7.1.jar
$HOME/.groovy/grapes/org.apache.httpcomponents/httpclient/jars/httpclient-4.2.1.jar
$HOME/.groovy/grapes/org.apache.httpcomponents/httpcore/jars/httpcore-4.2.1.jar
$HOME/.groovy/grapes/commons-logging/commons-logging/jars/commons-logging-1.1.1.jar
$HOME/.groovy/grapes/commons-codec/commons-codec/jars/commons-codec-1.6.jar
$HOME/.groovy/grapes/net.sf.json-lib/json-lib/jars/json-lib-2.3-jdk15.jar
$HOME/.groovy/grapes/commons-beanutils/commons-beanutils/jars/commons-beanutils-1.8.0.jar
$HOME/.groovy/grapes/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar
$HOME/.groovy/grapes/commons-lang/commons-lang/jars/commons-lang-2.4.jar
$HOME/.groovy/grapes/net.sf.ezmorph/ezmorph/jars/ezmorph-1.0.6.jar
$HOME/.groovy/grapes/net.sourceforge.nekohtml/nekohtml/jars/nekohtml-1.9.16.jar
$HOME/.groovy/grapes/xerces/xercesImpl/jars/xercesImpl-2.9.1.jar
$HOME/.groovy/grapes/xml-apis/xml-apis/jars/xml-apis-1.3.04.jar
$HOME/.groovy/grapes/xml-resolver/xml-resolver/jars/xml-resolver-1.2.jar
From this list you can build up your own classpath to pass to groovy and
work without grape. E.g.:
% cat no-grape.groovy
import groovyx.net.http.HTTPBuilder
def http = new HTTPBuilder('http://www.google.com')
def html = http.get( path : '/search', query : [q:'Groovy'] )
% groovy -cp `grape resolve org.codehaus.groovy.modules.http-builder http-builder 0.7.1 | paste -s -d:` no-grape.groovy
...
I'm trying to define variables in another groovy script that I want to use in my current script. I have two scripts like this:
script1.groovy
thing = evaluate(new File("script2.groovy"))
thing.setLocalEnv()
println(state)
script2.groovy
static def setLocalEnv(){
def state = "hi"
def item = "hey"
}
When I println(state), I get a missing property exception. Basically I want script2 to have config variables that I can load in the context of script1. How can I do this?
I'm not sure what/how you want to do exactly, but I guess you can achieve your goal using one of the class available in groovy dynamique scripting capabilities: groovy.lang.Binding or GroovyClassLoader or GroovyScriptEngine, here is an example using GroovyShell class:
abstract class MyScript extends Script {
String name
String greet() {
"Hello, $name!"
}
}
import org.codehaus.groovy.control.CompilerConfiguration
def config = new CompilerConfiguration()
config.scriptBaseClass = 'MyScript'
def shell = new GroovyShell(this.class.classLoader, new Binding(), config)
def script = shell.parse('greet()')
assert script instanceof MyScript
script.setName('covfefe')
assert script.run() == 'Hello, covfefe!'
This is one way to bind a variable to an external script file, more examples from the doc:
http://docs.groovy-lang.org/latest/html/documentation/guide-integrating.html
P.S. Loading external file can be done with GroovyClassLoader:
def gcl = new GroovyClassLoader()
def clazz2 = gcl.parseClass(new File(file.absolutePath))
Hope this helps.
I want to run some dynamic script with help of Groovyshell. But, i don't want to write new keyword in dynamic script. So, i thought of adding a CompilerConfiguration with Newify keyword. But, things are not working as expected.
CompilerConfiguration configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(
new ASTTransformationCustomizer(
[pattern: "[A-Za-z0-9].*"],
Newify
))
GroovyShell shell = new GroovyShell(profile, configuration)
Still i am getting error
Cannot find matching method sample#BoundingRegion(int, int, int, int)
where BoundingRegion is a class
Perhaps you need to provide more information. This works for me:
import org.codehaus.groovy.control.*
import org.codehaus.groovy.control.customizers.*
def script = '''
class Main {
static main(args) {
assert BigInteger.new(42).toString() == '42' // Ruby style
assert BigDecimal('3.14').toString() == '3.14' // Python style matching regex
}
}
'''
def configuration = new CompilerConfiguration()
configuration.addCompilationCustomizers(
new ASTTransformationCustomizer(
[pattern: "[A-Za-z0-9].*"],
Newify
))
new GroovyShell(configuration).evaluate(script)
I am trying to create a script library and compile a groovy class as described in https://stackoverflow.com/a/35498212/9997207
Groovy Script
import groovy.json.*
import com.eviware.soapui.*
class ScriptLibrary {
def context
def testRunner
def log
def boolean setHeaderValues(userId, password){
try{
loginTestStep = testRunner.testCase.testSuite.testCases["SetHeaderParameters"].testSteps["SetHeaderParametersJsonRequest"]
def request = loginTestStep.getPropertyValue("Request").toString()
def jsonReq = new JsonSlurper().parseText(request);
def builder = new JsonBuilder(jsonReq)
builder.content.userId=userId
builder.content.password=password
def jsonReqAsString = JsonOutput.toJson(jsonReq)
loginTestStep.setPropertyValue("Request",jsonReqAsString)
def contextJsonRequest = new WsdlTestRunContext(loginTestStep);
loginTestStep.run(testRunner,contextJsonRequest)
def response = loginTestStep.getPropertyValue("Response").toString()
def jsonResponse = new JsonSlurper().parseText(response);
def accessTokenFromResponse = jsonResponse.accessToken.toString()
def userPermissionFromResponse = jsonResponse.userPermissionIds.toString()
def userIdFromResponse = jsonResponse.userId.toString()
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_ID", userIdFromResponse)
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_PERMISSION", userPermissionFromResponse)
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_ACCESS_TOKEN", accessTokenFromResponse)
log.info "Header set with values "+userIdFromResponse+":::"+userPermissionFromResponse+":::"+accessTokenFromResponse
setHeader = true
}
return setHeader
}
catch (Exception ex) {
log.info "Header Not Set " +ex
setHeader = false
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_ID", "")
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_USER_PERMISSION", "")
testRunner.testCase.testSuite.project.setPropertyValue("HEADER_ACCESS_TOKEN", "")
return setHeader
}
}
}
Getting following compilation error while trying to compile the groovy script from the command prompt
C:\Path\apache-groovy-binary-2.5.1\groovy-2.5.1\bin\GroovyScripts>groovy ScriptLibrary.groovy
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
C:\Path\apache-groovy-binary-2.5.1\groovy-2.5.1\bin\GroovyScripts\ScriptLibrary.groovy: 20: unable to resolve class WsdlTestRunContext
# line 20, column 26.
def contextJsonRequest = new WsdlTestRunContext(loginTestStep);
^
1 error
You have to include soupui-{version}.jar file in the classpath to resolve this dependency issue. You can find it in SoapUI-{version}/bin folder. Let's say that SoapUI 5.4.0 is located in /tmp/SoapUI-5.4.0/. In this case I can compile a script with following command:
groovyc -d classes -cp ".:/tmp/SoapUI-5.4.0/bin/soapui-5.4.0.jar" script.groovy
Keep in mind that this command is run from the folder where script.groovy is located and compiled class can be found in ./classes/script.class
Trying to use the commons-vfs sync ant task from Groovy. Solved most of the things, but still having some issues. Here is my groovy script:
#Grapes([
#Grab(group='org.apache.commons', module='commons-vfs2', version='2.0'),
#Grab(group='com.jcraft', module='jsch', version='0.1.53'),
#GrabConfig(systemClassLoader = true)
])
import groovy.xml.NamespaceBuilder
import groovy.io.FileType
localRootDir = 'forUpdateSite'
updateServer = 'some.remote.server.com'
remoteRootDir = '/var/www/directory'
println("Syncing files from ${localRootDir} to ${updateServer} ${remoteRootDir}");
def ant = new AntBuilder()
def vfs = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.commons.vfs2.tasks')
def remoteURI = "sftp://username:{FAKEENCRYPTEDPASSWORD}#${updateServer}${remoteRootDir}"
vfs.sync (destdir: remoteURI) {
src() {
file: localRootDir
}
}
At this point the only thing I am missing is how to specify the local directory and files. This example gives me this stack trace:
Syncing files from forUpdateSite to some.remote.server.com /var/www/directory
Caught: : No source file specified.
: No source file specified.
at org.apache.commons.vfs2.tasks.AbstractSyncTask.addConfiguredSrc(AbstractSyncTask.java:149)
at org.apache.tools.ant.IntrospectionHelper$AddNestedCreator.istore(IntrospectionHelper.java:1469)
at org.apache.tools.ant.IntrospectionHelper$AddNestedCreator.store(IntrospectionHelper.java:1463)
at org.apache.tools.ant.IntrospectionHelper$Creator.store(IntrospectionHelper.java:1370)
at org.apache.tools.ant.UnknownElement.handleChild(UnknownElement.java:582)
at org.apache.tools.ant.UnknownElement.handleChildren(UnknownElement.java:349)
at org.apache.tools.ant.UnknownElement.configure(UnknownElement.java:201)
at org.apache.tools.ant.UnknownElement.maybeConfigure(UnknownElement.java:163)
at syncToUpdateSite.run(syncToUpdateSite.groovy:53)
Turned out to be pretty simple:
#Grapes([
#Grab(group='org.apache.commons', module='commons-vfs2', version='2.0'),
#Grab(group='com.jcraft', module='jsch', version='0.1.53'),
#GrabConfig(systemClassLoader = true)
])
import groovy.xml.NamespaceBuilder
import groovy.io.FileType
localRootDir = 'forUpdateSite'
updateServer = 'some.remote.server.com'
remoteRootDir = '/var/www/directory'
println("Syncing files from ${localRootDir} to ${updateServer} ${remoteRootDir}");
def ant = new AntBuilder()
def vfs = NamespaceBuilder.newInstance(ant, 'antlib:org.apache.commons.vfs2.tasks')
def remoteURI = "sftp://username:{FAKEENCRYPTEDPASSWORD}#${updateServer}${remoteRootDir}"
vfs.sync (destdir: remoteURI,
src: localRootDir)
Note that you have to include the jsch module with #Grab for the sftp URL parsing to work. I was getting the stack trace below before I included that.
Caught: : Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
: Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
at org.apache.commons.vfs2.tasks.AbstractSyncTask.execute(AbstractSyncTask.java:227)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:291)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at syncToUpdateSite.run(syncToUpdateSite.groovy:52)
Caused by: org.apache.commons.vfs2.FileSystemException: Badly formed URI "sftp://username:***#some.remote.server.com/var/www/directory".
at org.apache.commons.vfs2.provider.url.UrlFileProvider.findFile(UrlFileProvider.java:91)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:713)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:649)
at org.apache.commons.vfs2.impl.DefaultFileSystemManager.resolveFile(DefaultFileSystemManager.java:636)
at org.apache.commons.vfs2.tasks.VfsTask.resolveFile(VfsTask.java:56)
at org.apache.commons.vfs2.tasks.AbstractSyncTask.handleFiles(AbstractSyncTask.java:247)
at org.apache.commons.vfs2.tasks.AbstractSyncTask.execute(AbstractSyncTask.java:218)
... 3 more
Caused by: java.net.MalformedURLException: unknown protocol: sftp
at org.apache.commons.vfs2.provider.url.UrlFileProvider.findFile(UrlFileProvider.java:72)
... 9 more