1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  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.catalina.mbeans;
18
19 import java.io.File;
20 import java.net.InetAddress;
21
22 import javax.management.MBeanServer;
23 import javax.management.ObjectName;
24
25 import org.apache.catalina.Container;
26 import org.apache.catalina.Context;
27 import org.apache.catalina.Engine;
28 import org.apache.catalina.Host;
29 import org.apache.catalina.JmxEnabled;
30 import org.apache.catalina.Realm;
31 import org.apache.catalina.Server;
32 import org.apache.catalina.Service;
33 import org.apache.catalina.Valve;
34 import org.apache.catalina.connector.Connector;
35 import org.apache.catalina.core.StandardContext;
36 import org.apache.catalina.core.StandardEngine;
37 import org.apache.catalina.core.StandardHost;
38 import org.apache.catalina.core.StandardService;
39 import org.apache.catalina.loader.WebappLoader;
40 import org.apache.catalina.realm.DataSourceRealm;
41 import org.apache.catalina.realm.JDBCRealm;
42 import org.apache.catalina.realm.JNDIRealm;
43 import org.apache.catalina.realm.MemoryRealm;
44 import org.apache.catalina.realm.UserDatabaseRealm;
45 import org.apache.catalina.session.StandardManager;
46 import org.apache.catalina.startup.ContextConfig;
47 import org.apache.catalina.startup.HostConfig;
48 import org.apache.juli.logging.Log;
49 import org.apache.juli.logging.LogFactory;
50 import org.apache.tomcat.util.res.StringManager;
51
52
53 /**
54  * @author Amy Roh
55  */

56 public class MBeanFactory {
57
58     private static final Log log = LogFactory.getLog(MBeanFactory.class);
59
60     protected static final StringManager sm = StringManager.getManager(MBeanFactory.class);
61
62     /**
63      * The <code>MBeanServer</code> for this application.
64      */

65     private static final MBeanServer mserver = MBeanUtils.createServer();
66
67
68     // ------------------------------------------------------------- Attributes
69
70     /**
71      * The container (Server/Service) for which this factory was created.
72      */

73     private Object container;
74
75
76     // ------------------------------------------------------------- Operations
77
78     /**
79      * Set the container that this factory was created for.
80      * @param container The associated container
81      */

82     public void setContainer(Object container) {
83         this.container = container;
84     }
85
86
87     /**
88      * Little convenience method to remove redundant code
89      * when retrieving the path string
90      *
91      * @param t path string
92      * @return empty string if t==null || t.equals("/")
93      */

94     private final String getPathStr(String t) {
95         if (t == null || t.equals("/")) {
96             return "";
97         }
98         return t;
99     }
100
101    /**
102      * Get Parent Container to add its child component
103      * from parent's ObjectName
104      */

105     private Container getParentContainerFromParent(ObjectName pname)
106         throws Exception {
107
108         String type = pname.getKeyProperty("type");
109         String j2eeType = pname.getKeyProperty("j2eeType");
110         Service service = getService(pname);
111         StandardEngine engine = (StandardEngine) service.getContainer();
112         if ((j2eeType!=null) && (j2eeType.equals("WebModule"))) {
113             String name = pname.getKeyProperty("name");
114             name = name.substring(2);
115             int i = name.indexOf('/');
116             String hostName = name.substring(0,i);
117             String path = name.substring(i);
118             Container host = engine.findChild(hostName);
119             String pathStr = getPathStr(path);
120             Container context = host.findChild(pathStr);
121             return context;
122         } else if (type != null) {
123             if (type.equals("Engine")) {
124                 return engine;
125             } else if (type.equals("Host")) {
126                 String hostName = pname.getKeyProperty("host");
127                 Container host = engine.findChild(hostName);
128                 return host;
129             }
130         }
131         return null;
132
133     }
134
135
136     /**
137      * Get Parent ContainerBase to add its child component
138      * from child component's ObjectName  as a String
139      */

140     private Container getParentContainerFromChild(ObjectName oname)
141         throws Exception {
142
143         String hostName = oname.getKeyProperty("host");
144         String path = oname.getKeyProperty("path");
145         Service service = getService(oname);
146         Container engine = service.getContainer();
147         if (hostName == null) {
148             // child's container is Engine
149             return engine;
150         } else if (path == null) {
151             // child's container is Host
152             Container host = engine.findChild(hostName);
153             return host;
154         } else {
155             // child's container is Context
156             Container host = engine.findChild(hostName);
157             path = getPathStr(path);
158             Container context = host.findChild(path);
159             return context;
160         }
161     }
162
163
164     private Service getService(ObjectName oname) throws Exception {
165
166         if (container instanceof Service) {
167             // Don't bother checking the domain - this is the only option
168             return (Service) container;
169         }
170
171         StandardService service = null;
172         String domain = oname.getDomain();
173         if (container instanceof Server) {
174             Service[] services = ((Server)container).findServices();
175             for (int i = 0; i < services.length; i++) {
176                 service = (StandardService) services[i];
177                 if (domain.equals(service.getObjectName().getDomain())) {
178                     break;
179                 }
180             }
181         }
182         if (service == null ||
183                 !service.getObjectName().getDomain().equals(domain)) {
184             throw new Exception(sm.getString("mBeanFactory.noService", domain));
185         }
186         return service;
187
188     }
189
190
191     /**
192      * Create a new AjpConnector
193      *
194      * @param parent MBean Name of the associated parent component
195      * @param address The IP address on which to bind
196      * @param port TCP port number to listen on
197      * @return the object name of the created connector
198      *
199      * @exception Exception if an MBean cannot be created or registered
200      */

201     public String createAjpConnector(String parent, String address, int port)
202         throws Exception {
203
204         return createConnector(parent, address, port, truefalse);
205     }
206
207
208     /**
209      * Create a new DataSource Realm.
210      *
211      * @param parent MBean Name of the associated parent component
212      * @param dataSourceName the datasource name
213      * @param roleNameCol the column name for the role names
214      * @param userCredCol the column name for the user credentials
215      * @param userNameCol the column name for the user names
216      * @param userRoleTable the table name for the roles table
217      * @param userTable the table name for the users
218      * @return the object name of the created realm
219      * @exception Exception if an MBean cannot be created or registered
220      */

221     public String createDataSourceRealm(String parent, String dataSourceName,
222         String roleNameCol, String userCredCol, String userNameCol,
223         String userRoleTable, String userTable) throws Exception {
224
225         // Create a new DataSourceRealm instance
226         DataSourceRealm realm = new DataSourceRealm();
227         realm.setDataSourceName(dataSourceName);
228         realm.setRoleNameCol(roleNameCol);
229         realm.setUserCredCol(userCredCol);
230         realm.setUserNameCol(userNameCol);
231         realm.setUserRoleTable(userRoleTable);
232         realm.setUserTable(userTable);
233
234         // Add the new instance to its parent component
235         return addRealmToParent(parent, realm);
236     }
237
238
239     private String addRealmToParent(String parent, Realm realm) throws Exception {
240         ObjectName pname = new ObjectName(parent);
241         Container container = getParentContainerFromParent(pname);
242         // Add the new instance to its parent component
243         container.setRealm(realm);
244         // Return the corresponding MBean name
245         ObjectName oname = null;
246         if (realm instanceof JmxEnabled) {
247             oname = ((JmxEnabled) realm).getObjectName();
248         }
249         if (oname != null) {
250             return oname.toString();
251         } else {
252             return null;
253         }
254     }
255
256
257     /**
258      * Create a new HttpConnector
259      *
260      * @param parent MBean Name of the associated parent component
261      * @param address The IP address on which to bind
262      * @param port TCP port number to listen on
263      * @return the object name of the created connector
264      *
265      * @exception Exception if an MBean cannot be created or registered
266      */

267     public String createHttpConnector(String parent, String address, int port)
268             throws Exception {
269         return createConnector(parent, address, port, falsefalse);
270     }
271
272
273     /**
274      * Create a new Connector
275      *
276      * @param parent MBean Name of the associated parent component
277      * @param address The IP address on which to bind
278      * @param port TCP port number to listen on
279      * @param isAjp Create a AJP/1.3 Connector
280      * @param isSSL Create a secure Connector
281      *
282      * @exception Exception if an MBean cannot be created or registered
283      */

284     private String createConnector(String parent, String address, int port, boolean isAjp, boolean isSSL)
285         throws Exception {
286         // Set the protocol in the constructor
287         String protocol = isAjp ? "AJP/1.3" : "HTTP/1.1";
288         Connector retobj = new Connector(protocol);
289         if ((address!=null) && (address.length()>0)) {
290             retobj.setProperty("address", address);
291         }
292         // Set port number
293         retobj.setPort(port);
294         // Set SSL
295         retobj.setSecure(isSSL);
296         retobj.setScheme(isSSL ? "https" : "http");
297         // Add the new instance to its parent component
298         // FIX ME - addConnector will fail
299         ObjectName pname = new ObjectName(parent);
300         Service service = getService(pname);
301         service.addConnector(retobj);
302
303         // Return the corresponding MBean name
304         ObjectName coname = retobj.getObjectName();
305
306         return coname.toString();
307     }
308
309
310     /**
311      * Create a new HttpsConnector
312      *
313      * @param parent MBean Name of the associated parent component
314      * @param address The IP address on which to bind
315      * @param port TCP port number to listen on
316      * @return the object name of the created connector
317      *
318      * @exception Exception if an MBean cannot be created or registered
319      */

320     public String createHttpsConnector(String parent, String address, int port)
321         throws Exception {
322         return createConnector(parent, address, port, falsetrue);
323     }
324
325
326     /**
327      * Create a new JDBC Realm.
328      *
329      * @param parent MBean Name of the associated parent component
330      * @param driverName JDBC driver name
331      * @param connectionName the user name for the connection
332      * @param connectionPassword the password for the connection
333      * @param connectionURL the connection URL to the database
334      * @return the object name of the created realm
335      *
336      * @exception Exception if an MBean cannot be created or registered
337      */

338     public String createJDBCRealm(String parent, String driverName,
339         String connectionName, String connectionPassword, String connectionURL)
340         throws Exception {
341
342         // Create a new JDBCRealm instance
343         JDBCRealm realm = new JDBCRealm();
344         realm.setDriverName(driverName);
345         realm.setConnectionName(connectionName);
346         realm.setConnectionPassword(connectionPassword);
347         realm.setConnectionURL(connectionURL);
348
349         // Add the new instance to its parent component
350         return addRealmToParent(parent, realm);
351     }
352
353
354     /**
355      * Create a new JNDI Realm.
356      *
357      * @param parent MBean Name of the associated parent component
358      * @return the object name of the created realm
359      *
360      * @exception Exception if an MBean cannot be created or registered
361      */

362     public String createJNDIRealm(String parent) throws Exception {
363
364          // Create a new JNDIRealm instance
365         JNDIRealm realm = new JNDIRealm();
366
367         // Add the new instance to its parent component
368         return addRealmToParent(parent, realm);
369     }
370
371
372     /**
373      * Create a new Memory Realm.
374      *
375      * @param parent MBean Name of the associated parent component
376      * @return the object name of the created realm
377      *
378      * @exception Exception if an MBean cannot be created or registered
379      */

380     public String createMemoryRealm(String parent) throws Exception {
381
382          // Create a new MemoryRealm instance
383         MemoryRealm realm = new MemoryRealm();
384
385         // Add the new instance to its parent component
386         return addRealmToParent(parent, realm);
387     }
388
389
390    /**
391      * Create a new StandardContext.
392      *
393      * @param parent MBean Name of the associated parent component
394      * @param path The context path for this Context
395      * @param docBase Document base directory (or WAR) for this Context
396      * @return the object name of the created context
397      *
398      * @exception Exception if an MBean cannot be created or registered
399      */

400     public String createStandardContext(String parent,
401                                         String path,
402                                         String docBase)
403         throws Exception {
404
405         return createStandardContext(parent, path, docBase, falsefalse);
406     }
407
408
409     /**
410      * Create a new StandardContext.
411      *
412      * @param parent MBean Name of the associated parent component
413      * @param path The context path for this Context
414      * @param docBase Document base directory (or WAR) for this Context
415      * @param xmlValidation if XML descriptors should be validated
416      * @param xmlNamespaceAware if the XML processor should namespace aware
417      * @return the object name of the created context
418      *
419      * @exception Exception if an MBean cannot be created or registered
420      */

421     public String createStandardContext(String parent,
422                                         String path,
423                                         String docBase,
424                                         boolean xmlValidation,
425                                         boolean xmlNamespaceAware)
426         throws Exception {
427
428         // Create a new StandardContext instance
429         StandardContext context = new StandardContext();
430         path = getPathStr(path);
431         context.setPath(path);
432         context.setDocBase(docBase);
433         context.setXmlValidation(xmlValidation);
434         context.setXmlNamespaceAware(xmlNamespaceAware);
435
436         ContextConfig contextConfig = new ContextConfig();
437         context.addLifecycleListener(contextConfig);
438
439         // Add the new instance to its parent component
440         ObjectName pname = new ObjectName(parent);
441         ObjectName deployer = new ObjectName(pname.getDomain()+
442                                              ":type=Deployer,host="+
443                                              pname.getKeyProperty("host"));
444         if(mserver.isRegistered(deployer)) {
445             String contextName = context.getName();
446             mserver.invoke(deployer, "addServiced",
447                            new Object [] {contextName},
448                            new String [] {"java.lang.String"});
449             String configPath = (String)mserver.getAttribute(deployer,
450                                                              "configBaseName");
451             String baseName = context.getBaseName();
452             File configFile = new File(new File(configPath), baseName+".xml");
453             if (configFile.isFile()) {
454                 context.setConfigFile(configFile.toURI().toURL());
455             }
456             mserver.invoke(deployer, "manageApp",
457                            new Object[] {context},
458                            new String[] {"org.apache.catalina.Context"});
459             mserver.invoke(deployer, "removeServiced",
460                            new Object [] {contextName},
461                            new String [] {"java.lang.String"});
462         } else {
463             log.warn(sm.getString("mBeanFactory.noDeployer", pname.getKeyProperty("host")));
464             Service service = getService(pname);
465             Engine engine = service.getContainer();
466             Host host = (Host) engine.findChild(pname.getKeyProperty("host"));
467             host.addChild(context);
468         }
469
470         // Return the corresponding MBean name
471         return context.getObjectName().toString();
472
473     }
474
475
476     /**
477      * Create a new StandardHost.
478      *
479      * @param parent MBean Name of the associated parent component
480      * @param name Unique name of this Host
481      * @param appBase Application base directory name
482      * @param autoDeploy Should we auto deploy?
483      * @param deployOnStartup Deploy on server startup?
484      * @param deployXML Should we deploy Context XML config files property?
485      * @param unpackWARs Should we unpack WARs when auto deploying?
486      * @return the object name of the created host
487      *
488      * @exception Exception if an MBean cannot be created or registered
489      */

490     public String createStandardHost(String parent, String name,
491                                      String appBase,
492                                      boolean autoDeploy,
493                                      boolean deployOnStartup,
494                                      boolean deployXML,
495                                      boolean unpackWARs)
496         throws Exception {
497
498         // Create a new StandardHost instance
499         StandardHost host = new StandardHost();
500         host.setName(name);
501         host.setAppBase(appBase);
502         host.setAutoDeploy(autoDeploy);
503         host.setDeployOnStartup(deployOnStartup);
504         host.setDeployXML(deployXML);
505         host.setUnpackWARs(unpackWARs);
506
507         // add HostConfig for active reloading
508         HostConfig hostConfig = new HostConfig();
509         host.addLifecycleListener(hostConfig);
510
511         // Add the new instance to its parent component
512         ObjectName pname = new ObjectName(parent);
513         Service service = getService(pname);
514         Engine engine = service.getContainer();
515         engine.addChild(host);
516
517         // Return the corresponding MBean name
518         return host.getObjectName().toString();
519
520     }
521
522
523     /**
524      * Creates a new StandardService and StandardEngine.
525      *
526      * @param domain       Domain name for the container instance
527      * @param defaultHost  Name of the default host to be used in the Engine
528      * @param baseDir      Base directory value for Engine
529      * @return the object name of the created service
530      *
531      * @exception Exception if an MBean cannot be created or registered
532      */

533     public String createStandardServiceEngine(String domain,
534             String defaultHost, String baseDir) throws Exception{
535
536         if (!(container instanceof Server)) {
537             throw new Exception(sm.getString("mBeanFactory.notServer"));
538         }
539
540         StandardEngine engine = new StandardEngine();
541         engine.setDomain(domain);
542         engine.setName(domain);
543         engine.setDefaultHost(defaultHost);
544
545         Service service = new StandardService();
546         service.setContainer(engine);
547         service.setName(domain);
548
549         ((Server) container).addService(service);
550
551         return engine.getObjectName().toString();
552     }
553
554
555     /**
556      * Create a new StandardManager.
557      *
558      * @param parent MBean Name of the associated parent component
559      * @return the object name of the created manager
560      *
561      * @exception Exception if an MBean cannot be created or registered
562      */

563     public String createStandardManager(String parent)
564         throws Exception {
565
566         // Create a new StandardManager instance
567         StandardManager manager = new StandardManager();
568
569         // Add the new instance to its parent component
570         ObjectName pname = new ObjectName(parent);
571         Container container = getParentContainerFromParent(pname);
572         if (container instanceof Context) {
573             ((Context) container).setManager(manager);
574         } else {
575             throw new Exception(sm.getString("mBeanFactory.managerContext"));
576         }
577         ObjectName oname = manager.getObjectName();
578         if (oname != null) {
579             return oname.toString();
580         } else {
581             return null;
582         }
583
584     }
585
586
587     /**
588      * Create a new  UserDatabaseRealm.
589      *
590      * @param parent MBean Name of the associated parent component
591      * @param resourceName Global JNDI resource name of the associated
592      *  UserDatabase
593      * @return the object name of the created realm
594      *
595      * @exception Exception if an MBean cannot be created or registered
596      */

597     public String createUserDatabaseRealm(String parent, String resourceName)
598         throws Exception {
599
600          // Create a new UserDatabaseRealm instance
601         UserDatabaseRealm realm = new UserDatabaseRealm();
602         realm.setResourceName(resourceName);
603
604         // Add the new instance to its parent component
605         return addRealmToParent(parent, realm);
606     }
607
608
609     /**
610      * Create a new Valve and associate it with a {@link Container}.
611      *
612      * @param className The fully qualified class name of the {@link Valve} to
613      *                  create
614      * @param parent    The MBean name of the associated parent
615      *                  {@link Container}.
616      *
617      * @return  The MBean name of the {@link Valve} that was created or
618      *          <code>null</code> if the {@link Valve} does not implement
619      *          {@link JmxEnabled}.
620      * @exception Exception if an MBean cannot be created or registered
621      */

622     public String createValve(String className, String parent)
623             throws Exception {
624
625         // Look for the parent
626         ObjectName parentName = new ObjectName(parent);
627         Container container = getParentContainerFromParent(parentName);
628
629         if (container == null) {
630             // TODO
631             throw new IllegalArgumentException();
632         }
633
634         Valve valve = (Valve) Class.forName(className).getConstructor().newInstance();
635
636         container.getPipeline().addValve(valve);
637
638         if (valve instanceof JmxEnabled) {
639             return ((JmxEnabled) valve).getObjectName().toString();
640         } else {
641             return null;
642         }
643     }
644
645
646     /**
647      * Create a new Web Application Loader.
648      *
649      * @param parent MBean Name of the associated parent component
650      * @return the object name of the created loader
651      *
652      * @exception Exception if an MBean cannot be created or registered
653      */

654     public String createWebappLoader(String parent)
655         throws Exception {
656
657         // Create a new WebappLoader instance
658         WebappLoader loader = new WebappLoader();
659
660         // Add the new instance to its parent component
661         ObjectName pname = new ObjectName(parent);
662         Container container = getParentContainerFromParent(pname);
663         if (container instanceof Context) {
664             ((Context) container).setLoader(loader);
665         }
666         // FIXME add Loader.getObjectName
667         //ObjectName oname = loader.getObjectName();
668         ObjectName oname =
669             MBeanUtils.createObjectName(pname.getDomain(), loader);
670         return oname.toString();
671
672     }
673
674
675     /**
676      * Remove an existing Connector.
677      *
678      * @param name MBean Name of the component to remove
679      *
680      * @exception Exception if a component cannot be removed
681      */

682     public void removeConnector(String name) throws Exception {
683
684         // Acquire a reference to the component to be removed
685         ObjectName oname = new ObjectName(name);
686         Service service = getService(oname);
687         String port = oname.getKeyProperty("port");
688         String address = oname.getKeyProperty("address");
689         if (address != null) {
690             address = ObjectName.unquote(address);
691         }
692
693         Connector conns[] = service.findConnectors();
694
695         for (int i = 0; i < conns.length; i++) {
696             String connAddress = null;
697             Object objConnAddress = conns[i].getProperty("address");
698             if (objConnAddress != null) {
699                 connAddress = ((InetAddress) objConnAddress).getHostAddress();
700             }
701             String connPort = ""+conns[i].getPortWithOffset();
702
703             if (address == null) {
704                 // Don't combine this with outer if or we could get an NPE in
705                 // 'else if' below
706                 if (connAddress == null && port.equals(connPort)) {
707                     service.removeConnector(conns[i]);
708                     conns[i].destroy();
709                     break;
710                 }
711             } else if (address.equals(connAddress) && port.equals(connPort)) {
712                 service.removeConnector(conns[i]);
713                 conns[i].destroy();
714                 break;
715             }
716         }
717     }
718
719
720     /**
721      * Remove an existing Context.
722      *
723      * @param contextName MBean Name of the component to remove
724      *
725      * @exception Exception if a component cannot be removed
726      */

727     public void removeContext(String contextName) throws Exception {
728
729         // Acquire a reference to the component to be removed
730         ObjectName oname = new ObjectName(contextName);
731         String domain = oname.getDomain();
732         StandardService service = (StandardService) getService(oname);
733
734         Engine engine = service.getContainer();
735         String name = oname.getKeyProperty("name");
736         name = name.substring(2);
737         int i = name.indexOf('/');
738         String hostName = name.substring(0,i);
739         String path = name.substring(i);
740         ObjectName deployer = new ObjectName(domain+":type=Deployer,host="+
741                                              hostName);
742         String pathStr = getPathStr(path);
743         if(mserver.isRegistered(deployer)) {
744             mserver.invoke(deployer,"addServiced",
745                            new Object[]{pathStr},
746                            new String[] {"java.lang.String"});
747             mserver.invoke(deployer,"unmanageApp",
748                            new Object[] {pathStr},
749                            new String[] {"java.lang.String"});
750             mserver.invoke(deployer,"removeServiced",
751                            new Object[] {pathStr},
752                            new String[] {"java.lang.String"});
753         } else {
754             log.warn(sm.getString("mBeanFactory.noDeployer", hostName));
755             Host host = (Host) engine.findChild(hostName);
756             Context context = (Context) host.findChild(pathStr);
757             // Remove this component from its parent component
758             host.removeChild(context);
759             if(context instanceof StandardContext)
760             try {
761                 context.destroy();
762             } catch (Exception e) {
763                 log.warn(sm.getString("mBeanFactory.contextDestroyError"), e);
764            }
765
766         }
767
768     }
769
770
771     /**
772      * Remove an existing Host.
773      *
774      * @param name MBean Name of the component to remove
775      *
776      * @exception Exception if a component cannot be removed
777      */

778     public void removeHost(String name) throws Exception {
779
780         // Acquire a reference to the component to be removed
781         ObjectName oname = new ObjectName(name);
782         String hostName = oname.getKeyProperty("host");
783         Service service = getService(oname);
784         Engine engine = service.getContainer();
785         Host host = (Host) engine.findChild(hostName);
786
787         // Remove this component from its parent component
788         if(host!=null) {
789             engine.removeChild(host);
790         }
791     }
792
793
794     /**
795      * Remove an existing Loader.
796      *
797      * @param name MBean Name of the component to remove
798      *
799      * @exception Exception if a component cannot be removed
800      */

801     public void removeLoader(String name) throws Exception {
802
803         ObjectName oname = new ObjectName(name);
804         // Acquire a reference to the component to be removed
805         Container container = getParentContainerFromChild(oname);
806         if (container instanceof Context) {
807             ((Context) container).setLoader(null);
808         }
809     }
810
811
812     /**
813      * Remove an existing Manager.
814      *
815      * @param name MBean Name of the component to remove
816      *
817      * @exception Exception if a component cannot be removed
818      */

819     public void removeManager(String name) throws Exception {
820
821         ObjectName oname = new ObjectName(name);
822         // Acquire a reference to the component to be removed
823         Container container = getParentContainerFromChild(oname);
824         if (container instanceof Context) {
825             ((Context) container).setManager(null);
826         }
827     }
828
829
830     /**
831      * Remove an existing Realm.
832      *
833      * @param name MBean Name of the component to remove
834      *
835      * @exception Exception if a component cannot be removed
836      */

837     public void removeRealm(String name) throws Exception {
838
839         ObjectName oname = new ObjectName(name);
840         // Acquire a reference to the component to be removed
841         Container container = getParentContainerFromChild(oname);
842         container.setRealm(null);
843     }
844
845
846     /**
847      * Remove an existing Service.
848      *
849      * @param name MBean Name of the component to remove
850      *
851      * @exception Exception if a component cannot be removed
852      */

853     public void removeService(String name) throws Exception {
854
855         if (!(container instanceof Server)) {
856             throw new Exception();
857         }
858
859         // Acquire a reference to the component to be removed
860         ObjectName oname = new ObjectName(name);
861         Service service = getService(oname);
862         ((Server) container).removeService(service);
863     }
864
865
866     /**
867      * Remove an existing Valve.
868      *
869      * @param name MBean Name of the component to remove
870      *
871      * @exception Exception if a component cannot be removed
872      */

873     public void removeValve(String name) throws Exception {
874
875         // Acquire a reference to the component to be removed
876         ObjectName oname = new ObjectName(name);
877         Container container = getParentContainerFromChild(oname);
878         Valve[] valves = container.getPipeline().getValves();
879         for (int i = 0; i < valves.length; i++) {
880             ObjectName voname = ((JmxEnabled) valves[i]).getObjectName();
881             if (voname.equals(oname)) {
882                 container.getPipeline().removeValve(valves[i]);
883             }
884         }
885     }
886
887 }
888
889