blob: 38f1c866a79f20dbe42f6a3c6e5b84ec04379cf5 [file] [log] [blame]
/*
* Copyright (c) 2015, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// 01/05/2015 Rick Curtis
// - 455683: Automatically detect target server
// 04/24/2015 Rick Curtis
// - 465452: Throw ServerPlatformException rather than NPE on create null platformClass
package org.eclipse.persistence.platform.server;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.exceptions.ServerPlatformException;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.PropertiesHandler;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.server.glassfish.GlassfishPlatformDetector;
import org.eclipse.persistence.platform.server.was.WebSpherePlatformDetector;
import org.eclipse.persistence.platform.server.wls.WebLogicPlatformDetector;
import org.eclipse.persistence.sessions.DatabaseSession;
/**
* A utility class to interact with ServerPlatforms.
*/
public final class ServerPlatformUtils {
private static final List<ServerPlatformDetector> PLATFORMS = new ArrayList<ServerPlatformDetector>() {{
add(new NoServerPlatformDetector());
add(new WebSpherePlatformDetector());
add(new WebLogicPlatformDetector());
add(new GlassfishPlatformDetector());
}};
private static final String UNKNOWN_MARKER = "UNKNOWN";
private static String SERVER_PLATFORM_CLS;
private ServerPlatformUtils() {
// no instance please
}
/**
* @return The target-server class string that represents platform that is
* currently running. Return null if unknown.
*/
public static String detectServerPlatform(AbstractSession session) {
if (SERVER_PLATFORM_CLS == null) {
for (ServerPlatformDetector server : PLATFORMS) {
String res = server.checkPlatform();
if (res != null) {
// Convert property values to platform class
SERVER_PLATFORM_CLS = PropertiesHandler.getPropertyValue(PersistenceUnitProperties.TARGET_SERVER, res);
break;
}
}
// If we didn't detect a server, use the unknown marker so we don't
// continually try to detect the platform.
if (SERVER_PLATFORM_CLS == null) {
SERVER_PLATFORM_CLS = UNKNOWN_MARKER;
}
}
if (SERVER_PLATFORM_CLS == UNKNOWN_MARKER) {
return null;
} else {
//https://bugs.eclipse.org/bugs/show_bug.cgi?id=476018
//log message only when we know how loggers were set up
if (session != null) {
session.log(SessionLog.FINER, SessionLog.SERVER, "detect_server_platform", SERVER_PLATFORM_CLS);
} else {
AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.SERVER, "detect_server_platform", SERVER_PLATFORM_CLS);
}
return SERVER_PLATFORM_CLS;
}
}
/**
* Create an instance of {@link ServerPlatform} from parameters passed in.
*
* @param session {@link DatabaseSession} which will be passed to the constructor of {@link ServerPlatform}
* @param platformClass fully qualified name of the {@link ServerPlatform} implementation to initialize
* @param loader {@link ClassLoader} to look up given platformClass
*
* @return initialized instance of {@link ServerPlatform}
* @throws ServerPlatformException if supplied platformClass is not found, can not be initialized, or is null.
*
* @see ServerPlatformBase#ServerPlatformBase(DatabaseSession)
*/
public static ServerPlatform createServerPlatform(DatabaseSession session, String platformClass, ClassLoader loader) {
if (platformClass == null) {
throw ServerPlatformException.invalidServerPlatformClass(null, null);
}
Class cls = null;
try {
//try the supplied classloader
cls = findClass(platformClass, loader);
} catch (ClassNotFoundException | PrivilegedActionException ex) {
//fallback to EL loader
ClassLoader cl = ServerPlatformUtils.class.getClassLoader();
if (loader != cl) {
try {
cls = findClass(platformClass, cl);
} catch (ClassNotFoundException | PrivilegedActionException ex1) {
//ignore, throw first exception
throw ServerPlatformException.serverPlatformClassNotFound(platformClass, ex);
}
} else {
throw ServerPlatformException.serverPlatformClassNotFound(platformClass, ex);
}
}
final Class[] paramTypes = new Class[] { DatabaseSession.class };
final Object[] params = new Object[] { session };
ServerPlatform platform = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
try {
Constructor constructor = AccessController.doPrivileged(
new PrivilegedGetConstructorFor(cls, paramTypes, false));
platform = (ServerPlatform) AccessController.doPrivileged(
new PrivilegedInvokeConstructor(constructor, params));
} catch (PrivilegedActionException ex) {
throw ServerPlatformException.invalidServerPlatformClass(platformClass, ex);
}
} else {
try {
Constructor constructor = PrivilegedAccessHelper.getConstructorFor(cls, paramTypes, false);
platform = (ServerPlatform) PrivilegedAccessHelper.invokeConstructor(constructor, params);
} catch (NoSuchMethodException | IllegalAccessException
| InvocationTargetException | InstantiationException ex) {
throw ServerPlatformException.invalidServerPlatformClass(platformClass, ex);
}
}
return platform;
}
private static Class findClass(String className, ClassLoader loader) throws ClassNotFoundException, PrivilegedActionException {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
return AccessController.doPrivileged(new PrivilegedClassForName(className, false, loader));
} else {
return PrivilegedAccessHelper.getClassForName(className, false, loader);
}
}
}