Explorar o código

fix #2820 Add dynamic protocol registration based on PROTOCOL_TYPE in Handler class

Shinsuke Sugaya hai 1 ano
pai
achega
03f1eccee3

+ 59 - 0
src/main/java/org/codelibs/fess/helper/ProtocolHelper.java

@@ -18,12 +18,22 @@ package org.codelibs.fess.helper;
 import static org.codelibs.core.stream.StreamUtil.split;
 import static org.codelibs.core.stream.StreamUtil.stream;
 
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
 
 import javax.annotation.PostConstruct;
 
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
+import org.codelibs.core.exception.ClassNotFoundRuntimeException;
+import org.codelibs.core.exception.NoSuchFieldRuntimeException;
+import org.codelibs.core.lang.ClassUtil;
 import org.codelibs.core.lang.StringUtil;
 import org.codelibs.fess.mylasta.direction.FessConfig;
 import org.codelibs.fess.util.ComponentUtil;
@@ -42,12 +52,61 @@ public class ProtocolHelper {
                 .get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim() + ":").toArray(n -> new String[n]));
         fileProtocols = split(fessConfig.getCrawlerFileProtocols(), ",")
                 .get(stream -> stream.filter(StringUtil::isNotBlank).map(s -> s.trim() + ":").toArray(n -> new String[n]));
+
+        loadProtocols("org.codelibs.fess.net.protocol");
+
         if (logger.isDebugEnabled()) {
             logger.debug("web protocols: {}", Arrays.toString(webProtocols));
             logger.debug("file protocols: {}", Arrays.toString(fileProtocols));
         }
     }
 
+    protected void loadProtocols(final String basePackage) {
+        final List<String> subPackages = new ArrayList<>();
+        final String path = basePackage.replace('.', '/');
+        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        try {
+            final Enumeration<URL> resources = classLoader.getResources(path);
+
+            while (resources.hasMoreElements()) {
+                final URL resource = resources.nextElement();
+                final File directory = new File(resource.getFile());
+                if (directory.exists() && directory.isDirectory()) {
+                    final File[] files = directory.listFiles(File::isDirectory);
+                    if (files != null) {
+                        for (final File file : files) {
+                            subPackages.add(file.getName());
+                        }
+                    }
+                }
+            }
+        } catch (final IOException e) {
+            logger.warn("Cannot load subpackages from {}", basePackage, e);
+        }
+
+        subPackages.stream().forEach(protocol -> {
+            try {
+                final Class<Object> handlerClazz = ClassUtil.forName(basePackage + "." + protocol + ".Handler");
+                final Field protocolTypeField = ClassUtil.getDeclaredField(handlerClazz, "PROTOCOL_TYPE");
+                if (protocolTypeField.get(null) instanceof final String protocolType) {
+                    if ("web".equalsIgnoreCase(protocolType)) {
+                        addWebProtocol(protocol);
+                    } else if ("file".equalsIgnoreCase(protocolType)) {
+                        addFileProtocol(protocol);
+                    } else {
+                        logger.warn("Unknown protocol: {}", protocol);
+                    }
+                }
+            } catch (final ClassNotFoundRuntimeException e) {
+                logger.debug("{}.{}.Handler does not exist.", basePackage, protocol, e);
+            } catch (final NoSuchFieldRuntimeException e) {
+                logger.debug("{}.{}.Handler does not contain PROTOCOL_TYPE.", basePackage, protocol, e);
+            } catch (final Exception e) {
+                logger.warn("Cannot load Handler from {}.{}", basePackage, protocol, e);
+            }
+        });
+    }
+
     public String[] getWebProtocols() {
         return webProtocols;
     }

+ 8 - 0
src/test/java/org/codelibs/fess/helper/ProtocolHelperTest.java

@@ -99,4 +99,12 @@ public class ProtocolHelperTest extends UnitFessTestCase {
         assertEquals(2, protocolHelper.getWebProtocols().length);
         assertEquals(3, protocolHelper.getFileProtocols().length);
     }
+
+    public void test_loadProtocols() {
+        final ProtocolHelper protocolHelper = new ProtocolHelper();
+        protocolHelper.loadProtocols("org.codelibs.fess.test.net.protocol");
+
+        assertEquals(1, protocolHelper.getWebProtocols().length);
+        assertEquals(1, protocolHelper.getFileProtocols().length);
+    }
 }

+ 32 - 0
src/test/java/org/codelibs/fess/test/net/protocol/xxx1/Handler.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012-2024 CodeLibs Project and the Others.
+ *
+ * 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 org.codelibs.fess.test.net.protocol.xxx1;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+public class Handler extends URLStreamHandler {
+
+    public static final String PROTOCOL_TYPE = "web";
+
+    @Override
+    protected URLConnection openConnection(URL u) throws IOException {
+        return null;
+    }
+
+}

+ 32 - 0
src/test/java/org/codelibs/fess/test/net/protocol/xxx2/Handler.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012-2024 CodeLibs Project and the Others.
+ *
+ * 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 org.codelibs.fess.test.net.protocol.xxx2;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+public class Handler extends URLStreamHandler {
+
+    public static final String PROTOCOL_TYPE = "file";
+
+    @Override
+    protected URLConnection openConnection(URL u) throws IOException {
+        return null;
+    }
+
+}

+ 32 - 0
src/test/java/org/codelibs/fess/test/net/protocol/xxx3/Handler.java

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012-2024 CodeLibs Project and the Others.
+ *
+ * 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 org.codelibs.fess.test.net.protocol.xxx3;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+public class Handler extends URLStreamHandler {
+
+    public static final String PROTOCOL_TYPE = "test";
+
+    @Override
+    protected URLConnection openConnection(URL u) throws IOException {
+        return null;
+    }
+
+}

+ 30 - 0
src/test/java/org/codelibs/fess/test/net/protocol/xxx4/Handler.java

@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012-2024 CodeLibs Project and the Others.
+ *
+ * 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 org.codelibs.fess.test.net.protocol.xxx4;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+public class Handler extends URLStreamHandler {
+
+    @Override
+    protected URLConnection openConnection(URL u) throws IOException {
+        return null;
+    }
+
+}

+ 20 - 0
src/test/java/org/codelibs/fess/test/net/protocol/xxx5/TestHandler.java

@@ -0,0 +1,20 @@
+/*
+ * Copyright 2012-2024 CodeLibs Project and the Others.
+ *
+ * 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 org.codelibs.fess.test.net.protocol.xxx5;
+
+public class TestHandler {
+
+}