001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.jetty6.connector; 019 020 import java.net.InetAddress; 021 import java.net.InetSocketAddress; 022 import java.net.UnknownHostException; 023 024 import javax.management.j2ee.statistics.Stats; 025 026 import org.apache.geronimo.gbean.GBeanInfo; 027 import org.apache.geronimo.gbean.GBeanInfoBuilder; 028 import org.apache.geronimo.gbean.GBeanLifecycle; 029 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 030 import org.apache.geronimo.jetty6.JettyContainer; 031 import org.apache.geronimo.jetty6.JettyWebConnector; 032 import org.apache.geronimo.management.LazyStatisticsProvider; 033 import org.apache.geronimo.management.geronimo.stats.JettyWebConnectorStatsImpl; 034 import org.apache.geronimo.system.threads.ThreadPool; 035 import org.mortbay.jetty.AbstractConnector; 036 037 /** 038 * Base class for GBeans for Jetty network connectors (HTTP, HTTPS, AJP, etc.). 039 * 040 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 041 */ 042 public abstract class JettyConnector implements GBeanLifecycle, JettyWebConnector, LazyStatisticsProvider { 043 public final static String CONNECTOR_CONTAINER_REFERENCE = "JettyContainer"; 044 private final JettyContainer container; 045 protected final AbstractConnector listener; 046 private JettyWebConnectorStatsImpl stats; // data structure for jsr77 stats 047 private String connectHost; 048 049 /** 050 * Only used to allow declaration as a reference. 051 */ 052 public JettyConnector() { 053 container = null; 054 listener = null; 055 } 056 057 public JettyConnector(JettyContainer container, ThreadPool threadPool) { 058 this.container = container; 059 this.listener = null; 060 } 061 062 public JettyConnector(JettyContainer container, AbstractConnector listener, ThreadPool threadPool, String name) { 063 this.container = container; 064 this.listener = listener; 065 if (threadPool != null) { 066 JettyThreadPool jettyThreadPool = new JettyThreadPool(threadPool, name); 067 listener.setThreadPool(jettyThreadPool); 068 } 069 stats = new JettyWebConnectorStatsImpl(); 070 } 071 072 //TODO: support the jetty6 specific methods 073 public String getHost() { 074 return listener.getHost(); 075 } 076 077 public void setHost(String host) throws UnknownHostException { 078 // underlying impl treats null as 0.0.0.0 079 listener.setHost(host); 080 } 081 082 public int getPort() { 083 return listener.getPort(); 084 } 085 086 public void setPort(int port) { 087 listener.setPort(port); 088 } 089 090 public int getHeaderBufferSizeBytes() { 091 return listener.getHeaderBufferSize(); 092 } 093 public void setHeaderBufferSizeBytes(int size) { 094 listener.setHeaderBufferSize(size); 095 } 096 097 public abstract int getDefaultPort(); 098 099 public String getDefaultScheme() { 100 return null; 101 } 102 103 public String getConnectUrl() { 104 if (connectHost == null) { 105 String host = getHost(); 106 if (host == null || host.equals("0.0.0.0")) { 107 InetAddress address = null; 108 try { 109 address = InetAddress.getLocalHost(); 110 } catch (UnknownHostException e) { 111 host = "unknown-host"; 112 } 113 if (address != null) { 114 host = address.getHostName(); 115 if (host == null || host.equals("")) { 116 host = address.getHostAddress(); 117 } 118 } 119 } 120 connectHost = host; 121 } 122 return getProtocol().toLowerCase() + "://" + connectHost + (getPort() == getDefaultPort() ? "" : ":" + getPort()); 123 } 124 125 public int getMaxIdleTimeMs() { 126 return listener.getMaxIdleTime(); 127 } 128 129 public void setMaxIdleTimeMs(int idleTime) { 130 listener.setMaxIdleTime(idleTime); 131 } 132 133 public int getBufferSizeBytes() { 134 //TODO return the request buffer size, what about the response and header buffer size? 135 return listener.getRequestBufferSize(); 136 } 137 138 public void setBufferSizeBytes(int bytes) { 139 //TODO what about the response and header buffer size? 140 listener.setRequestBufferSize(bytes); 141 } 142 143 public int getAcceptQueueSize() { 144 return listener.getAcceptQueueSize(); 145 } 146 147 public void setAcceptQueueSize(int size) { 148 listener.setAcceptQueueSize(size); 149 } 150 151 public int getLingerMillis() { 152 return (int) ((AbstractConnector) listener).getSoLingerTime(); 153 } 154 155 public void setLingerMillis(int millis) { 156 listener.setSoLingerTime(millis); 157 } 158 159 public boolean isTcpNoDelay() { 160 return true; 161 } 162 163 public void setTcpNoDelay(boolean enable) { 164 throw new UnsupportedOperationException(listener == null ? "No Listener" : listener.getClass().getName()); 165 } 166 167 public void setMaxThreads(int maxThreads) { 168 //TODO: in jetty6 connectors have a number of acceptor threads 169 listener.setAcceptors(maxThreads); 170 } 171 172 public int getMaxThreads() { 173 //TODO: confirm that this is reasonable 174 return listener.getAcceptors(); 175 } 176 177 public int getRedirectPort() { 178 return listener.getConfidentialPort(); 179 } 180 181 public InetSocketAddress getListenAddress() { 182 try { 183 return new InetSocketAddress(InetAddress.getByName(listener.getHost()), listener.getPort()); 184 } catch (UnknownHostException e) { 185 throw new IllegalStateException("InetSocketAddress cannot be determined for host=" + listener.getHost(), e); 186 } 187 } 188 189 public void setRedirectPort(int port) { 190 throw new UnsupportedOperationException("No redirect port on " + this.getClass().getName()); 191 } 192 193 public abstract String getProtocol(); 194 195 public void doStart() throws Exception { 196 container.addListener(listener); 197 listener.start(); 198 } 199 200 public void doStop() { 201 while (true) { 202 try { 203 listener.stop(); 204 container.removeListener(listener); 205 return; 206 } catch (Exception e) { 207 continue; 208 } 209 } 210 } 211 212 public void doFail() { 213 while (true) { 214 try { 215 listener.stop(); 216 container.removeListener(listener); 217 return; 218 } catch (Exception e) { 219 continue; 220 } 221 } 222 } 223 224 public boolean isStatsOn() { 225 return listener.getStatsOn(); 226 } 227 228 public void setStatsOn(boolean on) { 229 listener.setStatsOn(on); 230 if (on) stats.setStartTime(); 231 } 232 233 /** 234 * Gets the statistics collected for this class. 235 * The first call to this method initializes the startTime for 236 * all statistics. 237 * 238 * @return gets collected for this class 239 */ 240 public Stats getStats() { 241 if(isStatsOn()) { 242 stats.setLastSampleTime(); 243 // connections open 244 stats.getOpenConnectionCountImpl().setCurrent(listener.getConnectionsOpen()); 245 stats.getOpenConnectionCountImpl().setHighWaterMark(listener.getConnectionsOpenMax()); 246 stats.getOpenConnectionCountImpl().setLowWaterMark(listener.getConnectionsOpenMin()); 247 // request count 248 stats.getRequestCountImpl().setCount(listener.getRequests()); 249 // connections count and durations 250 stats.getConnectionsDurationImpl().setCount(listener.getConnections()); 251 stats.getConnectionsDurationImpl().setMaxTime(listener.getConnectionsDurationMax()); 252 stats.getConnectionsDurationImpl().setMinTime(listener.getConnectionsDurationMin()); 253 stats.getConnectionsDurationImpl().setTotalTime(listener.getConnectionsDurationTotal()); 254 // requests per connection (connection requests) 255 stats.getConnectionsRequestImpl().setCurrent(listener.getConnectionsRequestsAve()); 256 stats.getConnectionsRequestImpl().setHighWaterMark(listener.getConnectionsRequestsMax()); 257 stats.getConnectionsRequestImpl().setLowWaterMark(listener.getConnectionsRequestsMin()); 258 } 259 return stats; 260 } 261 262 /** 263 * Reset the startTime for all statistics 264 */ 265 public void resetStats() { 266 listener.statsReset(); 267 stats.setStartTime(); // sets atartTime for all stats to Now 268 } 269 270 public boolean isStateManageable() { 271 return true; 272 } 273 274 public boolean isStatisticsProvider() { 275 return true; 276 } 277 278 public static final GBeanInfo GBEAN_INFO; 279 280 static { 281 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Jetty HTTP Connector", JettyConnector.class); 282 infoFactory.addReference(CONNECTOR_CONTAINER_REFERENCE, JettyContainer.class, NameFactory.GERONIMO_SERVICE); 283 infoFactory.addReference("ThreadPool", ThreadPool.class, NameFactory.GERONIMO_SERVICE); 284 // this is needed because the getters/setters are not added automatically 285 infoFactory.addOperation("setStatsOn", new Class[] { boolean.class }, "void"); 286 // removed 'minThreads' from persistent and manageable String[] 287 // removed 'tcpNoDelay' from persistent String[] 288 // added 'protocol' to persistent and manageable String[] 289 infoFactory.addInterface(JettyWebConnector.class, 290 new String[]{"host", "port", "minThreads", "maxThreads", "bufferSizeBytes", "headerBufferSizeBytes", "acceptQueueSize", "lingerMillis", "protocol", "redirectPort", "connectUrl", "maxIdleTimeMs"}, 291 new String[]{"host", "port", "minThreads", "maxThreads", "bufferSizeBytes", "headerBufferSizeBytes", "acceptQueueSize", "lingerMillis", "protocol", "redirectPort"}); 292 infoFactory.setConstructor(new String[]{"JettyContainer", "ThreadPool"}); 293 GBEAN_INFO = infoFactory.getBeanInfo(); 294 } 295 }