View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  package org.apache.geronimo.jetty;
19  
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  import java.util.List;
23  import java.util.Set;
24  
25  import org.apache.commons.logging.Log;
26  import org.apache.commons.logging.LogFactory;
27  import org.apache.geronimo.gbean.AbstractName;
28  import org.apache.geronimo.gbean.AbstractNameQuery;
29  import org.apache.geronimo.gbean.GBeanData;
30  import org.apache.geronimo.gbean.GBeanInfo;
31  import org.apache.geronimo.gbean.GBeanInfoBuilder;
32  import org.apache.geronimo.gbean.ReferencePatterns;
33  import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
34  import org.apache.geronimo.jetty.connector.AJP13Connector;
35  import org.apache.geronimo.jetty.connector.HTTPConnector;
36  import org.apache.geronimo.jetty.connector.HTTPSConnector;
37  import org.apache.geronimo.jetty.connector.JettyConnector;
38  import org.apache.geronimo.jetty.requestlog.JettyLogManager;
39  import org.apache.geronimo.kernel.GBeanNotFoundException;
40  import org.apache.geronimo.kernel.Kernel;
41  import org.apache.geronimo.kernel.config.ConfigurationUtil;
42  import org.apache.geronimo.kernel.config.EditableConfigurationManager;
43  import org.apache.geronimo.kernel.config.InvalidConfigException;
44  import org.apache.geronimo.kernel.proxy.ProxyManager;
45  import org.apache.geronimo.management.geronimo.KeystoreManager;
46  import org.apache.geronimo.management.geronimo.NetworkConnector;
47  import org.apache.geronimo.management.geronimo.WebAccessLog;
48  import org.apache.geronimo.management.geronimo.WebConnector;
49  import org.apache.geronimo.management.geronimo.WebContainer;
50  import org.apache.geronimo.management.geronimo.WebManager;
51  
52  /**
53   * Jetty implementation of WebManager.  Knows how to manipulate
54   * other Jetty objects for management purposes.
55   *
56   * @version $Rev:386276 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
57   */
58  public class JettyManagerImpl implements WebManager {
59      private final static Log log = LogFactory.getLog(JettyManagerImpl.class);
60      private final Kernel kernel;
61  
62      public JettyManagerImpl(Kernel kernel) {
63          this.kernel = kernel;
64      }
65  
66      public String getProductName() {
67          return "Jetty";
68      }
69  
70      /**
71       * Creates a new connector, and returns the ObjectName for it.  Note that
72       * the connector may well require further customization before being fully
73       * functional (e.g. SSL settings for an HTTPS connector).
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, HTTPConnector.GBEAN_INFO);
81          } else if (protocol.equals(PROTOCOL_HTTPS)) {
82              connector = new GBeanData(name, HTTPSConnector.GBEAN_INFO);
83              AbstractNameQuery query = new AbstractNameQuery(KeystoreManager.class.getName());
84              connector.setReferencePattern("KeystoreManager", query);
85              //todo: default HTTPS settings
86          } else if (protocol.equals(PROTOCOL_AJP)) {
87              connector = new GBeanData(name, AJP13Connector.GBEAN_INFO);
88          } else {
89              throw new IllegalArgumentException("Invalid protocol '" + protocol + "'");
90          }
91          connector.setAttribute("host", host);
92          connector.setAttribute("port", new Integer(port));
93          connector.setAttribute("minThreads", new Integer(10));
94          connector.setAttribute("maxThreads", new Integer(50));
95          connector.setReferencePattern(JettyConnector.CONNECTOR_CONTAINER_REFERENCE, containerName);
96          EditableConfigurationManager mgr = ConfigurationUtil.getEditableConfigurationManager(kernel);
97          if(mgr != null) {
98              try {
99                  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 }