KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > dispatch > ServletConfigImpl


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.dispatch;
31
32 import com.caucho.config.BuilderProgram;
33 import com.caucho.config.Config;
34 import com.caucho.config.NodeBuilderProgram;
35 import com.caucho.config.types.InitParam;
36 import com.caucho.config.types.InitProgram;
37 import com.caucho.jmx.Jmx;
38 import com.caucho.jsp.Page;
39 import com.caucho.jsp.QServlet;
40 import com.caucho.naming.Jndi;
41 import com.caucho.server.connection.StubServletRequest;
42 import com.caucho.server.connection.StubServletResponse;
43 import com.caucho.soa.servlet.ProtocolServlet;
44 import com.caucho.soa.servlet.SoapProtocolServlet;
45 import com.caucho.util.Alarm;
46 import com.caucho.util.AlarmListener;
47 import com.caucho.util.CompileException;
48 import com.caucho.util.L10N;
49 import com.caucho.util.Log;
50
51 import javax.annotation.PostConstruct;
52 import javax.jws.WebService;
53 import javax.naming.NamingException JavaDoc;
54 import javax.servlet.*;
55 import java.lang.reflect.Constructor JavaDoc;
56 import java.lang.reflect.Modifier JavaDoc;
57 import java.util.Collections JavaDoc;
58 import java.util.Enumeration JavaDoc;
59 import java.util.HashMap JavaDoc;
60 import java.util.Hashtable JavaDoc;
61 import java.util.Map JavaDoc;
62 import java.util.logging.Level JavaDoc;
63 import java.util.logging.Logger JavaDoc;
64
65 /**
66  * Configuration for a servlet.
67  */

68 public class ServletConfigImpl implements ServletConfig, AlarmListener {
69   static L10N L = new L10N(ServletConfigImpl.class);
70   protected static final Logger JavaDoc log = Log.open(ServletConfigImpl.class);
71
72   private String JavaDoc _location;
73
74   private String JavaDoc _jndiName;
75   private String JavaDoc _var;
76   
77   private String JavaDoc _servletName;
78   private String JavaDoc _servletClassName;
79   private Class JavaDoc _servletClass;
80   private String JavaDoc _jspFile;
81   private String JavaDoc _displayName;
82   private int _loadOnStartup = Integer.MIN_VALUE;
83
84   private boolean _allowEL = true;
85   private HashMap JavaDoc<String JavaDoc,String JavaDoc> _initParams = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
86
87   private HashMap JavaDoc<String JavaDoc,String JavaDoc> _roleMap;
88
89   private InitProgram _init;
90
91   private RunAt _runAt;
92
93   private Class JavaDoc _protocolClass;
94   private BuilderProgram _protocolInit;
95   
96   private Alarm _alarm;
97
98   private ServletContext _servletContext;
99   private ServletManager _servletManager;
100
101   private ServletException _initException;
102   private long _nextInitTime;
103
104   private Object JavaDoc _servlet;
105   private FilterChain _servletChain;
106
107   /**
108    * Creates a new servlet configuration object.
109    */

110   public ServletConfigImpl()
111   {
112   }
113
114   /**
115    * Sets the config location.
116    */

117   public void setConfigLocation(String JavaDoc location, int line)
118   {
119     _location = location + ":" + line + ": ";
120   }
121
122   /**
123    * Sets the id attribute
124    */

125   public void setId(String JavaDoc id)
126   {
127   }
128
129   /**
130    * Sets the servlet name.
131    */

132   public void setServletName(String JavaDoc name)
133   {
134     _servletName = name;
135   }
136
137   /**
138    * Gets the servlet name.
139    */

140   public String JavaDoc getServletName()
141   {
142     return _servletName;
143   }
144
145   /**
146    * Gets the servlet name.
147    */

148   public String JavaDoc getServletClassName()
149   {
150     return _servletClassName;
151   }
152
153   /**
154    * Sets the servlet class.
155    */

156   public void setServletClass(String JavaDoc servletClassName)
157     throws ServletException
158   {
159     _servletClassName = servletClassName;
160   }
161
162   /**
163    * Gets the servlet name.
164    */

165   public Class JavaDoc getServletClass()
166   {
167     return _servletClass;
168   }
169
170   /**
171    * Sets the JSP file
172    */

173   public void setJspFile(String JavaDoc jspFile)
174   {
175     _jspFile = jspFile;
176   }
177
178   /**
179    * Gets the JSP file
180    */

181   public String JavaDoc getJspFile()
182   {
183     return _jspFile;
184   }
185
186   /**
187    * Sets the allow value.
188    */

189   public void setAllowEL(boolean allowEL)
190   {
191     _allowEL = allowEL;
192   }
193
194   /**
195    * Sets an init-param
196    */

197   public void setInitParam(String JavaDoc param, String JavaDoc value)
198   {
199     _initParams.put(param, value);
200   }
201
202   /**
203    * Sets an init-param
204    */

205   public InitParam createInitParam()
206   {
207     InitParam initParam = new InitParam();
208
209     initParam.setAllowEL(_allowEL);
210
211     return initParam;
212   }
213
214   /**
215    * Sets an init-param
216    */

217   public void setInitParam(InitParam initParam)
218   {
219     _initParams.putAll(initParam.getParameters());
220   }
221
222   /**
223    * Gets the init params
224    */

225   public Map JavaDoc getInitParamMap()
226   {
227     return _initParams;
228   }
229
230   /**
231    * Gets the init params
232    */

233   public String JavaDoc getInitParameter(String JavaDoc name)
234   {
235     return _initParams.get(name);
236   }
237
238   /**
239    * Gets the init params
240    */

241   public Enumeration JavaDoc getInitParameterNames()
242   {
243     return Collections.enumeration(_initParams.keySet());
244   }
245
246   /**
247    * Returns the servlet context.
248    */

249   public ServletContext getServletContext()
250   {
251     return _servletContext;
252   }
253
254   /**
255    * Sets the servlet context.
256    */

257   public void setServletContext(ServletContext app)
258   {
259     _servletContext = app;
260   }
261
262   /**
263    * Returns the servlet manager.
264    */

265   public ServletManager getServletManager()
266   {
267     return _servletManager;
268   }
269
270   /**
271    * Sets the servlet manager.
272    */

273   public void setServletManager(ServletManager manager)
274   {
275     _servletManager = manager;
276   }
277
278   /**
279    * Sets the init block
280    */

281   public void setInit(InitProgram init)
282   {
283     _init = init;
284   }
285
286   /**
287    * Gets the init block
288    */

289   public InitProgram getInit()
290   {
291     return _init;
292   }
293
294   /**
295    * Sets the load-on-startup
296    */

297   public void setLoadOnStartup(int loadOnStartup)
298   {
299     _loadOnStartup = loadOnStartup;
300   }
301
302   /**
303    * Gets the load-on-startup value.
304    */

305   public int getLoadOnStartup()
306   {
307     if (_loadOnStartup > Integer.MIN_VALUE)
308       return _loadOnStartup;
309     else if (_runAt != null)
310       return 0;
311     else
312       return Integer.MIN_VALUE;
313   }
314
315   /**
316    * Creates the run-at configuration.
317    */

318   public RunAt createRunAt()
319   {
320     if (_runAt == null)
321       _runAt = new RunAt();
322
323     return _runAt;
324   }
325
326   public void setJndiName(String JavaDoc jndiName)
327   {
328     _jndiName = jndiName;
329   }
330
331   public void setVar(String JavaDoc var)
332   {
333     _var = var;
334   }
335
336   /**
337    * Returns the run-at configuration.
338    */

339   public RunAt getRunAt()
340   {
341     return _runAt;
342   }
343
344   /**
345    * Adds a security role reference.
346    */

347   public void addSecurityRoleRef(SecurityRoleRef ref)
348   {
349     if (_roleMap == null)
350       _roleMap = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
351
352     // server/12h2
353
// server/12m0
354
_roleMap.put(ref.getRoleName(), ref.getRoleLink());
355   }
356
357   /**
358    * Adds a security role reference.
359    */

360   public HashMap JavaDoc<String JavaDoc,String JavaDoc> getRoleMap()
361   {
362     return _roleMap;
363   }
364
365   /**
366    * Sets the display name
367    */

368   public void setDisplayName(String JavaDoc displayName)
369   {
370     _displayName = displayName;
371   }
372
373   /**
374    * Gets the display name
375    */

376   public String JavaDoc getDisplayName()
377   {
378     return _displayName;
379   }
380
381   /**
382    * Sets the description
383    */

384   public void setDescription(String JavaDoc description)
385   {
386   }
387
388   /**
389    * Sets the icon
390    */

391   public void setIcon(com.caucho.config.types.Icon icon)
392   {
393   }
394
395   /**
396    * Sets the web service protocol.
397    */

398   public void setProtocol(ServletProtocolConfig protocol)
399   {
400     _protocolClass = protocol.getType();
401     _protocolInit = protocol.getProgram();
402   }
403
404   /**
405    * Sets the init exception
406    */

407   public void setInitException(ServletException exn)
408   {
409     _initException = exn;
410
411     _nextInitTime = Long.MAX_VALUE / 2;
412
413     if (exn instanceof UnavailableException) {
414       UnavailableException unExn = (UnavailableException) exn;
415
416       if (! unExn.isPermanent())
417         _nextInitTime = (Alarm.getCurrentTime() +
418                          1000L * unExn.getUnavailableSeconds());
419     }
420   }
421
422   /**
423    * Returns the servlet.
424    */

425   public Object JavaDoc getServlet()
426   {
427     return _servlet;
428   }
429
430   /**
431    * Initialize the servlet config.
432    */

433   @PostConstruct
434   public void init()
435     throws ServletException
436   {
437     if (_runAt != null) {
438       _alarm = new Alarm(this);
439     }
440
441     if (_servletName != null) {
442     }
443     else if (_protocolClass != null) {
444       String JavaDoc protocol = _protocolClass.getName();
445       
446       int p = protocol.lastIndexOf('.');
447       protocol = protocol.substring(p + 1);
448       
449       _servletName = _servletClassName + "-" + protocol;
450     }
451     else
452       _servletName = _servletClassName;
453
454     // XXX: should only be for web services
455
if (_jndiName != null) {
456       validateClass(true);
457       
458       Object JavaDoc servlet = createServlet(false);
459
460       try {
461     Jndi.bindDeepShort(_jndiName, servlet);
462       } catch (NamingException JavaDoc e) {
463     throw new ServletException(e);
464       }
465     }
466
467     if (_var != null) {
468       validateClass(true);
469       
470       Object JavaDoc servlet = createServlet(false);
471
472       Config.setCurrentVar(_var, servlet);
473     }
474   }
475
476   protected void validateClass(boolean requireClass)
477     throws ServletException
478   {
479     if (_runAt != null || _loadOnStartup >= 0)
480       requireClass = true;
481
482     Thread JavaDoc thread = Thread.currentThread();
483     ClassLoader JavaDoc loader = thread.getContextClassLoader();
484
485     if (_servletClassName == null) {
486     }
487     else if (_servletClassName.equals("invoker")) {
488     }
489     else {
490       try {
491         _servletClass = Class.forName(_servletClassName, false, loader);
492       } catch (ClassNotFoundException JavaDoc e) {
493     if (e instanceof CompileException)
494       throw error(e);
495     
496         log.log(Level.FINER, e.toString(), e);
497       }
498
499       if (_servletClass != null) {
500       }
501       else if (requireClass) {
502         throw error(L.l("'{0}' is not a known servlet. Servlets belong in the classpath, often in WEB-INF/classes.", _servletClassName));
503       }
504       else {
505         String JavaDoc location = _location != null ? _location : "";
506
507         log.warning(L.l(location + "'{0}' is not a known servlet. Servlets belong in the classpath, often in WEB-INF/classes.", _servletClassName));
508         return;
509       }
510
511       Config.checkCanInstantiate(_servletClass);
512
513       if (_servletClass.isAnnotationPresent(WebService.class)) {
514     if (_protocolClass == null)
515       _protocolClass = SoapProtocolServlet.class;
516       }
517       else if (Servlet.class.isAssignableFrom(_servletClass)) {
518       }
519       else
520         throw error(L.l("'{0}' must implement javax.servlet.Servlet or have a @WebService annotation. All servlets must implement the Servlet interface.", _servletClassName));
521
522       /*
523       if (Modifier.isAbstract(_servletClass.getModifiers()))
524         throw error(L.l("'{0}' must not be abstract. Servlets must be fully-implemented classes.", _servletClassName));
525
526       if (! Modifier.isPublic(_servletClass.getModifiers()))
527         throw error(L.l("'{0}' must be public. Servlets must be public classes.", _servletClassName));
528
529       checkConstructor();
530       */

531     }
532   }
533
534   /**
535    * Checks the class constructor for the public-zero arg.
536    */

537   public void checkConstructor()
538     throws ServletException
539   {
540     Constructor JavaDoc []constructors = _servletClass.getDeclaredConstructors();
541
542     Constructor JavaDoc zeroArg = null;
543     for (int i = 0; i < constructors.length; i++) {
544       if (constructors[i].getParameterTypes().length == 0) {
545         zeroArg = constructors[i];
546         break;
547       }
548     }
549
550     if (zeroArg == null)
551       throw error(L.l("'{0}' must have a zero arg constructor. Servlets must have public zero-arg constructors.\n{1} is not a valid constructor.", _servletClassName, constructors[0]));
552
553
554     if (! Modifier.isPublic(zeroArg.getModifiers()))
555         throw error(L.l("'{0}' must be public. '{1}' must have a public, zero-arg constructor.",
556                         zeroArg,
557                         _servletClassName));
558   }
559
560   /**
561    * Handles a cron alarm callback.
562    */

563   public void handleAlarm(Alarm alarm)
564   {
565     try {
566       log.fine(this + " cron");
567
568       FilterChain chain = createServletChain();
569
570       ServletRequest req = new StubServletRequest();
571       ServletResponse res = new StubServletResponse();
572
573       chain.doFilter(req, res);
574     } catch (Throwable JavaDoc e) {
575       log.log(Level.WARNING, e.toString(), e);
576     } finally {
577       long nextTime = _runAt.getNextTimeout(Alarm.getCurrentTime());
578       _alarm.queue(nextTime - Alarm.getCurrentTime());
579     }
580   }
581
582   public FilterChain createServletChain()
583     throws ServletException
584   {
585     synchronized (this) {
586       // JSP files need to have separate chains created for each JSP
587

588       if (_servletChain != null)
589     return _servletChain;
590       else
591         return createServletChainImpl();
592     }
593   }
594
595   private FilterChain createServletChainImpl()
596     throws ServletException
597   {
598     String JavaDoc jspFile = getJspFile();
599     FilterChain servletChain = null;
600
601     if (jspFile != null) {
602       QServlet jsp = (QServlet) _servletManager.createServlet("resin-jsp");
603
604       servletChain = new PageFilterChain(_servletContext, jsp, jspFile, this);
605
606       return servletChain;
607     }
608
609     validateClass(true);
610
611     Class JavaDoc servletClass = getServletClass();
612
613     if (servletClass == null) {
614       throw new IllegalStateException JavaDoc(L.l("servlet class for {0} can't be null",
615                                           getServletName()));
616     }
617     else if (QServlet.class.isAssignableFrom(servletClass)) {
618       servletChain = new PageFilterChain(_servletContext, (QServlet) createServlet(false));
619     }
620     else if (SingleThreadModel.class.isAssignableFrom(servletClass)) {
621       servletChain = new SingleThreadServletFilterChain(this);
622     }
623     else if (servletClass.isAnnotationPresent(WebService.class))
624       servletChain = new WebServiceFilterChain(this);
625     else {
626       servletChain = new ServletFilterChain(this);
627     }
628
629     if (_roleMap != null)
630       servletChain = new SecurityRoleMapFilterChain(servletChain, _roleMap);
631
632     // server/10a8. JSP pages need a fresh PageFilterChain
633
// XXX: lock contention issues with JSPs?
634
/*
635     if (! QServlet.class.isAssignableFrom(servletClass))
636       _servletChain = servletChain;
637     */

638
639     return servletChain;
640   }
641
642   /**
643    * Instantiates a web service.
644    *
645    * @return the initialized servlet.
646    */

647   ProtocolServlet createWebServiceSkeleton()
648     throws ServletException
649   {
650     try {
651       Object JavaDoc service = createServlet(false);
652
653       ProtocolServlet skeleton
654     = (ProtocolServlet) _protocolClass.newInstance();
655
656       skeleton.setService(service);
657
658       if (_protocolInit != null) {
659     _protocolInit.configure(skeleton);
660       }
661
662       skeleton.init(this);
663
664       return skeleton;
665     } catch (RuntimeException JavaDoc e) {
666       throw e;
667     } catch (ServletException e) {
668       throw e;
669     } catch (Exception JavaDoc e) {
670       throw new ServletException(e);
671     }
672   }
673
674   /**
675    * Instantiates a servlet given its configuration.
676    *
677    * @param servletName the servlet
678    *
679    * @return the initialized servlet.
680    */

681   Object JavaDoc createServlet(boolean isNew)
682     throws ServletException
683   {
684     // server/102e
685
if (_servlet != null && ! isNew)
686       return _servlet;
687
688     Object JavaDoc servlet = null;
689
690     if (Alarm.getCurrentTime() < _nextInitTime)
691       throw _initException;
692
693     if (log.isLoggable(Level.FINE))
694       log.fine("Servlet[" + _servletName + "] starting");
695
696     try {
697       servlet = createServletImpl();
698
699       synchronized (this) {
700     if (_servlet == null && ! isNew)
701       _servlet = servlet;
702       }
703
704       //J2EEManagedObject.register(new com.caucho.management.j2ee.Servlet(this));
705

706       if (_servlet == servlet) {
707     // If the servlet has an MBean, register it
708
try {
709       Hashtable JavaDoc<String JavaDoc,String JavaDoc> props = new Hashtable JavaDoc<String JavaDoc,String JavaDoc>();
710
711       String JavaDoc className = _servlet.getClass().getName();
712       int p = className.lastIndexOf('.');
713       props.put("type", className.substring(p + 1));
714       props.put("name", _servletName);
715       Jmx.register(_servlet, props);
716     } catch (Exception JavaDoc e) {
717       log.finest(e.toString());
718     }
719
720     if (_runAt != null && _alarm != null) {
721       long nextTime = _runAt.getNextTimeout(Alarm.getCurrentTime());
722       _alarm.queue(nextTime - Alarm.getCurrentTime());
723     }
724       }
725
726       if (log.isLoggable(Level.FINER))
727         log.finer("Servlet[" + _servletName + "] started");
728
729       return servlet;
730     } catch (ServletException e) {
731       throw e;
732     } catch (Throwable JavaDoc e) {
733       log.log(Level.WARNING, e.toString(), e);
734
735       throw new ServletException(e);
736     }
737   }
738
739   private Object JavaDoc createServletImpl()
740     throws Throwable JavaDoc
741   {
742     Class JavaDoc servletClass = getServletClass();
743
744     Object JavaDoc servlet;
745     if (_jspFile != null) {
746       servlet = createJspServlet(_servletName, _jspFile);
747
748       if (servlet == null)
749         throw new ServletException(L.l("'{0}' is a missing JSP file.",
750                                        _jspFile));
751     }
752
753     else if (servletClass != null)
754       servlet = servletClass.newInstance();
755
756     else
757       throw new ServletException(L.l("Null servlet class for '{0}'.",
758                                      _servletName));
759
760     configureServlet(servlet);
761
762     try {
763       if (servlet instanceof Servlet) {
764     Servlet servletObj = (Servlet) servlet;
765     
766     servletObj.init(this);
767       }
768     } catch (UnavailableException e) {
769       setInitException(e);
770       throw e;
771     }
772
773     return servlet;
774   }
775
776   /**
777    * Configure the servlet (everything that is done after
778    * instantiation but before servlet.init()
779    */

780   void configureServlet(Object JavaDoc servlet)
781     throws Throwable JavaDoc
782   {
783     //InjectIntrospector.configure(servlet);
784

785     // Initialize bean properties
786
InitProgram init = getInit();
787     BuilderProgram program;
788
789     if (init != null)
790       program = init.getBuilderProgram();
791     else
792       program = NodeBuilderProgram.NULL;
793
794     program.configure(servlet);
795     program.init(servlet);
796   }
797
798   /**
799    * Instantiates a servlet given its configuration.
800    *
801    * @param servletName the servlet
802    *
803    * @return the initialized servlet.
804    */

805   private Servlet createJspServlet(String JavaDoc servletName, String JavaDoc jspFile)
806     throws ServletException
807   {
808     try {
809       ServletConfigImpl jspConfig = _servletManager.getServlet("resin-jsp");
810
811       QServlet jsp = (QServlet) jspConfig.createServlet(false);
812
813       Page page = jsp.getPage(servletName, jspFile);
814
815       return page;
816     } catch (ServletException e) {
817       throw e;
818     } catch (Exception JavaDoc e) {
819       throw new ServletException(e);
820     }
821   }
822
823   void killServlet()
824   {
825     Object JavaDoc servlet = _servlet;
826     _servlet = null;
827
828     if (_alarm != null)
829       _alarm.dequeue();
830
831     if (servlet instanceof Servlet) {
832       ((Servlet) servlet).destroy();
833     }
834   }
835
836   public void close()
837   {
838     killServlet();
839
840     _alarm = null;
841   }
842
843   protected ServletException error(String JavaDoc msg)
844   {
845     if (_location != null)
846       return new ServletLineConfigException(_location + msg);
847     else
848       return new ServletConfigException(msg);
849   }
850
851   protected ServletException error(Throwable JavaDoc e)
852   {
853     if (_location != null)
854       return new ServletLineConfigException(_location + e.getMessage(), e);
855     else
856       return new ServletConfigException(e);
857   }
858
859   /**
860    * Returns a printable representation of the servlet config object.
861    */

862   public String JavaDoc toString()
863   {
864     return "ServletConfigImpl[name=" + _servletName + ",class=" + _servletClass + "]";
865   }
866 }
867
Popular Tags