View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.tomcat;
19  
20  import java.net.InetSocketAddress;
21  import java.net.UnknownHostException;
22  import java.net.InetAddress;
23  import java.util.Map;
24  import java.util.HashMap;
25  
26  import org.apache.catalina.LifecycleException;
27  import org.apache.catalina.connector.Connector;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.geronimo.gbean.GBeanInfo;
31  import org.apache.geronimo.gbean.GBeanInfoBuilder;
32  import org.apache.geronimo.gbean.GBeanLifecycle;
33  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
34  import org.apache.geronimo.management.geronimo.WebManager;
35  
36  /**
37   * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
38   */
39  public class ConnectorGBean extends BaseGBean implements GBeanLifecycle, ObjectRetriever, TomcatWebConnector {
40      private static final Log log = LogFactory.getLog(ConnectorGBean.class);
41      public final static String CONNECTOR_CONTAINER_REFERENCE = "TomcatContainer";
42  
43      protected final Connector connector;
44      private final TomcatContainer container;
45      private String name;
46      private String connectHost;
47  
48      public ConnectorGBean(String name, String protocol, String host, int port, TomcatContainer container) throws Exception {
49          super(); // TODO: make it an attribute
50  
51          Map initParams = new HashMap();
52  
53          validateProtocol(protocol);
54          
55          //Default the host to listen on all address is one was not specified
56          if (host == null){
57              host = "0.0.0.0";
58          }
59          
60          //Must have a port
61          if (port == 0){
62              throw new IllegalArgumentException("Must declare a port.");
63          }
64  
65          initParams.put("address", host);
66          initParams.put("port", Integer.toString(port));
67          initializeParams(protocol, initParams);
68  
69          // Convert Geronimo standard values to Tomcat standard values
70          // Only AJP requires an explicit protocol setting
71          if(protocol != null && protocol.equals(WebManager.PROTOCOL_AJP)) {
72              protocol = "AJP/1.3";
73          } else {
74              protocol = null;
75          }
76  
77          if (name == null){
78              throw new IllegalArgumentException("name cannot be null.");
79          }
80  
81          if (container == null){
82              throw new IllegalArgumentException("container cannot be null.");
83          }
84   
85          this.name = name;
86          this.container = container;
87  
88          //Create the Connector object
89          connector = new Connector(protocol);
90  
91  
92          //Set the parameters
93          setParameters(connector, initParams);
94          
95      }
96  
97      /**
98       * Adds any special parameters before constructing the connector.  Note:
99       * all keys and values must be Strings.
100      *
101      * @param protocol Should be one of the constants from WebContainer.
102      * @param params   The map of parameters that will be used to initialize the connector.
103      */
104     protected void initializeParams(String protocol, Map params) {}
105 
106     /**
107      * Ensures that this implementation can handle the requested protocol.
108      * @param protocol
109      */
110     protected void validateProtocol(String protocol) {
111         if(protocol == null) {
112             return;
113         }
114         if(protocol.equals(WebManager.PROTOCOL_HTTPS)) {
115             throw new IllegalArgumentException("Use a HttpsConnectorGBean for an HTTPS connector");
116         } else if(!protocol.equals(WebManager.PROTOCOL_HTTP) && !protocol.equals(WebManager.PROTOCOL_AJP)) {
117             throw new IllegalArgumentException("Unrecognized protocol '"+protocol+"' (use the values of the PROTOCOL_* constants in WebConnector)");
118         }
119     }
120 
121     public String getName() {
122         return name;
123     }
124 
125     public Object getInternalObject() {
126         return connector;
127     }
128 
129     public void doStart() throws LifecycleException {
130         container.addConnector(connector);
131         connector.start();
132         log.debug(name + " connector started");
133    }
134 
135     public void doStop() {
136         try{
137             connector.stop();
138         } catch (LifecycleException e){
139             log.error(e);
140         }
141         container.removeConnector(connector);
142         log.debug(name + " connector stopped");
143     }
144 
145     public void doFail() {
146         log.warn(name + " connector failed");
147         doStop();
148     }
149 
150     public int getDefaultPort() {
151         return getProtocol().equals(WebManager.PROTOCOL_AJP) ? -1 :
152                 getProtocol().equals(WebManager.PROTOCOL_HTTP) ? 80 :
153                 getProtocol().equals(WebManager.PROTOCOL_HTTPS) ? 443 : -1;
154     }
155 
156     public String getConnectUrl() {
157         if(connectHost == null) {
158             String host = getHost();
159             if(host == null || host.equals("0.0.0.0")) {
160                 InetAddress address = null;
161                 try {
162                     address = InetAddress.getLocalHost();
163                 } catch (UnknownHostException e) {
164                     host = "unknown-host";
165                 }
166                 if(address != null) {
167                     host = address.getCanonicalHostName();
168                     if(host == null || host.equals("")) {
169                         host = address.getHostAddress();
170                     }
171                 }
172             }
173             connectHost = host;
174         }
175         return getProtocol().toLowerCase()+"://"+connectHost+(getPort() == getDefaultPort() ? "" : ":"+getPort());
176     }
177 
178     public boolean isEmptySessionPath(){
179         return connector.getEmptySessionPath();
180     }
181     
182     public void setEmptySessionPath(boolean emptySessionPath){
183        connector.setEmptySessionPath(emptySessionPath); 
184     }
185 
186     /**
187      * Gets the network protocol that this connector handles.
188      */
189     public String getProtocol() {
190         String protocol = connector.getProtocol();
191         if(protocol.indexOf("AJP") > -1) {
192             return WebManager.PROTOCOL_AJP;
193         } else if(connector.getScheme().equalsIgnoreCase("http")) {
194             return WebManager.PROTOCOL_HTTP;
195         } else if(connector.getScheme().equalsIgnoreCase("https")) {
196             return WebManager.PROTOCOL_HTTPS;
197         }
198         throw new IllegalStateException("Unknown protocol '"+protocol+"' and scheme '"+connector.getScheme()+"'");
199     }
200 
201     /**
202      * Gets the network port that this connector listens on.
203      */
204     public int getPort() {
205         return connector.getPort();
206     }
207 
208     /**
209      * Sets the network port that this connector listens on.
210      */
211     public void setPort(int port) {
212         connector.setPort(port);
213     }
214 
215     /**
216      * Gets the hostname/IP that this connector listens on.
217      */
218     public String getHost() {
219         Object value = connector.getAttribute("address");
220         if(value == null) {
221             return "0.0.0.0";
222         } else if(value instanceof InetAddress) {
223             return ((InetAddress)value).getHostAddress();
224         } else return value.toString();
225     }
226 
227     /**
228      * Sets the hostname/IP that this connector listens on.  This is typically
229      * most useful for machines with multiple network cards, but can be used
230      * to limit a connector to only listen for connections from the local
231      * machine (127.0.0.1).  To listen on all available network interfaces,
232      * specify an address of 0.0.0.0.
233      */
234     public void setHost(String host) throws UnknownHostException {
235         connector.setAttribute("address", host);
236     }
237 
238     /**
239      * Every connector must specify a property of type InetSocketAddress
240      * because we use that to identify the network services to print a list
241      * during startup.  However, this can be read-only since the host and port
242      * are set separately using setHost and setPort.
243      */
244     public InetSocketAddress getListenAddress() {
245         return new InetSocketAddress(getHost(), getPort());
246     }
247 
248     /**
249      * Gets the size of the buffer used to handle network data for this
250      * connector.
251      */
252     public int getBufferSizeBytes() {
253         Object value = connector.getAttribute("bufferSize");
254         return value == null ? 2048 : Integer.parseInt(value.toString());
255     }
256 
257     /**
258      * Gets the size of the buffer used to handle network data for this
259      * connector.
260      */
261     public void setBufferSizeBytes(int bytes) {
262         connector.setAttribute("bufferSize", new Integer(bytes));
263     }
264 
265     /**
266      * Gets the maximum number of threads used to service connections from
267      * this connector.
268      */
269     public int getMaxThreads() {
270         Object value = connector.getAttribute("maxThreads");
271         return value == null ? 200 : Integer.parseInt(value.toString());
272     }
273 
274     /**
275      * Sets the maximum number of threads used to service connections from
276      * this connector.
277      */
278     public void setMaxThreads(int threads) {
279         connector.setAttribute("maxThreads", new Integer(threads));
280     }
281 
282     /**
283      * Gets the maximum number of connections that may be queued while all
284      * threads are busy.  Any requests received while the queue is full will
285      * be rejected.
286      */
287     public int getAcceptQueueSize() {
288         Object value = connector.getAttribute("acceptCount");
289         return value == null ? 10 : Integer.parseInt(value.toString());
290     }
291 
292     /**
293      * Sets the maximum number of connections that may be queued while all
294      * threads are busy.  Any requests received while the queue is full will
295      * be rejected.
296      */
297     public void setAcceptQueueSize(int size) {
298         connector.setAttribute("acceptCount", new Integer(size));
299     }
300 
301     /**
302      * Gets the amount of time the socket used by this connector will linger
303      * after being closed.  -1 indicates that socket linger is disabled.
304      */
305     public int getLingerMillis() {
306         Object value = connector.getAttribute("connectionLinger");
307         return value == null ? -1 : Integer.parseInt(value.toString());
308     }
309 
310     /**
311      * Sets the amount of time the socket used by this connector will linger
312      * after being closed.  Use -1 to disable socket linger.
313      */
314     public void setLingerMillis(int millis) {
315         connector.setAttribute("connectionLinger", new Integer(millis));
316     }
317 
318     /**
319      * Gets whether the TCP_NODELAY flag is set for the sockets used by this
320      * connector.  This usually enhances performance, so it should typically
321      * be set.
322      */
323     public boolean isTcpNoDelay() {
324         Object value = connector.getAttribute("tcpNoDelay");
325         return value == null ? true : new Boolean(value.toString()).booleanValue();
326     }
327 
328     /**
329      * Sets whether the TCP_NODELAY flag is set for the sockets used by this
330      * connector.  This usually enhances performance, so it should typically
331      * be set.
332      */
333     public void setTcpNoDelay(boolean enable) {
334         connector.setAttribute("tcpNoDelay", new Boolean(enable));
335     }
336 
337     /**
338      * Gets the network port to which traffic will be redirected if this
339      * connector handles insecure traffic and the request requires a secure
340      * connection.  Needless to say, this should point to another connector
341      * configured for SSL.
342      */
343     public int getRedirectPort() {
344         return connector.getRedirectPort();
345     }
346 
347     /**
348      * Gets the network port to which traffic will be redirected if this
349      * connector handles insecure traffic and the request requires a secure
350      * connection.  Needless to say, this should point to another connector
351      * configured for SSL.  If no SSL connector is available, any port can
352      * be used as they all fail equally well.  :)
353      */
354     public void setRedirectPort(int port) {
355         connector.setRedirectPort(port);
356     }
357 
358     public int getMinSpareThreads() {
359         Object value = connector.getAttribute("minSpareThreads");
360         return value == null ? 4 : Integer.parseInt(value.toString());
361     }
362 
363     public void setMinSpareThreads(int threads) {
364         connector.setAttribute("minSpareThreads", new Integer(threads));
365     }
366 
367     public int getMaxSpareThreads() {
368         Object value = connector.getAttribute("maxSpareThreads");
369         return value == null ? 50 : Integer.parseInt(value.toString());
370     }
371 
372     public void setMaxSpareThreads(int threads) {
373         connector.setAttribute("maxSpareThreads", new Integer(threads));
374     }
375 
376     public int getMaxHttpHeaderSizeBytes() {
377         Object value = connector.getAttribute("maxHttpHeaderSize");
378         return value == null ? 4096 : Integer.parseInt(value.toString());
379     }
380 
381     public void setMaxHttpHeaderSizeBytes(int bytes) {
382         connector.setAttribute("maxHttpHeaderSize", new Integer(bytes));
383     }
384 
385     public boolean isHostLookupEnabled() {
386         return connector.getEnableLookups();
387     }
388 
389     public void setHostLookupEnabled(boolean enabled) {
390         connector.setEnableLookups(enabled);
391     }
392 
393     public int getConnectionTimeoutMillis() {
394         Object value = connector.getAttribute("connectionTimeout");
395         return value == null ? 60000 : Integer.parseInt(value.toString());
396     }
397 
398     public void setConnectionTimeoutMillis(int millis) {
399         connector.setAttribute("connectionTimeout", new Integer(millis));
400     }
401 
402     public boolean isUploadTimeoutEnabled() {
403         Object value = connector.getAttribute("disableUploadTimeout");
404         return value == null ? true : !new Boolean(value.toString()).booleanValue();
405     }
406 
407     public void setUploadTimeoutEnabled(boolean enabled) {
408         connector.setAttribute("disableUploadTimeout", new Boolean(!enabled));
409     }
410 
411     public int getMaxPostSize() {
412         int value = connector.getMaxPostSize();
413         return value == 0 ? 2097152 : value;
414     }
415 
416     public void setMaxPostSize(int bytes) {
417         connector.setMaxPostSize(bytes);
418     }
419 
420     public int getMaxSavePostSize() {
421         int value = connector.getMaxSavePostSize();
422         return value == 0 ? 4096 : value;
423     }
424 
425     public void setMaxSavePostSize(int kbytes) {
426         connector.setMaxSavePostSize(kbytes);
427     }
428 
429     public int getMaxKeepAliveRequests() {
430         Object value = connector.getAttribute("maxKeepAliveRequests");
431         return value == null ? 100 : Integer.parseInt(value.toString());
432     }
433 
434     public void setMaxKeepAliveRequests(int maxKeepAliveRequests) {
435         connector.setAttribute("maxKeepAliveRequests", new Integer(maxKeepAliveRequests));
436     }
437 
438     public int getSocketBuffer() {
439         Object value = connector.getAttribute("socketBuffer");
440         return value == null ? 9000 : Integer.parseInt(value.toString());
441     }
442 
443     public void setSocketBuffer(int kbytes) {
444         connector.setAttribute("socketBuffer", new Integer(kbytes));
445     }
446 
447     public boolean getUseBodyEncodingForURI() {
448         return connector.getUseBodyEncodingForURI();
449     }
450 
451     public void setUseBodyEncodingForURI(boolean enabled) {
452         connector.setUseBodyEncodingForURI(enabled);
453     }
454 
455     public void setAllowTrace(boolean allow) {
456         connector.setAllowTrace(allow);
457     }
458 
459     public boolean getAllowTrace() {
460         return connector.getAllowTrace();
461     }
462 
463     public void setProxyName(String proxyName) {
464         connector.setProxyName(proxyName);
465     }
466 
467     public String getProxyName() {
468         return connector.getProxyName();
469     }
470 
471     public void setProxyPort(int port) {
472         connector.setProxyPort(port);
473     }
474 
475     public int getProxyPort() {
476         return connector.getProxyPort();
477     }
478 
479     public void setScheme(String scheme) {
480         connector.setScheme(scheme);
481     }
482 
483     public String getScheme() {
484         return connector.getScheme();
485     }
486 
487     public void setUriEncoding(String encoding) {
488         connector.setURIEncoding(encoding);
489     }
490 
491     public String getUriEncoding() {
492         return connector.getURIEncoding();
493     }
494 
495     public void setUseIPVHosts(boolean useIPVHosts) {
496         connector.setUseIPVHosts(useIPVHosts);
497     }
498 
499     public boolean getUseIPVHosts() {
500         return connector.getUseIPVHosts();
501     }
502 
503     public void setXpoweredBy(boolean xpoweredBy) {
504         connector.setXpoweredBy(xpoweredBy);
505     }
506 
507     public boolean getXpoweredBy() {
508         return connector.getXpoweredBy();
509     }
510 
511     public void setCompressableMimeType(String compressableMimeType) {
512         connector.setAttribute("compressableMimeType", compressableMimeType);
513     }
514 
515     public String getCompressableMimeType() {
516         return (String) connector.getAttribute("compressableMimeType");
517     }
518 
519     public void setCompression(String compression) {
520         connector.setAttribute("compression", compression);
521     }
522 
523     public String getCompression() {
524         return (String) connector.getAttribute("compression");
525     }
526 
527     public void setNoCompressionUserAgents(String noCompressionUserAgents) {
528         connector.setAttribute("noCompressionUserAgents", noCompressionUserAgents);
529     }
530 
531     public String getNoCompressionUserAgents() {
532         return (String) connector.getAttribute("noCompressionUserAgents");
533     }
534 
535     public void setRestrictedUserAgents(String restrictedUserAgents) {
536         connector.setAttribute("restrictedUserAgents", restrictedUserAgents);
537     }
538 
539     public String getRestrictedUserAgents() {
540         return (String) connector.getAttribute("restrictedUserAgents");
541     }
542 
543     public void setThreadPriority(int threadPriority) {
544         connector.setAttribute("threadPriority", new Integer(threadPriority));
545     }
546 
547     public int getThreadPriority() {
548         Object value = connector.getAttribute("threadPriority");
549         return value == null ? 5 :Integer.parseInt(value.toString());
550     }
551 
552     public void setServer(String server) {
553         connector.setAttribute("server", server);
554     }
555 
556     public String getServer() {
557         return (String) connector.getAttribute("server");
558     }
559 
560     public void setStrategy(String strategy) {
561         connector.setAttribute("strategy", strategy);
562     }
563 
564     public String getStrategy() {
565         return (String) connector.getAttribute("strategy");
566     }
567 
568     public static final GBeanInfo GBEAN_INFO;
569 
570     static {
571         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Tomcat Connector", ConnectorGBean.class);
572         infoFactory.addAttribute("name", String.class, true);
573         infoFactory.addAttribute("protocol", String.class, true);
574         infoFactory.addReference(CONNECTOR_CONTAINER_REFERENCE, TomcatContainer.class, NameFactory.GERONIMO_SERVICE);
575         infoFactory.addOperation("getInternalObject");
576         infoFactory.addInterface(TomcatWebConnector.class,
577                 new String[]{
578                         "host",
579                         "port",
580                         "bufferSizeBytes",
581                         "maxThreads",
582                         "acceptQueueSize",
583                         "lingerMillis",
584                         "tcpNoDelay",
585                         "redirectPort",
586                         "minSpareThreads",
587                         "maxSpareThreads",
588                         "maxHttpHeaderSizeBytes",
589                         "hostLookupEnabled",
590                         "connectionTimeoutMillis",
591                         "uploadTimeoutEnabled",
592                         "connectUrl",
593                         "maxPostSize",
594                         "maxSavePostSize",
595                         "emptySessionPath",
596                         "maxKeepAliveRequests",
597                         "socketBuffer",
598                         "useBodyEncodingForURI",
599                         "allowTrace",
600                         "proxyName",
601                         "proxyPort",
602                         "scheme",
603                         "secure",
604                         "uriEncoding",
605                         "useIPVHosts",
606                         "xpoweredBy",
607                         "compressableMimeType",
608                         "compression",
609                         "noCompressionUserAgents",
610                         "restrictedUserAgents",
611                         "threadPriority",
612                         "server",
613                         "strategy"
614                 },
615 
616                 new String[]{
617                         "host",
618                         "port",
619                         "redirectPort",
620                         "maxThreads"});
621         infoFactory.setConstructor(new String[] { "name", "protocol", "host", "port", "TomcatContainer"});
622         GBEAN_INFO = infoFactory.getBeanInfo();
623     }
624 
625     public static GBeanInfo getGBeanInfo() {
626         return GBEAN_INFO;
627     }
628 
629 }