/*
 * 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.rest;

import org.apache.openejb.BeanContext;
import org.apache.openejb.BeanType;
import org.apache.openejb.Injection;
import org.apache.openejb.assembler.classic.AppInfo;
import org.apache.openejb.assembler.classic.Assembler;
import org.apache.openejb.assembler.classic.EjbJarInfo;
import org.apache.openejb.assembler.classic.EnterpriseBeanInfo;
import org.apache.openejb.assembler.classic.IdPropertiesInfo;
import org.apache.openejb.assembler.classic.ParamValueInfo;
import org.apache.openejb.assembler.classic.ServiceInfo;
import org.apache.openejb.assembler.classic.ServletInfo;
import org.apache.openejb.assembler.classic.WebAppInfo;
import org.apache.openejb.assembler.classic.event.AssemblerAfterApplicationCreated;
import org.apache.openejb.assembler.classic.event.AssemblerBeforeApplicationDestroyed;
import org.apache.openejb.assembler.classic.util.PojoUtil;
import org.apache.openejb.assembler.classic.util.ServiceConfiguration;
import org.apache.openejb.core.CoreContainerSystem;
import org.apache.openejb.core.WebContext;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.observer.Observes;
import org.apache.openejb.server.SelfManaging;
import org.apache.openejb.server.ServerService;
import org.apache.openejb.server.ServiceException;
import org.apache.openejb.server.ServiceManager;
import org.apache.openejb.server.httpd.HttpListener;
import org.apache.openejb.server.httpd.HttpListenerRegistry;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.xbean.finder.MetaAnnotatedClass;

import javax.naming.Context;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

public abstract class RESTService implements ServerService, SelfManaging {

    public static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_RS, RESTService.class);
    private static final boolean OLD_WEBSERVICE_DEPLOYMENT = SystemInstance.get().getOptions().get("openejb.webservice.old-deployment", false);
    public static final String OPENEJB_USE_APPLICATION_PROPERTY = "openejb.jaxrs.application";
    private static final String APPLICATION_DEPLOYMENT = SystemInstance.get().getOptions().get(OPENEJB_USE_APPLICATION_PROPERTY, "true");
    public static final String OPENEJB_JAXRS_PROVIDERS_AUTO_PROP = "openejb.jaxrs.providers.auto";

    private static final String IP = "n/a";
    private static final int PORT = -1;
    public static final String NOPATH_PREFIX = "http://nopath/";

    private final Set<AppInfo> deployedApplications = new HashSet<AppInfo>();
    private final Set<WebAppInfo> deployedWebApps = new HashSet<WebAppInfo>();
    private Assembler assembler;
    private CoreContainerSystem containerSystem;
    private RsRegistry rsRegistry;
    private List<DeployedService> services = new ArrayList<DeployedService>();
    private String virtualHost;
    private boolean enabled = true;
    private String wildcard = SystemInstance.get().getProperty("openejb.rest.wildcard", ".*"); // embedded = regex, tomee = servlet

    public void afterApplicationCreated(final AppInfo appInfo, final WebAppInfo webApp) {
        final WebContext webContext = containerSystem.getWebContext(webApp.moduleId);
        if (webContext == null) {
            return;
        }

        if (!deployedWebApps.add(webApp)) {
            return;
        }

        final Map<String, EJBRestServiceInfo> restEjbs = getRestEjbs(appInfo);

        final ClassLoader classLoader = getClassLoader(webContext.getClassLoader());
        final Collection<Injection> injections = webContext.getInjections();
        final WebBeansContext owbCtx;
        if (webContext.getWebbeansContext() != null) {
            owbCtx = webContext.getWebbeansContext();
        } else {
            owbCtx = webContext.getAppContext().getWebBeansContext();
        }

        Context context = webContext.getJndiEnc();
        if (context == null) { // usually true since it is set in org.apache.tomee.catalina.TomcatWebAppBuilder.afterStart() and lookup(comp) fails
            context = webContext.getAppContext().getAppJndiContext();
        }

        final Collection<Object> additionalProviders = new HashSet<Object>();
        if (useDiscoveredProviders()) {
            for (final String name : webApp.jaxRsProviders) {
                try {
                    additionalProviders.add(classLoader.loadClass(name));
                } catch (ClassNotFoundException e) {
                    LOGGER.warning("can't load '" + name + "'", e);
                }
            }
            additionalProviders.addAll(appProviders(appInfo, classLoader));
        }

        final ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(classLoader);

        Collection<IdPropertiesInfo> pojoConfigurations = null; // done lazily
        try {
            boolean deploymentWithApplication = "true".equalsIgnoreCase(appInfo.properties.getProperty(OPENEJB_USE_APPLICATION_PROPERTY, APPLICATION_DEPLOYMENT));
            if (deploymentWithApplication) {
                Application application = null;
                String prefix = "/";

                final Class<?> appClazz;
                if (webApp.restApplications.size() == 1) {
                    final String app = webApp.restApplications.iterator().next();
                    try {
                        appClazz = classLoader.loadClass(app);
                        application = Application.class.cast(appClazz.newInstance());
                        if (owbCtx.getBeanManagerImpl().isInUse()) {
                            try {
                                webContext.inject(application);
                            } catch (Exception e) {
                                // not important since not required by the spec
                            }
                        }
                    } catch (Exception e) {
                        throw new OpenEJBRestRuntimeException("can't create class " + app, e);
                    }

                    final Set<Class<?>> classes = application.getClasses();
                    final Set<Object> singletons = application.getSingletons();

                    if (classes.size() + singletons.size() == 0) {
                        application = null; // use discovered services
                    } else {
                        for (final Class<?> clazz : classes) {
                            if (isProvider(clazz)) {
                                additionalProviders.add(clazz);
                            } else if (!hasEjbAndIsNotAManagedBean(restEjbs, clazz.getName())) {
                                pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                                if (PojoUtil.findConfiguration(pojoConfigurations, clazz.getName()) != null) {
                                    deploymentWithApplication = false;
                                    logOldDeploymentUsage(clazz.getName());
                                }
                            }
                        }

                        if (deploymentWithApplication) { // don't do it if we detected we should use old deployment
                            for (final Object o : singletons) {
                                final Class<?> clazz = o.getClass();
                                if (isProvider(clazz)) {
                                    additionalProviders.add(o);
                                } else if (!hasEjbAndIsNotAManagedBean(restEjbs, clazz.getName())) {
                                    pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                                    if (PojoUtil.findConfiguration(pojoConfigurations, clazz.getName()) != null) {
                                        deploymentWithApplication = false;
                                        logOldDeploymentUsage(clazz.getName());
                                    }
                                }
                            }
                        }
                    }

                    if (deploymentWithApplication) { // don't do it if we detected we should use old deployment
                        final String path = appPrefix(webApp, appClazz);
                        if (path != null) {
                            prefix += path + wildcard;
                        } else {
                            prefix += wildcard;
                        }
                    }
                }

                if (deploymentWithApplication) { // don't do it if we detected we should use old deployment
                    if (application == null) {
                        application = new InternalApplication(application);

                        for (final String clazz : webApp.restClass) {
                            try {
                                final Class<?> loaded = classLoader.loadClass(clazz);
                                if (!isProvider(loaded)) {
                                    pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                                    if (PojoUtil.findConfiguration(pojoConfigurations, loaded.getName()) != null) {
                                        deploymentWithApplication = false;
                                        logOldDeploymentUsage(loaded.getName());
                                        break;
                                    }
                                    application.getClasses().add(loaded);
                                } else {
                                    additionalProviders.add(loaded);
                                }
                            } catch (Exception e) {
                                throw new OpenEJBRestRuntimeException("can't load class " + clazz, e);
                            }
                        }
                        if (deploymentWithApplication) {
                            for (final Map.Entry<String, EJBRestServiceInfo> ejb : restEjbs.entrySet()) {
                                application.getClasses().add(ejb.getValue().context.getBeanClass());
                            }
                            if (!prefix.endsWith(wildcard)) {
                                prefix += wildcard;
                            }
                        }
                    }

                    if (!application.getClasses().isEmpty() || !application.getSingletons().isEmpty()) {
                        pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                        deployApplication(appInfo, webApp.contextRoot, restEjbs, classLoader, injections, owbCtx, context, additionalProviders, pojoConfigurations, application, prefix);
                    }
                }

            }

            if (!deploymentWithApplication) {
                // The spec says:
                //
                // "The resources and providers that make up a JAX-RS application are configured via an application-supplied
                // subclass of Application. An implementation MAY provide alternate mechanisms for locating resource
                // classes and providers (e.g. runtime class scanning) but use of Application is the only portable means of
                //  configuration."
                //
                //  The choice here is to deploy using the Application if it exists or to use the scanned classes
                //  if there is no Application.
                //
                //  Like this providing an Application subclass user can totally control deployed services.

                boolean useApp = false;
                String appPrefix = webApp.contextRoot;
                for (final String app : webApp.restApplications) { // normally a unique one but we support more
                    appPrefix = webApp.contextRoot; // if multiple application classes reinit it
                    if (!appPrefix.endsWith("/")) {
                        appPrefix += "/";
                    }

                    final Application appInstance;
                    final Class<?> appClazz;
                    try {
                        appClazz = classLoader.loadClass(app);
                        appInstance = Application.class.cast(appClazz.newInstance());
                        if (owbCtx.getBeanManagerImpl().isInUse()) {
                            try {
                                webContext.inject(appInstance);
                            } catch (Exception e) {
                                // not important since not required by the spec
                            }
                        }
                    } catch (Exception e) {
                        throw new OpenEJBRestRuntimeException("can't create class " + app, e);
                    }

                    final String path = appPrefix(webApp, appClazz);
                    if (path != null) {
                        appPrefix += path;
                    }

                    final Set<Class<?>> classes = appInstance.getClasses();
                    final Set<Object> singletons = appInstance.getSingletons();

                    // look for providers
                    for (final Class<?> clazz : classes) {
                        if (isProvider(clazz)) {
                            additionalProviders.add(clazz);
                        }
                    }
                    for (final Object obj : singletons) {
                        if (obj != null && isProvider(obj.getClass())) {
                            additionalProviders.add(obj);
                        }
                    }

                    for (final Object o : singletons) {
                        if (o == null || additionalProviders.contains(o)) {
                            continue;
                        }

                        if (hasEjbAndIsNotAManagedBean(restEjbs, o.getClass().getName())) {
                            // no more a singleton if the ejb is not a singleton...but it is a weird case
                            deployEJB(webApp.contextRoot, appPrefix, restEjbs.get(o.getClass().getName()).context, additionalProviders, appInfo.services);
                        } else {
                            pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                            deploySingleton(webApp.contextRoot, appPrefix, o, appInstance, classLoader, additionalProviders,
                                            new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, o.getClass().getName()), appInfo.services));
                        }
                    }

                    for (final Class<?> clazz : classes) {
                        if (additionalProviders.contains(clazz)) {
                            continue;
                        }

                        if (hasEjbAndIsNotAManagedBean(restEjbs, clazz.getName())) {
                            deployEJB(webApp.contextRoot, appPrefix, restEjbs.get(clazz.getName()).context, additionalProviders, appInfo.services);
                        } else {
                            pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                            deployPojo(webApp.contextRoot, appPrefix, clazz, appInstance, classLoader, injections, context, owbCtx, additionalProviders,
                                       new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, clazz.getName()), appInfo.services));
                        }
                    }

                    useApp = useApp || classes.size() + singletons.size() > 0;
                    LOGGER.info("REST application deployed: " + app);
                }

                if (!useApp) {
                    if (webApp.restApplications.isEmpty() || webApp.restApplications.size() > 1) {
                        appPrefix = webApp.contextRoot;
                    } // else keep application prefix

                    final Set<String> restClasses = new HashSet<String>(webApp.restClass);
                    restClasses.addAll(webApp.ejbRestServices);

                    for (final String clazz : restClasses) {
                        if (restEjbs.containsKey(clazz)) {
                            final BeanContext ctx = restEjbs.get(clazz).context;
                            if (hasEjbAndIsNotAManagedBean(restEjbs, clazz)) {
                                deployEJB(webApp.contextRoot, appPrefix, restEjbs.get(clazz).context, additionalProviders, appInfo.services);
                            } else {
                                deployPojo(webApp.contextRoot, appPrefix, ctx.getBeanClass(), null, ctx.getClassLoader(), ctx.getInjections(), context,
                                           owbCtx, additionalProviders, new ServiceConfiguration(ctx.getProperties(), appInfo.services));
                            }
                        } else {
                            try {
                                final Class<?> loadedClazz = classLoader.loadClass(clazz);
                                pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp);
                                deployPojo(webApp.contextRoot, appPrefix, loadedClazz, null, classLoader, injections, context, owbCtx,
                                           additionalProviders,
                                           new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, loadedClazz.getName()), appInfo.services));
                            } catch (ClassNotFoundException e) {
                                throw new OpenEJBRestRuntimeException("can't find class " + clazz, e);
                            }
                        }
                    }
                }
            }
        } finally {
            Thread.currentThread().setContextClassLoader(oldLoader);
        }
    }

    protected static void logOldDeploymentUsage(final String clazz) {
        LOGGER.info("Using deployment by endpoint instead of by application for JAXRS deployment because an old configuration (by class/ejb) was found on " + clazz);
    }

    private void deployApplication(final AppInfo appInfo, final String contextRoot, final Map<String, EJBRestServiceInfo> restEjbs, final ClassLoader classLoader, final Collection<Injection> injections, final WebBeansContext owbCtx, final Context context, final Collection<Object> additionalProviders, final Collection<IdPropertiesInfo> pojoConfigurations, final Application application, final String prefix) {
        // get configuration
        Properties configuration = PojoUtil.findConfiguration(pojoConfigurations, application.getClass().getName());
        if (configuration == null) { // try a constant (common in half of cases)
            configuration = PojoUtil.findConfiguration(pojoConfigurations, "jaxrs-application");
        }
        if (configuration == null) { // try with context
            configuration = PojoUtil.findConfiguration(pojoConfigurations, contextRoot);
        }

        final String base = getAddress(contextRoot);
        final String nopath;
        if (base.endsWith("/") && prefix.startsWith("/")) {
            nopath = base + prefix.substring(1);
        } else {
            nopath = base + prefix;
        }

        final RsHttpListener listener = createHttpListener();
        final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(contextRoot, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost);

        services.add(new DeployedService(address.complete, contextRoot, application.getClass().getName()));
        listener.deployApplication(application, address.complete.substring(0, address.complete.length() - wildcard.length()), nopath.substring(NOPATH_PREFIX.length(), nopath.length() - wildcard.length()), additionalProviders, restEjbs, // app config
                                   classLoader, injections, context, owbCtx, // injection/webapp context
                                   new ServiceConfiguration(configuration, appInfo.services)); // deployment config
    }

    private static String appPrefix(final WebAppInfo info, final Class<?> appClazz) {
        final ApplicationPath path = appClazz.getAnnotation(ApplicationPath.class);
        if (path != null) {
            final String appPath = path.value();
            if (appPath.startsWith("/")) {
                return appPath.substring(1);
            } else {
                return appPath;
            }
        }

        // no annotation, try servlets
        for (final ServletInfo s : info.servlets) {
            if (s.mappings.isEmpty()) {
                continue;
            }

            String mapping = null;

            final String name = appClazz.getName();
            if (name.equals(s.servletClass) || name.equals(s.servletName)) {
                mapping = s.mappings.iterator().next();
            } else {
                for (final ParamValueInfo pvi : s.initParams) {
                    if ("javax.ws.rs.Application".equals(pvi.name) || Application.class.getName().equals(pvi.name)) {
                        mapping = s.mappings.iterator().next();
                        break;
                    }
                }
            }

            if (mapping != null) {
                if (mapping.endsWith("/*")) {
                    mapping = mapping.substring(0, mapping.length() - 2);
                }
                if (mapping.startsWith("/")) {
                    mapping = mapping.substring(1);
                }
                return mapping;
            }
        }

        return null;
    }

    private static <T> boolean isProvider(final Class<T> clazz) {
        return new MetaAnnotatedClass<T>(clazz).isAnnotationPresent(Provider.class);
    }

    private boolean hasEjbAndIsNotAManagedBean(final Map<String, EJBRestServiceInfo> restEjbs, final String clazz) {
        return restEjbs.containsKey(clazz) && !BeanType.MANAGED.equals(restEjbs.get(clazz).context.getComponentType());
    }

    private boolean useDiscoveredProviders() {
        return SystemInstance.get().getOptions().get(OPENEJB_JAXRS_PROVIDERS_AUTO_PROP, false);
    }

    private Collection<Object> appProviders(final AppInfo appInfo, final ClassLoader classLoader) {
        final Collection<Object> additionalProviders = new HashSet<Object>();
        for (final String name : appInfo.jaxRsProviders) {
            try {
                additionalProviders.add(classLoader.loadClass(name));
            } catch (ClassNotFoundException e) {
                LOGGER.warning("can't load '" + name + "'", e);
            }
        }
        return additionalProviders;
    }

    public void afterApplicationCreated(
                                               @Observes
                                               final AssemblerAfterApplicationCreated event) {
        if (!enabled)
            return;

        final AppInfo appInfo = event.getApp();
        if ("false".equalsIgnoreCase(appInfo.properties.getProperty("openejb.jaxrs.on", "true"))) {
            return;
        }

        quickCheckIfOldDeploymentShouldBeUsedFromEjbConfig(appInfo);

        if (deployedApplications.add(appInfo)) {
            if (appInfo.webApps.size() == 0) {
                final Map<String, EJBRestServiceInfo> restEjbs = getRestEjbs(appInfo);
                if (restEjbs.isEmpty()) {
                    return;
                }

                final Collection<Object> providers;
                if (useDiscoveredProviders()) {
                    providers = appProviders(appInfo, containerSystem.getAppContext(appInfo.appId).getClassLoader());
                } else {
                    providers = new ArrayList<Object>();
                }

                if ("true".equalsIgnoreCase(appInfo.properties.getProperty(OPENEJB_USE_APPLICATION_PROPERTY, APPLICATION_DEPLOYMENT))) {
                    final Application application = new InternalApplication(null);
                    for (final Map.Entry<String, EJBRestServiceInfo> ejb : restEjbs.entrySet()) {
                        application.getClasses().add(ejb.getValue().context.getBeanClass());
                    }

                    // merge configurations at app level since a single deployment is available
                    final List<IdPropertiesInfo> pojoConfigurations = new ArrayList<IdPropertiesInfo>();
                    BeanContext comp = null;
                    for (final EjbJarInfo ejbJar : appInfo.ejbJars) {
                        for (final EnterpriseBeanInfo bean : ejbJar.enterpriseBeans) {
                            if (comp != null) {
                                break;
                            }
                            if (bean.ejbClass.equals(BeanContext.Comp.class.getName())) {
                                comp = containerSystem.getBeanContext(bean.ejbDeploymentId);
                                break;
                            }
                        }
                        if (ejbJar.pojoConfigurations != null) {
                            pojoConfigurations.addAll(ejbJar.pojoConfigurations);
                        }
                    }
                    if (appInfo.pojoConfigurations != null) {
                        pojoConfigurations.addAll(appInfo.pojoConfigurations);
                    }

                    final Map.Entry<String, EJBRestServiceInfo> next = restEjbs.entrySet().iterator().next();
                    if (comp == null) {
                        comp = next.getValue().context;
                    }

                    deployApplication(appInfo, next.getValue().path, restEjbs, comp.getClassLoader(), comp.getInjections(),
                                      containerSystem.getAppContext(appInfo.appId).getWebBeansContext(), comp.getJndiContext(),
                                      providers, pojoConfigurations, application, wildcard);
                } else {
                    for (final Map.Entry<String, EJBRestServiceInfo> ejb : restEjbs.entrySet()) {
                        final BeanContext ctx = ejb.getValue().context;
                        if (BeanType.MANAGED.equals(ctx.getComponentType())) {
                            deployPojo("", ejb.getValue().path, ctx.getBeanClass(), null, ctx.getClassLoader(), ctx.getInjections(),
                                       ctx.getJndiContext(),
                                       containerSystem.getAppContext(appInfo.appId).getWebBeansContext(),
                                       providers, new ServiceConfiguration(ctx.getProperties(), appInfo.services));
                        } else {
                            deployEJB("", ejb.getValue().path, ctx, providers, appInfo.services);
                        }
                    }
                }
            } else {
                for (final WebAppInfo webApp : appInfo.webApps) {
                    afterApplicationCreated(appInfo, webApp);
                }
            }
        }
    }

    private void quickCheckIfOldDeploymentShouldBeUsedFromEjbConfig(final AppInfo appInfo) {
        // if forced don't update anything
        if (appInfo.properties.getProperty(OPENEJB_USE_APPLICATION_PROPERTY) != null) {
            return;
        }

        for (final EjbJarInfo ejbJar : appInfo.ejbJars) {
            for (final EnterpriseBeanInfo bean : ejbJar.enterpriseBeans) {
                if (bean.restService) {
                    final BeanContext beanContext = containerSystem.getBeanContext(bean.ejbDeploymentId);
                    if (containsJaxRsConfiguration(beanContext.getProperties())) {
                        appInfo.properties.setProperty(OPENEJB_USE_APPLICATION_PROPERTY, "false");
                        logOldDeploymentUsage(bean.ejbClass);
                        return; // no need to look further
                    }
                }
            }
        }
    }

    protected abstract boolean containsJaxRsConfiguration(final Properties properties);

    protected Map<String, EJBRestServiceInfo> getRestEjbs(final AppInfo appInfo) {
        final Map<String, BeanContext> beanContexts = new HashMap<String, BeanContext>();
        for (final EjbJarInfo ejbJar : appInfo.ejbJars) {
            for (final EnterpriseBeanInfo bean : ejbJar.enterpriseBeans) {
                if (bean.restService) {
                    final BeanContext beanContext = containerSystem.getBeanContext(bean.ejbDeploymentId);
                    if (beanContext == null) {
                        continue;
                    }

                    beanContexts.put(bean.ejbClass, beanContext);
                }
            }
        }

        final Map<String, EJBRestServiceInfo> restEjbs = new HashMap<String, EJBRestServiceInfo>();
        for (final WebAppInfo webApp : appInfo.webApps) {
            for (final String ejb : webApp.ejbRestServices) {
                restEjbs.put(ejb, new EJBRestServiceInfo(webApp.contextRoot, beanContexts.get(ejb)));
            }
        }
        for (final Map.Entry<String, BeanContext> ejbs : beanContexts.entrySet()) {
            final String clazz = ejbs.getKey();
            if (!restEjbs.containsKey(clazz)) {
                // null is important, it means there is no webroot path in standalone
                String context = null;
                if (!OLD_WEBSERVICE_DEPLOYMENT) {
                    if (appInfo.appId != null && !appInfo.appId.isEmpty()) {
                        context = appInfo.appId;
                    } else {
                        context = ejbs.getValue().getModuleName();
                    }
                }
                restEjbs.put(clazz, new EJBRestServiceInfo(context, beanContexts.get(clazz)));
            }
        }
        beanContexts.clear();

        return restEjbs;
    }

    private void deploySingleton(final String web, final String contextRoot, final Object o, final Application appInstance, final ClassLoader classLoader,
                                 final Collection<Object> additionalProviders, final ServiceConfiguration configuration) {
        final String nopath = getAddress(contextRoot, o.getClass());
        final RsHttpListener listener = createHttpListener();
        final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(web, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost);

        services.add(new DeployedService(address.complete, web, o.getClass().getName()));
        listener.deploySingleton(getFullContext(address.base, contextRoot), o, appInstance, additionalProviders, configuration);

        LOGGER.info("deployed REST singleton: " + o);
    }

    private void deployPojo(final String web, final String contextRoot, final Class<?> loadedClazz, final Application app, final ClassLoader classLoader, final Collection<Injection> injections,
                            final Context context, final WebBeansContext owbCtx, final Collection<Object> additionalProviders, final ServiceConfiguration config) {
        if (loadedClazz.isInterface()) {
            return;
        }

        final String nopath = getAddress(contextRoot, loadedClazz);
        final RsHttpListener listener = createHttpListener();
        final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(web, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost);

        services.add(new DeployedService(address.complete, contextRoot, loadedClazz.getName()));
        listener.deployPojo(getFullContext(address.base, contextRoot), loadedClazz, app, injections, context, owbCtx,
                            additionalProviders, config);

        LOGGER.info("REST Service: " + address.complete + "  -> Pojo " + loadedClazz.getName());
    }

    private void deployEJB(final String web, final String context, final BeanContext beanContext, final Collection<Object> additionalProviders, final Collection<ServiceInfo> serviceInfos) {
        final String nopath = getAddress(context, beanContext.getBeanClass());
        final RsHttpListener listener = createHttpListener();
        final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(web, listener, beanContext.getClassLoader(), nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost);

        services.add(new DeployedService(address.complete, context, beanContext.getBeanClass().getName()));
        listener.deployEJB(getFullContext(address.base, context), beanContext,
                           additionalProviders, new ServiceConfiguration(beanContext.getProperties(), serviceInfos));

        LOGGER.info("REST Service: " + address.complete + "  -> EJB " + beanContext.getEjbName());
    }

    /**
     * It creates the service container (http listener).
     *
     * @return the service container
     */
    protected abstract RsHttpListener createHttpListener();

    private static String getFullContext(final String address, final String context) {
        if (context == null) {
            return address;
        }
        if (context.isEmpty() && address.contains("/")) {
            return address.substring(0, address.lastIndexOf("/"));
        }

        // context can get the app path too
        // so keep only web context without /
        String webCtx = context;
        while (webCtx.startsWith("/")) {
            webCtx = webCtx.substring(1);
        }

        // get root path ending with /
        try {
            final URL url = new URL(address);
            final int port = url.getPort();
            if (port > 0) {
                return url.getProtocol() + "://" + url.getHost() + ":" + port + "/" + webCtx;
            } else {
                return url.getProtocol() + "://" + url.getHost() + "/" + webCtx;
            }
        } catch (MalformedURLException e) {
            throw new OpenEJBRestRuntimeException("bad url: " + address, e);
        }
    }

    private Class<?> findPath(final Class<?> clazz) {
        Class<?> usedClass = clazz;
        while (usedClass.getAnnotation(Path.class) == null && usedClass.getSuperclass() != null) {
            usedClass = usedClass.getSuperclass();
        }
        return usedClass;
    }

    private String getAddress(final String context, final Class<?> clazz) {
        String root = getAddress(context);

        Class<?> usedClass = findPath(clazz);
        if (usedClass == null || Object.class.equals(usedClass)) { // try interfaces
            final Class<?>[] itfs = clazz.getInterfaces();
            if (itfs != null) {
                for (final Class<?> c : itfs) {
                    usedClass = findPath(c);
                    if (usedClass.getAnnotation(Path.class) != null) {
                        break;
                    }
                }
            }

        }
        if (usedClass == null || usedClass.getAnnotation(Path.class) == null) {
            throw new IllegalArgumentException("no @Path annotation on " + clazz.getName());
        }

        String builtUrl = null;
        try {
            builtUrl = UriBuilder.fromUri(new URI(root)).path(usedClass).build().toURL().toString();
            return replaceParams(builtUrl); // pathparam at class level
        } catch (IllegalArgumentException iae) {
            if (builtUrl != null) {
                return builtUrl;
            }

            // try to do it manually with @Path on the class
            Class<?> current = usedClass;
            while (current != null && !Object.class.equals(current)) {
                final Path path = current.getAnnotation(Path.class);
                if (path != null) {
                    String classPath = path.value();
                    if (classPath.startsWith("/")) {
                        classPath = classPath.substring(1);
                    }
                    if (!root.endsWith("/")) {
                        root = root + "/";
                    }
                    return replaceParams(root + classPath);
                }
                current = current.getSuperclass();
            }

            throw new OpenEJBRestRuntimeException("can't built the service mapping for service '" + usedClass.getName() + "'", iae);
        } catch (MalformedURLException e) {
            throw new OpenEJBRestRuntimeException("url is malformed", e);
        } catch (URISyntaxException e) {
            throw new OpenEJBRestRuntimeException("uri syntax is not correct", e);
        }
    }

    private String getAddress(final String context) {
        String root = NOPATH_PREFIX;
        if (context != null) {
            if (context.startsWith("/")) {
                root += context.substring(1);
            } else {
                root += context;
            }
        }
        return root;
    }

    // this mean not really conflicting mappings (rest/servlet and so on) can be conflicting
    // a good solution is to handle a unique rest servlet managing the routing
    private String replaceParams(final String url) {
        final String managedUrl = url.replaceAll("\\{[^}]*\\}.*", wildcard);
        if (managedUrl.endsWith(wildcard)) {
            return managedUrl;
        }
        return managedUrl + "/" + wildcard;
    }

    private void undeployRestObject(final String context) {
        final HttpListener listener = rsRegistry.removeListener(context);
        if (listener != null) {
            RsHttpListener.class.cast(listener).undeploy();
        }
    }

    private static ClassLoader getClassLoader(final ClassLoader classLoader) {
        ClassLoader cl = classLoader;
        if (cl == null) {
            cl = Thread.currentThread().getContextClassLoader();
        }
        if (cl == null) {
            cl = RESTService.class.getClassLoader();
        }
        return cl;
    }

    public void beforeApplicationDestroyed(
                                                  @Observes
                                                  final AssemblerBeforeApplicationDestroyed event) {
        final AppInfo app = event.getApp();
        if (deployedApplications.contains(app)) {
            for (final WebAppInfo webApp : app.webApps) {
                final List<DeployedService> toRemove = new ArrayList<DeployedService>();
                for (final DeployedService service : services) {
                    if (service.isInWebApp(webApp)) {
                        undeployRestObject(service.address);
                        toRemove.add(service);
                    }
                }
                services.removeAll(toRemove);
                deployedWebApps.remove(webApp);
            }
        }
    }

    @Override
    public void start() throws ServiceException {
        SystemInstance.get().setComponent(RESTService.class, this);

        beforeStart();

        containerSystem = (CoreContainerSystem) SystemInstance.get().getComponent(ContainerSystem.class);
        assembler = SystemInstance.get().getComponent(Assembler.class);
        if (assembler != null) {
            SystemInstance.get().addObserver(this);
            for (final AppInfo appInfo : assembler.getDeployedApplications()) {
                afterApplicationCreated(new AssemblerAfterApplicationCreated(appInfo));
            }
        }
    }

    protected void beforeStart() {
        rsRegistry = SystemInstance.get().getComponent(RsRegistry.class);
        if (rsRegistry == null && SystemInstance.get().getComponent(HttpListenerRegistry.class) != null) {
            rsRegistry = new RsRegistryImpl();
        }
    }

    @Override
    public void stop() throws ServiceException {
        if (assembler != null) {
            SystemInstance.get().removeObserver(this);
            for (final AppInfo appInfo : new ArrayList<AppInfo>(deployedApplications)) {
                beforeApplicationDestroyed(new AssemblerBeforeApplicationDestroyed(appInfo));
            }
        }

        for (final DeployedService service : services) {
            undeployRestObject(service.address);
        }
    }

    @Override
    public void service(final InputStream in, final OutputStream out) throws ServiceException, IOException {
        throw new UnsupportedOperationException(getClass().getName() + " cannot be invoked directly");
    }

    @Override
    public void service(final Socket socket) throws ServiceException, IOException {
        throw new UnsupportedOperationException(getClass().getName() + " cannot be invoked directly");
    }

    @Override
    public String getIP() {
        return IP;
    }

    @Override
    public int getPort() {
        return PORT;
    }

    @Override
    public void init(final Properties props) throws Exception {
        virtualHost = props.getProperty("virtualHost");
        enabled = ServiceManager.isEnabled(props);
    }

    public String getVirtualHost() {
        return virtualHost;
    }

    public void setVirtualHost(final String virtualHost) {
        this.virtualHost = virtualHost;
    }

    // look WebServiceHelperImpl before updating it
    public static class DeployedService {

        public String address;
        public String webapp;
        public String origin;

        public DeployedService(final String address, final String webapp, final String origin) {
            this.address = address;
            this.webapp = webapp;
            this.origin = origin;
        }

        public boolean isInWebApp(final WebAppInfo webApp) {
            return (webApp.contextRoot != null && webApp.contextRoot.equals(webapp)) || (webapp != null && webapp.startsWith(webApp.contextRoot));
        }
    }

    public List<DeployedService> getServices() {
        return services;
    }

    public String getWildcard() {
        return wildcard;
    }
}
