Skip to content

Commit

Permalink
Refactor Jandex utility methods to be more reusable
Browse files Browse the repository at this point in the history
  • Loading branch information
baloo42 committed May 9, 2024
1 parent 3ac2865 commit 2842f0d
Show file tree
Hide file tree
Showing 8 changed files with 182 additions and 126 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class CustomResourceClassLoader {

private ClassLoader parentClassLoader;

private ClassLoader classLoader;
private ClassLoader cachedClassLoader;

public CustomResourceClassLoader withParentClassLoader(ClassLoader parentClassLoader) {
this.parentClassLoader = parentClassLoader;
Expand Down Expand Up @@ -74,8 +74,8 @@ private Class<?> loadClass(String className) {
}

private ClassLoader getClassLoader() {
if (classLoader != null) {
return classLoader;
if (cachedClassLoader != null) {
return cachedClassLoader;
}

if (!classpathElements.isEmpty()) {
Expand All @@ -89,19 +89,19 @@ private ClassLoader getClassLoader() {
}).toArray(URL[]::new);

if (parentClassLoader != null) {
this.classLoader = new URLClassLoader(urls, parentClassLoader);
this.cachedClassLoader = new URLClassLoader(urls, parentClassLoader);
} else {
this.classLoader = new URLClassLoader(urls);
this.cachedClassLoader = new URLClassLoader(urls);
}
} else {
if (parentClassLoader != null) {
this.classLoader = parentClassLoader;
this.cachedClassLoader = parentClassLoader;
} else {
this.classLoader = Thread.currentThread().getContextClassLoader();
this.cachedClassLoader = Thread.currentThread().getContextClassLoader();
}
}

return classLoader;
return cachedClassLoader;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class CustomResourceCollector {
private static final Logger log = LoggerFactory.getLogger(CustomResourceCollector.class);

private final CustomResourceClassLoader customResourceClassLoader = new CustomResourceClassLoader();
private final CustomResourceJandexCollector jandexCollector = new CustomResourceJandexCollector();
private final JandexCustomResourceClassScanner jandexCustomResourceClassScanner = new JandexCustomResourceClassScanner();

private final Set<String> customResourceClassNames = new HashSet<>();

Expand Down Expand Up @@ -78,27 +78,27 @@ public CustomResourceCollector withCustomResourceClasses(Collection<String> clas
}

public CustomResourceCollector withIndex(IndexView... index) {
jandexCollector.withIndex(index);
jandexCustomResourceClassScanner.withIndex(index);
return this;
}

public CustomResourceCollector withIndices(Collection<IndexView> indices) {
jandexCollector.withIndices(indices);
jandexCustomResourceClassScanner.withIndices(indices);
return this;
}

public CustomResourceCollector withFileToIndex(File... files) {
jandexCollector.withFileToIndex(files);
jandexCustomResourceClassScanner.withFileToIndex(files);
return this;
}

public CustomResourceCollector withFilesToIndex(Collection<File> files) {
jandexCollector.withFilesToIndex(files);
jandexCustomResourceClassScanner.withFilesToIndex(files);
return this;
}

public CustomResourceCollector withForceIndex(boolean forceIndex) {
jandexCollector.withForceIndex(forceIndex);
jandexCustomResourceClassScanner.withForceIndex(forceIndex);
return this;
}

Expand Down Expand Up @@ -127,10 +127,10 @@ public CustomResourceCollector withExcludePackages(Collection<String> packages)
private List<Class<? extends HasMetadata>> findCustomResourceClassesAsList() {
Set<String> customResourcesClassNames = new HashSet<>(customResourceClassNames);

// use indices only if custom resource class names are not explicitly given
// search only if custom resource class names are not explicitly given
if (customResourcesClassNames.isEmpty()) {
customResourcesClassNames.addAll(jandexCollector.findCustomResourceClasses());
log.debug("Found {} custom resource classes before filtering", customResourcesClassNames.size());
customResourcesClassNames.addAll(jandexCustomResourceClassScanner.findCustomResourceClasses());
log.debug("Found {} custom resource classes", customResourcesClassNames.size());
} else {
log.debug("Using explicit {} custom resource classes and skip scanning", customResourcesClassNames);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,57 @@
import io.fabric8.kubernetes.model.annotation.Group;
import io.fabric8.kubernetes.model.annotation.Version;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.CompositeIndex;
import org.jboss.jandex.Index;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
* Collects multiple Jandex index sources and allows to find Custom Resource class names by using
* {@link CustomResourceJandexCollector#findCustomResourceClasses()} in the resulting composite index.
* Collects multiple Jandex index sources and allows to find Custom Resource class names in the
* resulting composite index by using {@link JandexCustomResourceClassScanner#findCustomResourceClasses()}.
* <p>
* If not overridden by {@link JandexCustomResourceClassScanner#forceIndex}, the implementation uses an
* existing Jandex index if found in the source. Otherwise, the index will be created on the fly.
* </p>
*
* @see Index
* @see JandexIndexer
* @see JandexUtils
*/
class CustomResourceJandexCollector {

private static final Logger log = LoggerFactory.getLogger(CustomResourceJandexCollector.class);
public class JandexCustomResourceClassScanner {

private final List<IndexView> indices = new LinkedList<>();
private final Set<File> filesToIndex = new HashSet<>();

/**
* If <code>true</code>, indices will always be created even if an index exists at the source.
*/
private boolean forceIndex = false;

public CustomResourceJandexCollector withForceIndex(boolean forceIndex) {
public JandexCustomResourceClassScanner withForceIndex(boolean forceIndex) {
this.forceIndex = forceIndex;
return this;
}

public CustomResourceJandexCollector withIndex(IndexView... index) {
public JandexCustomResourceClassScanner withIndex(IndexView... index) {
if (index != null) {
withIndices(Arrays.asList(index));
}
return this;
}

public CustomResourceJandexCollector withIndices(Collection<IndexView> indices) {
public JandexCustomResourceClassScanner withIndices(Collection<IndexView> indices) {
if (indices != null) {
indices.stream()
.filter(Objects::nonNull)
Expand All @@ -76,14 +79,14 @@ public CustomResourceJandexCollector withIndices(Collection<IndexView> indices)
return this;
}

public CustomResourceJandexCollector withFileToIndex(File... files) {
public JandexCustomResourceClassScanner withFileToIndex(File... files) {
if (files != null) {
withFilesToIndex(Arrays.asList(files));
}
return this;
}

public CustomResourceJandexCollector withFilesToIndex(Collection<File> files) {
public JandexCustomResourceClassScanner withFilesToIndex(Collection<File> files) {
if (files != null) {
files.stream()
.filter(Objects::nonNull)
Expand All @@ -92,39 +95,33 @@ public CustomResourceJandexCollector withFilesToIndex(Collection<File> files) {
return this;
}

public List<String> findCustomResourceClasses() {
Collection<IndexView> allIndices = new LinkedList<>();
allIndices.add(createBaseIndex());
allIndices.addAll(this.indices);

if (!filesToIndex.isEmpty()) {
Set<File> actualFilesToIndex = new HashSet<>();
for (File file : filesToIndex) {
if (forceIndex) {
// no lookup for existing indices
actualFilesToIndex.add(file);
} else {
Optional<Index> index = JandexUtils.findExistingIndex(file);
if (index.isPresent()) {
allIndices.add(index.get());
} else {
actualFilesToIndex.add(file);
}
}
}

log.debug("Creating {} indices", actualFilesToIndex.size());
allIndices.add(JandexIndexer.indexFor(actualFilesToIndex));
}
/**
* Finds Custom Resource classes in the pre-configured scope.
*
* @return the Custom Resource classes
*/
public Collection<String> findCustomResourceClasses() {
List<IndexView> actualIndices = new ArrayList<>(indices);
actualIndices.add(createBaseIndex());

CompositeIndex compositeIndex = CompositeIndex.create(allIndices);
return findCustomResourceClasses(compositeIndex).stream()
IndexView index = JandexUtils.createIndex(actualIndices, filesToIndex, forceIndex);

return findCustomResourceClasses(index).stream()
.map(ClassInfo::toString)
.collect(Collectors.toList());
}

/**
* Finds Custom Resource classes in an index.
*
* @param index the index
* @return the Custom Resource classes
*
* @see JandexCustomResourceClassScanner#createBaseIndex()
*/
private List<ClassInfo> findCustomResourceClasses(IndexView index) {
// Only works if HasMetadata and all intermediate classes (like CustomResource) have been indexed
// Only works if HasMetadata and all intermediate classes (like CustomResource)
// are included in given index.
return index.getAllKnownImplementors(HasMetadata.class)
.stream()
.filter(classInfo -> classInfo.hasAnnotation(Group.class))
Expand All @@ -133,9 +130,11 @@ private List<ClassInfo> findCustomResourceClasses(IndexView index) {
}

/**
* Creates the base index required to scan for custom resources.
* Creates the base index required to scan for Custom Resource classes.
*
* @return the base index.
*
* @see JandexCustomResourceClassScanner#findCustomResourceClasses(IndexView)
*/
private Index createBaseIndex() {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 Red Hat, Inc.
*
* 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 io.fabric8.crd.generator.collector;

public class JandexException extends RuntimeException {

public JandexException(String message) {
super(message);
}

public JandexException(String message, Throwable cause) {
super(message, cause);
}

public JandexException(Throwable cause) {
super(cause);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,19 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Stream;

/**
* Allows to create a Jandex index based on given class files, directories and JAR archives.
* Unlike {@link Index#of(File...)}, this implementation performs a recursive scan of the directories.
* <p>
* Unlike {@link Index#of(File...)}, this implementation performs a recursive scan
* of the directories and enforces some limits.
* </p>
*/
class JandexIndexer {

Expand All @@ -48,28 +48,10 @@ class JandexIndexer {
private static final String CLASS_FILE_SUFFIX = ".class";
private static final String JAR_FILE_SUFFIX = ".jar";

private final List<File> files = new ArrayList<>();

private int maxJarEntries = 10000;
private int maxJarEntries = 100000;
private long maxBytesReadFromJar = 100000000; // 100 MB
private long maxClassFileSize = 1000000; // 1 MB

public JandexIndexer withFile(File... file) {
if (file != null) {
withFiles(Arrays.asList(file));
}
return this;
}

public JandexIndexer withFiles(Collection<File> files) {
if (files != null) {
files.stream()
.filter(Objects::nonNull)
.forEach(this.files::add);
}
return this;
}

public JandexIndexer withMaxJarEntries(int maxJarEntries) {
if (maxJarEntries < 1)
throw new IllegalArgumentException("maxJarEntries must be greater than 0");
Expand All @@ -91,13 +73,17 @@ public JandexIndexer withMaxBytesReadFromJar(long maxBytesReadFromJar) {
return this;
}

public Index createIndex() {
public Index createIndex(File... files) {
return createIndex(Arrays.asList(files));
}

public Index createIndex(Collection<File> files) {
Indexer indexer = new Indexer();
appendToIndex(indexer);
appendToIndex(files, indexer);
return indexer.complete();
}

private void appendToIndex(Indexer indexer) {
private void appendToIndex(Collection<File> files, Indexer indexer) {
for (File file : files) {
if (file.isDirectory()) {
scanDirectoryAndAddToIndex(file, indexer);
Expand Down Expand Up @@ -180,12 +166,6 @@ private long addToIndex(InputStream inputStream, Indexer indexer) throws IOExcep
}
}

public static Index indexFor(Collection<File> files) {
return new JandexIndexer()
.withFiles(files)
.createIndex();
}

static class BoundedInputStream extends InputStream implements AutoCloseable {
private final long maxBytes;
private final InputStream inputStream;
Expand Down
Loading

0 comments on commit 2842f0d

Please sign in to comment.