Skip to content

Commit

Permalink
Refactorings around JNDI, optimizations, tests
Browse files Browse the repository at this point in the history
- JavaURLContext now uses System.Logger instead of LogFacade
  - faster, and at least now I can see what produces the log message
- NamedNamingObjectManager is not public any more
- SimpleJndiName.isValidJndiName - useful to check string without constructing
  an instance.
- TCK tests - added some times to javadocs
  - measured on Dell 7740 with Xeon E2286M and 64 GB RAM + SSD disk.

Signed-off-by: David Matějček <david.matejcek@omnifish.ee>
  • Loading branch information
dmatej committed Nov 14, 2022
1 parent 28494c1 commit fa3624a
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 143 deletions.
Expand Up @@ -96,7 +96,7 @@ public final class GlassfishNamingManagerImpl implements GlassfishNamingManager

private InvocationManager invMgr;

// FIXME: cosContext has nothing to do with the rest of the class.
// FIXME: cosContext has nothing to do with the rest of the class. It could be pushed to own class.
private Context cosContext;

/**
Expand Down Expand Up @@ -350,42 +350,29 @@ private JavaNamespace getAppNamespace(String appName) throws NamingException {
}


private JavaNamespace getNamespace(String componentId, SimpleJndiName logicalJndiName) throws NamingException {
LOG.log(TRACE, "getNamespace(componentId={0}, logicalJndiName={1})", componentId, logicalJndiName);
ComponentIdInfo info = componentIdInfo.get(componentId);
if (info == null) {
return getComponentNamespace(componentId);
}
return getNamespace(info.appName, info.moduleName, componentId, logicalJndiName);
}


private JavaNamespace getNamespace(String appName, String moduleName, String componentId,
SimpleJndiName logicalJndiName) throws NamingException {
private JavaNamespace getNamespace(ComponentIdInfo info, SimpleJndiName logicalJndiName) throws NamingException {
LOG.log(TRACE, "getNamespace(info, logicalJndiName={0})", logicalJndiName);
if (logicalJndiName.isJavaModule()) {
return getModuleNamespace(new AppModuleKey(appName, moduleName));
return getModuleNamespace(new AppModuleKey(info.appName, info.moduleName));
} else if (logicalJndiName.isJavaApp()) {
return getAppNamespace(appName);
return getAppNamespace(info.appName);
} else {
return getComponentNamespace(componentId);
return getComponentNamespace(info.componentId);
}
}


/**
* This method binds them in a java:namespace.
*/
private void bindToNamespace(JavaNamespace namespace, SimpleJndiName logicalJndiName, Object value)
throws NamingException {
LOG.log(DEBUG, "bindToNamespace(namespace={0}, logicalJndiName={1}, value={2})", namespace.name, logicalJndiName, value);
if (namespace.put(logicalJndiName, value) != null) {
LOG.log(WARNING, "Naming binding already exists for {0} in namespace {1}", logicalJndiName, namespace);
private void bindToNamespace(JavaNamespace namespace, SimpleJndiName jndiName, Object value,
boolean warnDuplicities) throws NamingException {
LOG.log(DEBUG, "bindToNamespace(namespace={0}, jndiName={1}, value={2})", namespace.name, jndiName, value);
if (namespace.put(jndiName, value) != null) {
LOG.log(warnDuplicities ? WARNING : TRACE, "Binding already exists for {0} in namespace {1}", jndiName,
namespace);
}
bindIntermediateContexts(namespace, logicalJndiName);
}

private boolean existsInNamespace(Map<SimpleJndiName, ?> namespace, SimpleJndiName logicalJndiName) {
return namespace.containsKey(logicalJndiName);
bindIntermediateContexts(namespace, jndiName);
}

@Override
Expand Down Expand Up @@ -430,10 +417,7 @@ public void bindToComponentNamespace(String appName, String moduleName, String c
moduleName, componentId);
return;
}
// FIXME: it is checked inside again, but with warning.
if (!existsInNamespace(namespace, logicalJndiName)) {
bindToNamespace(namespace, logicalJndiName, binding.getValue());
}
bindToNamespace(namespace, logicalJndiName, binding.getValue(), false);
}
}

Expand All @@ -448,7 +432,7 @@ public void bindToModuleNamespace(String appName, String moduleName, Collection<
for (JNDIBinding binding : bindings) {
SimpleJndiName logicalJndiName = binding.getName();
if (logicalJndiName.isJavaModule()) {
bindToNamespace(namespace, logicalJndiName, binding.getValue());
bindToNamespace(namespace, logicalJndiName, binding.getValue(), true);
}
}
}
Expand All @@ -461,7 +445,7 @@ public void bindToAppNamespace(String appName, Collection<? extends JNDIBinding>
for (JNDIBinding binding : bindings) {
SimpleJndiName logicalJndiName = binding.getName();
if (logicalJndiName.isJavaApp()) {
bindToNamespace(namespace, logicalJndiName, binding.getValue());
bindToNamespace(namespace, logicalJndiName, binding.getValue(), true);
}
}
}
Expand Down Expand Up @@ -582,16 +566,10 @@ private <T> T lookup(String componentId, SimpleJndiName name, Context ctx) throw
// generic jndi names
return (T) initialContext.lookup(name.toName());
}
ComponentIdInfo info = componentIdInfo.get(componentId);
boolean replaceName = info != null && info.treatComponentAsModule && name.isJavaComponent();
final SimpleJndiName replacedName;
if (replaceName) {
replacedName = name.changePrefix(JNDI_CTX_JAVA_MODULE);
} else {
replacedName = name;
}

Map<SimpleJndiName, Object> namespace = getNamespace(componentId, replacedName);
final ComponentIdInfo info = componentIdInfo.get(componentId);
final boolean replaceName = info != null && info.treatComponentAsModule && name.isJavaComponent();
final SimpleJndiName replacedName = replaceName ? name.changePrefix(JNDI_CTX_JAVA_MODULE) : name;
JavaNamespace namespace = info == null ? getComponentNamespace(componentId) : getNamespace(info, replacedName);
Object obj = namespace.get(replacedName);
if (obj == null) {
throw new NameNotFoundException("No object bound to name " + replacedName + " in namespace " + namespace);
Expand Down Expand Up @@ -641,7 +619,7 @@ private ArrayList<SimpleJndiName> listNames(SimpleJndiName name) throws NamingEx
logicalJndiName = name;
}

JavaNamespace namespace = getNamespace(componentId, logicalJndiName);
JavaNamespace namespace = info == null ? getComponentNamespace(componentId) : getNamespace(info, logicalJndiName);
Object obj = namespace.get(logicalJndiName);
if (obj == null) {
throw new NameNotFoundException("No object bound to name " + name + " in namespace " + namespace);
Expand Down
Expand Up @@ -17,9 +17,10 @@

package com.sun.enterprise.naming.impl;

import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.Hashtable;
import java.util.Objects;
import java.util.logging.Level;

import javax.naming.Binding;
import javax.naming.CompositeName;
Expand All @@ -39,7 +40,6 @@
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.internal.api.Globals;

import static com.sun.enterprise.naming.util.LogFacade.logger;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_APP;
import static org.glassfish.api.naming.SimpleJndiName.JNDI_CTX_JAVA_APP_ENV;
Expand All @@ -54,6 +54,8 @@
* object in that component's local namespace.
*/
public final class JavaURLContext implements Context, Cloneable {
private static final Logger LOG = System.getLogger(JavaURLContext.class.getName());

private static GlassfishNamingManagerImpl namingManager;

private final SimpleJndiName myName;
Expand Down Expand Up @@ -121,6 +123,7 @@ public JavaURLContext(JavaURLContext ctx, SerialContext sctx) {
*/
@Override
public Object lookup(String name) throws NamingException {
LOG.log(Level.TRACE, "lookup(name={0}); this={1}", name, this);
if (name.isEmpty()) {

// javadocs for Context.lookup: If name is empty, returns a new
Expand All @@ -130,80 +133,46 @@ public Object lookup(String name) throws NamingException {
return new JavaURLContext(myName, myEnv);
}

final SimpleJndiName fullName;
if (myName.isEmpty()) {
fullName = new SimpleJndiName(name);
} else if (myName.toString().equals(JNDI_CTX_JAVA)) {
fullName = new SimpleJndiName(myName + name);
} else {
fullName = new SimpleJndiName(myName + "/" + name);
// Preconstructed exception collecting all tries which ended with an exception.
final NamingException e = new NameNotFoundException("No object bound for " + name);
final SimpleJndiName fullName = toFullName(name);
LOG.log(Level.DEBUG, "Computed fullname={0} for name={1}", fullName, name);
if (fullName == null) {
// if this fails, there is no reason trying another.
throw e;
}

try {
Object obj = null;
// If we know for sure it's an entry within an environment namespace
if (isLookingUpEnv(fullName)) {
// refers to a dependency defined by the application
obj = namingManager.lookup(fullName, serialContext);
} else {
// It's either an application-defined dependency in a java:
// namespace or a special EE platform object.
// Check for EE platform objects first to prevent overriding.
obj = NamedNamingObjectManager.tryNamedProxies(fullName);
if (obj == null) {
obj = namingManager.lookup(fullName, serialContext);
}
}

if (obj == null) {
throw new NamingException("No object found for " + name);
{
Object obj = tryNamingManager(fullName, e);
if (obj != null) {
return obj;
}

return obj;
} catch (NamingException ex) {

ServiceLocator services = Globals.getDefaultHabitat();
ProcessEnvironment processEnv = services.getService(ProcessEnvironment.class);
if (fullName.isJavaApp() && processEnv.getProcessType() == ProcessType.ACC) {

// This could either be an attempt by an app client to access a portable
// remote session bean JNDI name via the java:app namespace or a lookup of
// an application-defined java:app environment dependency. Try them in
// that order.

Context ic = namingManager.getInitialContext();
String appName = (String) namingManager.getInitialContext().lookup(JNDI_CTX_JAVA_APP + "AppName");

Object obj = null;

if (!fullName.hasPrefix(JNDI_CTX_JAVA_APP_ENV) || !"java:app/env".equals(fullName.toString())) {
try {
// Translate the java:app name into the equivalent java:global name so that
// the lookup will be resolved by the server.
obj = ic.lookup(JNDI_CTX_JAVA_GLOBAL + appName + "/" + fullName.removePrefix());
} catch (NamingException e) {
logger.log(Level.FINE, "Trying global version of java:app ejb lookup", e);
}
}

if (obj == null) {
ComponentNamingUtil util = services.getService(ComponentNamingUtil.class);
SimpleJndiName internalGlobalJavaAppName = util.composeInternalGlobalJavaAppName(appName, fullName);
obj = ic.lookup(internalGlobalJavaAppName.toString());
}

if (obj == null) {
throw new NamingException("No object found for " + name);
}
final ServiceLocator services = Globals.getDefaultHabitat();
final ProcessEnvironment processEnv = services.getService(ProcessEnvironment.class);
if (fullName.isJavaApp() && processEnv.getProcessType() == ProcessType.ACC) {
// This could either be an attempt by an app client to access a portable
// remote session bean JNDI name via the java:app namespace or a lookup of
// an application-defined java:app environment dependency. Try them in
// that order.
final Context context = namingManager.getInitialContext();
String appName = (String) context.lookup(JNDI_CTX_JAVA_APP + "AppName");
if (!fullName.hasPrefix(JNDI_CTX_JAVA_APP_ENV) || !"java:app/env".equals(fullName.toString())) {
// Translate the java:app name into the equivalent java:global name so that
// the lookup will be resolved by the server.
String globalName = JNDI_CTX_JAVA_GLOBAL + appName + '/' + fullName.removePrefix();
Object obj = lookupOrCollectException(globalName, e, context::lookup);
if (obj != null) {
return obj;
}

}
ComponentNamingUtil util = services.getService(ComponentNamingUtil.class);
SimpleJndiName internalGlobalJavaAppName = util.composeInternalGlobalJavaAppName(appName, fullName);
Object obj = lookupOrCollectException(internalGlobalJavaAppName.toString(), e, context::lookup);
if (obj != null) {
return obj;

}

throw ex;
} catch (Exception ex) {
throw (NamingException) (new NameNotFoundException("No object bound for " + fullName)).initCause(ex);
}
throw e;
}


Expand Down Expand Up @@ -530,13 +499,43 @@ public String toString() {
}


private boolean isLookingUpEnv(SimpleJndiName jndiName) {
final String fullName = jndiName.toString();
if (fullName.startsWith(JNDI_CTX_JAVA_COMPONENT_ENV) || fullName.startsWith(JNDI_CTX_JAVA_MODULE_ENV)
|| fullName.startsWith(JNDI_CTX_JAVA_APP_ENV)) {
private SimpleJndiName toFullName(String name) {
if (!name.startsWith(JNDI_CTX_JAVA) && name.indexOf(':') != -1) {
// this is probably some generic JNDI name like jdbc:derby: or http://... etc.,
// not compatible with java contexts.
return null;
}
if (myName.isEmpty()) {
return new SimpleJndiName(name);
} else if (myName.toString().equals(JNDI_CTX_JAVA)) {
return new SimpleJndiName(myName + name);
} else {
return new SimpleJndiName(myName + "/" + name);
}
}


private Object tryNamingManager(final SimpleJndiName fullName, NamingException collector) throws NamingException {
// If we know for sure it's an entry within an environment namespace it might be a proxy.
if (!isAnyJavaEnvJndiName(fullName)) {
Object obj = lookupOrCollectException(fullName, collector, NamedNamingObjectManager::tryNamedProxies);
if (obj != null) {
return obj;
}
}
return lookupOrCollectException(fullName, collector, n -> namingManager.lookup(n, serialContext));
}


private static boolean isAnyJavaEnvJndiName(SimpleJndiName jndiName) {
if (jndiName == null || jndiName.isEmpty()) {
return false;
}
if (jndiName.hasPrefix(JNDI_CTX_JAVA_COMPONENT_ENV) || jndiName.hasPrefix(JNDI_CTX_JAVA_MODULE_ENV)
|| jndiName.hasPrefix(JNDI_CTX_JAVA_APP_ENV)) {
return true;
} else if ("java:comp/env".equals(fullName) || "java:module/env".equals(fullName)
|| "java:app/env".equals(fullName)) {
} else if (jndiName.toString().equals("java:comp/env") || jndiName.toString().equals("java:module/env")
|| jndiName.toString().equals("java:app/env")) {
return true;
}
return false;
Expand All @@ -547,4 +546,21 @@ private boolean isLookingUpEnv(SimpleJndiName jndiName) {
private static Hashtable<Object, Object> getMyEnv(Hashtable<Object, Object> environment) {
return environment == null ? new Hashtable<>() : (Hashtable<Object, Object>) environment.clone();
}


private static <N> Object lookupOrCollectException(final N jndiName, final NamingException collector,
final NamingFunction<N> lookup) {
try {
return lookup.applyName(jndiName);
} catch (NamingException e) {
collector.addSuppressed(e);
return null;
}
}


@FunctionalInterface
private interface NamingFunction<N> {
Object applyName(N jndiName) throws NamingException;
}
}
Expand Up @@ -40,7 +40,7 @@
/**
* @author Mahesh Kannan
*/
public final class NamedNamingObjectManager {
final class NamedNamingObjectManager {

private static final AtomicReference<ServiceLocator> locatorReference = new AtomicReference<>();
private static final Map<String, NamedNamingObjectProxy> proxies = new HashMap<>();
Expand All @@ -63,13 +63,13 @@ static void checkAndLoadProxies(ServiceLocator locator) {
}


public static Object tryNamedProxies(SimpleJndiName name) throws NamingException {
static Object tryNamedProxies(SimpleJndiName name) throws NamingException {
logger.log(Level.FINEST, "tryNamedProxies(name={0})", name);
NamedNamingObjectProxy proxy = getCachedProxy(name);
if (proxy != null) {
if (logger.isLoggable(Level.FINE)) {
logger.logp(Level.FINE, "NamedNamingObjectManager", "tryNamedProxies",
"found cached proxy [{0}] for [{1}]", new Object[] {proxy, name});
"Found cached proxy [{0}] for [{1}]", new Object[] {proxy, name});
}
return proxy.handle(name.toString());
}
Expand Down

0 comments on commit fa3624a

Please sign in to comment.