Skip to content

Commit

Permalink
Fixes #4325 - Add HandlesTypes extension (#4326)
Browse files Browse the repository at this point in the history
  • Loading branch information
mnriem authored Dec 8, 2024
1 parent da6ff98 commit c8aa1d5
Show file tree
Hide file tree
Showing 32 changed files with 1,384 additions and 39 deletions.
103 changes: 103 additions & 0 deletions core/api/src/main/java/cloud/piranha/core/api/HandlesTypesManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2002-2024 Manorrock.com. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package cloud.piranha.core.api;

import java.util.Set;

/**
* The manager that delivers support for the HandlesTypes annotation.
*
* <p>
* Whenever the onStartup method of a ServletContainerInitializer is called it
* gets passed a set of classes that it expressed interest in. This manager
* delivers the way a web application can vend that set of classes. See the
* JavaDoc of the ServletContainerInitializer for more information about the
* onStartup method.
* </p>
*
* @author Manfred Riem ([email protected])
*/
public interface HandlesTypesManager {

/**
* Add the annotated class.
*
* @param annotationClass the annotation class.
* @param annotatedClass the annotated class.
*/
void addAnnotatedClass(Class<?> annotationClass, Class<?> annotatedClass);

/**
* Add the extending class.
*
* @param baseClass the based class.
* @param extendingClass the extending class.
*/
void addExtendingClass(Class<?> baseClass, Class<?> extendingClass);

/**
* Add the implementing class.
*
* @param interfaceClass the interface.
* @param implementingClass the implementing class.
*/
void addImplementingClass(Class<?> interfaceClass, Class<?> implementingClass);

/**
* Get the annotated classes.
*
* @param annotationClass the annotation classes.
* @return the annotated classes.
*/
Set<Class<?>> getAnnotatedClasses(Class<?> annotationClass);

/**
* Get the extending classes.
*
* @param baseClass the base class.
* @return the set of extending classes.
*/
Set<Class<?>> getExtendingClasses(Class<?> baseClass);

/**
* Get the implementing classes.
*
* @param interfaceClass the interface class.
* @return the set of implementing classes.
*/
Set<Class<?>> getImplementingClasses(Class<?> interfaceClass);

/**
* Get the set of classes that either are annotated with the given classes,
* implement any of the given classes, or extend any of the given classes.
*
* @param classes the set of given classes.
* @return the set of classes or null if none found.
*/
Set<Class<?>> getClasses(Set<Class<?>> classes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ public interface WebApplicationManager {
*/
DispatcherManager getDispatcherManager();

/**
* Get the HandlesTypes manager.
*
* @return the HandlesTypes manager.
*/
HandlesTypesManager getHandlesTypesManager();

/**
* Get the HTTP session manager.
*
Expand Down Expand Up @@ -153,6 +160,13 @@ public interface WebApplicationManager {
*/
void setErrorPageManager(ErrorPageManager errorPageManager);

/**
* Set the HandlesTypes manager.
*
* @param handlesTypesManager the HandlesTypes manager.
*/
void setHandlesTypesManager(HandlesTypesManager handlesTypesManager);

/**
* Set the HTTP session manager.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
import java.util.stream.Stream;
import cloud.piranha.core.api.WebApplicationManager;
import static java.lang.System.Logger.Level.INFO;
import java.util.Arrays;

/**
* The default WebApplication.
Expand Down Expand Up @@ -505,14 +506,18 @@ public Dynamic addServlet(String servletName, String className) {
DefaultServletEnvironment servletEnvironment = servletEnvironments.get(servletName);
if (servletEnvironment == null) {
servletEnvironment = new DefaultServletEnvironment(this, servletName);
servletEnvironment.setClassName(className);
if (className != null && !className.isBlank()) {
servletEnvironment.setClassName(className);
}
servletEnvironments.put(servletName, servletEnvironment);
} else {
if (!isEmpty(servletEnvironment.getClassName())) {
// Servlet already set, can't override
return null;
}
servletEnvironment.setClassName(className);
if (className != null && !className.isBlank()) {
servletEnvironment.setClassName(className);
}
}
return servletEnvironment;
}
Expand Down Expand Up @@ -984,7 +989,7 @@ public void initializeFilters() {
try {
environment.initialize();
environment.getFilter().init(environment);
} catch (Exception e) {
} catch (Throwable e) {
LOGGER.log(WARNING, () -> "Unable to initialize filter: " + environment.getFilterName(), e);
environment.setStatus(UNAVAILABLE);
}
Expand All @@ -1010,28 +1015,49 @@ public void initializeInitializers() {
try {
HandlesTypes annotation = initializer.getClass().getAnnotation(HandlesTypes.class);
Set<Class<?>> classes = Collections.emptySet();
if (annotation != null && manager.getAnnotationManager() != null) {
if (annotation != null) {
Class<?>[] value = annotation.value();
// Get instances
Stream<Class<?>> instances = manager.getAnnotationManager()
.getInstances(value).stream();

// Get classes by target type
List<AnnotationInfo<?>> annotations = manager.getAnnotationManager()
.getAnnotations(value);
if (manager.getAnnotationManager() != null) {
// Get instances
Stream<Class<?>> instances = manager.getAnnotationManager()
.getInstances(value).stream();

// Get classes by target type
List<AnnotationInfo<?>> annotations = manager.getAnnotationManager()
.getAnnotations(value);

Stream<Class<?>> classStream = annotations.stream().map(AnnotationInfo::getTargetType);
Stream<Class<?>> classStream = annotations.stream().map(AnnotationInfo::getTargetType);

classes = Stream.concat(instances, classStream).collect(Collectors.toSet());
classes.addAll(manager.getAnnotationManager().getAnnotatedClasses(annotation.value()));
classes = Stream.concat(instances, classStream).collect(Collectors.toSet());
classes.addAll(manager.getAnnotationManager().getAnnotatedClasses(annotation.value()));
}

/*
* If we have a HandlesTypes manager we use it to get the
* set of classes we need to pass to the onStartup method.
*/
if (manager.getHandlesTypesManager() != null && value != null) {
Set<Class<?>> handlesTypesClasses
= manager.getHandlesTypesManager().getClasses(
Arrays.stream(value)
.collect(Collectors.toSet()));
if (handlesTypesClasses != null && !handlesTypesClasses.isEmpty()) {
if (classes == null) {
classes = handlesTypesClasses;
} else {
classes.addAll(handlesTypesClasses);
}
}
}
}
try {
source = initializer;
initializer.onStartup(classes, this);
} finally {
source = null;
}
} catch (Exception e) {
} catch (Throwable e) {
LOGGER.log(WARNING, () -> "Initializer " + initializer.getClass().getName() + " failing onStartup", e);
error = true;
}
Expand Down Expand Up @@ -1084,7 +1110,7 @@ private void initializeServlet(DefaultServletEnvironment environment) {
}
environment.getServlet().init(environment);
LOGGER.log(DEBUG, "Initialized servlet: {0}", environment.servletName);
} catch (Exception e) {
} catch (Throwable e) {
LOGGER.log(WARNING, () -> "Unable to initialize servlet: " + environment.className, e);

environment.setStatus(ServletEnvironment.UNAVAILABLE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import cloud.piranha.core.api.AsyncManager;
import cloud.piranha.core.api.DispatcherManager;
import cloud.piranha.core.api.ErrorPageManager;
import cloud.piranha.core.api.HandlesTypesManager;
import cloud.piranha.core.api.HttpSessionManager;
import cloud.piranha.core.api.JspManager;
import cloud.piranha.core.api.LocaleEncodingManager;
Expand All @@ -49,27 +50,32 @@
* @author Manfred Riem ([email protected])
*/
public class DefaultWebApplicationManager implements WebApplicationManager {

/**
* Stores the annotation manager.
*/
protected AnnotationManager annotationManager;

/**
* Stores the async manager.
*/
protected AsyncManager asyncManager = new DefaultAsyncManager();

/**
* Stores the dispatcher manager.
*/
protected DispatcherManager dispatcherManager = new DefaultDispatcherManager();

/**
* Stores the error page manager.
*/
protected ErrorPageManager errorPageManager = new DefaultErrorPageManager();


/**
* Stores the HandlesTypes manager.
*/
protected HandlesTypesManager handlesTypesManager;

/**
* Stores the HTTP session manager.
*/
Expand All @@ -79,22 +85,22 @@ public class DefaultWebApplicationManager implements WebApplicationManager {
* Stores the JSP manager.
*/
protected JspManager jspManager = new DefaultJspManager();

/**
* Stores the locale encoding manager.
*/
protected LocaleEncodingManager localeEncodingManager = new DefaultLocaleEncodingManager();

/**
* Stores the multi-part manager.
*/
protected MultiPartManager multiPartManager = new DefaultMultiPartManager();

/**
* Stores the object instance manager.
*/
protected ObjectInstanceManager objectInstanceManager = new DefaultObjectInstanceManager();

/**
* Stores the resource manager.
*/
Expand All @@ -104,7 +110,7 @@ public class DefaultWebApplicationManager implements WebApplicationManager {
* Stores the security manager.
*/
protected SecurityManager securityManager = new DefaultSecurityManager();

/**
* Stores the servlet request manager.
*/
Expand All @@ -125,11 +131,6 @@ public AsyncManager getAsyncManager() {
return asyncManager;
}

/**
* Get the dispatcher manager.
*
* @return the dispatcher manager.
*/
@Override
public DispatcherManager getDispatcherManager() {
return dispatcherManager;
Expand All @@ -140,6 +141,11 @@ public ErrorPageManager getErrorPageManager() {
return errorPageManager;
}

@Override
public HandlesTypesManager getHandlesTypesManager() {
return handlesTypesManager;
}

@Override
public HttpSessionManager getHttpSessionManager() {
return httpSessionManager;
Expand Down Expand Up @@ -201,8 +207,8 @@ public void setErrorPageManager(ErrorPageManager errorPageManager) {
}

@Override
public void setServletRequestManager(ServletRequestManager servletRequestManager) {
this.servletRequestManager = servletRequestManager;
public void setHandlesTypesManager(HandlesTypesManager handlesTypesManager) {
this.handlesTypesManager = handlesTypesManager;
}

@Override
Expand Down Expand Up @@ -240,6 +246,11 @@ public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
}

@Override
public void setServletRequestManager(ServletRequestManager servletRequestManager) {
this.servletRequestManager = servletRequestManager;
}

@Override
public void setWelcomeFileManager(WelcomeFileManager welcomeFileManager) {
this.welcomeFileManager = welcomeFileManager;
Expand Down
6 changes: 6 additions & 0 deletions extension/coreprofile/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cloud.piranha.extension</groupId>
<artifactId>piranha-extension-handlestypes</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cloud.piranha.extension</groupId>
<artifactId>piranha-extension-herring</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import cloud.piranha.core.api.WebApplicationExtensionContext;
import cloud.piranha.extension.annotationscan.AnnotationScanExtension;
import cloud.piranha.extension.annotationscan.classfile.ClassfileAnnotationScanExtension;
import cloud.piranha.extension.handlestypes.HandlesTypesExtension;
import cloud.piranha.extension.herring.HerringExtension;
import cloud.piranha.extension.scinitializer.ServletContainerInitializerExtension;
import cloud.piranha.extension.webxml.WebXmlExtension;
Expand All @@ -45,6 +46,7 @@ public class CoreProfileExtension implements WebApplicationExtension {

@Override
public void extend(WebApplicationExtensionContext context) {
context.add(HandlesTypesExtension.class); // HandlesTypes support
context.add(HerringExtension.class); // Herring (JNDI)
context.add(WebXmlExtension.class);
context.add(getAnnotationScanExtensionClass());
Expand Down
Loading

0 comments on commit c8aa1d5

Please sign in to comment.