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: */package org.apache.geronimo.jetty6;
017:
018: import java.util.ArrayList;
019: import java.util.Arrays;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Map.Entry;
025: import java.util.Set;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.geronimo.gbean.AbstractName;
030: import org.apache.geronimo.gbean.AbstractNameQuery;
031: import org.apache.geronimo.gbean.GBeanData;
032: import org.apache.geronimo.gbean.GBeanInfo;
033: import org.apache.geronimo.gbean.GBeanInfoBuilder;
034: import org.apache.geronimo.gbean.ReferencePatterns;
035: import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
036: import org.apache.geronimo.jetty6.connector.AJP13Connector;
037: import org.apache.geronimo.jetty6.connector.HTTPBlockingConnector;
038: import org.apache.geronimo.jetty6.connector.HTTPSSelectChannelConnector;
039: import org.apache.geronimo.jetty6.connector.HTTPSSocketConnector;
040: import org.apache.geronimo.jetty6.connector.HTTPSelectChannelConnector;
041: import org.apache.geronimo.jetty6.connector.HTTPSocketConnector;
042: import org.apache.geronimo.jetty6.connector.JettyConnector;
043: import org.apache.geronimo.jetty6.requestlog.JettyLogManager;
044: import org.apache.geronimo.kernel.GBeanNotFoundException;
045: import org.apache.geronimo.kernel.Kernel;
046: import org.apache.geronimo.kernel.config.ConfigurationUtil;
047: import org.apache.geronimo.kernel.config.EditableConfigurationManager;
048: import org.apache.geronimo.kernel.config.InvalidConfigException;
049: import org.apache.geronimo.kernel.proxy.ProxyManager;
050: import org.apache.geronimo.management.geronimo.KeystoreManager;
051: import org.apache.geronimo.management.geronimo.NetworkConnector;
052: import org.apache.geronimo.management.geronimo.WebAccessLog;
053: import org.apache.geronimo.management.geronimo.WebContainer;
054: import org.apache.geronimo.management.geronimo.WebManager;
055: import org.apache.geronimo.management.geronimo.WebManager.ConnectorAttribute;
056:
057: /**
058: * Jetty implementation of WebManager. Knows how to manipulate
059: * other Jetty objects for management purposes.
060: *
061: * @version $Rev:386276 $ $Date: 2007-11-06 12:06:33 -0800 (Tue, 06 Nov 2007) $
062: */
063: public class JettyManagerImpl implements WebManager {
064: private final static Log log = LogFactory
065: .getLog(JettyManagerImpl.class);
066:
067: private static final ConnectorType HTTP_NIO = new ConnectorType(
068: Messages.getString("JettyManagerImpl.0")); //$NON-NLS-1$
069: private static final ConnectorType HTTPS_NIO = new ConnectorType(
070: Messages.getString("JettyManagerImpl.1")); //$NON-NLS-1$
071: private static final ConnectorType HTTP_BLOCKING_NIO = new ConnectorType(
072: Messages.getString("JettyManagerImpl.2")); //$NON-NLS-1$
073: private static final ConnectorType HTTP_BIO = new ConnectorType(
074: Messages.getString("JettyManagerImpl.3")); //$NON-NLS-1$
075: private static final ConnectorType HTTPS_BIO = new ConnectorType(
076: Messages.getString("JettyManagerImpl.4")); //$NON-NLS-1$
077: private static final ConnectorType AJP_NIO = new ConnectorType(
078: Messages.getString("JettyManagerImpl.5")); //$NON-NLS-1$
079: private static List<ConnectorType> CONNECTOR_TYPES = Arrays.asList(
080: HTTP_NIO, HTTPS_NIO, HTTP_BLOCKING_NIO, HTTP_BIO,
081: HTTPS_BIO, AJP_NIO);
082:
083: private static Map<ConnectorType, List<ConnectorAttribute>> CONNECTOR_ATTRIBUTES = new HashMap<ConnectorType, List<ConnectorAttribute>>();
084:
085: static {
086: List<ConnectorAttribute> connectorAttributes = new ArrayList<ConnectorAttribute>();
087: addCommonConnectorAttributes(connectorAttributes);
088: CONNECTOR_ATTRIBUTES.put(HTTP_NIO, connectorAttributes);
089:
090: connectorAttributes = new ArrayList<ConnectorAttribute>();
091: addCommonConnectorAttributes(connectorAttributes);
092: addSslConnectorAttributes(connectorAttributes);
093: setAttribute(connectorAttributes, "port", 8443); // SSL port
094: CONNECTOR_ATTRIBUTES.put(HTTPS_NIO, connectorAttributes);
095:
096: connectorAttributes = new ArrayList<ConnectorAttribute>();
097: addCommonConnectorAttributes(connectorAttributes);
098: CONNECTOR_ATTRIBUTES.put(HTTP_BIO, connectorAttributes);
099:
100: connectorAttributes = new ArrayList<ConnectorAttribute>();
101: addCommonConnectorAttributes(connectorAttributes);
102: addSslConnectorAttributes(connectorAttributes);
103: setAttribute(connectorAttributes, "port", 8443); // SSL port
104: CONNECTOR_ATTRIBUTES.put(HTTPS_BIO, connectorAttributes);
105:
106: connectorAttributes = new ArrayList<ConnectorAttribute>();
107: addCommonConnectorAttributes(connectorAttributes);
108: CONNECTOR_ATTRIBUTES
109: .put(HTTP_BLOCKING_NIO, connectorAttributes);
110:
111: connectorAttributes = new ArrayList<ConnectorAttribute>();
112: addCommonConnectorAttributes(connectorAttributes);
113: CONNECTOR_ATTRIBUTES.put(AJP_NIO, connectorAttributes);
114:
115: }
116:
117: private static Map<ConnectorType, GBeanInfo> CONNECTOR_GBEAN_INFOS = new HashMap<ConnectorType, GBeanInfo>();
118:
119: static {
120: CONNECTOR_GBEAN_INFOS.put(HTTP_NIO,
121: HTTPSelectChannelConnector.GBEAN_INFO);
122: CONNECTOR_GBEAN_INFOS.put(HTTPS_NIO,
123: HTTPSSelectChannelConnector.GBEAN_INFO);
124: CONNECTOR_GBEAN_INFOS.put(HTTP_BLOCKING_NIO,
125: HTTPBlockingConnector.GBEAN_INFO);
126: CONNECTOR_GBEAN_INFOS.put(HTTP_BIO,
127: HTTPSocketConnector.GBEAN_INFO);
128: CONNECTOR_GBEAN_INFOS.put(HTTPS_BIO,
129: HTTPSSocketConnector.GBEAN_INFO);
130: CONNECTOR_GBEAN_INFOS.put(AJP_NIO, AJP13Connector.GBEAN_INFO);
131: }
132:
133: private final Kernel kernel;
134:
135: public JettyManagerImpl(Kernel kernel) {
136: this .kernel = kernel;
137: }
138:
139: public String getProductName() {
140: return "Jetty";
141: }
142:
143: /**
144: * Get a list of containers for this web implementation.
145: */
146: public Object[] getContainers() {
147: ProxyManager proxyManager = kernel.getProxyManager();
148: AbstractNameQuery query = new AbstractNameQuery(
149: JettyContainer.class.getName());
150: Set names = kernel.listGBeans(query);
151: JettyContainer[] results = new JettyContainer[names.size()];
152: int i = 0;
153: for (Iterator it = names.iterator(); it.hasNext(); i++) {
154: AbstractName name = (AbstractName) it.next();
155: results[i] = (JettyContainer) proxyManager.createProxy(
156: name, JettyContainer.class.getClassLoader());
157: }
158: return results;
159: }
160:
161: /**
162: * Gets the protocols that this web container supports (that you can create
163: * connectors for).
164: */
165: public String[] getSupportedProtocols() {
166: return new String[] { PROTOCOL_HTTP, PROTOCOL_HTTPS,
167: PROTOCOL_AJP };
168: }
169:
170: /**
171: * Removes a connector. This shuts it down if necessary, and removes it
172: * from the server environment. It must be a connector that this container
173: * is responsible for.
174: *
175: * @param connectorName
176: */
177: public void removeConnector(AbstractName connectorName) {
178: try {
179: GBeanInfo info = kernel.getGBeanInfo(connectorName);
180: boolean found = false;
181: Set intfs = info.getInterfaces();
182: for (Iterator it = intfs.iterator(); it.hasNext();) {
183: String intf = (String) it.next();
184: if (intf.equals(JettyWebConnector.class.getName())) {
185: found = true;
186: }
187: }
188: if (!found) {
189: throw new GBeanNotFoundException(connectorName);
190: }
191: EditableConfigurationManager mgr = ConfigurationUtil
192: .getEditableConfigurationManager(kernel);
193: if (mgr != null) {
194: try {
195: mgr.removeGBeanFromConfiguration(connectorName
196: .getArtifact(), connectorName);
197: } catch (InvalidConfigException e) {
198: log.error("Unable to add GBean", e);
199: } finally {
200: ConfigurationUtil.releaseConfigurationManager(
201: kernel, mgr);
202: }
203: } else {
204: log
205: .warn("The ConfigurationManager in the kernel does not allow editing");
206: }
207: } catch (GBeanNotFoundException e) {
208: log.warn("No such GBean '" + connectorName + "'"); //todo: what if we want to remove a failed GBean?
209: } catch (Exception e) {
210: log.error(e);
211: }
212: }
213:
214: /**
215: * Gets the ObjectNames of any existing connectors for the specified
216: * protocol.
217: *
218: * @param protocol A protocol as returned by getSupportedProtocols
219: */
220: public NetworkConnector[] getConnectors(String protocol) {
221: if (protocol == null) {
222: return getConnectors();
223: }
224: List result = new ArrayList();
225: ProxyManager proxyManager = kernel.getProxyManager();
226: AbstractNameQuery query = new AbstractNameQuery(
227: JettyWebConnector.class.getName());
228: Set names = kernel.listGBeans(query);
229: for (Iterator it = names.iterator(); it.hasNext();) {
230: AbstractName name = (AbstractName) it.next();
231: try {
232: if (kernel.getAttribute(name, "protocol").equals(
233: protocol)) {
234: result.add(proxyManager.createProxy(name,
235: JettyWebConnector.class.getClassLoader()));
236: }
237: } catch (Exception e) {
238: log.error(
239: "Unable to check the protocol for a connector",
240: e);
241: }
242: }
243: return (JettyWebConnector[]) result
244: .toArray(new JettyWebConnector[names.size()]);
245: }
246:
247: public WebAccessLog getAccessLog(WebContainer container) {
248: AbstractNameQuery query = new AbstractNameQuery(
249: JettyLogManager.class.getName());
250: Set names = kernel.listGBeans(query);
251: if (names.size() == 0) {
252: return null;
253: } else if (names.size() > 1) {
254: throw new IllegalStateException(
255: "Should not be more than one Jetty access log manager");
256: }
257: return (WebAccessLog) kernel.getProxyManager().createProxy(
258: (AbstractName) names.iterator().next(),
259: JettyLogManager.class.getClassLoader());
260: }
261:
262: public List<ConnectorType> getConnectorTypes() {
263: return CONNECTOR_TYPES;
264: }
265:
266: public List<ConnectorAttribute> getConnectorAttributes(
267: ConnectorType connectorType) {
268: return ConnectorAttribute.copy(CONNECTOR_ATTRIBUTES
269: .get(connectorType));
270: }
271:
272: public AbstractName getConnectorConfiguration(
273: ConnectorType connectorType,
274: List<ConnectorAttribute> connectorAttributes,
275: WebContainer container, String uniqueName) {
276: GBeanInfo gbeanInfo = CONNECTOR_GBEAN_INFOS.get(connectorType);
277: AbstractName containerName = kernel
278: .getAbstractNameFor(container);
279: AbstractName name = kernel.getNaming()
280: .createSiblingName(containerName, uniqueName,
281: NameFactory.GERONIMO_SERVICE);
282: GBeanData gbeanData = new GBeanData(name, gbeanInfo);
283: gbeanData.setReferencePattern(
284: JettyConnector.CONNECTOR_CONTAINER_REFERENCE,
285: containerName);
286: for (ConnectorAttribute connectorAttribute : connectorAttributes) {
287: Object value = connectorAttribute.getValue();
288: if (value != null) {
289: gbeanData.setAttribute(connectorAttribute
290: .getAttributeName(), connectorAttribute
291: .getValue());
292: }
293: }
294:
295: // provide a reference to KeystoreManager gbean for HTTPS connectors
296: if (connectorType.equals(HTTPS_NIO)
297: || connectorType.equals(HTTPS_BIO)) {
298: AbstractNameQuery query = new AbstractNameQuery(
299: KeystoreManager.class.getName());
300: gbeanData.setReferencePattern("KeystoreManager", query);
301: }
302:
303: EditableConfigurationManager mgr = ConfigurationUtil
304: .getEditableConfigurationManager(kernel);
305: if (mgr != null) {
306: try {
307: mgr.addGBeanToConfiguration(
308: containerName.getArtifact(), gbeanData, false);
309: } catch (InvalidConfigException e) {
310: log.error("Unable to add GBean", e);
311: return null;
312: } finally {
313: ConfigurationUtil.releaseConfigurationManager(kernel,
314: mgr);
315: }
316: } else {
317: log
318: .warn("The ConfigurationManager in the kernel does not allow editing");
319: return null;
320: }
321: return name;
322: }
323:
324: public ConnectorType getConnectorType(AbstractName connectorName) {
325: ConnectorType connectorType = null;
326: try {
327: GBeanInfo info = kernel.getGBeanInfo(connectorName);
328: boolean found = false;
329: Set intfs = info.getInterfaces();
330: for (Iterator it = intfs.iterator(); it.hasNext() && !found;) {
331: String intf = (String) it.next();
332: if (intf.equals(JettyWebConnector.class.getName())) {
333: found = true;
334: }
335: }
336: if (!found) {
337: throw new GBeanNotFoundException(connectorName);
338: }
339: String searchingFor = info.getName();
340: for (Entry<ConnectorType, GBeanInfo> entry : CONNECTOR_GBEAN_INFOS
341: .entrySet()) {
342: String candidate = entry.getValue().getName();
343: if (candidate.equals(searchingFor)) {
344: return entry.getKey();
345: }
346: }
347: } catch (GBeanNotFoundException e) {
348: log.warn("No such GBean '" + connectorName + "'");
349: } catch (Exception e) {
350: log.error(e);
351: }
352:
353: return connectorType;
354: }
355:
356: /**
357: * Gets the ObjectNames of any existing connectors.
358: */
359: public NetworkConnector[] getConnectors() {
360: ProxyManager proxyManager = kernel.getProxyManager();
361: AbstractNameQuery query = new AbstractNameQuery(
362: JettyWebConnector.class.getName());
363: Set names = kernel.listGBeans(query);
364: JettyWebConnector[] results = new JettyWebConnector[names
365: .size()];
366: int i = 0;
367: for (Iterator it = names.iterator(); it.hasNext(); i++) {
368: AbstractName name = (AbstractName) it.next();
369: results[i] = (JettyWebConnector) proxyManager.createProxy(
370: name, JettyWebConnector.class.getClassLoader());
371: }
372: return results;
373: }
374:
375: public NetworkConnector[] getConnectorsForContainer(
376: Object container, String protocol) {
377: if (protocol == null) {
378: return getConnectorsForContainer(container);
379: }
380: AbstractName containerName = kernel
381: .getAbstractNameFor(container);
382: ProxyManager mgr = kernel.getProxyManager();
383: try {
384: List results = new ArrayList();
385: AbstractNameQuery query = new AbstractNameQuery(
386: JettyWebConnector.class.getName());
387: Set set = kernel.listGBeans(query); // all Jetty connectors
388: for (Iterator it = set.iterator(); it.hasNext();) {
389: AbstractName name = (AbstractName) it.next(); // a single Jetty connector
390: GBeanData data = kernel.getGBeanData(name);
391: ReferencePatterns refs = data
392: .getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE);
393: if (containerName.equals(refs.getAbstractName())) {
394: try {
395: String testProtocol = (String) kernel
396: .getAttribute(name, "protocol");
397: if (testProtocol != null
398: && testProtocol.equals(protocol)) {
399: results.add(mgr.createProxy(name,
400: JettyWebConnector.class
401: .getClassLoader()));
402: }
403: } catch (Exception e) {
404: log.error(
405: "Unable to look up protocol for connector '"
406: + name + "'", e);
407: }
408: break;
409: }
410: }
411: return (JettyWebConnector[]) results
412: .toArray(new JettyWebConnector[results.size()]);
413: } catch (Exception e) {
414: throw (IllegalArgumentException) new IllegalArgumentException(
415: "Unable to look up connectors for Jetty container '"
416: + containerName + "': ").initCause(e);
417: }
418: }
419:
420: public NetworkConnector[] getConnectorsForContainer(Object container) {
421: AbstractName containerName = kernel
422: .getAbstractNameFor(container);
423: ProxyManager mgr = kernel.getProxyManager();
424: try {
425: List results = new ArrayList();
426: AbstractNameQuery query = new AbstractNameQuery(
427: JettyWebConnector.class.getName());
428: Set set = kernel.listGBeans(query); // all Jetty connectors
429: for (Iterator it = set.iterator(); it.hasNext();) {
430: AbstractName name = (AbstractName) it.next(); // a single Jetty connector
431: GBeanData data = kernel.getGBeanData(name);
432: ReferencePatterns refs = data
433: .getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE);
434: if (containerName.equals(refs.getAbstractName())) {
435: results.add(mgr.createProxy(name,
436: JettyWebConnector.class.getClassLoader()));
437: }
438: }
439: return (JettyWebConnector[]) results
440: .toArray(new JettyWebConnector[results.size()]);
441: } catch (Exception e) {
442: throw (IllegalArgumentException) new IllegalArgumentException(
443: "Unable to look up connectors for Jetty container '"
444: + containerName + "'").initCause(e);
445: }
446: }
447:
448: private static void addCommonConnectorAttributes(
449: List<ConnectorAttribute> connectorAttributes) {
450: connectorAttributes
451: .add(new ConnectorAttribute<String>(
452: "host", "0.0.0.0", Messages.getString("JettyManagerImpl.30"), String.class, true)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
453: connectorAttributes
454: .add(new ConnectorAttribute<Integer>(
455: "port", 8080, Messages.getString("JettyManagerImpl.32"), Integer.class, true)); //$NON-NLS-1$ //$NON-NLS-2$
456: connectorAttributes
457: .add(new ConnectorAttribute<Integer>(
458: "maxThreads", 10, Messages.getString("JettyManagerImpl.34"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
459: connectorAttributes
460: .add(new ConnectorAttribute<Integer>(
461: "bufferSizeBytes", 8096, Messages.getString("JettyManagerImpl.36"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
462: connectorAttributes
463: .add(new ConnectorAttribute<Integer>(
464: "headerBufferSizeBytes", 8192, Messages.getString("JettyManagerImpl.57"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
465: connectorAttributes
466: .add(new ConnectorAttribute<Integer>(
467: "acceptQueueSize", 10, Messages.getString("JettyManagerImpl.38"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
468: connectorAttributes
469: .add(new ConnectorAttribute<Integer>(
470: "lingerMillis", 30000, Messages.getString("JettyManagerImpl.40"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
471: //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "If true then setTcpNoDelay(true) is called on accepted sockets.", Boolean.class));
472: connectorAttributes
473: .add(new ConnectorAttribute<Integer>(
474: "redirectPort", 8443, Messages.getString("JettyManagerImpl.42"), Integer.class)); //$NON-NLS-1$ //$NON-NLS-2$
475: //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, " The time in milliseconds that a connection can be idle before being closed.", Integer.class));
476: }
477:
478: private static void addSslConnectorAttributes(
479: List<ConnectorAttribute> connectorAttributes) {
480: //connectorAttributes.add(new ConnectorAttribute<Boolean>("clientAuthRequested", false, "clientAuthRequested", Boolean.class));
481: connectorAttributes
482: .add(new ConnectorAttribute<Boolean>(
483: "clientAuthRequired", false, Messages.getString("JettyManagerImpl.44"), Boolean.class)); //$NON-NLS-1$ //$NON-NLS-2$
484: connectorAttributes
485: .add(new ConnectorAttribute<String>(
486: "keyStore", "", Messages.getString("JettyManagerImpl.47"), String.class, true)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
487: connectorAttributes
488: .add(new ConnectorAttribute<String>(
489: "trustStore", "", Messages.getString("JettyManagerImpl.50"), String.class)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
490: //connectorAttributes.add(new ConnectorAttribute<String>("keyAlias", "", "keyAlias", String.class, true));
491: connectorAttributes
492: .add(new ConnectorAttribute<String>(
493: "secureProtocol", "", Messages.getString("JettyManagerImpl.53"), String.class)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
494: connectorAttributes
495: .add(new ConnectorAttribute<String>(
496: "algorithm", "Default", Messages.getString("JettyManagerImpl.56"), String.class)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
497: }
498:
499: private static <T> void setAttribute(
500: List<ConnectorAttribute> connectorAttributes,
501: String attributeName, T value) {
502: for (ConnectorAttribute connectorAttribute : connectorAttributes) {
503: if (connectorAttribute.getAttributeName().equals(
504: attributeName)) {
505: connectorAttribute.setValue(value);
506: return;
507: }
508: }
509: }
510:
511: public static final GBeanInfo GBEAN_INFO;
512:
513: static {
514: GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(
515: "Jetty Web Manager", JettyManagerImpl.class);
516: infoFactory.addAttribute("kernel", Kernel.class, false);
517: infoFactory.addInterface(WebManager.class);
518: infoFactory.setConstructor(new String[] { "kernel" });
519: GBEAN_INFO = infoFactory.getBeanInfo();
520: }
521:
522: public static GBeanInfo getGBeanInfo() {
523: return GBEAN_INFO;
524: }
525: }
|