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    package org.apache.geronimo.jetty6;
018    
019    import java.util.ArrayList;
020    import java.util.Arrays;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.Map.Entry;
026    import java.util.Set;
027    
028    import org.apache.commons.logging.Log;
029    import org.apache.commons.logging.LogFactory;
030    import org.apache.geronimo.gbean.AbstractName;
031    import org.apache.geronimo.gbean.AbstractNameQuery;
032    import org.apache.geronimo.gbean.GBeanData;
033    import org.apache.geronimo.gbean.GBeanInfo;
034    import org.apache.geronimo.gbean.GBeanInfoBuilder;
035    import org.apache.geronimo.gbean.ReferencePatterns;
036    import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
037    import org.apache.geronimo.jetty6.connector.AJP13Connector;
038    import org.apache.geronimo.jetty6.connector.HTTPBlockingConnector;
039    import org.apache.geronimo.jetty6.connector.HTTPSSelectChannelConnector;
040    import org.apache.geronimo.jetty6.connector.HTTPSSocketConnector;
041    import org.apache.geronimo.jetty6.connector.HTTPSelectChannelConnector;
042    import org.apache.geronimo.jetty6.connector.HTTPSocketConnector;
043    import org.apache.geronimo.jetty6.connector.JettyConnector;
044    import org.apache.geronimo.jetty6.requestlog.JettyLogManager;
045    import org.apache.geronimo.kernel.GBeanNotFoundException;
046    import org.apache.geronimo.kernel.Kernel;
047    import org.apache.geronimo.kernel.config.ConfigurationUtil;
048    import org.apache.geronimo.kernel.config.EditableConfigurationManager;
049    import org.apache.geronimo.kernel.config.InvalidConfigException;
050    import org.apache.geronimo.kernel.proxy.ProxyManager;
051    import org.apache.geronimo.management.geronimo.KeystoreManager;
052    import org.apache.geronimo.management.geronimo.NetworkConnector;
053    import org.apache.geronimo.management.geronimo.WebAccessLog;
054    import org.apache.geronimo.management.geronimo.WebContainer;
055    import org.apache.geronimo.management.geronimo.WebManager;
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-08-02 20:28:32 -0400 (Thu, 02 Aug 2007) $
062     */
063    public class JettyManagerImpl implements WebManager {
064        private final static Log log = LogFactory.getLog(JettyManagerImpl.class);
065    
066        private static final ConnectorType HTTP_NIO = new ConnectorType("Jetty NIO HTTP Connector");
067        private static final ConnectorType HTTPS_NIO = new ConnectorType("Jetty NIO HTTPS Connector");
068        private static final ConnectorType HTTP_BLOCKING_NIO = new ConnectorType("Jetty Blocking HTTP Connector using NIO");
069        private static final ConnectorType HTTP_BIO = new ConnectorType("Jetty BIO HTTP Connector");
070        private static final ConnectorType HTTPS_BIO = new ConnectorType("Jetty BIO HTTPS Connector");
071        private static final ConnectorType AJP_NIO = new ConnectorType("Jetty NIO AJP Connector");
072        private static List<ConnectorType> CONNECTOR_TYPES = Arrays.asList(
073                HTTP_NIO,
074                HTTPS_NIO,
075                HTTP_BLOCKING_NIO,
076                HTTP_BIO,
077                HTTPS_BIO,
078                AJP_NIO
079        );
080    
081        private static Map<ConnectorType, List<ConnectorAttribute>> CONNECTOR_ATTRIBUTES = new HashMap<ConnectorType, List<ConnectorAttribute>>();
082    
083        static {
084            List<ConnectorAttribute> connectorAttributes = new ArrayList<ConnectorAttribute>();
085            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
086            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8080, "The network port to bind to.", Integer.class, true));
087            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
088            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
089            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
090            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
091            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
092            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
093            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
094            CONNECTOR_ATTRIBUTES.put(HTTP_NIO, connectorAttributes);
095    
096            connectorAttributes = new ArrayList<ConnectorAttribute>();
097            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
098            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8443, "The network port to bind to.", Integer.class, true));
099            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
100            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
101            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
102            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
103            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
104            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
105            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
106            //connectorAttributes.add(new ConnectorAttribute<Boolean>("clientAuthRequested", false, "clientAuthRequested", Boolean.class));
107            connectorAttributes.add(new ConnectorAttribute<Boolean>("clientAuthRequired", false, "If set, then clients connecting through this connector must supply a valid client certificate.", Boolean.class));
108            connectorAttributes.add(new ConnectorAttribute<String>("keyStore", "", "The keystore to use for accessing the server's private key", String.class, true));
109            connectorAttributes.add(new ConnectorAttribute<String>("trustStore", "", "The keystore containing the trusted certificate entries, including Certification Authority (CA) certificates", String.class));
110            //connectorAttributes.add(new ConnectorAttribute<String>("keyAlias", "", "keyAlias", String.class, true));
111            connectorAttributes.add(new ConnectorAttribute<String>("secureProtocol", "", "This should normally be set to TLS, though some (IBM) JVMs don't work properly with popular browsers unless it is changed to SSL.", String.class));
112            connectorAttributes.add(new ConnectorAttribute<String>("algorithm", "Default", "This should normally be set to match the JVM vendor.", String.class));
113            CONNECTOR_ATTRIBUTES.put(HTTPS_NIO, connectorAttributes);
114    
115            connectorAttributes = new ArrayList<ConnectorAttribute>();
116            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
117            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8080, "The network port to bind to.", Integer.class, true));
118            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
119            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
120            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
121            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
122            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
123            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
124            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
125            CONNECTOR_ATTRIBUTES.put(HTTP_BIO, connectorAttributes);
126    
127            connectorAttributes = new ArrayList<ConnectorAttribute>();
128            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
129            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8443, "The network port to bind to.", Integer.class, true));
130            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
131            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
132            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
133            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
134            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
135            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
136            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
137            //connectorAttributes.add(new ConnectorAttribute<Boolean>("clientAuthRequested", false, "clientAuthRequested", Boolean.class));
138            connectorAttributes.add(new ConnectorAttribute<Boolean>("clientAuthRequired", false, "If set, then clients connecting through this connector must supply a valid client certificate.", Boolean.class));
139            connectorAttributes.add(new ConnectorAttribute<String>("keyStore", "", "The keystore to use for accessing the server's private key", String.class, true));
140            connectorAttributes.add(new ConnectorAttribute<String>("trustStore", "", "The keystore containing the trusted certificate entries, including Certification Authority (CA) certificates", String.class));
141            //connectorAttributes.add(new ConnectorAttribute<String>("keyAlias", "", "keyAlias", String.class, true));
142            connectorAttributes.add(new ConnectorAttribute<String>("secureProtocol", "", "This should normally be set to TLS, though some (IBM) JVMs don't work properly with popular browsers unless it is changed to SSL.", String.class));
143            connectorAttributes.add(new ConnectorAttribute<String>("algorithm", "Default", "This should normally be set to match the JVM vendor.", String.class));
144            CONNECTOR_ATTRIBUTES.put(HTTPS_BIO, connectorAttributes);
145    
146            connectorAttributes = new ArrayList<ConnectorAttribute>();
147            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
148            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8080, "The network port to bind to.", Integer.class, true));
149            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
150            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
151            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
152            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
153            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
154            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
155            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
156            CONNECTOR_ATTRIBUTES.put(HTTP_BLOCKING_NIO, connectorAttributes);
157    
158            connectorAttributes = new ArrayList<ConnectorAttribute>();
159            connectorAttributes.add(new ConnectorAttribute<String>("host", "0.0.0.0", "The host name or IP to bind to. The normal values are 0.0.0.0 (all interfaces) or localhost (local connections only)", String.class, true));
160            connectorAttributes.add(new ConnectorAttribute<Integer>("port", 8009, "The network port to bind to.", Integer.class, true));
161            connectorAttributes.add(new ConnectorAttribute<Integer>("maxThreads", 10, "The maximum number of threads this connector should use to handle incoming requests", Integer.class));
162            connectorAttributes.add(new ConnectorAttribute<Integer>("bufferSizeBytes", 8096, "Buffer size", Integer.class));
163            connectorAttributes.add(new ConnectorAttribute<Integer>("acceptQueueSize", 10, "acceptQueueSize", Integer.class));
164            connectorAttributes.add(new ConnectorAttribute<Integer>("lingerMillis", 30000, "lingerMillis", Integer.class));
165            //connectorAttributes.add(new ConnectorAttribute<Boolean>("tcpNoDelay", false, "tcpNoDelay", Boolean.class));
166            connectorAttributes.add(new ConnectorAttribute<Integer>("redirectPort", 8443, "redirectPort", Integer.class));
167            //connectorAttributes.add(new ConnectorAttribute<Integer>("maxIdleTimeMs", 30000, "maxIdleTimeMs", Integer.class));
168            CONNECTOR_ATTRIBUTES.put(AJP_NIO, connectorAttributes);
169    
170        }
171    
172        private static Map<ConnectorType, GBeanInfo> CONNECTOR_GBEAN_INFOS = new HashMap<ConnectorType, GBeanInfo>();
173    
174        static {
175            CONNECTOR_GBEAN_INFOS.put(HTTP_NIO, HTTPSelectChannelConnector.GBEAN_INFO);
176            CONNECTOR_GBEAN_INFOS.put(HTTPS_NIO, HTTPSSelectChannelConnector.GBEAN_INFO);
177            CONNECTOR_GBEAN_INFOS.put(HTTP_BLOCKING_NIO, HTTPBlockingConnector.GBEAN_INFO);
178            CONNECTOR_GBEAN_INFOS.put(HTTP_BIO, HTTPSocketConnector.GBEAN_INFO);
179            CONNECTOR_GBEAN_INFOS.put(HTTPS_BIO, HTTPSSocketConnector.GBEAN_INFO);
180            CONNECTOR_GBEAN_INFOS.put(AJP_NIO, AJP13Connector.GBEAN_INFO);
181        }
182    
183        private final Kernel kernel;
184    
185        public JettyManagerImpl(Kernel kernel) {
186            this.kernel = kernel;
187        }
188    
189        public String getProductName() {
190            return "Jetty";
191        }
192    
193        /**
194         * Get a list of containers for this web implementation.
195         */
196        public Object[] getContainers() {
197            ProxyManager proxyManager = kernel.getProxyManager();
198            AbstractNameQuery query = new AbstractNameQuery(JettyContainer.class.getName());
199            Set names = kernel.listGBeans(query);
200            JettyContainer[] results = new JettyContainer[names.size()];
201            int i = 0;
202            for (Iterator it = names.iterator(); it.hasNext(); i++) {
203                AbstractName name = (AbstractName) it.next();
204                results[i] = (JettyContainer) proxyManager.createProxy(name, JettyContainer.class.getClassLoader());
205            }
206            return results;
207        }
208    
209        /**
210         * Gets the protocols that this web container supports (that you can create
211         * connectors for).
212         */
213        public String[] getSupportedProtocols() {
214            return new String[]{PROTOCOL_HTTP, PROTOCOL_HTTPS, PROTOCOL_AJP};
215        }
216    
217        /**
218         * Removes a connector.  This shuts it down if necessary, and removes it
219         * from the server environment.  It must be a connector that this container
220         * is responsible for.
221         *
222         * @param connectorName
223         */
224        public void removeConnector(AbstractName connectorName) {
225            try {
226                GBeanInfo info = kernel.getGBeanInfo(connectorName);
227                boolean found = false;
228                Set intfs = info.getInterfaces();
229                for (Iterator it = intfs.iterator(); it.hasNext();) {
230                    String intf = (String) it.next();
231                    if (intf.equals(JettyWebConnector.class.getName())) {
232                        found = true;
233                    }
234                }
235                if (!found) {
236                    throw new GBeanNotFoundException(connectorName);
237                }
238                EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
239                if (mgr != null) {
240                    try {
241                        mgr.removeGBeanFromConfiguration(connectorName.getArtifact(), connectorName);
242                    } catch (InvalidConfigException e) {
243                        log.error("Unable to add GBean", e);
244                    } finally {
245                        ConfigurationUtil.releaseConfigurationManager(kernel, mgr);
246                    }
247                } else {
248                    log.warn("The ConfigurationManager in the kernel does not allow editing");
249                }
250            } catch (GBeanNotFoundException e) {
251                log.warn("No such GBean '" + connectorName + "'"); //todo: what if we want to remove a failed GBean?
252            } catch (Exception e) {
253                log.error(e);
254            }
255        }
256    
257        /**
258         * Gets the ObjectNames of any existing connectors for the specified
259         * protocol.
260         *
261         * @param protocol A protocol as returned by getSupportedProtocols
262         */
263        public NetworkConnector[] getConnectors(String protocol) {
264            if (protocol == null) {
265                return getConnectors();
266            }
267            List result = new ArrayList();
268            ProxyManager proxyManager = kernel.getProxyManager();
269            AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName());
270            Set names = kernel.listGBeans(query);
271            for (Iterator it = names.iterator(); it.hasNext();) {
272                AbstractName name = (AbstractName) it.next();
273                try {
274                    if (kernel.getAttribute(name, "protocol").equals(protocol)) {
275                        result.add(proxyManager.createProxy(name, JettyWebConnector.class.getClassLoader()));
276                    }
277                } catch (Exception e) {
278                    log.error("Unable to check the protocol for a connector", e);
279                }
280            }
281            return (JettyWebConnector[]) result.toArray(new JettyWebConnector[names.size()]);
282        }
283    
284        public WebAccessLog getAccessLog(WebContainer container) {
285            AbstractNameQuery query = new AbstractNameQuery(JettyLogManager.class.getName());
286            Set names = kernel.listGBeans(query);
287            if (names.size() == 0) {
288                return null;
289            } else if (names.size() > 1) {
290                throw new IllegalStateException("Should not be more than one Jetty access log manager");
291            }
292            return (WebAccessLog) kernel.getProxyManager().createProxy((AbstractName) names.iterator().next(), JettyLogManager.class.getClassLoader());
293        }
294    
295        public List<ConnectorType> getConnectorTypes() {
296            return CONNECTOR_TYPES;
297        }
298    
299        public List<ConnectorAttribute> getConnectorAttributes(ConnectorType connectorType) {
300            return ConnectorAttribute.copy(CONNECTOR_ATTRIBUTES.get(connectorType));
301        }
302    
303        public AbstractName getConnectorConfiguration(ConnectorType connectorType, List<ConnectorAttribute> connectorAttributes, WebContainer container, String uniqueName) {
304            GBeanInfo gbeanInfo = CONNECTOR_GBEAN_INFOS.get(connectorType);
305            AbstractName containerName = kernel.getAbstractNameFor(container);
306            AbstractName name = kernel.getNaming().createSiblingName(containerName, uniqueName, NameFactory.GERONIMO_SERVICE);
307            GBeanData gbeanData = new GBeanData(name, gbeanInfo);
308            gbeanData.setReferencePattern(JettyConnector.CONNECTOR_CONTAINER_REFERENCE, containerName);
309            for (ConnectorAttribute connectorAttribute : connectorAttributes) {
310                Object value = connectorAttribute.getValue();
311                if (value != null) {
312                    gbeanData.setAttribute(connectorAttribute.getAttributeName(), connectorAttribute.getValue());
313                }
314            }
315            
316            // provide a reference to KeystoreManager gbean for HTTPS connectors
317            if (connectorType.equals(HTTPS_NIO) || connectorType.equals(HTTPS_BIO)) {
318                AbstractNameQuery query = new AbstractNameQuery(KeystoreManager.class.getName());
319                gbeanData.setReferencePattern("KeystoreManager", query);
320            }
321            
322            EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
323            if (mgr != null) {
324                try {
325                    mgr.addGBeanToConfiguration(containerName.getArtifact(), gbeanData, false);
326                } catch (InvalidConfigException e) {
327                    log.error("Unable to add GBean", e);
328                    return null;
329                } finally {
330                    ConfigurationUtil.releaseConfigurationManager(kernel, mgr);
331                }
332            } else {
333                log.warn("The ConfigurationManager in the kernel does not allow editing");
334                return null;
335            }
336            return name;
337        }
338        
339        public ConnectorType getConnectorType(AbstractName connectorName) {
340            ConnectorType connectorType = null; 
341            try {
342                GBeanInfo info = kernel.getGBeanInfo(connectorName);
343                boolean found = false;
344                Set intfs = info.getInterfaces();
345                for (Iterator it = intfs.iterator(); it.hasNext() && !found;) {
346                    String intf = (String) it.next();
347                    if (intf.equals(JettyWebConnector.class.getName())) {
348                        found = true;
349                    }
350                }
351                if (!found) {
352                    throw new GBeanNotFoundException(connectorName);
353                }
354                String searchingFor = info.getName();
355                for (Entry<ConnectorType, GBeanInfo> entry : CONNECTOR_GBEAN_INFOS.entrySet() ) {
356                    String candidate = entry.getValue().getName();
357                    if (candidate.equals(searchingFor)) {
358                        return entry.getKey();
359                    }
360                }
361            } catch (GBeanNotFoundException e) {
362                log.warn("No such GBean '" + connectorName + "'");
363            } catch (Exception e) {
364                log.error(e);
365            }
366                
367            return connectorType;
368        }
369    
370        /**
371         * Gets the ObjectNames of any existing connectors.
372         */
373        public NetworkConnector[] getConnectors() {
374            ProxyManager proxyManager = kernel.getProxyManager();
375            AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName());
376            Set names = kernel.listGBeans(query);
377            JettyWebConnector[] results = new JettyWebConnector[names.size()];
378            int i = 0;
379            for (Iterator it = names.iterator(); it.hasNext(); i++) {
380                AbstractName name = (AbstractName) it.next();
381                results[i] = (JettyWebConnector) proxyManager.createProxy(name, JettyWebConnector.class.getClassLoader());
382            }
383            return results;
384        }
385    
386        public NetworkConnector[] getConnectorsForContainer(Object container, String protocol) {
387            if (protocol == null) {
388                return getConnectorsForContainer(container);
389            }
390            AbstractName containerName = kernel.getAbstractNameFor(container);
391            ProxyManager mgr = kernel.getProxyManager();
392            try {
393                List results = new ArrayList();
394                AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName());
395                Set set = kernel.listGBeans(query); // all Jetty connectors
396                for (Iterator it = set.iterator(); it.hasNext();) {
397                    AbstractName name = (AbstractName) it.next(); // a single Jetty connector
398                    GBeanData data = kernel.getGBeanData(name);
399                    ReferencePatterns refs = data.getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE);
400                    if (containerName.equals(refs.getAbstractName())) {
401                        try {
402                            String testProtocol = (String) kernel.getAttribute(name, "protocol");
403                            if (testProtocol != null && testProtocol.equals(protocol)) {
404                                results.add(mgr.createProxy(name, JettyWebConnector.class.getClassLoader()));
405                            }
406                        } catch (Exception e) {
407                            log.error("Unable to look up protocol for connector '" + name + "'", e);
408                        }
409                        break;
410                    }
411                }
412                return (JettyWebConnector[]) results.toArray(new JettyWebConnector[results.size()]);
413            } catch (Exception e) {
414                throw (IllegalArgumentException) new IllegalArgumentException("Unable to look up connectors for Jetty container '" + containerName + "': ").initCause(e);
415            }
416        }
417    
418        public NetworkConnector[] getConnectorsForContainer(Object container) {
419            AbstractName containerName = kernel.getAbstractNameFor(container);
420            ProxyManager mgr = kernel.getProxyManager();
421            try {
422                List results = new ArrayList();
423                AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName());
424                Set set = kernel.listGBeans(query); // all Jetty connectors
425                for (Iterator it = set.iterator(); it.hasNext();) {
426                    AbstractName name = (AbstractName) it.next(); // a single Jetty connector
427                    GBeanData data = kernel.getGBeanData(name);
428                    ReferencePatterns refs = data.getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE);
429                    if (containerName.equals(refs.getAbstractName())) {
430                        results.add(mgr.createProxy(name, JettyWebConnector.class.getClassLoader()));
431                    }
432                }
433                return (JettyWebConnector[]) results.toArray(new JettyWebConnector[results.size()]);
434            } catch (Exception e) {
435                throw (IllegalArgumentException) new IllegalArgumentException("Unable to look up connectors for Jetty container '" + containerName + "'").initCause(e);
436            }
437        }
438    
439        public static final GBeanInfo GBEAN_INFO;
440    
441        static {
442            GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Jetty Web Manager", JettyManagerImpl.class);
443            infoFactory.addAttribute("kernel", Kernel.class, false);
444            infoFactory.addInterface(WebManager.class);
445            infoFactory.setConstructor(new String[]{"kernel"});
446            GBEAN_INFO = infoFactory.getBeanInfo();
447        }
448    
449        public static GBeanInfo getGBeanInfo() {
450            return GBEAN_INFO;
451        }
452    }