Skip to content

Commit

Permalink
Replaced custom Reflection with java service loader. Bundle jar.
Browse files Browse the repository at this point in the history
  • Loading branch information
bmarwell committed May 20, 2019
1 parent 83f9b88 commit 27dc23a
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 226 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# maven
**/target
**/dependency-reduced-pom.xml

# intellij
.idea/**
Expand Down
80 changes: 80 additions & 0 deletions bundle/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>zchunk-parent</artifactId>
<groupId>io.github.zchunk</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>zchunk-bundle</artifactId>
<name>bundle</name>
<description>ZChunk library bundle jar</description>

<dependencies>
<dependency>
<groupId>io.github.zchunk</groupId>
<artifactId>zchunk-fileformat</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>io.github.zchunk</groupId>
<artifactId>zchunk-compression-none</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>io.github.zchunk</groupId>
<artifactId>zchunk-compression-zstd</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedGroupFilter>io.github.zchunk</shadedGroupFilter>
<shadedArtifactAttached>false</shadedArtifactAttached>
<createSourcesJar>true</createSourcesJar>
<promoteTransitiveDependencies>true</promoteTransitiveDependencies>
<createDependencyReducedPom>true</createDependencyReducedPom>

<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
<projectName>ZChunk Library</projectName>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
import io.github.zchunk.compression.api.err.DecompressionException;
import java.util.Map;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

@Disabled(value = "does not work with test-only dependencies. "
+ "Move into separate test module or create zchunk-all / zchunk-lib.")
public class ZChunkCompressionSupportTest {

@Test
public void testCompressionImplementations() {
final Map<Long, Class<CompressionAlgorithm>> algorithms = CompressionAlgorithmFactory.getKnownAlgorithms();
final Map<Long, CompressionAlgorithm> algorithms = CompressionAlgorithmFactory.getKnownAlgorithms();
Assertions.assertTrue(algorithms.size() >= 3);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@
package io.github.zchunk.compression.api;

import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import io.github.zchunk.compressedint.CompressedInt;
import io.github.zchunk.compression.algo.unknown.UnknownAlgorithm;
import io.github.zchunk.compression.api.internal.ReflectionUtil;
import java.util.AbstractMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.checkerframework.checker.initialization.qual.UnderInitialization;
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand All @@ -43,16 +45,10 @@ private CompressionAlgorithmFactory() {
// util class.
}

public static Map<Long, Class<CompressionAlgorithm>> getKnownAlgorithms() {
public static Map<Long, CompressionAlgorithm> getKnownAlgorithms() {
return unmodifiableMap(getTypeMappings());
}

private static Map.@Nullable Entry<Long, Class<CompressionAlgorithm>> mapEntryOrNull(final Class<CompressionAlgorithm> clazz) {
return ReflectionUtil.newInstance(clazz)
.map(compInstance -> new AbstractMap.SimpleEntry<>(compInstance.getCompressionTypeValue().getUnsignedLongValue(), clazz))
.orElse(null);
}

/**
* Tries to load a compression algorithm. If it fails, it will return {@link UnknownAlgorithm}.
*
Expand All @@ -64,17 +60,16 @@ public static Map<Long, Class<CompressionAlgorithm>> getKnownAlgorithms() {
*/
public static CompressionAlgorithm forType(final long compressionType) {
return Optional.ofNullable(getTypeMappings().get(compressionType))
.flatMap(ReflectionUtil::newInstance)
.orElseGet(UnknownAlgorithm::new);
}

/* Utility methods */

private static List<Class<CompressionAlgorithm>> getImplementations() {
private static List<CompressionAlgorithm> getImplementations() {
return ResourceHolder.newInstance(ROOT_PACKAGE).getImplementations();
}

private static Map<Long, Class<CompressionAlgorithm>> getTypeMappings() {
private static Map<Long, CompressionAlgorithm> getTypeMappings() {
return ResourceHolder.newInstance(ROOT_PACKAGE).getTypeMapping();
}

Expand All @@ -87,19 +82,19 @@ private static class ResourceHolder {

private static @Nullable ResourceHolder INSTANCE = null;

private final List<Class<CompressionAlgorithm>> implementations;
private final List<CompressionAlgorithm> implementations;

private final Map<Long, Class<CompressionAlgorithm>> typeMapping;
private final Map<Long, CompressionAlgorithm> typeMapping;

public ResourceHolder(final String rootPackage) {
this.implementations = loadImplementations(rootPackage, CompressionAlgorithm.class);
public ResourceHolder() {
this.implementations = loadImplementations();
this.typeMapping = loadTypeMapping(this.implementations);
}

@EnsuresNonNull({"INSTANCE"})
public static ResourceHolder newInstance(final String rootPackage) {
if (INSTANCE == null) {
INSTANCE = new ResourceHolder(rootPackage);
INSTANCE = new ResourceHolder();
}

return INSTANCE;
Expand All @@ -108,39 +103,39 @@ public static ResourceHolder newInstance(final String rootPackage) {
/**
* 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 <T>
* the class type.
* @return a list of classes implementing T / clazz.
*/
public <T> List<Class<T>> loadImplementations(@UnderInitialization ResourceHolder this,
final String rootPackage,
final Class<T> clazz) {
final List<Class<T>> classes = ReflectionUtil.getClasses(rootPackage, clazz);

return classes.stream()
.filter(ReflectionUtil.classImplementsCompressionAlgorithm(clazz))
.collect(toList());
public List<CompressionAlgorithm> loadImplementations(@UnderInitialization ResourceHolder this) {
final ServiceLoader<CompressionAlgorithm> load = ServiceLoader.load(CompressionAlgorithm.class);
final Logger logger = Logger.getLogger("io.github.zchunk");

logger.info("ServiceLoader: " + load);

return StreamSupport.stream(load.spliterator(), false)
.peek(clazz2 -> logger.info("Class: " + clazz2.getClass()))
.collect(Collectors.toList());
}

private Map<Long, Class<CompressionAlgorithm>> loadTypeMapping(@UnderInitialization ResourceHolder this,
final List<Class<CompressionAlgorithm>> implementations) {
final Stream<@Nullable Entry<Long, Class<CompressionAlgorithm>>> entryStream = implementations.stream()
.map(CompressionAlgorithmFactory::mapEntryOrNull);
private Map<Long, CompressionAlgorithm> loadTypeMapping(@UnderInitialization ResourceHolder this,
final List<CompressionAlgorithm> implementations) {
final Stream<@Nullable Entry<Long, CompressionAlgorithm>> entryStream = implementations.stream()
.map(ResourceHolder::mapEntryOrNull);
return entryStream
.filter(Objects::nonNull)
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
}

public List<Class<CompressionAlgorithm>> getImplementations() {
public List<CompressionAlgorithm> getImplementations() {
return this.implementations;
}

public Map<Long, Class<CompressionAlgorithm>> getTypeMapping() {
public Map<Long, CompressionAlgorithm> getTypeMapping() {
return this.typeMapping;
}

private static Map.Entry<Long, CompressionAlgorithm> mapEntryOrNull(final CompressionAlgorithm clazz) {
return new AbstractMap.SimpleEntry<>(clazz.getCompressionTypeValue().getUnsignedLongValue(), clazz);
}
}

}
Loading

0 comments on commit 27dc23a

Please # to comment.