View Javadoc

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              //todo: default HTTPS settings
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 + "'"); //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 }