All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ogema.impl.security.ApplicationWebAccessManager Maven / Gradle / Ivy

There is a newer version: 2.2.1
Show newest version
/**
 * Copyright 2011-2018 Fraunhofer-Gesellschaft zur Förderung der angewandten Wissenschaften e.V.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.ogema.impl.security;

import java.net.URL;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import java.util.Objects;
import java.util.Set;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.ogema.accesscontrol.HttpConfigManagement;
import org.ogema.core.application.AppID;
import org.ogema.webadmin.AdminWebAccessManager;
import org.osgi.framework.Bundle;
import org.osgi.framework.PackagePermission;
import org.osgi.service.http.NamespaceException;

/**
 * WebAccessManager implementation that holds web resources for a single Application. Instances are created by
 * {@link ApplicationWebAccessFactory#createApplicationWebAccessManager(org.ogema.core.application.AppID) }.
 *
 * @author jlapp
 */
public class ApplicationWebAccessManager implements AdminWebAccessManager {

	final AppID appId;
	final ApplicationWebAccessFactory fac;
	final static String FILTER_APPLICATION = "FILTER_APPLICATION";
	private final static Permission adminPackagePermission = new PackagePermission(
			AdminWebAccessManager.class.getPackage().getName(), "import");
	private final AtomicReference headerManagement;

	volatile OgemaHttpContext ctx;

	ApplicationWebAccessManager(AppID appId, ApplicationWebAccessFactory fac, 
			AtomicReference headerManagement) {
		this.appId = appId;
		this.fac = fac;
		this.headerManagement = headerManagement;
	}

	private synchronized OgemaHttpContext getOrCreateHttpContext() {
		if (ctx == null) {
			ctx = new OgemaHttpContext(fac.pm, appId, headerManagement);
		}
		return ctx;
	}

	synchronized void close() {
		if (ctx != null) {
			for (String alias : ctx.resources.keySet()) {
				unregisterWebResource(alias, true);
			}
			for (String alias : ctx.servlets.keySet()) {
				unregisterWebResource(alias, true);
			}
			ctx.close();
		}
		ctx = null;
	}

	/**
	 * This method is called by the application or a osgi bundle. The registration is delegated to the http service with
	 * a OgemaHttpContext each App/Bundle. Bundle reference and the alias are registered by WebResourceManager so these
	 * information can be provided to security handling in OgemaHttpContext.
	 */
	@Override
	public String registerWebResource(String alias, String name) {
		String result = alias;
		// In this case we use the HttpContext already created for this bundle.
		// Otherwise we need a new one.
		OgemaHttpContext httpCon = getOrCreateHttpContext();

		alias = normalizePath(alias);
		name = normalizePath(name);

		try {
			// 1. register Resource to the http service
			fac.http.registerResources(alias, name, httpCon);
		} catch (NamespaceException e) {
			throw new RuntimeException("Webresource path already in use: " + alias);
		}

		httpCon.resources.put(result, name);
		return result;
	}

	/**
	 * Like registerWebResource above but registerServlet instead of registerResource
	 */
	@Override
	public String registerWebResource(String alias, Servlet servlet) {
		Objects.requireNonNull(servlet);
		OgemaHttpContext httpCon = getOrCreateHttpContext();

		alias = normalizePath(alias);

		String result = alias;

		try {
			// register Resource to the http service
			fac.http.registerServlet(alias, servlet, null, httpCon);
		} catch (NamespaceException e) {
			throw new RuntimeException("Servlet path already in use: " + alias);
		} catch (ServletException e) {
			throw new RuntimeException("Servlet exception " + alias, e);
		}
		httpCon.servlets.put(result, appId.getIDString());

		return result;
	}

	String generateAlias(String alias, AppID id) {
		return alias + id.getIDString().hashCode();
	}

	@Override
	public String registerWebResourcePath(String alias, Servlet servlet) {
		alias = normalizePath(alias);
		String newAlias = extendPath(alias);
		return registerWebResource(newAlias, servlet);
	}

	@Override
	public String registerWebResourcePath(String alias, String name) {
		alias = normalizePath(alias);
		name = normalizePath(name);
		String newAlias = extendPath(alias);
		return registerWebResource(newAlias, name);
	}

	@Override
	public void unregisterWebResource(String alias) {
		unregisterWebResource(alias, false);
	}

	private void unregisterWebResource(String alias, boolean silent) {
		final OgemaHttpContext ctx = this.ctx;
		if (!silent && (ctx == null || (ctx.resources.isEmpty() && ctx.servlets.isEmpty()))) {
			fac.logger.warn("unregisterWebResource called on empty context. alias={}", alias);
		}
		alias = normalizePath(alias);
		if (ctx != null) { // only happens if framework is shutting down
			ctx.unregisterResource(alias);
		}
		try {
			fac.http.unregister(alias);
		} catch (IllegalArgumentException iae) {
			if (!silent)
				fac.logger.info("No registration found " + alias);
		}
	}

	@Override
	public boolean unregisterWebResourcePath(String alias) {
		alias = normalizePath(alias);
		String newAlias = extendPath(alias);
		final OgemaHttpContext ctx = this.ctx;
		// OgemaHttpContext httpContext = getOrCreateHttpContext();
		if (ctx != null) { // only happens if framework is shutting down
			ctx.unregisterResource(newAlias);
		}
		try {
			fac.http.unregister(newAlias);
		} catch (IllegalArgumentException iae) {
			fac.logger.error("No registration found " + newAlias);
			return false;
		}
		return true;
	}

	private String extendPath(String alias) {
		char seperator = '/';
		String newAlias = appId.getBundle().getSymbolicName() + alias;
		newAlias = seperator + newAlias.replace('.', seperator);
		newAlias = newAlias.toLowerCase();

		// if the last character is "/" then remove it due to possible path exception
		if (newAlias.charAt(newAlias.length() - 1) == '/') {
			newAlias = newAlias.substring(0, newAlias.length() - 1);
		}
		return newAlias;
	}

	private static String normalizePath(String alias) {
		char seperator = '/';

		// always add "/" as prefix
		if (!alias.isEmpty() && alias.charAt(0) != seperator) {
			alias = seperator + alias;
		}

		return alias;
	}

	@Override
	public String getStartUrl() {

		// was called because key exists
		if (fac.baseUrls.containsKey(appId.getIDString())) {

			String baseUrl = fac.baseUrls.get(appId.getIDString());
			if (baseUrl.equals(FILTER_APPLICATION)) {
				return null;
			}

			// key does not exist so it was never called
		}
		else {
			Map registeredResources = getRegisteredResources(appId);
			final Bundle b = appId.getBundle();
			// Look for the first occurrence of index.html within the registered paths.
			Set> entries = registeredResources.entrySet();
			for (Entry e : entries) {
				String alias = e.getKey();
				final String path = e.getValue();
				final Enumeration urls = AccessController.doPrivileged(new PrivilegedAction>() {

					@Override
					public Enumeration run() {
						return b.findEntries(path, "index.html", true);
					}
				});
				if (urls != null) {
					String url = urls.nextElement().getPath();
					final int length = alias.length();
					int lastChar = alias.charAt(length - 1);
					if (length > 0 && lastChar == '/')
						return url.replaceFirst(path, alias.substring(0, length - 1));
					if (path.equals("/") && lastChar != '/')
						return alias + url;
					else
						return url.replaceFirst(path, alias);
				}
			}
		}
		return fac.baseUrls.get(appId.getIDString());
	}

	public void registerStartUrl(AppID appId, String url) {
		if (url == null) {
			url = FILTER_APPLICATION;
		}
		else {
			if (url.length() > 0) {
				if ('/' != url.charAt(0)) {
					url = "/" + url;
				}
			}
		}
		fac.baseUrls.put(appId.getIDString(), url);
	}

	@Override
	public void registerStartUrl(String url) {
		registerStartUrl(appId, url);
	}

	// public void setStartUrl(String url) {
	// registerStartUrl(appId, url);
	// }

	@Override
	@Deprecated
	public Map getRegisteredResources(AppID appid) {
		return fac.getRegisteredResources(appid);
	}

	@Override
	@Deprecated
	public Set getRegisteredServlets(AppID appid) {
		return fac.getRegisteredServlets(appid);
	}

	@Override
	public Map getRegisteredResources() {
		return getRegisteredResources(appId);
	}

	@Override
	public Set getRegisteredServlets() {
		return getRegisteredServlets(appId);
	}

	@Override
	public boolean authenticate(HttpSession ses, String usr, String pwd) {
		return fac.authenticate(ses, usr, pwd);
	}

	/**
	 * Proposal for a new API method: register a servlet as a static web page
	 * 
	 * @param servlet
	 * @param req
	 * @return null if not logged in, a size two String array {user, one-time-password} otherwise
	 */
	@Deprecated
	public String[] registerStaticResource(HttpServlet servlet, HttpServletRequest req) {
		return fac.registerStaticResource(servlet, req, appId);
	}

	@Override
	public StaticRegistration registerStaticWebResource(String alias, Servlet servlet) {
		final SecurityManager sman = System.getSecurityManager();
		if (sman != null)
			sman.checkPermission(adminPackagePermission);
		final String path = registerWebResource(alias, servlet); // ensures that ctx != null
		return getOrCreateHttpContext().addStaticRegistration(path, servlet, this);
	}

	@Override
	public String registerBasicResource(String alias, String path) {
		final SecurityManager sman = System.getSecurityManager();
		if (sman != null)
			sman.checkPermission(adminPackagePermission);
		final String result = registerWebResource(alias, path);
		getOrCreateHttpContext().addBasicResourceAlias(result);
		return result;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy