From Evgeny Goldin

Jump to: navigation, search



GCommons is a general-usage library similar to Apache Commons. It extracts general reusable pieces from other projects and provides them in a simple and intuitive way for anyone. All my Maven plugins rely heavily on its abilities, especially "copy-maven-plugin" for its copying and archiving operations and "assert-maven-plugin" when it compares directories and evaluates Groovy expressions.

GCommons is covered in GroovyMag March 2011.


Provided By
Mailing List Nabble
Source Code GitHub
Tests GitHub
GroovyDoc Gradle Groovydoc
Issue Tracker YouTrack
Build Server Gradle
Maven Coordinates com.github.goldin:gcommons:0.5.4
Maven Repositories Artifactory Online

What's New

v0.5.4, May 10, 2012

Issue Id Type Summary GroovyDoc
gc-115 Feature FileBean.pack() - allow to set compression level when using Ant FileBean.pack()
gc-112 Feature FileBean.pack() - add "overwrite" option FileBean.pack()
gc-73 Task Switch to Guice
gc-114 Feature FileBean.baseName() - retrieve file base name (file.name minus ".$extension") FileBean.baseName()
gc-103 Bug NullPointerException in GeneralBean.array()
gc-111 Exception GeneralBean$array.call fails on Java7

v0.5.3.5, November 12, 2011

Issue Id Type Summary GroovyDoc
gc-102 Bug FileBean.copy() doesn't preserve origin's lastModified FileBean.copy()
gc-100 Bug FileBean.extension() returns extension lower-cased FileBean.extension()
gc-104 Bug FileBean.files() fails when directory specified doesn't exist even if "failIfNotFound" is "false" FileBean.files()
gc-105 Bug GeneralBean.executeWithResult() occasionally returns empty String GeneralBean.executeWithResult()
gc-98 Feature FileBean.extension() - return empty String if file has no extension FileBean.extension()
gc-99 Feature FileBean.recurse() - return list of files iterated and passed to the closure callback FileBean.recurse()
gc-101 Feature FileBean.unpackZipEntries() - accept new parameter: zip entries to exclude FileBean.unpackZipEntries()
gc-75 Task Eliminate CodeNarc violations
gc-45 Task FileBean.recurse() - make sure no values are left in configuration Map after it is read

v0.5.3.4, October 17, 2011

Issue Id Type Summary GroovyDoc
gc-86 Bug Ant scanner fix - set basedir with canonical path
gc-78 Bug Duplicate log messages
gc-77 Feature FileBean.pack() - add "fullpath" and "prefix" options FileBean.pack()
gc-88 Feature FileBean.pack() - support "fullpath", "prefix" for all archives (zip/tar/tar.gz) and "filemode" for tar/tar.gz FileBean.pack()
gc-93 Feature FileBean.pack() - support "filemode" specified as part of include pattern FileBean.pack()
gc-85 Feature FileBean.pack() - allow to optionally use TrueZip when packing archives FileBean.pack()
gc-94 Feature VerifyBean.equal() - use combination "directory/pattern" to match files VerifyBean.equal()
gc-95 Feature VerifyBean.equal() - provide an option whether or not to fail if no files were found VerifyBean.equal()
gc-87 Feature GeneralBean.executeWithResult() returning String (stdout + stderr) GeneralBean.executeWithResult()
gc-90 Feature FileBean.copyDir() - copy directory recursively FileBean.copyDir()
gc-84 Feature FileBean.unpack() - allow to optionally use TrueZip when unpacking archives FileBean.unpack()
gc-89 Feature Treat "sar" extension as zip archive
gc-40 Feature FileBean.checksum() - add checksum support FileBean.checksum()
gc-67 Usability Problem Do not impose logging backend

v0.5.3, May 15, 2011

Issue # Type Summary GroovyDoc
gc-58 Feature Switch to Groovy 1.8.0
gc-57 Feature Add full FTP path to FTPFile when listing files natively
gc-66 Bug After unpacking zip entry of <dependency> without <dependenciesAtM2> - it can't be deleted from a temp folder
gc-47 Feature VerifyBean.isInstance(Object, Class) VerifyBean.isInstance(Object, Class)
gc-56 Feature AlgorithmsBean - various sort and search implementations AlgorithmsBean
gc-60 Feature IOBean.resource(), IOBean.resourceText() - convenient retrieval of classpath resources IOBean
gc-70 Feature LoggerOutputStream - OutputStream implementation sending all output to SLF4J Logger LoggerOutputStream

v0.5.2, March 09, 2011

Issue # Type Summary GroovyDoc
gc-27 Bug NoSuchMethodError running svnOp.groovy
gc-53 Feature Switch to Groovy "1.8-rc-2"

v0.5.1, February 25, 2011

Issue # Type Summary GroovyDoc
gc-28 Feature FileBean.copy() - provide third optional argument: a file name FileBean.copy()
gc-29 Feature VerifyBean.equal() - make sure identical directories are of the same size VerifyBean.equal()
gc-33 Feature Return ConfigurableApplicationContext from GCommons instead of ApplicationContext GCommons.context()
gc-34 Feature Add GeneralBean.execute() GeneralBean.execute()



repositories { maven { url 'http://evgenyg.artifactoryonline.com/evgenyg/repo/' }}
dependencies { compile 'com.github.goldin:gcommons:0.5.4' }


@GrabResolver( name='com.github.goldin', root='http://evgenyg.artifactoryonline.com/evgenyg/repo/' )
import com.github.goldin.gcommons.GCommons

  • Example of a script using GCommons with @Grab.
  • When run for the first time it may take some time to download all library dependencies.




Other general libraries usually provide classes with static methods. GCommons is different, it supplies its functionality through a number of Spring beans, retrieved from com.github.goldin.gcommons.GCommons entry point.

import com.github.goldin.gcommons.GCommons
 * Retrieving Spring context
ApplicationContext context = GCommons.context()
 * Retrieving verification bean
GCommons.verify().file( sourceFile )
GCommons.verify().notNullOrEmpty( data ).splitWith( 'eachLine', String )*.trim().findAll{ it }
Class.getResourceAsStream( GCommons.verify().notNullOrEmpty( classPath ))
 * Retrieving file bean
File       tempDirectory = GCommons.file().tempDirectory()
List<File> files         = GCommons.file().files( sourceDirectory, [ '**/*.groovy' ], [ '**/*-Test.groovy'] )
GCommons.file().delete( sourceDirectory )
GCommons.file().unpack( archiveFile, targetDirectory )
GCommons.file().pack  ( sourceDirectory, archiveFile, [ '**/*.xml', '**/*.properties' ] )

Spring Beans

Bean Retrieved as Summary
ConstantsBean GCommons.constants() Constant values:
  • System line separator
  • User current and home directory
  • ...
GeneralBean GCommons.general() General methods for:
  • Matching file paths with Ant patterns
  • Splitting object to "pieces" with any of its iteration methods
  • Attempting to run a closure specified a number of time
  • ...
VerifyBean GCommons.verify() Verification methods for:
  • Verifying that file provided is an existing file or directory
  • Verifying that objects provided are all null or not-null
  • Verifying two directories are equal (see "assert-maven-plugin")
  • Verifying Strings/Collection specified are not null or empty
  • ...
FileBean GCommons.file() File methods for:
  • Listing all files in directory provided that match include/exclude patterns specified (see "copy-maven-plugin")
  • Calculating file checksum
  • Packing and unpacking archives or Zip entries
  • Recursively iterating a directory with enhanced options to detect loops and stop recursion with filters
  • Deleting files or whole directories
  • Calculating directory size
  • ...
IOBean GCommons.io() I/O methods for:
  • Safely closing Closeable instances provided
  • Copying of InputStream into OutputStream
  • ...
NetBean GCommons.net() Networking methods for:
  • Listing FTP files
  • Safely retrieving Commons Net FTPClient instance
  • ...
GroovyBean GCommons.groovy() Groovy-related methods for:
  • Evaluating Groovy expression with custom binding Map
  • ...

MOP Updates

GCommons adds new methods to traditional JDK classes.

Class.method Summary Also available as Example
File.recurse File.eachFileRecurse on steroids! Provides the following improvements over traditional recursive iteration:
  • Loops detection
  • Filters to apply for files or directories iterated
  • Recursion control with filters and callback return value


  • Optional configuration Map<String, Object>
Key name Value type Default Summary
"filter" Closure accepting a single File argument No filter Filters files/directories, only those passing the filter will be iterated and passed to callback Closure
"type" groovy.io.FileType FileType.ANY Type of files to iterate and pass to callback, default is compatible with File.eachFileRecurse( Closure )
"filterType" groovy.io.FileType Same as "type" Type of files to iterate and pass to filter
"stopOnFalse" boolean false Whether recursion stops if callback returns false
(Groovy Truth)
"stopOnFilter" boolean false Whether recursion stops if "filterType" is FileType.DIRECTORIES and directory doesn't pass the filter
"detectLoops" boolean false Whether loops should be detected and not iterated for the second time. Detecting loops introduces slight performance overhead as canonical path is calculated for each directory iterated so this feature is turned off by default.
  • Callback Closure accepting a single File argument. Will be invoked for each file matched.


  • Nothing

long directorySize = 0
new File( directory ).recurse([ type        : FileType.FILES,
                                detectLoops : true ]){ directorySize += it.size() }
assert dir.splitWith( 'recurse' ) == dir.splitWith( 'eachFileRecurse' )
new File( directory ).recurse { println "[$it]" }
Object.splitWith Splits object provided to "pieces" using one of its iteration methods, like String.eachLine or File.eachFile.


  • Name of method that accepts a single Closure argument and iterates over an object
  • Element type (optional) - if provided, each element in the List returned will be verified to be of correct type


  • List of elements

" ... ".splitWith( 'eachLine' )*.trim().findAll{ it }
" ... ".splitWith( 'eachLine', String )*.trim().findAll{ it }
assert dir.splitWith( 'recurse' ) == dir.splitWith( 'eachFileRecurse' )
new File( .. ).splitWith( 'eachLine' )*.trim().findAll{ it }
new File( .. ).splitWith( 'eachFile', File ).findAll{ it.size() > 10240 }
File.directorySize Calculates directory size. Runs recurse() with loop-detection enabled.


  • None


  • Directory size in bytes

def size = new File( .. ).directorySize()


This library follows a number of principals which I find very useful:

  • It always tries to operate on varargs arguments so a caller can provide any number of parameters to validate or files to delete:

GCommons.verify().file( sourceFile, anotherFile, thirdFile )
GCommons.verify().notNull( argument1, argument2 )
GCommons.verify().notNullOrEmpty( data, " ... ", anotherString )
GCommons.file().mkdirs( dir1, dir2, dir3 )
GCommons.general().choose( object, anotherObject, thirdObject, defaultValue )
GCommons.io().close( stream, anotherStream, thirdStream )

Right now varargs arguments are not shown by GroovyDoc, an issue was created.

  • It does not return void if any meaningful information can be returned instead. Therefore, all validation methods, for example, return first value validated allowing to reuse it in following chain calls. Likewise, file operations return File that was deleted or created.

def size   = GCommons.verify().notNullOrEmpty( " .. " ).size()
def parent = GCommons.verify().file( someFile ).parentFile
GCommons.file().mkdirs( directory ).recurse { ... }
def dir    = fileBean.mkdirs( fileBean.delete( dir ).parentFile )
Personal tools