1 /**
2 *
3 * Copyright 2003-2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.geronimo.tomcat;
18
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Set;
23 import org.apache.commons.logging.Log;
24 import org.apache.commons.logging.LogFactory;
25 import org.apache.geronimo.gbean.AbstractName;
26 import org.apache.geronimo.gbean.AbstractNameQuery;
27 import org.apache.geronimo.gbean.GBeanData;
28 import org.apache.geronimo.gbean.GBeanInfo;
29 import org.apache.geronimo.gbean.GBeanInfoBuilder;
30 import org.apache.geronimo.gbean.ReferencePatterns;
31 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
32 import org.apache.geronimo.kernel.GBeanNotFoundException;
33 import org.apache.geronimo.kernel.Kernel;
34 import org.apache.geronimo.kernel.config.ConfigurationUtil;
35 import org.apache.geronimo.kernel.config.EditableConfigurationManager;
36 import org.apache.geronimo.kernel.config.InvalidConfigException;
37 import org.apache.geronimo.kernel.proxy.ProxyManager;
38 import org.apache.geronimo.management.geronimo.NetworkConnector;
39 import org.apache.geronimo.management.geronimo.WebAccessLog;
40 import org.apache.geronimo.management.geronimo.WebConnector;
41 import org.apache.geronimo.management.geronimo.WebContainer;
42 import org.apache.geronimo.management.geronimo.WebManager;
43 import org.apache.geronimo.system.serverinfo.ServerInfo;
44
45 /**
46 * Tomcat implementation of the WebManager management API. Knows how to
47 * manipulate other Tomcat objects for management purposes.
48 *
49 * @version $Rev: 406807 $ $Date: 2006-05-15 19:50:45 -0700 (Mon, 15 May 2006) $
50 */
51 public class TomcatManagerImpl implements WebManager {
52 private final static Log log = LogFactory.getLog(TomcatManagerImpl.class);
53 private final Kernel kernel;
54
55 public TomcatManagerImpl(Kernel kernel) {
56 this.kernel = kernel;
57 }
58
59 public String getProductName() {
60 return "Tomcat";
61 }
62
63 /**
64 * Creates and returns a new connector. Note that the connector may well
65 * require further customization before being fully functional (e.g. SSL
66 * settings for a secure connector). This may need to be done before
67 * starting the resulting connector.
68 *
69 * @param container The container to add the connector to
70 * @param uniqueName A name fragment that's unique to this connector
71 * @param protocol The protocol that the connector should use
72 * @param host The host name or IP that the connector should listen on
73 * @param port The port that the connector should listen on
74 */
75 public WebConnector addConnector(WebContainer container, String uniqueName, String protocol, String host, int port) {
76 AbstractName containerName = kernel.getAbstractNameFor(container);
77 AbstractName name = kernel.getNaming().createSiblingName(containerName, uniqueName, NameFactory.GERONIMO_SERVICE);
78 GBeanData connector;
79 if(protocol.equals(PROTOCOL_HTTP)) {
80 connector = new GBeanData(name, ConnectorGBean.GBEAN_INFO);
81 } else if(protocol.equals(PROTOCOL_HTTPS)) {
82 connector = new GBeanData(name, HttpsConnectorGBean.GBEAN_INFO);
83 AbstractNameQuery query = new AbstractNameQuery(ServerInfo.class.getName());
84 Set set = kernel.listGBeans(query);
85 connector.setReferencePattern("ServerInfo", (AbstractName)set.iterator().next());
86
87 } else if(protocol.equals(PROTOCOL_AJP)) {
88 connector = new GBeanData(name, ConnectorGBean.GBEAN_INFO);
89 } else {
90 throw new IllegalArgumentException("Invalid protocol '"+protocol+"'");
91 }
92 connector.setAttribute("protocol", protocol);
93 connector.setAttribute("host", host);
94 connector.setAttribute("port", new Integer(port));
95 connector.setAttribute("maxThreads", new Integer(50));
96 connector.setAttribute("acceptQueueSize", new Integer(100));
97 connector.setReferencePattern(ConnectorGBean.CONNECTOR_CONTAINER_REFERENCE, containerName);
98 connector.setAttribute("name", uniqueName);
99 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 + "'");
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);
245 for (Iterator it = set.iterator(); it.hasNext();) {
246 AbstractName name = (AbstractName) it.next();
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);
277 for (Iterator it = set.iterator(); it.hasNext();) {
278 AbstractName name = (AbstractName) it.next();
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 }