SubscriptionFilter.java

  1. package de.dlr.shepard.filters;

  2. import java.util.List;
  3. import java.util.concurrent.Executor;
  4. import java.util.concurrent.Executors;
  5. import java.util.regex.Pattern;

  6. import de.dlr.shepard.neo4Core.entities.Subscription;
  7. import de.dlr.shepard.neo4Core.io.EventIO;
  8. import de.dlr.shepard.neo4Core.io.HasIdIO;
  9. import de.dlr.shepard.neo4Core.io.SubscriptionIO;
  10. import de.dlr.shepard.neo4Core.services.SubscriptionService;
  11. import de.dlr.shepard.security.PermissionsUtil;
  12. import de.dlr.shepard.util.AccessType;
  13. import de.dlr.shepard.util.HasId;
  14. import de.dlr.shepard.util.RequestMethod;
  15. import jakarta.ws.rs.ProcessingException;
  16. import jakarta.ws.rs.client.ClientBuilder;
  17. import jakarta.ws.rs.client.Entity;
  18. import jakarta.ws.rs.container.ContainerRequestContext;
  19. import jakarta.ws.rs.container.ContainerResponseContext;
  20. import jakarta.ws.rs.container.ContainerResponseFilter;
  21. import jakarta.ws.rs.core.MediaType;
  22. import jakarta.ws.rs.ext.Provider;
  23. import lombok.extern.slf4j.Slf4j;

  24. @Subscribable
  25. @Provider
  26. @Slf4j
  27. public class SubscriptionFilter implements ContainerResponseFilter {

  28.     private Executor executor;

  29.     /**
  30.      * Default constructor
  31.      */
  32.     public SubscriptionFilter() {
  33.         this.executor = Executors.newCachedThreadPool();
  34.     }

  35.     /**
  36.      * Constructor to inject your own executor service
  37.      *
  38.      * @param executor Your own Executor Service
  39.      */
  40.     public SubscriptionFilter(Executor executor) {
  41.         this.executor = executor;
  42.     }

  43.     @Override
  44.     public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
  45.         SubscriptionService subscriptionService = getService();

  46.         // request not successful
  47.         var status = responseContext.getStatus();
  48.         if (!(status >= 200 && status < 300)) {
  49.             log.debug("Skip subscriptions since the http statuscode is not between 200 and 299");
  50.             return;
  51.         }

  52.         // request successful
  53.         EventIO event = new EventIO(requestContext.getUriInfo().getAbsolutePath().toString(),
  54.                 RequestMethod.valueOf(requestContext.getMethod()));

  55.         Object entity = responseContext.getEntity();
  56.         if (entity instanceof HasId hasId) {
  57.             event.setSubscribedObject(new HasIdIO(hasId));
  58.         }

  59.         var permissionsUtil = getPermissionsUtil();
  60.         List<Subscription> subs = subscriptionService.getMatchingSubscriptions(event.getRequestMethod());
  61.         for (Subscription sub : subs) {
  62.             // TODO: This could develop into a bottleneck
  63.             Pattern pattern = Pattern.compile(sub.getSubscribedURL());
  64.             if (pattern.matcher(event.getUrl()).matches() && permissionsUtil.isAllowed(
  65.                     requestContext.getUriInfo().getPathSegments(), AccessType.Read, sub.getCreatedBy().getUsername())) {
  66.                 EventIO e = new EventIO(event);
  67.                 e.setSubscription(new SubscriptionIO(sub));
  68.                 log.debug("{} was triggered with {}", sub, e);
  69.                 executor.execute(() -> sendCallback(sub, e));
  70.             }
  71.         }
  72.     }

  73.     private void sendCallback(Subscription sub, EventIO event) {
  74.         var client = ClientBuilder.newClient();
  75.         var webTarget = client.target(sub.getCallbackURL());

  76.         try {
  77.             var entity = Entity.entity(event, MediaType.APPLICATION_JSON);
  78.             var response = webTarget.request().buildPost(entity).invoke();
  79.             log.info("Notification has been send to {} with response code: {}", sub.getCallbackURL(),
  80.                     response.getStatus());
  81.         } catch (ProcessingException e) {
  82.             log.error("Could not execute notification request");
  83.         } finally {
  84.             client.close();
  85.         }
  86.     }

  87.     protected SubscriptionService getService() {
  88.         return new SubscriptionService();
  89.     }

  90.     protected PermissionsUtil getPermissionsUtil() {
  91.         return new PermissionsUtil();
  92.     }

  93. }