/******************************************************************************* * 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.ofbiz.catalina.container; import java.io.File; import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import org.apache.tomcat.JarScanFilter; import org.apache.tomcat.JarScanType; import org.apache.tomcat.util.scan.StandardJarScanFilter; import org.ofbiz.base.component.ComponentConfig; import org.ofbiz.base.component.ComponentConfig.WebappInfo; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.UtilProperties; import org.reflections.Reflections; import javax.servlet.ServletContext; import javax.websocket.DeploymentException; import javax.websocket.server.ServerContainer; /** * Catalina Container Jar Filter. * <p> * SCIPIO: 2018-10-02: This class is completely redesigned. */ final class FilterJars extends StandardJarScanFilter { private static final Debug.OfbizLogger module = Debug.getOfbizLogger(java.lang.invoke.MethodHandles.lookup().lookupClass()); private static Set<String> globalScanEnabledJarNames; private final WebappInfo webappInfo; private static ServletContext servletContext = null; static { Set<String> jarNames = new HashSet<>(); readGlobalScanEnabledJarNames(jarNames); Debug.logInfo("Global server-scan enabled JAR names: " + new TreeSet<>(jarNames), module); globalScanEnabledJarNames = jarNames; } //private final WebappInfo webappInfo; private Set<String> scanEnabledJarNames; public FilterJars(WebappInfo webappInfo, ServletContext context) { super(); this.webappInfo = webappInfo; this.servletContext = context; this.scanEnabledJarNames = getCombinedScanEnabledJarNames(webappInfo); } @Override public boolean check(final JarScanType jarScanType, final String jarName) { return scanEnabledJarNames.contains(jarName); // SCIPIO: 2018-10-03: Simplified } static Set<String> getCombinedScanEnabledJarNames(WebappInfo webappInfo) { Set<String> jarNames = new HashSet<>(); // SCIPIO: 2019-12-21: Added scanning of base jars String configRoot = webappInfo.componentConfig.getRootLocation(); configRoot = configRoot.replace('\\', '/'); for(ComponentConfig.ClasspathInfo info : webappInfo.componentConfig.getClasspathInfos()){ if("jar".equals(info.type)){ String location = info.location.replace('\\', '/'); if (location.startsWith("/")) { location = location.substring(1); } String dirLoc = location; if (dirLoc.endsWith("/*")) { // strip off the slash splat dirLoc = location.substring(0, location.length() - 2); } String fileNameSeparator = ("\\".equals(File.separator) ? "\\" + File.separator : File.separator); dirLoc = dirLoc.replaceAll("/+|\\\\+", fileNameSeparator); File path = new File(configRoot, dirLoc); if (path.exists()) { if (path.isDirectory()) { for (File file: path.listFiles()) { String fileName = file.getName().toLowerCase(); if (fileName.endsWith(".jar")) { jarNames.add(file.getName()); } } } else { jarNames.add(path.getName()); } } } } readWebappScanEnabledJarNames(jarNames, webappInfo); if (jarNames.isEmpty()) { return globalScanEnabledJarNames; } Debug.logInfo("Webapp-specific server-scan enabled JAR names for " + webappInfo + ": " + new TreeSet<>(jarNames), module); jarNames.addAll(globalScanEnabledJarNames); return jarNames; } static void readGlobalScanEnabledJarNames(Set<String> jarNames) { if (UtilProperties.getPropertyAsBoolean("catalina", "webSocket", false)) { // SCIPIO: 2018-10-02: This should not be needed in our current setup, // will only slow loading down. //jarNames.add("ofbiz.jar"); for(File file : ComponentConfig.readClasspathSpecialJarLocations("websockets")) { jarNames.add(file.getName()); } /* https://stackoverflow.com/questions/20127800/mapping-websocketendpoints-in-a-web-xml-file Reflections reflections = new Reflections("org.home.junk"); Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(javax.annotation.); // Get a reference to the ServerContainer javax.websocket.server.ServerContainer ServerContainer = (javax.websocket.server.ServerContainer) servletContext.getAttribute("javax.websocket.server.ServerContainer"); // Add endpoint manually to server container serverContainer.addEndpoint(game.WebSocketEndpoint.class); */ } for(File file : ComponentConfig.readClasspathSpecialJarLocations("server-scan")) { jarNames.add(file.getName()); } } static void readWebappScanEnabledJarNames(Set<String> jarNames, WebappInfo webappInfo) { if (UtilProperties.getPropertyAsBoolean("catalina", "webSocket", false)) { // SCIPIO: 2018-10-02: This should not be needed in our current setup, // will only slow loading down. //jarNames.add("ofbiz.jar"); for(File file : ComponentConfig.readClasspathSpecialJarLocations(webappInfo.componentConfig, "websockets", webappInfo.getName())) { jarNames.add(file.getName()); } } for(File file : ComponentConfig.readClasspathSpecialJarLocations(webappInfo.componentConfig, "server-scan", webappInfo.getName())) { jarNames.add(file.getName()); } } }