/*
 *
 *  * Copyright 2013 the original author or authors.
 *  *
 *  * 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 leap.oauth2.server.endpoint.token;

import leap.core.BeanFactory;
import leap.core.annotation.Inject;
import leap.lang.Out;
import leap.lang.intercepting.State;
import leap.lang.logging.Log;
import leap.lang.logging.LogFactory;
import leap.oauth2.server.OAuth2Params;
import leap.oauth2.server.token.AuthzAccessToken;
import leap.web.Request;
import leap.web.Response;

/**
 * @author kael.
 */
public class DefaultGrantTokenManager implements GrantTokenManager {
    private static final Log log = LogFactory.get(DefaultGrantTokenManager.class);
    
    protected @Inject BeanFactory factory;
    protected @Inject GrantTokenInterceptor[] interceptors;
    
    @Override
    public GrantTypeHandler getHandler(String grantType) {
        return factory.tryGetBean(GrantTypeHandler.class, grantType);
    }

    @Override
    public AuthzAccessToken grantAccessToken(Request request, Response response, OAuth2Params params, GrantTypeHandler handler) throws Throwable {
        Out<AuthzAccessToken> out = new Out<>();
        try {
            out.set(grantToken(request, response, params, handler));
        }finally {
            for(GrantTokenInterceptor interceptor : interceptors) {
                try {
                    interceptor.grantTypeHandleComplete(request,response,params,handler,out);
                }catch (Exception e){
                    log.warn("complete grant type handle fail for class {}, error message: ",interceptor.getClass().getName(),e);
                    log.warn(e);
                }
            }
        }
        return out.get();
    }

    protected AuthzAccessToken grantToken(Request request, Response response, OAuth2Params params, GrantTypeHandler handler) throws Throwable{
        Out<AuthzAccessToken> out = new Out<>();
        for(GrantTokenInterceptor interceptor:interceptors){
            if(State.isIntercepted(interceptor.beforeGrantTypeHandle(request,response,params,handler,out))){
                return out.get();
            }
        }
        handler.handleRequest(request,response,params,accessToken -> out.set(accessToken));
        for(GrantTokenInterceptor interceptor:interceptors){
            if(State.isIntercepted(interceptor.afterGrantTypeHandle(request,response,params,handler,out))){
                return out.get();
            }
        }
        return out.get();
    }

}

@@ -885,32 +885,65 @@
 ing.LogFactory;%0A
+import leap.lang.time.StopWatch;%0A
 import leap.oaut
@@ -1816,24 +1816,73 @@
  %7Dfinally %7B%0A
+            StopWatch sw = StopWatch.startNew();%0A
             
@@ -1951,32 +1951,96 @@
           try %7B%0A
+                    sw.reset();%0A                    sw.start();%0A
                 
@@ -2314,24 +2314,225 @@
 og.warn(e);%0A
+                %7Dfinally %7B%0A                    sw.stop();%0A                    log.debug(%22interceptor %7B%7D execute grantTypeHandleComplete use %7B%7Dms%22, interceptor.getClass(), sw.getElapsedMilliseconds());%0A
             
@@ -2778,32 +2778,77 @@
  = new Out%3C%3E();%0A
+        StopWatch sw = StopWatch.startNew();%0A
         for(Gran
@@ -2884,32 +2884,110 @@
 :interceptors)%7B%0A
+            try %7B%0A                sw.reset();%0A                sw.start();%0A    
             if(S
@@ -3087,32 +3087,36 @@
                 
+    
 return out.get()
@@ -3133,173 +3133,666 @@
     
-%7D%0A        %7D%0A        handler.handleRequest(request,response,params,accessToken -%3E out.set(accessToken));%0A        for(GrantTokenInterceptor interceptor:interceptors)%7B%0A
+    %7D%0A            %7D finally %7B%0A                sw.stop();%0A                log.debug(%22interceptor %7B%7D execute beforeGrantTypeHandle use %7B%7Dms%22, interceptor.getClass(), sw.getElapsedMilliseconds());%0A            %7D%0A        %7D%0A        try %7B%0A            sw.reset();%0A            sw.start();%0A            handler.handleRequest(request,response,params, out::set);%0A        %7Dfinally %7B%0A            sw.stop();%0A            log.debug(%22handler %7B%7D execute handleRequest use %7B%7Dms%22, handler.getClass(), sw.getElapsedMilliseconds());%0A        %7D%0A        for(GrantTokenInterceptor interceptor:interceptors)%7B%0A            try %7B%0A                sw.reset();%0A                sw.start();%0A    
     
@@ -3903,32 +3903,36 @@
                 
+    
 return out.get()
@@ -3937,33 +3937,239 @@
 ();%0A            
+   
-%7D
+ %7D%0A            %7D finally %7B%0A                sw.stop();%0A                log.debug(%22interceptor %7B%7D execute afterGrantTypeHandle use %7B%7Dms%22, interceptor.getClass(), sw.getElapsedMilliseconds());%0A            %7D%0A
 %0A        %7D%0A     

add execute time watcher