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

org.apache.cxf.dosgi.common.httpservice.HttpServiceManager 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.cxf.dosgi.common.httpservice;

import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import org.apache.cxf.Bus;
import org.apache.cxf.transport.http.DestinationRegistry;
import org.apache.cxf.transport.http.DestinationRegistryImpl;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component //
(//
    name = "org.apache.cxf.dosgi.http", //
    service = HttpServiceManager.class //
)
public class HttpServiceManager {
    /**
     * Prefix to create an absolute URL from a relative URL. See HttpServiceManager.getAbsoluteAddress
     * Defaults to: http://localhost:8181
     */
    public static final String KEY_HTTP_BASE = "httpBase";
    public static final String KEY_CXF_SERVLET_ALIAS = "cxfServletAlias";
    public static final String DEFAULT_CXF_SERVLET_ALIAS = "/cxf";
    private static final Logger LOG = LoggerFactory.getLogger(HttpServiceManager.class);

    private Map exportedAliases = Collections.synchronizedMap(new HashMap());
    private String httpBase;
    private String cxfServletAlias;
    private HttpService httpService;
    private BundleContext context;

    @Activate
    public void activate(ComponentContext compContext) {
        Dictionary config = compContext.getProperties();
        initFromConfig(config);
        this.context = compContext.getBundleContext();
    }

    public void initFromConfig(Dictionary config) {
        if (config == null) {
            config = new Hashtable();
        }
        this.httpBase = getWithDefault(config.get(KEY_HTTP_BASE), "http://localhost:8181");
        this.cxfServletAlias = getWithDefault(config.get(KEY_CXF_SERVLET_ALIAS), "/cxf");
    }

    private String getWithDefault(Object value, String defaultValue) {
        return value == null ? defaultValue : value.toString();
    }

    public Bus registerServlet(Bus bus, String contextRoot, BundleContext callingContext, Long sid) {
        bus.setExtension(new DestinationRegistryImpl(), DestinationRegistry.class);
        CXFNonSpringServlet cxf = new CXFNonSpringServlet();
        cxf.setBus(bus);
        try {
            HttpContext httpContext1 = httpService.createDefaultHttpContext();
            HttpContext httpContext = new SecurityDelegatingHttpContext(callingContext, httpContext1);
            httpService.registerServlet(contextRoot, cxf, new Hashtable(), httpContext);

            registerUnexportHook(sid, contextRoot);

            LOG.info("Successfully registered CXF DOSGi servlet at " + contextRoot);
        } catch (Exception e) {
            throw new ServiceException("CXF DOSGi: problem registering CXF HTTP Servlet", e);
        }
        return bus;
    }

    /**
     * This listens for service removal events and "un-exports" the service from the HttpService.
     *
     * @param sref the service reference to track
     * @param alias the HTTP servlet context alias
     */
    private void registerUnexportHook(Long sid, String alias) {
        LOG.debug("Registering service listener for service with ID {}", sid);

        String previous = exportedAliases.put(sid, alias);
        if (previous != null) {
            LOG.warn("Overwriting service export for service with ID {}", sid);
        }

        try {
            Filter f = context.createFilter("(" + org.osgi.framework.Constants.SERVICE_ID + "=" + sid + ")");
            if (f != null) {
                context.addServiceListener(new UnregisterListener(), f.toString());
            } else {
                LOG.warn("Service listener could not be started. The service will not be automatically unexported.");
            }
        } catch (InvalidSyntaxException e) {
            LOG.warn("Service listener could not be started. The service will not be automatically unexported.",
                     e);
        }
    }

    public String getDefaultAddress(Class type) {
        return "/" + type.getName().replace('.', '/');
    }

    public String getAbsoluteAddress(String contextRoot, String endpointAddress) {
        if (endpointAddress.startsWith("http")) {
            return endpointAddress;
        }
        String effContextRoot = contextRoot == null ? cxfServletAlias : contextRoot;
        return this.httpBase + effContextRoot + endpointAddress;
    }

    private final class UnregisterListener implements ServiceListener {

        public void serviceChanged(ServiceEvent event) {
            if (!(event.getType() == ServiceEvent.UNREGISTERING)) {
                return;
            }
            final ServiceReference sref = event.getServiceReference();
            final Long sid = (Long)sref.getProperty(org.osgi.framework.Constants.SERVICE_ID);
            final String alias = exportedAliases.remove(sid);
            if (alias == null) {
                LOG.error("Unable to unexport HTTP servlet for service class '{}',"
                          + " service-id {}: no servlet alias found",
                          sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS), sid);
                return;
            }
            LOG.debug("Unexporting HTTP servlet for alias '{}'", alias);
            try {
                httpService.unregister(alias);
            } catch (Exception e) {
                LOG.warn("An exception occurred while unregistering service for HTTP servlet alias '{}'",
                         alias, e);
            }
        }
    }

    public void setContext(BundleContext context) {
        this.context = context;
    }

    @Reference
    public void setHttpService(HttpService httpService) {
        this.httpService = httpService;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy