View Javadoc

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  
18  package org.apache.struts2.jasper.runtime;
19  
20  import org.apache.struts2.jasper.Constants;
21  
22  import javax.servlet.ServletConfig;
23  import javax.servlet.jsp.JspException;
24  import javax.servlet.jsp.tagext.Tag;
25  import java.util.Enumeration;
26  import java.util.Vector;
27  
28  /***
29   * Thread-local based pool of tag handlers that can be reused.
30   *
31   * @author Jan Luehe
32   * @author Costin Manolache
33   */
34  public class PerThreadTagHandlerPool extends TagHandlerPool {
35  
36      private int maxSize;
37  
38      // For cleanup
39      private Vector perThreadDataVector;
40  
41      private ThreadLocal perThread;
42  
43      private static class PerThreadData {
44          Tag handlers[];
45          int current;
46      }
47  
48      /***
49       * Constructs a tag handler pool with the default capacity.
50       */
51      public PerThreadTagHandlerPool() {
52          super();
53          perThreadDataVector = new Vector();
54      }
55  
56      protected void init(ServletConfig config) {
57          maxSize = Constants.MAX_POOL_SIZE;
58          String maxSizeS = getOption(config, OPTION_MAXSIZE, null);
59          if (maxSizeS != null) {
60              maxSize = Integer.parseInt(maxSizeS);
61              if (maxSize < 0) {
62                  maxSize = Constants.MAX_POOL_SIZE;
63              }
64          }
65  
66          perThread = new ThreadLocal() {
67              protected Object initialValue() {
68                  PerThreadData ptd = new PerThreadData();
69                  ptd.handlers = new Tag[maxSize];
70                  ptd.current = -1;
71                  perThreadDataVector.addElement(ptd);
72                  return ptd;
73              }
74          };
75      }
76  
77      /***
78       * Gets the next available tag handler from this tag handler pool,
79       * instantiating one if this tag handler pool is empty.
80       *
81       * @param handlerClass Tag handler class
82       * @return Reused or newly instantiated tag handler
83       * @throws JspException if a tag handler cannot be instantiated
84       */
85      public Tag get(Class handlerClass) throws JspException {
86          PerThreadData ptd = (PerThreadData) perThread.get();
87          if (ptd.current >= 0) {
88              return ptd.handlers[ptd.current--];
89          } else {
90              try {
91                  return (Tag) handlerClass.newInstance();
92              } catch (Exception e) {
93                  throw new JspException(e.getMessage(), e);
94              }
95          }
96      }
97  
98      /***
99       * Adds the given tag handler to this tag handler pool, unless this tag
100      * handler pool has already reached its capacity, in which case the tag
101      * handler's release() method is called.
102      *
103      * @param handler Tag handler to add to this tag handler pool
104      */
105     public void reuse(Tag handler) {
106         PerThreadData ptd = (PerThreadData) perThread.get();
107         if (ptd.current < (ptd.handlers.length - 1)) {
108             ptd.handlers[++ptd.current] = handler;
109         } else {
110             handler.release();
111         }
112     }
113 
114     /***
115      * Calls the release() method of all tag handlers in this tag handler pool.
116      */
117     public void release() {
118         Enumeration enumeration = perThreadDataVector.elements();
119         while (enumeration.hasMoreElements()) {
120             PerThreadData ptd = (PerThreadData) enumeration.nextElement();
121             if (ptd.handlers != null) {
122                 for (int i = ptd.current; i >= 0; i--) {
123                     if (ptd.handlers[i] != null) {
124                         ptd.handlers[i].release();
125                     }
126                 }
127             }
128         }
129     }
130 }
131