1 /*
2  * JBoss, Home of Professional Open Source.
3  * Copyright 2014 Red Hat, Inc., and individual contributors
4  * as indicated by the @author tags.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */

18
19 package io.undertow.servlet.handlers;
20
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.Executor;
24
25 import io.undertow.server.HttpHandler;
26 import io.undertow.server.HttpServerExchange;
27 import io.undertow.servlet.core.ManagedFilter;
28 import io.undertow.servlet.core.ManagedServlet;
29
30 import javax.servlet.DispatcherType;
31 import javax.servlet.ServletException;
32 import javax.servlet.http.MappingMatch;
33
34 /**
35 * @author Stuart Douglas
36 */

37 public class ServletChain {
38     private final HttpHandler handler;
39     private final ManagedServlet managedServlet;
40     private final String servletPath;
41     private final Executor executor;
42     private final boolean defaultServletMapping;
43     private final MappingMatch mappingMatch;
44     private final String pattern;
45     private final Map<DispatcherType, List<ManagedFilter>> filters;
46
47     public ServletChain(final HttpHandler handler, final ManagedServlet managedServlet, final String servletPath, boolean defaultServletMapping, MappingMatch mappingMatch, String pattern, Map<DispatcherType, List<ManagedFilter>> filters) {
48         this(handler, managedServlet, servletPath, defaultServletMapping, mappingMatch, pattern, filters, true);
49     }
50
51     private ServletChain(final HttpHandler originalHandler, final ManagedServlet managedServlet, final String servletPath, boolean defaultServletMapping, MappingMatch mappingMatch, String pattern, Map<DispatcherType, List<ManagedFilter>> filters, boolean wrapHandler) {
52         if (wrapHandler) {
53             this.handler = new HttpHandler() {
54
55                 private volatile boolean initDone = false;
56
57                 @Override
58                 public void handleRequest(HttpServerExchange exchange) throws Exception {
59                     if(!initDone) {
60                         synchronized (this) {
61                             if(!initDone) {
62                                 ServletRequestContext src = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
63                                 forceInit(src.getDispatcherType());
64                                 initDone = true;
65                             }
66                         }
67                     }
68                     originalHandler.handleRequest(exchange);
69                 }
70             };
71         } else {
72             this.handler = originalHandler;
73         }
74         this.managedServlet = managedServlet;
75         this.servletPath = servletPath;
76         this.defaultServletMapping = defaultServletMapping;
77         this.mappingMatch = mappingMatch;
78         this.pattern = pattern;
79         this.executor = managedServlet.getServletInfo().getExecutor();
80         this.filters = filters;
81     }
82
83     public ServletChain(final ServletChain other, String pattern, MappingMatch mappingMatch) {
84         this(other.getHandler(), other.getManagedServlet(), other.getServletPath(), other.isDefaultServletMapping(), mappingMatch, pattern, other.filters, false);
85     }
86
87     public HttpHandler getHandler() {
88         return handler;
89     }
90
91     public ManagedServlet getManagedServlet() {
92         return managedServlet;
93     }
94
95     /**
96      *
97      * @return The servlet path part
98      */

99     public String getServletPath() {
100         return servletPath;
101     }
102
103     public Executor getExecutor() {
104         return executor;
105     }
106
107     public boolean isDefaultServletMapping() {
108         return defaultServletMapping;
109     }
110
111     public MappingMatch getMappingMatch() {
112         return mappingMatch;
113     }
114
115     public String getPattern() {
116         return pattern;
117     }
118
119     //see UNDERTOW-1132
120     void forceInit(DispatcherType dispatcherType) throws ServletException {
121         if(filters != null) {
122             List<ManagedFilter> list = filters.get(dispatcherType);
123             if(list != null && !list.isEmpty()) {
124                 for(int i = 0; i < list.size(); ++i) {
125                     ManagedFilter filter = list.get(i);
126                     filter.forceInit();
127                 }
128             }
129         }
130         managedServlet.forceInit();
131     }
132 }
133