load external jar in groovy script in SoapUI - groovy

I need to call a method inside Jar from groovy script inside SoapUI project.
Due to the lack of administrative access I can't place that jar in "../bin/ext" folder in SaopUI intall directory.
So the only option left is load the jar in runtime and call the method. Very simple approach.
I tried the below approach.
this.class.classLoader.rootLoader.addURL(new URL("file:///H://Foo-2//Foo.jar"));
def cls = Class.forName("test").newInstance();
cls.add()
This is not working as rootLoader is null.
second approach .
def classLoader = ClassLoader.systemClassLoader
def newClassLoader = new URLClassLoader([new File("file:///H://Foo-2//Foo.jar")
.toString().toURL()] as URL[], classLoader)
def cls = Class.forName("test").newInstance();
this is not working too , it's giving me ClassNotFoundException.
I spent a day in this. even change the class name to lower case after seeing this thread.
Edit 1
I tried this too. and change my code like this.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
log.info "utils=" + groovyUtils
mystring = "file://H://Baz.jar"
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
def cls = new bar() // how to call the static method add of `bar` class ?
log.info cls
My Jar code is too simple. Here it is
public class bar {
public static void main(String[] args) {
add();
}
public static void add(){
String path = "H:" + File.separator + "Groovy" + File.separator + "hi.txt";
File f = new File(path);
f.getParentFile().mkdirs();
try {
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
}
What all the other option I have? What i am doing wrong?
Solved. Here is the final Groovy script.
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
path = groovyUtils.getProjectPath()
myfile = new java.io.File(path + "/Baz.jar")
mystring = "file://" + path + "/Baz.jar"
log.info "myfile=" + myfile
classpathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
//import Baz
def instance = this.class.classLoader.loadClass( 'bar', true, false )?.newInstance()
instance.add();

Do you know about com.eviware.soapui.support.ClasspathHacker?
Maybe that is away to go about it, if you really cannot put it to the /ext folder.
Reference:
https://community.smartbear.com/t5/SoapUI-Open-Source/Soapui-is-not-loading-external-jar-file-location-added-to/td-p/7619
def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
def classpathHacker = new com.eviware.soapui.support.ClasspathHacker ()
log.info "utils=" + groovyUtils
path = groovyUtils.getProjectPath()
myfile = new java.io.File(path + "/ojdbc14.jar")
mystring = "file://" + path + "/ojdbc14.jar"
log.info "myfile=" + myfile
classpathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addFile( myfile )
com.eviware.soapui.support.ClasspathHacker.addURL( new URL(mystring) )
import groovy.sql.*
def sql = groovy.sql.Sql.newInstance( db, userid, password, 'oracle.jdbc.driver.OracleDriver' )

Related

Using threads to speedup deploying

I am trying to use threads inside my own plugin. I need to deploy 5 files into Artifactory simultaneously to save time.
baseDir.eachFile {
def Thread thread = new Thread(){
public void run(){
def InputStream fileAsInputStream = new File (it.getAbsolutePath()).newInputStream()
def File fileRepoPath = new File (baseDirInRepo, it.getName())
if(!deployRepoMetadata(item.repoPath.repoKey, fileRepoPath, fileAsInputStream)) {
throw new Exception ("Can't deploy " + fileRepoPath + " for package " + item.name)
}
}
}
thread.start()
}
def boolean deployRepoMetadata(String repoKey, File deployPath, InputStream binary) {
def String targetRepoKey = repoKey
def String targetPath = deployPath
def RepoPath deployRepoPath = RepoPathFactory.create(targetRepoKey, targetPath)
repositories.deploy(deployRepoPath, binary)
}
But I've got the following error:
User _system_ is not permitted to deploy
How can I deal with this error?

Error: md5sum: stat '>': No such file or directory

I am trying to write a program that runs the Linux commands using Scala.
I have written a snippet of code to run the functionalities of md5sum command.
Code snippet
object Test extends App {
import sys.process._
case class md5sum_builder private(i: Seq[String]) {
println(i)
protected def this() = this(Seq(""))
def optionCheck() = new md5sum_builder(i :+ "-c")
def files(file: String) = new md5sum_builder(i :+ file)
def hashFile(hashfile: String) = new md5sum_builder(i :+ hashfile)
def assignment(operator: String) = new md5sum_builder(i :+ operator)
def build() = println(("md5sum" + i.mkString(" ")).!!)
}
object md5sum_builder {
def apply() = new md5sum_builder
}
md5sum_builder().files("text.txt").files("text1.txt").assignment(">").hashFile("hashes.md5").build()
}
When I try to run the command md5sum text.txt text1.txt > hashes.md5 using this program, it throws the error:
Error: md5sum: stat '>': No such file or directory
I don't know why. Any way to make it work?
Your interface doesn't appear to be well thought out. Notice that files(), hashFile(), and assignment() all do the same thing. So someone could come along and do something like this ...
md5sum_builder().assignment("text0.txt")
.hashFile("text1.txt")
.files(">") // <--shell redirection won't work
.assignment("hashes.md5")
.build()
... and get the same (non-functional) result as your posted example.
Here's a modification that corrects for that as well as allowing redirected output.
case class md5sum_builder private(i :Seq[String], outfile :String = "/dev/null") {
protected def this() = this(Seq.empty[String])
def optionCheck(file :String) = this.copy(i = i ++ Seq("-c", file))
def file(file: String) = this.copy(i = i :+ file)
def hashFile(file: String) = this.copy(outfile = file)
def build() = println(("md5sum" +: i).#|(Seq("tee", outfile)).!!)
}
Now the methods can be in almost any order and still get the expected results.
md5sum_builder().file("text0.txt")
.hashFile("hashes.md5")
.file("text1.txt")
.build()

Groovy throws MissingPropertyException when calling getter method

I'm writing a small Groovy script for Hybris.
For reasons unknown when I attempt to call .getCronExpression() Groovy tries to get a property named getCron.
Script execution has failed [reason: groovy.lang.MissingPropertyException: No such property: getCron for class: de.hybris.platform.cronjob.model.TriggerModel]
The getter which I try to call exists on the class.
def methods = TriggerModel.declaredMethods.findAll { !it.synthetic }.name
println methods;
//[getDaysOfWeek, getWeekInterval, setDaysOfWeek, setWeekInterval, getRelative, getJob, setActivationTime, setMaxAcceptableDelay, getTimeTable, setActive, setJob, getCronJob, getActivationTime, setDateRange, getDateRange, getMaxAcceptableDelay, getCronExpression, setCronExpression, setCronJob, getActive, setRelative, setDay, setHour, setMinute, setSecond, getHour, getMinute, getSecond, getYear, getMonth, setYear, setMonth, getDay]
Code part:
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} IS true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
}
Update: the project uses hybris 5.7
Replacing the getter with the variable name fixed the issue.
Replace-
def x = at.getCronExpression(); // error
with
def xam = at.cronExpression; // working
Complete working groovy-
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active}='1'");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def xam = at.cronExpression; // working
}
}
Can you share your groovy part where you are loading activeTriggers?
I created a sample groovy to load Triggers and print CronExpression for 1st object and it worked like a charm.
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
flexibleQuery = new FlexibleSearchQuery("select {pk} from {Trigger}");
flexibleSearchService = spring.getBean("flexibleSearchService")
activeTriggers = flexibleSearchService.search(flexibleQuery).getResult();
def at = activeTriggers.get(0);
def x = at.getCronExpression();
OUTPUT
0 0 0/4 * * ? *
AFTER PO EDITED THE QUESTION I still don't see getCronExpression error, I believe you were calling the function on a different object then TriggerModel. Though there were some syntax errors in your groovy, a working version of the copy is as below. (Tested on 1905 version)
import de.hybris.platform.servicelayer.search.FlexibleSearchQuery;
def currentDate = new Date();
def query = new FlexibleSearchQuery("SELECT {pk} FROM {cronjob} WHERE {active} = true");
def result = flexibleSearchService.search(query).getResult();
for (cj in result) {
def activeTriggers = cj.getTriggers().stream().filter{p -> p.getActive()}.collect();
if (activeTriggers){
def at = activeTriggers.get(0);
def activationTS = at.getActivationTime(); // works
if (activationTS!=null && activationTS.before(currentDate)){
println cj.code + " has invalid next activation date set: " + activationTS;
}
def x = at.getCronExpression(); // error
println x;
}
}

antlr4 visitor does not work

I am trying to process .pas file. I generated lexers, parsers, visitors, listeners for grammar
Here is my custom visitor implementation
class GroovyPascalVisitor extends PascalBaseVisitor<ScriptSkeleton> {
private static final String PASCAL_SCRIPT_NAME = "PascalScript"
#Lazy ScriptSkeleton scriptSkeleton = new ScriptSkeleton()
#Override
public ScriptSkeleton visitProgramHeading(
PascalParser.ProgramHeadingContext ctx) {
log.info "Visiting program heading"
def scriptName = ctx.identifier().getText()?.trim()
if (!scriptName) {
scriptName = PASCAL_SCRIPT_NAME +
"${new Random().nextInt(1000)}"
}
scriptSkeleton.scriptName = scriptName
return scriptSkeleton
}
}
Here is the code in my script
def file = new ANTLRFileStream(pas)
def lexer = new PascalLexer(file)
def parser = new PascalParser(new CommonTokenStream(lexer))
tree = parser.program()
stringTree = tree.toStringTree(parser)
visitor = new GroovyPascalVisitor()
skeleton = visitor.visit(tree)
The .pas file content looks like this
program HelloWorld;
begin
writeln('Hello, World!');
end.
But when I run script - it does not println message from log and object scriptSkeleton is null, meaning that it does not invoke visitProgramHeading at all.
What it is the problem?

Modifying the file contents of a zipfile entry

I would like to update the contents of text file located inside a zipfile.
I cannot find out how to do this, and the code below is not working properly.
May thanks for any help!!
import java.util.zip.ZipFile
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
String zipFileFullPath = "C:/path/to/myzipfile/test.zip"
ZipFile zipFile = new ZipFile(zipFileFullPath)
ZipEntry entry = zipFile.getEntry ( "someFile.txt" )
if(entry){
InputStream input = zipFile.getInputStream(entry)
BufferedReader br = new BufferedReader(new InputStreamReader(input, "UTF-8"))
String s = null
StringBuffer sb = new StringBuffer()
while ((s=br.readLine())!=null){
sb.append(s)
}
sb.append("adding some text..")
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileFullPath))
out.putNextEntry(new ZipEntry("someFile.txt"));
int length
InputStream fin = new ByteArrayInputStream(sb.toString().getBytes("UTF8"))
while((length = fin.read(sb)) > 0)
{
out.write(sb, 0, length)
}
out.closeEntry()
}
Just some slight modifications to #Opal's answer, I've just:
used groovy methods where possible
packaged in a method
Groovy Snippet
void updateZipEntry(String zipFile, String zipEntry, String newContent){
def zin = new ZipFile(zipFile)
def tmp = File.createTempFile("temp_${System.nanoTime()}", '.zip')
tmp.withOutputStream { os ->
def zos = new ZipOutputStream(os)
zin.entries().each { entry ->
def isReplaced = entry.name == zipEntry
zos.putNextEntry(isReplaced ? new ZipEntry(zipEntry) : entry)
zos << (isReplaced ? newContent.getBytes('UTF8') : zin.getInputStream(entry).bytes )
zos.closeEntry()
}
zos.close()
}
zin.close()
assert new File(zipFile).delete()
tmp.renameTo(zipFile)
}
Usage
updateZipEntry('/tmp/file.zip', 'META-INF/web.xml', '<foobar>new content!</foobar>')
What exactly isn't working? Is there any exception thrown?
As far as I know it's not possible to modify a zip file in situ. The following script rewrites the file and if desired entry is processed - modifies it.
import java.util.zip.*
def zipIn = new File('lol.zip')
def zip = new ZipFile(zipIn)
def zipTemp = File.createTempFile('out', 'zip')
zipTemp.deleteOnExit()
def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
def toModify = 'lol.txt'
for(e in zip.entries()) {
if(!e.name.equalsIgnoreCase(toModify)) {
zos.putNextEntry(e)
zos << zip.getInputStream(e).bytes
} else {
zos.putNextEntry(new ZipEntry(toModify))
zos << 'lollol\n'.bytes
}
zos.closeEntry()
}
zos.close()
zipIn.delete()
zipTemp.renameTo(zipIn)
UPDATE
I wasn't right. It's possible to modify zip file in situ, but Your solution will omit other files that were zipped. The output file will contain only one single file - the file You wanted to modify. I also suppose that You file was corrupted because of not invoking close() on out.
Below is You script slightly modified (more groovier):
import java.util.zip.*
def zipFileFullPath = 'lol.zip'
def zipFile = new ZipFile(zipFileFullPath)
def entry = zipFile.getEntry('lol.txt')
if(entry) {
def input = zipFile.getInputStream(entry)
def br = new BufferedReader(new InputStreamReader(input, 'UTF-8'))
def sb = new StringBuffer()
sb << br.text
sb << 'adding some text..'
def out = new ZipOutputStream(new FileOutputStream(zipFileFullPath))
out.putNextEntry(new ZipEntry('lol.txt'))
out << sb.toString().getBytes('UTF8')
out.closeEntry()
out.close()
}

Resources