Skip to content

Commit

Permalink
Add support for GZip compression
Browse files Browse the repository at this point in the history
  • Loading branch information
samrocketman committed Oct 1, 2023
1 parent 673e764 commit a401893
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 0 deletions.
105 changes: 105 additions & 0 deletions src/main/groovy/net/gleske/jervis/tools/GZip.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright 2014-2023 Sam Gleske - https://github.com/samrocketman/jervis
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.gleske.jervis.tools

import java.util.zip.Deflater
import java.util.zip.GZIPOutputStream


/**
A class to provide compression features to Jervis, specifically GZip.
<tt>GZip</tt> provides groovy-like leftShift for compressing strings. This
class also uses maximum compression by default and provides an easy means to
change the compression level.
<h2>Sample usage</h2>
<p>To run this example, clone Jervis and execute <tt>./gradlew console</tt>
to bring up a <a href="http://groovy-lang.org/groovyconsole.html" target="_blank">Groovy Console</a>
with the classpath set up.</p>
<h4>Write out a compressed file</h4>
<pre><code>
import net.gleske.jervis.tools.GZip
new File('test.gz').withOutputStream { OutputStream os -&gt;
try {
(new GZip(os)).withCloseable {
it &lt;&lt; 'hello world\n\nMy friend\n'
}
} finally {
os.close()
}
}
</code></pre>
<h4>Upload a compressed file</h4>
<p>This example uploads compressed data directly to <a href="https://help.sonatype.com/repomanager3" target=_blank>Sonatype Nexus</a>.</p>
<pre><code>
import net.gleske.jervis.tools.GZip
import net.gleske.jervis.tools.SecurityIO
String username = 'your user'
String password = 'your pass'
URL api_url = new URL('http://localhost:8081/repository/hosted-raw-repo/file.gz')
HttpURLConnection response = api_url.openConnection().with { conn -&gt;
conn.doOutput = true
conn.setRequestMethod('PUT')
conn.setRequestProperty('Authorization', "Basic " + SecurityIO.encodeBase64("${username}:${password}"))
conn.setRequestProperty('Accept', '*&sol;*')
conn.setRequestProperty('Expect', '100-continue')
conn.outputStream.withCloseable { nexus_os -&gt;
new GZip(nexus_os).withCloseable { gzip -&gt;
gzip &lt;&lt; 'hello world\n\nMy friend\n'
}
}
conn
}
// getting the response code completes the setup and makes the network connection
assert response.responseCode == 201
</code></pre>
*/

class GZip extends GZIPOutputStream {

/**
Creates a <tt>{@link java.util.zip.GZIPOutputStream}</tt> with maximum compression enabled.
@param os An <tt>{@link java.io.OutputStream</tt> to wrap which will write out compressed data.
@param level A compression level between fastest (<tt>1</tt>) and best compression (<tt>9</tt>).
*/
GZip(OutputStream os, Integer level = Deflater.BEST_COMPRESSION) {
super(os)
setLevel(level)
}

/**
This can change the compression level before you write data to <tt>GZip</tt> after it was instantiated.
@param level A compression level between fastest (<tt>1</tt>) and best compression (<tt>9</tt>).
*/
void setLevel(Integer level) {
this.@def.setLevel(level)
}

/**
Write a <tt>String</tt> similar to how you would write to a file with <tt>leftShift</tt> on a <tt>{@link java.io.Writer}</tt>.
@param shiftString A string which will be written out after being compressed.
*/
OutputStream leftShift(String shiftString) {
leftShift(shiftString.bytes)
}
}
54 changes: 54 additions & 0 deletions src/test/groovy/net/gleske/jervis/tools/GZipTest.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright 2014-2023 Sam Gleske - https://github.com/samrocketman/jervis
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package net.gleske.jervis.tools
//the GZipTest() class automatically sees the GZip() class because they're in the same package

import java.util.zip.GZIPInputStream
import org.junit.Test

class GZipTest extends GroovyTestCase {
@Test public void test_GZip_utility_decompression() {
StringWriter stdout = new StringWriter()
StringWriter stderr = new StringWriter()
Process proc = 'gunzip'.execute()
// write to stdin
proc.outputStream.withCloseable { stdin ->
new GZip(stdin).withCloseable {
it << 'hello\n'
}
}
// capture stdout
proc.waitForProcessOutput(stdout, stderr)
// stdout is decompressed data by gunzip
assert stdout.toString() == 'hello\n'
assert stderr.toString() == ''
assert proc.isAlive() == false
assert proc.exitValue() == 0
}
@Test public void test_GZip_fast_decompression() {
String text_to_compress = ''
ByteArrayOutputStream compressed = new ByteArrayOutputStream()
// fast compression
new GZip(compressed, 0).withCloseable {
it << text_to_compress
}
ByteArrayInputStream is = new ByteArrayInputStream(compressed.toByteArray())
ByteArrayOutputStream plain = new ByteArrayOutputStream()
GZIPInputStream gunzip = new GZIPInputStream(is)
plain << gunzip
assert plain.toString() == text_to_compress
}
}

0 comments on commit a401893

Please sign in to comment.