/*
 * Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
 * and other contributors as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.hawkular.inventory.rest.interceptors;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.ext.Provider;

import org.hawkular.inventory.api.EntityAlreadyExistsException;
import org.hawkular.inventory.api.Inventory;
import org.hawkular.inventory.api.model.Tenant;
import org.hawkular.inventory.rest.RestApiLogger;
import org.hawkular.inventory.rest.cdi.AutoTenant;
import org.hawkular.inventory.rest.security.Security;
import org.hawkular.inventory.rest.security.TenantId;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.interception.ServerInterceptor;

/**
 * A {@link ContainerRequestFilter} that auto-creates a new tenant based on the {@code tenantId} provided by the current
 * {@link Security} SPI. {@link AutocreateTenantRequestFilter} uses a simple local cache of {@code tenantId}s so that
 * the existence of the given {@code tenantId} does not need to be checked on every request.
 *
 * @author <a href="https://github.com/ppalaga">Peter Palaga</a>
 */
@Provider
@ServerInterceptor
public class AutocreateTenantRequestFilter implements ContainerRequestFilter {

    private static final RestApiLogger log =
            Logger.getMessageLogger(RestApiLogger.class, AutocreateTenantRequestFilter.class.getName());

    private final Set<String> existingTenantIds = ConcurrentHashMap.newKeySet();

    @Inject
    @TenantId
    private String tenantId;

    @Inject
    @AutoTenant
    private Inventory inventory;

    /**
     * @see javax.ws.rs.container.ContainerRequestFilter#filter(javax.ws.rs.container.ContainerRequestContext)
     */
    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {
        log.tracef("Checking if tenant [%s] needs to be auto-created", tenantId);
        /* do nothing if tenantId is unknown */
        if (tenantId != null) {
            if (!existingTenantIds.contains(tenantId)) {
                log.tracef("Tenant [%s] needs to be created", tenantId);
                try {
                    inventory.tenants().create(Tenant.Blueprint.builder().withId(tenantId).build());
                    log.tracef("Tenant [%s] auto-created sucessfully", tenantId);
                    existingTenantIds.add(tenantId);
                } catch (EntityAlreadyExistsException e) {
                    /* Probably created by another thread or during a previous run of the server */
                    log.tracef("Tenant [%s] could not be auto-created because it existed in the backedn already",
                            tenantId);
                    existingTenantIds.add(tenantId);
                }
            } else {
                log.tracef("Tenant [%s] exists already", tenantId);
            }
        }
    }

}

@@ -751,24 +751,47 @@
 OException;%0A
+import java.util.List;%0A
 import java.
@@ -847,16 +847,157 @@
 ashMap;%0A
+import java.util.regex.Pattern;%0Aimport java.util.stream.Collectors;%0Aimport java.util.stream.Stream;%0A%0Aimport javax.enterprise.inject.Instance;
 %0Aimport 
@@ -2145,16 +2145,283 @@
 lter %7B%0A%0A
+    /* URI chunks to which this filter should not be applied */%0A    private static final List%3CPattern%3E uriExceptionPatterns = Stream.of(%22.*/inventory/status/?%22,%0A            %22.*/inventory/ping/?%22, %22.*/inventory/?%22).map(Pattern::compile).collect(Collectors.toList());%0A%0A
     priv
@@ -2683,22 +2683,32 @@
 private 
+Instance%3C
 String
+%3E
  tenantI
@@ -2708,16 +2708,24 @@
 tenantId
+Producer
 ;%0A%0A    @
@@ -3006,16 +3006,219 @@
 ption %7B%0A
+        boolean shouldSkip = shouldSkip(requestContext.getUriInfo().getRequestUri().getPath());%0A        if (shouldSkip) %7B%0A            return;%0A        %7D%0A%0A        String tenantId = tenantIdProducer.get();%0A
         
@@ -3684,16 +3684,17 @@
 ated suc
+c
 essfully
@@ -4024,10 +4024,10 @@
 acke
-d
 n
+d
  alr
@@ -4263,10 +4263,150 @@
 %0A    %7D%0A%0A
+    private boolean shouldSkip(String uri) %7B%0A        return uriExceptionPatterns.stream().anyMatch((p -%3E p.matcher(uri).matches()));%0A    %7D%0A%0A
 %7D%0A

Allow to make URI exceptions from the AutocreateTenantRequestFilter so that request to /status will not create the tenant. Currently the filter may fail when the tenant header is not there although it should work for unsecured whitelisted endpoints.