001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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.servicemix.jbi.framework;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.Collections;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Properties;
025    
026    import javax.jbi.JBIException;
027    import javax.jbi.management.LifeCycleMBean;
028    import javax.management.JMException;
029    import javax.management.MBeanOperationInfo;
030    
031    import org.apache.servicemix.jbi.management.BaseSystemService;
032    import org.apache.servicemix.jbi.management.OperationInfoHelper;
033    import org.apache.servicemix.jbi.management.ParameterHelper;
034    
035    public class AdminCommandsService extends BaseSystemService implements AdminCommandsServiceMBean {
036    
037        /**
038         * @return a description of this
039         */
040        public String getDescription() {
041            return "Admin Commands Service";
042        }
043    
044        protected Class getServiceMBean() {
045            return AdminCommandsServiceMBean.class;
046        }
047    
048        /**
049         * Install a JBI component (a Service Engine or Binding Component)
050         * 
051         * @param file
052         *            jbi component archive to install
053         * @param props
054         *            installation properties
055         * @return
056         */
057        public String installComponent(String file, Properties props, boolean deferException) throws Exception {
058            try {
059                if (deferException) {
060                    container.updateExternalArchive(file);
061                } else {
062                    container.getInstallationService().install(file, props, false);
063                }
064                return ManagementSupport.createSuccessMessage("installComponent", file);
065            } catch (Exception e) {
066                throw ManagementSupport.failure("installComponent", file, e);
067            }
068        }
069    
070        /**
071         * Uninstalls a previously install JBI Component (a Service Engine or
072         * Binding Component)
073         * 
074         * @param name
075         * @return
076         */
077        public String uninstallComponent(String name) throws Exception {
078            ComponentMBeanImpl comp = container.getComponent(name);
079            if (comp == null) {
080                throw ManagementSupport.failure("uninstallComponent", "Component '" + name + "' is not installed.");
081            }
082            if (!comp.isShutDown()) {
083                throw ManagementSupport.failure("uninstallComponent", "Component '" + name + "' is not shut down.");
084            }
085            boolean success = container.getInstallationService().unloadInstaller(name, true);
086            if (success) {
087                return ManagementSupport.createSuccessMessage("uninstallComponent", name);
088            } else {
089                throw ManagementSupport.failure("uninstallComponent", name);
090            }
091        }
092    
093        /**
094         * Installs a Shared Library.
095         * 
096         * @param file
097         * @return
098         */
099        public String installSharedLibrary(String file, boolean deferException) throws Exception {
100            if (deferException) {
101                container.updateExternalArchive(file);
102                return ManagementSupport.createSuccessMessage("installSharedLibrary", file);
103            } else {
104                return container.getInstallationService().installSharedLibrary(file);
105            }
106        }
107    
108        /**
109         * Uninstalls a previously installed Shared Library.
110         * 
111         * @param name
112         * @return
113         */
114        public String uninstallSharedLibrary(String name) throws Exception {
115            // Check that the library is installed
116            SharedLibrary sl = container.getRegistry().getSharedLibrary(name);
117            if (sl == null) {
118                throw ManagementSupport.failure("uninstallSharedLibrary", "Shared library '" + name + "' is not installed.");
119            }
120            // Check that it is not used by a running component
121            Collection components = container.getRegistry().getComponents();
122            for (Iterator iter = components.iterator(); iter.hasNext();) {
123                ComponentMBeanImpl comp = (ComponentMBeanImpl) iter.next();
124                if (!comp.isShutDown()) {
125                    String[] sls = comp.getSharedLibraries();
126                    if (sls != null) {
127                        for (int i = 0; i < sls.length; i++) {
128                            if (name.equals(sls[i])) {
129                                throw ManagementSupport.failure("uninstallSharedLibrary", "Shared library '" + name
130                                                + "' is used by component '" + comp.getName() + "'.");
131                            }
132                        }
133                    }
134                }
135            }
136            boolean success = container.getInstallationService().uninstallSharedLibrary(name);
137            if (success) {
138                return ManagementSupport.createSuccessMessage("uninstallSharedLibrary", name);
139            } else {
140                throw ManagementSupport.failure("uninstallSharedLibrary", name);
141            }
142        }
143    
144        /**
145         * Starts a particular Component (Service Engine or Binding Component).
146         * 
147         * @param name
148         * @return
149         */
150        public String startComponent(String name) throws Exception {
151            try {
152                ComponentMBeanImpl lcc = container.getComponent(name);
153                if (lcc == null) {
154                    throw new JBIException("Component " + name + " not found");
155                }
156                lcc.start();
157                return ManagementSupport.createSuccessMessage("startComponent", name);
158            } catch (JBIException e) {
159                throw ManagementSupport.failure("startComponent", name, e);
160            }
161        }
162    
163        /**
164         * Stops a particular Component (Service Engine or Binding Component).
165         * 
166         * @param name
167         * @return
168         */
169        public String stopComponent(String name) throws Exception {
170            try {
171                ComponentMBeanImpl lcc = container.getComponent(name);
172                if (lcc == null) {
173                    throw new JBIException("Component " + name + " not found");
174                }
175                lcc.stop();
176                return ManagementSupport.createSuccessMessage("stopComponent", name);
177            } catch (JBIException e) {
178                throw ManagementSupport.failure("stopComponent", name, e);
179            }
180        }
181    
182        /**
183         * Shuts down a particular Component.
184         * 
185         * @param name
186         * @return
187         */
188        public String shutdownComponent(String name) throws Exception {
189            try {
190                ComponentMBeanImpl lcc = container.getComponent(name);
191                if (lcc == null) {
192                    throw new JBIException("Component " + name + " not found");
193                }
194                lcc.shutDown();
195                return ManagementSupport.createSuccessMessage("shutdownComponent", name);
196            } catch (JBIException e) {
197                throw ManagementSupport.failure("shutdownComponent", name, e);
198            }
199        }
200    
201        /**
202         * Deploys a Service Assembly.
203         * 
204         * @param file
205         * @return
206         */
207        public String deployServiceAssembly(String file, boolean deferException) throws Exception {
208            if (deferException) {
209                container.updateExternalArchive(file);
210                return ManagementSupport.createSuccessMessage("deployServiceAssembly", file);
211            } else {
212                return container.getDeploymentService().deploy(file);
213            }
214        }
215    
216        /**
217         * Undeploys a previously deployed service assembly.
218         * 
219         * @param name
220         * @return
221         */
222        public String undeployServiceAssembly(String name) throws Exception {
223            return container.getDeploymentService().undeploy(name);
224        }
225    
226        /**
227         * Starts a service assembly.
228         * 
229         * @param name
230         * @return
231         */
232        public String startServiceAssembly(String name) throws Exception {
233            return container.getDeploymentService().start(name);
234        }
235    
236        /**
237         * Stops a particular service assembly.
238         * 
239         * @param name
240         * @return
241         */
242        public String stopServiceAssembly(String name) throws Exception {
243            return container.getDeploymentService().stop(name);
244        }
245    
246        /**
247         * Shuts down a particular service assembly.
248         * 
249         * @param name
250         * @return
251         */
252        public String shutdownServiceAssembly(String name) throws Exception {
253            return container.getDeploymentService().shutDown(name);
254        }
255    
256        /**
257         * load an archive from an external location and starts it The archive can
258         * be a Component, Service Assembly or Shared Library.
259         * 
260         * @param location -
261         *            can either be a url or filename (if relative - must be
262         *            relative to the container)
263         * @return status
264         * @throws Exception
265         */
266        public String installArchive(String location) throws Exception {
267            try {
268                container.updateExternalArchive(location);
269                return ManagementSupport.createSuccessMessage("installComponent", location);
270            } catch (Exception e) {
271                throw ManagementSupport.failure("installComponent", location, e);
272            }
273        }
274    
275        /**
276         * Prints information about all components (Service Engine or Binding
277         * Component) installed
278         * 
279         * @param serviceEngines
280         * @param bindingComponents
281         * @param state
282         * @param sharedLibraryName
283         * @param serviceAssemblyName
284         * @return list of components in an XML blob
285         */
286        public String listComponents(boolean excludeSEs, boolean excludeBCs, boolean excludePojos, String requiredState,
287                        String sharedLibraryName, String serviceAssemblyName) throws Exception {
288            // validate requiredState
289            if (requiredState != null && requiredState.length() > 0
290                            && !LifeCycleMBean.UNKNOWN.equalsIgnoreCase(requiredState)
291                            && !LifeCycleMBean.SHUTDOWN.equalsIgnoreCase(requiredState)
292                            && !LifeCycleMBean.STOPPED.equalsIgnoreCase(requiredState)
293                            && !LifeCycleMBean.STARTED.equalsIgnoreCase(requiredState)) {
294                throw ManagementSupport.failure("listComponents", "Required state '" + requiredState + "' is not a valid state.");
295            }
296            // Get components
297            Collection connectors = container.getRegistry().getComponents();
298            List<ComponentMBeanImpl> components = new ArrayList<ComponentMBeanImpl>();
299            for (Iterator iter = connectors.iterator(); iter.hasNext();) {
300                ComponentMBeanImpl component = (ComponentMBeanImpl) iter.next();
301                // Skip SEs if needed
302                if (excludeSEs && component.isService()) {
303                    continue;
304                }
305                // Skip BCs if needed
306                if (excludeBCs && component.isBinding()) {
307                    continue;
308                }
309                // Skip Pojos if needed
310                if (excludePojos && component.isPojo()) {
311                    continue;
312                }
313                // Check status
314                if (requiredState != null && requiredState.length() > 0 && !requiredState.equalsIgnoreCase(component.getCurrentState())) {
315                    continue;
316                }
317                // Check shared library
318                // TODO: check component dependency on SL
319                if (sharedLibraryName != null && sharedLibraryName.length() > 0
320                                && !container.getInstallationService().containsSharedLibrary(sharedLibraryName)) {
321                    continue;
322                }
323                // Check deployed service assembly
324                // TODO: check SA dependency on component
325                if (serviceAssemblyName != null && serviceAssemblyName.length() > 0) {
326                    String[] saNames = container.getRegistry().getDeployedServiceAssembliesForComponent(component.getName());
327                    boolean found = false;
328                    for (int i = 0; i < saNames.length; i++) {
329                        if (serviceAssemblyName.equals(saNames[i])) {
330                            found = true;
331                            break;
332                        }
333                    }
334                    if (!found) {
335                        continue;
336                    }
337                }
338                components.add(component);
339            }
340    
341            StringBuffer buffer = new StringBuffer();
342            buffer.append("<?xml version='1.0'?>\n");
343            buffer.append("<component-info-list xmlns='http://java.sun.com/xml/ns/jbi/component-info-list' version='1.0'>\n");
344            for (Iterator<ComponentMBeanImpl> iter = components.iterator(); iter.hasNext();) {
345                ComponentMBeanImpl component = iter.next();
346                buffer.append("  <component-info");
347                if (!component.isBinding() && component.isService()) {
348                    buffer.append(" type='service-engine'");
349                } else if (component.isBinding() && !component.isService()) {
350                    buffer.append(" type='binding-component'");
351                }
352                buffer.append(" name='" + component.getName() + "'");
353                buffer.append(" state='" + component.getCurrentState() + "'>\n");
354                if (component.getDescription() != null) {
355                    buffer.append("    <description>");
356                    buffer.append(component.getDescription());
357                    buffer.append("</description>\n");
358                }
359                buffer.append("  </component-info>\n");
360            }
361            buffer.append("</component-info-list>");
362            return buffer.toString();
363        }
364    
365        /**
366         * Prints information about shared libraries installed.
367         * 
368         * @param componentName
369         * @param sharedLibraryName
370         * @return
371         */
372        public String listSharedLibraries(String componentName, String sharedLibraryName) throws Exception {
373            Collection<SharedLibrary> libs;
374            if (sharedLibraryName != null) {
375                SharedLibrary sl = container.getRegistry().getSharedLibrary(sharedLibraryName);
376                if (sl == null) {
377                    libs = Collections.EMPTY_LIST;
378                } else {
379                    libs = Collections.singletonList(sl);
380                }
381            } else if (componentName != null) {
382                // TODO: handle componentName
383                libs = container.getRegistry().getSharedLibraries();
384            } else {
385                libs = container.getRegistry().getSharedLibraries();
386            }
387            StringBuffer buffer = new StringBuffer();
388            buffer.append("<?xml version='1.0'?>\n");
389            buffer.append("<component-info-list xmlns='http://java.sun.com/xml/ns/jbi/component-info-list' version='1.0'>\n");
390            for (Iterator<SharedLibrary> iter = libs.iterator(); iter.hasNext();) {
391                SharedLibrary sl = iter.next();
392                buffer.append("  <component-info type='shared-library' name='").append(sl.getName()).append("' state='Started'>");
393                if (sl.getDescription() != null) {
394                    buffer.append("    <description>");
395                    buffer.append(sl.getDescription());
396                    buffer.append("</description>\n");
397                }
398                buffer.append("  </component-info>\n");
399            }
400            buffer.append("</component-info-list>");
401            return buffer.toString();
402        }
403    
404        /**
405         * Prints information about service assemblies deployed.
406         * 
407         * @param state
408         * @param componentName
409         * @param serviceAssemblyName
410         * @return
411         */
412        public String listServiceAssemblies(String state, String componentName, String serviceAssemblyName) throws Exception {
413            String[] result = null;
414            if (null != serviceAssemblyName && serviceAssemblyName.length() > 0) {
415                result = new String[] {serviceAssemblyName };
416            } else if (null != componentName && componentName.length() > 0) {
417                result = container.getRegistry().getDeployedServiceAssembliesForComponent(componentName);
418            } else {
419                result = container.getRegistry().getDeployedServiceAssemblies();
420            }
421    
422            List<ServiceAssemblyLifeCycle> assemblies = new ArrayList<ServiceAssemblyLifeCycle>();
423            for (int i = 0; i < result.length; i++) {
424                ServiceAssemblyLifeCycle sa = container.getRegistry().getServiceAssembly(result[i]);
425                if (sa != null) {
426                    // Check status
427                    if (state != null && state.length() > 0 && !state.equals(sa.getCurrentState())) {
428                        continue;
429                    }
430                    assemblies.add(sa);
431                }
432            }
433    
434            StringBuffer buffer = new StringBuffer();
435            buffer.append("<?xml version='1.0'?>\n");
436            buffer.append("<service-assembly-info-list xmlns='http://java.sun.com/xml/ns/jbi/service-assembly-info-list' version='1.0'>\n");
437            for (Iterator<ServiceAssemblyLifeCycle> iter = assemblies.iterator(); iter.hasNext();) {
438                ServiceAssemblyLifeCycle sa = iter.next();
439                buffer.append("  <service-assembly-info");
440                buffer.append(" name='" + sa.getName() + "'");
441                buffer.append(" state='" + sa.getCurrentState() + "'>\n");
442                buffer.append("    <description>" + sa.getDescription() + "</description>\n");
443    
444                ServiceUnitLifeCycle[] serviceUnitList = sa.getDeployedSUs();
445                for (int i = 0; i < serviceUnitList.length; i++) {
446                    buffer.append("    <service-unit-info");
447                    buffer.append(" name='" + serviceUnitList[i].getName() + "'");
448                    buffer.append(" state='" + serviceUnitList[i].getCurrentState() + "'");
449                    buffer.append(" deployed-on='" + serviceUnitList[i].getComponentName() + "'>\n");
450                    buffer.append("      <description>" + serviceUnitList[i].getDescription() + "</description>\n");
451                    buffer.append("    </service-unit-info>\n");
452                }
453    
454                buffer.append("  </service-assembly-info>\n");
455            }
456            buffer.append("</service-assembly-info-list>");
457    
458            return buffer.toString();
459        }
460    
461        public MBeanOperationInfo[] getOperationInfos() throws JMException {
462            OperationInfoHelper helper = new OperationInfoHelper();
463            ParameterHelper ph = helper.addOperation(getObjectToManage(), "installComponent", 3, "install a component");
464            ph.setDescription(0, "file", "location of JBI Component to install");
465            ph.setDescription(1, "properties", "component installation properties");
466            ph.setDescription(1, "deferExceptions", "true if exceptions due to missing dependencies should be differed");
467    
468            ph = helper.addOperation(getObjectToManage(), "uninstallComponent", 1, "uninstall a component");
469            ph.setDescription(0, "name", "component name to uninstall");
470    
471            ph = helper.addOperation(getObjectToManage(), "installSharedLibrary", 1, "install a shared library");
472            ph.setDescription(0, "file", "location of shared library to install");
473    
474            ph = helper.addOperation(getObjectToManage(), "uninstallSharedLibrary", 1, "uninstall a shared library");
475            ph.setDescription(0, "name", "name of shared library to uninstall");
476    
477            ph = helper.addOperation(getObjectToManage(), "installArchive", 1, "install an archive (component/SA etc)");
478            ph.setDescription(0, "location", "file name or url to the location");
479    
480            ph = helper.addOperation(getObjectToManage(), "startComponent", 1, "start a component");
481            ph.setDescription(0, "name", "name of component to start");
482    
483            ph = helper.addOperation(getObjectToManage(), "stopComponent", 1, "stop a component");
484            ph.setDescription(0, "name", "name of component to stop");
485    
486            ph = helper.addOperation(getObjectToManage(), "shutdownComponent", 1, "shutdown a component");
487            ph.setDescription(0, "name", "name of component to shutdown");
488    
489            ph = helper.addOperation(getObjectToManage(), "deployServiceAssembly", 1, "deploy a service assembly");
490            ph.setDescription(0, "file", "location of service assembly to deploy");
491    
492            ph = helper.addOperation(getObjectToManage(), "undeployServiceAssembly", 1, "undeploy a service assembly");
493            ph.setDescription(0, "name", "name of service assembly to undeploy");
494    
495            ph = helper.addOperation(getObjectToManage(), "startServiceAssembly", 1, "start a service assembly");
496            ph.setDescription(0, "name", "name of service assembly to start");
497    
498            ph = helper.addOperation(getObjectToManage(), "stopServiceAssembly", 1, "stop a service assembly");
499            ph.setDescription(0, "name", "name of service assembly to stop");
500    
501            ph = helper.addOperation(getObjectToManage(), "shutdownServiceAssembly", "shutdown a service assembly");
502            ph.setDescription(0, "name", "name of service assembly to shutdown");
503    
504            ph = helper.addOperation(getObjectToManage(), "listComponents", 5, "list all components installed");
505            ph.setDescription(0, "excludeSEs", "if true will exclude service engines");
506            ph.setDescription(1, "excludeBCs", "if true will exclude binding components");
507            ph.setDescription(1, "excludePojos", "if true will exclude pojos components");
508            ph.setDescription(2, "requiredState", "component state to list, if null will list all");
509            ph.setDescription(3, "sharedLibraryName", "shared library name to list");
510            ph.setDescription(4, "serviceAssemblyName", "service assembly name to list");
511    
512            ph = helper.addOperation(getObjectToManage(), "listSharedLibraries", 2, "list shared library");
513            ph.setDescription(0, "componentName", "component name");
514            ph.setDescription(1, "sharedLibraryName", "shared library name");
515    
516            ph = helper.addOperation(getObjectToManage(), "listServiceAssemblies", 3, "list service assemblies");
517            ph.setDescription(0, "state", "service assembly state to list");
518            ph.setDescription(1, "componentName", "component name");
519            ph.setDescription(2, "serviceAssemblyName", "service assembly name");
520    
521            return OperationInfoHelper.join(super.getOperationInfos(), helper.getOperationInfos());
522        }
523    
524    }