org.apache.openejb.server.hessian.TomcatHessianRegistry Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.server.hessian;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
import org.apache.catalina.Engine;
import org.apache.catalina.Service;
import org.apache.catalina.Valve;
import org.apache.catalina.Wrapper;
import org.apache.catalina.authenticator.BasicAuthenticator;
import org.apache.catalina.authenticator.DigestAuthenticator;
import org.apache.catalina.authenticator.NonLoginAuthenticator;
import org.apache.catalina.authenticator.SSLAuthenticator;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.deploy.LoginConfig;
import org.apache.catalina.deploy.SecurityCollection;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.openejb.assembler.classic.WebAppBuilder;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.server.httpd.util.HttpUtil;
import org.apache.tomee.catalina.IgnoredStandardContext;
import org.apache.tomee.catalina.OpenEJBValve;
import org.apache.tomee.catalina.TomcatWebAppBuilder;
import org.apache.tomee.loader.TomcatHelper;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TomcatHessianRegistry implements HessianRegistry {
private static final String TOMEE_HESSIAN_SECURITY_ROLE_PREFIX = "tomee.hessian.security-role.";
private final Map> fakeContexts = new HashMap>();
private Engine engine;
private List connectors;
public TomcatHessianRegistry() {
final StandardServer standardServer = TomcatHelper.getServer();
for (final Service service : standardServer.findServices()) {
if (Engine.class.isInstance(service.getContainer())) {
connectors = Arrays.asList(service.findConnectors());
engine = Engine.class.cast(service.getContainer());
break;
}
}
}
@Override
public String deploy(final ClassLoader loader, final HessianServer listener,
final String hostname, final String app,
final String authMethod, final String transportGuarantee,
final String realmName, final String name) throws URISyntaxException {
Container host = engine.findChild(hostname);
if (host == null) {
host = engine.findChild(engine.getDefaultHost());
if (host == null) {
throw new IllegalArgumentException("Invalid virtual host '" + host + "'. Do you have a matchiing Host entry in the server.xml?");
}
}
final String contextRoot = contextName(app);
Context context = Context.class.cast(host.findChild(contextRoot));
if (context == null) {
Pair fakeContext = fakeContexts.get(contextRoot);
if (fakeContext != null) {
context = fakeContext.getLeft();
fakeContext.setValue(fakeContext.getValue() + 1);
} else {
context = Context.class.cast(host.findChild(contextRoot));
if (context == null) {
fakeContext = fakeContexts.get(contextRoot);
if (fakeContext == null) {
context = createNewContext(loader, authMethod, transportGuarantee, realmName, app);
fakeContext = new MutablePair(context, 1);
fakeContexts.put(contextRoot, fakeContext);
} else {
context = fakeContext.getLeft();
fakeContext.setValue(fakeContext.getValue() + 1);
}
}
}
}
final String servletMapping = generateServletPath(name);
Wrapper wrapper = Wrapper.class.cast(context.findChild(servletMapping));
if (wrapper != null) {
throw new IllegalArgumentException("Servlet " + servletMapping + " in web application context " + context.getName() + " already exists");
}
wrapper = context.createWrapper();
wrapper.setName(HESSIAN.replace("/", "") + "_" + name);
wrapper.setServlet(new OpenEJBHessianServlet(listener));
context.addChild(wrapper);
context.addServletMapping(servletMapping, wrapper.getName());
if ("BASIC".equals(authMethod) && StandardContext.class.isInstance(context)) {
final StandardContext standardContext = StandardContext.class.cast(context);
boolean found = false;
for (final Valve v : standardContext.getPipeline().getValves()) {
if (LimitedBasicValve.class.isInstance(v) || BasicAuthenticator.class.isInstance(v)) {
found = true;
break;
}
}
if (!found) {
standardContext.addValve(new LimitedBasicValve(new LoginConfig(authMethod, realmName, null, null)));
}
}
final List addresses = new ArrayList();
for (final Connector connector : connectors) {
for (final String mapping : wrapper.findMappings()) {
final URI address = new URI(connector.getScheme(), null, host.getName(), connector.getPort(), contextRoot + mapping, null, null);
addresses.add(address.toString());
}
}
return HttpUtil.selectSingleAddress(addresses);
}
private static Context createNewContext(final ClassLoader classLoader, final String rAuthMethod, final String rTransportGuarantee, final String realmName, final String name) {
String path = name;
if (path == null) {
path = "/";
}
if (!path.startsWith("/")) {
path = "/" + path;
}
final StandardContext context = new IgnoredStandardContext();
context.setPath(path);
context.setDocBase("");
context.setParentClassLoader(classLoader);
context.setDelegate(true);
context.setName(name);
TomcatWebAppBuilder.class.cast(SystemInstance.get().getComponent(WebAppBuilder.class)).initJ2EEInfo(context);
// Configure security
String authMethod = rAuthMethod;
if (authMethod != null) {
authMethod = authMethod.toUpperCase();
}
String transportGuarantee = rTransportGuarantee;
if (transportGuarantee != null) {
transportGuarantee = transportGuarantee.toUpperCase();
}
if (authMethod != null & !"NONE".equals(authMethod)) {
if ("BASIC".equals(authMethod) || "DIGEST".equals(authMethod) || "CLIENT-CERT".equals(authMethod)) {
//Setup a login configuration
final LoginConfig loginConfig = new LoginConfig();
loginConfig.setAuthMethod(authMethod);
loginConfig.setRealmName(realmName);
context.setLoginConfig(loginConfig);
//Setup a default Security Constraint
final String securityRole = SystemInstance.get().getProperty(TOMEE_HESSIAN_SECURITY_ROLE_PREFIX + name, "default");
for (final String role : securityRole.split(",")) {
final SecurityCollection collection = new SecurityCollection();
collection.addMethod("GET");
collection.addMethod("POST");
collection.addPattern("/*");
collection.setName(role);
final SecurityConstraint sc = new SecurityConstraint();
sc.addAuthRole("*");
sc.addCollection(collection);
sc.setAuthConstraint(true);
sc.setUserConstraint(transportGuarantee);
context.addConstraint(sc);
context.addSecurityRole(role);
}
}
//Set the proper authenticator
if ("BASIC".equals(authMethod)) {
context.addValve(new BasicAuthenticator());
} else if ("DIGEST".equals(authMethod)) {
context.addValve(new DigestAuthenticator());
} else if ("CLIENT-CERT".equals(authMethod)) {
context.addValve(new SSLAuthenticator());
} else if ("NONE".equals(authMethod)) {
context.addValve(new NonLoginAuthenticator());
}
context.getPipeline().addValve(new OpenEJBValve());
} else {
throw new IllegalArgumentException("Invalid authMethod: " + authMethod);
}
return context;
}
private static String generateServletPath(String name) {
return HESSIAN + name;
}
private static String contextName(final String app) {
if (!app.startsWith("/") && !app.isEmpty()) {
return "/" + app;
}
return app;
}
@Override
public void undeploy(final String hostname, final String app, final String name) {
Container host = engine.findChild(hostname);
if (host == null) {
host = engine.findChild(engine.getDefaultHost());
if (host == null) {
throw new IllegalArgumentException("Invalid virtual host '" + host + "'. Do you have a matchiing Host entry in the server.xml?");
}
}
final String contextRoot = contextName(app);
final Pair fakeContext = fakeContexts.get(contextRoot);
if (fakeContext != null) {
fakeContext.setValue(fakeContext.getValue() - 1);
if (fakeContext.getValue() == 0) {
fakeContexts.remove(contextRoot);
host.removeChild(fakeContext.getKey());
}
}
}
protected static class LimitedBasicValve extends BasicAuthenticator {
private final LoginConfig fakeLoginConfig;
protected LimitedBasicValve(final LoginConfig fakeLoginConfig) {
this.fakeLoginConfig = fakeLoginConfig;
}
@Override
public void invoke(final Request request, final Response response) throws IOException, ServletException {
final String requestURI = request.getDecodedRequestURI();
if (requestURI.startsWith(HESSIAN)) {
if (!authenticate(request, response, fakeLoginConfig)) {
return;
}
}
getNext().invoke(request, response);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy