diff --git a/src/fr/devinsy/kiss4web/dispatcher/KissDispatcher.java b/src/fr/devinsy/kiss4web/dispatcher/KissDispatcher.java index eea3912..230ea76 100755 --- a/src/fr/devinsy/kiss4web/dispatcher/KissDispatcher.java +++ b/src/fr/devinsy/kiss4web/dispatcher/KissDispatcher.java @@ -21,6 +21,8 @@ package fr.devinsy.kiss4web.dispatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import fr.devinsy.kiss4web.dispatcher.annotation.AnnotationHooks; +import fr.devinsy.kiss4web.dispatcher.annotation.AnnotationUtils; import fr.devinsy.kiss4web.dispatcher.hooks.ErrorServlet; import fr.devinsy.kiss4web.dispatcher.hooks.Hook; import fr.devinsy.kiss4web.dispatcher.hooks.HookRegister; @@ -49,6 +51,7 @@ public class KissDispatcher // Pathinfo -> Servlet. private ServletCache cache; + private AnnotationHooks annotationHooks; /** * Instantiates a new kiss dispatcher. @@ -57,6 +60,17 @@ public class KissDispatcher { this.cache = new ServletCache(); this.hookRegister = new HookRegister("Init").register(new InitHook()); + this.annotationHooks = AnnotationUtils.getAnnotationHooks(); + } + + /** + * Gets the annotation hooks. + * + * @return the annotation hooks + */ + public AnnotationHooks getAnnotationHooks() + { + return this.annotationHooks; } /** diff --git a/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHook.java b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHook.java new file mode 100644 index 0000000..04d0019 --- /dev/null +++ b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHook.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2024 Christian Pierre MOMON + * + * This file is part of Kiss4web. + * + * Kiss4web is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Kiss4web is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Kiss4web. If not, see + */ +package fr.devinsy.kiss4web.dispatcher.annotation; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fr.devinsy.kiss4web.dispatcher.hooks.RewriteHook; + +/** + * The Class AnnotationHook. + */ +public class AnnotationHook extends RewriteHook +{ + private static Logger logger = LoggerFactory.getLogger(AnnotationHook.class); + + /** + * Instantiates a new annotation hook. + * + * @param regex + * the regex + * @param targetClassName + * the target class name + */ + public AnnotationHook(final String regex, final String targetClassName) + { + super(regex, targetClassName); + } +} diff --git a/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHooks.java b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHooks.java new file mode 100644 index 0000000..ec40396 --- /dev/null +++ b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationHooks.java @@ -0,0 +1,37 @@ +/** + * Copyright (C) 2024 Christian Pierre MOMON + * + * This file is part of Kiss4web. + * + * Kiss4web is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Kiss4web is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Kiss4web. If not, see + */ +package fr.devinsy.kiss4web.dispatcher.annotation; + +import java.util.ArrayList; + +/** + * The Class AnnotationHooks. + */ +public class AnnotationHooks extends ArrayList +{ + private static final long serialVersionUID = 1979896054785066359L; + + /** + * Instantiates a new hook list. + */ + public AnnotationHooks() + { + super(); + } +} diff --git a/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationUtils.java b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationUtils.java new file mode 100644 index 0000000..e95bcaf --- /dev/null +++ b/src/fr/devinsy/kiss4web/dispatcher/annotation/AnnotationUtils.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2006-2024 Christian Pierre MOMON + * + * This file is part of Kiss4web. + * + * Kiss4web is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Kiss4web is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Kiss4web. If not, see + */ +package fr.devinsy.kiss4web.dispatcher.annotation; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fr.devinsy.kiss4web.Kiss4webException; +import jakarta.servlet.http.HttpServlet; + +/** + * The Class AnnotationUtils. + */ +public class AnnotationUtils +{ + private static final Logger logger = LoggerFactory.getLogger(AnnotationUtils.class); + + /** + * Recursive method used to find all classes in a given directory and + * subdirs. + * + * @param directory + * The base directory + * @param packageName + * The package name for classes found inside the base directory + * @return The classes + * @throws ClassNotFoundException + */ + private static List findClasses(final File directory, final String packageName) throws ClassNotFoundException + { + List result; + + result = new ArrayList(); + if (directory.exists()) + { + File[] files = directory.listFiles(); + for (File file : files) + { + if (file.isDirectory()) + { + assert !file.getName().contains("."); + result.addAll(findClasses(file, packageName + "." + file.getName())); + } + else if (file.getName().endsWith(".class")) + { + result.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6))); + } + } + } + + // + return result; + } + + /** + * Gets the annotation hooks. + * + * @return the annotation hooks + * @throws Kiss4webException + */ + public static AnnotationHooks getAnnotationHooks() + { + AnnotationHooks result; + + try + { + result = new AnnotationHooks(); + Class[] classes = getClasses("website"); + for (Class clazz : classes) + { + if (clazz.isAnnotationPresent(KissServlet.class)) + { + // System.out.println("==> " + clazz.getName() + " " + + // clazz.getCanonicalName()); + // System.out.println("==> " + ((Class) + // clazz).getAnnotation(KissServlet.class).value()); + + String className = clazz.getCanonicalName(); + String regexPathInfo = ((Class) clazz).getAnnotation(KissServlet.class).value(); + + AnnotationHook hook = new AnnotationHook(regexPathInfo, className); + result.add(hook); + } + } + } + catch (ClassNotFoundException | IOException exception) + { + logger.error("Package website undefined, KissServlet annotations ignored.", exception); + result = new AnnotationHooks(); + } + + // + return result; + } + + /** + * Gets the classes. + * + * @param packageName + * the package name + * @return the classes + * @throws ClassNotFoundException + * the class not found exception + * @throws IOException + * Signals that an I/O exception has occurred. + */ + private static Class[] getClasses(final String packageName) throws ClassNotFoundException, IOException + { + Class[] result; + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + assert classLoader != null; + String path = packageName.replace('.', '/'); + Enumeration resources = classLoader.getResources(path); + List dirs = new ArrayList(); + while (resources.hasMoreElements()) + { + URL resource = resources.nextElement(); + dirs.add(new File(resource.getFile())); + } + ArrayList classes = new ArrayList(); + for (File directory : dirs) + { + classes.addAll(findClasses(directory, packageName)); + } + result = classes.toArray(new Class[classes.size()]); + + // + return result; + } +} \ No newline at end of file diff --git a/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServlet.java b/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServlet.java new file mode 100644 index 0000000..ac8e58f --- /dev/null +++ b/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServlet.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 Christian Pierre MOMON + * + * This file is part of Kiss4web. + * + * Kiss4web is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Kiss4web is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Kiss4web. If not, see + */ +package fr.devinsy.kiss4web.dispatcher.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface KissServlet +{ + String value(); +} diff --git a/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServletProcessor.java b/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServletProcessor.java new file mode 100644 index 0000000..4c9d62d --- /dev/null +++ b/src/fr/devinsy/kiss4web/dispatcher/annotation/KissServletProcessor.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 Christian Pierre MOMON + * + * This file is part of Kiss4web. + * + * Kiss4web is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Kiss4web is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Kiss4web. If not, see + */ +package fr.devinsy.kiss4web.dispatcher.annotation; + +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.ProcessingEnvironment; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic; + +@javax.annotation.processing.SupportedAnnotationTypes("fr.devinsy.kiss4web.dispatcher.annotation.KissServlet") +@javax.annotation.processing.SupportedSourceVersion(javax.lang.model.SourceVersion.RELEASE_17) +public class KissServletProcessor extends AbstractProcessor +{ + /** + * {@inheritDoc} + */ + @Override + public synchronized void init(final ProcessingEnvironment processingEnv) + { + super.init(processingEnv); + // Initialization code, if needed + System.out.println("=============== @INIT"); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean process(final Set annotations, final RoundEnvironment roundEnv) + { + for (TypeElement annotation : annotations) + { + // Find elements annotated with MyCustomAnnotation + for (Element element : roundEnv.getElementsAnnotatedWith(annotation)) + { + // Process each element + this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Processing: " + element.getSimpleName()); + + // Your processing logic here + System.out.println("=============== YOOOOOOOOOOP"); + } + } + + // + return true; // No further processing of this annotation type + } +} \ No newline at end of file diff --git a/src/fr/devinsy/kiss4web/dispatcher/hooks/HookRegister.java b/src/fr/devinsy/kiss4web/dispatcher/hooks/HookRegister.java index 47d92ac..43930ab 100644 --- a/src/fr/devinsy/kiss4web/dispatcher/hooks/HookRegister.java +++ b/src/fr/devinsy/kiss4web/dispatcher/hooks/HookRegister.java @@ -18,6 +18,7 @@ */ package fr.devinsy.kiss4web.dispatcher.hooks; +import java.util.Collection; import java.util.Iterator; import jakarta.servlet.ServletContext; @@ -119,6 +120,25 @@ public class HookRegister return result; } + /** + * Register. + * + * @param hook + * the hook + * @return the hook register + */ + public HookRegister register(final Collection hooks) + { + HookRegister result; + + this.hooks.addAll(hooks); + + result = this; + + // + return result; + } + /** * Register. * diff --git a/src/fr/devinsy/kiss4web/dispatcher/hooks/RewriteHook.java b/src/fr/devinsy/kiss4web/dispatcher/hooks/RewriteHook.java index bf0274a..fd264e9 100644 --- a/src/fr/devinsy/kiss4web/dispatcher/hooks/RewriteHook.java +++ b/src/fr/devinsy/kiss4web/dispatcher/hooks/RewriteHook.java @@ -95,4 +95,20 @@ public class RewriteHook extends HookCore // return result; } + + /** + * To string. + * + * @return the string + */ + @Override + public String toString() + { + String result; + + result = this.pattern.toString() + " -> " + this.targetClassName; + + // + return result; + } }