| /* |
| * 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.knox.gateway.deploy; |
| |
| import org.apache.knox.gateway.GatewayMessages; |
| import org.apache.knox.gateway.GatewayServlet; |
| import org.apache.knox.gateway.config.GatewayConfig; |
| import org.apache.knox.gateway.deploy.impl.ApplicationDeploymentContributor; |
| import org.apache.knox.gateway.descriptor.GatewayDescriptor; |
| import org.apache.knox.gateway.descriptor.GatewayDescriptorFactory; |
| import org.apache.knox.gateway.i18n.messages.MessagesFactory; |
| import org.apache.knox.gateway.services.ServiceType; |
| import org.apache.knox.gateway.services.GatewayServices; |
| import org.apache.knox.gateway.services.registry.ServiceRegistry; |
| import org.apache.knox.gateway.topology.Application; |
| import org.apache.knox.gateway.topology.Provider; |
| import org.apache.knox.gateway.topology.Service; |
| import org.apache.knox.gateway.topology.Topology; |
| import org.apache.knox.gateway.topology.Version; |
| import org.apache.knox.gateway.util.ServiceDefinitionsLoader; |
| import org.apache.knox.gateway.util.Urls; |
| import org.jboss.shrinkwrap.api.ShrinkWrap; |
| import org.jboss.shrinkwrap.api.asset.Asset; |
| import org.jboss.shrinkwrap.api.asset.StringAsset; |
| import org.jboss.shrinkwrap.api.spec.EnterpriseArchive; |
| import org.jboss.shrinkwrap.api.spec.WebArchive; |
| import org.jboss.shrinkwrap.descriptor.api.Descriptors; |
| import org.jboss.shrinkwrap.descriptor.api.webapp30.WebAppDescriptor; |
| import org.jboss.shrinkwrap.descriptor.api.webcommon30.FilterType; |
| import org.jboss.shrinkwrap.descriptor.api.webcommon30.ServletType; |
| |
| import javax.xml.bind.JAXBContext; |
| import javax.xml.bind.JAXBException; |
| import javax.xml.bind.Marshaller; |
| import java.beans.Statement; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.ServiceLoader; |
| import java.util.Set; |
| import java.util.TreeMap; |
| |
| public abstract class DeploymentFactory { |
| private static final JAXBContext jaxbContext = getJAXBContext(); |
| |
| private static final String SERVLET_NAME_SUFFIX = "-knox-gateway-servlet"; |
| private static final String FILTER_NAME_SUFFIX = "-knox-gateway-filter"; |
| private static final GatewayMessages log = MessagesFactory.get( GatewayMessages.class ); |
| private static GatewayServices gatewayServices; |
| |
| private static Map<String,Map<String,Map<Version, ServiceDeploymentContributor>>> SERVICE_CONTRIBUTOR_MAP; |
| static { |
| loadServiceContributors(); |
| } |
| |
| private static Set<ProviderDeploymentContributor> PROVIDER_CONTRIBUTORS; |
| private static Map<String,Map<String,ProviderDeploymentContributor>> PROVIDER_CONTRIBUTOR_MAP; |
| static { |
| loadProviderContributors(); |
| } |
| |
| private static JAXBContext getJAXBContext() { |
| Map<String,String> properties = new HashMap<>(2); |
| properties.put( "eclipselink-oxm-xml", "org/apache/knox/gateway/topology/topology_binding-xml.xml"); |
| properties.put( "eclipselink.media-type", "application/xml" ); |
| |
| try { |
| return JAXBContext.newInstance(Topology.class.getPackage().getName(), Topology.class.getClassLoader(), properties); |
| } catch (JAXBException e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| public static void setGatewayServices(GatewayServices services) { |
| DeploymentFactory.gatewayServices = services; |
| } |
| |
| static List<Application> findApplicationsByUrl( Topology topology, String url ) { |
| List<Application> foundApps = new ArrayList<>(); |
| if( topology != null ) { |
| url = Urls.trimLeadingAndTrailingSlash( url ); |
| Collection<Application> searchApps = topology.getApplications(); |
| if( searchApps != null ) { |
| for( Application searchApp : searchApps ) { |
| List<String> searchUrls = searchApp.getUrls(); |
| if( searchUrls == null || searchUrls.isEmpty() ) { |
| searchUrls = new ArrayList<>(1); |
| searchUrls.add( searchApp.getName() ); |
| } |
| for( String searchUrl : searchUrls ) { |
| if( url.equalsIgnoreCase( Urls.trimLeadingAndTrailingSlash( searchUrl ) ) ) { |
| foundApps.add( searchApp ); |
| break; |
| } |
| } |
| } |
| } |
| } |
| return foundApps; |
| } |
| |
| // Verify that there are no two apps with duplicate urls. |
| static void validateNoAppsWithDuplicateUrlsInTopology( Topology topology ) { |
| if( topology != null ) { |
| Collection<Application> apps = topology.getApplications(); |
| if( apps != null ) { |
| for( Application app : apps ) { |
| List<String> urls = app.getUrls(); |
| if( urls == null || urls.isEmpty() ) { |
| urls = new ArrayList<>(1); |
| urls.add( app.getName() ); |
| } |
| for( String url : urls ) { |
| List<Application> dups = findApplicationsByUrl( topology, url ); |
| for( Application dup : dups ) { |
| if( dup != app ) { //NOPMD - check for exact same object |
| throw new DeploymentException( "Topology " + topology.getName() + " contains applications " + app.getName() + " and " + dup.getName() + " with the same url: " + url ); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| // Verify that if there are services that there are no applications with a root url. |
| static void validateNoAppsWithRootUrlsInServicesTopology( Topology topology ) { |
| if( topology != null ) { |
| Collection<Service> services = topology.getServices(); |
| if( services != null && !services.isEmpty() ) { |
| List<Application> dups = findApplicationsByUrl( topology, "/" ); |
| if(!dups.isEmpty()) { |
| throw new DeploymentException( "Topology " + topology.getName() + " contains both services and an application " + dups.get( 0 ).getName() + " with a root url." ); |
| } |
| } |
| } |
| } |
| |
| static void validateTopology( Topology topology ) { |
| validateNoAppsWithRootUrlsInServicesTopology( topology ); |
| validateNoAppsWithDuplicateUrlsInTopology( topology ); |
| } |
| |
| public static EnterpriseArchive createDeployment( GatewayConfig config, Topology topology ) { |
| validateTopology( topology ); |
| loadStacksServiceContributors( config ); |
| Map<String,List<ProviderDeploymentContributor>> providers = selectContextProviders( topology ); |
| Map<String,List<ServiceDeploymentContributor>> services = selectContextServices( topology ); |
| Map<String,ServiceDeploymentContributor> applications = selectContextApplications( config, topology ); |
| EnterpriseArchive ear = ShrinkWrap.create( EnterpriseArchive.class, topology.getName() ); |
| ear.addAsResource( toStringAsset( topology ), "topology.xml" ); |
| if( !services.isEmpty() ) { |
| WebArchive war = createServicesDeployment( config, topology, providers, services ); |
| ear.addAsModule( war ); |
| } |
| if( !applications.isEmpty() ) { |
| for( Map.Entry<String, ServiceDeploymentContributor> application : applications.entrySet() ) { |
| WebArchive war = createApplicationDeployment( config, topology, providers, application ); |
| ear.addAsModule( war ); |
| } |
| } |
| return ear; |
| } |
| |
| private static WebArchive createServicesDeployment( |
| GatewayConfig config, |
| Topology topology, |
| Map<String,List<ProviderDeploymentContributor>> providers, |
| Map<String,List<ServiceDeploymentContributor>> services ) { |
| DeploymentContext context = createDeploymentContext( config, "/", topology, providers ); |
| initialize( context, providers, services, null ); |
| contribute( context, providers, services, null ); |
| finish( context, providers, services, null ); |
| return context.getWebArchive(); |
| } |
| |
| public static WebArchive createApplicationDeployment( |
| GatewayConfig config, |
| Topology topology, |
| Map<String,List<ProviderDeploymentContributor>> providers, |
| Map.Entry<String,ServiceDeploymentContributor> application ) { |
| String appPath = "/" + Urls.trimLeadingAndTrailingSlash( application.getKey() ); |
| DeploymentContext context = createDeploymentContext( config, appPath, topology, providers ); |
| initialize( context, providers, null, application ); |
| contribute( context, providers, null, application ); |
| finish( context, providers, null, application ); |
| return context.getWebArchive(); |
| } |
| |
| private static Asset toStringAsset( Topology topology ) { |
| StringWriter writer = new StringWriter(); |
| String xml; |
| try { |
| Marshaller marshaller = jaxbContext.createMarshaller(); |
| marshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true ); |
| marshaller.marshal( topology, writer ); |
| xml = writer.toString(); |
| } catch (JAXBException e) { |
| throw new DeploymentException( "Failed to marshall topology.", e ); |
| } |
| return new StringAsset( xml ); |
| } |
| |
| private static DeploymentContext createDeploymentContext( |
| GatewayConfig config, |
| String archivePath, |
| Topology topology, |
| Map<String,List<ProviderDeploymentContributor>> providers ) { |
| archivePath = Urls.encode( archivePath ); |
| WebArchive webArchive = ShrinkWrap.create( WebArchive.class, archivePath ); |
| WebAppDescriptor webAppDesc = Descriptors.create( WebAppDescriptor.class ); |
| GatewayDescriptor gateway = GatewayDescriptorFactory.create(); |
| return new DeploymentContextImpl( |
| config, topology, gateway, webArchive, webAppDesc, providers ); |
| } |
| |
| // Scan through the providers in the topology. Collect any named providers in their roles list. |
| // Scan through all of the loaded providers. For each that doesn't have an existing provider in the role |
| // list add it. |
| private static Map<String,List<ProviderDeploymentContributor>> selectContextProviders( Topology topology ) { |
| Map<String,List<ProviderDeploymentContributor>> providers = new LinkedHashMap<>(); |
| addMissingDefaultProviders(topology); |
| collectTopologyProviders( topology, providers ); |
| collectDefaultProviders( providers ); |
| return providers; |
| } |
| |
| private static void addMissingDefaultProviders(Topology topology) { |
| Collection<Provider> providers = topology.getProviders(); |
| HashMap<String, String> providerMap = new HashMap<>(); |
| for (Provider provider : providers) { |
| providerMap.put(provider.getRole(), provider.getName()); |
| } |
| // first make sure that the required provider is available from the serviceloaders |
| // for some tests the number of providers are limited to the classpath of the module |
| // and exceptions will be thrown as topologies are deployed even though they will |
| // work fine at actual server runtime. |
| if (PROVIDER_CONTRIBUTOR_MAP.get("identity-assertion") != null) { |
| // check for required providers and add the defaults if missing |
| if (!providerMap.containsKey("identity-assertion")) { |
| Provider idassertion = new Provider(); |
| idassertion.setRole("identity-assertion"); |
| idassertion.setName("Default"); |
| idassertion.setEnabled(true); |
| providers.add(idassertion); |
| } |
| } |
| } |
| |
| private static void collectTopologyProviders( |
| Topology topology, Map<String, List<ProviderDeploymentContributor>> defaults ) { |
| for( Provider provider : topology.getProviders() ) { |
| String name = provider.getName(); |
| if( name != null ) { |
| String role = provider.getRole(); |
| Map<String,ProviderDeploymentContributor> nameMap = PROVIDER_CONTRIBUTOR_MAP.get( role ); |
| if( nameMap != null ) { |
| ProviderDeploymentContributor contributor = nameMap.get( name ); |
| // If there isn't a contributor with this role/name try to find a "*" contributor. |
| if( contributor == null ) { |
| nameMap = PROVIDER_CONTRIBUTOR_MAP.get( "*" ); |
| if( nameMap != null ) { |
| contributor = nameMap.get( name ); |
| } |
| } |
| if( contributor != null ) { |
| List list = defaults.get( role ); |
| if( list == null ) { |
| list = new ArrayList( 1 ); |
| defaults.put( role, list ); |
| } |
| if( !list.contains( contributor ) ) { |
| list.add( contributor ); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private static void collectDefaultProviders( Map<String,List<ProviderDeploymentContributor>> defaults ) { |
| for( ProviderDeploymentContributor contributor : PROVIDER_CONTRIBUTORS ) { |
| String role = contributor.getRole(); |
| List<ProviderDeploymentContributor> list = defaults.computeIfAbsent(role, k -> new ArrayList<>()); |
| if( list.isEmpty() ) { |
| list.add( contributor ); |
| } |
| } |
| } |
| |
| // Scan through the services in the topology. |
| // For each that we find add it to the list of service roles included in the topology. |
| private static Map<String,List<ServiceDeploymentContributor>> selectContextServices( Topology topology ) { |
| Map<String,List<ServiceDeploymentContributor>> defaults |
| = new HashMap<>(); |
| for( Service service : topology.getServices() ) { |
| String role = service.getRole(); |
| ServiceDeploymentContributor contributor = getServiceContributor( role, service.getName(), service.getVersion() ); |
| if( contributor != null ) { |
| List<ServiceDeploymentContributor> list = defaults.computeIfAbsent(role, k -> new ArrayList<>(1)); |
| if( !list.contains( contributor ) ) { |
| list.add( contributor ); |
| } |
| } |
| } |
| return defaults; |
| } |
| |
| private static Map<String,ServiceDeploymentContributor> selectContextApplications( |
| GatewayConfig config, Topology topology ) { |
| Map<String,ServiceDeploymentContributor> contributors = new HashMap<>(); |
| if( topology != null ) { |
| for( Application application : topology.getApplications() ) { |
| String name = application.getName(); |
| if( name == null || name.isEmpty() ) { |
| throw new DeploymentException( "Topologies cannot contain an application without a name." ); |
| } |
| ApplicationDeploymentContributor contributor = new ApplicationDeploymentContributor( config, application ); |
| List<String> urls = application.getUrls(); |
| if( urls == null || urls.isEmpty() ) { |
| urls = new ArrayList<>( 1 ); |
| urls.add( "/" + name ); |
| } |
| for( String url : urls ) { |
| if( url == null || url.isEmpty() || "/".equals(url) ) { |
| if( !topology.getServices().isEmpty() ) { |
| throw new DeploymentException( String.format(Locale.ROOT, |
| "Topologies with services cannot contain an application (%s) with a root url.", name ) ); |
| } |
| } |
| contributors.put( url, contributor ); |
| } |
| } |
| } |
| return contributors; |
| } |
| |
| private static void initialize( |
| DeploymentContext context, |
| Map<String,List<ProviderDeploymentContributor>> providers, |
| Map<String,List<ServiceDeploymentContributor>> services, |
| Map.Entry<String,ServiceDeploymentContributor> applications ) { |
| WebAppDescriptor wad = context.getWebAppDescriptor(); |
| String topoName = context.getTopology().getName(); |
| if( applications == null ) { |
| String servletName = topoName + SERVLET_NAME_SUFFIX; |
| wad.createServlet().servletName( servletName ).servletClass( GatewayServlet.class.getName() ); |
| wad.createServletMapping().servletName( servletName ).urlPattern( "/*" ); |
| } else { |
| String filterName = topoName + FILTER_NAME_SUFFIX; |
| wad.createFilter().filterName( filterName ).filterClass( GatewayServlet.class.getName() ); |
| wad.createFilterMapping().filterName( filterName ).urlPattern( "/*" ); |
| } |
| if (gatewayServices != null) { |
| gatewayServices.initializeContribution(context); |
| } else { |
| log.gatewayServicesNotInitialized(); |
| } |
| initializeProviders( context, providers ); |
| initializeServices( context, services ); |
| initializeApplications( context, applications ); |
| } |
| |
| private static void initializeProviders( |
| DeploymentContext context, |
| Map<String,List<ProviderDeploymentContributor>> providers ) { |
| if( providers != null ) { |
| for( Entry<String, List<ProviderDeploymentContributor>> entry : providers.entrySet() ) { |
| for( ProviderDeploymentContributor contributor : entry.getValue() ) { |
| try { |
| injectServices( contributor ); |
| log.initializeProvider( contributor.getName(), contributor.getRole() ); |
| contributor.initializeContribution( context ); |
| } catch( Exception e ) { |
| log.failedToInitializeContribution( e ); |
| throw new DeploymentException( "Failed to initialize contribution.", e ); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void initializeServices( DeploymentContext context, Map<String, List<ServiceDeploymentContributor>> services ) { |
| if( services != null ) { |
| for( Entry<String, List<ServiceDeploymentContributor>> entry : services.entrySet() ) { |
| for( ServiceDeploymentContributor contributor : entry.getValue() ) { |
| try { |
| injectServices( contributor ); |
| log.initializeService( contributor.getName(), contributor.getRole() ); |
| contributor.initializeContribution( context ); |
| } catch( Exception e ) { |
| log.failedToInitializeContribution( e ); |
| throw new DeploymentException( "Failed to initialize contribution.", e ); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void initializeApplications( DeploymentContext context, Map.Entry<String, ServiceDeploymentContributor> application ) { |
| if( application != null ) { |
| ServiceDeploymentContributor contributor = application.getValue(); |
| if( contributor != null ) { |
| try { |
| injectServices( contributor ); |
| log.initializeApplication( contributor.getName() ); |
| contributor.initializeContribution( context ); |
| } catch( Exception e ) { |
| log.failedToInitializeContribution( e ); |
| throw new DeploymentException( "Failed to initialize application contribution.", e ); |
| } |
| } |
| } |
| } |
| |
| private static void injectServices(Object contributor) { |
| if (gatewayServices != null) { |
| Statement stmt; |
| for(ServiceType serviceType : gatewayServices.getServiceTypes()) { |
| |
| try { |
| // TODO: this is just a temporary injection solution |
| // TODO: test for the existence of the setter before attempting it |
| // TODO: avoid exception throwing when there is no setter |
| stmt = new Statement(contributor, "set" + serviceType.getServiceTypeName(), new Object[]{gatewayServices.getService(serviceType)}); |
| stmt.execute(); |
| } catch (NoSuchMethodException e) { |
| // TODO: eliminate the possibility of this being thrown up front |
| } catch (Exception e) { |
| // Maybe it makes sense to throw exception |
| log.failedToInjectService( serviceType.getServiceTypeName(), e ); |
| throw new DeploymentException("Failed to inject service.", e); |
| } |
| } |
| } |
| } |
| |
| private static void contribute( |
| DeploymentContext context, |
| Map<String,List<ProviderDeploymentContributor>> providers, |
| Map<String,List<ServiceDeploymentContributor>> services, |
| Map.Entry<String,ServiceDeploymentContributor> applications ) { |
| Topology topology = context.getTopology(); |
| contributeProviders( context, topology, providers ); |
| contributeServices( context, topology, services ); |
| contributeApplications( context, topology, applications ); |
| } |
| |
| private static void contributeProviders( DeploymentContext context, Topology topology, Map<String, List<ProviderDeploymentContributor>> providers ) { |
| for( Provider provider : topology.getProviders() ) { |
| ProviderDeploymentContributor contributor = getProviderContributor( providers, provider.getRole(), provider.getName() ); |
| if( contributor != null && provider.isEnabled() ) { |
| try { |
| log.contributeProvider( provider.getName(), provider.getRole() ); |
| contributor.contributeProvider( context, provider ); |
| } catch( Exception e ) { |
| // Maybe it makes sense to throw exception |
| log.failedToContributeProvider( provider.getName(), provider.getRole(), e ); |
| throw new DeploymentException("Failed to contribute provider.", e); |
| } |
| } |
| } |
| } |
| |
| private static void contributeServices( DeploymentContext context, Topology topology, Map<String, List<ServiceDeploymentContributor>> services ) { |
| if( services != null ) { |
| for( Service service : topology.getServices() ) { |
| ServiceDeploymentContributor contributor = getServiceContributor( service.getRole(), service.getName(), service.getVersion() ); |
| if( contributor != null ) { |
| try { |
| log.contributeService( service.getName(), service.getRole() ); |
| contributor.contributeService( context, service ); |
| if( gatewayServices != null ) { |
| ServiceRegistry sr = gatewayServices.getService( ServiceType.SERVICE_REGISTRY_SERVICE ); |
| if( sr != null ) { |
| String regCode = sr.getRegistrationCode( topology.getName() ); |
| sr.registerService( regCode, topology.getName(), service.getRole(), service.getUrls() ); |
| } |
| } |
| } catch( Exception e ) { |
| // Maybe it makes sense to throw exception |
| log.failedToContributeService( service.getName(), service.getRole(), e ); |
| throw new DeploymentException( "Failed to contribute service.", e ); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void contributeApplications( DeploymentContext context, Topology topology, Map.Entry<String, ServiceDeploymentContributor> applications ) { |
| if( applications != null ) { |
| ServiceDeploymentContributor contributor = applications.getValue(); |
| if( contributor != null ) { |
| try { |
| log.contributeApplication( contributor.getName() ); |
| Application applicationDesc = topology.getApplication( applications.getKey() ); |
| contributor.contributeService( context, applicationDesc ); |
| } catch( Exception e ) { |
| log.failedToInitializeContribution( e ); |
| throw new DeploymentException( "Failed to contribution application.", e ); |
| } |
| } |
| } |
| } |
| |
| public static ProviderDeploymentContributor getProviderContributor( String role, String name ) { |
| ProviderDeploymentContributor contributor = null; |
| Map<String,ProviderDeploymentContributor> nameMap = PROVIDER_CONTRIBUTOR_MAP.get( role ); |
| if( nameMap != null ) { |
| if( name != null ) { |
| contributor = nameMap.get( name ); |
| } else if ( !nameMap.isEmpty() ) { |
| contributor = nameMap.values().iterator().next(); |
| } |
| } |
| return contributor; |
| } |
| |
| public static ServiceDeploymentContributor getServiceContributor( String role, String name, Version version ) { |
| ServiceDeploymentContributor contributor = null; |
| Map<String,Map<Version, ServiceDeploymentContributor>> nameMap = SERVICE_CONTRIBUTOR_MAP.get( role ); |
| if( nameMap != null && !nameMap.isEmpty()) { |
| Map<Version, ServiceDeploymentContributor> versionMap; |
| if ( name == null ) { |
| versionMap = nameMap.values().iterator().next(); |
| } else { |
| versionMap = nameMap.get( name ); |
| } |
| if ( versionMap != null && !versionMap.isEmpty()) { |
| if( version == null ) { |
| contributor = ((TreeMap<Version, ServiceDeploymentContributor>) versionMap).lastEntry().getValue(); |
| } else { |
| contributor = versionMap.get( version ); |
| } |
| } |
| } |
| return contributor; |
| } |
| |
| private static void finish( |
| DeploymentContext context, |
| Map<String,List<ProviderDeploymentContributor>> providers, |
| Map<String,List<ServiceDeploymentContributor>> services, |
| Map.Entry<String,ServiceDeploymentContributor> application ) { |
| try { |
| // Write the gateway descriptor (gateway.xml) into the war. |
| StringWriter writer = new StringWriter(); |
| GatewayDescriptorFactory.store( context.getGatewayDescriptor(), "xml", writer ); |
| context.getWebArchive().addAsWebInfResource( |
| new StringAsset( writer.toString() ), |
| GatewayServlet.GATEWAY_DESCRIPTOR_LOCATION_DEFAULT ); |
| |
| // Set the location of the gateway descriptor as a servlet init param. |
| if( application == null ) { |
| String servletName = context.getTopology().getName() + SERVLET_NAME_SUFFIX; |
| ServletType<WebAppDescriptor> servlet = findServlet( context, servletName ); |
| // Coverity CID 1352314 |
| if( servlet == null ) { |
| throw new DeploymentException( "Missing servlet " + servletName ); |
| } else { |
| servlet.createInitParam() |
| .paramName( GatewayServlet.GATEWAY_DESCRIPTOR_LOCATION_PARAM ) |
| .paramValue( "/WEB-INF/" + GatewayServlet.GATEWAY_DESCRIPTOR_LOCATION_DEFAULT ); |
| } |
| } else { |
| String servletName = context.getTopology().getName() + FILTER_NAME_SUFFIX; |
| FilterType<WebAppDescriptor> filter = findFilter( context, servletName ); |
| // Coverity CID 1352313 |
| if( filter == null ) { |
| throw new DeploymentException( "Missing filter " + servletName ); |
| } else { |
| filter.createInitParam() |
| .paramName( GatewayServlet.GATEWAY_DESCRIPTOR_LOCATION_PARAM ) |
| .paramValue( "/WEB-INF/" + GatewayServlet.GATEWAY_DESCRIPTOR_LOCATION_DEFAULT ); |
| } |
| } |
| if (gatewayServices != null) { |
| gatewayServices.finalizeContribution(context); |
| } |
| finalizeProviders( context, providers ); |
| finalizeServices( context, services ); |
| finalizeApplications( context, application ); |
| writeDeploymentDescriptor( context, application != null ); |
| } catch ( IOException e ) { |
| throw new RuntimeException( e ); |
| } |
| } |
| |
| private static void finalizeProviders( DeploymentContext context, Map<String, List<ProviderDeploymentContributor>> providers ) { |
| if( providers != null ) { |
| for( Entry<String, List<ProviderDeploymentContributor>> entry : providers.entrySet() ) { |
| for( ProviderDeploymentContributor contributor : entry.getValue() ) { |
| try { |
| log.finalizeProvider( contributor.getName(), contributor.getRole() ); |
| contributor.finalizeContribution( context ); |
| } catch( Exception e ) { |
| // Maybe it makes sense to throw exception |
| log.failedToFinalizeContribution( e ); |
| throw new DeploymentException( "Failed to finish contribution.", e ); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void finalizeServices( DeploymentContext context, Map<String, List<ServiceDeploymentContributor>> services ) { |
| if( services != null ) { |
| for( Entry<String, List<ServiceDeploymentContributor>> entry : services.entrySet() ) { |
| for( ServiceDeploymentContributor contributor : entry.getValue() ) { |
| try { |
| log.finalizeService( contributor.getName(), contributor.getRole() ); |
| contributor.finalizeContribution( context ); |
| } catch( Exception e ) { |
| // Maybe it makes sense to throw exception |
| log.failedToFinalizeContribution( e ); |
| throw new DeploymentException( "Failed to finish contribution.", e ); |
| } |
| } |
| } |
| } |
| } |
| |
| private static void finalizeApplications( DeploymentContext context, Map.Entry<String, ServiceDeploymentContributor> application ) { |
| if( application != null ) { |
| ServiceDeploymentContributor contributor = application.getValue(); |
| if( contributor != null ) { |
| try { |
| log.finalizeApplication( contributor.getName() ); |
| contributor.finalizeContribution( context ); |
| } catch( Exception e ) { |
| log.failedToInitializeContribution( e ); |
| throw new DeploymentException( "Failed to contribution application.", e ); |
| } |
| } |
| } |
| } |
| |
| private static void writeDeploymentDescriptor( DeploymentContext context, boolean override ) { |
| // Write the web.xml into the war. |
| Asset webXmlAsset = new StringAsset( context.getWebAppDescriptor().exportAsString() ); |
| if( override ) { |
| context.getWebArchive().addAsWebInfResource( webXmlAsset, "override-web.xml" ); |
| } else { |
| context.getWebArchive().setWebXML( webXmlAsset ); |
| } |
| } |
| |
| public static ServletType<WebAppDescriptor> findServlet( DeploymentContext context, String name ) { |
| List<ServletType<WebAppDescriptor>> servlets = context.getWebAppDescriptor().getAllServlet(); |
| for( ServletType<WebAppDescriptor> servlet : servlets ) { |
| if( name.equals( servlet.getServletName() ) ) { |
| return servlet; |
| } |
| } |
| return null; |
| } |
| |
| public static FilterType<WebAppDescriptor> findFilter( DeploymentContext context, String name ) { |
| List<FilterType<WebAppDescriptor>> filters = context.getWebAppDescriptor().getAllFilter(); |
| for( FilterType<WebAppDescriptor> filter : filters ) { |
| if( name.equals( filter.getFilterName() ) ) { |
| return filter; |
| } |
| } |
| return null; |
| } |
| |
| private static void loadStacksServiceContributors( GatewayConfig config ) { |
| String stacks = config.getGatewayServicesDir(); |
| log.usingServicesDirectory(stacks); |
| File stacksDir = new File(stacks); |
| Set<ServiceDeploymentContributor> deploymentContributors = ServiceDefinitionsLoader.loadServiceDefinitionDeploymentContributors(stacksDir); |
| addServiceDeploymentContributors(deploymentContributors.iterator()); |
| } |
| |
| private static void loadServiceContributors() { |
| SERVICE_CONTRIBUTOR_MAP = new HashMap<>(); |
| ServiceLoader<ServiceDeploymentContributor> loader = ServiceLoader.load( ServiceDeploymentContributor.class ); |
| Iterator<ServiceDeploymentContributor> contributors = loader.iterator(); |
| addServiceDeploymentContributors(contributors); |
| } |
| |
| private static void addServiceDeploymentContributors(Iterator<ServiceDeploymentContributor> contributors) { |
| while( contributors.hasNext() ) { |
| ServiceDeploymentContributor contributor = contributors.next(); |
| if( contributor.getName() == null ) { |
| log.ignoringServiceContributorWithMissingName( contributor.getClass().getName() ); |
| continue; |
| } |
| if( contributor.getRole() == null ) { |
| log.ignoringServiceContributorWithMissingRole( contributor.getClass().getName() ); |
| continue; |
| } |
| if( contributor.getVersion() == null ) { |
| log.ignoringServiceContributorWithMissingVersion(contributor.getClass().getName()); |
| continue; |
| } |
| Map<String,Map<Version, ServiceDeploymentContributor>> nameMap = SERVICE_CONTRIBUTOR_MAP.get( contributor.getRole() ); |
| if( nameMap == null ) { |
| nameMap = new HashMap<>(); |
| SERVICE_CONTRIBUTOR_MAP.put( contributor.getRole(), nameMap ); |
| } |
| Map<Version, ServiceDeploymentContributor> versionMap = nameMap.get(contributor.getName()); |
| if (versionMap == null) { |
| versionMap = new TreeMap<>(); |
| nameMap.put(contributor.getName(), versionMap); |
| } |
| versionMap.put( contributor.getVersion(), contributor ); |
| } |
| } |
| |
| private static void loadProviderContributors() { |
| Set<ProviderDeploymentContributor> set = new HashSet<>(); |
| Map<String,Map<String,ProviderDeploymentContributor>> roleMap |
| = new HashMap<>(); |
| |
| ServiceLoader<ProviderDeploymentContributor> loader = ServiceLoader.load( ProviderDeploymentContributor.class ); |
| for (ProviderDeploymentContributor contributor : loader) { |
| if (contributor.getName() == null) { |
| log.ignoringProviderContributorWithMissingName(contributor.getClass().getName()); |
| continue; |
| } |
| if (contributor.getRole() == null) { |
| log.ignoringProviderContributorWithMissingRole(contributor.getClass().getName()); |
| continue; |
| } |
| set.add(contributor); |
| Map nameMap = roleMap.get(contributor.getRole()); |
| if (nameMap == null) { |
| nameMap = new HashMap<>(); |
| roleMap.put(contributor.getRole(), nameMap); |
| } |
| nameMap.put(contributor.getName(), contributor); |
| } |
| PROVIDER_CONTRIBUTORS = set; |
| PROVIDER_CONTRIBUTOR_MAP = roleMap; |
| } |
| |
| static ProviderDeploymentContributor getProviderContributor( |
| Map<String,List<ProviderDeploymentContributor>> providers, String role, String name ) { |
| ProviderDeploymentContributor contributor = null; |
| if( name == null ) { |
| List<ProviderDeploymentContributor> list = providers.get( role ); |
| if( list != null && !list.isEmpty() ) { |
| contributor = list.get( 0 ); |
| } |
| } else { |
| contributor = getProviderContributor( role, name ); |
| // Explicit configuration that is wrong should just fail |
| // rather than randomly select a provider. Implicit default |
| // providers can be selected when no name is provided. |
| if (contributor == null || !contributor.getRole().equals(role) || |
| !contributor.getName().equals(name)) { |
| throw new DeploymentException( |
| "Failed to contribute provider. Role: " + |
| role + " Name: " + name + ". Please check the topology for" + |
| " errors in name and role and that the provider is " + |
| "on the classpath."); |
| } |
| } |
| return contributor; |
| } |
| } |