Skip to content

Commit

Permalink
[LOGMGR-261] Add a simple API to allow jboss-modules to implement a m…
Browse files Browse the repository at this point in the history
…odule loader for cases when the log manager is on the boot class path.
  • Loading branch information
jamezp committed Nov 12, 2019
1 parent fe03cc4 commit 97f6d2f
Show file tree
Hide file tree
Showing 5 changed files with 208 additions and 31 deletions.
30 changes: 30 additions & 0 deletions src/main/java/org/jboss/logmanager/JDKSpecific.java
Expand Up @@ -26,6 +26,7 @@
import java.util.Set;

import org.jboss.modules.Module;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.modules.Version;

/**
Expand Down Expand Up @@ -102,6 +103,12 @@ static void calculateCaller(ExtLogRecord logRecord) {
logRecord.setSourceLineNumber(element.getLineNumber());
if (JBOSS_MODULES) {
calculateModule(logRecord, clazz);
} else {
// If JBoss Modules is not installed we want to defer to a possible ModuleResolver
// implementation. JBoss Modules itself may have it's own implementation for cases when
// the log manager is on the boot class path.
logRecord.setSourceModuleName(ModuleResolverFactory.getInstance().getModuleNameOf(clazz));
logRecord.setSourceModuleVersion(ModuleResolverFactory.getInstance().getModuleVersionOf(clazz));
}
return;
}
Expand All @@ -120,6 +127,29 @@ static void calculateCaller(ExtLogRecord logRecord) {
}
}

static String getModuleNameOf(final Class<?> clazz) {
if (JBOSS_MODULES) {
final ClassLoader cl = clazz.getClassLoader();
if (cl instanceof ModuleClassLoader) {
return ((ModuleClassLoader) cl).getModule().getName();
}
}
return null;
}

static String getModuleVersionOf(final Class<?> clazz) {
if (JBOSS_MODULES) {
final ClassLoader cl = clazz.getClassLoader();
if (cl instanceof ModuleClassLoader) {
final Version version = ((ModuleClassLoader) cl).getModule().getVersion();
if (version != null) {
return version.toString();
}
}
}
return null;
}

private static void calculateModule(final ExtLogRecord logRecord, final Class<?> clazz) {
final Module module = Module.forClass(clazz);
if (module != null) {
Expand Down
67 changes: 67 additions & 0 deletions src/main/java/org/jboss/logmanager/ModuleResolver.java
@@ -0,0 +1,67 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2019 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.jboss.logmanager;

/**
* An interface which can be used to locate information about a module.
*
* <p>
* Note that if JBoss Modules is found on the class path for the log manager the {@link #getModuleNameOf(Class)} and
* {@link #getModuleVersionOf(Class)} will not be invoked on the resolver and the name and version will be resolved from
* JBoss Modules itself.
* </p>
*
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public interface ModuleResolver {

/**
* Retrieves the name of the module for the specified class.
*
* @param clazz the class to resolve the module for
*
* @return the name of the module for the class or {@code null} if it could not be determined
*/
default String getModuleNameOf(Class<?> clazz) {
return JDKSpecific.getModuleNameOf(clazz);
}

/**
* Retrieves the version of the module for the specified class.
*
* @param clazz the class to resolve the module for
*
* @return the version of the module for the class or {@code null} if it could not be determined
*/
default String getModuleVersionOf(Class<?> clazz) {
return JDKSpecific.getModuleVersionOf(clazz);
}

/**
* Determines the class loader for the module.
*
* @param name the name of the module
*
* @return the class loader for the module
*
* @throws IllegalArgumentException if an error occurs determining the class loader
*/
ClassLoader getModuleClassLoader(String name) throws IllegalArgumentException;
}
80 changes: 80 additions & 0 deletions src/main/java/org/jboss/logmanager/ModuleResolverFactory.java
@@ -0,0 +1,80 @@
/*
* JBoss, Home of Professional Open Source.
*
* Copyright 2019 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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 org.jboss.logmanager;

import org.jboss.modules.Module;
import org.jboss.modules.ModuleLoadException;
import org.jboss.modules.ModuleLoader;

/**
* The factory used to get an instance of the {@linkplain ModuleResolver module resolver}.
*
* @author <a href="mailto:jperkins@redhat.com">James R. Perkins</a>
*/
public class ModuleResolverFactory {
private static volatile ModuleResolver INSTANCE;

/**
* Returns the current instance of the {@link ModuleResolver}.
*
* @return the module resolver used to load modules
*/
@SuppressWarnings("Convert2Lambda")
public static ModuleResolver getInstance() {
ModuleResolver result = INSTANCE;
if (INSTANCE == null) {
synchronized (ModuleResolverFactory.class) {
if (INSTANCE == null) {
result = INSTANCE = new ModuleResolver() {
@Override
public ClassLoader getModuleClassLoader(final String name) throws IllegalArgumentException {
// If we're in a module use that loader, otherwise use the boot module loader
ModuleLoader moduleLoader = ModuleLoader.forClass(ModuleResolver.class);
if (moduleLoader == null) {
moduleLoader = Module.getBootModuleLoader();
}
try {
return moduleLoader.loadModule(name).getClassLoader();
} catch (ModuleLoadException e) {
throw new IllegalArgumentException("Could load module " + name, e);
}
}
};
}
}
}
return result;
}

/**
* Sets the module resolver to use for loading modules. If set to {@code null} a default module resolver will be
* used based on JBoss Modules.
*
* @param resolver the module resolver to use or {@code null} to use a default module resolver
*/
@SuppressWarnings("unused")
public static void setModuleResolver(final ModuleResolver resolver) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(LogContext.CONTROL_PERMISSION);
}
INSTANCE = resolver;
}
}
Expand Up @@ -34,10 +34,8 @@
import java.util.Map;
import java.util.regex.Pattern;

import org.jboss.logmanager.ModuleResolverFactory;
import org.jboss.logmanager.StandardOutputStreams;
import org.jboss.modules.Module;
import org.jboss.modules.ModuleIdentifier;
import org.jboss.modules.ModuleLoader;

/**
* @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
Expand All @@ -60,7 +58,7 @@ protected AbstractPropertyConfiguration(final Class<T> baseClass, final LogConte
this.constructorProperties = constructorProperties;
final ClassLoader classLoader;
if (moduleName != null) try {
classLoader = ModuleFinder.getClassLoader(moduleName);
classLoader = ModuleResolverFactory.getInstance().getModuleClassLoader(moduleName);
} catch (Throwable e) {
throw new IllegalArgumentException(String.format("Failed to load module \"%s\" for %s \"%s\"", moduleName, getDescription(), name), e);
}
Expand Down Expand Up @@ -546,18 +544,4 @@ private static ObjectProducer getDefaultValue(final Class<?> paramType) {
return SimpleObjectProducer.NULL_PRODUCER;
}
}

static class ModuleFinder {

private ModuleFinder() {
}

static ClassLoader getClassLoader(final String moduleName) throws Exception {
ModuleLoader moduleLoader = ModuleLoader.forClass(ModuleFinder.class);
if (moduleLoader == null) {
moduleLoader = Module.getBootModuleLoader();
}
return moduleLoader.loadModule(ModuleIdentifier.fromString(moduleName)).getClassLoader();
}
}
}
42 changes: 29 additions & 13 deletions src/main/java9/org/jboss/logmanager/JDKSpecific.java
Expand Up @@ -27,12 +27,12 @@
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Stream;

import org.jboss.modules.Module;
import org.jboss.modules.ModuleClassLoader;
import org.jboss.modules.Version;

/**
Expand Down Expand Up @@ -77,23 +77,37 @@ static void calculateCaller(ExtLogRecord logRecord) {
WALKER.walk(new CallerCalcFunction(logRecord));
}

static void calculateJdkModule(final ExtLogRecord logRecord, final Class<?> clazz) {
static String getModuleNameOf(final Class<?> clazz) {
if (JBOSS_MODULES) {
final ClassLoader cl = clazz.getClassLoader();
if (cl instanceof ModuleClassLoader) {
return ((ModuleClassLoader) cl).getModule().getName();
}
}
final java.lang.Module module = clazz.getModule();
if (module != null) {
logRecord.setSourceModuleName(module.getName());
final ModuleDescriptor descriptor = module.getDescriptor();
if (descriptor != null) {
final Optional<ModuleDescriptor.Version> optional = descriptor.version();
if (optional.isPresent()) {
logRecord.setSourceModuleVersion(optional.get().toString());
} else {
logRecord.setSourceModuleVersion(null);
}
return module.isNamed() ? module.getName() : null;
}

static String getModuleVersionOf(final Class<?> clazz) {
if (JBOSS_MODULES) {
final ClassLoader cl = clazz.getClassLoader();
if (cl instanceof ModuleClassLoader) {
final Version version = ((ModuleClassLoader) cl).getModule().getVersion();
return version == null ? null : version.toString();
}
}
final java.lang.Module module = clazz.getModule();
final ModuleDescriptor.Version version = module.isNamed() ? module.getDescriptor().version().orElse(null) : null;
return version == null ? null : version.toString();
}

private static void calculateJdkModule(final ExtLogRecord logRecord, final Class<?> clazz) {
// Default to the ModuleResolver instance to resolve these values.
logRecord.setSourceModuleName(ModuleResolverFactory.getInstance().getModuleNameOf(clazz));
logRecord.setSourceModuleVersion(ModuleResolverFactory.getInstance().getModuleVersionOf(clazz));
}

static void calculateModule(final ExtLogRecord logRecord, final Class<?> clazz) {
private static void calculateModule(final ExtLogRecord logRecord, final Class<?> clazz) {
final Module module = Module.forClass(clazz);
if (module != null) {
logRecord.setSourceModuleName(module.getName());
Expand Down Expand Up @@ -131,6 +145,8 @@ public Void apply(final Stream<StackWalker.StackFrame> stream) {
logRecord.setSourceFileName(frame.getFileName());
logRecord.setSourceLineNumber(frame.getLineNumber());
if (JBOSS_MODULES) {
// If JBoss Modules is installed directly invoke retrieving the module name and version from
// JBoss Modules rather than the overhead of using the ModuleResolver.
calculateModule(logRecord, clazz);
} else {
calculateJdkModule(logRecord, clazz);
Expand Down

0 comments on commit 97f6d2f

Please sign in to comment.