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

io.gravitee.rest.api.standalone.jetty.JettyEmbeddedContainer Maven / Gradle / Ivy

/*
 * Copyright © 2015 The Gravitee team (http://gravitee.io)
 *
 * 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 io.gravitee.rest.api.standalone.jetty;

import io.gravitee.common.component.AbstractLifecycleComponent;
import io.gravitee.rest.api.management.rest.resource.GraviteeManagementApplication;
import io.gravitee.rest.api.management.security.SecurityManagementConfiguration;
import io.gravitee.rest.api.management.v2.rest.GraviteeManagementV2Application;
import io.gravitee.rest.api.management.v2.security.SecurityManagementV2Configuration;
import io.gravitee.rest.api.portal.rest.resource.GraviteePortalApplication;
import io.gravitee.rest.api.portal.security.SecurityPortalConfiguration;
import io.gravitee.rest.api.standalone.jetty.handler.NoContentOutputErrorHandler;
import jakarta.servlet.DispatcherType;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
import org.eclipse.jetty.ee10.servlet.FilterHolder;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.eclipse.jetty.ee10.servlet.ServletHolder;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.glassfish.jersey.servlet.ServletContainer;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.security.config.annotation.authentication.configuration.GlobalAuthenticationConfigurerAdapter;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;

/**
 * @author David BRASSELY (david.brassely at graviteesource.com)
 * @author GraviteeSource Team
 */
public final class JettyEmbeddedContainer extends AbstractLifecycleComponent implements ApplicationContextAware {

    private final JettyServerFactory jettyServerFactory;

    private Server server;
    private ApplicationContext applicationContext;

    @Value("${http.api.management.enabled:true}")
    private boolean startManagementAPI;

    @Value("${http.api.management.entrypoint:${http.api.entrypoint:/}management}")
    private String managementEntrypoint;

    @Value("${http.api.portal.enabled:true}")
    private boolean startPortalAPI;

    @Value("${http.api.portal.entrypoint:${http.api.entrypoint:/}portal}")
    private String portalEntrypoint;

    public JettyEmbeddedContainer(JettyServerFactory jettyServerFactory) {
        this.jettyServerFactory = jettyServerFactory;
    }

    @Override
    protected void doStart() throws Exception {
        server = Objects.requireNonNull(jettyServerFactory.getObject());

        Request.Handler noContentHandler = new NoContentOutputErrorHandler();
        // This part is needed to avoid WARN while starting container.

        server.setErrorHandler(noContentHandler);

        // Spring configuration
        System.setProperty(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "basic");

        List contexts = new ArrayList<>();

        if (startPortalAPI) {
            // REST configuration for Portal API
            ServletContextHandler portalContextHandler = configureAPI(
                portalEntrypoint,
                GraviteePortalApplication.class.getName(),
                SecurityPortalConfiguration.class
            );
            contexts.add(portalContextHandler);
        }

        if (startManagementAPI) {
            // REST configuration for Management API
            ServletContextHandler managementContextHandler = configureAPI(
                managementEntrypoint,
                GraviteeManagementApplication.class.getName(),
                SecurityManagementConfiguration.class
            );
            contexts.add(managementContextHandler);

            // REST configuration for Management API - V2
            ServletContextHandler managementV2ContextHandler = configureAPI(
                managementEntrypoint + "/v2",
                GraviteeManagementV2Application.class.getName(),
                SecurityManagementV2Configuration.class
            );
            contexts.add(managementV2ContextHandler);
        }

        if (contexts.isEmpty()) {
            throw new IllegalStateException("At least one API should be enabled");
        }

        server.setHandler(new ContextHandlerCollection(contexts.toArray(new ServletContextHandler[0])));

        // start the server
        server.start();
    }

    private ServletContextHandler configureAPI(
        String apiContextPath,
        String applicationName,
        Class securityConfigurationClass
    ) {
        final ServletContextHandler childContext = new ServletContextHandler(apiContextPath, ServletContextHandler.SESSIONS);

        final ServletHolder servletHolder = new ServletHolder(ServletContainer.class);
        servletHolder.setInitParameter("jakarta.ws.rs.Application", applicationName);
        servletHolder.setInitOrder(0);
        childContext.addServlet(servletHolder, "/*");

        AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
        webApplicationContext.register(securityConfigurationClass);

        webApplicationContext.setEnvironment((ConfigurableEnvironment) applicationContext.getEnvironment());
        webApplicationContext.setParent(applicationContext);

        childContext.addEventListener(new ContextLoaderListener(webApplicationContext));

        // Spring Security filter
        childContext.addFilter(
            new FilterHolder(new DelegatingFilterProxy("springSecurityFilterChain")),
            "/*",
            EnumSet.allOf(DispatcherType.class)
        );
        return childContext;
    }

    @Override
    protected void doStop() throws Exception {
        if (server != null) {
            server.stop();
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy