001 /** 002 * 003 * Copyright 2003-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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.tomcat; 018 019 import java.util.ArrayList; 020 import java.util.Iterator; 021 import java.util.List; 022 import java.util.Set; 023 import org.apache.commons.logging.Log; 024 import org.apache.commons.logging.LogFactory; 025 import org.apache.geronimo.gbean.AbstractName; 026 import org.apache.geronimo.gbean.AbstractNameQuery; 027 import org.apache.geronimo.gbean.GBeanData; 028 import org.apache.geronimo.gbean.GBeanInfo; 029 import org.apache.geronimo.gbean.GBeanInfoBuilder; 030 import org.apache.geronimo.gbean.ReferencePatterns; 031 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 032 import org.apache.geronimo.kernel.GBeanNotFoundException; 033 import org.apache.geronimo.kernel.Kernel; 034 import org.apache.geronimo.kernel.config.ConfigurationUtil; 035 import org.apache.geronimo.kernel.config.EditableConfigurationManager; 036 import org.apache.geronimo.kernel.config.InvalidConfigException; 037 import org.apache.geronimo.kernel.proxy.ProxyManager; 038 import org.apache.geronimo.management.geronimo.NetworkConnector; 039 import org.apache.geronimo.management.geronimo.WebAccessLog; 040 import org.apache.geronimo.management.geronimo.WebConnector; 041 import org.apache.geronimo.management.geronimo.WebContainer; 042 import org.apache.geronimo.management.geronimo.WebManager; 043 import org.apache.geronimo.system.serverinfo.ServerInfo; 044 045 /** 046 * Tomcat implementation of the WebManager management API. Knows how to 047 * manipulate other Tomcat objects for management purposes. 048 * 049 * @version $Rev: 406807 $ $Date: 2006-05-15 19:50:45 -0700 (Mon, 15 May 2006) $ 050 */ 051 public class TomcatManagerImpl implements WebManager { 052 private final static Log log = LogFactory.getLog(TomcatManagerImpl.class); 053 private final Kernel kernel; 054 055 public TomcatManagerImpl(Kernel kernel) { 056 this.kernel = kernel; 057 } 058 059 public String getProductName() { 060 return "Tomcat"; 061 } 062 063 /** 064 * Creates and returns a new connector. Note that the connector may well 065 * require further customization before being fully functional (e.g. SSL 066 * settings for a secure connector). This may need to be done before 067 * starting the resulting connector. 068 * 069 * @param container The container to add the connector to 070 * @param uniqueName A name fragment that's unique to this connector 071 * @param protocol The protocol that the connector should use 072 * @param host The host name or IP that the connector should listen on 073 * @param port The port that the connector should listen on 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, ConnectorGBean.GBEAN_INFO); 081 } else if(protocol.equals(PROTOCOL_HTTPS)) { 082 connector = new GBeanData(name, HttpsConnectorGBean.GBEAN_INFO); 083 AbstractNameQuery query = new AbstractNameQuery(ServerInfo.class.getName()); 084 Set set = kernel.listGBeans(query); 085 connector.setReferencePattern("ServerInfo", (AbstractName)set.iterator().next()); 086 //todo: default HTTPS settings 087 } else if(protocol.equals(PROTOCOL_AJP)) { 088 connector = new GBeanData(name, ConnectorGBean.GBEAN_INFO); 089 } else { 090 throw new IllegalArgumentException("Invalid protocol '"+protocol+"'"); 091 } 092 connector.setAttribute("protocol", protocol); 093 connector.setAttribute("host", host); 094 connector.setAttribute("port", new Integer(port)); 095 connector.setAttribute("maxThreads", new Integer(50)); 096 connector.setAttribute("acceptQueueSize", new Integer(100)); 097 connector.setReferencePattern(ConnectorGBean.CONNECTOR_CONTAINER_REFERENCE, containerName); 098 connector.setAttribute("name", uniqueName); 099 EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel); 100 if(mgr != null) { 101 try { 102 mgr.addGBeanToConfiguration(containerName.getArtifact(), connector, false); 103 return (WebConnector) kernel.getProxyManager().createProxy(name, TomcatWebConnector.class.getClassLoader()); 104 } catch (InvalidConfigException e) { 105 log.error("Unable to add GBean", e); 106 return null; 107 } finally { 108 ConfigurationUtil.releaseConfigurationManager(kernel, mgr); 109 } 110 } else { 111 log.warn("The ConfigurationManager in the kernel does not allow editing"); 112 return null; 113 } 114 } 115 116 /** 117 * Gets the network containers. 118 */ 119 public Object[] getContainers() { 120 ProxyManager proxyManager = kernel.getProxyManager(); 121 AbstractNameQuery query = new AbstractNameQuery(TomcatWebContainer.class.getName()); 122 Set names = kernel.listGBeans(query); 123 TomcatWebContainer[] results = new TomcatWebContainer[names.size()]; 124 int i=0; 125 for (Iterator it = names.iterator(); it.hasNext(); i++) { 126 AbstractName name = (AbstractName) it.next(); 127 results[i] = (TomcatWebContainer) proxyManager.createProxy(name, TomcatWebContainer.class.getClassLoader()); 128 } 129 return results; 130 } 131 132 /** 133 * Gets the protocols which this container can configure connectors for. 134 */ 135 public String[] getSupportedProtocols() { 136 return new String[]{PROTOCOL_HTTP, PROTOCOL_HTTPS, PROTOCOL_AJP}; 137 } 138 139 /** 140 * Removes a connector. This shuts it down if necessary, and removes it from the server environment. It must be a 141 * connector that uses this network technology. 142 * @param connectorName 143 */ 144 public void removeConnector(AbstractName connectorName) { 145 try { 146 GBeanInfo info = kernel.getGBeanInfo(connectorName); 147 boolean found = false; 148 Set intfs = info.getInterfaces(); 149 for (Iterator it = intfs.iterator(); it.hasNext();) { 150 String intf = (String) it.next(); 151 if (intf.equals(TomcatWebConnector.class.getName())) { 152 found = true; 153 } 154 } 155 if (!found) { 156 throw new GBeanNotFoundException(connectorName); 157 } 158 EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel); 159 if(mgr != null) { 160 try { 161 mgr.removeGBeanFromConfiguration(connectorName.getArtifact(), connectorName); 162 } catch (InvalidConfigException e) { 163 log.error("Unable to add GBean", e); 164 } finally { 165 ConfigurationUtil.releaseConfigurationManager(kernel, mgr); 166 } 167 } else { 168 log.warn("The ConfigurationManager in the kernel does not allow editing"); 169 } 170 } catch (GBeanNotFoundException e) { 171 log.warn("No such GBean '" + connectorName + "'"); //todo: what if we want to remove a failed GBean? 172 } catch (Exception e) { 173 log.error(e); 174 } 175 } 176 177 /** 178 * Gets the ObjectNames of any existing connectors for this network technology for the specified 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(TomcatWebConnector.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, TomcatWebConnector.class.getClassLoader())); 195 } 196 } catch (Exception e) { 197 log.error("Unable to check the protocol for a connector", e); 198 } 199 } 200 return (TomcatWebConnector[]) result.toArray(new TomcatWebConnector[names.size()]); 201 } 202 203 public WebAccessLog getAccessLog(WebContainer container) { 204 AbstractNameQuery query = new AbstractNameQuery(TomcatLogManager.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 Tomcat access log manager"); 210 } 211 return (WebAccessLog) kernel.getProxyManager().createProxy((AbstractName)names.iterator().next(), TomcatLogManager.class.getClassLoader()); 212 } 213 214 /** 215 * Gets the ObjectNames of any existing connectors associated with this network technology. 216 */ 217 public NetworkConnector[] getConnectors() { 218 ProxyManager proxyManager = kernel.getProxyManager(); 219 AbstractNameQuery query = new AbstractNameQuery(TomcatWebConnector.class.getName()); 220 Set names = kernel.listGBeans(query); 221 TomcatWebConnector[] results = new TomcatWebConnector[names.size()]; 222 int i=0; 223 for (Iterator it = names.iterator(); it.hasNext(); i++) { 224 AbstractName name = (AbstractName) it.next(); 225 results[i] = (TomcatWebConnector) proxyManager.createProxy(name, TomcatWebConnector.class.getClassLoader()); 226 } 227 return results; 228 } 229 230 /** 231 * Gets the ObjectNames of any existing connectors for the specified container for the specified protocol. 232 * 233 * @param protocol A protocol as returned by getSupportedProtocols 234 */ 235 public NetworkConnector[] getConnectorsForContainer(Object container, String protocol) { 236 if(protocol == null) { 237 return getConnectorsForContainer(container); 238 } 239 AbstractName containerName = kernel.getAbstractNameFor(container); 240 ProxyManager mgr = kernel.getProxyManager(); 241 try { 242 List results = new ArrayList(); 243 AbstractNameQuery query = new AbstractNameQuery(TomcatWebConnector.class.getName()); 244 Set set = kernel.listGBeans(query); // all Tomcat connectors 245 for (Iterator it = set.iterator(); it.hasNext();) { 246 AbstractName name = (AbstractName) it.next(); // a single Tomcat connector 247 GBeanData data = kernel.getGBeanData(name); 248 ReferencePatterns refs = data.getReferencePatterns(ConnectorGBean.CONNECTOR_CONTAINER_REFERENCE); 249 if(containerName.equals(refs.getAbstractName())) { 250 try { 251 String testProtocol = (String) kernel.getAttribute(name, "protocol"); 252 if(testProtocol != null && testProtocol.equals(protocol)) { 253 results.add(mgr.createProxy(name, TomcatWebConnector.class.getClassLoader())); 254 } 255 } catch (Exception e) { 256 log.error("Unable to look up protocol for connector '"+name+"'",e); 257 } 258 break; 259 } 260 } 261 return (TomcatWebConnector[]) results.toArray(new TomcatWebConnector[results.size()]); 262 } catch (Exception e) { 263 throw (IllegalArgumentException)new IllegalArgumentException("Unable to look up connectors for Tomcat container '"+containerName +"': ").initCause(e); 264 } 265 } 266 267 /** 268 * Gets the ObjectNames of any existing connectors for the specified container. 269 */ 270 public NetworkConnector[] getConnectorsForContainer(Object container) { 271 AbstractName containerName = kernel.getAbstractNameFor(container); 272 ProxyManager mgr = kernel.getProxyManager(); 273 try { 274 List results = new ArrayList(); 275 AbstractNameQuery query = new AbstractNameQuery(TomcatWebConnector.class.getName()); 276 Set set = kernel.listGBeans(query); // all Tomcat connectors 277 for (Iterator it = set.iterator(); it.hasNext();) { 278 AbstractName name = (AbstractName) it.next(); // a single Tomcat connector 279 GBeanData data = kernel.getGBeanData(name); 280 ReferencePatterns refs = data.getReferencePatterns(ConnectorGBean.CONNECTOR_CONTAINER_REFERENCE); 281 if (containerName.equals(refs.getAbstractName())) { 282 results.add(mgr.createProxy(name, TomcatWebConnector.class.getClassLoader())); 283 } 284 } 285 return (TomcatWebConnector[]) results.toArray(new TomcatWebConnector[results.size()]); 286 } catch (Exception e) { 287 throw (IllegalArgumentException) new IllegalArgumentException("Unable to look up connectors for Tomcat container '"+containerName).initCause(e); 288 } 289 } 290 291 public static final GBeanInfo GBEAN_INFO; 292 293 static { 294 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Tomcat Web Manager", TomcatManagerImpl.class); 295 infoFactory.addAttribute("kernel", Kernel.class, false); 296 infoFactory.addInterface(WebManager.class); 297 infoFactory.setConstructor(new String[] {"kernel"}); 298 GBEAN_INFO = infoFactory.getBeanInfo(); 299 } 300 301 public static GBeanInfo getGBeanInfo() { 302 return GBEAN_INFO; 303 } 304 }