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 }