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.io.File;
020    import java.io.IOException;
021    import java.io.StringReader;
022    import java.util.ArrayList;
023    import java.util.Iterator;
024    import java.util.List;
025    
026    import javax.jbi.JBIException;
027    import javax.jbi.component.ServiceUnitManager;
028    import javax.jbi.management.DeploymentException;
029    import javax.jbi.management.DeploymentServiceMBean;
030    import javax.management.JMException;
031    import javax.management.MBeanAttributeInfo;
032    import javax.management.MBeanOperationInfo;
033    import javax.xml.parsers.DocumentBuilder;
034    import javax.xml.parsers.DocumentBuilderFactory;
035    import javax.xml.parsers.ParserConfigurationException;
036    
037    import org.w3c.dom.Document;
038    import org.w3c.dom.Element;
039    import org.w3c.dom.NodeList;
040    
041    import org.xml.sax.InputSource;
042    import org.xml.sax.SAXException;
043    
044    import org.apache.commons.logging.Log;
045    import org.apache.commons.logging.LogFactory;
046    import org.apache.servicemix.jbi.container.EnvironmentContext;
047    import org.apache.servicemix.jbi.container.JBIContainer;
048    import org.apache.servicemix.jbi.container.ServiceAssemblyEnvironment;
049    import org.apache.servicemix.jbi.deployment.Descriptor;
050    import org.apache.servicemix.jbi.deployment.DescriptorFactory;
051    import org.apache.servicemix.jbi.deployment.ServiceAssembly;
052    import org.apache.servicemix.jbi.deployment.ServiceUnit;
053    import org.apache.servicemix.jbi.management.AttributeInfoHelper;
054    import org.apache.servicemix.jbi.management.BaseSystemService;
055    import org.apache.servicemix.jbi.management.OperationInfoHelper;
056    import org.apache.servicemix.jbi.management.ParameterHelper;
057    import org.apache.servicemix.jbi.util.DOMUtil;
058    import org.apache.servicemix.jbi.util.FileUtil;
059    
060    /**
061     * The deployment service MBean allows administrative tools to manage service assembly deployments.
062     * 
063     * @version $Revision: 564900 $
064     */
065    public class DeploymentService extends BaseSystemService implements DeploymentServiceMBean {
066        
067        private static final Log LOG = LogFactory.getLog(DeploymentService.class);
068        
069        private EnvironmentContext environmentContext;
070        private Registry registry;
071        
072        //
073        // ServiceMix service implementation
074        //
075    
076        /**
077         * Initialize the Service
078         * 
079         * @param container
080         * @throws JBIException 
081         * @throws DeploymentException
082         */
083        public void init(JBIContainer container) throws JBIException {
084            this.environmentContext = container.getEnvironmentContext();
085            this.registry = container.getRegistry();
086            super.init(container);
087            buildState();
088        }
089        
090        protected Class<DeploymentServiceMBean> getServiceMBean() {
091            return DeploymentServiceMBean.class;
092        }
093    
094        public void start() throws javax.jbi.JBIException {
095            super.start();
096            String[] sas = registry.getDeployedServiceAssemblies();
097            for (int i = 0; i < sas.length; i++) {
098                try {
099                    ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(sas[i]);
100                    sa.restore();
101                } catch (Exception e) {
102                    LOG.error("Unable to restore state for service assembly " + sas[i], e);
103                }
104            }
105        }
106        
107        /**
108         * Get an array of MBeanAttributeInfo
109         * 
110         * @return array of AttributeInfos
111         * @throws JMException
112         */
113        public MBeanAttributeInfo[] getAttributeInfos() throws JMException {
114            AttributeInfoHelper helper = new AttributeInfoHelper();
115            helper.addAttribute(getObjectToManage(), "deployedServiceAssemblies", "list of deployed SAs");
116            return AttributeInfoHelper.join(super.getAttributeInfos(), helper.getAttributeInfos());
117        }
118    
119        /**
120         * Get an array of MBeanOperationInfo
121         * 
122         * @return array of OperationInfos
123         * @throws JMException
124         */
125        public MBeanOperationInfo[] getOperationInfos() throws JMException {
126            OperationInfoHelper helper = new OperationInfoHelper();
127            ParameterHelper ph = helper.addOperation(getObjectToManage(), "deploy", 1, "deploy An SA");
128            ph.setDescription(0, "saZipURL", "location of SA zip file");
129            ph = helper.addOperation(getObjectToManage(), "undeploy", 1, "undeploy An SA");
130            ph.setDescription(0, "saName", "SA name");
131            ph = helper.addOperation(getObjectToManage(), "getDeployedServiceUnitList", 1,
132                    "list of SU's currently deployed");
133            ph.setDescription(0, "componentName", "Component name");
134            ph = helper.addOperation(getObjectToManage(), "getServiceAssemblyDescriptor", 1, "Get descriptor for a SA");
135            ph.setDescription(0, "saName", "SA name");
136            ph = helper.addOperation(getObjectToManage(), "getDeployedServiceAssembliesForComponent", 1,
137                    "list of SA's for a Component");
138            ph.setDescription(0, "componentName", "Component name");
139            ph = helper.addOperation(getObjectToManage(), "getComponentsForDeployedServiceAssembly", 1,
140                    "list of Components  for a SA");
141            ph.setDescription(0, "saName", "SA name");
142            ph = helper.addOperation(getObjectToManage(), "isDeployedServiceUnit", 2, "is SU deployed at a Component ?");
143            ph.setDescription(0, "componentName", "Component name");
144            ph.setDescription(1, "suName", "SU name");
145            ph = helper
146                    .addOperation(getObjectToManage(), "canDeployToComponent", 1, "Can a SU be deployed to a Component?");
147            ph.setDescription(0, "componentName", "Component name");
148            ph = helper.addOperation(getObjectToManage(), "start", 1, "start an SA");
149            ph.setDescription(0, "saName", "SA name");
150            ph = helper.addOperation(getObjectToManage(), "stop", 1, "stop an SA");
151            ph.setDescription(0, "saName", "SA name");
152            ph = helper.addOperation(getObjectToManage(), "shutDown", 1, "shutDown an SA");
153            ph.setDescription(0, "saName", "SA name");
154            ph = helper.addOperation(getObjectToManage(), "getState", 1, "Running state of an SA");
155            ph.setDescription(0, "saName", "SA name");
156            return OperationInfoHelper.join(super.getOperationInfos(), helper.getOperationInfos());
157        }
158        /**
159         * Get the description
160         * 
161         * @return description
162         */
163        public String getDescription() {
164            return "Allows admin tools to manage service deployments";
165        }
166    
167        //
168        // DeploymentServiceMBean implementation
169        //
170    
171        /**
172         * Deploys the given SA to the JBI environment.
173         * 
174         * @param saZipURL String containing the location of the Service Assembly zip file.
175         * @return Result/Status of the SA deployment in xml format.
176         * @throws Exception in xml format if complete deployment fails.
177         */
178        public String deploy(String saZipURL) throws Exception {
179            try {
180                if (saZipURL == null) {
181                    throw ManagementSupport.failure("deploy", "saZipURL must not be null");
182                }
183                File tmpDir = null;
184                try {
185                    tmpDir = AutoDeploymentService.unpackLocation(environmentContext.getTmpDir(), saZipURL);
186                } catch (Exception e) {
187                    throw ManagementSupport.failure("deploy", "Unable to unpack archive: " + saZipURL, e);
188                }
189                // unpackLocation returns null if no jbi descriptor is found
190                if (tmpDir == null) {
191                    throw ManagementSupport.failure("deploy", "Unable to find jbi descriptor: " + saZipURL);
192                }
193                Descriptor root = null;
194                try {
195                    root = DescriptorFactory.buildDescriptor(tmpDir);
196                } catch (Exception e) {
197                    throw ManagementSupport.failure("deploy", "Unable to build jbi descriptor: " + saZipURL, e);
198                }
199                if (root == null) {
200                    throw ManagementSupport.failure("deploy", "Unable to find jbi descriptor: " + saZipURL);
201                }
202                ServiceAssembly sa = root.getServiceAssembly();
203                if (sa == null) {
204                    throw ManagementSupport.failure("deploy", "JBI descriptor is not an assembly descriptor: " + saZipURL);
205                }
206                return deployServiceAssembly(tmpDir, sa);
207            } catch (Exception e) {
208                LOG.error("Error deploying service assembly", e);
209                throw e;
210            }
211        }
212    
213        /**
214         * Undeploys the given SA from the JBI environment.
215         * 
216         * @param saName name of the SA that has to be undeployed.
217         * @return Result/Status of the SA undeployment.
218         * @throws Exception if compelete undeployment fails.
219         */
220        public String undeploy(String saName) throws Exception {
221            if (saName == null) {
222                throw ManagementSupport.failure("undeploy", "SA name must not be null");
223            }
224            ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(saName);
225            if (sa == null) {
226                throw ManagementSupport.failure("undeploy", "SA has not been deployed: " + saName);
227            }
228            String state = sa.getCurrentState();
229            if (!DeploymentServiceMBean.SHUTDOWN.equals(state)) {
230                throw ManagementSupport.failure("undeploy", "SA must be shut down: " + saName);
231            }
232            try {
233                // Make sure the all service units in the assembly are shutdown.
234                // SUs can have different states (if a previous shutdown failed).
235                try {
236                    sa.shutDown();
237                } catch (Exception e) {
238                    // Ignore
239                }
240    
241                String result = null;
242                String assemblyName = sa.getName();
243                registry.unregisterServiceAssembly(assemblyName);
244                ServiceUnitLifeCycle[] sus = sa.getDeployedSUs();
245                if (sus != null) {
246                    for (int i = 0; i < sus.length; i++) {
247                        undeployServiceUnit(sus[i]);
248                    }
249                }
250                FileUtil.deleteFile(sa.getEnvironment().getRootDir());
251    
252                return result;
253            } catch (Exception e) {
254                LOG.info("Unable to undeploy assembly", e);
255                throw e;
256            }
257        }
258    
259        /**
260         * Returns a list of Service Units that are currently deployed to the given component.
261         * 
262         * @param componentName name of the component.
263         * @return List of deployed ASA Ids.
264         */
265        public String[] getDeployedServiceUnitList(String componentName) throws Exception {
266            try {
267                ServiceUnitLifeCycle[] sus = registry.getDeployedServiceUnits(componentName);
268                String[] names = new String[sus.length];
269                for (int i = 0; i < names.length; i++) {
270                    names[i] = sus[i].getName();
271                }
272                return names;
273            } catch (Exception e) {
274                LOG.info("Unable to get deployed service unit list", e);
275                throw e;
276            }
277        }
278    
279        /**
280         * Returns a list of Service Assemblies deployed to the JBI enviroment.
281         * 
282         * @return list of Service Assembly Name's.
283         */
284        public String[] getDeployedServiceAssemblies() throws Exception {
285            try {
286                return registry.getDeployedServiceAssemblies();
287            } catch (Exception e) {
288                LOG.info("Unable to get deployed service assemblies", e);
289                throw e;
290            }
291        }
292    
293        /**
294         * Returns the descriptor of the Service Assembly that was deployed to the JBI enviroment.
295         * 
296         * @param saName name of the service assembly.
297         * @return descriptor of the Service Assembly.
298         */
299        public String getServiceAssemblyDescriptor(String saName) throws Exception {
300            ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(saName);
301            if (sa != null) {
302                return sa.getDescriptor();
303            } else {
304                return null;
305            }
306        }
307    
308        /**
309         * Returns a list of Service Assemblies that contain SUs for the given component.
310         * 
311         * @param componentName name of the component.
312         * @return list of Service Assembly names.
313         * @throws Exception if unable to retrieve service assembly list.
314         */
315        public String[] getDeployedServiceAssembliesForComponent(String componentName) throws Exception {
316            try {
317                return registry.getDeployedServiceAssembliesForComponent(componentName);
318            } catch (Exception e) {
319                LOG.info("Error in getDeployedServiceAssembliesForComponent", e);
320                throw e;
321            }
322        }
323    
324        /**
325         * Returns a list of components(to which SUs are targeted for) in a Service Assembly.
326         * 
327         * @param saName name of the service assembly.
328         * @return list of component names.
329         * @throws Exception if unable to retrieve component list.
330         */
331        public String[] getComponentsForDeployedServiceAssembly(String saName) throws Exception {
332            try {
333                return registry.getComponentsForDeployedServiceAssembly(saName);
334            } catch (Exception e) {
335                LOG.info("Error in getComponentsForDeployedServiceAssembly", e);
336                throw e;
337            }
338        }
339    
340        /**
341         * Returns a boolean value indicating whether the SU is currently deployed.
342         * 
343         * @param componentName - name of component.
344         * @param suName - name of the Service Unit.
345         * @return boolean value indicating whether the SU is currently deployed.
346         * @throws Exception if unable to return status of service unit.
347         */
348        public boolean isDeployedServiceUnit(String componentName, String suName) throws Exception {
349            try {
350                return registry.isSADeployedServiceUnit(componentName, suName);
351            } catch (Exception e) {
352                LOG.info("Error in isSADeployedServiceUnit", e);
353                throw e;
354            }
355        }
356    
357        /**
358         * Returns a boolean value indicating whether the SU can be deployed to a component.
359         * 
360         * @param componentName - name of the component.
361         * @return boolean value indicating whether the SU can be deployed.
362         */
363        public boolean canDeployToComponent(String componentName) {
364            ComponentMBeanImpl lcc = container.getComponent(componentName);
365            return lcc != null && lcc.isStarted() && lcc.getServiceUnitManager() != null;
366        }
367    
368        /**
369         * Starts the service assembly and puts it in STARTED state.
370         * 
371         * @param serviceAssemblyName - name of the service assembly.
372         * @return Result/Status of this operation.
373         * @throws Exception if operation fails.
374         */
375        public String start(String serviceAssemblyName) throws Exception {
376            try {
377                ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(serviceAssemblyName);
378                return sa.start(true);
379            } catch (Exception e) {
380                LOG.info("Error in start", e);
381                throw e;
382            }
383        }
384        
385        
386    
387        /**
388         * Stops the service assembly and puts it in STOPPED state.
389         * 
390         * @param serviceAssemblyName - name of the service assembly.
391         * @return Result/Status of this operation.
392         * @throws Exception if operation fails.
393         */
394        public String stop(String serviceAssemblyName) throws Exception {
395            try {
396                ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(serviceAssemblyName);
397                return sa.stop(true, false);
398            } catch (Exception e) {
399                LOG.info("Error in stop", e);
400                throw e;
401            }
402        }
403    
404        /**
405         * Shutdown the service assembly and puts it in SHUTDOWN state.
406         * 
407         * @param serviceAssemblyName - name of the service assembly.
408         * @return Result/Status of this operation.
409         * @throws Exception if operation fails.
410         */
411        public String shutDown(String serviceAssemblyName) throws Exception {
412            try {
413                ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(serviceAssemblyName);
414                return sa.shutDown(true);
415            } catch (Exception e) {
416                LOG.info("Error in shutDown", e);
417                throw e;
418            }
419        }
420    
421        /**
422         * Returns the state of service assembly.
423         * 
424         * @param serviceAssemblyName - name of the service assembly.
425         * @return State of the service assembly.
426         * @throws Exception if operation fails.
427         */
428        public String getState(String serviceAssemblyName) throws Exception {
429            try {
430                ServiceAssemblyLifeCycle sa = registry.getServiceAssembly(serviceAssemblyName);
431                return sa.getCurrentState();
432            } catch (Exception e) {
433                LOG.info("Error in getState", e);
434                throw e;
435            }
436        }
437    
438        /**
439         * See if an Sa is already deployed
440         * 
441         * @param serviceAssemblyName - name of the service assembly.
442         * @return true if already deployed
443         */
444        protected boolean isSaDeployed(String serviceAssemblyName) {
445            return registry.getServiceAssembly(serviceAssemblyName) != null;
446        }
447    
448        /**
449         * Deploy an SA
450         * 
451         * @param tmpDir
452         * @param sa
453         * @return result/status of the deployment in xml format
454         * @throws Exception  in xml format
455         */
456        protected String deployServiceAssembly(File tmpDir, ServiceAssembly sa) throws Exception {
457            String assemblyName = sa.getIdentification().getName();
458            ServiceAssemblyEnvironment env = environmentContext.getNewServiceAssemblyEnvironment(assemblyName);
459            File saDirectory = env.getInstallDir();
460    
461            // move the assembly to a well-named holding area
462            if (LOG.isDebugEnabled()) {
463                LOG.debug("Moving " + tmpDir.getAbsolutePath() + " to " + saDirectory.getAbsolutePath());
464            }
465            saDirectory.getParentFile().mkdirs();
466            if (!tmpDir.renameTo(saDirectory)) {
467                throw ManagementSupport.failure("deploy", "Failed to rename " + tmpDir + " to " + saDirectory);
468            }
469            // Check all SUs requirements
470            ServiceUnit[] sus = sa.getServiceUnits();
471            if (sus != null) {
472                checkSus(saDirectory, sus);
473            }
474            // Everything seems ok, so deploy all SUs
475            int nbFailures = 0;
476            List<Element> componentResults = new ArrayList<Element>();
477            List<String> suKeys = new ArrayList<String>();
478            if (sus != null) {
479                for (int i = 0; i < sus.length; i++) {
480                    File targetDir = null;
481                    String suName = sus[i].getIdentification().getName();
482                    String artifact = sus[i].getTarget().getArtifactsZip();
483                    String componentName = sus[i].getTarget().getComponentName();
484                    // TODO: skip duplicates
485                    // Unpack SU
486                    try {
487                        File artifactFile = new File(saDirectory, artifact);
488                        targetDir = env.getServiceUnitDirectory(componentName, suName);
489                        if (LOG.isDebugEnabled()) {
490                            LOG.debug("Unpack service unit archive " + artifactFile + " to " + targetDir);
491                        }
492                        FileUtil.unpackArchive(artifactFile, targetDir);
493                    } catch (IOException e) {
494                        nbFailures++;
495                        componentResults.add(ManagementSupport.createComponentFailure(
496                                "deploy", componentName,
497                                "Error unpacking service unit", e));
498                        continue;
499                    }
500                    // Deploy it
501                    boolean success = false;
502                    try {
503                        ComponentMBeanImpl lcc = container.getComponent(componentName);
504                        ServiceUnitManager sum = lcc.getServiceUnitManager();
505                        ClassLoader cl = Thread.currentThread().getContextClassLoader();
506                        try {
507                            Thread.currentThread().setContextClassLoader(lcc.getComponent().getClass().getClassLoader());
508                            String resultMsg = sum.deploy(suName, targetDir.getAbsolutePath());
509                            success = getComponentTaskResult(resultMsg, componentName, componentResults, true);
510                        } finally {
511                            Thread.currentThread().setContextClassLoader(cl);
512                        }
513                        // TODO: need to register the SU somewhere to keep track of its state
514                    } catch (Exception e) {
515                        getComponentTaskError(e, componentName, componentResults);
516                    }
517                    if (success) {
518                        suKeys.add(registry.registerServiceUnit(sus[i], assemblyName, targetDir));
519                    } else {
520                        nbFailures++;
521                    }
522                }
523            }
524            // Note: the jbi spec says that if at least one deployment succeeds, 
525            // this should be a SUCCESS.  However, ServiceMix handles SA in an
526            // atomic way: for a given operation on an SA, all operations on SU
527            // should succeed.  This is clearly a minor violation of the spec.
528            //
529            // Failure
530            if (nbFailures > 0) {
531                // Undeploy SUs
532                for (Iterator<String> iter = suKeys.iterator(); iter.hasNext();) {
533                    try {
534                        String suName = iter.next();
535                        ServiceUnitLifeCycle su = registry.getServiceUnit(suName);
536                        undeployServiceUnit(su);
537                    } catch (Exception e) {
538                        LOG.warn("Error undeploying SU", e);
539                    }
540                }
541                // Delete SA deployment directory 
542                FileUtil.deleteFile(saDirectory);
543                throw ManagementSupport.failure("deploy", componentResults);
544            // Success
545            } else {
546                // Register SA
547                String[] deployedSUs = suKeys.toArray(new String[suKeys.size()]);
548                ServiceAssemblyLifeCycle salc = registry.registerServiceAssembly(sa, deployedSUs, env);
549                salc.writeRunningState();
550                // Build result string
551                if (nbFailures > 0) {
552                    return ManagementSupport.createWarningMessage("deploy", "Failed to deploy some service units", componentResults);
553                } else {
554                    return ManagementSupport.createSuccessMessage("deploy", componentResults);
555                }
556            }
557        }
558    
559        protected void checkSus(File saDirectory, ServiceUnit[] sus) throws Exception {
560            for (int i = 0; i < sus.length; i++) {
561                String suName = sus[i].getIdentification().getName();
562                String artifact = sus[i].getTarget().getArtifactsZip();
563                String componentName = sus[i].getTarget().getComponentName();
564                File artifactFile = new File(saDirectory, artifact);
565                if (!artifactFile.exists()) {
566                    throw ManagementSupport.failure("deploy", "Artifact " + artifact + " not found for service unit " + suName);
567                }
568                ComponentMBeanImpl lcc = container.getComponent(componentName);
569                if (lcc == null) {
570                    throw ManagementSupport.failure("deploy", "Target component " + componentName
571                                                                + " for service unit " + suName + " is not installed");
572                }
573                if (!lcc.isStarted()) {
574                    throw ManagementSupport.failure("deploy", "Target component " + componentName
575                                                                + " for service unit " + suName + " is not started");
576                }
577                if (lcc.getServiceUnitManager() == null) {
578                    throw ManagementSupport.failure("deploy", "Target component " + componentName
579                                                                + " for service unit " + suName + " does not accept deployments");
580                }
581                // TODO: check duplicates here ?
582                if (isDeployedServiceUnit(componentName, suName)) {
583                    throw ManagementSupport.failure("deploy", "Service unit " + suName
584                                                                + " is already deployed on component " + componentName);
585                }
586            }
587        }
588        
589        protected void getComponentTaskError(Exception exception, String component, List<Element> results) {
590            Element result = null;
591            try {
592                Document doc = parse(exception.getMessage());
593                result = getElement(doc, "component-task-result");
594            } catch (Exception e) {
595                result = ManagementSupport.createComponentFailure(
596                        "deploy", component,
597                        "Unable to parse result string", exception);
598            }
599            if (result != null) {
600                results.add(result);
601            }
602        }
603    
604        protected boolean getComponentTaskResult(String resultMsg, String component, List<Element> results, boolean success) {
605            Element result = null;
606            try {
607                Document doc = parse(resultMsg);
608                result = getElement(doc, "component-task-result");
609                Element e = getChildElement(result, "component-task-result-details");
610                e = getChildElement(e, "task-result-details");
611                e = getChildElement(e, "task-result");
612                String r = DOMUtil.getElementText(e);
613                if (!"SUCCESS".equals(r)) {
614                    success = false;
615                }
616            } catch (Exception e) {
617                // The component did not throw an exception upon deployment,
618                // but the result string is not compliant, so issue a warning
619                // and consider this is a successfull deployment
620                try {
621                    if (success) {
622                        result = ManagementSupport.createComponentWarning(
623                                "deploy", component,
624                                "Unable to parse result string", e);
625                    } else {
626                        result = ManagementSupport.createComponentFailure(
627                                "deploy", component,
628                                "Unable to parse result string", e);
629                    }
630                } catch (Exception e2) {
631                    LOG.error(e2);
632                    result = null;
633                }
634            }
635            if (result != null) {
636                results.add(result);
637            }
638            return success;
639        }
640        
641        protected Document parse(String result) throws ParserConfigurationException, SAXException, IOException {
642            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
643            factory.setNamespaceAware(true);
644            factory.setIgnoringElementContentWhitespace(true);
645            factory.setIgnoringComments(true);
646            DocumentBuilder builder = factory.newDocumentBuilder();
647            return builder.parse(new InputSource(new StringReader(result)));
648        }
649        
650        protected Element getElement(Document doc, String name) {
651            NodeList l = doc.getElementsByTagNameNS("http://java.sun.com/xml/ns/jbi/management-message", name);
652            return (Element) l.item(0);
653        }
654        
655        protected Element getChildElement(Element element, String name) {
656            NodeList l = element.getElementsByTagNameNS("http://java.sun.com/xml/ns/jbi/management-message", name);
657            return (Element) l.item(0);
658        }
659    
660        protected void undeployServiceUnit(ServiceUnitLifeCycle su) throws DeploymentException {
661            String name = su.getName();
662            String componentName = su.getComponentName();
663            File targetDir = su.getServiceUnitRootPath();
664            registry.unregisterServiceUnit(su.getKey());
665            // unpack the artifact
666            // now get the component and give it a SA
667            ComponentMBeanImpl component = container.getComponent(componentName);
668            if (component != null) {
669                ServiceUnitManager sum = component.getServiceUnitManager();
670                if (sum != null) {
671                    ClassLoader cl = Thread.currentThread().getContextClassLoader();
672                    try {
673                        Thread.currentThread().setContextClassLoader(component.getComponent().getClass().getClassLoader());
674                        sum.undeploy(name, targetDir.getAbsolutePath());
675                    } finally {
676                        Thread.currentThread().setContextClassLoader(cl);
677                    }
678                    FileUtil.deleteFile(targetDir);
679                }
680            } else {
681                FileUtil.deleteFile(targetDir);
682            }
683            LOG.info("UnDeployed ServiceUnit " + name + " from Component: " + componentName);
684        }
685    
686        /**
687         * Find runnning state and things deployed before shutdown
688         */
689        protected void buildState() {
690            LOG.info("Restoring service assemblies");
691            // walk through deployed SA's
692            File top = environmentContext.getServiceAssembliesDir();
693            if (top == null || !top.exists() || !top.isDirectory()) {
694                return;
695            }
696            File[] files = top.listFiles();
697            if (files == null) {
698                return;
699            }
700            // Initialize all assemblies
701            for (int i = 0; i < files.length; i++) {
702                if (files[i].isDirectory()) {
703                    String assemblyName = files[i].getName();
704                    try {
705                        ServiceAssemblyEnvironment env = environmentContext.getServiceAssemblyEnvironment(assemblyName);
706                        Descriptor root = DescriptorFactory.buildDescriptor(env.getInstallDir());
707                        if (root != null) {
708                            ServiceAssembly sa = root.getServiceAssembly();
709                            if (sa != null && sa.getIdentification() != null) {
710                                registry.registerServiceAssembly(sa, env);
711                            }
712                        }
713                    } catch (Exception e) {
714                        LOG.error("Failed to initialized service assembly: " + assemblyName, e);
715                    }
716                }
717            }
718        }
719    
720    }