1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.jasper.runtime;
18
19 import java.security.AccessController;
20 import java.security.PrivilegedAction;
21
22 import javax.servlet.Servlet;
23 import javax.servlet.ServletContext;
24 import javax.servlet.ServletRequest;
25 import javax.servlet.ServletResponse;
26 import javax.servlet.jsp.JspApplicationContext;
27 import javax.servlet.jsp.JspEngineInfo;
28 import javax.servlet.jsp.JspFactory;
29 import javax.servlet.jsp.PageContext;
30
31 import org.apache.jasper.Constants;
32 import org.apache.juli.logging.Log;
33 import org.apache.juli.logging.LogFactory;
34
35 /**
36 * Implementation of JspFactory.
37 *
38 * @author Anil K. Vijendran
39 */
40 public class JspFactoryImpl extends JspFactory {
41
42 // Logger
43 private Log log = LogFactory.getLog(JspFactoryImpl.class);
44
45 private static final String SPEC_VERSION = "2.1";
46 private static final boolean USE_POOL =
47 Boolean.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.USE_POOL", "true")).booleanValue();
48 private static final int POOL_SIZE =
49 Integer.valueOf(System.getProperty("org.apache.jasper.runtime.JspFactoryImpl.POOL_SIZE", "8")).intValue();
50
51 private ThreadLocal<PageContextPool> localPool = new ThreadLocal<PageContextPool>();
52
53 public PageContext getPageContext(Servlet servlet, ServletRequest request,
54 ServletResponse response, String errorPageURL, boolean needsSession,
55 int bufferSize, boolean autoflush) {
56
57 if( Constants.IS_SECURITY_ENABLED ) {
58 PrivilegedGetPageContext dp = new PrivilegedGetPageContext(
59 (JspFactoryImpl)this, servlet, request, response, errorPageURL,
60 needsSession, bufferSize, autoflush);
61 return (PageContext)AccessController.doPrivileged(dp);
62 } else {
63 return internalGetPageContext(servlet, request, response,
64 errorPageURL, needsSession,
65 bufferSize, autoflush);
66 }
67 }
68
69 public void releasePageContext(PageContext pc) {
70 if( pc == null )
71 return;
72 if( Constants.IS_SECURITY_ENABLED ) {
73 PrivilegedReleasePageContext dp = new PrivilegedReleasePageContext(
74 (JspFactoryImpl)this,pc);
75 AccessController.doPrivileged(dp);
76 } else {
77 internalReleasePageContext(pc);
78 }
79 }
80
81 public JspEngineInfo getEngineInfo() {
82 return new JspEngineInfo() {
83 public String getSpecificationVersion() {
84 return SPEC_VERSION;
85 }
86 };
87 }
88
89 private PageContext internalGetPageContext(Servlet servlet, ServletRequest request,
90 ServletResponse response, String errorPageURL, boolean needsSession,
91 int bufferSize, boolean autoflush) {
92 try {
93 PageContext pc;
94 if (USE_POOL) {
95 PageContextPool pool = localPool.get();
96 if (pool == null) {
97 pool = new PageContextPool();
98 localPool.set(pool);
99 }
100 pc = pool.get();
101 if (pc == null) {
102 pc = new PageContextImpl();
103 }
104 } else {
105 pc = new PageContextImpl();
106 }
107 pc.initialize(servlet, request, response, errorPageURL,
108 needsSession, bufferSize, autoflush);
109 return pc;
110 } catch (Throwable ex) {
111 /* FIXME: need to do something reasonable here!! */
112 log.fatal("Exception initializing page context", ex);
113 return null;
114 }
115 }
116
117 private void internalReleasePageContext(PageContext pc) {
118 pc.release();
119 if (USE_POOL && (pc instanceof PageContextImpl)) {
120 localPool.get().put(pc);
121 }
122 }
123
124 private class PrivilegedGetPageContext implements PrivilegedAction {
125
126 private JspFactoryImpl factory;
127 private Servlet servlet;
128 private ServletRequest request;
129 private ServletResponse response;
130 private String errorPageURL;
131 private boolean needsSession;
132 private int bufferSize;
133 private boolean autoflush;
134
135 PrivilegedGetPageContext(JspFactoryImpl factory, Servlet servlet,
136 ServletRequest request, ServletResponse response, String errorPageURL,
137 boolean needsSession, int bufferSize, boolean autoflush) {
138 this.factory = factory;
139 this.servlet = servlet;
140 this.request = request;
141 this.response = response;
142 this.errorPageURL = errorPageURL;
143 this.needsSession = needsSession;
144 this.bufferSize = bufferSize;
145 this.autoflush = autoflush;
146 }
147
148 public Object run() {
149 return factory.internalGetPageContext(servlet, request, response,
150 errorPageURL, needsSession, bufferSize, autoflush);
151 }
152 }
153
154 private class PrivilegedReleasePageContext implements PrivilegedAction {
155
156 private JspFactoryImpl factory;
157 private PageContext pageContext;
158
159 PrivilegedReleasePageContext(JspFactoryImpl factory,
160 PageContext pageContext) {
161 this.factory = factory;
162 this.pageContext = pageContext;
163 }
164
165 public Object run() {
166 factory.internalReleasePageContext(pageContext);
167 return null;
168 }
169 }
170
171 protected final class PageContextPool {
172
173 private PageContext[] pool;
174
175 private int current = -1;
176
177 public PageContextPool() {
178 this.pool = new PageContext[POOL_SIZE];
179 }
180
181 public void put(PageContext o) {
182 if (current < (POOL_SIZE - 1)) {
183 current++;
184 pool[current] = o;
185 }
186 }
187
188 public PageContext get() {
189 PageContext item = null;
190 if (current >= 0) {
191 item = pool[current];
192 current--;
193 }
194 return item;
195 }
196
197 }
198
199 public JspApplicationContext getJspApplicationContext(ServletContext context) {
200 return JspApplicationContextImpl.getInstance(context);
201 }
202 }