<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8557381644441801065</id><updated>2024-10-09T23:32:59.077+02:00</updated><title type='text'>grooveek.metaClass.blog = {shareDiscoveries()}</title><subtitle type='html'>Ideas about Groovy and Java. Some Grails stuff and plenty of other things</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://grooveek.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://grooveek.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>grooveek</name><uri>http://www.blogger.com/profile/02670644989809112570</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9ae6KXkaNimTrunBMdvOpHTOcHAwvOhyliVvLUdhDRvwXq7P_ypPICt8V-MGGlDDjklpv2dHB06ufIxF4GGA6XgrqfKs2FqpiPla7JfVjqCA9PB1-Qh2gnMFRJPnsAE/s220/photo_fb.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8557381644441801065.post-4934725685087218492</id><published>2009-09-15T01:22:00.004+02:00</published><updated>2009-09-15T01:33:05.686+02:00</updated><title type='text'>Playing again with zip and Groovy MOP ( and spread operator)</title><content type='html'>After I posted the &lt;a href=&quot;http://grooveek.blogspot.com/2009/09/adding-zipping-and-unzipping.html&quot;&gt;zip and unzip snippet&lt;/a&gt;, I came accross an interesting question on &lt;a href=&quot;http://www.gr8forums.org&quot;&gt;gr8forums.org&lt;/a&gt;.&lt;br /&gt;
Someone told me it would be great if ths code could be applied to an array of files.&lt;br /&gt;
&lt;br /&gt;
That&#39;s a good use case, isn&#39;t it ? So, I thought about it and saw immediately which groovy &#39;magic item&#39; could be useful : the spread operator aka star-dot operator, mister &lt;b&gt;*.&lt;/b&gt; &lt;br /&gt;
Better than I could explain myself, here&#39;s what&#39;s said about this little thing in Groovy&#39;s doc :&lt;br /&gt;
&lt;p style=&quot;background:CadetBlue;color:DarkBlue;padding-left:15px;&quot;&gt;The Spread Operator is used to invoke an action on all items of an aggregate object.&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
Unfortunately, ZipOutputStream in Java doesn&#39;t permit to append something to a zip file. So, I&#39;ll show you an awful (yes, unzip the existing zip-append file-rezip IS awful) implementation of this functionnality. It&#39;s just for fun, not for production, after all.&lt;br /&gt;
&lt;br /&gt;
First, you&#39;ll need a deleteDir closure, as java.io.File.delete() doesn&#39;t delete non-empty directories :&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;def deleteDir
deleteDir = { File f -&gt;
    if (f?.exists()){
      f.listFiles().each{ sf -&gt;
        sf.isDirectory()?deleteDir(sf):sf.delete()
      }
    }
    f?.delete()
}
&lt;/pre&gt;&lt;br /&gt;
With this wonderful snippet, you can replace the File.metaClass.zip block in &lt;a href=&quot;http://grooveek.blogspot.com/2009/09/adding-zipping-and-unzipping.html&quot;&gt;this snippet&lt;/a&gt; by :&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;File.metaClass.zip = { String destination -&gt;
    //cache the delegate (the File Object) as it will be modified
    //in the withStream closure
    def input = delegate
    if (destination == null){
        destination = input.canonicalPath + &quot;.zip&quot;
    }
    def dest = new File(destination)
    def append = false
    def tmp
    if (dest.exists()){
        tmp = new File(System.properties[&#39;java.io.tmpdir&#39;] + File.separator + &#39;grooz&#39;)           
        tmp.mkdir()
        dest.unzip(tmp.canonicalPath)
        append = true
    }
    def result = new ZipOutputStream(new FileOutputStream(destination))
    try{
    result.withStream {zipOutStream-&gt;
        //recursively zip files
        if (append) {
            
                tmp.eachFile{
                    zip(zipOutStream,it,&quot;&quot;)
                }
            
        }
        zip(zipOutStream,input,&quot;&quot;)
    }
    }
    catch(all){
      all.printStackTrace()
    }
    finally{                        
      deleteDir(tmp)
    }    
}

&lt;/pre&gt;&lt;br /&gt;
This version is very easy to use. If you want to zip a bunch of files, then list them and use the spread operator like this :&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;// to zip all files in a directory
new File(&#39;/path/to/dir&#39;).listFiles()*.zip(&#39;allmyfiles.zip&#39;) 
//if you&#39;ve got files instances
[file1,file2,dir1,dir2]*.zip(&#39;stuff.zip&#39;)
&lt;/pre&gt;&lt;br /&gt;
This code is not performance-friendly nor beauty-frienly and is provided as is. Every enhancement you can think of is welcome (yes, I know, it&#39;ll be difficult to improve, but you can do it ;-) )&lt;br /&gt;
&lt;br /&gt;
See you soon with a totally new subject : joy of Java Classoading !</content><link rel='replies' type='application/atom+xml' href='http://grooveek.blogspot.com/feeds/4934725685087218492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grooveek.blogspot.com/2009/09/playing-again-with-zip-and-groovy-mop.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/4934725685087218492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/4934725685087218492'/><link rel='alternate' type='text/html' href='http://grooveek.blogspot.com/2009/09/playing-again-with-zip-and-groovy-mop.html' title='Playing again with zip and Groovy MOP ( and spread operator)'/><author><name>grooveek</name><uri>http://www.blogger.com/profile/02670644989809112570</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9ae6KXkaNimTrunBMdvOpHTOcHAwvOhyliVvLUdhDRvwXq7P_ypPICt8V-MGGlDDjklpv2dHB06ufIxF4GGA6XgrqfKs2FqpiPla7JfVjqCA9PB1-Qh2gnMFRJPnsAE/s220/photo_fb.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8557381644441801065.post-6509924833942654110</id><published>2009-09-11T01:00:00.003+02:00</published><updated>2009-09-15T01:38:51.991+02:00</updated><title type='text'>Adding Zipping and unzipping capabilities to Java.io.File via Groovy MOP</title><content type='html'>&lt;p style=&quot;background:CadetBlue;color:DarkBlue;padding-left:15px;&quot;&gt;this post has an update : &lt;a href=&quot;http://grooveek.blogspot.com/2009/09/playing-again-with-zip-and-groovy-mop.html&quot;&gt;Playing again with zip and Groovy MOP ( and spread operator)&lt;/a&gt;&lt;br /&gt;
&lt;/p&gt;&lt;br /&gt;
[First technical post, and I don&#39;t know how to begin... Please be kind with me]&lt;br /&gt;
So, as I&#39;m writing a Plugin System in Groovy, I needed to zip and unzip so-called &#39;Bundles&#39; which contain config files, Plugin jars and dependencies.&lt;br /&gt;
&lt;br /&gt;
I didn&#39;t want to make a classical FileUtils or BundleUtils class, and I decided to try Groovy MOP (Meta Object Protocol) to directly modify the java.io.File so I could write &lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;new File(&#39;/path/to.file&#39;).zip(/path/to.zip)&lt;/pre&gt;&lt;br /&gt;
First thing to do is adding capability when you need to. As an example, I decided to load the capability statically in a Class. You could either have a bootsrap class that loads your metaprogramming functionnalities before starting your App. This is your choice&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;static{
  bootstrapPluginSystem()
}

private static void bootstrapPluginSystem(){
   //zipping methods here
   ..................
   //unzipping methods here
   ..................
}
&lt;/pre&gt;&lt;br /&gt;
Zipping files is easy in Java and is performed via the &lt;a href=&quot;http://www.j2ee.me/javase/6/docs/api/java/util/zip/ZipOutputStream.html&quot;&gt;ZipOutputStream&lt;/a&gt; class.&lt;br /&gt;
&lt;br /&gt;
One of the grooviest groovy goodies is the ability to work seamlessly with streams without boilerplate resource closing code&lt;br /&gt;
Simply use the &lt;a href=&quot;http://groovy.codehaus.org/groovy-jdk/java/io/InputStream.html#withStream&quot;&gt;withStream&lt;/a&gt; method, and Groovy manage the resource for you. How great it is !!!&lt;br /&gt;
&lt;br /&gt;
Groovy MOP is wonderful to add methods to Class at Runtime. The simple example I take here demonstrates the power of this technique&lt;br /&gt;
&lt;br /&gt;
Zipping is quite easy :&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;//define zip closure first, then allocate it
 //it is needed to make the recursion work
 def zip
 zip = { ZipOutputStream zipOutStream,File f , String path-&gt;                        
    def name = (path.equals(&quot;&quot;))?f.name:path + File.separator + f.name
    if(!f.isDirectory() ){                            
      def entry = new ZipEntry(name)
      zipOutStream.putNextEntry(entry)
      new FileInputStream(f).withStream { inStream -&gt;
        def buffer = new byte[1024]
        def count
        while((count = inStream.read(buffer, 0, 1024)) != -1) {
          zipOutStream.write(buffer,0,count)
        }
      }
      zipOutStream.closeEntry()
    }
    else {
      //write the directory first, in order to allow empty directories
      def entry = new ZipEntry(name + File.separator)
      zipOutStream.putNextEntry(entry)
      zipOutStream.closeEntry()                            
      f.eachFile{
        //recurse
        zip(zipOutStream,it,name)
      }
    }
 }

 File.metaClass.zip = { String destination -&gt;
    //cache the delegate (the File Object) as it will be modified 
    //in the withStream closure
    def input = delegate            
    def result = new ZipOutputStream(new FileOutputStream(destination))
    result.withStream {zipOutStream-&gt;   
      //recursively zip files             
      zip(zipOutStream,input,&quot;&quot;)
    }
 }

&lt;/pre&gt;&lt;br /&gt;
Code is almost self explaining...&lt;br /&gt;
Unzipping comes with less efforts : &lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;File.metaClass.unzip = { String dest -&gt;
 //in metaclass added methods, &#39;delegate&#39; is the object on which 
 //the method is called. Here it&#39;s the file to unzip
 def result = new ZipInputStream(new FileInputStream(delegate))
 def destFile = new File(dest)
 if(!destFile.exists()){
   destFile.mkdir();
 }
 result.withStream{
   def entry
   while(entry = result.nextEntry){
     if (!entry.isDirectory()){
       new File(dest + File.separator + entry.name).parentFile?.mkdirs()
       def output = new FileOutputStream(dest + File.separator 
                                         + entry.name)                        
       output.withStream{
         int len = 0;
         byte[] buffer = new byte[4096]
         while ((len = result.read(buffer)) &gt; 0){
           output.write(buffer, 0, len);
         }
       }
    }
    else {
      new File(dest + File.separator + entry.name).mkdir()
    }
   }
 }
}

&lt;/pre&gt;&lt;br /&gt;
All that is not really thoroughly tested, but I managed to zip and unzip the grails project directory without problems. I can also unzip with Ark files zipped by these lines of code&lt;br /&gt;
&lt;br /&gt;
Here are minimal tests :&lt;br /&gt;
&lt;pre class=&quot;brush: groovy&quot;&gt;import groovy.util.GroovyTestCase
/**
 *
 * @author grooveek
 */
class ZipTest extends GroovyTestCase{
 // load the static block to add zip capabilities
 static def bootstrap = new BootStrap()

 void testZipUnzip(){
   def fi = new File(&#39;testfiles&#39;)
   if (!fi.exists()){
     fi.mkdir()
   }
   def writer = new File(&#39;testfiles/ziptest.txt&#39;).newWriter()
   100.times{
     writer.writeLine(&quot;$it&quot;)
   }
   writer.close()
   //testing zipping/unzipping
   def fileToZip = new File(&#39;testfiles/ziptest.txt&#39;)
   fileToZip.zip(&#39;testfiles/toto.zip&#39;)
   def zipToUnzip = new File(&#39;testfiles/toto.zip&#39;)
   zipToUnzip.unzip(&#39;testfiles/ziptestdir&#39;)
 }

 void testZipUnzipWithDirectories(){
   def fi = new File(&#39;testfiles&#39;)
   if (!fi.exists()){
     fi.mkdir()
   }
   new File(&#39;testfiles/toto/titi&#39;).mkdirs()
   def writer = new File(&#39;testfiles/toto/titi/ziptest.txt&#39;).newWriter()
   100.times{
     writer.writeLine(&quot;$it&quot;)
   }
   writer.close()
   //testing zipping/unzipping
   def fileToZip = new File(&#39;testfiles/toto&#39;)
   fileToZip.zip(&#39;testfiles/toto2.zip&#39;)
   def zipToUnzip = new File(&#39;testfiles/toto2.zip&#39;)
   zipToUnzip.unzip(&#39;testfiles/ziptestdir2&#39;)
 }

 void testZipUnzipWithDirectoriesAndMultipleFiles(){
   def fi = new File(&#39;testfiles&#39;)
   if (!fi.exists()){
     fi.mkdir()
   }
   new File(&#39;testfiles/tata/titi&#39;).mkdirs()
   5.times{
     def writer = new File(&quot;testfiles/tata/titi/ziptest${it}.txt&quot;).newWriter()
     100.times{
       writer.writeLine(&quot;$it&quot;)
     }
     writer.close()
   }
   new File(&#39;testfiles/tata/titi/toto&#39;).mkdirs()
   5.times{
     def writer = new File(&quot;testfiles/tata/titi/toto/ziptest${it}.txt&quot;).newWriter()
     100.times{
       writer.writeLine(&quot;$it&quot;)
     }
     writer.close()
   }
   new File(&#39;testfiles/tata/titi/toto/tutu&#39;).mkdirs()
   //testing zipping/unzipping
   def fileToZip = new File(&#39;testfiles/tata&#39;)
   fileToZip.zip(&#39;testfiles/toto3.zip&#39;)
   def zipToUnzip = new File(&#39;testfiles/toto3.zip&#39;)
   zipToUnzip.unzip(&#39;testfiles/ziptestdir3&#39;)
}
        

 void testZipBigAndDeepDirectory(){
   def fileToZip = new File(&quot;/home/grooveek/grails-1.1.1&quot;)
   fileToZip.zip(&quot;testfiles/grails.zip&quot;)
   def zipToUnzip = new File(&#39;testfiles/grails.zip&#39;)
   zipToUnzip.unzip(&#39;testfiles&#39;)
 }
}
&lt;/pre&gt;&lt;br /&gt;
I hope you enjoyed reading&lt;br /&gt;
Don&#39;t forget to let a kind word (or something not so kind if that&#39;s your mind)you want&lt;br /&gt;
&lt;br /&gt;
See you soon&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://www.twitter.com/grooveek&quot;&gt;@grooveek&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://grooveek.blogspot.com/feeds/6509924833942654110/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grooveek.blogspot.com/2009/09/adding-zipping-and-unzipping.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/6509924833942654110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/6509924833942654110'/><link rel='alternate' type='text/html' href='http://grooveek.blogspot.com/2009/09/adding-zipping-and-unzipping.html' title='Adding Zipping and unzipping capabilities to Java.io.File via Groovy MOP'/><author><name>grooveek</name><uri>http://www.blogger.com/profile/02670644989809112570</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9ae6KXkaNimTrunBMdvOpHTOcHAwvOhyliVvLUdhDRvwXq7P_ypPICt8V-MGGlDDjklpv2dHB06ufIxF4GGA6XgrqfKs2FqpiPla7JfVjqCA9PB1-Qh2gnMFRJPnsAE/s220/photo_fb.png'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8557381644441801065.post-1406409705556075635</id><published>2009-09-06T23:52:00.001+02:00</published><updated>2009-09-07T00:00:06.100+02:00</updated><title type='text'>What strikes me in Groovy ...</title><content type='html'>&lt;pre class=&quot;brush: groovy&quot; name=&quot;code&quot;&gt;// Simple list with names.
def names = [&#39;groovy&#39;, &#39;grails&#39;, &#39;mrhaki&#39;]

// Simple closure.
names.each { println &#39;Normal closure says: Hello &#39; + it + &#39;!&#39; }

// Groovy method to convert to closure.
def groovySays(s) {
 &quot;Groovy says: Hello ${s}!&quot;
}
// Use .&amp;amp; syntax to convert method to closure.
names.each(this.&amp;amp;groovySays)

// Convert Java method to closure and use it.
def javaSays = JavaObject.&amp;amp;javaSays
names.each javaSays

&lt;/pre&gt;&lt;br /&gt;
This code comes from &lt;a href=&quot;http://mrhaki.blogspot.com/2009/08/groovy-goodness-turn-methods-into.html&quot;&gt;mr haki&#39;s blog&lt;/a&gt;. What I like here is the ability to switch from Java to Groovy ! You can have the power of Java with the simplicity of Groovy&lt;br /&gt;
(and that&#39;s also a test post for the &lt;a href=&quot;http://alexgorbatchev.com/wiki/SyntaxHighlighter&quot;&gt;syntax highlighting plugin&lt;/a&gt;)</content><link rel='replies' type='application/atom+xml' href='http://grooveek.blogspot.com/feeds/1406409705556075635/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grooveek.blogspot.com/2009/09/what-strikes-me-in-groovy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/1406409705556075635'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/1406409705556075635'/><link rel='alternate' type='text/html' href='http://grooveek.blogspot.com/2009/09/what-strikes-me-in-groovy.html' title='What strikes me in Groovy ...'/><author><name>grooveek</name><uri>http://www.blogger.com/profile/02670644989809112570</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9ae6KXkaNimTrunBMdvOpHTOcHAwvOhyliVvLUdhDRvwXq7P_ypPICt8V-MGGlDDjklpv2dHB06ufIxF4GGA6XgrqfKs2FqpiPla7JfVjqCA9PB1-Qh2gnMFRJPnsAE/s220/photo_fb.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8557381644441801065.post-1795175434214493491</id><published>2009-09-06T15:28:00.000+02:00</published><updated>2009-09-06T15:28:13.796+02:00</updated><title type='text'>Welcome to this blog</title><content type='html'>I love Groovy and Java. I mean : I LOVE Groovy and Java. I&#39;m writing here to share experiences, and to get some help sometimes as I&#39;m not a Groovy Champion ;-)&lt;br /&gt;
Feel free to share your feelings about Groovy and Java technologies here and please, please.... excuse me for my bad english. I&#39;m French and would be really happy to find people who want to talk about what&#39;s really fun in coding !&lt;br /&gt;
&lt;br /&gt;
My best JVM-related technologies at this time (just) :&lt;br /&gt;
* Groovy / Grails /Gorm&lt;br /&gt;
* Spring&lt;br /&gt;
* Gridgain&lt;br /&gt;
* HtmlUnit / Webtest&lt;br /&gt;
&lt;br /&gt;
Enjoy your readings&lt;br /&gt;
&lt;br /&gt;
Grooveek</content><link rel='replies' type='application/atom+xml' href='http://grooveek.blogspot.com/feeds/1795175434214493491/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://grooveek.blogspot.com/2009/09/welcome-to-this-blog.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/1795175434214493491'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8557381644441801065/posts/default/1795175434214493491'/><link rel='alternate' type='text/html' href='http://grooveek.blogspot.com/2009/09/welcome-to-this-blog.html' title='Welcome to this blog'/><author><name>grooveek</name><uri>http://www.blogger.com/profile/02670644989809112570</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='33' height='29' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjV9ae6KXkaNimTrunBMdvOpHTOcHAwvOhyliVvLUdhDRvwXq7P_ypPICt8V-MGGlDDjklpv2dHB06ufIxF4GGA6XgrqfKs2FqpiPla7JfVjqCA9PB1-Qh2gnMFRJPnsAE/s220/photo_fb.png'/></author><thr:total>0</thr:total></entry></feed>