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 }