
org.glassfish.grizzly.osgi.httpservice.OSGiCleanMapper Maven / Gradle / Ivy
/*
* Copyright (c) 2009, 2020 Oracle and/or its affiliates. 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.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package org.glassfish.grizzly.osgi.httpservice;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.ReentrantLock;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.osgi.httpservice.util.Logger;
import org.osgi.service.http.HttpContext;
import jakarta.servlet.Servlet;
/**
* Context mapper. Supports complex context.
*
* @author Hubert Iwaniuk
*/
class OSGiCleanMapper {
private static final ReentrantLock lock = new ReentrantLock();
private static final TreeSet aliasTree = new TreeSet<>();
private static final Map registrations = new HashMap<>(16);
private static final Set registeredServlets = new HashSet<>(16);
private final Set localAliases = new HashSet<>(4);
private final HashMap> contextServletHandlerMap = new HashMap<>(3);
private final Logger logger;
protected final Map httpContextToServletContextMap = new HashMap<>();
// ------------------------------------------------------------ Constructors
protected OSGiCleanMapper(final Logger logger) {
this.logger = logger;
}
// ---------------------------------------------------------- Public Methods
/**
* Performs mapping of requested URI to registered alias if any.
*
* Works in two modes:
*
* - Full match - Checks for full match of resource (cutAfterSlash == false),
* - Reducing match - Checks {@link String#substring(int, int)} (0, {@link String#lastIndexOf(String)} ('/')) for
* match (cutAfterSlash == true).
*
*
* @param resource Resource to be mapped.
* @param cutAfterSlash Should cut off after last '/' before looking up.
* @return First matching alias, or null
if no match has been found.
*/
public static String map(String resource, boolean cutAfterSlash) {
String result;
String match = resource;
while (true) {
int i = 0;
if (cutAfterSlash) {
i = match.lastIndexOf('/');
if (i == -1) {
result = null;
break;
} else {
if (i == 0) {
match = "/";
} else {
match = resource.substring(0, i);
}
}
}
if (containsAlias(match)) {
result = match;
break;
} else if (i == 0) {
result = null;
break;
}
}
return result;
}
/**
* Checks if alias has been registered.
*
* @param alias Alias to check.
* @return true
if alias has been registered, else false
.
*/
public static boolean containsAlias(String alias) {
return aliasTree.contains(alias);
}
/**
* Checks if {@link Servlet} has been registered.
*
* @param servlet Servlet instance to check.
* @return true
if alias has been registered, else false
.
*/
public static boolean containsServlet(Servlet servlet) {
return registeredServlets.contains(servlet);
}
/**
* Gets mappers {@link ReentrantLock}.
*
* This {@link java.util.concurrent.locks.Lock} should protect mappers state.
*
* @return {@link java.util.concurrent.locks.Lock} to protect operations on mapper.
*/
public static ReentrantLock getLock() {
return lock;
}
/**
* Looks up {@link HttpHandler} registered under alias.
*
* @param alias Registered alias.
* @return {@link HttpHandler} registered under alias.
*/
static HttpHandler getHttpHandler(String alias) {
return registrations.get(alias);
}
/**
* Remove registration information for internal book keeping.
*
* @param alias Alias to unregister.
*/
public void recycleRegistrationData(String alias) {
if (containsAlias(alias)) {
// global cleanup
aliasTree.remove(alias);
HttpHandler handler = registrations.remove(alias);
handler.destroy();
// local cleanup
localAliases.remove(alias);
}
}
/**
* Add {@link HttpHandler}.
*
*
* @param alias Registration alias.
* @param handler HttpHandler handling requests for alias
.
*/
public void addHttpHandler(String alias, HttpHandler handler) {
if (!containsAlias(alias)) {
registerAliasHandler(alias, handler);
if (handler instanceof OSGiServletHandler) {
registeredServlets.add(((OSGiServletHandler) handler).getServletInstance());
}
localAliases.add(alias);
}
}
/**
* Checks if alias was registered by calling bundle.
*
* @param alias Alias to check for local registration.
* @return true
if alias was registered locally, else false
.
*/
public boolean isLocalyRegisteredAlias(String alias) {
return localAliases.contains(alias);
}
/**
* Executes unregistering of alias
optionally calling {@link jakarta.servlet.Servlet#destroy()}.
*
* @param alias Alias to unregister.
* @param callDestroyOnServlet If true
call {@link jakarta.servlet.Servlet#destroy()}, else don't call.
*/
public void doUnregister(String alias, boolean callDestroyOnServlet) {
if (containsAlias(alias)) {
HttpHandler httpHandler = getHttpHandler(alias);
if (httpHandler instanceof OSGiServletHandler) {
((OSGiHandler) httpHandler).getRemovalLock().lock();
try {
Servlet servlet = ((OSGiServletHandler) httpHandler).getServletInstance();
registeredServlets.remove(servlet);
if (callDestroyOnServlet) {
servlet.destroy();
}
} finally {
((OSGiHandler) httpHandler).getRemovalLock().unlock();
}
}
}
recycleRegistrationData(alias);
}
/**
* Gets locally registered aliases.
*
* @return Unmodifiable {@link Set} of locally registered aliases.
*/
public Set getLocalAliases() {
return Collections.unmodifiableSet(localAliases);
}
/**
* Gets all registered aliases.
*
* @return {@link Set} of all registered aliases.
*/
/* package */ static Set getAllAliases() {
return aliasTree;
}
/**
* Checks if {@link HttpContext} has been registered..
*
* @param httpContext Context to check.
* @return true
if httpContext has been registered.
*/
public boolean containsContext(HttpContext httpContext) {
return contextServletHandlerMap.containsKey(httpContext);
}
public List getContext(HttpContext httpContext) {
return contextServletHandlerMap.get(httpContext);
}
public void addContext(final HttpContext httpContext, final List servletHandlers) {
addContext(httpContext, null, servletHandlers);
}
public void addContext(final HttpContext httpContext, OSGiServletContext servletCtx, final List servletHandlers) {
if (servletCtx == null) {
servletCtx = new OSGiServletContext(httpContext, logger);
}
contextServletHandlerMap.put(httpContext, servletHandlers);
httpContextToServletContextMap.put(httpContext, servletCtx);
}
public OSGiServletContext getServletContext(final HttpContext httpContext) {
return httpContextToServletContextMap.get(httpContext);
}
private static boolean registerAliasHandler(String alias, HttpHandler httpHandler) {
boolean wasNew = aliasTree.add(alias);
if (wasNew) {
registrations.put(alias, httpHandler);
}
return wasNew;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy