/*
 * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
 *
 * Copyright (c) 2017, Gluu
 */
package org.gluu.oxtrust.service.filter;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;

import org.gluu.oxtrust.auth.uma.BaseUmaProtectionService;
import org.gluu.oxtrust.auth.uma.BindingUrls;
import org.jboss.weld.inject.WeldInstance;
import org.slf4j.Logger;

/**
 * A RestEasy filter to centralize protection of APIs with UMA based on path
 * pattern. Created by jgomer on 2017-11-25.
 * 
 * @author Yuriy Movchan Date: 02/14/2017
 */
// To protect methods with this filter just add the @ProtectedApi annotation to
// them and ensure there is a proper subclass
// of {@link BaseUmaProtectionService} that can handle specific protection logic
// for your particular case
@Provider
@ProtectedApi
public class AuthorizationProcessingFilter implements ContainerRequestFilter {

	@Inject
	private Logger log;

	@Context
	private HttpHeaders httpHeaders;

	@Context
	private ResourceInfo resourceInfo;

	@Inject
	private WeldInstance<BaseUmaProtectionService> protectionServiceInstance;

	private Map<String, Class<BaseUmaProtectionService>> protectionMapping;

	/**
	 * This method performs the protection check of service invocations: it provokes
	 * returning an early error response if the underlying protection logic does not
	 * succeed, otherwise, makes the request flow to its destination service object
	 * 
	 * @param requestContext
	 *            The ContainerRequestContext associated to filter execution
	 * @throws IOException
	 *             In practice no exception is thrown here. It's present to conform
	 *             to interface implemented.
	 */
	@Override
	public void filter(ContainerRequestContext requestContext) throws IOException {
		String path = requestContext.getUriInfo().getPath();
		log.info("REST call to '{}' intercepted", path);
		BaseUmaProtectionService protectionService = null;
		for (String prefix : protectionMapping.keySet()) {
			if (path.startsWith(prefix)) {
				protectionService = protectionServiceInstance.select(protectionMapping.get(prefix)).get();
				break;
			}
		}
		if (protectionService == null) {
			log.warn(
					"No concrete UMA protection mechanism is associated to this path (resource will be accessed anonymously)");
		} else {
			log.info("Path is protected, proceeding with authorization processing...");
			Response authorizationResponse = protectionService.processAuthorization(httpHeaders, resourceInfo);
			if (authorizationResponse == null)
				log.info("Authorization passed"); // If authorization passed, proceed with actual processing of request
			else
				requestContext.abortWith(authorizationResponse);
		}

	}

	/**
	 * Builds a map around url patterns and service beans that are aimed to perform
	 * actual protection
	 */
	@SuppressWarnings("unchecked")
	@PostConstruct
	private void init() {
		protectionMapping = new HashMap<String, Class<BaseUmaProtectionService>>();
		for (WeldInstance.Handler<BaseUmaProtectionService> handler : protectionServiceInstance.handlers()) {
			Class<BaseUmaProtectionService> beanClass = (Class<BaseUmaProtectionService>) handler.getBean()
					.getBeanClass();
			BindingUrls annotation = beanClass.getAnnotation(BindingUrls.class);
			if (annotation != null) {
				for (String pattern : annotation.value()) {
					if (pattern.length() > 0) {
						protectionMapping.put(pattern, beanClass);
					}
				}
			}
		}
	}

}

@@ -314,21 +314,133 @@
 vax.
-inject.Inject
+annotation.Priority;%0Aimport javax.enterprise.context.RequestScoped;%0Aimport javax.inject.Inject;%0Aimport javax.ws.rs.Priorities
 ;%0Aim
@@ -1334,16 +1334,68 @@
 ctedApi%0A
+@Priority(Priorities.AUTHENTICATION)%0A@RequestScoped%0A
 public c
@@ -2423,39 +2423,78 @@
 EST 
-call to '%7B%7D' intercepted%22, path
+CALL ON '%7B%7D' INTERCEPTED%22, requestContext.getUriInfo().getRequestUri()
 );%0A%09
@@ -2908,16 +2908,17 @@
 sly)%22);%0A
+%0A
 %09%09%7D else
@@ -3102,16 +3102,16 @@
 eInfo);%0A
-
 %09%09%09if (a
@@ -3140,16 +3140,49 @@
 = null)%0A
+%09%09if (protectionService == null)%0A
 %09%09%09%09log.

Add scope information