KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > cluster > Server


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.cluster;
31
32 import com.caucho.config.ConfigException;
33 import com.caucho.config.SchemaBean;
34 import com.caucho.config.types.Bytes;
35 import com.caucho.config.types.Period;
36 import com.caucho.jca.ResourceManagerImpl;
37 import com.caucho.lifecycle.Lifecycle;
38 import com.caucho.loader.ClassLoaderListener;
39 import com.caucho.loader.DynamicClassLoader;
40 import com.caucho.loader.Environment;
41 import com.caucho.loader.EnvironmentBean;
42 import com.caucho.loader.EnvironmentClassLoader;
43 import com.caucho.loader.EnvironmentLocal;
44 import com.caucho.make.AlwaysModified;
45 import com.caucho.management.server.ServerMXBean;
46 import com.caucho.security.PermissionManager;
47 import com.caucho.server.cache.AbstractCache;
48 import com.caucho.server.dispatch.ErrorFilterChain;
49 import com.caucho.server.dispatch.ExceptionFilterChain;
50 import com.caucho.server.dispatch.Invocation;
51 import com.caucho.server.dispatch.InvocationMatcher;
52 import com.caucho.server.e_app.EarConfig;
53 import com.caucho.server.host.Host;
54 import com.caucho.server.host.HostConfig;
55 import com.caucho.server.host.HostContainer;
56 import com.caucho.server.host.HostController;
57 import com.caucho.server.host.HostExpandDeployGenerator;
58 import com.caucho.server.log.AccessLog;
59 import com.caucho.server.port.AbstractSelectManager;
60 import com.caucho.server.port.Port;
61 import com.caucho.server.port.ProtocolDispatchServer;
62 import com.caucho.server.resin.Resin;
63 import com.caucho.server.webapp.ErrorPage;
64 import com.caucho.server.webapp.RewriteInvocation;
65 import com.caucho.server.webapp.WebApp;
66 import com.caucho.server.webapp.WebAppConfig;
67 import com.caucho.util.Alarm;
68 import com.caucho.util.AlarmListener;
69 import com.caucho.util.L10N;
70 import com.caucho.util.ThreadPool;
71 import com.caucho.vfs.Path;
72 import com.caucho.vfs.Vfs;
73
74 import javax.annotation.PostConstruct;
75 import javax.resource.spi.ResourceAdapter JavaDoc;
76 import javax.servlet.http.HttpServletResponse JavaDoc;
77 import java.lang.reflect.Method JavaDoc;
78 import java.util.ArrayList JavaDoc;
79 import java.util.Collection JavaDoc;
80 import java.util.Collections JavaDoc;
81 import java.util.logging.Level JavaDoc;
82 import java.util.logging.Logger JavaDoc;
83 import java.util.regex.Matcher JavaDoc;
84 import java.util.regex.Pattern JavaDoc;
85
86 public class Server extends ProtocolDispatchServer
87   implements EnvironmentBean, SchemaBean, AlarmListener,
88              ClassLoaderListener {
89   private static final L10N L = new L10N(Server.class);
90   private static final Logger JavaDoc log
91     = Logger.getLogger(Server.class.getName());
92
93   private static final long ALARM_INTERVAL = 60000;
94
95   private static final EnvironmentLocal<String JavaDoc> _serverIdLocal
96     = new EnvironmentLocal<String JavaDoc>("caucho.server-id");
97
98   private final ClusterServer _clusterServer;
99   private final Resin _resin;
100   
101   private EnvironmentClassLoader _classLoader;
102
103   private Throwable JavaDoc _configException;
104
105   private HostContainer _hostContainer;
106
107   private String JavaDoc _serverHeader = "Resin/" + com.caucho.Version.VERSION;
108
109   private String JavaDoc _url = "";
110
111   private int _srunCount;
112
113   private AccessLog _accessLog;
114
115   private long _waitForActiveTime = 10000L;
116
117   // <server> configuration
118
private int _acceptListenBacklog = 100;
119   
120   private int _acceptThreadMin = 5;
121   private int _acceptThreadMax = 10;
122
123   private int _keepaliveMax = 128;
124   
125   private long _keepaliveTimeout = 15000;
126   
127   private boolean _keepaliveSelectEnable = true;
128   private long _keepaliveSelectThreadTimeout = 1000;
129
130   private long _memoryFreeMin = 1024 * 1024;
131   
132   private long _socketTimeout = 65000L;
133   
134   private long _shutdownWaitMax = 60 * 1000;
135   
136   private int _threadMax = 4096;
137   private int _threadIdleMin = 5;
138   private int _threadIdleMax = 10;
139
140   // <cluster> configuration
141

142   private String JavaDoc _connectionErrorPage;
143
144   private ServerAdmin _admin;
145
146   private Alarm _alarm;
147   private AbstractCache _cache;
148
149   private boolean _isBindPortsAtEnd;
150   private volatile boolean _isStartedPorts;
151
152   private long _startTime;
153
154   private final Lifecycle _lifecycle;
155
156   /**
157    * Creates a new servlet server.
158    */

159   public Server(ClusterServer clusterServer)
160   {
161     if (clusterServer == null)
162       throw new NullPointerException JavaDoc();
163     
164     _clusterServer = clusterServer;
165     _resin = _clusterServer.getCluster().getResin();
166
167     try {
168       Thread JavaDoc thread = Thread.currentThread();
169
170       ClassLoader JavaDoc loader = clusterServer.getCluster().getClassLoader();
171       _classLoader = (EnvironmentClassLoader) loader;
172
173       Environment.addClassLoaderListener(this, _classLoader);
174
175       PermissionManager permissionManager = new PermissionManager();
176       PermissionManager.setPermissionManager(permissionManager);
177
178       ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
179
180       try {
181         thread.setContextClassLoader(_classLoader);
182     
183     _serverIdLocal.set(_clusterServer.getId());
184
185         _hostContainer = new HostContainer();
186         _hostContainer.setClassLoader(_classLoader);
187         _hostContainer.setDispatchServer(this);
188
189     _clusterServer.getServerProgram().configure(this);
190
191     _admin = new ServerAdmin(this);
192     
193     _alarm = new Alarm(this);
194       } finally {
195         thread.setContextClassLoader(oldLoader);
196       }
197     } catch (Throwable JavaDoc e) {
198       log.log(Level.WARNING, e.toString(), e);
199
200       _configException = e;
201     } finally {
202       _lifecycle = new Lifecycle(log, toString(), Level.INFO);
203     }
204   }
205
206   /**
207    * Returns the classLoader
208    */

209   public ClassLoader JavaDoc getClassLoader()
210   {
211     return _classLoader;
212   }
213
214   /**
215    * Returns the configuration exception
216    */

217   public Throwable JavaDoc getConfigException()
218   {
219     return _configException;
220   }
221
222   /**
223    * Returns the configuration instance.
224    */

225   public void setConfigException(Throwable JavaDoc exn)
226   {
227     _configException = exn;
228   }
229
230   //
231
// Configuration from <server>
232
//
233

234   /**
235    * Sets the socket's listen property
236    */

237   public void setAcceptListenBacklog(int backlog)
238   {
239     _acceptListenBacklog = backlog;
240   }
241
242   /**
243    * Gets the socket's listen property
244    */

245   public int getAcceptListenBacklog()
246   {
247     return _acceptListenBacklog;
248   }
249
250   /**
251    * Sets the minimum spare listen.
252    */

253   public void setAcceptThreadMin(int minSpare)
254     throws ConfigException
255   {
256     if (minSpare < 1)
257       throw new ConfigException(L.l("accept-thread-max must be at least 1."));
258
259     _acceptThreadMin = minSpare;
260   }
261
262   /**
263    * Gets the minimum spare listen.
264    */

265   public int getAcceptThreadMin()
266   {
267     return _acceptThreadMin;
268   }
269
270   /**
271    * Sets the maximum spare listen.
272    */

273   public void setAcceptThreadMax(int maxSpare)
274     throws ConfigException
275   {
276     if (maxSpare < 1)
277       throw new ConfigException(L.l("accept-thread-max must be at least 1."));
278
279     _acceptThreadMax = maxSpare;
280   }
281
282   /**
283    * Sets the maximum spare listen.
284    */

285   public int getAcceptThreadMax()
286   {
287     return _acceptThreadMax;
288   }
289
290   /**
291    * Sets the minimum free memory after a GC
292    */

293   public void setMemoryFreeMin(Bytes min)
294   {
295     _memoryFreeMin = min.getBytes();
296   }
297
298   /**
299    * Sets the minimum free memory after a GC
300    */

301   public long getMemoryFreeMin()
302   {
303     return _memoryFreeMin;
304   }
305
306   /**
307    * Sets the maximum keepalive
308    */

309   public void setKeepaliveMax(int max)
310   {
311     _keepaliveMax = max;
312   }
313
314   /**
315    * Returns the thread-based keepalive max.
316    *
317    * @return the keepalive max.
318    */

319   public int getKeepaliveMax()
320   {
321     return _keepaliveMax;
322   }
323
324   /**
325    * Sets the keepalive timeout
326    */

327   public void setKeepaliveTimeout(Period period)
328   {
329     _keepaliveTimeout = period.getPeriod();
330   }
331
332   /**
333    * Sets the keepalive timeout
334    */

335   public long getKeepaliveTimeout()
336   {
337     return _keepaliveTimeout;
338   }
339
340   /**
341    * Sets the select-based keepalive timeout
342    */

343   public void setKeepaliveSelectEnable(boolean enable)
344   {
345     _keepaliveSelectEnable = enable;
346   }
347
348   /**
349    * Gets the select-based keepalive timeout
350    */

351   public boolean isKeepaliveSelectEnable()
352   {
353     return _keepaliveSelectEnable;
354   }
355
356   /**
357    * Sets the select-based keepalive timeout
358    */

359   public void getKeepaliveSelectThreadTimeout(Period period)
360   {
361     _keepaliveSelectThreadTimeout = period.getPeriod();
362   }
363
364   /**
365    * Sets the select-based keepalive timeout
366    */

367   public long getKeepaliveSelectThreadTimeout()
368   {
369     return _keepaliveSelectThreadTimeout;
370   }
371
372   /**
373    * Sets the max wait time for shutdown.
374    */

375   public void setShutdownWaitMax(Period waitTime)
376   {
377     _shutdownWaitMax = waitTime.getPeriod();
378   }
379
380   /**
381    * Gets the max wait time for a shutdown.
382    */

383   public long getShutdownWaitMax()
384   {
385     return _shutdownWaitMax;
386   }
387
388   /**
389    * Sets the default read/write timeout for the request sockets.
390    */

391   public void setSocketTimeout(Period period)
392   {
393     _socketTimeout = period.getPeriod();
394   }
395
396   /**
397    * Gets the read timeout for the request sockets.
398    */

399   public long getSocketTimeout()
400   {
401     return _socketTimeout;
402   }
403
404   /**
405    * Sets the maximum thread-based keepalive
406    */

407   public void setThreadMax(int max)
408   {
409     if (max < 0)
410       throw new ConfigException(L.l("<thread-max> ({0}) must be greater than zero.",
411                     max));
412     
413     _threadMax = max;
414   }
415
416   /**
417    * Sets the minimum number of idle threads in the thread pool.
418    */

419   public void setThreadIdleMin(int min)
420   {
421     _threadIdleMin = min;
422   }
423
424   /**
425    * Sets the maximum number of idle threads in the thread pool.
426    */

427   public void setThreadIdleMax(int max)
428   {
429     _threadIdleMax = max;
430   }
431
432   //
433
// Configuration from <cluster>
434
//
435

436   /**
437    * Sets the connection error page.
438    */

439   public void setConnectionErrorPage(String JavaDoc errorPage)
440   {
441     _connectionErrorPage = errorPage;
442   }
443
444   /**
445    * Gets the connection error page.
446    */

447   public String JavaDoc getConnectionErrorPage()
448   {
449     return _connectionErrorPage;
450   }
451
452   /**
453    * Return true if idle.
454    */

455   public boolean isDeployError()
456   {
457     return _configException != null;
458   }
459
460   /**
461    * Returns the relax schema.
462    */

463   public String JavaDoc getSchema()
464   {
465     return "com/caucho/server/resin/cluster.rnc";
466   }
467
468   /**
469    * Returns the id.
470    */

471   public String JavaDoc getServerId()
472   {
473     return _clusterServer.getId();
474   }
475
476   /**
477    * Sets the root directory.
478    */

479   public void setRootDirectory(Path path)
480   {
481     _hostContainer.setRootDirectory(path);
482
483     Vfs.setPwd(path, _classLoader);
484   }
485
486   /**
487    * Sets the root directory.
488    */

489   public Path getRootDirectory()
490   {
491     return _hostContainer.getRootDirectory();
492   }
493
494   /**
495    * Sets the root directory.
496    */

497   public void setRootDir(Path path)
498   {
499     setRootDirectory(path);
500   }
501
502   /**
503    * Sets the server header.
504    */

505   public void setServerHeader(String JavaDoc server)
506   {
507     _serverHeader = server;
508   }
509
510   /**
511    * Gets the server header.
512    */

513   public String JavaDoc getServerHeader()
514   {
515     return _serverHeader;
516   }
517
518   /**
519    * Adds a WebAppDefault.
520    */

521   public void addWebAppDefault(WebAppConfig init)
522   {
523     _hostContainer.addWebAppDefault(init);
524   }
525
526   /**
527    * Adds an EarDefault
528    */

529   public void addEarDefault(EarConfig config)
530   {
531     _hostContainer.addEarDefault(config);
532   }
533
534   /**
535    * Adds a HostDefault.
536    */

537   public void addHostDefault(HostConfig init)
538   {
539     _hostContainer.addHostDefault(init);
540   }
541
542   /**
543    * Adds a HostDeploy.
544    */

545   public HostExpandDeployGenerator createHostDeploy()
546   {
547     return _hostContainer.createHostDeploy();
548   }
549
550   /**
551    * Adds a HostDeploy.
552    */

553   public void addHostDeploy(HostExpandDeployGenerator deploy)
554   {
555     _hostContainer.addHostDeploy(deploy);
556   }
557
558   /**
559    * Adds the host.
560    */

561   public void addHost(HostConfig host)
562     throws Exception JavaDoc
563   {
564     _hostContainer.addHost(host);
565   }
566
567   /**
568    * Returns the cluster.
569    */

570   public Cluster getCluster()
571   {
572     return _clusterServer.getCluster();
573   }
574
575   /**
576    * Adds rewrite-dispatch.
577    */

578   public RewriteInvocation createRewriteDispatch()
579   {
580     return _hostContainer.createRewriteDispatch();
581   }
582
583   /**
584    * Adds the cache.
585    */

586   public AbstractCache createCache()
587     throws ConfigException
588   {
589     try {
590       Class JavaDoc cl = Class.forName("com.caucho.server.cache.Cache");
591
592       _cache = (AbstractCache) cl.newInstance();
593     } catch (Throwable JavaDoc e) {
594       e.printStackTrace();
595     }
596
597     if (_cache == null) {
598       throw new ConfigException(L.l("<cache> requires Resin Professional. Please see http://www.caucho.com for Resin Professional information and licensing."));
599     }
600
601     return _cache;
602   }
603
604   /**
605    * Sets the access log.
606    */

607   public void setAccessLog(AccessLog log)
608   {
609     _accessLog = log;
610
611     Environment.setAttribute("caucho.server.access-log", log);
612   }
613
614   /**
615    * Returns the dependency check interval.
616    */

617   public long getDependencyCheckInterval()
618   {
619     return Environment.getDependencyCheckInterval(getClassLoader());
620   }
621
622   /**
623    * Sets the session cookie
624    */

625   public void setSessionCookie(String JavaDoc cookie)
626   {
627     getInvocationDecoder().setSessionCookie(cookie);
628   }
629
630   /**
631    * Gets the session cookie
632    */

633   public String JavaDoc getSessionCookie()
634   {
635     return getInvocationDecoder().getSessionCookie();
636   }
637
638   /**
639    * Sets the ssl session cookie
640    */

641   public void setSSLSessionCookie(String JavaDoc cookie)
642   {
643     getInvocationDecoder().setSSLSessionCookie(cookie);
644   }
645
646   /**
647    * Gets the ssl session cookie
648    */

649   public String JavaDoc getSSLSessionCookie()
650   {
651     return getInvocationDecoder().getSSLSessionCookie();
652   }
653
654   /**
655    * Sets the session url prefix.
656    */

657   public void setSessionURLPrefix(String JavaDoc urlPrefix)
658   {
659     getInvocationDecoder().setSessionURLPrefix(urlPrefix);
660   }
661
662   /**
663    * Gets the session url prefix.
664    */

665   public String JavaDoc getSessionURLPrefix()
666   {
667     return getInvocationDecoder().getSessionURLPrefix();
668   }
669
670   /**
671    * Sets the alternate session url prefix.
672    */

673   public void setAlternateSessionURLPrefix(String JavaDoc urlPrefix)
674     throws ConfigException
675   {
676     getInvocationDecoder().setAlternateSessionURLPrefix(urlPrefix);
677   }
678
679   /**
680    * Gets the alternate session url prefix.
681    */

682   public String JavaDoc getAlternateSessionURLPrefix()
683   {
684     return getInvocationDecoder().getAlternateSessionURLPrefix();
685   }
686
687   /**
688    * Sets URL encoding.
689    */

690   public void setURLCharacterEncoding(String JavaDoc encoding)
691     throws ConfigException
692   {
693     getInvocationDecoder().setEncoding(encoding);
694   }
695
696   /**
697    * Adds the ping.
698    */

699   public Object JavaDoc createPing()
700     throws ConfigException
701   {
702     try {
703       Class JavaDoc pingClass = Class.forName("com.caucho.server.admin.PingThread");
704
705       return pingClass.newInstance();
706     } catch (ClassNotFoundException JavaDoc e) {
707       throw new ConfigException(L.l("<ping> is only available in Resin Professional."));
708     } catch (Throwable JavaDoc e) {
709       log.fine(e.toString());
710
711       throw new ConfigException(e);
712     }
713   }
714
715   /**
716    * Adds the ping.
717    */

718   public void addPing(ResourceAdapter JavaDoc ping)
719     throws ConfigException
720   {
721     ResourceManagerImpl.addResource(ping);
722   }
723
724   /**
725    * Sets true if the select manager should be enabled
726    */

727   public boolean isSelectManagerEnabled()
728   {
729     return getSelectManager() != null;
730   }
731
732   public void addSelectManager(SelectManagerCompat selectManager)
733   {
734
735   }
736
737   /**
738    * Returns the number of select keepalives available.
739    */

740   public int getFreeKeepaliveSelect()
741   {
742     AbstractSelectManager selectManager = getSelectManager();
743
744     if (selectManager != null)
745       return selectManager.getFreeKeepalive();
746     else
747       return Integer.MAX_VALUE / 2;
748   }
749
750   /**
751    * Adds an error page
752    */

753   public void addErrorPage(ErrorPage errorPage)
754   {
755     getErrorWebApp().addErrorPage(errorPage);
756   }
757
758   //
759
// statistics
760
//
761

762   /**
763    * Returns the time the server started in ms.
764    */

765   public long getStartTime()
766   {
767     return _startTime;
768   }
769
770   /**
771    * Returns the lifecycle state
772    */

773   public String JavaDoc getState()
774   {
775     return _lifecycle.getStateName();
776   }
777
778   //
779
// runtime operations
780
//
781

782   /**
783    * Sets the invocation
784    */

785   public void buildInvocation(Invocation invocation)
786     throws Throwable JavaDoc
787   {
788     if (_configException != null) {
789       invocation.setFilterChain(new ExceptionFilterChain(_configException));
790       invocation.setWebApp(getErrorWebApp());
791       invocation.setDependency(AlwaysModified.create());
792       return;
793     }
794     else if (_lifecycle.waitForActive(_waitForActiveTime)) {
795       _hostContainer.buildInvocation(invocation);
796     }
797     else {
798       int code = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
799
800       invocation.setFilterChain(new ErrorFilterChain(code));
801       invocation.setWebApp(getErrorWebApp());
802       invocation.setDependency(AlwaysModified.create());
803     }
804   }
805
806   /**
807    * Returns the matching servlet pattern for a URL.
808    */

809   public String JavaDoc getServletPattern(String JavaDoc hostName, int port, String JavaDoc url)
810   {
811     try {
812       Host host = _hostContainer.getHost(hostName, port);
813
814       if (host == null)
815         return null;
816
817       WebApp app = host.findWebAppByURI(url);
818
819       if (app == null)
820         return null;
821
822       String JavaDoc pattern = app.getServletPattern(url);
823
824       return pattern;
825     } catch (Throwable JavaDoc e) {
826       log.log(Level.WARNING, e.toString(), e);
827
828       return null;
829     }
830   }
831
832   /**
833    * Returns the admin.
834    */

835   public ServerMXBean getAdmin()
836   {
837     return _admin;
838   }
839
840   /**
841    * Returns the matching servlet pattern for a URL.
842    */

843   public WebApp getWebApp(String JavaDoc hostName, int port, String JavaDoc url)
844   {
845     try {
846       HostContainer hostContainer = _hostContainer;
847
848       if (hostContainer == null)
849         return null;
850
851       Host host = hostContainer.getHost(hostName, port);
852
853       if (host == null)
854         return null;
855
856       return host.findWebAppByURI(url);
857     } catch (Throwable JavaDoc e) {
858       log.log(Level.WARNING, e.toString(), e);
859
860       return null;
861     }
862   }
863
864   /**
865    * Returns the error webApp during startup.
866    */

867   public WebApp getErrorWebApp()
868   {
869     HostContainer hostContainer = _hostContainer;
870
871     if (hostContainer != null)
872       return hostContainer.getErrorWebApp();
873     else
874       return null;
875   }
876
877   /**
878    * Returns the host controllers.
879    */

880   public Collection JavaDoc<HostController> getHostControllers()
881   {
882     HostContainer hostContainer = _hostContainer;
883
884     if (hostContainer == null)
885       return Collections.emptyList();
886
887     return Collections.unmodifiableList(hostContainer.getHostList());
888   }
889
890   /**
891    * Returns the matching servlet pattern for a URL.
892    */

893   public Host getHost(String JavaDoc hostName, int port)
894   {
895     try {
896       return _hostContainer.getHost(hostName, port);
897     } catch (Throwable JavaDoc e) {
898       log.log(Level.WARNING, e.toString(), e);
899
900       return null;
901     }
902   }
903
904   /**
905    * If true, ports are bound at end.
906    */

907   public void setBindPortsAfterStart(boolean bindAtEnd)
908   {
909     _isBindPortsAtEnd = bindAtEnd;
910   }
911
912   /**
913    * If true, ports are bound at end.
914    */

915   public boolean isBindPortsAfterStart()
916   {
917     return _isBindPortsAtEnd;
918   }
919
920   /**
921    * Returns the {@link Port}s for this server.
922    */

923   public Collection JavaDoc<Port> getPorts()
924   {
925     return Collections.unmodifiableList(_clusterServer.getPorts());
926   }
927
928   /**
929    * Handles the case where a class loader is activated.
930    */

931   public void classLoaderInit(DynamicClassLoader loader)
932   {
933     try {
934       //Jmx.register(_controller.getThreadPool(), "resin:type=ThreadPool");
935
} catch (Exception JavaDoc e) {
936       log.log(Level.WARNING, e.toString(), e);
937     }
938   }
939
940   /**
941    * Handles the case where a class loader is dropped.
942    */

943   public void classLoaderDestroy(DynamicClassLoader loader)
944   {
945     /*
946     try {
947       Jmx.unregister("resin:name=default,type=Server");
948       Jmx.unregister("resin:type=ThreadPool");
949     } catch (Throwable e) {
950       log.log(Level.FINEST, e.toString(), e);
951     }
952     */

953   }
954
955   /**
956    * Initialization.
957    */

958   @PostConstruct
959   public void init()
960   {
961     _classLoader.init();
962
963     super.init();
964
965     if (_threadMax < _threadIdleMax)
966       throw new ConfigException(L.l("<thread-idle-max> ({0}) must be less than <thread-max> ({1})",
967                     _threadIdleMax, _threadMax));
968
969     if (_threadIdleMax < _threadIdleMin)
970       throw new ConfigException(L.l("<thread-idle-min> ({0}) must be less than <thread-max> ({1})",
971                     _threadIdleMin, _threadIdleMax));
972
973     if (_keepaliveSelectEnable) {
974       try {
975         Class JavaDoc cl = Class.forName("com.caucho.server.port.JniSelectManager");
976         Method JavaDoc method = cl.getMethod("create", new Class JavaDoc[0]);
977
978         initSelectManager((AbstractSelectManager) method.invoke(null, null));
979       } catch (ClassNotFoundException JavaDoc e) {
980         log.warning(L.l("'select-manager' requires Resin Professional. See http://www.caucho.com for information and licensing."));
981       } catch (Throwable JavaDoc e) {
982         log.warning(L.l("Cannot enable select-manager {0}", e.toString()));
983
984         log.log(Level.FINER, e.toString());
985       }
986     }
987   }
988
989   /**
990    * Start the server.
991    */

992   public void start()
993   {
994     init();
995
996     Thread JavaDoc thread = Thread.currentThread();
997     ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
998     try {
999       thread.setContextClassLoader(_classLoader);
1000
1001      if (! _lifecycle.toStarting())
1002        return;
1003
1004      _startTime = Alarm.getCurrentTime();
1005
1006      if (! Alarm.isTest()) {
1007        log.info("");
1008
1009        log.info(System.getProperty("os.name") + " " +
1010                 System.getProperty("os.version") + " " +
1011                 System.getProperty("os.arch"));
1012
1013        log.info("Java " + System.getProperty("java.vm.version") + ", " +
1014                 System.getProperty("sun.arch.data.model") + ", " +
1015                 System.getProperty("java.vm.info") + ", " +
1016                 System.getProperty("file.encoding") + ", " +
1017                 System.getProperty("user.language") + ", " +
1018                 System.getProperty("java.vm.vendor"));
1019
1020        log.info("user.name: " + System.getProperty("user.name"));
1021
1022        Resin resin = Resin.getLocal();
1023
1024        if (resin != null) {
1025          log.info("resin.home = " + resin.getResinHome().getNativePath());
1026          log.info("root.directory = " + resin.getRootDirectory().getNativePath());
1027          log.info("resin.conf = " + resin.getResinConf());
1028        }
1029        else {
1030          log.info("resin.home = " + System.getProperty("resin.home"));
1031        }
1032
1033        log.info("");
1034      }
1035
1036      AbstractSelectManager selectManager = getSelectManager();
1037      if (_keepaliveSelectEnable && selectManager != null)
1038        selectManager.start();
1039
1040      if (! _isBindPortsAtEnd) {
1041        bindPorts();
1042      }
1043
1044      _lifecycle.toActive();
1045
1046      _classLoader.start();
1047
1048      _hostContainer.start();
1049
1050      // will only occur if bind-ports-at-end is true
1051
if (_isBindPortsAtEnd) {
1052        bindPorts();
1053      }
1054
1055      startPorts();
1056
1057      _alarm.queue(ALARM_INTERVAL);
1058    } catch (Throwable JavaDoc e) {
1059      log.log(Level.WARNING, e.toString(), e);
1060
1061      _configException = e;
1062    } finally {
1063      thread.setContextClassLoader(oldLoader);
1064    }
1065  }
1066
1067  /**
1068   * Bind the ports.
1069   */

1070  public void bindPorts()
1071    throws Exception JavaDoc
1072  {
1073    synchronized (this) {
1074      if (_isStartedPorts)
1075        return;
1076
1077      _isStartedPorts = true;
1078    }
1079
1080    Thread JavaDoc thread = Thread.currentThread();
1081    ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
1082    try {
1083      thread.setContextClassLoader(_classLoader);
1084
1085      ArrayList JavaDoc<Port> ports = _clusterServer.getPorts();
1086      for (int i = 0; i < ports.size(); i++) {
1087    Port port = ports.get(i);
1088
1089    port.setServer(this);
1090
1091    port.bind();
1092      }
1093    } finally {
1094      thread.setContextClassLoader(oldLoader);
1095    }
1096  }
1097
1098  /**
1099   * Start the ports.
1100   */

1101  public void startPorts()
1102    throws Throwable JavaDoc
1103  {
1104    Thread JavaDoc thread = Thread.currentThread();
1105    ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
1106    try {
1107      thread.setContextClassLoader(_classLoader);
1108
1109      ArrayList JavaDoc<Port> ports = _clusterServer.getPorts();
1110      for (int i = 0; i < ports.size(); i++) {
1111        Port port = ports.get(i);
1112
1113    port.start();
1114      }
1115    } finally {
1116      thread.setContextClassLoader(oldLoader);
1117    }
1118  }
1119
1120  /**
1121   * Handles the alarm.
1122   */

1123  public void handleAlarm(Alarm alarm)
1124  {
1125    if (! _lifecycle.isActive())
1126      return;
1127
1128    try {
1129      long now = Alarm.getCurrentTime();
1130
1131      if (isModified()) {
1132        // XXX: message slightly wrong
1133
log.info("Resin restarting due to configuration change");
1134
1135        _clusterServer.getCluster().getResin().destroy();
1136        return;
1137      }
1138
1139      try {
1140      ArrayList JavaDoc<Port> ports = _clusterServer.getPorts();
1141        for (int i = 0; i < ports.size(); i++) {
1142          Port port = ports.get(i);
1143
1144          if (port.isClosed()) {
1145            log.info("Resin restarting due to closed port: " + port);
1146            // destroy();
1147
//_controller.restart();
1148
}
1149        }
1150      } catch (Throwable JavaDoc e) {
1151        log.log(Level.WARNING, e.toString(), e);
1152        // destroy();
1153
//_controller.restart();
1154
return;
1155      }
1156    } finally {
1157      alarm.queue(ALARM_INTERVAL);
1158    }
1159  }
1160
1161  /**
1162   * Returns true if the server has been modified and needs restarting.
1163   */

1164  public boolean isModified()
1165  {
1166    boolean isModified = _classLoader.isModified();
1167
1168    if (isModified)
1169      log.fine("server is modified");
1170
1171    return isModified;
1172  }
1173
1174  /**
1175   * Returns true if the server has been modified and needs restarting.
1176   */

1177  public boolean isModifiedNow()
1178  {
1179    boolean isModified = _classLoader.isModifiedNow();
1180
1181    if (isModified)
1182      log.fine("server is modified");
1183
1184    return isModified;
1185  }
1186
1187  /**
1188   * Returns true if the server is stopped.
1189   */

1190  public boolean isStopping()
1191  {
1192    return _lifecycle.isStopping();
1193  }
1194
1195  /**
1196   * Returns true if the server is stopped.
1197   */

1198  public boolean isStopped()
1199  {
1200    return _lifecycle.isStopped();
1201  }
1202
1203  /**
1204   * Returns true if the server is closed.
1205   */

1206  public boolean isDestroyed()
1207  {
1208    return _lifecycle.isDestroyed();
1209  }
1210
1211  /**
1212   * Returns true if the server is closed.
1213   */

1214  public boolean isDestroying()
1215  {
1216    return _lifecycle.isDestroying();
1217  }
1218
1219  /**
1220   * Returns true if the server is currently active and accepting requests
1221   */

1222  public boolean isActive()
1223  {
1224    return _lifecycle.isActive();
1225  }
1226
1227  /**
1228   * Clears the catch by matching the invocation.
1229   */

1230  public void clearCacheByPattern(String JavaDoc hostPattern, String JavaDoc uriPattern)
1231  {
1232    final Matcher hostMatcher;
1233    if (hostPattern != null)
1234      hostMatcher = Pattern.compile(hostPattern).matcher("");
1235    else
1236      hostMatcher = null;
1237
1238    final Matcher uriMatcher;
1239    if (uriPattern != null)
1240      uriMatcher = Pattern.compile(uriPattern).matcher("");
1241    else
1242      uriMatcher = null;
1243
1244    InvocationMatcher matcher = new InvocationMatcher() {
1245        public boolean isMatch(Invocation invocation)
1246        {
1247          if (hostMatcher != null) {
1248            hostMatcher.reset(invocation.getHost());
1249            if (! hostMatcher.find()) {
1250              return false;
1251            }
1252          }
1253
1254          if (uriMatcher != null) {
1255            uriMatcher.reset(invocation.getURI());
1256            if (! uriMatcher.find()) {
1257              return false;
1258            }
1259          }
1260
1261          return true;
1262        }
1263      };
1264
1265    invalidateMatchingInvocations(matcher);
1266  }
1267
1268  /**
1269   * Clears the proxy cache.
1270   */

1271  public void clearCache()
1272  {
1273    // skip the clear on restart
1274
if (isStopping())
1275      return;
1276
1277    if (log.isLoggable(Level.FINEST))
1278      log.finest("ServletServer clearCache");
1279
1280    // the invocation cache must be cleared first because the old
1281
// filter chain entries must not point to the cache's
1282
// soon-to-be-invalid entries
1283
super.clearCache();
1284
1285    if (_cache != null)
1286      _cache.clear();
1287  }
1288
1289  /**
1290   * Returns the proxy cache hit count.
1291   */

1292  public long getProxyCacheHitCount()
1293  {
1294    if (_cache != null)
1295      return _cache.getHitCount();
1296    else
1297      return 0;
1298  }
1299
1300  /**
1301   * Returns the proxy cache miss count.
1302   */

1303  public long getProxyCacheMissCount()
1304  {
1305    if (_cache != null)
1306      return _cache.getMissCount();
1307    else
1308      return 0;
1309  }
1310
1311  /**
1312   * Closes the server.
1313   */

1314  public void stop()
1315  {
1316    Thread JavaDoc thread = Thread.currentThread();
1317    ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
1318
1319    try {
1320      thread.setContextClassLoader(_classLoader);
1321
1322      if (! _lifecycle.toStopping())
1323        return;
1324
1325      super.stop();
1326
1327      Alarm alarm = _alarm;
1328      _alarm = null;
1329
1330      if (alarm != null)
1331        alarm.dequeue();
1332
1333      if (getSelectManager() != null)
1334        getSelectManager().stop();
1335
1336      ArrayList JavaDoc<Port> ports = _clusterServer.getPorts();
1337      for (int i = 0; i < ports.size(); i++) {
1338        Port port = ports.get(i);
1339
1340        try {
1341          port.close();
1342        } catch (Throwable JavaDoc e) {
1343          log.log(Level.WARNING, e.toString(), e);
1344        }
1345      }
1346
1347      try {
1348        ThreadPool.getThreadPool().interrupt();
1349      } catch (Throwable JavaDoc e) {
1350        log.log(Level.WARNING, e.toString(), e);
1351      }
1352
1353      try {
1354        Thread.yield();
1355      } catch (Throwable JavaDoc e) {
1356      }
1357
1358      try {
1359    if (_hostContainer != null)
1360      _hostContainer.stop();
1361      } catch (Throwable JavaDoc e) {
1362        log.log(Level.WARNING, e.toString(), e);
1363      }
1364
1365      try {
1366        _classLoader.stop();
1367      } catch (Throwable JavaDoc e) {
1368        log.log(Level.WARNING, e.toString(), e);
1369      }
1370
1371      _lifecycle.toStop();
1372    } finally {
1373      thread.setContextClassLoader(oldLoader);
1374    }
1375  }
1376
1377  /**
1378   * Closes the server.
1379   */

1380  public void destroy()
1381  {
1382    stop();
1383
1384    if (! _lifecycle.toDestroy())
1385      return;
1386
1387    Thread JavaDoc thread = Thread.currentThread();
1388    ClassLoader JavaDoc oldLoader = thread.getContextClassLoader();
1389
1390    try {
1391      thread.setContextClassLoader(_classLoader);
1392
1393      try {
1394        _hostContainer.destroy();
1395      } catch (Throwable JavaDoc e) {
1396        log.log(Level.WARNING, e.toString(), e);
1397      }
1398
1399      super.destroy();
1400
1401      log.fine(this + " destroyed");
1402
1403      _classLoader.destroy();
1404
1405      _hostContainer = null;
1406      _accessLog = null;
1407      _cache = null;
1408    } finally {
1409      DynamicClassLoader.setOldLoader(thread, oldLoader);
1410
1411      Resin resin = _resin;
1412
1413      if (resin != null)
1414        resin.destroy();
1415    }
1416  }
1417
1418  public String JavaDoc toString()
1419  {
1420    return ("Server[id=" + getServerId()
1421        + ",cluster=" + _clusterServer.getCluster().getId() + "]");
1422  }
1423
1424  public static class SelectManagerCompat {
1425    private boolean _isEnable = true;
1426
1427    public void setEnable(boolean isEnable)
1428    {
1429      _isEnable = isEnable;
1430    }
1431
1432    public boolean isEnable()
1433    {
1434      return _isEnable;
1435    }
1436  }
1437}
1438
Popular Tags