/* * 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.httpd; import org.apache.openejb.AppContext; import org.apache.openejb.assembler.classic.OpenEjbConfiguration; import org.apache.openejb.assembler.classic.ServiceInfo; import org.apache.openejb.core.WebContext; import org.apache.openejb.loader.SystemInstance; import org.apache.openejb.spi.ContainerSystem; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.openejb.util.PropertyPlaceHolderHelper; import org.apache.webbeans.config.WebBeansContext; import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; public class OpenEJBHttpRegistry { public static final Logger log = Logger.getInstance(LogCategory.HTTPSERVER, OpenEJBHttpRegistry.class); protected final HttpListenerRegistry registry; protected final List<URI> baseUris = new ArrayList<URI>(); public OpenEJBHttpRegistry() { try { OpenEjbConfiguration configuration = SystemInstance.get().getComponent(OpenEjbConfiguration.class); for (ServiceInfo service : configuration.facilities.services) { if (service.className.equals(HttpServerFactory.class.getName())) { int port = Integer.parseInt(PropertyPlaceHolderHelper.simpleValue(service.properties.getProperty("port"))); String ip = service.properties.getProperty("bind"); if ("0.0.0.0".equals(ip)) { InetAddress[] addresses = InetAddress.getAllByName(ip); for (InetAddress address : addresses) { baseUris.add(new URI("http", null, address.getHostAddress(), port, null, null, null)); } } else { baseUris.add(new URI("http", null, ip, port, null, null, null)); } break; } } } catch (Exception e) { log.error("Unable to build base URIs for " + getClass().getSimpleName() + " registry", e); } registry = SystemInstance.get().getComponent(HttpListenerRegistry.class); } public HttpListener addWrappedHttpListener(HttpListener httpListener, ClassLoader classLoader, String regex) { HttpListener listener = new ClassLoaderHttpListener(httpListener, classLoader); registry.addHttpListener(listener, regex); return listener; } public List<String> getResolvedAddresses(String path) { String suffix = path; if (!path.startsWith("/")) { suffix = '/' + suffix; } List<String> addresses = new ArrayList<String>(); for (final URI baseUri : baseUris) { URI uri = baseUri; if (baseUri.getPort() == 0) { // if port was set to 0 we need to get httpejbd service port which was updated in SystemInstance final int port = Integer.parseInt(SystemInstance.get().getProperty("httpejbd.port", "0")); if (port != 0) { try { uri = new URI(baseUri.getScheme(), baseUri.getUserInfo(), baseUri.getHost(), port, baseUri.getPath(), baseUri.getQuery(), baseUri.getFragment()); } catch (final URISyntaxException e) { // no-op } } } final URI address = uri.resolve(suffix); addresses.add(address.toString()); } return addresses; } protected static class ClassLoaderHttpListener implements HttpListener { private final HttpListener delegate; private final ClassLoader classLoader; protected ClassLoaderHttpListener(HttpListener delegate, ClassLoader classLoader) { this.delegate = delegate; this.classLoader = classLoader; } public void onMessage(HttpRequest request, HttpResponse response) throws Exception { final Thread thread = Thread.currentThread(); final ClassLoader oldCl = thread.getContextClassLoader(); WebBeansContext wbc = null; try { if (request instanceof HttpRequestImpl) { final HttpRequestImpl httpRequest = HttpRequestImpl.class.cast(request); final WebContext web = findWebContext(request.getURI() == null ? request.getContextPath() : request.getURI().getPath()); if (web != null) { httpRequest.setApplication(web); if (web.getClassLoader() != null) { thread.setContextClassLoader(web.getClassLoader()); } else if (web.getAppContext().getClassLoader() != null) { thread.setContextClassLoader(web.getAppContext().getClassLoader()); } final String ctx = (web.getContextRoot().startsWith("/") ? "" : "/") + web.getContextRoot(); httpRequest.initPathFromContext(ctx); wbc = web.getWebbeansContext() != null ? web.getWebbeansContext() : web.getAppContext().getWebBeansContext(); } else { thread.setContextClassLoader(classLoader); if (SystemInstance.isInitialized()) { // avoid to rely on default if we didnt init it and then create lazily a context try { // surely an issue or something just tolerated for fake webapps wbc = WebBeansContext.currentInstance(); } catch (final IllegalStateException ise) { // no-op } } } if (wbc != null) { httpRequest.setAttribute("openejb_owb_context", wbc); initCdi(wbc, httpRequest).init(); } } delegate.onMessage(request, response); } finally { if (wbc != null) { HttpRequestImpl.class.cast(request).destroy(); } thread.setContextClassLoader(oldCl); } } private static WebContext findWebContext(final String path) { // TODO: this is a poor impl, would need registration of app etc to be better and have a rooter for (final AppContext app : SystemInstance.get().getComponent(ContainerSystem.class).getAppContexts()) { for (final WebContext web : app.getWebContexts()) { if (path.startsWith(web.getContextRoot()) || path.startsWith('/' + web.getContextRoot())) { return web; } } } return null; } private static HttpRequestImpl initCdi(final WebBeansContext context, final HttpRequestImpl request) { try { if (context.getBeanManagerImpl().isInUse()) { request.setBeginListener(new BeginWebBeansListener(context)); request.setEndListener(new EndWebBeansListener(context)); } } catch (IllegalStateException ise) { // no-op: ignore } return request; } public HttpListener getDelegate() { return delegate; } } }