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();
50
51 Map initParams = new HashMap();
52
53 validateProtocol(protocol);
54
55
56 if (host == null){
57 host = "0.0.0.0";
58 }
59
60
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
70
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
89 connector = new Connector(protocol);
90
91
92
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 }