/*
 * 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.ode.jbi;

import java.util.HashMap;
import java.util.Map;

import javax.jbi.component.ServiceUnitManager;
import javax.jbi.management.DeploymentException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.XMLParserUtils;

public class OdeSUManager implements ServiceUnitManager {
  private static final Logger __log = LoggerFactory.getLogger(OdeSUManager.class);

  private static final Messages __msgs = Messages.getMessages(Messages.class);

  private static final String XMLNS_JBI_MGMT = "http://java.sun.com/xml/ns/jbi/management-message";

  private OdeContext _ode;

  /** All the service units that have been "init"ed. */
  private Map<String, OdeServiceUnit> _serviceUnits = new HashMap<String, OdeServiceUnit>();

  public OdeSUManager(OdeContext odeContext) {
    _ode = odeContext;
  }

    public synchronized String deploy(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException {
        __log.trace("deploy: id=" + serviceUnitID + ", path=" + serviceUnitRootPath);

        OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath);
    try {
      su.deploy();
    } catch (Exception ex) {
      __log.error(__msgs.msgServiceUnitDeployFailed(serviceUnitID));
      return makeStatusMessage("deploy", "FAILED");
    }

    return makeStatusMessage("deploy", "SUCCESS");

  }

    public synchronized void init(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException {
    __log.trace("init called for " + serviceUnitID);

    if (_serviceUnits.containsKey(serviceUnitID)) {
            __log.debug("odd, init() called for su " + serviceUnitID + ", but it is already init()ed");
      return;
    }

    try {
            OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath);
      su.init();
      _serviceUnits.put(serviceUnitID, su);
    } catch (Exception ex) {
      String errmsg = __msgs.msgServiceUnitInitFailed(serviceUnitID);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    }
  }

    public synchronized void shutDown(String serviceUnitID) throws DeploymentException {
    __log.trace("shutDown called for " + serviceUnitID);

    OdeServiceUnit su = _serviceUnits.remove(serviceUnitID);
    if (su == null)
      return;

    try {
      su.shutdown();
    } catch (Exception ex) {
      String errmsg = __msgs.msgServiceUnitShutdownFailed(serviceUnitID);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    }
  }

    public synchronized void start(String serviceUnitID) throws DeploymentException {
    __log.trace("start called for " + serviceUnitID);

    OdeServiceUnit su = _serviceUnits.get(serviceUnitID);
    if (su == null) {
      // Should not really happen if JBI is working.
      String errmsg = "Unexpected state; start() called before init()";
      IllegalStateException ex = new IllegalStateException(errmsg);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    }
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    try {
        Thread.currentThread().setContextClassLoader(su.getConfigurationClassLoader());
        su.start();
    } catch (Exception ex) {
      String errmsg = __msgs.msgServiceUnitStartFailed(serviceUnitID);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    } finally {
        Thread.currentThread().setContextClassLoader(cl);
    }

  }

  /**
   * Stop the deployment. This causes the component to cease generating service
   * requests related to the deployment. This returns the deployment to a state
   * equivalent to after init() was called
   *
   * @param serviceUnitID
   *          service unit ID
   *
   * @throws DeploymentException
   *           deployment exception
   */
    public synchronized void stop(String serviceUnitID) throws DeploymentException {
    __log.trace("stop called for " + serviceUnitID);

    OdeServiceUnit su = _serviceUnits.get(serviceUnitID);
    if (su == null) {
      // Should not really happen if JBI is working.
      String errmsg = "Unexpected state; stop() called before init()";
      IllegalStateException ex = new IllegalStateException(errmsg);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    }

    try {
      su.stop();
    } catch (Exception ex) {
      String errmsg = __msgs.msgServiceUnitStopFailed(serviceUnitID);
      __log.error(errmsg, ex);
      throw new DeploymentException(errmsg, ex);
    }

  }

  /**
   * Cancel a Service Deployment. If the deployment is in use (has
   * dependencies), then will operation may fail.
   *
   * @param serviceUnitID -
   *          ID of the Service Unit being undeployed
   * @param serviceUnitRootPath -
   *          Full path to the Service Unit root.
   *
   * @return NOT YET DOCUMENTED
   *
   * @throws DeploymentException
   *           deployment exception
   */
    public synchronized String undeploy(String serviceUnitID, String serviceUnitRootPath) throws DeploymentException {
        __log.trace("undeploy: id=" + serviceUnitID + ", path=" + serviceUnitRootPath);

        OdeServiceUnit su = new OdeServiceUnit(_ode, serviceUnitID, serviceUnitRootPath);

    try {
      su.undeploy();
    } catch (Exception ex) {
      __log.error(__msgs.msgServiceUnitDeployFailed(serviceUnitID));
      return makeStatusMessage("undeploy", "FAILED");
    }

    return makeStatusMessage("undeploy", "SUCCESS");

  }

  /**
   * Generate those lame XML result strings that JBI requires. Oh did I mention
   * how lame this is? If not, let me remind the reader: this is just about the
   * lamest "clever idea" I have ever seen.
   *
   * @param task
   *          the task that failed and must now generate a lame result string
   * @param status
   *          the status code that will go into the lame result string.
   * @return a lame JBI result string
   */
  private String makeStatusMessage(String task, String status) {

    /*
     * Cheat sheet: <component-task-result> <component-name>BC1</component-name>
     * <component-task-result-details
     * xmlns="http://java.sun.com/xml/ns/jbi/management- <task-result-details>
     * <task-id>deploy</task-id> <task-result>SUCCESS</task-result>
     * </task-result-details> </component-task-result-details>
     * </component-task-result>
     *
     */

    // First of all, what is the logic why XML ? and if XML, why a String
    // and not a DOM ? But the 64k question is what is wrong with Exceptions?
    Document doc;
    try {
        // Note that we are using our own choice of factory (xerces), not the
        // one that is provided by the system. This is important, otherwise the
        // serialization routine won't work.
      DocumentBuilderFactory dbf = XMLParserUtils.getDocumentBuilderFactory();
      DocumentBuilder db = dbf.newDocumentBuilder();
      doc = db.newDocument();
    } catch (Exception ex) {
      throw new RuntimeException(ex);
    }

    Element elem = doc.createElementNS(XMLNS_JBI_MGMT, "component-task-result");
    doc.appendChild(elem);
    Element compNameElem = doc.createElementNS(XMLNS_JBI_MGMT, "component-name");
    elem.appendChild(compNameElem);
    Element compTaskRsltDtlsElem = doc.createElementNS(XMLNS_JBI_MGMT, "component-task-result-details");
    elem.appendChild(compTaskRsltDtlsElem);
    Element taskRsltDtlsElem = doc.createElementNS(XMLNS_JBI_MGMT, "task-result-details");
    compTaskRsltDtlsElem.appendChild(taskRsltDtlsElem);

    Element taskId = doc.createElementNS(XMLNS_JBI_MGMT, "task-id");
    taskRsltDtlsElem.appendChild(taskId);

    Element taskResult = doc.createElementNS(XMLNS_JBI_MGMT, "task-result");
    taskRsltDtlsElem.appendChild(taskResult);

    // Why do I have to tell this thing the component name? It /knows/ the
    // component name....
    compNameElem.appendChild(doc.createTextNode(_ode.getContext().getComponentName()));

    // And why on earth do I have to tell my caller the method he just
    // called?
    taskId.appendChild(doc.createTextNode(task));

    taskResult.appendChild(doc.createTextNode(status));
    return DOMUtils.domToString(elem);
  }
}
