ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/startup/WebappServiceLoader.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/catalina/startup/WebappServiceLoader.java
Status
scanned
Type
file
Name
WebappServiceLoader.java
Extension
.java
Programming language
Java
Mime type
text/plain
File type
ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
10828 (10.6 KB)
MD5
9ca7f37b5ed0738caa7e18d5ed6b9593
SHA1
2cfe28f65f2e0c215dc56d2e4abf0b57c153cea1
SHA256
ffbb077fde6362a48a31a64969965f734beb1f840e7be9fed97fa32102c4d118
SHA512

      
    
SHA1_git
c9cdb66151683d4bacebd7ae7e67939d866d4f04
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
WebappServiceLoader.java | 10.6 KB |

/* * 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.catalina.startup; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.regex.Pattern; import jakarta.servlet.ServletContext; import org.apache.catalina.Context; import org.apache.tomcat.util.scan.JarFactory; /** * A variation of Java's JAR ServiceLoader that respects exclusion rules for web applications. * <p> * Primarily intended for use loading ServletContainerInitializers as defined by Servlet 8.2.4. This implementation does * not attempt lazy loading as the container is required to introspect all implementations discovered. * <p> * If the ServletContext defines ORDERED_LIBS, then only JARs in WEB-INF/lib that are named in that set will be included * in the search for provider configuration files; if ORDERED_LIBS is not defined then all JARs will be searched for * provider configuration files. Providers defined by resources in the parent ClassLoader will always be returned. * <p> * Provider classes will be loaded using the context's ClassLoader. * * @param <T> The type of service to load * * @see jakarta.servlet.ServletContainerInitializer * @see java.util.ServiceLoader */ public class WebappServiceLoader<T> { private static final String CLASSES = "/WEB-INF/classes/"; private static final String LIB = "/WEB-INF/lib/"; private static final String SERVICES = "META-INF/services/"; private final Context context; private final ServletContext servletContext; private final Pattern containerSciFilterPattern; /** * Construct a loader to load services from a ServletContext. * * @param context the context to use */ public WebappServiceLoader(Context context) { this.context = context; this.servletContext = context.getServletContext(); String containerSciFilter = context.getContainerSciFilter(); if (containerSciFilter != null && !containerSciFilter.isEmpty()) { containerSciFilterPattern = Pattern.compile(containerSciFilter); } else { containerSciFilterPattern = null; } } /** * Load the providers for a service type. Container defined services will be loaded before application defined * services in case the application depends on a Container provided service. Note that services are always loaded * via the Context (web application) class loader so it is possible for an application to provide an alternative * implementation of what would normally be a Container provided service. * * @param serviceType the type of service to load * * @return an unmodifiable collection of service providers * * @throws IOException if there was a problem loading any service */ public List<T> load(Class<T> serviceType) throws IOException { String configFile = SERVICES + serviceType.getName(); // Obtain the Container provided service configuration files. ClassLoader loader = context.getParentClassLoader(); Enumeration<URL> containerResources; if (loader == null) { containerResources = ClassLoader.getSystemResources(configFile); } else { containerResources = loader.getResources(configFile); } // Extract the Container provided service class names. Each // configuration file may list more than one service class name. This // uses a LinkedHashSet so if a service class name appears more than // once in the configuration files, only the first one found is used. LinkedHashSet<String> containerServiceClassNames = new LinkedHashSet<>(); Set<URL> containerServiceConfigFiles = new HashSet<>(); while (containerResources.hasMoreElements()) { URL containerServiceConfigFile = containerResources.nextElement(); containerServiceConfigFiles.add(containerServiceConfigFile); parseConfigFile(containerServiceClassNames, containerServiceConfigFile); } // Filter the discovered container SCIs if required if (containerSciFilterPattern != null) { containerServiceClassNames.removeIf(s -> containerSciFilterPattern.matcher(s).find()); } // Obtaining the application provided configuration files is a little // more difficult for two reasons: // - The web application may employ a custom class loader. Ideally, we // would use ClassLoader.findResources() but that method is protected. // We could force custom class loaders to override that method and // make it public but that would be a new requirement and break // backwards compatibility for what is an often customised component. // - If the application web.xml file has defined an order for fragments // then only those JAR files represented by fragments in that order // (and arguably WEB-INF/classes) should be scanned for services. LinkedHashSet<String> applicationServiceClassNames = new LinkedHashSet<>(); // Check to see if the ServletContext has ORDERED_LIBS defined @SuppressWarnings("unchecked") List<String> orderedLibs = (List<String>) servletContext.getAttribute(ServletContext.ORDERED_LIBS); // Obtain the application provided service configuration files if (orderedLibs == null) { // Because a custom class loader may be being used, we have to use // getResources() which will return application and Container files. Enumeration<URL> allResources = servletContext.getClassLoader().getResources(configFile); while (allResources.hasMoreElements()) { URL serviceConfigFile = allResources.nextElement(); // Only process the service configuration file if it is not a // Container level file that has already been processed if (!containerServiceConfigFiles.contains(serviceConfigFile)) { parseConfigFile(applicationServiceClassNames, serviceConfigFile); } } } else { // Ordered libs so only use services defined in those libs and any // in WEB-INF/classes URL unpacked = servletContext.getResource(CLASSES + configFile); if (unpacked != null) { parseConfigFile(applicationServiceClassNames, unpacked); } for (String lib : orderedLibs) { URL jarUrl = servletContext.getResource(LIB + lib); if (jarUrl == null) { // should not happen, just ignore continue; } String base = jarUrl.toExternalForm(); URL url; if (base.endsWith("/")) { URI uri; try { uri = new URI(base + configFile); } catch (URISyntaxException e) { // Not ideal but consistent with public API throw new IOException(e); } url = uri.toURL(); } else { url = JarFactory.getJarEntryURL(jarUrl, configFile); } try { parseConfigFile(applicationServiceClassNames, url); } catch (FileNotFoundException e) { // no provider file found, this is OK } } } // Add the application services after the container services to ensure // that the container services are loaded first containerServiceClassNames.addAll(applicationServiceClassNames); // Short-cut if no services have been found if (containerServiceClassNames.isEmpty()) { return Collections.emptyList(); } // Load the discovered services return loadServices(serviceType, containerServiceClassNames); } void parseConfigFile(LinkedHashSet<String> servicesFound, URL url) throws IOException { try (InputStream is = url.openStream(); InputStreamReader in = new InputStreamReader(is, StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(in)) { String line; while ((line = reader.readLine()) != null) { int i = line.indexOf('#'); if (i >= 0) { line = line.substring(0, i); } line = line.trim(); if (line.isEmpty()) { continue; } servicesFound.add(line); } } } List<T> loadServices(Class<T> serviceType, LinkedHashSet<String> servicesFound) throws IOException { ClassLoader loader = servletContext.getClassLoader(); List<T> services = new ArrayList<>(servicesFound.size()); for (String serviceClass : servicesFound) { try { Class<?> clazz = Class.forName(serviceClass, true, loader); services.add(serviceType.cast(clazz.getConstructor().newInstance())); } catch (ReflectiveOperationException | ClassCastException e) { throw new IOException(e); } } return Collections.unmodifiableList(services); } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
11.31
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9