From 0758a21b93c6397c371bf00f40146b4e5806e95a Mon Sep 17 00:00:00 2001 From: Benjamin Marwell Date: Sun, 19 May 2019 00:46:54 +0200 Subject: [PATCH] Javadoc, checkstyle, travis etc. --- .travis.yml | 10 +- build/checkstyle/checkstyle.xml | 288 ++++++++++++++++++ build/checkstyle/header.txt | 15 + compressedint/pom.xml | 1 + .../zchunk/compressedint/CompressedInt.java | 26 ++ .../compressedint/CompressedIntFactory.java | 26 ++ .../compressedint/CompressedIntUtil.java | 21 +- compression/compression-api/pom.xml | 2 +- .../compression/api/CompressionAlgorithm.java | 14 + .../api/CompressionAlgorithmFactory.java | 9 + .../api/internal/ReflectionUtil.java | 20 ++ .../zchunk/fileformat/IndexChecksumType.java | 12 +- .../zchunk/fileformat/ZChunkHeader.java | 10 +- .../zchunk/fileformat/ZChunkHeaderIndex.java | 2 + .../zchunk/fileformat/ZChunkHeaderLead.java | 2 +- .../fileformat/ZChunkHeaderPreface.java | 1 - .../fileformat/err/InvalidFileException.java | 2 + .../zchunk/fileformat/util/ChecksumUtil.java | 14 +- pom.xml | 48 +++ 19 files changed, 495 insertions(+), 28 deletions(-) create mode 100644 build/checkstyle/checkstyle.xml create mode 100644 build/checkstyle/header.txt diff --git a/.travis.yml b/.travis.yml index 09f1c28..3f5c93a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,18 +19,12 @@ stages: jobs: include: - stage: validations - script: mvn checkstyle:check + script: mvn clean install -DskipTests=true name: "Code validations (format, binary compatibilty, whitesource, etc.)" - stage: test script: mvn clean test - name: "Run tests for Java 8" - - # Test against Java 11 - - stage: java11 - script: mvn clean test - env: TRAVIS_JDK=adopt-openj9@1.11.0-2 - name: "Run tests for Java 11" + name: "Run tests for every java" cache: directories: diff --git a/build/checkstyle/checkstyle.xml b/build/checkstyle/checkstyle.xml new file mode 100644 index 0000000..da1d94b --- /dev/null +++ b/build/checkstyle/checkstyle.xml @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build/checkstyle/header.txt b/build/checkstyle/header.txt new file mode 100644 index 0000000..36a1e4e --- /dev/null +++ b/build/checkstyle/header.txt @@ -0,0 +1,15 @@ +/* + * Copyright 2019, the zchunk-java contributors. + * + * 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. + */ diff --git a/compressedint/pom.xml b/compressedint/pom.xml index 7d72d65..500fedd 100644 --- a/compressedint/pom.xml +++ b/compressedint/pom.xml @@ -22,6 +22,7 @@ zchunk-parent de.bmarwell.zchunk 1.0.0-SNAPSHOT + ../pom.xml 4.0.0 diff --git a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedInt.java b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedInt.java index eaa8056..f9b038d 100644 --- a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedInt.java +++ b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedInt.java @@ -21,6 +21,11 @@ public interface CompressedInt { + /** + * Return the compressed int as compressed bytes. This is useful to determine the original arrray length. + * + * @return the compressed int as bytes. + */ byte[] getCompressedBytes(); /** @@ -31,12 +36,33 @@ public interface CompressedInt { @Value.Lazy BigInteger getValue(); + /** + * Returns the value as signed(!) long value. As the compressedInt value may exceed {@link Long#MAX_VALUE}, it might throw an {@link + * ArithmeticException}. + * + * @return the value as signed long (normal java use). + * @throws ArithmeticException + * if the value exceeds {@link Long#MAX_VALUE}. + */ @Value.Lazy long getLongValue(); + /** + * Returns the value as unsigned long value, so that it can overflow. + * + *

If your input value was {@code 0xffffffffffffffff}, this method will throw no exception and happily overflow and return {@code + * -1L}.

+ */ @Value.Lazy long getUnsignedLongValue(); + /** + * Tries to fit the value into an int. As int conversion is often needed for array indexing, this will always throw an {@link + * ArithmeticException}, if + * the content value does not fit into a signed integer. + * + * @return an int representing the {@link #getValue()} value. + */ @Value.Lazy int getIntValue(); } diff --git a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntFactory.java b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntFactory.java index bf9af56..e909fdd 100644 --- a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntFactory.java +++ b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntFactory.java @@ -25,6 +25,19 @@ private CompressedIntFactory() { // util class } + /** + * Try to parse a compressed in from a given byte array. + * + * @param input + * the input byte array. + * @return a compressed int if it was parseable. + * @throws IllegalArgumentException + * if the byte array has zero-length. + * @throws IllegalArgumentException + * if the byte array length (byte count) is larger than {@link CompressedIntUtil#MAX_COMPRESSED_INT_LENGTH}. + * @throws NullPointerException + * if input is {@code null}. + */ public static CompressedInt fromCompressedBytes(final byte[] input) { if (input.length > CompressedIntUtil.MAX_COMPRESSED_INT_LENGTH) { throw new IllegalArgumentException( @@ -52,6 +65,19 @@ public static CompressedInt valueOf(final long unsignedLongValue) { return fromCompressedBytes(unsignedBytes); } + /** + * Directly takes an open {@link InputStream} and tries to read as many bytes as it takes for the compressed integer to end. + * + *

Does not close the stream. That is the caller‘s responsibility.

+ * + * @param inputStream + * the not-closed stream to read from. + * @return a compresssed int. + * @throws IOException + * if we cannot read from the underlying stream. + * @throws IllegalArgumentException + * if the compressed int size (bytes read) will exceed {@link CompressedIntUtil#MAX_COMPRESSED_INT_LENGTH}. + */ public static CompressedInt readCompressedInt(final InputStream inputStream) throws IOException { int currentByte; int byteCounter = 0; diff --git a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntUtil.java b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntUtil.java index 3f53340..fae80fe 100644 --- a/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntUtil.java +++ b/compressedint/src/main/java/de/bmarwell/zchunk/compressedint/CompressedIntUtil.java @@ -45,7 +45,14 @@ private CompressedIntUtil() { // private util } - + /** + * Compress a long to a compressed int. The long will be interpreted as positive, which may be confusing. + * + *

E.g. All positive numbers will come out as expected. All negative numbers will exceed that value. + * The highest number you can convert is -{@code -1L}, which is interpreted as {@code 18446744073709551615 (2^64 - 1)}.

+ * + * @return a byte array which will never exceed the length of MAX_COMPRESSED_INT_LENGTH and will never have leading all-zero bytes. + */ public static byte[] compress(final long unsignedIntValue) { long modValue = unsignedIntValue; final byte[] tmp = new byte[MAX_COMPRESSED_INT_LENGTH]; @@ -73,6 +80,18 @@ public static byte[] compress(final long unsignedIntValue) { return out; } + /** + * Decompresses an unsignedint's bytevalue. + * + *

The result is stored as {@link BigInteger}, because values might exceed overflow {@link Long#MAX_VALUE} and end up as + * negative. With BigInteger, no such information is lost.

+ * + * @param compressedUnsignedInt + * the bytearray holding a compressed int to decompress. + * @return a {@link BigInteger} object holding the uncompressed unsigned int value. + * @throws IllegalArgumentException + * if parameter {@code compressedUnsignedInt::length} exceeds the value of {@link #MAX_COMPRESSED_INT_LENGTH}. + */ public static BigInteger decompress(final byte[] compressedUnsignedInt) { if (compressedUnsignedInt.length > MAX_COMPRESSED_INT_LENGTH) { throw new IllegalArgumentException("Compressed int too big!"); diff --git a/compression/compression-api/pom.xml b/compression/compression-api/pom.xml index e63e3ec..7e0cc74 100644 --- a/compression/compression-api/pom.xml +++ b/compression/compression-api/pom.xml @@ -24,7 +24,7 @@ de.bmarwell.zchunk zchunk-parent 1.0.0-SNAPSHOT - ../.. + ../../pom.xml compression-api diff --git a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithm.java b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithm.java index 2fa042d..d3d445e 100644 --- a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithm.java +++ b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithm.java @@ -24,9 +24,23 @@ @Value.Immutable public interface CompressionAlgorithm { + /** + * The type value as defined by {@code zchunk_format.txt}. + * + * @return the compressiontype as CompressedInt. + */ CompressedInt getCompressionTypeValue(); + /** + * A user-friendly name of the compression algorithm. + * + * @return the name of the compression algorithm. + */ String getName(); + /** + * A method that will take in a stream and output an uncompressed stream. + * @return a stream conversion method. + */ Function getOutputStreamSupplier(); } diff --git a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithmFactory.java b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithmFactory.java index b422d7a..7079f8e 100644 --- a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithmFactory.java +++ b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/CompressionAlgorithmFactory.java @@ -42,6 +42,15 @@ private CompressionAlgorithmFactory() { .orElse(null); } + /** + * Tries to load a compression algorithm. If it fails, it will return {@link UnknownAlgorithm}. + * + *

Warning! Unstable API, this might change to Optional some day.

+ * + * @param compressionType + * the compression type value as defined in {@code zchunk_format.txt}. + * @return a compression algorithm which can decompress an input stream. + */ public static CompressionAlgorithm forType(final long compressionType) { return Optional.ofNullable(getTypeMappings().get(compressionType)) .flatMap(ReflectionUtil::newInstance) diff --git a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/internal/ReflectionUtil.java b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/internal/ReflectionUtil.java index e5d7ee7..d2518fd 100644 --- a/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/internal/ReflectionUtil.java +++ b/compression/compression-api/src/main/java/de/bmarwell/zchunk/compression/api/internal/ReflectionUtil.java @@ -43,6 +43,17 @@ private ReflectionUtil() { // util } + /** + * Will try to load classes implementing clazz, from any package below rootpackage. + * + * @param rootPackage + * the root package to search in. + * @param clazz + * the class which should be implemented by the found classes. + * @param + * the class type. + * @return a list of classes implementing T / clazz. + */ public static List> loadImplementations(final String rootPackage, final Class clazz) { final List> classes = getClasses(rootPackage, clazz); @@ -136,6 +147,15 @@ private static List getListFromArray(final T[] input) { .orElseGet(Collections::emptyList); } + /** + * Tries to create a new instance using the default constructor. + * + * @param clazz + * the class to instantiate. + * @param + * the class type. + * @return {@link Optional#empty} if it did not succeed, Optional with an instance otherwise. + */ public static Optional newInstance(final Class clazz) { try { return Optional.of(clazz.newInstance()); diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/IndexChecksumType.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/IndexChecksumType.java index 3f8cc32..16fa41b 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/IndexChecksumType.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/IndexChecksumType.java @@ -21,11 +21,15 @@ import java.util.StringJoiner; /** + * Checksum type for everything in the index. + * + *

* Current values: - * 0 = SHA-1 - * 1 = SHA-256 - * 2 = SHA-512 - * 3 = SHA-512/128 (first 128 bits of SHA-512 checksum) + * 0 = SHA-1
+ * 1 = SHA-256
+ * 2 = SHA-512
+ * 3 = SHA-512/128 (first 128 bits of SHA-512 checksum)
+ *

*/ public enum IndexChecksumType { SHA1("SHA-1", -1), diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeader.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeader.java index a9f9053..bd0cfad 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeader.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeader.java @@ -19,13 +19,13 @@ import org.immutables.value.Value; /** - * The header consists of four parts: + * The header consists of four parts. * *
    - *
  • The lead: Everything necessary to validate the header
  • - *
  • The preface: Metadata about the zchunk file
  • - *
  • The index: Details about each chunk
  • - *
  • The signatures: Signatures used to sign the zchunk file
  • + *
  • The lead: Everything necessary to validate the header.
  • + *
  • The preface: Metadata about the zchunk file.
  • + *
  • The index: Details about each chunk.
  • + *
  • The signatures: Signatures used to sign the zchunk file.
  • *
*/ @Value.Immutable diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderIndex.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderIndex.java index 1f12dd9..78c7e01 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderIndex.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderIndex.java @@ -28,6 +28,8 @@ import org.immutables.value.Value; /** + * Header index. + * *
  * +=================+==========================+==================+
  * | Index size (ci) | Chunk checksum type (ci) | Chunk count (ci) |
diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderLead.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderLead.java
index 82e8898..26e6314 100644
--- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderLead.java
+++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderLead.java
@@ -24,7 +24,7 @@
 import org.immutables.value.Value;
 
 /**
- * The lead:
+ * The lead. * *

* +-+-+-+-+-+====================+==================+=================+
diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderPreface.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderPreface.java index b337753..1c56ace 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderPreface.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/ZChunkHeaderPreface.java @@ -31,7 +31,6 @@ * +===============+============+========================+
*
* (Optional elements will only be set if flag 1 is set to 1)
- * * +=============================+
* | Optional element count (ci) |
* +=============================+
diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/err/InvalidFileException.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/err/InvalidFileException.java index 81e7f2b..fbcf624 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/err/InvalidFileException.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/err/InvalidFileException.java @@ -23,6 +23,8 @@ public class InvalidFileException extends RuntimeException { + private static final long serialVersionUID = -1329481614175727163L; + private final @Nullable File sourceFile; public InvalidFileException(final String message) { diff --git a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/util/ChecksumUtil.java b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/util/ChecksumUtil.java index d1a1266..42affa9 100644 --- a/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/util/ChecksumUtil.java +++ b/fileformat/src/main/java/de/bmarwell/zchunk/fileformat/util/ChecksumUtil.java @@ -135,10 +135,10 @@ private static byte[] getPrefaceBytes(final ZChunkHeaderPreface preface) { ); if (preface.hasOptionalElements()) { + // TODO: optional elements header final byte[] prefaceWithOptional = concat( prefaceBytes, preface.getOptionalElementCount().getCompressedBytes() - // TODO: optional elements header ); return prefaceWithOptional; @@ -210,19 +210,19 @@ public static boolean isValidData(final ZChunkHeader zChunkHeader, final File fi } - public static boolean allChunksAreValid(final ZChunkHeader zChunkFile, final File file) { - return zChunkFile.getIndex().getChunkInfoSortedByIndex().stream() - .allMatch(chunk -> chunkIsValid(chunk, zChunkFile, file)); + public static boolean allChunksAreValid(final ZChunkHeader zchunkFile, final File file) { + return zchunkFile.getIndex().getChunkInfoSortedByIndex().stream() + .allMatch(chunk -> chunkIsValid(chunk, zchunkFile, file)); } - private static boolean chunkIsValid(final ZChunkHeaderChunkInfo chunk, final ZChunkHeader zChunkFile, final File file) { - final long chunkOffset = OffsetUtil.getChunkOffset(zChunkFile, chunk.getCurrentIndex()); + private static boolean chunkIsValid(final ZChunkHeaderChunkInfo chunk, final ZChunkHeader zchunkFile, final File file) { + final long chunkOffset = OffsetUtil.getChunkOffset(zchunkFile, chunk.getCurrentIndex()); try (final FileInputStream fis = new FileInputStream(file)) { fis.skip(chunkOffset); final byte[] chunkData = new byte[chunk.getChunkLength().getIntValue()]; fis.read(chunkData); - final byte[] digest = zChunkFile.getIndex().getChunkChecksumType().digest(chunkData); + final byte[] digest = zchunkFile.getIndex().getChunkChecksumType().digest(chunkData); return Arrays.equals(chunk.getChunkChecksum(), digest); } catch (final IOException ioEx) { diff --git a/pom.xml b/pom.xml index 076c5f5..0ab4277 100644 --- a/pom.xml +++ b/pom.xml @@ -94,6 +94,11 @@ + true + true + + -Xlint:all,-processing + @@ -107,8 +112,51 @@ + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + ${maven.multiModuleProjectDirectory}/build/checkstyle/checkstyle.xml + + + ${maven.multiModuleProjectDirectory}/build/checkstyle/header.txt + + UTF-8 + true + true + false + + + + com.puppycrawl.tools + checkstyle + 8.20 + + + + + + + org.apache.maven.plugins + maven-checkstyle-plugin + 3.0.0 + + + checkstyle-check + validate + + check + + + + +