001 /** 002 * 003 * Licensed to the Apache Software Foundation (ASF) under one or more 004 * contributor license agreements. See the NOTICE file distributed with 005 * this work for additional information regarding copyright ownership. 006 * The ASF licenses this file to You under the Apache License, Version 2.0 007 * (the "License"); you may not use this file except in compliance with 008 * the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 package org.apache.geronimo.jetty; 019 020 import java.util.ArrayList; 021 import java.util.Iterator; 022 import java.util.List; 023 import java.util.Set; 024 025 import org.apache.commons.logging.Log; 026 import org.apache.commons.logging.LogFactory; 027 import org.apache.geronimo.gbean.AbstractName; 028 import org.apache.geronimo.gbean.AbstractNameQuery; 029 import org.apache.geronimo.gbean.GBeanData; 030 import org.apache.geronimo.gbean.GBeanInfo; 031 import org.apache.geronimo.gbean.GBeanInfoBuilder; 032 import org.apache.geronimo.gbean.ReferencePatterns; 033 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 034 import org.apache.geronimo.jetty.connector.AJP13Connector; 035 import org.apache.geronimo.jetty.connector.HTTPConnector; 036 import org.apache.geronimo.jetty.connector.HTTPSConnector; 037 import org.apache.geronimo.jetty.connector.JettyConnector; 038 import org.apache.geronimo.jetty.requestlog.JettyLogManager; 039 import org.apache.geronimo.kernel.GBeanNotFoundException; 040 import org.apache.geronimo.kernel.Kernel; 041 import org.apache.geronimo.kernel.config.ConfigurationUtil; 042 import org.apache.geronimo.kernel.config.EditableConfigurationManager; 043 import org.apache.geronimo.kernel.config.InvalidConfigException; 044 import org.apache.geronimo.kernel.proxy.ProxyManager; 045 import org.apache.geronimo.management.geronimo.KeystoreManager; 046 import org.apache.geronimo.management.geronimo.NetworkConnector; 047 import org.apache.geronimo.management.geronimo.WebAccessLog; 048 import org.apache.geronimo.management.geronimo.WebConnector; 049 import org.apache.geronimo.management.geronimo.WebContainer; 050 import org.apache.geronimo.management.geronimo.WebManager; 051 052 /** 053 * Jetty implementation of WebManager. Knows how to manipulate 054 * other Jetty objects for management purposes. 055 * 056 * @version $Rev:386276 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $ 057 */ 058 public class JettyManagerImpl implements WebManager { 059 private final static Log log = LogFactory.getLog(JettyManagerImpl.class); 060 private final Kernel kernel; 061 062 public JettyManagerImpl(Kernel kernel) { 063 this.kernel = kernel; 064 } 065 066 public String getProductName() { 067 return "Jetty"; 068 } 069 070 /** 071 * Creates a new connector, and returns the ObjectName for it. Note that 072 * the connector may well require further customization before being fully 073 * functional (e.g. SSL settings for an HTTPS connector). 074 */ 075 public WebConnector addConnector(WebContainer container, String uniqueName, String protocol, String host, int port) { 076 AbstractName containerName = kernel.getAbstractNameFor(container); 077 AbstractName name = kernel.getNaming().createSiblingName(containerName, uniqueName, NameFactory.GERONIMO_SERVICE); 078 GBeanData connector; 079 if (protocol.equals(PROTOCOL_HTTP)) { 080 connector = new GBeanData(name, HTTPConnector.GBEAN_INFO); 081 } else if (protocol.equals(PROTOCOL_HTTPS)) { 082 connector = new GBeanData(name, HTTPSConnector.GBEAN_INFO); 083 AbstractNameQuery query = new AbstractNameQuery(KeystoreManager.class.getName()); 084 connector.setReferencePattern("KeystoreManager", query); 085 //todo: default HTTPS settings 086 } else if (protocol.equals(PROTOCOL_AJP)) { 087 connector = new GBeanData(name, AJP13Connector.GBEAN_INFO); 088 } else { 089 throw new IllegalArgumentException("Invalid protocol '" + protocol + "'"); 090 } 091 connector.setAttribute("host", host); 092 connector.setAttribute("port", new Integer(port)); 093 connector.setAttribute("minThreads", new Integer(10)); 094 connector.setAttribute("maxThreads", new Integer(50)); 095 connector.setReferencePattern(JettyConnector.CONNECTOR_CONTAINER_REFERENCE, containerName); 096 EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel); 097 if(mgr != null) { 098 try { 099 mgr.addGBeanToConfiguration(containerName.getArtifact(), connector, false); 100 return (WebConnector) kernel.getProxyManager().createProxy(name, JettyWebConnector.class.getClassLoader()); 101 } catch (InvalidConfigException e) { 102 log.error("Unable to add GBean", e); 103 return null; 104 } finally { 105 ConfigurationUtil.releaseConfigurationManager(kernel, mgr); 106 } 107 } else { 108 log.warn("The ConfigurationManager in the kernel does not allow editing"); 109 return null; 110 } 111 } 112 113 /** 114 * Get a list of containers for this web implementation. 115 */ 116 public Object[] getContainers() { 117 ProxyManager proxyManager = kernel.getProxyManager(); 118 AbstractNameQuery query = new AbstractNameQuery(JettyContainer.class.getName()); 119 Set names = kernel.listGBeans(query); 120 JettyContainer[] results = new JettyContainer[names.size()]; 121 int i=0; 122 for (Iterator it = names.iterator(); it.hasNext(); i++) { 123 AbstractName name = (AbstractName) it.next(); 124 results[i] = (JettyContainer) proxyManager.createProxy(name, JettyContainer.class.getClassLoader()); 125 } 126 return results; 127 } 128 129 /** 130 * Gets the protocols that this web container supports (that you can create 131 * connectors for). 132 */ 133 public String[] getSupportedProtocols() { 134 return new String[]{PROTOCOL_HTTP, PROTOCOL_HTTPS, PROTOCOL_AJP}; 135 } 136 137 /** 138 * Removes a connector. This shuts it down if necessary, and removes it 139 * from the server environment. It must be a connector that this container 140 * is responsible for. 141 * @param connectorName 142 */ 143 public void removeConnector(AbstractName connectorName) { 144 try { 145 GBeanInfo info = kernel.getGBeanInfo(connectorName); 146 boolean found = false; 147 Set intfs = info.getInterfaces(); 148 for (Iterator it = intfs.iterator(); it.hasNext();) { 149 String intf = (String) it.next(); 150 if (intf.equals(JettyWebConnector.class.getName())) { 151 found = true; 152 } 153 } 154 if (!found) { 155 throw new GBeanNotFoundException(connectorName); 156 } 157 EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel); 158 if(mgr != null) { 159 try { 160 mgr.removeGBeanFromConfiguration(connectorName.getArtifact(), connectorName); 161 } catch (InvalidConfigException e) { 162 log.error("Unable to add GBean", e); 163 } finally { 164 ConfigurationUtil.releaseConfigurationManager(kernel, mgr); 165 } 166 } else { 167 log.warn("The ConfigurationManager in the kernel does not allow editing"); 168 } 169 } catch (GBeanNotFoundException e) { 170 log.warn("No such GBean '" + connectorName + "'"); //todo: what if we want to remove a failed GBean? 171 } catch (Exception e) { 172 log.error(e); 173 } 174 } 175 176 /** 177 * Gets the ObjectNames of any existing connectors for the specified 178 * protocol. 179 * 180 * @param protocol A protocol as returned by getSupportedProtocols 181 */ 182 public NetworkConnector[] getConnectors(String protocol) { 183 if(protocol == null) { 184 return getConnectors(); 185 } 186 List result = new ArrayList(); 187 ProxyManager proxyManager = kernel.getProxyManager(); 188 AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName()); 189 Set names = kernel.listGBeans(query); 190 for (Iterator it = names.iterator(); it.hasNext();) { 191 AbstractName name = (AbstractName) it.next(); 192 try { 193 if (kernel.getAttribute(name, "protocol").equals(protocol)) { 194 result.add(proxyManager.createProxy(name, JettyWebConnector.class.getClassLoader())); 195 } 196 } catch (Exception e) { 197 log.error("Unable to check the protocol for a connector", e); 198 } 199 } 200 return (JettyWebConnector[]) result.toArray(new JettyWebConnector[names.size()]); 201 } 202 203 public WebAccessLog getAccessLog(WebContainer container) { 204 AbstractNameQuery query = new AbstractNameQuery(JettyLogManager.class.getName()); 205 Set names = kernel.listGBeans(query); 206 if(names.size() == 0) { 207 return null; 208 } else if(names.size() > 1) { 209 throw new IllegalStateException("Should not be more than one Jetty access log manager"); 210 } 211 return (WebAccessLog) kernel.getProxyManager().createProxy((AbstractName)names.iterator().next(), JettyLogManager.class.getClassLoader()); 212 } 213 214 /** 215 * Gets the ObjectNames of any existing connectors. 216 */ 217 public NetworkConnector[] getConnectors() { 218 ProxyManager proxyManager = kernel.getProxyManager(); 219 AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName()); 220 Set names = kernel.listGBeans(query); 221 JettyWebConnector[] results = new JettyWebConnector[names.size()]; 222 int i=0; 223 for (Iterator it = names.iterator(); it.hasNext(); i++) { 224 AbstractName name = (AbstractName) it.next(); 225 results[i] = (JettyWebConnector) proxyManager.createProxy(name, JettyWebConnector.class.getClassLoader()); 226 } 227 return results; 228 } 229 230 public NetworkConnector[] getConnectorsForContainer(Object container, String protocol) { 231 if(protocol == null) { 232 return getConnectorsForContainer(container); 233 } 234 AbstractName containerName = kernel.getAbstractNameFor(container); 235 ProxyManager mgr = kernel.getProxyManager(); 236 try { 237 List results = new ArrayList(); 238 AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName()); 239 Set set = kernel.listGBeans(query); // all Jetty connectors 240 for (Iterator it = set.iterator(); it.hasNext();) { 241 AbstractName name = (AbstractName) it.next(); // a single Jetty connector 242 GBeanData data = kernel.getGBeanData(name); 243 ReferencePatterns refs = data.getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE); 244 if(containerName.equals(refs.getAbstractName())) { 245 try { 246 String testProtocol = (String) kernel.getAttribute(name, "protocol"); 247 if(testProtocol != null && testProtocol.equals(protocol)) { 248 results.add(mgr.createProxy(name, JettyWebConnector.class.getClassLoader())); 249 } 250 } catch (Exception e) { 251 log.error("Unable to look up protocol for connector '"+name+"'",e); 252 } 253 break; 254 } 255 } 256 return (JettyWebConnector[]) results.toArray(new JettyWebConnector[results.size()]); 257 } catch (Exception e) { 258 throw (IllegalArgumentException)new IllegalArgumentException("Unable to look up connectors for Jetty container '"+containerName +"': ").initCause(e); 259 } 260 } 261 262 public NetworkConnector[] getConnectorsForContainer(Object container) { 263 AbstractName containerName = kernel.getAbstractNameFor(container); 264 ProxyManager mgr = kernel.getProxyManager(); 265 try { 266 List results = new ArrayList(); 267 AbstractNameQuery query = new AbstractNameQuery(JettyWebConnector.class.getName()); 268 Set set = kernel.listGBeans(query); // all Jetty connectors 269 for (Iterator it = set.iterator(); it.hasNext();) { 270 AbstractName name = (AbstractName) it.next(); // a single Jetty connector 271 GBeanData data = kernel.getGBeanData(name); 272 ReferencePatterns refs = data.getReferencePatterns(JettyConnector.CONNECTOR_CONTAINER_REFERENCE); 273 if (containerName.equals(refs.getAbstractName())) { 274 results.add(mgr.createProxy(name, JettyWebConnector.class.getClassLoader())); 275 } 276 } 277 return (JettyWebConnector[]) results.toArray(new JettyWebConnector[results.size()]); 278 } catch (Exception e) { 279 throw (IllegalArgumentException) new IllegalArgumentException("Unable to look up connectors for Jetty container '"+containerName+"'").initCause(e); 280 } 281 } 282 283 public static final GBeanInfo GBEAN_INFO; 284 285 static { 286 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Jetty Web Manager", JettyManagerImpl.class); 287 infoFactory.addAttribute("kernel", Kernel.class, false); 288 infoFactory.addInterface(WebManager.class); 289 infoFactory.setConstructor(new String[] {"kernel"}); 290 GBEAN_INFO = infoFactory.getBeanInfo(); 291 } 292 293 public static GBeanInfo getGBeanInfo() { 294 return GBEAN_INFO; 295 } 296 }