Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Количество инстансов сервлета в Tomcat / 19 сообщений из 19, страница 1 из 1
24.05.2012, 22:41:32
    #37810670
Kachalov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Сегодня общался с программистом который сказал мне что в Tomcat можно настроить количество экземпляров сервлета которое будет создаваться (т. е. пул экземпляров). На просьбу указать что это за настройка и к какому месту ее приткнуть, ответил что все есть в документации. Я с Tomcat работаю много лет и неплохо знаком с его настройками, но про такое слышу впервые (ранее наивно предполагал что инстанс сервлета создается один). Просветите, может и правда есть такое?
...
Рейтинг: 0 / 0
24.05.2012, 23:06:35
    #37810689
Alexander A. Sak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Тоже стало интересно. вот результат исследования.

1. Спецификация.
Servlet-3_0-final-spec.pdf2.2. Number of instances.
...
For a servlet not hosted in a distributed environment (the default), the servlet
container must use only one instance per servlet declaration. However, for a servlet
implementing the SingleThreadModel interface, the servlet container may
instantiate multiple instances to handle a heavy request load and serialize requests
to a particular instance.

Но есть лазейка с интерфейсом SingleThreadModel. Вроде как контейнер вправе реализовывать как синхронизацией, так и пулом экземпляров. Гугл выдал такое:

2. http://www.codestyle.org/java/servlets/faq-Threads.shtml
Q: How can I invoke servlet pooling with SingleThreadedModel?

A: The SingleThreadedModel servlet specification does not require the creation of a pool of servlets. A single threaded model implementation may also synchronize access to a single servlet instance to achieve the same outcome, so that only one request is processed at a time. Apache Tomcat uses the synchronized approach , other servlet containers may use the pooled approach.


Получается, либо вы друг друга не поняли, либо программист -- фантазер.
...
Рейтинг: 0 / 0
24.05.2012, 23:09:57
    #37810692
vas0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Kachalov,

В целом непонятно что дает пул сервлетов если он будет потоко-безопасен.

Другое дело если сервлет потоко-небезопасен и реализует SingleThreadModel. Вроде как в этом случае контейнер действительно должен создавать пул. Но насколько это настраивается в tomcat не в курсе.
...
Рейтинг: 0 / 0
24.05.2012, 23:26:18
    #37810707
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Kachalov,

Скорее всего, он имел в виду многопоточность сервлетов, когда каждый поток выполнения имеет дело со своими собственными объектами ServletRequest и ServletResponse, изолированными от других потоков. По- умолчанию сервлеты многопоточны и можно конфигурировать пулы:

Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
...
<!-- A pooled AJPV12 Connector for out-of-process operation -->
<Connector className="org.apache.tomcat.service.PoolTcpConnector">
    <Parameter
        name="handler"
        value="org.apache.tomcat.service.connector.Ajp12ConnectionHandler"/>
    <Parameter
        name="port"
        value="8007"/>
    <Parameter
        name="max_threads"
        value="30"/>
    <Parameter
        name="max_spare_threads"
        value="20"/>
    <Parameter
        name="min_spare_threads"
        value="5" />
</Connector>

...



Имплементация SingleThreadModel делает сервлет однопоточным, что выстраивает реквесты в очередь.
...
Рейтинг: 0 / 0
08.06.2012, 12:36:49
    #37830913
in7
in7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Посмотел FAQ http://www.codestyle.org/java/servlets/faq-Threads.shtml

В нём есть ответ на ваш вопрос:

Q: Are you saying there is only one servlet instance for all requests?
A: The way that servlet containers handle servlet requests is not prescribed to this extent; they may use a single servlet, they may use servlet pooling, it depends on the vendor's system architecture.

Вообще, не встречал описания настройки для пула экземпляров одного сервлетаё в tomcat'е.

Чуть выше приведены настройки для пула соединений. Наверное, он путает их или даже не понимает разницы


Обычно продуктивная среда работает в кластере с балансировщиком, что гарантирует доступность при следующем обращении пользовательских данных в сессии и контексте, и становится бессмысленным использовать поля и статические поля сервлета.
Поэтому возможность появления нескольких экземпляров не пугает.
...
Рейтинг: 0 / 0
08.06.2012, 13:56:41
    #37831088
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
На старте контейнера, HTTP Connector создает число потоков сервлета, равное minSpareThreads . Далее это число возрастает по мере необходимости до MaxThreads . Чуть ниже в том же FAQ приведен пример; наверное, вы не дочитал его до конца или даже не догадываетесь о существовании других источников информации по сабжу.
...
Рейтинг: 0 / 0
08.06.2012, 17:28:21
    #37831595
in7
in7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-void,

вот ещё один пример, когда программист путает количество потоков и количество экземпляров.
...
Рейтинг: 0 / 0
08.06.2012, 21:13:54
    #37831876
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
in7,

Tomcat ожидает запрос входящих соединений в PoolTcpEndPoint.class и создает для каждого запроса новый рабочий поток -

PoolTcpEndPoint.java
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
   /*
    *  Licensed to the Apache Software Foundation (ASF) under one or more
    *  contributor license agreements.  See the NOTICE file distributed with
    *  this work for additional information regarding copyright ownership.
    *  The ASF licenses this file to You 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 org.apache.tomcat.util.net;
   
   import java.io.IOException;
   import java.io.InterruptedIOException;
   import java.net.BindException;
   import java.net.InetAddress;
   import java.net.ServerSocket;
   import java.net.Socket;
   import java.net.SocketException;
   import java.security.AccessControlException;
   import java.util.Stack;
   import java.util.Vector;
   
   import org.apache.juli.logging.Log;
   import org.apache.juli.logging.LogFactory;
   import org.apache.tomcat.util.res.StringManager;
   import org.apache.tomcat.util.threads.ThreadPool;
   import org.apache.tomcat.util.threads.ThreadPoolRunnable;
      
      /* Similar with MPM module in Apache2.0. Handles all the details related with
         "tcp server" functionality - thread management, accept policy, etc.
         It should do nothing more - as soon as it get a socket ( and all socket options
         are set, etc), it just handle the stream to ConnectionHandler.processConnection. (costin)
      */
      
      
      
      /**
       * Handle incoming TCP connections.
       *
       * This class implement a simple server model: one listener thread accepts on a socket and
       * creates a new worker thread for each incoming connection.
       *
       * More advanced Endpoints will reuse the threads, use queues, etc.
       *
       * @author James Duncan Davidson [duncan@eng.sun.com]
       * @author Jason Hunter [jch@eng.sun.com]
       * @author James Todd [gonzo@eng.sun.com]
       * @author Costin@eng.sun.com
       * @author Gal Shachor [shachor@il.ibm.com]
       * @author Yoav Shapira <yoavs@apache.org>;
       */
      public class PoolTcpEndpoint implements Runnable { // implements Endpoint {
      
          static Log log=LogFactory.getLog(PoolTcpEndpoint.class );
      
          private StringManager sm = 
              StringManager.getManager("org.apache.tomcat.util.net.res");
      
          private static final int BACKLOG = 100;
          private static final int TIMEOUT = 1000;
      
          private final Object threadSync = new Object();
      
          private int backlog = BACKLOG;
          private int serverTimeout = TIMEOUT;
      
          private InetAddress inet;
          private int port;
      
          private ServerSocketFactory factory;
          private ServerSocket serverSocket;
      
          private volatile boolean running = false;
          private volatile boolean paused = false;
          private boolean initialized = false;
          private boolean reinitializing = false;
          static final int debug=0;
      
          protected boolean tcpNoDelay=false;
          protected int linger=100;
          protected int socketTimeout=-1;
          private boolean lf = true;
      
          
          // ------ Leader follower fields
      
          
          TcpConnectionHandler handler;
          ThreadPoolRunnable listener;
          ThreadPool tp;
      
         
         // ------ Master slave fields
     
         /* The background thread. */
         private Thread thread = null;
         /* Available processors. */
         private Stack workerThreads = new Stack();
         private int curThreads = 0;
         private int maxThreads = 20;
         /* All processors which have been created. */
         private Vector created = new Vector();
     
         
         public PoolTcpEndpoint() {
     	tp = new ThreadPool();
         }
     
         public PoolTcpEndpoint( ThreadPool tp ) {
             this.tp=tp;
         }
     
         // -------------------- Configuration --------------------
     
         public void setMaxThreads(int maxThreads) {
     	if( maxThreads > 0)
     	    tp.setMaxThreads(maxThreads);
         }
     
         public int getMaxThreads() {
             return tp.getMaxThreads();
         }
     
         public void setMaxSpareThreads(int maxThreads) {
     	if(maxThreads > 0) 
     	    tp.setMaxSpareThreads(maxThreads);
         }
     
         public int getMaxSpareThreads() {
             return tp.getMaxSpareThreads();
         }
     
         public void setMinSpareThreads(int minThreads) {
     	if(minThreads > 0) 
     	    tp.setMinSpareThreads(minThreads);
         }
     
         public int getMinSpareThreads() {
             return tp.getMinSpareThreads();
         }
     
         public void setThreadPriority(int threadPriority) {
           tp.setThreadPriority(threadPriority);
         }
     
         public int getThreadPriority() {
           return tp.getThreadPriority();
         }
     
         public int getPort() {
             return port;
         }
     
         public void setPort(int port ) {
             this.port=port;
         }
     
         public InetAddress getAddress() {
     	    return inet;
         }
     
         public void setAddress(InetAddress inet) {
     	    this.inet=inet;
         }
     
         public void setServerSocket(ServerSocket ss) {
     	    serverSocket = ss;
         }
     
         public void setServerSocketFactory(  ServerSocketFactory factory ) {
     	    this.factory=factory;
         }
     
        ServerSocketFactory getServerSocketFactory() {
      	    return factory;
        }
     
         public void setConnectionHandler( TcpConnectionHandler handler ) {
         	this.handler=handler;
         }
     
         public TcpConnectionHandler getConnectionHandler() {
     	    return handler;
         }
     
         public boolean isRunning() {
     	return running;
         }
         
         public boolean isPaused() {
     	return paused;
         }
         
         /**
        * Allows the server developer to specify the backlog that
         * should be used for server sockets. By default, this value
          * is 100.
          */
        public void setBacklog(int backlog) {
    	if( backlog>0)
     	    this.backlog = backlog;
        }
     
        public int getBacklog() {
             return backlog;
         }
     
         /**
         * Sets the timeout in ms of the server sockets created by this
          * server. This method allows the developer to make servers
          * more or less responsive to having their server sockets
          * shut down.
          *
          * <p>By default this value is 1000ms.
          */
         public void setServerTimeout(int timeout) {
    	this.serverTimeout = timeout;
         }
     
         public boolean getTcpNoDelay() {
             return tcpNoDelay;
         }
         
         public void setTcpNoDelay( boolean b ) {
     	tcpNoDelay=b;
         }
    
         public int getSoLinger() {
             return linger;
         }
        
         public void setSoLinger( int i ) {
     	linger=i;
         }
     
         public int getSoTimeout() {
             return socketTimeout;
         }
         
         public void setSoTimeout( int i ) {
    	socketTimeout=i;
         }
         
         public int getServerSoTimeout() {
             return serverTimeout;
         }  
         
         public void setServerSoTimeout( int i ) {
     	serverTimeout=i;
         }
     
         public String getStrategy() {
             if (lf) {
                 return "lf";
             } else {
                 return "ms";
             }
         }
         
         public void setStrategy(String strategy) {
             if ("ms".equals(strategy)) {
                 lf = false;
            } else {
                 lf = true;
             }
         }
     
         public int getCurrentThreadCount() {
             return curThreads;
         }
         
         public int getCurrentThreadsBusy() {
             return curThreads - workerThreads.size();
         }
         
         // -------------------- Public methods --------------------
     
         public void initEndpoint() throws IOException, InstantiationException {
             try {
                 if(factory==null)
                     factory=ServerSocketFactory.getDefault();
                 if(serverSocket==null) {
                     try {
                         if (inet == null) {
                             serverSocket = factory.createSocket(port, backlog);
                         } else {
                             serverSocket = factory.createSocket(port, backlog, inet);
                         }
                     } catch (BindException orig) {
                         String msg;
                         if (inet == null)
                             msg = orig.getMessage() + "<null>:" + port;
                         else
                             msg = orig.getMessage() + " " +
                                     inet.toString() + ":" + port;
                         BindException be = new BindException(msg);
                         be.initCause(orig);
                         throw be;
                     }
                 }
                 if( serverTimeout >= 0 )
                     serverSocket.setSoTimeout( serverTimeout );
             } catch( IOException ex ) {
                 throw ex;
             } catch( InstantiationException ex1 ) {
                 throw ex1;
             }
             initialized = true;
         }
         
         public void startEndpoint() throws IOException, InstantiationException {
             if (!initialized) {
                 initEndpoint();
             }
             if (lf) {
                 tp.start();
             }
             running = true;
             paused = false;
             if (lf) {
                 listener = new LeaderFollowerWorkerThread(this);
                 tp.runIt(listener);
             } else {
                 maxThreads = getMaxThreads();
                 threadStart();
             }
         }
     
         public void pauseEndpoint() {
             if (running && !paused) {
                 paused = true;
                 unlockAccept();
             }
         }
     
         public void resumeEndpoint() {
             if (running) {
                 paused = false;
             }
         }
     
         public void stopEndpoint() {
             if (running) {
                 if (lf) {
                     tp.shutdown();
                 }
                 running = false;
                 if (serverSocket != null) {
                     closeServerSocket();
                 }
                 if (!lf) {
                     threadStop();
                 }
                 initialized=false ;
             }
         }
     
         protected void closeServerSocket() {
             if (!paused)
                 unlockAccept();
             try {
                 if( serverSocket!=null)
                     serverSocket.close();
             } catch(Exception e) {
                 log.error(sm.getString("endpoint.err.close"), e);
             }
             serverSocket = null;
         }
     
         protected void unlockAccept() {
             Socket s = null;
             try {
                 // Need to create a connection to unlock the accept();
                 if (inet == null) {
                     s = new Socket(InetAddress.getByName("localhost").getHostAddress(), port);
                 } else {
                     s = new Socket(inet, port);
                         // setting soLinger to a small value will help shutdown the
                         // connection quicker
                     s.setSoLinger(true, 0);
                 }
             } catch(Exception e) {
                 if (log.isDebugEnabled()) {
                     log.debug(sm.getString("endpoint.debug.unlock", "" + port), e);
                 }
             } finally {
                 if (s != null) {
                     try {
                         s.close();
                     } catch (Exception e) {
                         // Ignore
                     }
                 }
             }
         }
     
         // -------------------- Private methods
     
         Socket acceptSocket() {
             if( !running || serverSocket==null ) return null;
     
             Socket accepted = null;
     
         	try {
                 if(factory==null) {
                     accepted = serverSocket.accept();
                 } else {
                     accepted = factory.acceptSocket(serverSocket);
                 }
                 if (null == accepted) {
                     log.warn(sm.getString("endpoint.warn.nullSocket"));
                 } else {
                     if (!running) {
                         accepted.close();  // rude, but unlikely!
                         accepted = null;
                     } else if (factory != null) {
                         factory.initSocket( accepted );
                     }
                 }
             }
             catch(InterruptedIOException iioe) {
                 // normal part -- should happen regularly so
                 // that the endpoint can release if the server
                 // is shutdown.
             }
             catch (AccessControlException ace) {
                 // When using the Java SecurityManager this exception
                 // can be thrown if you are restricting access to the
                 // socket with SocketPermission's.
                 // Log the unauthorized access and continue
                 String msg = sm.getString("endpoint.warn.security",
                                           serverSocket, ace);
                 log.warn(msg);
             }
             catch (IOException e) {
     
                 String msg = null;
     
                 if (running) {
                     msg = sm.getString("endpoint.err.nonfatal",
                             serverSocket, e);
                     log.error(msg, e);
                 }
     
                 if (accepted != null) {
                     try {
                         accepted.close();
                     } catch(Throwable ex) {
                         msg = sm.getString("endpoint.err.nonfatal",
                                            accepted, ex);
                         log.warn(msg, ex);
                     }
                     accepted = null;
                 }
     
                 if( ! running ) return null;
                 reinitializing = true;
                 // Restart endpoint when getting an IOException during accept
                 synchronized (threadSync) {
                     if (reinitializing) {
                         reinitializing = false;
                         // 1) Attempt to close server socket
                         closeServerSocket();
                         initialized = false;
                         // 2) Reinit endpoint (recreate server socket)
                         try {
                             msg = sm.getString("endpoint.warn.reinit");
                             log.warn(msg);
                             initEndpoint();
                         } catch (Throwable t) {
                             msg = sm.getString("endpoint.err.nonfatal",
                                                serverSocket, t);
                             log.error(msg, t);
                         }
                         // 3) If failed, attempt to restart endpoint
                         if (!initialized) {
                             msg = sm.getString("endpoint.warn.restart");
                             log.warn(msg);
                             try {
                                 stopEndpoint();
                                 initEndpoint();
                                 startEndpoint();
                             } catch (Throwable t) {
                                 msg = sm.getString("endpoint.err.fatal",
                                                    serverSocket, t);
                                 log.error(msg, t);
                             }
                             // Current thread is now invalid: kill it
                             throw new ThreadDeath();
                         }
                     }
                 }
     
             }
     
             return accepted;
         }
     
         void setSocketOptions(Socket socket)
             throws SocketException {
             if(linger >= 0 ) 
                 socket.setSoLinger( true, linger);
             if( tcpNoDelay )
                 socket.setTcpNoDelay(tcpNoDelay);
             if( socketTimeout > 0 )
                 socket.setSoTimeout( socketTimeout );
         }
     
         
         void processSocket(Socket s, TcpConnection con, Object[] threadData) {
             // Process the connection
             int step = 1;
             try {
                 
                 // 1: Set socket options: timeout, linger, etc
                 setSocketOptions(s);
                 
                 // 2: SSL handshake
                 step = 2;
                 if (getServerSocketFactory() != null) {
                     getServerSocketFactory().handshake(s);
                 }
                 
                 // 3: Process the connection
                 step = 3;
                 con.setEndpoint(this);
                 con.setSocket(s);
                 getConnectionHandler().processConnection(con, threadData);
                 
             } catch (SocketException se) {
                 log.debug(sm.getString("endpoint.err.socket", s.getInetAddress()),
                         se);
                 // Try to close the socket
                 try {
                     s.close();
                 } catch (IOException e) {
                 }
             } catch (Throwable t) {
                 if (step == 2) {
                     if (log.isDebugEnabled()) {
                         log.debug(sm.getString("endpoint.err.handshake"), t);
                     }
                 } else {
                     log.error(sm.getString("endpoint.err.unexpected"), t);
                 }
                 // Try to close the socket
                 try {
                     s.close();
                 } catch (IOException e) {
                 }
             } finally {
                 if (con != null) {
                     con.recycle();
                 }
             }
         }
         
    
         // -------------------------------------------------- Master Slave Methods
     
     
         /**
          * Create (or allocate) and return an available processor for use in
          * processing a specific HTTP request, if possible.  If the maximum
          * allowed processors have already been created and are in use, return
          * <code>null</code> instead.
          */
         private MasterSlaveWorkerThread createWorkerThread() {
     
             synchronized (workerThreads) {
                 if (workerThreads.size() > 0) {
                     return ((MasterSlaveWorkerThread) workerThreads.pop());
                 }
                 if ((maxThreads > 0) && (curThreads < maxThreads)) {
                     return (newWorkerThread());
                 } else {
                     if (maxThreads < 0) {
                         return (newWorkerThread());
                     } else {
                         return (null);
                     }
                 }
             }
     
         }
     
         
         /**
          * Create and return a new processor suitable for processing HTTP
          * requests and returning the corresponding responses.
          */
         private MasterSlaveWorkerThread newWorkerThread() {
     
             MasterSlaveWorkerThread workerThread = 
                 new MasterSlaveWorkerThread(this, tp.getName() + "-" + (++curThreads));
             workerThread.start();
             created.addElement(workerThread);
             return (workerThread);
     
         }
     
     
         /**
          * Recycle the specified Processor so that it can be used again.
          *
          * @param processor The processor to be recycled
          */
         void recycleWorkerThread(MasterSlaveWorkerThread workerThread) {
             workerThreads.push(workerThread);
         }
     
         
         /**
          * The background thread that listens for incoming TCP/IP connections and
          * hands them off to an appropriate processor.
          */
         public void run() {
     
             // Loop until we receive a shutdown command
             while (running) {
     
                 // Loop if endpoint is paused
                 while (paused) {
                     try {
                         Thread.sleep(1000);
                     } catch (InterruptedException e) {
                         // Ignore
                     }
                 }
     
                 // Allocate a new worker thread
                 MasterSlaveWorkerThread workerThread = createWorkerThread();
                 if (workerThread == null) {
                     try {
                         // Wait a little for load to go down: as a result, 
                         // no accept will be made until the concurrency is
                         // lower than the specified maxThreads, and current
                         // connections will wait for a little bit instead of
                         // failing right away.
                         Thread.sleep(100);
                     } catch (InterruptedException e) {
                         // Ignore
                     }
                     continue;
                 }
                 
                 // Accept the next incoming connection from the server socket
                 Socket socket = acceptSocket();
     
                 // Hand this socket off to an appropriate processor
                 workerThread.assign(socket);
     
                 // The processor will recycle itself when it finishes
     
             }
     
             // Notify the threadStop() method that we have shut ourselves down
             synchronized (threadSync) {
                 threadSync.notifyAll();
             }
     
         }
     
     
         /**
          * Start the background processing thread.
          */
         private void threadStart() {
             thread = new Thread(this, tp.getName());
             thread.setPriority(getThreadPriority());
             thread.setDaemon(true);
             thread.start();
         }
     
     
         /**
          * Stop the background processing thread.
          */
         private void threadStop() {
             thread = null;
         }
     
     
     }



Что вы понимаете под количеством экземпляров?
...
Рейтинг: 0 / 0
08.06.2012, 21:43:23
    #37831915
in7
in7
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-void,
что и все люди.

есть такой ресурс wikipedia . Там можно искать значения разных слов.
...
Рейтинг: 0 / 0
08.06.2012, 21:56:01
    #37831928
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
in7ivanov-void,
что и все люди.

есть такой ресурс wikipedia . Там можно искать значения разных слов.

Создает ли?
...
Рейтинг: 0 / 0
08.06.2012, 22:24:16
    #37831956
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
тьфу не на то ответил - в общем потоки не создаются а переиспользуются, сорри:)
...
Рейтинг: 0 / 0
08.06.2012, 22:27:22
    #37831958
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
in7есть такой ресурс wikipedia. Там можно искать значения разных слов.

Это если на гугле забанили.

забыл никСоздает ли?

Создает или извлекает из стека-

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
...
        /**
          * Create (or allocate) and return an available processor for use in
          * processing a specific HTTP request, if possible.  If the maximum
          * allowed processors have already been created and are in use, return
          * <code>null</code> instead.
          */
         private MasterSlaveWorkerThread createWorkerThread() {
     
             synchronized (workerThreads) {
                 if (workerThreads.size() > 0) {
                     return ((MasterSlaveWorkerThread) workerThreads.pop());
                 }
                 if ((maxThreads > 0) && (curThreads < maxThreads)) {
                     return (newWorkerThread());
                 } else {
                     if (maxThreads < 0) {
                         return (newWorkerThread());
                     } else {
                         return (null);
                     }
                 }
             }
     
         }
...
...
Рейтинг: 0 / 0
09.06.2012, 12:09:50
    #37832490
Kachalov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-voidСоздает или извлекает из стека-

- по прежнему Вы пишите о чем-то своем, изначально речь шла о количестве экземпляров пользовательского сервлета , а не объекта типа WorkerThread . Поясню, речь идет о вызовах методов одного экземпляра сервлета в разных потоках, связанных с обрабатываемыми запросам, и создании отдельного экземпляра сервлета (из пула или в процессе обращения - не так важно) для каждого потока, связанного с обрабатываемым запросом. По итогам дискуссии вроде пришли к выводу, что второе возможно только для SingleThreadModel. Теперь осталось понять есть ли в Tomcat настройка определяющая размер пула экземпляров сервлета для этого случая (если конечно, он вообще создает пул в этом случае). По приведенной выше ссылке на www.codestyle.org (авторитетность ресурса, ИМХО, под сомнением, по уму надо самому лезть в код Tomcat) вроде Tomcat не создает пула экземпляров сервлета и в этом случае.
...
Рейтинг: 0 / 0
09.06.2012, 16:07:27
    #37832907
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Kachalov,

Все это настраивается через StandardWrapper , но смысла большого не имеет, поскольку с 2003 года интерфейс SingleThreadModel is deprecated, и при необходимости сервлет нужно писать потокобезопасным, организуя свои стратегии рандеву.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
942.
943.
944.
945.
946.
947.
948.
949.
950.
951.
952.
953.
954.
955.
956.
957.
958.
959.
960.
961.
962.
963.
964.
965.
966.
967.
968.
969.
970.
971.
972.
973.
974.
975.
976.
977.
978.
979.
980.
981.
982.
983.
984.
985.
986.
987.
988.
989.
990.
991.
992.
993.
994.
995.
996.
997.
998.
999.
1000.
1001.
1002.
1003.
1004.
1005.
1006.
1007.
1008.
1009.
1010.
1011.
1012.
1013.
1014.
1015.
1016.
1017.
1018.
1019.
1020.
1021.
1022.
1023.
1024.
1025.
1026.
1027.
1028.
1029.
1030.
1031.
1032.
1033.
1034.
1035.
1036.
1037.
1038.
1039.
1040.
1041.
1042.
1043.
1044.
1045.
1046.
1047.
1048.
1049.
1050.
1051.
1052.
1053.
1054.
1055.
1056.
1057.
1058.
1059.
1060.
1061.
1062.
1063.
1064.
1065.
1066.
1067.
1068.
1069.
1070.
1071.
1072.
1073.
1074.
1075.
1076.
1077.
1078.
1079.
1080.
1081.
1082.
1083.
1084.
1085.
1086.
1087.
1088.
1089.
1090.
1091.
1092.
1093.
1094.
1095.
1096.
1097.
1098.
1099.
1100.
1101.
1102.
1103.
1104.
1105.
1106.
1107.
1108.
1109.
1110.
1111.
1112.
1113.
1114.
1115.
1116.
1117.
1118.
1119.
1120.
1121.
1122.
1123.
1124.
1125.
1126.
1127.
1128.
1129.
1130.
1131.
1132.
1133.
1134.
1135.
1136.
1137.
1138.
1139.
1140.
1141.
1142.
1143.
1144.
1145.
1146.
1147.
1148.
1149.
1150.
1151.
1152.
1153.
1154.
1155.
1156.
1157.
1158.
1159.
1160.
1161.
1162.
1163.
1164.
1165.
1166.
1167.
1168.
1169.
1170.
1171.
1172.
1173.
1174.
1175.
1176.
1177.
1178.
1179.
1180.
1181.
1182.
1183.
1184.
1185.
1186.
1187.
1188.
1189.
1190.
1191.
1192.
1193.
1194.
1195.
1196.
1197.
1198.
1199.
1200.
1201.
1202.
1203.
1204.
1205.
1206.
1207.
1208.
1209.
1210.
1211.
1212.
1213.
1214.
1215.
1216.
1217.
1218.
1219.
1220.
1221.
1222.
1223.
1224.
1225.
1226.
1227.
1228.
1229.
1230.
1231.
1232.
1233.
1234.
1235.
1236.
1237.
1238.
1239.
1240.
1241.
1242.
1243.
1244.
1245.
1246.
1247.
1248.
1249.
1250.
1251.
1252.
1253.
1254.
1255.
1256.
1257.
1258.
1259.
1260.
1261.
1262.
1263.
1264.
1265.
1266.
1267.
1268.
1269.
1270.
1271.
1272.
1273.
1274.
1275.
1276.
1277.
1278.
1279.
1280.
1281.
1282.
1283.
1284.
1285.
1286.
1287.
1288.
1289.
1290.
1291.
1292.
1293.
1294.
1295.
1296.
1297.
1298.
1299.
1300.
1301.
1302.
1303.
1304.
1305.
1306.
1307.
1308.
1309.
1310.
1311.
1312.
1313.
1314.
1315.
1316.
1317.
1318.
1319.
1320.
1321.
1322.
1323.
1324.
1325.
1326.
1327.
1328.
1329.
1330.
1331.
1332.
1333.
1334.
1335.
1336.
1337.
1338.
1339.
1340.
1341.
1342.
1343.
1344.
1345.
1346.
1347.
1348.
1349.
1350.
1351.
1352.
1353.
1354.
1355.
1356.
1357.
1358.
1359.
1360.
1361.
1362.
1363.
1364.
1365.
1366.
1367.
1368.
1369.
1370.
1371.
1372.
1373.
1374.
1375.
1376.
1377.
1378.
1379.
1380.
1381.
1382.
1383.
1384.
1385.
1386.
1387.
1388.
1389.
1390.
1391.
1392.
1393.
1394.
1395.
1396.
1397.
1398.
1399.
1400.
1401.
1402.
1403.
1404.
1405.
1406.
1407.
1408.
1409.
1410.
1411.
1412.
1413.
1414.
1415.
1416.
1417.
1418.
1419.
1420.
1421.
1422.
1423.
1424.
1425.
1426.
1427.
1428.
1429.
1430.
1431.
1432.
1433.
1434.
1435.
1436.
1437.
1438.
1439.
1440.
1441.
1442.
1443.
1444.
1445.
1446.
1447.
1448.
1449.
1450.
1451.
1452.
1453.
1454.
1455.
1456.
1457.
1458.
1459.
1460.
1461.
1462.
1463.
1464.
1465.
1466.
1467.
1468.
1469.
1470.
1471.
1472.
1473.
1474.
1475.
1476.
1477.
1478.
1479.
1480.
1481.
1482.
1483.
1484.
1485.
1486.
1487.
1488.
1489.
1490.
1491.
1492.
1493.
1494.
1495.
1496.
1497.
1498.
1499.
1500.
1501.
1502.
1503.
1504.
1505.
1506.
1507.
1508.
1509.
1510.
1511.
1512.
1513.
1514.
1515.
1516.
1517.
1518.
1519.
1520.
1521.
1522.
1523.
1524.
1525.
1526.
1527.
1528.
1529.
1530.
1531.
1532.
1533.
1534.
1535.
1536.
1537.
1538.
1539.
1540.
1541.
1542.
1543.
1544.
1545.
1546.
1547.
1548.
1549.
1550.
1551.
1552.
1553.
1554.
1555.
1556.
1557.
1558.
1559.
1560.
1561.
1562.
1563.
1564.
1565.
1566.
1567.
1568.
1569.
1570.
1571.
1572.
1573.
1574.
1575.
1576.
1577.
1578.
1579.
1580.
1581.
1582.
1583.
1584.
1585.
1586.
1587.
1588.
1589.
1590.
1591.
1592.
1593.
1594.
1595.
1596.
1597.
1598.
1599.
1600.
1601.
1602.
1603.
1604.
1605.
1606.
1607.
1608.
1609.
1610.
1611.
1612.
1613.
1614.
1615.
1616.
1617.
1618.
1619.
1620.
1621.
1622.
1623.
1624.
1625.
1626.
1627.
1628.
1629.
1630.
1631.
1632.
1633.
1634.
1635.
1636.
1637.
1638.
1639.
1640.
1641.
1642.
1643.
1644.
1645.
1646.
1647.
1648.
1649.
1650.
1651.
1652.
1653.
1654.
1655.
1656.
1657.
1658.
1659.
1660.
1661.
1662.
1663.
1664.
1665.
1666.
1667.
1668.
1669.
1670.
1671.
1672.
1673.
1674.
1675.
1676.
1677.
1678.
1679.
1680.
1681.
1682.
1683.
1684.
1685.
1686.
1687.
1688.
1689.
1690.
1691.
1692.
1693.
1694.
1695.
1696.
1697.
1698.
1699.
1700.
1701.
1702.
1703.
1704.
1705.
1706.
1707.
1708.
1709.
1710.
1711.
1712.
1713.
1714.
1715.
1716.
1717.
1718.
1719.
1720.
1721.
1722.
1723.
1724.
1725.
1726.
1727.
1728.
1729.
1730.
1731.
1732.
1733.
1734.
1735.
1736.
1737.
1738.
1739.
1740.
1741.
1742.
1743.
1744.
1745.
1746.
1747.
1748.
1749.
1750.
1751.
1752.
1753.
1754.
1755.
1756.
1757.
1758.
1759.
1760.
1761.
1762.
1763.
1764.
1765.
1766.
1767.
1768.
1769.
1770.
1771.
1772.
1773.
1774.
1775.
1776.
1777.
1778.
1779.
1780.
1781.
1782.
1783.
1784.
1785.
1786.
1787.
1788.
1789.
1790.
1791.
1792.
1793.
1794.
1795.
1796.
1797.
1798.
1799.
1800.
1801.
1802.
1803.
1804.
1805.
1806.
1807.
1808.
1809.
1810.
1811.
1812.
1813.
1814.
1815.
1816.
1817.
1818.
1819.
1820.
1821.
1822.
1823.
1824.
1825.
1826.
1827.
1828.
1829.
1830.
1831.
1832.
1833.
1834.
1835.
1836.
1837.
1838.
1839.
1840.
1841.
1842.
1843.
1844.
1845.
1846.
1847.
1848.
1849.
1850.
1851.
1852.
1853.
1854.
1855.
1856.
1857.
1858.
1859.
1860.
1861.
1862.
1863.
1864.
1865.
1866.
1867.
1868.
1869.
1870.
1871.
1872.
1873.
1874.
1875.
1876.
1877.
1878.
1879.
1880.
1881.
1882.
1883.
1884.
1885.
1886.
1887.
1888.
1889.
1890.
1891.
1892.
1893.
1894.
1895.
1896.
1897.
1898.
1899.
1900.
1901.
1902.
1903.
1904.
1905.
1906.
1907.
1908.
1909.
1910.
1911.
1912.
1913.
1914.
1915.
1916.
1917.
1918.
1919.
1920.
1921.
1922.
1923.
1924.
1925.
1926.
1927.
1928.
1929.
1930.
1931.
1932.
1933.
1934.
1935.
1936.
1937.
1938.
1939.
1940.
1941.
1942.
1943.
1944.
1945.
1946.
1947.
1948.
1949.
1950.
1951.
1952.
1953.
1954.
1955.
1956.
1957.
1958.
1959.
1960.
1961.
1962.
1963.
1964.
1965.
1966.
1967.
1968.
1969.
1970.
1971.
1972.
1973.
1974.
1975.
1976.
1977.
1978.
1979.
1980.
1981.
1982.
1983.
1984.
1985.
1986.
1987.
1988.
1989.
1990.
1991.
1992.
1993.
1994.
1995.
1996.
1997.
1998.
1999.
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.catalina.core;

import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletSecurityElement;
import javax.servlet.SingleThreadModel;
import javax.servlet.UnavailableException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.ServletSecurity;

import org.apache.catalina.Container;
import org.apache.catalina.ContainerServlet;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.InstanceEvent;
import org.apache.catalina.InstanceListener;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Wrapper;
import org.apache.catalina.mbeans.MBeanUtils;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.InstanceSupport;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.PeriodicEventListener;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.modeler.Registry;

/**
 * Standard implementation of the <b>Wrapper</b> interface that represents
 * an individual servlet definition.  No child Containers are allowed, and
 * the parent Container must be a Context.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @version $Id: StandardWrapper.java 1241892 2012-02-08 13:28:05Z markt $
 */
@SuppressWarnings("deprecation") // SingleThreadModel
public class StandardWrapper extends ContainerBase
    implements ServletConfig, Wrapper, NotificationEmitter {

    private static final Log log = LogFactory.getLog( StandardWrapper.class );

    protected static final String[] DEFAULT_SERVLET_METHODS = new String[] {
                                                    "GET", "HEAD", "POST" };

    // ----------------------------------------------------------- Constructors


    /**
     * Create a new StandardWrapper component with the default basic Valve.
     */
    public StandardWrapper() {

        super();
        swValve=new StandardWrapperValve();
        pipeline.setBasic(swValve);
        broadcaster = new NotificationBroadcasterSupport();

    }


    // ----------------------------------------------------- Instance Variables


    /**
     * The date and time at which this servlet will become available (in
     * milliseconds since the epoch), or zero if the servlet is available.
     * If this value equals Long.MAX_VALUE, the unavailability of this
     * servlet is considered permanent.
     */
    protected long available = 0L;
    
    /**
     * The broadcaster that sends j2ee notifications. 
     */
    protected NotificationBroadcasterSupport broadcaster = null;
    
    /**
     * The count of allocations that are currently active (even if they
     * are for the same instance, as will be true on a non-STM servlet).
     */
    protected AtomicInteger countAllocated = new AtomicInteger(0);


    /**
     * The facade associated with this wrapper.
     */
    protected StandardWrapperFacade facade =
        new StandardWrapperFacade(this);


    /**
     * The descriptive information string for this implementation.
     */
    protected static final String info =
        "org.apache.catalina.core.StandardWrapper/1.0";


    /**
     * The (single) possibly uninitialized instance of this servlet.
     */
    protected volatile Servlet instance = null;


    /**
     * Flag that indicates if this instance has been initialized
     */
    protected volatile boolean instanceInitialized = false;

    /**
     * The support object for our instance listeners.
     */
    protected InstanceSupport instanceSupport = new InstanceSupport(this);


    /**
     * The load-on-startup order value (negative value means load on
     * first call) for this servlet.
     */
    protected int loadOnStartup = -1;


    /**
     * Mappings associated with the wrapper.
     */
    protected ArrayList<String> mappings = new ArrayList<String>();


    /**
     * The initialization parameters for this servlet, keyed by
     * parameter name.
     */
    protected HashMap<String, String> parameters = new HashMap<String, String>();


    /**
     * The security role references for this servlet, keyed by role name
     * used in the servlet.  The corresponding value is the role name of
     * the web application itself.
     */
    protected HashMap<String, String> references = new HashMap<String, String>();


    /**
     * The run-as identity for this servlet.
     */
    protected String runAs = null;

    /**
     * The notification sequence number.
     */
    protected long sequenceNumber = 0;

    /**
     * The fully qualified servlet class name for this servlet.
     */
    protected String servletClass = null;


    /**
     * Does this servlet implement the SingleThreadModel interface?
     */
    protected volatile boolean singleThreadModel = false;


    /**
     * Are we unloading our servlet instance at the moment?
     */
    protected boolean unloading = false;


    /**
     * Maximum number of STM instances.
     */
    protected int maxInstances = 20;


    /**
     * Number of instances currently loaded for a STM servlet.
     */
    protected int nInstances = 0;


    /**
     * Stack containing the STM instances.
     */
    protected Stack<Servlet> instancePool = null;

    
    /**
     * Wait time for servlet unload in ms.
     */
    protected long unloadDelay = 2000;
    

    /**
     * True if this StandardWrapper is for the JspServlet
     */
    protected boolean isJspServlet;


    /**
     * The ObjectName of the JSP monitoring mbean
     */
    protected ObjectName jspMonitorON;


    /**
     * Should we swallow System.out
     */
    protected boolean swallowOutput = false;

    // To support jmx attributes
    protected StandardWrapperValve swValve;
    protected long loadTime=0;
    protected int classLoadTime=0;
    
    /**
     * Multipart config
     */
    protected MultipartConfigElement multipartConfigElement = null;
    
    /**
     * Async support
     */
    protected boolean asyncSupported = false;

    /**
     * Enabled
     */
    protected boolean enabled = true;

    protected volatile boolean servletSecurityAnnotationScanRequired = false;

    private boolean overridable = false;
    
    /**
     * Static class array used when the SecurityManager is turned on and 
     * <code>Servlet.init</code> is invoked.
     */
    protected static Class<?>[] classType = new Class[]{ServletConfig.class};
    
    
    /**
     * Static class array used when the SecurityManager is turned on and 
     * <code>Servlet.service</code>  is invoked.
     */                                                 
    @Deprecated
    protected static Class<?>[] classTypeUsedInService = new Class[]{
                                                         ServletRequest.class,
                                                         ServletResponse.class};
    

    private final ReentrantReadWriteLock parametersLock =
            new ReentrantReadWriteLock();

    private final ReentrantReadWriteLock mappingsLock =
            new ReentrantReadWriteLock();

    private final ReentrantReadWriteLock referencesLock =
            new ReentrantReadWriteLock();


    // ------------------------------------------------------------- Properties

    @Override
    public boolean isOverridable() {
        return overridable;
    }

    @Override
    public void setOverridable(boolean overridable) {
        this.overridable = overridable;
    }

    /**
     * Return the available date/time for this servlet, in milliseconds since
     * the epoch.  If this date/time is Long.MAX_VALUE, it is considered to mean
     * that unavailability is permanent and any request for this servlet will return
     * an SC_NOT_FOUND error.  If this date/time is in the future, any request for
     * this servlet will return an SC_SERVICE_UNAVAILABLE error.  If it is zero,
     * the servlet is currently available.
     */
    @Override
    public long getAvailable() {

        return (this.available);

    }


    /**
     * Set the available date/time for this servlet, in milliseconds since the
     * epoch.  If this date/time is Long.MAX_VALUE, it is considered to mean
     * that unavailability is permanent and any request for this servlet will return
     * an SC_NOT_FOUND error. If this date/time is in the future, any request for
     * this servlet will return an SC_SERVICE_UNAVAILABLE error.
     *
     * @param available The new available date/time
     */
    @Override
    public void setAvailable(long available) {

        long oldAvailable = this.available;
        if (available > System.currentTimeMillis())
            this.available = available;
        else
            this.available = 0L;
        support.firePropertyChange("available", Long.valueOf(oldAvailable),
                                   Long.valueOf(this.available));

    }


    /**
     * Return the number of active allocations of this servlet, even if they
     * are all for the same instance (as will be true for servlets that do
     * not implement <code>SingleThreadModel</code>.
     */
    public int getCountAllocated() {

        return (this.countAllocated.get());

    }


    /**
     * Return descriptive information about this Container implementation and
     * the corresponding version number, in the format
     * <code>&lt;description&gt;/&lt;version&gt;</code>.
     */
    @Override
    public String getInfo() {

        return (info);

    }


    /**
     * Return the InstanceSupport object for this Wrapper instance.
     */
    public InstanceSupport getInstanceSupport() {

        return (this.instanceSupport);

    }


    /**
     * Return the load-on-startup order value (negative value means
     * load on first call).
     */
    @Override
    public int getLoadOnStartup() {

        if (isJspServlet && loadOnStartup < 0) {
            /*
             * JspServlet must always be preloaded, because its instance is
             * used during registerJMX (when registering the JSP
             * monitoring mbean)
             */
             return Integer.MAX_VALUE;
        } else {
            return (this.loadOnStartup);
        }
    }


    /**
     * Set the load-on-startup order value (negative value means
     * load on first call).
     *
     * @param value New load-on-startup value
     */
    @Override
    public void setLoadOnStartup(int value) {

        int oldLoadOnStartup = this.loadOnStartup;
        this.loadOnStartup = value;
        support.firePropertyChange("loadOnStartup",
                                   Integer.valueOf(oldLoadOnStartup),
                                   Integer.valueOf(this.loadOnStartup));

    }



    /**
     * Set the load-on-startup order value from a (possibly null) string.
     * Per the specification, any missing or non-numeric value is converted
     * to a zero, so that this servlet will still be loaded at startup
     * time, but in an arbitrary order.
     *
     * @param value New load-on-startup value
     */
    public void setLoadOnStartupString(String value) {

        try {
            setLoadOnStartup(Integer.parseInt(value));
        } catch (NumberFormatException e) {
            setLoadOnStartup(0);
        }
    }

    public String getLoadOnStartupString() {
        return Integer.toString( getLoadOnStartup());
    }


    /**
     * Return maximum number of instances that will be allocated when a single
     * thread model servlet is used.
     */
    public int getMaxInstances() {

        return (this.maxInstances);

    }


    /**
     * Set the maximum number of instances that will be allocated when a single
     * thread model servlet is used.
     *
     * @param maxInstances New value of maxInstances
     */
    public void setMaxInstances(int maxInstances) {

        int oldMaxInstances = this.maxInstances;
        this.maxInstances = maxInstances;
        support.firePropertyChange("maxInstances", oldMaxInstances,
                                   this.maxInstances);

    }


    /**
     * Set the parent Container of this Wrapper, but only if it is a Context.
     *
     * @param container Proposed parent Container
     */
    @Override
    public void setParent(Container container) {

        if ((container != null) &&
            !(container instanceof Context))
            throw new IllegalArgumentException
                (sm.getString("standardWrapper.notContext"));
        if (container instanceof StandardContext) {
            swallowOutput = ((StandardContext)container).getSwallowOutput();
            unloadDelay = ((StandardContext)container).getUnloadDelay();
        }
        super.setParent(container);

    }


    /**
     * Return the run-as identity for this servlet.
     */
    @Override
    public String getRunAs() {

        return (this.runAs);

    }


    /**
     * Set the run-as identity for this servlet.
     *
     * @param runAs New run-as identity value
     */
    @Override
    public void setRunAs(String runAs) {

        String oldRunAs = this.runAs;
        this.runAs = runAs;
        support.firePropertyChange("runAs", oldRunAs, this.runAs);

    }


    /**
     * Return the fully qualified servlet class name for this servlet.
     */
    @Override
    public String getServletClass() {

        return (this.servletClass);

    }


    /**
     * Set the fully qualified servlet class name for this servlet.
     *
     * @param servletClass Servlet class name
     */
    @Override
    public void setServletClass(String servletClass) {

        String oldServletClass = this.servletClass;
        this.servletClass = servletClass;
        support.firePropertyChange("servletClass", oldServletClass,
                                   this.servletClass);
        if (Constants.JSP_SERVLET_CLASS.equals(servletClass)) {
            isJspServlet = true;
        }
    }



    /**
     * Set the name of this servlet.  This is an alias for the normal
     * <code>Container.setName()</code> method, and complements the
     * <code>getServletName()</code> method required by the
     * <code>ServletConfig</code> interface.
     *
     * @param name The new name of this servlet
     */
    public void setServletName(String name) {

        setName(name);

    }


    /**
     * Return <code>true</code> if the servlet class represented by this
     * component implements the <code>SingleThreadModel</code> interface.
     */
    public boolean isSingleThreadModel() {

        // Short-cuts
        // If singleThreadModel is true, must have already checked this
        // If instance != null, must have already loaded 
        if (singleThreadModel || instance != null) {
            return singleThreadModel;
        }
        
        // The logic to determine this safely is more complex than one might
        // expect. allocate() already has the necessary logic so re-use it.
        try {
            Servlet s = allocate();
            deallocate(s);
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
        }
        return (singleThreadModel);

    }


    /**
     * Is this servlet currently unavailable?
     */
    @Override
    public boolean isUnavailable() {

        if (!isEnabled())
            return true;
        else if (available == 0L)
            return false;
        else if (available <= System.currentTimeMillis()) {
            available = 0L;
            return false;
        } else
            return true;

    }


    /**
     * Gets the names of the methods supported by the underlying servlet.
     *
     * This is the same set of methods included in the Allow response header
     * in response to an OPTIONS request method processed by the underlying
     * servlet.
     *
     * @return Array of names of the methods supported by the underlying
     * servlet
     */
    @Override
    public String[] getServletMethods() throws ServletException {

        instance = loadServlet();
        
        Class<? extends Servlet> servletClazz = instance.getClass();
        if (!javax.servlet.http.HttpServlet.class.isAssignableFrom(
                                                        servletClazz)) {
            return DEFAULT_SERVLET_METHODS;
        }

        HashSet<String> allow = new HashSet<String>();
        allow.add("TRACE");
        allow.add("OPTIONS");

        Method[] methods = getAllDeclaredMethods(servletClazz);
        for (int i=0; methods != null && i<methods.length; i++) {
            Method m = methods[i];

            if (m.getName().equals("doGet")) {
                allow.add("GET");
                allow.add("HEAD");
            } else if (m.getName().equals("doPost")) {
                allow.add("POST");
            } else if (m.getName().equals("doPut")) {
                allow.add("PUT");
            } else if (m.getName().equals("doDelete")) {
                allow.add("DELETE");
            }
        }

        String[] methodNames = new String[allow.size()];
        return allow.toArray(methodNames);

    }


    /**
     * Return the associated servlet instance.
     */
    @Override
    public Servlet getServlet() {
        return instance;
    }
    
    
    /**
     * Set the associated servlet instance.
     */
    @Override
    public void setServlet(Servlet servlet) {
        instance = servlet;
    }

    
    /**
     * {@inheritDoc}
     */
    @Override
    public void setServletSecurityAnnotationScanRequired(boolean b) {
        this.servletSecurityAnnotationScanRequired = b;
    }

    // --------------------------------------------------------- Public Methods


    /**
     * Execute a periodic task, such as reloading, etc. This method will be
     * invoked inside the classloading context of this container. Unexpected
     * throwables will be caught and logged.
     */
    @Override
    public void backgroundProcess() {
        super.backgroundProcess();
        
        if (!getState().isAvailable())
            return;
        
        if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) {
            ((PeriodicEventListener) getServlet()).periodicEvent();
        }
    }
    
    
    /**
     * Extract the root cause from a servlet exception.
     * 
     * @param e The servlet exception
     */
    public static Throwable getRootCause(ServletException e) {
        Throwable rootCause = e;
        Throwable rootCauseCheck = null;
        // Extra aggressive rootCause finding
        int loops = 0;
        do {
            loops++;
            rootCauseCheck = rootCause.getCause();
            if (rootCauseCheck != null)
                rootCause = rootCauseCheck;
        } while (rootCauseCheck != null && (loops < 20));
        return rootCause;
    }


    /**
     * Refuse to add a child Container, because Wrappers are the lowest level
     * of the Container hierarchy.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {

        throw new IllegalStateException
            (sm.getString("standardWrapper.notChild"));

    }


    /**
     * Add a new servlet initialization parameter for this servlet.
     *
     * @param name Name of this initialization parameter to add
     * @param value Value of this initialization parameter to add
     */
    @Override
    public void addInitParameter(String name, String value) {

        try {
            parametersLock.writeLock().lock();
            parameters.put(name, value);
        } finally {
            parametersLock.writeLock().unlock();
        }
        fireContainerEvent("addInitParameter", name);

    }


    /**
     * Add a new listener interested in InstanceEvents.
     *
     * @param listener The new listener
     */
    @Override
    public void addInstanceListener(InstanceListener listener) {

        instanceSupport.addInstanceListener(listener);

    }


    /**
     * Add a mapping associated with the Wrapper.
     *
     * @param mapping The new wrapper mapping
     */
    @Override
    public void addMapping(String mapping) {

        try {
            mappingsLock.writeLock().lock();
            mappings.add(mapping);
        } finally {
            mappingsLock.writeLock().unlock();
        }
        if(parent.getState().equals(LifecycleState.STARTED))
            fireContainerEvent(ADD_MAPPING_EVENT, mapping);

    }


    /**
     * Add a new security role reference record to the set of records for
     * this servlet.
     *
     * @param name Role name used within this servlet
     * @param link Role name used within the web application
     */
    @Override
    public void addSecurityReference(String name, String link) {

        try {
            referencesLock.writeLock().lock();
            references.put(name, link);
        } finally {
            referencesLock.writeLock().unlock();
        }
        fireContainerEvent("addSecurityReference", name);

    }


    /**
     * Allocate an initialized instance of this Servlet that is ready to have
     * its <code>service()</code> method called.  If the servlet class does
     * not implement <code>SingleThreadModel</code>, the (only) initialized
     * instance may be returned immediately.  If the servlet class implements
     * <code>SingleThreadModel</code>, the Wrapper implementation must ensure
     * that this instance is not allocated again until it is deallocated by a
     * call to <code>deallocate()</code>.
     *
     * @exception ServletException if the servlet init() method threw
     *  an exception
     * @exception ServletException if a loading error occurs
     */
    @Override
    public Servlet allocate() throws ServletException {

        // If we are currently unloading this servlet, throw an exception
        if (unloading)
            throw new ServletException
              (sm.getString("standardWrapper.unloading", getName()));

        boolean newInstance = false;
        
        // If not SingleThreadedModel, return the same instance every time
        if (!singleThreadModel) {

            // Load and initialize our instance if necessary
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        try {
                            if (log.isDebugEnabled())
                                log.debug("Allocating non-STM instance");

                            instance = loadServlet();
                            if (!singleThreadModel) {
                                // For non-STM, increment here to prevent a race
                                // condition with unload. Bug 43683, test case
                                // #3
                                newInstance = true;
                                countAllocated.incrementAndGet();
                            }
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            ExceptionUtils.handleThrowable(e);
                            throw new ServletException
                                (sm.getString("standardWrapper.allocate"), e);
                        }
                    }
                }
            }

            if (!instanceInitialized) {
                initServlet(instance);
            }

            if (singleThreadModel) {
                if (newInstance) {
                    // Have to do this outside of the sync above to prevent a
                    // possible deadlock
                    synchronized (instancePool) {
                        instancePool.push(instance);
                        nInstances++;
                    }
                }
            } else {
                if (log.isTraceEnabled())
                    log.trace("  Returning non-STM instance");
                // For new instances, count will have been incremented at the
                // time of creation
                if (!newInstance) {
                    countAllocated.incrementAndGet();
                }
                return (instance);
            }
        }

        synchronized (instancePool) {

            while (countAllocated.get() >= nInstances) {
                // Allocate a new instance if possible, or else wait
                if (nInstances < maxInstances) {
                    try {
                        instancePool.push(loadServlet());
                        nInstances++;
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        ExceptionUtils.handleThrowable(e);
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
            }
            if (log.isTraceEnabled())
                log.trace("  Returning allocated STM instance");
            countAllocated.incrementAndGet();
            return instancePool.pop();

        }

    }


    /**
     * Return this previously allocated servlet to the pool of available
     * instances.  If this servlet class does not implement SingleThreadModel,
     * no action is actually required.
     *
     * @param servlet The servlet to be returned
     *
     * @exception ServletException if a deallocation error occurs
     */
    @Override
    public void deallocate(Servlet servlet) throws ServletException {

        // If not SingleThreadModel, no action is required
        if (!singleThreadModel) {
            countAllocated.decrementAndGet();
            return;
        }

        // Unlock and free this instance
        synchronized (instancePool) {
            countAllocated.decrementAndGet();
            instancePool.push(servlet);
            instancePool.notify();
        }

    }


    /**
     * Return the value for the specified initialization parameter name,
     * if any; otherwise return <code>null</code>.
     *
     * @param name Name of the requested initialization parameter
     */
    @Override
    public String findInitParameter(String name) {

        try {
            parametersLock.readLock().lock();
            return parameters.get(name);
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * Return the names of all defined initialization parameters for this
     * servlet.
     */
    @Override
    public String[] findInitParameters() {

        try {
            parametersLock.readLock().lock();
            String results[] = new String[parameters.size()];
            return parameters.keySet().toArray(results);
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * Return the mappings associated with this wrapper.
     */
    @Override
    public String[] findMappings() {

        try {
            mappingsLock.readLock().lock();
            return mappings.toArray(new String[mappings.size()]);
        } finally {
            mappingsLock.readLock().unlock();
        }

    }


    /**
     * Return the security role link for the specified security role
     * reference name, if any; otherwise return <code>null</code>.
     *
     * @param name Security role reference used within this servlet
     */
    @Override
    public String findSecurityReference(String name) {

        try {
            referencesLock.readLock().lock();
            return references.get(name);
        } finally {
            referencesLock.readLock().unlock();
        }

    }


    /**
     * Return the set of security role reference names associated with
     * this servlet, if any; otherwise return a zero-length array.
     */
    @Override
    public String[] findSecurityReferences() {

        try {
            referencesLock.readLock().lock();
            String results[] = new String[references.size()];
            return references.keySet().toArray(results);
        } finally {
            referencesLock.readLock().unlock();
        }

    }


    /**
     * FIXME: Fooling introspection ...
     */
    @Deprecated
    public Wrapper findMappingObject() {
        return (Wrapper) getMappingObject();
    }


    /**
     * Load and initialize an instance of this servlet, if there is not already
     * at least one initialized instance.  This can be used, for example, to
     * load servlets that are marked in the deployment descriptor to be loaded
     * at server startup time.
     * <p>
     * <b>IMPLEMENTATION NOTE</b>:  Servlets whose classnames begin with
     * <code>org.apache.catalina.</code> (so-called "container" servlets)
     * are loaded by the same classloader that loaded this class, rather than
     * the classloader for the current web application.
     * This gives such classes access to Catalina internals, which are
     * prevented for classes loaded for web applications.
     *
     * @exception ServletException if the servlet init() method threw
     *  an exception
     * @exception ServletException if some other loading problem occurs
     */
    @Override
    public synchronized void load() throws ServletException {
        instance = loadServlet();
        
        if (!instanceInitialized) {
            initServlet(instance);
        }

        if (isJspServlet) {
            StringBuilder oname =
                new StringBuilder(MBeanUtils.getDomain(getParent()));
            
            oname.append(":type=JspMonitor,name=");
            oname.append(getName());
            
            oname.append(getWebModuleKeyProperties());
            
            try {
                jspMonitorON = new ObjectName(oname.toString());
                Registry.getRegistry(null, null)
                    .registerComponent(instance, jspMonitorON, null);
            } catch( Exception ex ) {
                log.info("Error registering JSP monitoring with jmx " +
                         instance);
            }
        }
    }


    /**
     * Load and initialize an instance of this servlet, if there is not already
     * at least one initialized instance.  This can be used, for example, to
     * load servlets that are marked in the deployment descriptor to be loaded
     * at server startup time.
     */
    public synchronized Servlet loadServlet() throws ServletException {

        // Nothing to do if we already have an instance or an instance pool
        if (!singleThreadModel && (instance != null))
            return instance;

        PrintStream out = System.out;
        if (swallowOutput) {
            SystemLogHandler.startCapture();
        }

        Servlet servlet;
        try {
            long t1=System.currentTimeMillis();
            // Complain if no servlet class has been specified
            if (servletClass == null) {
                unavailable(null);
                throw new ServletException
                    (sm.getString("standardWrapper.notClass", getName()));
            }

            InstanceManager instanceManager = ((StandardContext)getParent()).getInstanceManager();
            try {
                servlet = (Servlet) instanceManager.newInstance(servletClass);
            } catch (ClassCastException e) {
                unavailable(null);
                // Restore the context ClassLoader
                throw new ServletException
                    (sm.getString("standardWrapper.notServlet", servletClass), e);
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                unavailable(null);

                // Added extra log statement for Bugzilla 36630:
                // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630
                if(log.isDebugEnabled()) {
                    log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
                }

                // Restore the context ClassLoader
                throw new ServletException
                    (sm.getString("standardWrapper.instantiate", servletClass), e);
            }

            if (multipartConfigElement == null) {
                MultipartConfig annotation =
                        servlet.getClass().getAnnotation(MultipartConfig.class);
                if (annotation != null) {
                    multipartConfigElement =
                            new MultipartConfigElement(annotation);
                }
            }

            processServletSecurityAnnotation(servlet.getClass());

            // Special handling for ContainerServlet instances
            if ((servlet instanceof ContainerServlet) &&
                    (isContainerProvidedServlet(servletClass) ||
                            ((Context) getParent()).getPrivileged() )) {
                ((ContainerServlet) servlet).setWrapper(this);
            }

            classLoadTime=(int) (System.currentTimeMillis() -t1);

            if (servlet instanceof SingleThreadModel) {
                if (instancePool == null) {
                    instancePool = new Stack<Servlet>();
                }
                singleThreadModel = true;
            }

            initServlet(servlet);

            fireContainerEvent("load", this);

            loadTime=System.currentTimeMillis() -t1;
        } finally {
            if (swallowOutput) {
                String log = SystemLogHandler.stopCapture();
                if (log != null && log.length() > 0) {
                    if (getServletContext() != null) {
                        getServletContext().log(log);
                    } else {
                        out.println(log);
                    }
                }
            }
        }
        return servlet;

    }

    /**
     * {@inheritDoc}
     * @throws ClassNotFoundException 
     */
    @Override
    public void servletSecurityAnnotationScan() throws ServletException {
        if (getServlet() == null) {
            Class<?> clazz = null;
            try {
                clazz = getParent().getLoader().getClassLoader().loadClass(
                        getServletClass());
                processServletSecurityAnnotation(clazz);
            } catch (ClassNotFoundException e) {
                // Safe to ignore. No class means no annotations to process
            }
        } else {
            if (servletSecurityAnnotationScanRequired) {
                processServletSecurityAnnotation(getServlet().getClass());
            }
        }
    }

    private void processServletSecurityAnnotation(Class<?> clazz) {
        // Calling this twice isn't harmful so no syncs
        servletSecurityAnnotationScanRequired = false;

        Context ctxt = (Context) getParent();
        
        if (ctxt.getIgnoreAnnotations()) {
            return;
        }

        ServletSecurity secAnnotation =
            clazz.getAnnotation(ServletSecurity.class);
        if (secAnnotation != null) {
            ctxt.addServletSecurity(
                    new ApplicationServletRegistration(this, ctxt),
                    new ServletSecurityElement(secAnnotation));
        }
    }

    private synchronized void initServlet(Servlet servlet)
            throws ServletException {
        
        if (instanceInitialized && !singleThreadModel) return;

        // Call the initialization method of this servlet
        try {
            instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
                                              servlet);

            if( Globals.IS_SECURITY_ENABLED) {

                Object[] args = new Object[]{(facade)};
                SecurityUtil.doAsPrivilege("init",
                                           servlet,
                                           classType,
                                           args);
                args = null;
            } else {
                servlet.init(facade);
            }

            instanceInitialized = true;

            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet);
        } catch (UnavailableException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw f;
        } catch (Throwable f) {
            ExceptionUtils.handleThrowable(f);
            getServletContext().log("StandardWrapper.Throwable", f );
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw new ServletException
                (sm.getString("standardWrapper.initException", getName()), f);
        }
    }

    /**
     * Remove the specified initialization parameter from this servlet.
     *
     * @param name Name of the initialization parameter to remove
     */
    @Override
    public void removeInitParameter(String name) {

        try {
            parametersLock.writeLock().lock();
            parameters.remove(name);
        } finally {
            parametersLock.writeLock().unlock();
        }
        fireContainerEvent("removeInitParameter", name);

    }


    /**
     * Remove a listener no longer interested in InstanceEvents.
     *
     * @param listener The listener to remove
     */
    @Override
    public void removeInstanceListener(InstanceListener listener) {

        instanceSupport.removeInstanceListener(listener);

    }


    /**
     * Remove a mapping associated with the wrapper.
     *
     * @param mapping The pattern to remove
     */
    @Override
    public void removeMapping(String mapping) {

        try {
            mappingsLock.writeLock().lock();
            mappings.remove(mapping);
        } finally {
            mappingsLock.writeLock().unlock();
        }
        if(parent.getState().equals(LifecycleState.STARTED))
            fireContainerEvent(REMOVE_MAPPING_EVENT, mapping);

    }


    /**
     * Remove any security role reference for the specified role name.
     *
     * @param name Security role used within this servlet to be removed
     */
    @Override
    public void removeSecurityReference(String name) {

        try {
            referencesLock.writeLock().lock();
            references.remove(name);
        } finally {
            referencesLock.writeLock().unlock();
        }
        fireContainerEvent("removeSecurityReference", name);

    }


    /**
     * Return a String representation of this component.
     */
    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();
        if (getParent() != null) {
            sb.append(getParent().toString());
            sb.append(".");
        }
        sb.append("StandardWrapper[");
        sb.append(getName());
        sb.append("]");
        return (sb.toString());

    }


    /**
     * Process an UnavailableException, marking this servlet as unavailable
     * for the specified amount of time.
     *
     * @param unavailable The exception that occurred, or <code>null</code>
     *  to mark this servlet as permanently unavailable
     */
    @Override
    public void unavailable(UnavailableException unavailable) {
        getServletContext().log(sm.getString("standardWrapper.unavailable", getName()));
        if (unavailable == null)
            setAvailable(Long.MAX_VALUE);
        else if (unavailable.isPermanent())
            setAvailable(Long.MAX_VALUE);
        else {
            int unavailableSeconds = unavailable.getUnavailableSeconds();
            if (unavailableSeconds <= 0)
                unavailableSeconds = 60;        // Arbitrary default
            setAvailable(System.currentTimeMillis() +
                         (unavailableSeconds * 1000L));
        }

    }


    /**
     * Unload all initialized instances of this servlet, after calling the
     * <code>destroy()</code> method for each instance.  This can be used,
     * for example, prior to shutting down the entire servlet engine, or
     * prior to reloading all of the classes from the Loader associated with
     * our Loader's repository.
     *
     * @exception ServletException if an exception is thrown by the
     *  destroy() method
     */
    @Override
    public synchronized void unload() throws ServletException {

        // Nothing to do if we have never loaded the instance
        if (!singleThreadModel && (instance == null))
            return;
        unloading = true;

        // Loaf a while if the current instance is allocated
        // (possibly more than once if non-STM)
        if (countAllocated.get() > 0) {
            int nRetries = 0;
            long delay = unloadDelay / 20;
            while ((nRetries < 21) && (countAllocated.get() > 0)) {
                if ((nRetries % 10) == 0) {
                    log.info(sm.getString("standardWrapper.waiting",
                                          countAllocated.toString()));
                }
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    // Ignore
                }
                nRetries++;
            }
        }

        if (instanceInitialized) {
            PrintStream out = System.out;
            if (swallowOutput) {
                SystemLogHandler.startCapture();
            }
    
            // Call the servlet destroy() method
            try {
                instanceSupport.fireInstanceEvent
                  (InstanceEvent.BEFORE_DESTROY_EVENT, instance);
    
                if( Globals.IS_SECURITY_ENABLED) {
                    SecurityUtil.doAsPrivilege("destroy",
                                               instance);
                    SecurityUtil.remove(instance);                           
                } else {
                    instance.destroy();
                }
                
                instanceSupport.fireInstanceEvent
                  (InstanceEvent.AFTER_DESTROY_EVENT, instance);
    
                // Annotation processing
                if (!((Context) getParent()).getIgnoreAnnotations()) {
                   ((StandardContext)getParent()).getInstanceManager().destroyInstance(instance);
                }
    
            } catch (Throwable t) {
                t = ExceptionUtils.unwrapInvocationTargetException(t);
                ExceptionUtils.handleThrowable(t);
                instanceSupport.fireInstanceEvent
                  (InstanceEvent.AFTER_DESTROY_EVENT, instance, t);
                instance = null;
                instancePool = null;
                nInstances = 0;
                fireContainerEvent("unload", this);
                unloading = false;
                throw new ServletException
                    (sm.getString("standardWrapper.destroyException", getName()),
                     t);
            } finally {
                // Write captured output
                if (swallowOutput) {
                    String log = SystemLogHandler.stopCapture();
                    if (log != null && log.length() > 0) {
                        if (getServletContext() != null) {
                            getServletContext().log(log);
                        } else {
                            out.println(log);
                        }
                    }
                }
            }
        }

        // Deregister the destroyed instance
        instance = null;

        if (isJspServlet && jspMonitorON != null ) {
            Registry.getRegistry(null, null).unregisterComponent(jspMonitorON);
        }

        if (singleThreadModel && (instancePool != null)) {
            try {
                while (!instancePool.isEmpty()) {
                    Servlet s = instancePool.pop();
                    if (Globals.IS_SECURITY_ENABLED) {
                        SecurityUtil.doAsPrivilege("destroy", s);
                        SecurityUtil.remove(instance);                           
                    } else {
                        s.destroy();
                    }
                    // Annotation processing
                    if (!((Context) getParent()).getIgnoreAnnotations()) {
                       ((StandardContext)getParent()).getInstanceManager().destroyInstance(s);
                    }
                }
            } catch (Throwable t) {
                t = ExceptionUtils.unwrapInvocationTargetException(t);
                ExceptionUtils.handleThrowable(t);
                instancePool = null;
                nInstances = 0;
                unloading = false;
                fireContainerEvent("unload", this);
                throw new ServletException
                    (sm.getString("standardWrapper.destroyException",
                                  getName()), t);
            }
            instancePool = null;
            nInstances = 0;
        }

        singleThreadModel = false;

        unloading = false;
        fireContainerEvent("unload", this);

    }


    // -------------------------------------------------- ServletConfig Methods


    /**
     * Return the initialization parameter value for the specified name,
     * if any; otherwise return <code>null</code>.
     *
     * @param name Name of the initialization parameter to retrieve
     */
    @Override
    public String getInitParameter(String name) {

        return (findInitParameter(name));

    }


    /**
     * Return the set of initialization parameter names defined for this
     * servlet.  If none are defined, an empty Enumeration is returned.
     */
    @Override
    public Enumeration<String> getInitParameterNames() {

        try {
            parametersLock.readLock().lock();
            return Collections.enumeration(parameters.keySet());
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * Return the servlet context with which this servlet is associated.
     */
    @Override
    public ServletContext getServletContext() {

        if (parent == null)
            return (null);
        else if (!(parent instanceof Context))
            return (null);
        else
            return (((Context) parent).getServletContext());

    }


    /**
     * Return the name of this servlet.
     */
    @Override
    public String getServletName() {

        return (getName());

    }

    public long getProcessingTime() {
        return swValve.getProcessingTime();
    }

    @Deprecated
    public void setProcessingTime(long processingTime) {
        swValve.setProcessingTime(processingTime);
    }

    public long getMaxTime() {
        return swValve.getMaxTime();
    }

    @Deprecated
    public void setMaxTime(long maxTime) {
        swValve.setMaxTime(maxTime);
    }

    public long getMinTime() {
        return swValve.getMinTime();
    }

    @Deprecated
    public void setMinTime(long minTime) {
        swValve.setMinTime(minTime);
    }

    public int getRequestCount() {
        return swValve.getRequestCount();
    }

    @Deprecated
    public void setRequestCount(int requestCount) {
        swValve.setRequestCount(requestCount);
    }

    public int getErrorCount() {
        return swValve.getErrorCount();
    }

    @Deprecated
    public void setErrorCount(int errorCount) {
           swValve.setErrorCount(errorCount);
    }

    /**
     * Increment the error count used for monitoring.
     */
    @Override
    public void incrementErrorCount(){
        swValve.setErrorCount(swValve.getErrorCount() + 1);
    }

    public long getLoadTime() {
        return loadTime;
    }

    @Deprecated
    public void setLoadTime(long loadTime) {
        this.loadTime = loadTime;
    }

    public int getClassLoadTime() {
        return classLoadTime;
    }

    @Override
    public MultipartConfigElement getMultipartConfigElement() {
        return multipartConfigElement;
    }

    @Override
    public void setMultipartConfigElement(
            MultipartConfigElement multipartConfigElement) {
        this.multipartConfigElement = multipartConfigElement;
    }

    @Override
    public boolean isAsyncSupported() {
        return asyncSupported;
    }
    
    @Override
    public void setAsyncSupported(boolean asyncSupported) {
        this.asyncSupported = asyncSupported;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
    
    @Override
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    // -------------------------------------------------------- Package Methods


    // -------------------------------------------------------- protected Methods


    /**
     * Return <code>true</code> if the specified class name represents a
     * container provided servlet class that should be loaded by the
     * server class loader.
     *
     * @param classname Name of the class to be checked
     */
    protected boolean isContainerProvidedServlet(String classname) {

        if (classname.startsWith("org.apache.catalina.")) {
            return (true);
        }
        try {
            Class<?> clazz =
                this.getClass().getClassLoader().loadClass(classname);
            return (ContainerServlet.class.isAssignableFrom(clazz));
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            return (false);
        }

    }


    protected Method[] getAllDeclaredMethods(Class<?> c) {

        if (c.equals(javax.servlet.http.HttpServlet.class)) {
            return null;
        }

        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());

        Method[] thisMethods = c.getDeclaredMethods();
        if (thisMethods == null) {
            return parentMethods;
        }

        if ((parentMethods != null) && (parentMethods.length > 0)) {
            Method[] allMethods =
                new Method[parentMethods.length + thisMethods.length];
            System.arraycopy(parentMethods, 0, allMethods, 0,
                             parentMethods.length);
            System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
                             thisMethods.length);

            thisMethods = allMethods;
        }

        return thisMethods;
    }


    // ------------------------------------------------------ Lifecycle Methods


    /**
     * Start this component and implement the requirements
     * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    @Override
    protected synchronized void startInternal() throws LifecycleException {
    
        // Send j2ee.state.starting notification 
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting", 
                                                        this.getObjectName(), 
                                                        sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        // Start up this component
        super.startInternal();

        setAvailable(0L);

        // Send j2ee.state.running notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.running", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

    }


    /**
     * Stop this component and implement the requirements
     * of {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error
     *  that prevents this component from being used
     */
    @Override
    protected synchronized void stopInternal() throws LifecycleException {

        setAvailable(Long.MAX_VALUE);
        
        // Send j2ee.state.stopping notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.stopping", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        // Shut down our servlet instance (if it has been initialized)
        try {
            unload();
        } catch (ServletException e) {
            getServletContext().log(sm.getString
                      ("standardWrapper.unloadException", getName()), e);
        }

        // Shut down this component
        super.stopInternal();

        // Send j2ee.state.stoppped notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.stopped", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        // Send j2ee.object.deleted notification 
        Notification notification = 
            new Notification("j2ee.object.deleted", this.getObjectName(), 
                            sequenceNumber++);
        broadcaster.sendNotification(notification);

    }

    
    @Override
    protected String getObjectNameKeyProperties() {

        StringBuilder keyProperties =
            new StringBuilder("j2eeType=Servlet,name=");
        
        keyProperties.append(getName());
        
        keyProperties.append(getWebModuleKeyProperties());

        return keyProperties.toString();
    }
        

    private String getWebModuleKeyProperties() {
        
        StringBuilder keyProperties = new StringBuilder(",WebModule=//");
        String hostName = getParent().getParent().getName();
        if (hostName == null) {
            keyProperties.append("DEFAULT");
        } else {
            keyProperties.append(hostName);
        }
        
        String contextName = ((Context) getParent()).getName();
        if (!contextName.startsWith("/")) {
            keyProperties.append('/');
        }
        keyProperties.append(contextName);

        StandardContext ctx = null;
        if (parent instanceof StandardContext) {
            ctx = (StandardContext) getParent();
        }
        
        keyProperties.append(",J2EEApplication=");
        if (ctx == null) {
            keyProperties.append("none");
        } else {
            keyProperties.append(ctx.getJ2EEApplication());
        }
        keyProperties.append(",J2EEServer=");
        if (ctx == null) {
            keyProperties.append("none");
        } else {
            keyProperties.append(ctx.getJ2EEServer());
        }
        
        return keyProperties.toString();
    }
    

    /**
     * JSR 77. Always return false.
     */
    public boolean isStateManageable() {
        return false;
    }
    

    /* Remove a JMX notficationListener 
     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
     */
    @Override
    public void removeNotificationListener(NotificationListener listener, 
            NotificationFilter filter, Object object) throws ListenerNotFoundException {
        broadcaster.removeNotificationListener(listener,filter,object);
    }
    
    protected MBeanNotificationInfo[] notificationInfo;
    
    /* Get JMX Broadcaster Info
     * @TODO use StringManager for international support!
     * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
     */
    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {

        if(notificationInfo == null) {
            notificationInfo = new MBeanNotificationInfo[]{
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.object.created"},
                    Notification.class.getName(),
                    "servlet is created"
                    ), 
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.state.starting"},
                    Notification.class.getName(),
                    "servlet is starting"
                    ),
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.state.running"},
                    Notification.class.getName(),
                    "servlet is running"
                    ),
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.state.stopped"},
                    Notification.class.getName(),
                    "servlet start to stopped"
                    ),
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.object.stopped"},
                    Notification.class.getName(),
                    "servlet is stopped"
                    ),
                    new MBeanNotificationInfo(new String[] {
                    "j2ee.object.deleted"},
                    Notification.class.getName(),
                    "servlet is deleted"
                    )
            };
        }

        return notificationInfo;
    }
    
    
    /* Add a JMX-NotificationListener
     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
     */
    @Override
    public void addNotificationListener(NotificationListener listener, 
            NotificationFilter filter, Object object) throws IllegalArgumentException {
        broadcaster.addNotificationListener(listener,filter,object);
    }
    
    
    /**
     * Remove a JMX-NotificationListener 
     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
     */
    @Override
    public void removeNotificationListener(NotificationListener listener) 
        throws ListenerNotFoundException {
        broadcaster.removeNotificationListener(listener);
    }
    
    
     // ------------------------------------------------------------- Attributes
        
        
    @Deprecated
    public boolean isEventProvider() {
        return false;
    }
    
    @Deprecated
    public boolean isStatisticsProvider() {
        return false;
    }
}

...
Рейтинг: 0 / 0
11.06.2012, 09:38:57
    #37834090
Kachalov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-voidВсе это настраивается через StandardWrapper

- где настраивается? (собственно об этом и был вопрос)

ivanov-voidно смысла большого не имеет, поскольку с 2003 года интерфейс SingleThreadModel is deprecated, и при необходимости сервлет нужно писать потокобезопасным, организуя свои стратегии рандеву.

- лирика, уверен что все кто отметился в этой теме знакомы с актуальным ServletAPI и знают смысл слова deprecated
...
Рейтинг: 0 / 0
11.06.2012, 10:05:13
    #37834102
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Kachalov,

Вот здесь -
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
...
   /**
     * Set the maximum number of instances that will be allocated when a single
     * thread model servlet is used.
     *
     * @param maxInstances New value of maxInstances
     */
    public void setMaxInstances(int maxInstances) {

        int oldMaxInstances = this.maxInstances;
        this.maxInstances = maxInstances;
        support.firePropertyChange("maxInstances", oldMaxInstances,
                                   this.maxInstances);

    }
...



Дефолтная настройка -

Код: java
1.
2.
3.
4.
5.
6.
7.
   
...
    /**
     * Maximum number of STM instances.
     */
    protected int maxInstances = 20;
...
...
Рейтинг: 0 / 0
11.06.2012, 11:56:14
    #37834197
Kachalov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-voidВот здесь -

- думаю большинство пользователей Tomcat не собирают его из исходников. Можете объяснить для дураков в каком конфигурационном файле и в каком свойстве эта настройка задается? Ссылки на документацию Tomcat приветствуются ;)
...
Рейтинг: 0 / 0
11.06.2012, 14:38:56
    #37834338
ivanov-void
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
Kachalov,

Предлагаю интерпретировать этот вариант решения-
http://stackoverflow.com/questions/6851111/how-to-configure-the-maximum-pool-size-of-servlets-implementing-singlethreadmode

В процессе инициализации сервлета, контейнер вызывает метод init() , который инициализирует объект, имплементирующий ServletConfig , через который можно обратиться к параметрам инициализации, определенным в дескрипторе развертывания.

Поскольку для настройки числа числа экземпляров сервлета никаких xml- конфигураций не предусмотрено, мы добавляем эту настройку программно, переопределяя метод init() . В org.apache.catalina.core есть фасад для StandardWrapper - StandardWrapperFacade , из которого мы рефлексивно получаем приватное поле config типа ServletConfig :

Код: java
1.
2.
3.
...
Field config = StandardWrapperFacade.class.getDeclaredField("config");
...



Получаем доступ к приватному полю:
Код: java
1.
2.
3.
...
config.setAccessible(true);
...



В том же пакете org.apache.catalina.core находится StandardWrapper , которым оборачиваем наш объект,
инкапсулирующий параметры инициализации:
Код: java
1.
2.
3.
...
StandardWrapper standardWrapper = (StandardWrapper) config.get(getServletConfig());
...



Устанавливаем максимальное число экземпляров, определяющее верхнюю границу пула:
Код: java
1.
2.
3.
...
standardWrapper.setMaxInstances(...N.....);
...



"Дурак — всякий инакомыслящий" Г. Флобер
...
Рейтинг: 0 / 0
11.06.2012, 20:43:11
    #37834686
Kachalov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Количество инстансов сервлета в Tomcat
ivanov-voidдля настройки числа числа экземпляров сервлета никаких xml- конфигураций не предусмотрено
- это и есть ответ на вопрос который я задавал :) Устанавливать количество экземпляров сервлета в Tomcat и использовать SingleThreadedModel я лично не планирую. Просто хотелось получить от сообщества поддержку при обсуждении спорного вопроса о наличии или отсутствии в Tomcat настроек регулирующих количество инстансов сервлета. Спасибо за активное участие!
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Количество инстансов сервлета в Tomcat / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]