diff --git a/src/main/groovy/net/gleske/jervis/tools/GZip.groovy b/src/main/groovy/net/gleske/jervis/tools/GZip.groovy new file mode 100644 index 00000000..0846ca88 --- /dev/null +++ b/src/main/groovy/net/gleske/jervis/tools/GZip.groovy @@ -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. + GZip 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. + + +
To run this example, clone Jervis and execute ./gradlew console + to bring up a Groovy Console + with the classpath set up.
+ +
+import net.gleske.jervis.tools.GZip
+
+new File('test.gz').withOutputStream { OutputStream os ->
+ try {
+ (new GZip(os)).withCloseable {
+ it << 'hello world\n\nMy friend\n'
+ }
+ } finally {
+ os.close()
+ }
+}
+
+
+ This example uploads compressed data directly to Sonatype Nexus.
+
+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 ->
+ conn.doOutput = true
+ conn.setRequestMethod('PUT')
+ conn.setRequestProperty('Authorization', "Basic " + SecurityIO.encodeBase64("${username}:${password}"))
+ conn.setRequestProperty('Accept', '*/*')
+ conn.setRequestProperty('Expect', '100-continue')
+ conn.outputStream.withCloseable { nexus_os ->
+ new GZip(nexus_os).withCloseable { gzip ->
+ gzip << 'hello world\n\nMy friend\n'
+ }
+ }
+ conn
+}
+// getting the response code completes the setup and makes the network connection
+assert response.responseCode == 201
+
+ */
+
+ class GZip extends GZIPOutputStream {
+
+ /**
+ Creates a {@link java.util.zip.GZIPOutputStream} with maximum compression enabled.
+ @param os An {@link java.io.OutputStream to wrap which will write out compressed data.
+ @param level A compression level between fastest (1) and best compression (9).
+ */
+ GZip(OutputStream os, Integer level = Deflater.BEST_COMPRESSION) {
+ super(os)
+ setLevel(level)
+ }
+
+ /**
+ This can change the compression level before you write data to GZip after it was instantiated.
+ @param level A compression level between fastest (1) and best compression (9).
+ */
+ void setLevel(Integer level) {
+ this.@def.setLevel(level)
+ }
+
+ /**
+ Write a String similar to how you would write to a file with leftShift on a {@link java.io.Writer}.
+ @param shiftString A string which will be written out after being compressed.
+ */
+ OutputStream leftShift(String shiftString) {
+ leftShift(shiftString.bytes)
+ }
+}
diff --git a/src/test/groovy/net/gleske/jervis/tools/GZipTest.groovy b/src/test/groovy/net/gleske/jervis/tools/GZipTest.groovy
new file mode 100644
index 00000000..45e0082e
--- /dev/null
+++ b/src/test/groovy/net/gleske/jervis/tools/GZipTest.groovy
@@ -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
+ }
+}