RE: Displaying the entered command-line options as parsed by clibuilder

2024-01-16 Thread Merlin Beedell
And if anyone is interested to print the cliBuilder usage in the order that you 
added them, try

def cli = new CliBuilder(usage:'Blaa')
cli.x(..)
cli.a(..)
cli.formatter.setOptionComparator({a,b -> 1})

cli.usage() will now print in the order added (x then a).

Merlin Beedell
From: Merlin Beedell 
Sent: Tuesday, January 16, 2024 3:42 PM
To: users@groovy.apache.org
Subject: Displaying the entered command-line options as parsed by clibuilder

I thought this might be useful... I wanted an easy way to print the parameters 
passed to groovy CliBuilder.
Unlike the usage() method that prints the 'how to use' (header/parameter 
options/footer), I just wanted to print the final parsed value set.
(Perhaps something like this could be incorporated into CliBuilder's 
OptionAccessor - a pretty print method?)
It turns out to be a one liner [for basic single args] and 1 more for 
additional args.  For example...

def cli = new CliBuilder(usage:'''Cryoserver Export to PST''', footer:'''
V1.0 MGB Jul 2020.''')
cli.i(longOpt:'input', args:1, required: true, argName:'filepath', type:File, 
'a directory containing Cryoserver Export zip files')
cli.o(longOpt:'output', args:1, required: true, argName:'filepath', type:File, 
'output into this directory')
cli.d(longOpt:'depth',args:1, required: false, argName:'number', type:int, 
defaultValue: '1', 'levels of subdirectories to traverse. Default 1.')
cli.m(longOpt:'max',args:1, required: false, argName:'number', type:int, 
defaultValue: '5', 'Max num mails per pst. Default 5.')
cli.t(longOpt:'threads',args:1, required: false, argName:'number', type:int, 
defaultValue: '4', 'number of threads. Default 4.')
cli.w(longOpt:'wrapped', args:0, required: false, defaultValue:false, 'Include 
Wrapper? Default = false (strip any wrapper)')
cli.x(longOpt:'filefilter', args:1, required: false, argName:'regex', 
defaultValue: fileMatch, "a regex to select required export files. default = 
$fileMatch")
cli.'?'(longOpt:'help', 'help')

def opts = cli.parse(['-i','b','-o','c', 'plus', 'more'])
if (!opts) { //if invalid opts then it prints usage by default
  return
}
cli.options.options.each {println "-$it.option(${it.longOpt}) = 
${opts[(it.option)]}"}
if (opts.arguments()) {println opts.arguments()}

prints (note - args are in the same order as defined):
-i(input) = b
-o(output) = c
-d(depth) = 1
-m(max) = 5
-t(threads) = 4
-w(wrapped) = false
-x(filefilter) = .*
-?(help) = false
  [Plus, more]

Merlin Beedell



Displaying the entered command-line options as parsed by clibuilder

2024-01-16 Thread Merlin Beedell
I thought this might be useful... I wanted an easy way to print the parameters 
passed to groovy CliBuilder.
Unlike the usage() method that prints the 'how to use' (header/parameter 
options/footer), I just wanted to print the final parsed value set.
(Perhaps something like this could be incorporated into CliBuilder's 
OptionAccessor - a pretty print method?)
It turns out to be a one liner [for basic single args] and 1 more for 
additional args.  For example...

def cli = new CliBuilder(usage:'''Cryoserver Export to PST''', footer:'''
V1.0 MGB Jul 2020.''')
cli.i(longOpt:'input', args:1, required: true, argName:'filepath', type:File, 
'a directory containing Cryoserver Export zip files')
cli.o(longOpt:'output', args:1, required: true, argName:'filepath', type:File, 
'output into this directory')
cli.d(longOpt:'depth',args:1, required: false, argName:'number', type:int, 
defaultValue: '1', 'levels of subdirectories to traverse. Default 1.')
cli.m(longOpt:'max',args:1, required: false, argName:'number', type:int, 
defaultValue: '5', 'Max num mails per pst. Default 5.')
cli.t(longOpt:'threads',args:1, required: false, argName:'number', type:int, 
defaultValue: '4', 'number of threads. Default 4.')
cli.w(longOpt:'wrapped', args:0, required: false, defaultValue:false, 'Include 
Wrapper? Default = false (strip any wrapper)')
cli.x(longOpt:'filefilter', args:1, required: false, argName:'regex', 
defaultValue: fileMatch, "a regex to select required export files. default = 
$fileMatch")
cli.'?'(longOpt:'help', 'help')

def opts = cli.parse(['-i','b','-o','c', 'plus', 'more'])
if (!opts) { //if invalid opts then it prints usage by default
  return
}
cli.options.options.each {println "-$it.option(${it.longOpt}) = 
${opts[(it.option)]}"}
if (opts.arguments()) {println opts.arguments()}

prints (note - args are in the same order as defined):
-i(input) = b
-o(output) = c
-d(depth) = 1
-m(max) = 5
-t(threads) = 4
-w(wrapped) = false
-x(filefilter) = .*
-?(help) = false
  [Plus, more]

Merlin Beedell



RE: Design pattern for processing a huge directory tree of files using GPars

2022-05-13 Thread Merlin Beedell
Thank you Bob, that did work for me.
Some Java syntax is new to me - like this .map(Path::toFile). Back to school 
again.
This is standard Java, which is pretty groovy already, but I wonder if this 
could be (or already has been) groovy-ised in some way, e.g. to simplify the 
Files.walk(..).collect(..).parallelStream().
I put the filter before the collect - on the assertion that it would be more 
efficient to skip unnecessary files before adding to the parallel processing.
In the following snippet I include a processedCount counter - and although this 
works, I am aware that altering things outside of the parallel process can be 
bad.

import java.nio.file.*
import java.util.stream.*

   long scanFolder (File directory, Pattern fileMatch)
   {
long processedCount = 0
Files.walk(directory.toPath(), 1)  //just walk the current directory, not 
subdirectories
  .filter(p -> (Files.isRegularFile(p) && p.toString().matches(fileMatch) ) )  
//skip files that do not match a regex pattern
  .collect(Collectors.toList())
  .parallelStream()
 .map(Path::toFile)
  .forEach( msgFile -> {
  
   processedCount++
} )
return processedCount
   }

Merlin Beedell

From: Bob Brown 
Sent: 10 May 2022 09:19
To: users@groovy.apache.org
Subject: RE: Design pattern for processing a huge directory tree of files using 
GPars

If you are able to use a modern Java implementation, you can use pure-Java 
streams, eg:

https://stackoverflow.com/a/66044221

///
Files.walk(Paths.get("/path/to/root/directory")) // create a stream of paths
.collect(Collectors.toList()) // collect paths into list to better parallize
.parallelStream() // process this stream in multiple threads
.filter(Files::isRegularFile) // filter out any non-files (such as 
directories)
.map(Path::toFile) // convert Path to File object
.sorted((a, b) -> Long.compare(a.lastModified(), b.lastModified())) // sort 
files date
.limit(500) // limit processing to 500 files (optional)
.forEachOrdered(f -> {
// do processing here
System.out.println(f);
});
///

also read : 
https://www.airpair.com/java/posts/parallel-processing-of-io-based-data-with-java-streams

Hope this helps some.

BOB


From: Merlin Beedell mailto:mbeed...@cryoserver.com>>
Sent: Monday, 9 May 2022 8:12 PM
To: users@groovy.apache.org<mailto:users@groovy.apache.org>
Subject: Design pattern for processing a huge directory tree of files using 
GPars

I am trying to process millions of files, spread over a tree of directories.  
At the moment I can collect the set of top level directories into a list and 
then process these in parallel using GPars with list processing (e.g. 
.eachParallel).
But what would be more efficient would be a 'parallel' for the File handling 
routines, for example:

   withPool() {
  directory.eachFileMatchParallel (FILES, 
~/($fileMatch)/) {aFile ->  ...

then I would be a very happy bunny!

I know I could copy the list of matching files into an Array list and then use 
the withPool { filesArray.eachParallel { ... - but this does not seem like an 
efficient solution - especially if there are several hundred thousand files in 
a directory.

What design pattern(s) might be better to consider using?

Merlin Beedell



Design pattern for processing a huge directory tree of files using GPars

2022-05-09 Thread Merlin Beedell
I am trying to process millions of files, spread over a tree of directories.  
At the moment I can collect the set of top level directories into a list and 
then process these in parallel using GPars with list processing (e.g. 
.eachParallel).
But what would be more efficient would be a 'parallel' for the File handling 
routines, for example:

   withPool() {
  directory.eachFileMatchParallel (FILES, 
~/($fileMatch)/) {aFile ->  ...

then I would be a very happy bunny!

I know I could copy the list of matching files into an Array list and then use 
the withPool { filesArray.eachParallel { ... - but this does not seem like an 
efficient solution - especially if there are several hundred thousand files in 
a directory.

What design pattern(s) might be better to consider using?

Merlin Beedell



Delete empty folders in a tree

2021-01-26 Thread Merlin Beedell
Groovy provides a File.deleteDir() method that deletes a complete tree of 
directories AND files.  But what if I just want to delete empty directories?
It would be useful if this method could take an optional parameter (e.g. 
Boolean  -  onlyEmpty = if true only delete if empty) - or perhaps even a 
closure returning true/false to determine the criteria on which deletion should 
occur - e.g. delete folder and content unless the folder contains a particular 
file.

This simple method below will delete any empty folders below the provided File 
path.  For performance, it is over simple, as it could skip deletes of parent 
folders where a child folder is not empty (hence not deleted).

  void clearEmptyDirectories(File aDir) {
  def emptyDirs = []

  aDir.eachDirRecurse { testDir ->
emptyDirs << testDir
  }
  // reverse so that we do the deepest folders first
  // but do not delete a folder if it is not empty
  emptyDirs.reverseEach { it.delete() }
  }

Merlin Beedell



RE: Self logging scripts

2021-01-26 Thread Merlin Beedell
This line should have been like this:
  new 
File(getClass().protectionDomain.codeSource.location.path).name.toLowerCase().replace('.groovy',
 '')
Merlin Beedell

From: Merlin Beedell 
Sent: 26 January 2021 3:33 PM
To: users@groovy.apache.org
Subject: Self logging scripts

Hi all,
I am successfully using the following chunk of groovy code at the top of 
various console scripts in order to preserve the various stdout/strerr output 
to a log file - as well as on the console.
There are a couple of points.  First it uses SystemOutputInterceptor - but this 
class appears to be depreciated.  Is there something coming to replace it?
Second, I would like to be able to print the command line as entered by the 
user who provoked the script. The nearest I could get was to print the args 
list (as below).  Is there a simple way of obtaining the actual command entered 
by the user so it can be included with the log?  I was hoping the CliBuilder 
might have a pretty print feature, but I can't see one.

import groovy.ui.SystemOutputInterceptor

def dateString = new Date().format('MMMdd-HHmmss')
String getScriptFileName() {
  new 
File(getClass().protectionDomain.codeSource.location.path).name.toLowerCase().replace(/\.groovy/,
 '')
}
new File('./logs').mkdir()
def logOutput = new PrintWriter(new 
File("./logs/${getScriptFileName()}-${dateString}.log"))
def myLoger = new SystemOutputInterceptor( { Object... args -> logOutput << 
args[-1]; logOutput.flush(); true } )
myLoger.start()
if (args) {
  print "Parameters provided:"
  args.each {print " " + it}
  println ""
}

println  "this is printed to the console window and to the log file - like a 
'tee' feature.  Really useful"


Merlin Beedell


Self logging scripts

2021-01-26 Thread Merlin Beedell
Hi all,
I am successfully using the following chunk of groovy code at the top of 
various console scripts in order to preserve the various stdout/strerr output 
to a log file - as well as on the console.
There are a couple of points.  First it uses SystemOutputInterceptor - but this 
class appears to be depreciated.  Is there something coming to replace it?
Second, I would like to be able to print the command line as entered by the 
user who provoked the script. The nearest I could get was to print the args 
list (as below).  Is there a simple way of obtaining the actual command entered 
by the user so it can be included with the log?  I was hoping the CliBuilder 
might have a pretty print feature, but I can't see one.

import groovy.ui.SystemOutputInterceptor

def dateString = new Date().format('MMMdd-HHmmss')
String getScriptFileName() {
  new 
File(getClass().protectionDomain.codeSource.location.path).name.toLowerCase().replace(/\.groovy/,
 '')
}
new File('./logs').mkdir()
def logOutput = new PrintWriter(new 
File("./logs/${getScriptFileName()}-${dateString}.log"))
def myLoger = new SystemOutputInterceptor( { Object... args -> logOutput << 
args[-1]; logOutput.flush(); true } )
myLoger.start()
if (args) {
  print "Parameters provided:"
  args.each {print " " + it}
  println ""
}

println  "this is printed to the console window and to the log file - like a 
'tee' feature.  Really useful"


Merlin Beedell
0800 280 0525 / +44 (0)207 045 0520
DDI: +44 (0)207 045 0528
Mob: +44 (0)7876 226865
Cryoserver: A focused, flexible email archive delivered by experts



RE: Defining a global variable

2020-10-21 Thread Merlin Beedell
I thought that implicit variables would overcome this.  Not an elegant solution 
- as you are simply declaring variables on the fly without an explicit data 
type or even a 'def'.
Having said, it is generally safer to explicitly list the parameters used in a 
method when used in this context (e.g. in a script without an explicit class 
declaration to mop up this case).
And as for 'global' - I sure wish the word 'global' was used instead of 
'static'.  It just kinda makes more sense to me!
//===
   test=''  //implicit declaration of a variable
   void func()
   {
  println(test)
   }
   test = 'hello'
   func()
//===

Or just

//===
   void func()
   {
  println(test)
   }
   test = 'hello'
   func()  
//===

Merlin Beedell 
-Original Message-
From: MG  
Sent: 15 October 2020 6:21 PM
To: users@groovy.apache.org; Jochen Theodorou 
Subject: Re: Defining a global variable

On 15/10/2020 18:27, Jochen Theodorou wrote:
> well.. even scripts are first compiled into a class before the class 
> is then executed. Groovy has no interpreter

Which, I think, is a lesser known fact, and quite surprising to people who 
perceive Groovy just under its "script language" aspect ;-)




RE: 3.0.x Windows installers released

2020-09-29 Thread Merlin Beedell
Keegan, Thanks very much for that reply.
I can’t really comment on the 32/64 bit debate.  I just think that apps 
installed in ProgFiles32 are ‘old’ – which I am sure that Groovy would not wish 
to be thought to be.
Just read your recent update: I now understand the “groovy …”.execute() thing 
better, I may evolve my scripts to use the Script Engine and move away from 
returning exit statuses.  But nevertheless, there may be a case to include an 
‘option’ in the installer for binary wrappers.

As for the scriptom thing – I guess it does not need to evolve as the Windows 
COM objects have equally not changed for many years. But COM enabled things 
very much still exist and will probably continue to do so for a good while 
longer – but a time appears to be coming when Windows becomes a side project to 
Linux (as seen from the WSL efforts).  And I think that Office Automation 
tooling is shifting to newer APIs and web services (like OAuth and ‘Graph’). So 
if there was a simple way to download and install Jacob/scriptom as a separate 
thing, that might help for the few that still use it!

Merlin Beedell
From: Keegan Witt 
Sent: 29 September 2020 7:33 AM
To: users@groovy.apache.org
Subject: Re: 3.0.x Windows installers released

1.
That's correct.  There were a few discussions about why I thought we should do 
this.  Here's a short summary: Most of the modules included you can just use 
@grab for anyway, the few others where that wouldn't apply (GroovyServ, 
Grengine) seemed low usage.  Scriptom was the only other one in this category 
that I've heard folks actually use.  But multiple of the installed extras 
hadn't been updated in years (and some never will).  It's been 10 1/2 years 
since the last Scriptom release.  I know Scriptom is specific to Windows, but I 
also thought it'd be good to be somewhat consistent with the environment 
provided between platforms, which would help folks writing scripts targeting 
different platforms have some consistency.

2.
I opened a PR to update the installer links 
(https://github.com/apache/groovy-website/pull/25).

3.
Yes, as noted in the 3.0 announcement email, when the WiX version replaced the 
NSIS version (when 3.0 first released), the NSIS version should be uninstalled 
before installing the new version.

4.
There are no native binaries included anymore, so there's nothing x86 or x64 
specific about it.  One of the things I didn't like about how the old installer 
worked is it would detect your current Java (from JAVA_HOME if I recall 
correctly) and those would be the binaries copied over.  But this seemed a 
fragile way to do it to me, since you might have several JDKs installed, and on 
different architectures.  There also wasn't really any reason to have 64 bit 
binaries in my view, since they're just wrappers for calling java.exe and will 
never need so much memory that they'd benefit from being 64 bit.

5.
This kept the installer logic simple.  I'm not sure the best practice about the 
installation directory when the thing being installed is platform independent.  
I think I should be able to use the variable for the 64 bit program files 
directory if available, if you think that'd be better.  It seemed somewhat an 
arbitrary choice.

6. (the question about .bat)
I think this is related to the known issue with needing vbs files to have the 
appropriate file association (https://github.com/groovy/groovy-wix/issues/2).  
I've been trying to find a better solution for this, without needing to have 
something as heavy-weight as the native binaries we used to use, which have 
logic about JAVA_HOME, etc.  I haven't found a better solution yet, I may have 
to revive the native binaries (or do something similar).  I've documented my 
investigations in that issue.  I also mention there how you can check and fix 
your file associations there.

7. (the question about execute)
I don't quite understand this question.  The "execute" thing you're showing is 
a feature of the JDK.  GroovyScriptEngine is included in Groovy and there's no 
reason you shouldn't be able to use this instead if you wish.


A bit of a discussion for the dev mailing list I suppose, but what do we 
consider the official position on Scriptom?  Should it be considered 
deprecated?  We copied the stuff over from Codehaus after the shutdown, but it 
hasn't been touched since (and I think hadn't been touched in a while even 
before the move).  If it's something we want to continue to support, I think we 
need to do some updates, like updating to the latest Jacob.  Some questions I'd 
have if it were to be revived (bearing in mind I'm not really familiar with 
these features):

  1.  Should we drop the Office modules?  Or if not, we might need to update 
for newer Office versions.
  2.  Should the IE6 module be dropped?  IE6 is pretty dead at this point.
I'm willing to reconsider the decision on including Scriptom, but not until we 
have a clear position on its maintenance status.  I'd

3.0.x Windows installers released

2020-09-28 Thread Merlin Beedell
Hi Groovy magic workers,

I notice that the Windows Installer has changed quite a lot recently.  It is 
nice and quick and the UI is simple. However: things I note in this release:

  1.  The supplementary extras (e.g. Jacob / scriptom) are not included at all, 
not even as a custom install.  Not sure how to include these separately, other 
than to copy-paste from an older release. [I use scriptom to query the Windows 
Services list to start/stop/query various services].
  2.  The Windows 3.0.4 installer and 3.0.5 releases are not yet on the 
‘groovy-lang.org’ download site.
  3.  My Environment PATH variable appears to have 2 entries pointing to the 
new groovy home. Perhaps it edits the previous entry and then adds the new one 
as well.
  4.  It does not supply separate 64-bit executables that can be exchanged with 
the 32-bit executables, which might relate to the next item…
  5.  It defaults the install under program files (x86) – suggesting a 32-bit 
implementation only.   Only the ‘custom’ option allows it to be put somewhere 
else.

I then noticed that if I execute this in groovysh or in the groovyConsole:
“groovy -v”.execute().waitForProcessOutput(System.out, System.err)
Exception thrown
java.io.IOException: Cannot run program "groovy": CreateProcess error=2, The 
system cannot find the file specified
   at ConsoleScript5.run(ConsoleScript5:1)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find 
the file specified

But this works

“groovy.bat -v”.execute().waitForProcessOutput(System.out, System.err)
Groovy Version: 3.0.3 JVM: 1.8.0_162 Vendor: Oracle Corporation OS: Windows 10

Does this suggest that the installed groovy is 32-bit when my computer and JDK 
are both 64-bit?  My older groovy installs (going back to 2.0.4) would all work.

PS – Why call groovy using “execute” rather than GroovyScriptEngine? Well some 
of these called scripts use System.exit (error-number) and if I use the 
ScriptEngine or similar, it causes my script to exit as well!

Merlin Beedell
0800 280 0525 / +44 (0)207 045 0520
DDI: +44 (0)207 045 0528
Mob: +44 (0)7876 226865
Cryoserver: A focused, flexible email archive delivered by experts

From: Guillaume Laforge 
Sent: 23 July 2020 12:51 PM
To: users@groovy.apache.org; Paul King 
Subject: Re: [ANNOUNCE] Groovy 2.4.20, 2.5.13, and 3.0.5 Windows installers 
released

Combo!

Le jeu. 23 juil. 2020 à 12:13, Paul King 
mailto:pa...@asert.com.au>> a écrit :
Nice!

On Thu, Jul 23, 2020 at 3:07 PM Keegan Witt 
mailto:keeganw...@gmail.com>> wrote:
2.4.20: 
https://bintray.com/groovy/Distributions/download_file?file_path=groovy-2.4.20.msi
2.5.13: 
https://bintray.com/groovy/Distributions/download_file?file_path=groovy-2.5.13.msi
3.0.5: 
https://bintray.com/groovy/Distributions/download_file?file_path=groovy-3.0.5.msi

-Keegan


File counting methods

2020-06-10 Thread Merlin Beedell
This might not be a suitable question for the groovy users, but I am using it 
in a groovy script, so thought it might solicit some useful feedback and 
alternate ideas.

In Java's NIO there are a couple of ways to walk the tree of files in order to 
return a file count.  There must be lots of ways!  I don't know  Groovy has a 
better built in method - but I could not see it.
This one should be the fastest, using concurrent processes. However, if the set 
of files changes during the count it errors.  I have no idea how to catch and 
ignore that error.
long fileCountV2(Path dir) {
return Files.walk(dir)
.parallel()
.filter(p -> !p.toFile().isDirectory())
.count();
}

This one works regardless of any file changes, and uses a Stream for low memory 
overhead.  But it could do with concurrency to speed it up, but I really cannot 
figure how to GPARS this for performance.  This script did once fail with "too 
many files open" error on Linux (and a directory with 200,000+ files).  I can't 
determine how - no files are actually opened!

long fileCount(Path dir)
{
  long i = 0
  try {
Files.newDirectoryStream(dir).each {i++}
  } catch (e) {
println (e)
  }
  return i
}

Merlin Beedell



Help! - GPARS with eachFile & database concurrency

2020-01-24 Thread Merlin Beedell
Hi wonderful Groovy team,

I am really struggling to determine a "straight forward" groovy way to amend a 
simple linear script into one using some level of concurrency.  I cannot find 
suitable examples for the task at hand, namely:

I use derby database to collect data from email files on a server.  So

  1.  I walk the directory tree using a mix of eachDirRecurse and eachFileMatch.
  2.  High level directories are names of mailboxes - so I add these to the 
database, first checking that the mailbox is not already in the db.



   int addUser(def Username)

   {

  def res = sql.firstRow ("select id from user_info 
where user_name = ?", [Username])

  if (!res) {

 def keys = 
sql.executeInsert("insert into user_info (user_name) "

   + 
"VALUES (?)", [Username])

 return keys[0][0]  //return the 
auto-generated row id number from the db

  } else {

 return res.id

  }

   }



I guess I could just insert the data - and if it errors with 'duplicate key' 
then I know it already exists, but then I would still need to obtain the row ID 
to return back to the caller.


  1.  And when I find a file that is an email type, I read it line-by-line 
until I obtain the required header details (date: / subject: / from: / 
message-id: ) or a blank line ( end of headers).  I add these details to the 
database (again, checking that the item is not already there).

So I currently use a single SQL connection and a simple loop over the directory 
and files - its simple and works well.  But as there are several million files, 
I really need to use multiple threads.

I read that a "DataSource" is a way to pool Database connections.  I just cant 
see how this works - does it just dynamically create connections on demand [def 
sql = new Sql(mydatasource)], and when the 'sql' variable is garbage collected, 
the connection is returned to the 'pool'?  Is each sql instance "thread safe" 
from each other?
And are prepared statements also in the 'pool' - so the sql statements are not 
parsed every time regardless of the connection used?
As for concurrency...
I have previously used, in a basic sense, threads.  And then I looked at GPARS, 
which seems to be the appropriate way to go. So how might the 'eachDirRecurse' 
and 'eachFileMatch' be altered to a GPARs "withPool" collection loop?  How 
should each loop call the sql routines so they are thread safe - presumably by 
creating sql connection from datasource (pool) > do sql > done.  The withPool 
will create upto cpu-count + 1 - but should I use more with this type of 
process logic?  I assume that I could use the "withPool" within another  
"withPool", so that I can process [the pool count] some mailboxes in 
concurrently and also the files within each mailbox in parallel.

Is there some metric that determines how effective concurrent disk actions 
(just reading in this case) can be - e.g. so I could determine a sensible limit 
on the number of [email] files being read at the same time.  What monitoring 
method would help?

I don't think I need to use "actors" here, nor the "dataflow" feature.
Even after reading Groovy in Action (2ed), it is still not really clear how to 
proceed.  I have googled a lot, but still cannot map my ideas into a GPARS 
solution.  So I thought I should ask the experts - the groovy community - for 
some suggestions or appropriate reading material.

The nearest I have found to a useful template on this topic is 
https://stackoverflow.com/questions/35702351/concurrent-parallel-database-queries-using-groovy
But I just cannot see how or why the db connection pool interacts with the 
GPARs so that the same connection is not grabbed by each concurrent process.

Yours, hopefully,

Merlin Beedell



RE: New Groovy Windows installer

2019-02-18 Thread Merlin Beedell
I was a bit confused, as WIX is a web site design and hosting service: 
www.wix.com<http://www.wix.com>.
 But now I see your link, and it is WiX Toolset – “The most powerful set of 
tools available to create your Windows installation experience.”
That makes more sense.
Though it’s a shame that a multi-platform Java based installer could not be 
used (if such a thing exists).

Merlin Beedell
From: Keegan Witt 
Sent: 11 February 2019 2:24 AM
To: users@groovy.apache.org
Subject: New Groovy Windows installer

I'm working on a new installer<https://github.com/keeganwitt/groovy-wix> for 
Windows using WIX<http://wixtoolset.org/> to create an MSI installer, which 
should be more robust for things like altering environment variables and make 
it easier to do corporate installations.

I'm a total noob when it comes to Windows Installer and WIX, so I'm sure I've 
done some dumb things, but I hacked together a basic working installer this 
weekend.  I've put the initial version of the installer 
here<https://www.dropbox.com/sh/w2giakqb2jcc82e/AAB_gqvCvzOU1t-2dRlV4yBoa?dl=0>.
  Your feedback is appreciated.

Some things I'm still thinking about or working on:

  *   The start menu shortcuts for documentation don't go into a subfolder, I'm 
not sure why.
  *   Heat will generate new GUIDs for the binaries and docs folders every time 
the project is built -- I'm not sure if that's the correct thing to do.
  *   Would you ever want to set GROOVY_HOME without adding to PATH?  Or add to 
PATH without setting GROOVY_HOME?  Currently the installer groups these 
together in a single feature.
  *   We should use registry entries to remember which features the user 
selected to install, so those are automatically selected during upgrades.
  *   Desktop shortcuts.
  *   Quick launch shortcuts.  I don't think people use these much anymore, but 
I can throw them in -- maybe disabled by default?
  *   Should I create an exe version of the installer as well as the msi?
-Keegan


RE: Groovy file associations on Windows

2019-02-11 Thread Merlin Beedell
I use Scriptom – for registering and managing Windows Services (mostly).  I 
believe that MS are moving away from the COM model – but I am sure it will be 
around for a while yet.  As such it will not change much – and hence the 
ScriptOM utility is unlikely to need changing either.

Here is an example:


org.codehaus.groovy.scriptom.Scriptom.inApartment {

def locator = new 
org.codehaus.groovy.scriptom.ActiveXObject('WbemScripting.SWbemLocator')

def services = locator.ConnectServer('.')



<



/* a test to list all cryo services with their dependencies */

if (testOnly) {

for(process in services.ExecQuery("SELECT Name FROM Win32_Service where 
(displayname like 'cryo%') and StartMode != 'Disabled'", 'WQL', 
wbemFlagForwardOnly)) {

  println process.Name()

  for (depServ in services.ExecQuery("Associators of 
{Win32_Service.Name='" + process.Name() + "'} Where 
AssocClass=Win32_DependentService Role=Dependent")) {

println  "\tDep: ${depServ.DisplayName} state: ${depServ.State}"

  }

  for (depServ in services.ExecQuery("Associators of 
{Win32_Service.Name='" + process.Name() + "'} Where 
AssocClass=Win32_DependentService Role=Antecedent")) {

println  "\tAsc: ${depServ.DisplayName} state: ${depServ.State}"

  }

}

}

}

Merlin Beedell
0800 280 0525 / +44 (0)207 045 0520
DDI: +44 (0)207 045 0528
Mob: +44 (0)7876 226865
Cryoserver: A focused, flexible email archive delivered by experts

From: Keegan Witt 
Sent: 11 February 2019 2:24 AM
To: users@groovy.apache.org
Subject: Groovy file associations on Windows

In addition to removing projects that are no longer developed from the Groovy 
Windows installer (Gpars, Gaelyk, Scriptom, EasyB, Gant, GMock), I'm 
considering removing the exe files from 
groovy-native-launcher<https://github.com/groovy/groovy-native-launcher>.  
These haven't been compiled in quite a while and are just another thing to 
maintain.  As I see it, there are two primary benefits these provide.

  1.  Provide a way to create file associations so you can double click a 
Groovy file, or run myFile.groovy instead of groovy myFile.groovy.
  2.  Hide the command window when launching GroovyConsole.
For #2, I can work around this with a VBScript file (or NirCmd).  #1 doesn't 
have a good way to solve other than the current native binary solution since 
Launch4J doesn't support variable 
expansion<https://sourceforge.net/p/launch4j/bugs/162/>.  My question is, do 
many folks need this functionality?  It's something I've never personally used. 
 Please weigh in with your thoughts.

-Keegan


Advent of Code challenges

2018-12-10 Thread Merlin Beedell
There is an interesting web with a daily challenge throughout advent - 
http://adventofcode.com .  Perhaps groovy enthusiasts could show their 
solutions for each challenge?

My son (15) has learnt a variety of programming techniques - like linked lists 
- in order to answer the challenges.   He is using JavaScript and Python, as 
these are taught at school.

Merlin Beedell


RE: [DISCUSS] Groovy 2.6 potential retirement to focus on Groovy 3.0

2018-12-10 Thread Merlin Beedell
I see a monthly release of the 2.5x product – but nothing similar for version 
3.  What might be happening in the V3 world?  Given the license terms change 
under JDK 11, will the main target be OpenJDK?

Merlin Beedell
From: Paul King 
Sent: 23 June 2018 2:53 AM
To: users@groovy.apache.org
Subject: Re: [DISCUSS] Groovy 2.6 potential retirement to focus on Groovy 3.0


There was overwhelming support to drop 2.6 to focus on 3.0 and mixed feedback
on whether to do one more 2.6 alpha release or not. So, I'll go ahead and do 
one more
2.6 alpha release - quite possibly much less work than further discussions and 
it gives
us a clean end point which I am highly in favour of to reduce subsequent 
discussions
about what exactly was in the last alpha release.

We aren't planning to delete the branch - so it's still around if we need some
further emergency regression fixes down the track, but we aren't planning to do
any merges, so it will start to go out of sync with other branches. So even if 
you
have an "emergency fix" for that branch, we'd encourage you to have a discussion
on the mailing list before creating PRs against that branch.

Cheers, Paul.


On Sat, Jun 16, 2018 at 8:55 AM Robert Stagner 
mailto:restag...@gmail.com>> wrote:
option #2 for me
On Wed, Jun 13, 2018 at 12:06 AM Paul King 
mailto:pa...@asert.com.au>> wrote:

Hi everyone,

There was some discussion at gr8conf about how to speed up delivery of Groovy 
3.0. Some of that discussion was around the scope of what we want to include 
and have yet to complete in 3.0 but I won't discuss that right now.

One of the other discussion points was Groovy around 2.6. As many of you know, 
we have released alpha versions of Groovy 2.6. That version is a backport of 
most but not all of Groovy 3.0 to JDK7 including the Parrot parser (though it 
isn't enabled by default). The purpose of this version has always been to 
assist people/projects wanting to use the Parrot parser but who might be stuck 
on JDK7. So in some sense it is an intermediate version to assist with porting 
towards Groovy 3.0. While that is still a noble goal in theory, in practice, 
many of our users are already on JDK8 and we have limited resources to work on 
many potential areas.

With that in mind, we'd like to understand the preferences in our user base for 
the following two options:

Option 1: please continue releasing the best possible 2.6 even if that slows 
down the final release of Groovy 3.0 and delays further work on better support 
for JDK9+.

Option 2: please release one more alpha of 2.6 over the next month or so which 
will become the best version to use to assist porting for users stuck on JDK7 
and then focus on 3.0. The 2.6 branch will essentially be retired though we 
will consider PRs from the community for critical fixes.

Feedback welcome.

Cheers, Paul.




JDK 10: Use of var over def?

2018-03-23 Thread Merlin Beedell
I see that the newly release JDK 10 now supports the "var" declaration for 
local variables where the type can clearly be inferred from its initialiser:

http://openjdk.java.net/jeps/286

I note that Groovy's "def" syntax (among others) was mentioned but rejected.

Would Groovy move to support this syntax in the same way (support 'var' only 
for Type Safe inferred declarations) or as a general alias to the "def" keyword?

JDK 10 also has support for "docker" containers.  The ecosystem has certainly 
shifted!

Merlin Beedell



RE: Scriptom

2017-12-18 Thread Merlin Beedell
I think that MS are trying to move away from the COM / DCOM model - and I found 
it quite difficult to locate the documentation on the basic VBA type model 
objects properties and methods for Outlook (as used by Scriptom). The MSDN kept 
directing me to other APIs, like this: 
https://docs.microsoft.com/en-us/office/dev/add-ins/excel/excel-add-ins-overview?product=excel
This was the sort of thing that I was doing:

org.codehaus.groovy.scriptom.Scriptom.inApartment {

def OutApp = new 
org.codehaus.groovy.scriptom.ActiveXObject("Outlook.Application")
 
def myNameSpace = OutApp.GetNameSpace("MAPI")
//println myNameSpace.Folders.Count

def OutMail = OutApp.CreateItem(0)

OutMail.to = "m...@blaa.com"
OutMail.CC = ""
OutMail.BCC = ""
OutMail.Subject = "This is the Subject line"
OutMail.Body = "Hi there"
OutMail.Send()
OutMail = null
OutApp = null
} 

Merlin Beedell 
0800 280 0525 / +44 (0)207 045 0520
DDI: +44 (0)207 045 0528
Mob: +44 (0)7876 226865
Cryoserver: A focused, flexible email archive delivered by experts

-Original Message-
From: vlkodlak [mailto:sedivy.vlkod...@gmail.com] 
Sent: 18 December 2017 00:53
To: us...@groovy.incubator.apache.org
Subject: Re: Scriptom

Hi,

I used scriptom in the past and it was a really great library.

Is there any hope that it will be woken up / reborn?
And is / will there be some alternative on Mac? I'd like to control MS app via 
Groovy ...

Thanks

Tomas



--
Sent from: http://groovy.329449.n5.nabble.com/Groovy-Users-f329450.html


Getting Methods/Properties of objects under "Scriptom"

2017-11-16 Thread Merlin Beedell
I am trying to analyse a large chunk of emails in Outlook.  I thought that I 
could re-write my VBA script using Groovy with "scriptom" to access the COM 
objects - and indeed it works. Yippee! So I can send an email and query the 
folder tree etc.
However, I am a curious person, and sometime would like to "query" the methods 
and properties of an Object - and the "listMnP (Object)" [see below] works 
nicely for Java objects.
This often helps when I am trying to match the documentation that I can find on 
Google, to the various objects that I am accessing.
However, I get a "Can't map name to dispid: metaClass" error - which is 
probably quite understandable.  Is it possible to query the Methods and 
Properties of a dynamic object in any way?

org.codehaus.groovy.scriptom.Scriptom.inApartment {

def OutApp = new 
org.codehaus.groovy.scriptom.ActiveXObject("Outlook.Application")
def myNameSpace = OutApp.GetNameSpace("MAPI")
println myNameSpace.Folders.Count
def myFolder = myNameSpace.Folders.GetFirst()
println myFolder.name

listMnP myFolder   /// this should cause the object "myFolder" to list its 
Methods and Properties - but it errors.

def OutMail = OutApp.CreateItem(0)

OutMail.to = "an email address!!"
OutMail.CC = ""
OutMail.BCC = ""
OutMail.Subject = "This is the Subject line"
OutMail.Body = "Hi there"
OutMail.Send()
OutMail = null
OutApp = null
}

/ end 
void listMnP (def thing) {
  println " >> Methods of ${thing.class} >>"
  thing.metaClass.methods.each {  method ->
println "$method.name -> $method.parameterTypes"
  }
  println " >> Properties >>"
  thing.metaClass.properties.each { prop ->
print "$prop.name -> "
try {println thing[prop.name]} catch (Exception e) {println "-NoValue-"}
  }
  try {println "Class Loader: ${thing.class.classLoader}"} catch (e) {println 
"No Class Loader"}

}

== When run the "List Methods and Properties" function is not 
effective ===

PS C:\opt\groovy\OutlookScripts> groovy .\scanMailbox.groovy
3
Online Archive - mbeed...@cryoserver.com
>> Methods of class org.codehaus.groovy.scriptom.ActiveXObject >>
Caught: com.jacob.com.ComFailException: Can't map name to dispid: metaClass
com.jacob.com.ComFailException: Can't map name to dispid: metaClass
at com.jacob.com.Dispatch.invokev(Native Method)
at com.jacob.com.Dispatch.invokev(Dispatch.java:858)
at com.jacob.com.Dispatch.get(Dispatch.java:1258)
at 
com.jacob.activeX.ActiveXComponent.getProperty(ActiveXComponent.java:171)
at scanMailbox.listMnP(scanMailbox.groovy:61)
at scanMailbox$_run_closure2.doCall(scanMailbox.groovy:45)
at scanMailbox$_run_closure2.doCall(scanMailbox.groovy)
at scanMailbox.run(scanMailbox.groovy:37)

Merlin Beedell



RE: Use of SystemOutputInterceptor with different groovy versions

2017-11-10 Thread Merlin Beedell
Perfect – that works a treat.  I thought I needed to overload the closure – 
specifying 2 closures, one with 1 parameter and another with 2. But I don’t 
think that is possible.  Your solution is simple and effective – and now I can 
see how to use varags too.

I use it an all my critical scripts, as it is so useful.  It replicates the 
‘tee’ command in Linux.
We do not use many bash or bat scripts any more, just groovy scripts. And now 
they get logged to file and screen when they run without any fancy loggers.

I don’t know if [the apache groovy dev team] might modify the documentation 
accordingly for this (and any other class) to cater for different Groovy 
versions.

Merlin

From: Paul King [mailto:pa...@asert.com.au]
Sent: 10 November 2017 01:06
To: users@groovy.apache.org
Subject: Re: Use of SystemOutputInterceptor with different groovy versions

I guess we regarded that class as somewhat internal when we made that change. 
You could use:

myLogger = new SystemOutputInterceptor({
  Object... args -> logOutput << args[-1]; logOutput.flush(); true
})

Cheers, Paul.


On Fri, Nov 10, 2017 at 4:15 AM, Merlin Beedell 
<mbeed...@cryoserver.com<mailto:mbeed...@cryoserver.com>> wrote:
I also noted that the following code would work just fine in recent Groovy 
version, but not in older.  The idea is to intercept the stdout (System.out) so 
any output can be logged to a text file as well as to the console [really 
rather handy!].


import groovy.ui.SystemOutputInterceptor

dateString = new Date().format("MMMdd-HHmmss")

logOutput = new PrintWriter(new File("./","scriptLog_" + dateString +".log"))  
//log into the current directory

myLoger = new SystemOutputInterceptor(

   {Integer i, String s -> logOutput << s; logOutput.flush(); true }

)

myLoger.start()

In older groovy versions, it seems that the Integer parameter is not passed to 
the closure (and the ‘start’ method is not required either):


myLoger = new SystemOutputInterceptor(

{Integer i, String s -> logOutput << s; logOutput.flush(); true }

)

myLoger.start()

But I can’t think how I can specify this code so it works for all versions of 
Groovy.  This is the error if it is wrong (here under Groovy 2.0.5):


Caught: groovy.lang.MissingMethodException: No signature of method: 
test$_run_closure2.doCall() is applicable for argument types: 
(java.lang.Integer, java.lang.String) values: [0,  Hello world]

Possible solutions: doCall(java.lang.String), findAll(), findAll()

It is as though I need to be able to provide two closure definitions – one with 
and one without the Integer parameter.
Any ideas?

Merlin



Use of SystemOutputInterceptor with different groovy versions

2017-11-09 Thread Merlin Beedell
I also noted that the following code would work just fine in recent Groovy 
version, but not in older.  The idea is to intercept the stdout (System.out) so 
any output can be logged to a text file as well as to the console [really 
rather handy!].


import groovy.ui.SystemOutputInterceptor

dateString = new Date().format("MMMdd-HHmmss")

logOutput = new PrintWriter(new File("./","scriptLog_" + dateString +".log"))  
//log into the current directory

myLoger = new SystemOutputInterceptor(

   {Integer i, String s -> logOutput << s; logOutput.flush(); true }

)

myLoger.start()

In older groovy versions, it seems that the Integer parameter is not passed to 
the closure (and the 'start' method is not required either):


myLoger = new SystemOutputInterceptor(

{Integer i, String s -> logOutput << s; logOutput.flush(); true }

)

myLoger.start()

But I can't think how I can specify this code so it works for all versions of 
Groovy.  This is the error if it is wrong (here under Groovy 2.0.5):


Caught: groovy.lang.MissingMethodException: No signature of method: 
test$_run_closure2.doCall() is applicable for argument types: 
(java.lang.Integer, java.lang.String) values: [0,  Hello world]

Possible solutions: doCall(java.lang.String), findAll(), findAll()

It is as though I need to be able to provide two closure definitions - one with 
and one without the Integer parameter.
Any ideas?

Merlin


RE: Slashy strings in GroovyConsole

2017-06-16 Thread Merlin Beedell
My preference is to use File (or Path) object whenever dealing with files – and 
then ONLY using forward slashes.  So for your request:
def scriptDir = /C:\Folder1\My Documents\Folder2\Version\etc\/
becomes
def scriptDir = new File("C:/Folder1/My Documents/Folder2/Version/etc")
or (if you really wanted the path as a string)
def scriptDir = new File("C:/Folder1/My 
Documents/Folder2/Version/etc").absolutePath

I agree that copy-pasting file paths from File Explorer and then twiddling the 
slash direction is a bit tedious – but better than figuring out all that 
escaping!  I dare say that using a File object has overheads – but at least you 
can test if the file or directory exists. Iterate over the files etc. etc.

Adding pieces of a path or path and file name together, again use the File 
class:

def myScript = new File("C:/Folder1/My Scripts", "Script1.groovy")
def myScript = new File(scriptDir, "Script1.groovy")

It saves getting the System.properties['file.separator'] – and you can even 
ignore the drive letter (if it is on the current disk).
def myScript = new File("/Folder1/My Scripts", "Script1.groovy")

And yes – I use groovy rather a lot on Windows.

Merlin Beedell
Cryoserver: A focused, flexible email archive delivered by experts

From: Joe Wolf [mailto:joew...@gmail.com]
Sent: 14 June 2017 14:53
To: users@groovy.apache.org; Paul King <pa...@asert.com.au>
Subject: Re: Slashy strings in GroovyConsole

Also be careful when using slashy Strings with path names that start with a 
lowercase "u"

They'll get interpreted as a unicode character escape, e.g. /c:\users/ --> 
TokenStreamIOException: Did not find four digit hex character code.

(BTW, I'm glad to see there are other GroovyConsole users on Windows out there)

-Joe

On Wed, Jun 14, 2017 at 6:32 AM, Paul King 
<pa...@asert.com.au<mailto:pa...@asert.com.au>> wrote:
What bo zhang said or use dollar slashy string.

Cheers, Paul.

On Wed, Jun 14, 2017 at 7:37 PM, bo zhang 
<zhangbo...@gmail.com<mailto:zhangbo...@gmail.com>> wrote:
def scriptDir = /C:\Folder1\My Documents\Folder2\Version\etc\//

note the last slash. \/ is escaping /

On Wed, Jun 14, 2017 at 4:44 PM, Dmytro Shyshchenko 
<shysche...@gmail.com<mailto:shysche...@gmail.com>> wrote:
Long time ago I was using slashy strings in my groovy scripts for the paths on 
Windows. Somehting like this:
def scriptDir = /C:\Folder1\My Documents\Folder2\Version\etc\/

However in the recent versions, like 2.3.6 or 2.4.11, I can no longer execute 
those scripts via a GroovyConsole. It always gave me an error pointing to the 
last charecter of the script. Like this:
unexpected char: 0x at line: 19, column: 13
which was a bit misleading...

When I change the paths to a "normal" srtings, everything works fine, as it was 
before.
def scriptDir = "C:\\Folder1\\My Documents\\Folder2\\Version\\etc\\"

Is it a bug? Shall I report it?





[https://www.cryoserver.com/wp-content/uploads/2017/03/ISO-logo-signature.jpg]  
[https://www.cryoserver.com/wp-content/uploads/2017/03/softech-signature.png]   
[https://www.cryoserver.com/wp-content/uploads/2017/03/ITE-signature.png]

FCS (UK) Limited is registered in England & Wales, Registration Number: 5940018 
- Registered Address: Wigglesworth House, 69 Southwark Bridge Road, London SE1 
9HH Disclaimer: This e-mail contains proprietary information, some or all of 
which may be legally privileged and is for the intended recipient only and the 
information in it are provided in confidence and may not be disclosed to any 
third party or used for any other purpose without the express permission of FCS 
(UK) Ltd. If an addressing or transmission error has misdirected this e-mail, 
please notify the author by replying. If you are not the intended recipient you 
should not use, disclose, distribute, copy, print or relay on this e-mail. The 
views expressed in this communication are not necessarily the views held by FCS 
(UK) Limited.


gpars for calculating directory content size

2017-06-16 Thread Merlin Beedell
I see that groovy has a handy method to return the sum of file & sub-directory 
sizes in a directory:
new File('sample').directorySize()

But I would be interested to see if the underlying code uses gpars - on the 
assumption that the computation would be faster if sub-directories are found 
(the sum of each being performed in parallel).

Actually - my interest is more in seeing a useful(?) example of gpars!

Merlin Beedell

[https://www.cryoserver.com/wp-content/uploads/2017/03/ISO-logo-signature.jpg]  
[https://www.cryoserver.com/wp-content/uploads/2017/03/softech-signature.png]   
[https://www.cryoserver.com/wp-content/uploads/2017/03/ITE-signature.png]

FCS (UK) Limited is registered in England & Wales, Registration Number: 5940018 
- Registered Address: Wigglesworth House, 69 Southwark Bridge Road, London SE1 
9HH Disclaimer: This e-mail contains proprietary information, some or all of 
which may be legally privileged and is for the intended recipient only and the 
information in it are provided in confidence and may not be disclosed to any 
third party or used for any other purpose without the express permission of FCS 
(UK) Ltd. If an addressing or transmission error has misdirected this e-mail, 
please notify the author by replying. If you are not the intended recipient you 
should not use, disclose, distribute, copy, print or relay on this e-mail. The 
views expressed in this communication are not necessarily the views held by FCS 
(UK) Limited.


Groovy Documentation query

2017-05-31 Thread Merlin Beedell
Before Groovy became an Apache project, I think the web and documentation was 
created and maintained on an Atlassian Confluence service?
What platform hosts this now?  I can't see any references to it on 
http://www.groovy-lang.org/documentation.html
And if you were able to compare the two, which was easier to use, for 
publishing your documentation both on the web and as a pdf / html page set 
included in each release?

I ask because both services are really very good, and just the sort of thing 
that we could use!

Merlin Beedell

[https://www.cryoserver.com/wp-content/uploads/2017/03/ISO-logo-signature.jpg]  
[https://www.cryoserver.com/wp-content/uploads/2017/03/softech-signature.png]   
[https://www.cryoserver.com/wp-content/uploads/2017/03/ITE-signature.png]

FCS (UK) Limited is registered in England & Wales, Registration Number: 5940018 
- Registered Address: Wigglesworth House, 69 Southwark Bridge Road, London SE1 
9HH Disclaimer: This e-mail contains proprietary information, some or all of 
which may be legally privileged and is for the intended recipient only and the 
information in it are provided in confidence and may not be disclosed to any 
third party or used for any other purpose without the express permission of FCS 
(UK) Ltd. If an addressing or transmission error has misdirected this e-mail, 
please notify the author by replying. If you are not the intended recipient you 
should not use, disclose, distribute, copy, print or relay on this e-mail. The 
views expressed in this communication are not necessarily the views held by FCS 
(UK) Limited.