package org.glassfish.grizzly.websockets.glassfish;
import java.lang.reflect.Method;
import java.security.Principal;
import org.glassfish.grizzly.http.server.Request;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
public class GlassfishSupport {
private final GlassfishContext context;
private final GlassfishWrapper wrapper;
private final GlassfishManager manager;
private final HttpServletRequest request;
private GlassfishSession session;
public GlassfishSupport() {
manager = null;
request = null;
context = null;
wrapper = null;
}
public GlassfishSupport(final Object context, final Object wrapper, HttpServletRequest request) {
this.context = new GlassfishContext(context);
this.wrapper = new GlassfishWrapper(wrapper);
manager = this.context.getManager();
this.request = request;
}
public boolean isValid() {
return manager != null;
}
public boolean isUserInRole(String role) {
Principal userPrincipal = request.getUserPrincipal();
if (userPrincipal == null) {
return false;
}
if (context == null) {
return false;
}
GlassfishRealm realm = context.getRealm();
if (realm == null) {
return false;
}
String servletName = null;
if (wrapper != null) {
servletName = wrapper.getServletName();
String realRole = wrapper.findSecurityReference(role);
if (realRole != null &&
realm.hasRole(servletName, userPrincipal, realRole)) {
return true;
}
}
return realm.hasRole(servletName, userPrincipal, role);
}
public HttpSession getSession(boolean create) {
GlassfishSession gfSession = doGetSession(create);
if (gfSession != null) {
return gfSession.getSession();
} else {
return null;
}
}
private GlassfishSession doGetSession(boolean create) {
if (!isValid()) {
return null;
}
if (session != null && !session.isValid()) {
session = null;
}
if (session != null) {
return session;
}
final String requestedSessionId = request.getRequestedSessionId();
if (requestedSessionId != null) {
try {
session = manager.findSession(requestedSessionId, request);
} catch (Exception e) {
session = null;
}
if (session != null && !session.isValid()) {
session = null;
}
if (session != null) {
session.access();
return session;
}
}
if (!create) {
return null;
}
if (requestedSessionId != null && context.getReuseSessionID()) {
session = manager.createSession(requestedSessionId);
manager.removeFromInvalidatedSessions(requestedSessionId);
} else {
session = manager.createSession();
}
if (session != null) {
session.access();
return session;
} else {
return null;
}
}
public void updateUserPrincipal(Request grizzlyRequest) {
final GlassfishSession gfSession = doGetSession(false);
if (gfSession != null) {
grizzlyRequest.setUserPrincipal(gfSession.getPrincipal());
grizzlyRequest.getRequest().authType().setString(gfSession.getAuthType());
}
}
private static class GlassfishRealm {
private volatile static Boolean isChecked;
private static Method hasRoleMethod1;
private static Method hasRoleMethod2;
private final Object realm;
public GlassfishRealm(Object realm) {
this.realm = realm;
check();
}
public boolean hasRole(String servletName, Principal principal, String role) {
if (hasRoleMethod1 != null) {
return (Boolean) exec(hasRoleMethod1, servletName, principal, role);
} else {
return (Boolean) exec(hasRoleMethod2, principal, role);
}
}
private Object exec(Method m, Object... params) {
try {
return m.invoke(realm, params);
} catch (Throwable e) {
throw new IllegalStateException("Can't call method '" + m.getName() + "'", e);
}
}
private void check() {
if (isChecked == null) {
synchronized (GlassfishSession.class) {
if (isChecked == null) {
try {
try {
hasRoleMethod1 = realm.getClass().getMethod("hasRole", String.class, Principal.class, String.class);
} catch (Throwable t) {
hasRoleMethod2 = realm.getClass().getMethod("hasRole", Principal.class, String.class);
}
isChecked = true;
} catch (Throwable t) {
isChecked = false;
throw new IllegalStateException("GlassfishRealm can't be initialized", t);
}
}
}
} else if (!isChecked) {
throw new IllegalStateException("GlassfishRealm can't be initialized");
}
}
}
private static class GlassfishSession {
private volatile static Boolean isChecked;
private static Method isValidMethod;
private static Method getSessionMethod;
private static Method accessMethod;
private static Method getPrincipalMethod;
private static Method getAuthTypeMethod;
private final Object session;
public GlassfishSession(Object session) {
this.session = session;
check();
}
public boolean isValid() {
return (Boolean) exec(isValidMethod);
}
public HttpSession getSession() {
return (HttpSession) exec(getSessionMethod);
}
public void access() {
exec(accessMethod);
}
public Principal getPrincipal() {
return (Principal) exec(getPrincipalMethod);
}
public String getAuthType() {
return (String) exec(getAuthTypeMethod);
}
private Object exec(Method m, Object... params) {
try {
return m.invoke(session, params);
} catch (Throwable e) {
throw new IllegalStateException("Can't call method '" + m.getName() + "'", e);
}
}
private void check() {
if (isChecked == null) {
synchronized (GlassfishSession.class) {
if (isChecked == null) {
try {
isValidMethod = session.getClass().getMethod("isValid");
getSessionMethod = session.getClass().getMethod("getSession");
accessMethod = session.getClass().getMethod("access");
getPrincipalMethod = session.getClass().getMethod("getPrincipal");
getAuthTypeMethod = session.getClass().getMethod("getAuthType");
isChecked = true;
} catch (Throwable t) {
isChecked = false;
throw new IllegalStateException("GlassfishSession can't be initialized", t);
}
}
}
} else if (!isChecked) {
throw new IllegalStateException("GlassfishSession can't be initialized");
}
}
}
private static class GlassfishManager {
private volatile static Boolean isChecked;
private static Method findSessionMethod;
private static Method createSession0Method;
private static Method createSession1Method;
private static Method removeFromInvalidatedSessionsMethod;
private final Object manager;
private GlassfishManager(Object manager) {
this.manager = manager;
check();
}
public GlassfishSession findSession(String requestedSessionId, HttpServletRequest request) {
return wrapSession(exec(findSessionMethod, requestedSessionId, request));
}
public GlassfishSession createSession() {
return wrapSession(exec(createSession0Method));
}
public GlassfishSession createSession(String requestedSessionId) {
return wrapSession(exec(createSession1Method, requestedSessionId));
}
private void removeFromInvalidatedSessions(String requestedSessionId) {
if (removeFromInvalidatedSessionsMethod != null) {
exec(removeFromInvalidatedSessionsMethod, requestedSessionId);
}
}
private Object exec(Method m, Object... params) {
try {
return m.invoke(manager, params);
} catch (Throwable e) {
throw new IllegalStateException("Can't call method '" + m.getName() + "'", e);
}
}
private GlassfishSession wrapSession(Object session) {
return session != null ? new GlassfishSession(session) : null;
}
private void check() {
if (isChecked == null) {
synchronized (GlassfishManager.class) {
if (isChecked == null) {
try {
findSessionMethod = manager.getClass().getMethod("findSession", String.class, HttpServletRequest.class);
createSession0Method = manager.getClass().getMethod("createSession");
createSession1Method = manager.getClass().getMethod("createSession", String.class);
try {
removeFromInvalidatedSessionsMethod = manager.getClass().getDeclaredMethod("removeFromInvalidatedSessions", String.class);
} catch (Throwable e) {
}
isChecked = true;
} catch (Throwable t) {
isChecked = false;
throw new IllegalStateException("GlassfishSessionManager can't be initialized", t);
}
}
}
} else if (!isChecked) {
throw new IllegalStateException("GlassfishSessionManager can't be initialized");
}
}
}
private static class GlassfishContext {
private static Method getManagerMethod;
private static Method getReuseSessionIDMethod;
private static Method getRealmMethod;
private final Object context;
private GlassfishContext(Object context) {
this.context = context;
check();
}
public GlassfishManager getManager() {
return new GlassfishManager(exec(getManagerMethod));
}
public boolean getReuseSessionID() {
return (Boolean) exec(getReuseSessionIDMethod);
}
public GlassfishRealm getRealm() {
return new GlassfishRealm(exec(getRealmMethod));
}
private Object exec(Method m, Object... params) {
try {
return m.invoke(context, params);
} catch (Throwable e) {
throw new IllegalStateException("Can't call method '" + m.getName() + "'", e);
}
}
private void check() {
try {
getManagerMethod = context.getClass().getMethod("getManager");
getReuseSessionIDMethod = context.getClass().getMethod("getReuseSessionID");
getRealmMethod = context.getClass().getMethod("getRealm");
} catch (Throwable t) {
throw new IllegalStateException("GlassfishContext can't be initialized", t);
}
}
}
private static class GlassfishWrapper {
private static Method findSecurityReferenceMethod;
private static Method getServletNameMethod;
private final Object wrapper;
private GlassfishWrapper(Object wrapper) {
this.wrapper = wrapper;
check();
}
public String findSecurityReference(String name) {
return (String) exec(findSecurityReferenceMethod, name);
}
public String getServletName() {
return (String) exec(getServletNameMethod);
}
private Object exec(Method m, Object... params) {
try {
return m.invoke(wrapper, params);
} catch (Throwable e) {
throw new IllegalStateException("Can't call method '" + m.getName() + "'", e);
}
}
private void check() {
try {
findSecurityReferenceMethod = wrapper.getClass().getMethod("findSecurityReference", String.class);
getServletNameMethod = wrapper.getClass().getMethod("getServletName");
} catch (Throwable t) {
throw new IllegalStateException("GlassfishWrapper can't be initialized", t);
}
}
}
}