1 /*
2 * Copyright 2012-2025 CodeLibs Project and the Others.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
15 */
16 package org.codelibs.fess.tomcat.webresources;
17
18 import java.util.jar.Attributes;
19 import java.util.jar.JarFile;
20 import java.util.jar.Manifest;
21 import java.util.logging.Level;
22 import java.util.logging.Logger;
23
24 import org.apache.catalina.Context;
25 import org.apache.catalina.LifecycleException;
26 import org.apache.catalina.WebResource;
27 import org.apache.catalina.webresources.StandardRoot;
28
29 /**
30 * Fess-specific web resource root implementation for Tomcat.
31 * This class extends StandardRoot to provide custom web resource handling
32 * for Fess plugins, including support for plugin JAR files in the WEB-INF/plugin directory.
33 */
34 public class FessWebResourceRoot extends StandardRoot {
35 /** Logger instance for this class */
36 private static final Logger logger = Logger.getLogger(FessWebResourceRoot.class.getName());
37
38 /**
39 * Constructs a new FessWebResourceRoot with the specified context.
40 *
41 * @param context the Tomcat context for this web resource root
42 */
43 public FessWebResourceRoot(final Context context) {
44 super(context);
45 }
46
47 /**
48 * Processes WEB-INF/lib directory and additionally scans WEB-INF/plugin for Fess plugins.
49 * This method extends the standard processing to include plugin JAR files that contain
50 * the "Fess-WebAppJar" manifest attribute.
51 *
52 * @throws LifecycleException if an error occurs during processing
53 */
54 @Override
55 protected void processWebInfLib() throws LifecycleException {
56 super.processWebInfLib();
57
58 final WebResource[] possibleJars = listResources("/WEB-INF/plugin", false);
59
60 for (final WebResource possibleJar : possibleJars) {
61 if (possibleJar.isFile() && possibleJar.getName().endsWith(".jar")) {
62 try (final JarFile jarFile = new JarFile(possibleJar.getCanonicalPath())) {
63 final Manifest manifest = jarFile.getManifest();
64 if (manifest != null && manifest.getEntries() != null) {
65 final Attributes attributes = manifest.getMainAttributes();
66 if (attributes != null
67 && (attributes.get("Fess-WebAppJar") != null || attributes.getValue("Fess-WebAppJar") != null)) {
68 createWebResourceSet(ResourceSetType.CLASSES_JAR, "/WEB-INF/classes", possibleJar.getURL(), "/");
69 }
70 }
71 } catch (final Exception e) {
72 logger.log(Level.WARNING, e, () -> {
73 final String canonicalPath = possibleJar.getCanonicalPath();
74 return "Failed to read JAR file: path=" + canonicalPath;
75 });
76 }
77 }
78 }
79 }
80 }