org.apache.servicemix.jbi.deployer.utils.ManagementSupport.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.servicemix.jbi.deployer.utils.ManagementSupport.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.servicemix.jbi.deployer.utils;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.List;

import javax.jbi.management.DeploymentException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.servicemix.jbi.runtime.impl.utils.DOMUtil;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * ManagementMessageHelper is a class that ease the parsing and build of management messages.
 */
public final class ManagementSupport {

    public static final String FAILED = "FAILED";
    public static final String ERROR = "ERROR";
    public static final String SUCCESS = "SUCCESS";
    public static final String WARNING = "WARNING";

    public static final String COMPONENT_NAME = "component-name";
    public static final String COMPONENT_TASK_RESULT = "component-task-result";
    public static final String COMPONENT_TASK_RESULT_DETAILS = "component-task-result-details";
    public static final String DEFAULT_VERSION = "1.0";
    public static final String EXCEPTION_INFO = "exception-info";
    public static final String FRMWK_TASK_RESULT = "frmwk-task-result";
    public static final String FRMWK_TASK_RESULT_DETAILS = "frmwk-task-result-details";
    public static final String HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE = "http://java.sun.com/xml/ns/jbi/management-message";
    public static final String JBI_TASK = "jbi-task";
    public static final String JBI_TASK_RESULT = "jbi-task-result";
    public static final String LOC_MESSAGE = "loc-message";
    public static final String LOC_TOKEN = "loc-token";
    public static final String LOCALE = "locale";
    public static final String MESSAGE_TYPE = "message-type";
    public static final String MSG_LOC_INFO = "msg-loc-info";
    public static final String NESTING_LEVEL = "nesting-level";
    public static final String STACK_TRACE = "stack-trace";
    public static final String TASK_ID = "task-id";
    public static final String TASK_RESULT = "task-result";
    public static final String TASK_RESULT_DETAILS = "task-result-details";
    public static final String TASK_STATUS_MSG = "task-status-msg";
    public static final String VERSION = "version";
    public static final String XMLNS = "xmlns";

    private static final String WRAPPER = "wrapper";

    private static final Log LOG = LogFactory.getLog(ManagementSupport.class);

    private ManagementSupport() {
    }

    public static class Message {
        private boolean isCauseFramework;
        private String task;
        private String result;
        private Throwable exception;
        private String type;
        private String message;
        private String component;
        private String locale;

        public Throwable getException() {
            return exception;
        }

        public void setException(Throwable exception) {
            this.exception = exception;
        }

        public boolean isCauseFramework() {
            return isCauseFramework;
        }

        public void setCauseFramework(boolean value) {
            this.isCauseFramework = value;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getResult() {
            return result;
        }

        public void setResult(String result) {
            this.result = result;
        }

        public String getTask() {
            return task;
        }

        public void setTask(String task) {
            this.task = task;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getComponent() {
            return component;
        }

        public void setComponent(String component) {
            this.component = component;
        }

        public String getLocale() {
            return locale;
        }

        public void setLocale(String locale) {
            this.locale = locale;
        }
    }

    public static RuntimeException failure(String task, String info) {
        return failure(task, info, null, null);
    }

    public static RuntimeException failure(String task, List componentResults) {
        return failure(task, null, null, componentResults);
    }

    public static RuntimeException failure(String task, String info, Throwable t) {
        return failure(task, info, t, null);
    }

    public static RuntimeException failure(String task, String info, Throwable t, List<Element> componentResults) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(FAILED);
        msg.setType(ERROR);
        msg.setException(t);
        msg.setMessage(info);
        return new RuntimeException(ManagementSupport.createFrameworkMessage(msg, componentResults));
    }

    public static String createSuccessMessage(String task) {
        return createSuccessMessage(task, null, null);
    }

    public static String createSuccessMessage(String task, List<Element> componentResults) {
        return createSuccessMessage(task, null, componentResults);
    }

    public static String createSuccessMessage(String task, String info) {
        return createSuccessMessage(task, info, null);
    }

    public static String createSuccessMessage(String task, String info, List<Element> componentResults) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(SUCCESS);
        msg.setMessage(info);
        return ManagementSupport.createFrameworkMessage(msg, componentResults);
    }

    public static String createWarningMessage(String task, String info, List<Element> componentResults) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(SUCCESS);
        msg.setType(WARNING);
        msg.setMessage(info);
        return ManagementSupport.createFrameworkMessage(msg, componentResults);
    }

    public static String createFrameworkMessage(Message fmkMsg, List<Element> componentResults) {
        try {
            Document doc = createDocument();
            Element jbiTask = createChild(doc, JBI_TASK);
            jbiTask.setAttribute(XMLNS, HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE);
            jbiTask.setAttribute(VERSION, DEFAULT_VERSION);
            Element jbiTaskResult = createChild(jbiTask, JBI_TASK_RESULT);
            Element frmkTaskResult = createChild(jbiTaskResult, FRMWK_TASK_RESULT);
            Element frmkTaskResultDetails = createChild(frmkTaskResult, FRMWK_TASK_RESULT_DETAILS);
            appendTaskResultDetails(frmkTaskResultDetails, fmkMsg);
            if (fmkMsg.getLocale() != null) {
                createChild(frmkTaskResult, LOCALE, fmkMsg.getLocale());
            }
            if (componentResults != null) {
                for (Element element : componentResults) {
                    jbiTaskResult.appendChild(doc.importNode(element, true));
                }
            }
            return DOMUtil.asIndentedXML(doc);
        } catch (Exception e) {
            LOG.error("Error", e);
            return null;
        }
    }

    private static Document createDocument() {
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.newDocument();
        } catch (Exception e) {
            throw new RuntimeException("Could not create DOM document", e);
        }
    }

    private static Element createChild(Node parent, String name) {
        return createChild(parent, name, null);
    }

    private static Element createChild(Node parent, String name, String text) {
        Document doc = parent instanceof Document ? (Document) parent : parent.getOwnerDocument();
        Element child = doc.createElementNS(HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE, name);
        if (text != null) {
            child.appendChild(doc.createTextNode(text));
        }
        parent.appendChild(child);
        return child;
    }

    private static void appendTaskResultDetails(Element root, Message fmkMsg) {
        Element taskResultDetails = createChild(root, TASK_RESULT_DETAILS);
        createChild(taskResultDetails, TASK_ID, fmkMsg.getTask());
        createChild(taskResultDetails, TASK_RESULT, fmkMsg.getResult());
        if (fmkMsg.getType() != null) {
            createChild(taskResultDetails, MESSAGE_TYPE, fmkMsg.getType());
        }
        // task-status-message
        if (fmkMsg.getMessage() != null) {
            Element taskStatusMessage = createChild(taskResultDetails, TASK_STATUS_MSG);
            Element msgLocInfo = createChild(taskStatusMessage, MSG_LOC_INFO);
            createChild(msgLocInfo, LOC_TOKEN);
            createChild(msgLocInfo, LOC_MESSAGE, fmkMsg.getMessage());
        }
        // exception-info
        if (fmkMsg.getException() != null) {
            Element exceptionInfo = createChild(taskResultDetails, EXCEPTION_INFO);
            createChild(exceptionInfo, NESTING_LEVEL, "1");
            createChild(exceptionInfo, LOC_TOKEN);
            createChild(exceptionInfo, LOC_MESSAGE, fmkMsg.getException().getMessage());
            Element stackTrace = createChild(exceptionInfo, STACK_TRACE);
            StringWriter sw2 = new StringWriter();
            PrintWriter pw = new PrintWriter(sw2);
            fmkMsg.getException().printStackTrace(pw);
            pw.close();
            stackTrace.appendChild(root.getOwnerDocument().createCDATASection(sw2.toString()));
        }
    }

    public static DeploymentException componentFailure(String task, String component, String info) {
        try {
            Element e = createComponentFailure(task, component, info, null);
            return new DeploymentException(DOMUtil.asXML(e));
        } catch (Exception e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Error creating management message", e);
            }
            return new DeploymentException(info);
        }
    }

    public static Element createComponentMessage(Message msg) {
        Document doc = createDocument();
        Element componentTaskResult = createChild(doc, COMPONENT_TASK_RESULT);
        createChild(componentTaskResult, COMPONENT_NAME, msg.getComponent());
        Element componentTaskResultDetails = createChild(componentTaskResult, COMPONENT_TASK_RESULT_DETAILS);
        appendTaskResultDetails(componentTaskResultDetails, msg);
        return componentTaskResult;
    }

    public static Element createComponentSuccess(String task, String component) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(SUCCESS);
        msg.setComponent(component);
        return createComponentMessage(msg);
    }

    public static Element createComponentFailure(String task, String component, String info, Throwable t) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(FAILED);
        msg.setType(ERROR);
        msg.setException(t);
        msg.setMessage(info);
        msg.setComponent(component);
        return createComponentMessage(msg);
    }

    public static Element createComponentWarning(String task, String component, String info, Throwable t) {
        ManagementSupport.Message msg = new ManagementSupport.Message();
        msg.setTask(task);
        msg.setResult(SUCCESS);
        msg.setType(WARNING);
        msg.setException(t);
        msg.setMessage(info);
        msg.setComponent(component);
        return createComponentMessage(msg);
    }

    public static boolean getComponentTaskResult(String resultMsg, String component, List<Element> results) {
        Element result = null;
        boolean success = true;

        try {
            Document doc = parse(wrap(resultMsg));
            Element wrapper = getElement(doc, WRAPPER);
            result = getChildElement(wrapper, COMPONENT_TASK_RESULT);
            Element e = getChildElement(result, COMPONENT_TASK_RESULT_DETAILS);
            e = getChildElement(e, TASK_RESULT_DETAILS);
            e = getChildElement(e, TASK_RESULT);
            String r = DOMUtil.getElementText(e);
            if (!SUCCESS.equals(r)) {
                success = false;
            }
        } catch (Exception e) {
            // The component did not throw an exception upon deployment, but the
            // result string is not compliant: issue a warning and consider this
            // is a successful deployment
            try {
                if (success) {
                    result = ManagementSupport.createComponentWarning("deploy", component,
                            "Unable to parse result string", e);
                } else {
                    result = ManagementSupport.createComponentFailure("deploy", component,
                            "Unable to parse result string", e);
                }
            } catch (Exception e2) {
                LOG.error(e2);
                result = null;
            }
        }
        if (result != null) {
            results.add(result);
        }
        return success;
    }

    /**
     * Wrap the result message string to set the default namespace. The JBI spec
     * is a bit misleading here: the javadoc for ServiceUnitManager.deploy shows
     * a result string that does not declare the namespace for the
     * component-task-result element. That would be invalid, but we'll hack the
     * result string to allow it.
     */
    private static String wrap(String resultMsg) {
        String xmlDecl = "<?xml version=\"1.0\" encoding=\"UTF-8\"/?>";
        int ix = 0;
        if (resultMsg.startsWith("<?xml")) {
            ix = resultMsg.indexOf("?>") + 2;
            xmlDecl = resultMsg.substring(0, ix);
        }
        return xmlDecl + "<" + WRAPPER + " xmlns=\"" + HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE + "\"> "
                + resultMsg.substring(ix) + "</" + WRAPPER + ">";
    }

    private static Document parse(String result) throws ParserConfigurationException, SAXException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setIgnoringElementContentWhitespace(true);
        factory.setIgnoringComments(true);
        DocumentBuilder builder = factory.newDocumentBuilder();
        return builder.parse(new InputSource(new StringReader(result)));
    }

    private static Element getElement(Document doc, String name) {
        NodeList l = doc.getElementsByTagNameNS(HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE, name);
        return (Element) l.item(0);
    }

    private static Element getChildElement(Element element, String name) {
        NodeList l = element.getElementsByTagNameNS(HTTP_JAVA_SUN_COM_XML_NS_JBI_MANAGEMENT_MESSAGE, name);
        return (Element) l.item(0);
    }

}