001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.jasper.runtime;
019:
020: import javax.servlet.ServletConfig;
021: import javax.servlet.jsp.JspException;
022: import javax.servlet.jsp.tagext.Tag;
023:
024: import org.apache.AnnotationProcessor;
025: import org.apache.jasper.Constants;
026: import org.apache.juli.logging.Log;
027: import org.apache.juli.logging.LogFactory;
028:
029: /**
030: * Pool of tag handlers that can be reused.
031: *
032: * @author Jan Luehe
033: */
034: public class TagHandlerPool {
035:
036: private Tag[] handlers;
037:
038: public static String OPTION_TAGPOOL = "tagpoolClassName";
039: public static String OPTION_MAXSIZE = "tagpoolMaxSize";
040:
041: private Log log = LogFactory.getLog(TagHandlerPool.class);
042:
043: // index of next available tag handler
044: private int current;
045: protected AnnotationProcessor annotationProcessor = null;
046:
047: public static TagHandlerPool getTagHandlerPool(ServletConfig config) {
048: TagHandlerPool result = null;
049:
050: String tpClassName = getOption(config, OPTION_TAGPOOL, null);
051: if (tpClassName != null) {
052: try {
053: Class c = Class.forName(tpClassName);
054: result = (TagHandlerPool) c.newInstance();
055: } catch (Exception e) {
056: e.printStackTrace();
057: result = null;
058: }
059: }
060: if (result == null)
061: result = new TagHandlerPool();
062: result.init(config);
063:
064: return result;
065: }
066:
067: protected void init(ServletConfig config) {
068: int maxSize = -1;
069: String maxSizeS = getOption(config, OPTION_MAXSIZE, null);
070: if (maxSizeS != null) {
071: try {
072: maxSize = Integer.parseInt(maxSizeS);
073: } catch (Exception ex) {
074: maxSize = -1;
075: }
076: }
077: if (maxSize < 0) {
078: maxSize = Constants.MAX_POOL_SIZE;
079: }
080: this .handlers = new Tag[maxSize];
081: this .current = -1;
082: this .annotationProcessor = (AnnotationProcessor) config
083: .getServletContext().getAttribute(
084: AnnotationProcessor.class.getName());
085: }
086:
087: /**
088: * Constructs a tag handler pool with the default capacity.
089: */
090: public TagHandlerPool() {
091: // Nothing - jasper generated servlets call the other constructor,
092: // this should be used in future + init .
093: }
094:
095: /**
096: * Constructs a tag handler pool with the given capacity.
097: *
098: * @param capacity Tag handler pool capacity
099: * @deprecated Use static getTagHandlerPool
100: */
101: public TagHandlerPool(int capacity) {
102: this .handlers = new Tag[capacity];
103: this .current = -1;
104: }
105:
106: /**
107: * Gets the next available tag handler from this tag handler pool,
108: * instantiating one if this tag handler pool is empty.
109: *
110: * @param handlerClass Tag handler class
111: *
112: * @return Reused or newly instantiated tag handler
113: *
114: * @throws JspException if a tag handler cannot be instantiated
115: */
116: public Tag get(Class handlerClass) throws JspException {
117: Tag handler = null;
118: synchronized (this ) {
119: if (current >= 0) {
120: handler = handlers[current--];
121: return handler;
122: }
123: }
124:
125: // Out of sync block - there is no need for other threads to
126: // wait for us to construct a tag for this thread.
127: try {
128: Tag instance = (Tag) handlerClass.newInstance();
129: AnnotationHelper.postConstruct(annotationProcessor,
130: instance);
131: return instance;
132: } catch (Exception e) {
133: throw new JspException(e.getMessage(), e);
134: }
135: }
136:
137: /**
138: * Adds the given tag handler to this tag handler pool, unless this tag
139: * handler pool has already reached its capacity, in which case the tag
140: * handler's release() method is called.
141: *
142: * @param handler Tag handler to add to this tag handler pool
143: */
144: public void reuse(Tag handler) {
145: synchronized (this ) {
146: if (current < (handlers.length - 1)) {
147: handlers[++current] = handler;
148: return;
149: }
150: }
151: // There is no need for other threads to wait for us to release
152: handler.release();
153: if (annotationProcessor != null) {
154: try {
155: AnnotationHelper.preDestroy(annotationProcessor,
156: handler);
157: } catch (Exception e) {
158: log.warn(
159: "Error processing preDestroy on tag instance of "
160: + handler.getClass().getName(), e);
161: }
162: }
163: }
164:
165: /**
166: * Calls the release() method of all available tag handlers in this tag
167: * handler pool.
168: */
169: public synchronized void release() {
170: for (int i = current; i >= 0; i--) {
171: handlers[i].release();
172: if (annotationProcessor != null) {
173: try {
174: AnnotationHelper.preDestroy(annotationProcessor,
175: handlers[i]);
176: } catch (Exception e) {
177: log.warn(
178: "Error processing preDestroy on tag instance of "
179: + handlers[i].getClass().getName(),
180: e);
181: }
182: }
183: }
184: }
185:
186: protected static String getOption(ServletConfig config,
187: String name, String defaultV) {
188: if (config == null)
189: return defaultV;
190:
191: String value = config.getInitParameter(name);
192: if (value != null)
193: return value;
194: if (config.getServletContext() == null)
195: return defaultV;
196: value = config.getServletContext().getInitParameter(name);
197: if (value != null)
198: return value;
199: return defaultV;
200: }
201:
202: }
|