001/* 002 * Copyright 2022-2025 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet; 018 019import javax.annotation.Nonnull; 020import java.lang.reflect.Method; 021import java.util.Optional; 022import java.util.Set; 023 024import static java.util.Objects.requireNonNull; 025 026/** 027 * Contract for matching incoming HTTP requests with appropriate <em>Resource Methods</em> (Java methods to invoke to handle requests). 028 * <p> 029 * A <em>Resource Method</em> is a Java {@link Method} with an HTTP method annotation applied, e.g. {@link com.soklet.annotation.GET}, {@link com.soklet.annotation.POST}, {@link com.soklet.annotation.ServerSentEventSource}, ... 030 * <p> 031 * Standard threadsafe implementations can be acquired via these factory methods: 032 * <ul> 033 * <li>{@link #fromClasspathIntrospection()} (examines an annotation-processor-generated lookup table of Java {@link Method} declarations with corresponding HTTP method annotations)</li> 034 * <li>{@link #withClasses(Set)} (examines methods within the hardcoded set of classes)</li> 035 * <li>{@link #withMethods(Set)} (examines the hardcoded set of methods)</li> 036 * </ul> 037 * <p> 038 * It is likely that one or more of the above implementations is sufficient for your application and test suite. 039 * <p> 040 * However, should a custom implementation be necessary, documentation is available at <a href="https://www.soklet.com/docs/request-handling#resource-method-resolution">https://www.soklet.com/docs/request-handling#resource-method-resolution</a>. 041 * 042 * @author <a href="https://www.revetkn.com">Mark Allen</a> 043 */ 044public interface ResourceMethodResolver { 045 /** 046 * Given an HTTP request, provide a matching <em>Resource Method</em> to invoke. 047 * <p> 048 * An unmatched <em>Resource Method</em> generally indicates an {@code HTTP 404}. 049 * 050 * @param request the HTTP request 051 * @param serverType the type of server that's handling the request 052 * @return the matching <em>Resource Method</em>, or {@link Optional#empty()} if no match was found 053 */ 054 @Nonnull 055 Optional<ResourceMethod> resourceMethodForRequest(@Nonnull Request request, 056 @Nonnull ServerType serverType); 057 058 /** 059 * Vends the set of all <em>Resource Methods</em> registered in the system. 060 * 061 * @return the set of all <em>Resource Methods</em> in the system 062 */ 063 @Nonnull 064 Set<ResourceMethod> getResourceMethods(); 065 066 /** 067 * Acquires a threadsafe {@link ResourceMethodResolver} implementation which locates <em>Resource Methods</em> by examining a lookup table of Java {@link Method} declarations that are annotated with {@link com.soklet.annotation.GET}, {@link com.soklet.annotation.POST}, {@link com.soklet.annotation.ServerSentEventSource}, etc. 068 * <p> 069 * This implementation requires that your application be compiled with the {@link SokletProcessor} annotation processor, as shown below: 070 * <p> 071 * <pre>javac -parameters -processor com.soklet.SokletProcessor ...[rest of javac command elided]</pre> 072 * <p> 073 * The returned instance is guaranteed to be a JVM-wide singleton. 074 * 075 * @return a {@code ResourceMethodResolver} which performs classpath introspection against the annotation processor's lookup table 076 */ 077 @Nonnull 078 static ResourceMethodResolver fromClasspathIntrospection() { 079 return DefaultResourceMethodResolver.fromClasspathIntrospection(); 080 } 081 082 /** 083 * Acquires a threadsafe {@link ResourceMethodResolver} implementation which locates <em>Resource Methods</em> by examining the provided {@code classes}. 084 * <p> 085 * This method is guaranteed to return a new instance. 086 * 087 * @param classes the classes to inspect for <em>Resource Methods</em> 088 * @return a {@code ResourceMethodResolver} backed by the given {@code classes} 089 */ 090 @Nonnull 091 static ResourceMethodResolver withClasses(@Nonnull Set<Class<?>> classes) { 092 requireNonNull(classes); 093 return DefaultResourceMethodResolver.withClasses(classes); 094 } 095 096 /** 097 * Acquires a threadsafe {@link ResourceMethodResolver} implementation which locates <em>Resource Methods</em> by examining the provided {@code methods}. 098 * <p> 099 * This method is guaranteed to return a new instance. 100 * 101 * @param methods the methods to inspect for <em>Resource Method</em> annotations 102 * @return a {@code ResourceMethodResolver} backed by the given {@code methods} 103 */ 104 @Nonnull 105 static ResourceMethodResolver withMethods(@Nonnull Set<Method> methods) { 106 requireNonNull(methods); 107 return DefaultResourceMethodResolver.withMethods(methods); 108 } 109}