Skip to content

Commit

Permalink
support hk2osgi locator,
Browse files Browse the repository at this point in the history
clean up javadoc

Signed-off-by: Lukas Jungmann <lukas.jungmann@oracle.com>
  • Loading branch information
lukasj committed Oct 29, 2021
1 parent 3286a1b commit 4d84d6b
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 66 deletions.
5 changes: 5 additions & 0 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@
<Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
<Implementation-Build-Id>${buildNumber}</Implementation-Build-Id>
<DynamicImport-Package>*</DynamicImport-Package>
<DynamicImport-Package>org.glassfish.hk2.osgiresourcelocator</DynamicImport-Package>
<Import-Package>
!org.glassfish.hk2.osgiresourcelocator,
*
</Import-Package>
</instructions>
</configuration>
<executions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public class ActivationDataFlavor {
* representationClass = representationClass<br>
* mimeType = mimeType<br>
* humanName = humanName
* <p>
*
* @param representationClass the class used in this ActivationDataFlavor
* @param mimeType the MIME type of the data represented by this class
Expand All @@ -76,7 +75,7 @@ public ActivationDataFlavor(Class<?> representationClass,
* otherwise:
* <p>
* representationClass = InputStream<p>
* mimeType = mimeType<p>
* mimeType = mimeType
*
* @param representationClass the class used in this ActivationDataFlavor
* @param humanPresentableName the human presentable name of the flavor
Expand All @@ -98,7 +97,7 @@ public ActivationDataFlavor(Class<?> representationClass,
* the result is the same as calling new
* ActivationDataFlavor(Class.forName()) as above, otherwise:
* <p>
* representationClass = InputStream<p>
* representationClass = InputStream<br>
* mimeType = mimeType
*
* @param mimeType the MIME type of the data represented by this class
Expand Down
10 changes: 3 additions & 7 deletions api/src/main/java/jakarta/activation/CommandInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public String getCommandClass() {
* this method will check if it implements the
* java.io.Externalizable interface. If it does, the bean's
* readExternal method will be called if an InputStream
* can be acquired from the DataHandler.<p>
* can be acquired from the DataHandler.
*
* @param dh The DataHandler that describes the data to be
* passed to the command.
Expand Down Expand Up @@ -142,9 +142,7 @@ private static final class Beans {
try {
Class<?> c = Class.forName("java.beans.Beans");
m = c.getDeclaredMethod("instantiate", ClassLoader.class, String.class);
} catch (ClassNotFoundException e) {
m = null;
} catch (NoSuchMethodException e) {
} catch (ClassNotFoundException | NoSuchMethodException e) {
m = null;
}
instantiateMethod = m;
Expand All @@ -163,9 +161,7 @@ static Object instantiate(ClassLoader loader, String cn)
// invoke Beans.instantiate
try {
return instantiateMethod.invoke(null, loader, cn);
} catch (InvocationTargetException e) {
exception = e;
} catch (IllegalAccessException e) {
} catch (InvocationTargetException | IllegalAccessException e) {
exception = e;
}

Expand Down
2 changes: 1 addition & 1 deletion api/src/main/java/jakarta/activation/DataHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ public String getContentType() {
* stream data into one end of the pipe. The other end of the pipe
* is returned to the caller. Because a thread is created to copy
* the data, IOExceptions that may occur during the copy can not be
* propagated back to the caller. The result is an empty stream.<p>
* propagated back to the caller. The result is an empty stream.
*
* @return the InputStream representing this data
* @exception IOException if an I/O error occurs
Expand Down
161 changes: 161 additions & 0 deletions api/src/main/java/jakarta/activation/FactoryFinder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0, which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*/

package jakarta.activation;

import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;


class FactoryFinder {

private static final Logger logger = Logger.getLogger("jakarta.activation");

private static final ServiceLoaderUtil.ExceptionHandler<RuntimeException> EXCEPTION_HANDLER =
new ServiceLoaderUtil.ExceptionHandler<RuntimeException>() {
@Override
public RuntimeException createException(Throwable throwable, String message) {
return new RuntimeException(message, throwable);
}
};

/**
* Finds the implementation {@code Class} object for the given
* factory type. If it fails and {@code tryFallback} is {@code true}
* finds the {@code Class} object for the given default class name.
* The arguments supplied must be used in order
* Note the default class name may be needed even if fallback
* is not to be attempted in order to check if requested type is fallback.
* <P>
* This method is package private so that this code can be shared.
*
* @return the {@code Class} object of the specified message factory;
* may not be {@code null}
*
* @param factoryClass factory abstract class or interface to be found
* @param defaultClassName the implementation class name, which is
* to be used only if nothing else
* is found; {@code null} to indicate
* that there is no default class name
* @param tryFallback whether to try the default class as a
* fallback
* @exception RuntimeException if there is a SOAP error
*/
static <T> T find(Class<T> factoryClass,
String defaultClassName,
boolean tryFallback) throws RuntimeException {

ClassLoader tccl = ServiceLoaderUtil.contextClassLoader(EXCEPTION_HANDLER);
String factoryId = factoryClass.getName();

// Use the system property first
String className = fromSystemProperty(factoryId);
if (className != null) {
T result = newInstance(className, defaultClassName, tccl);
if (result != null) {
return result;
}
}

// standard services: java.util.ServiceLoader
T factory = ServiceLoaderUtil.firstByServiceLoader(
factoryClass,
logger,
EXCEPTION_HANDLER);
if (factory != null) {
return factory;
}

// handling Glassfish/OSGi (platform specific default)
if (isOsgi()) {
T result = lookupUsingOSGiServiceLoader(factoryId);
if (result != null) {
return result;
}
}

// If not found and fallback should not be tried, return a null result.
if (!tryFallback)
return null;

// We didn't find the class through the usual means so try the default
// (built in) factory if specified.
if (defaultClassName == null) {
throw new RuntimeException(
"Provider for " + factoryId + " cannot be found", null);
}
return newInstance(defaultClassName, defaultClassName, tccl);
}

private static <T> T newInstance(String className, String defaultClassName, ClassLoader tccl) throws RuntimeException {
return ServiceLoaderUtil.newInstance(
className,
defaultClassName,
tccl,
EXCEPTION_HANDLER);
}

private static String fromSystemProperty(String factoryId) {
String systemProp = getSystemProperty(factoryId);
return systemProp;
}

private static String getSystemProperty(final String property) {
logger.log(Level.FINE, "Checking system property {0}", property);
String value = AccessController.doPrivileged(new PrivilegedAction<String>() {
@Override
public String run() {
return System.getProperty(property);
}
});
logFound(value);
return value;
}

private static void logFound(String value) {
if (value != null) {
logger.log(Level.FINE, " found {0}", value);
} else {
logger.log(Level.FINE, " not found");
}
}

private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader";

private static boolean isOsgi() {
try {
Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
return true;
} catch (ClassNotFoundException ignored) {
}
return false;
}

@SuppressWarnings({"unchecked"})
private static <T> T lookupUsingOSGiServiceLoader(String factoryId) {
try {
// Use reflection to avoid having any dependency on HK2 ServiceLoader class
Class<?> serviceClass = Class.forName(factoryId);
Class<?>[] args = new Class<?>[]{serviceClass};
Class<?> target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
Method m = target.getMethod("lookupProviderInstances", Class.class);
Iterator<?> iter = ((Iterable<?>) m.invoke(null, (Object[]) args)).iterator();
return iter.hasNext() ? (T) iter.next() : null;
} catch (Exception ignored) {
// log and continue
return null;
}
}

}
Loading

0 comments on commit 4d84d6b

Please sign in to comment.