Package org.openeai.afa

Source Code of org.openeai.afa.ScheduledCommandImpl

/*******************************************************************************
$Source: /cvs/repositories/openii3/project/java/source/org/openeai/afa/ScheduledCommandImpl.java,v $
$Revision: 1.19 $
*******************************************************************************/

/**********************************************************************
This file is part of the OpenEAI Application Foundation or
OpenEAI Message Object API created by Tod Jackson
(tod@openeai.org) and Steve Wheat (steve@openeai.org) at
the University of Illinois Urbana-Champaign.

Copyright (C) 2002 The OpenEAI Software Foundation

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

For specific licensing details and examples of how this software
can be used to build commercial integration software or to implement
integrations for your enterprise, visit http://www.OpenEai.org/licensing.
*/

package org.openeai.afa;

import org.openeai.*;
import org.openeai.xml.*;

import org.openeai.moa.objects.resources.*;
import org.openeai.moa.*;

import org.openeai.config.*;
import org.openeai.jms.producer.PubSubProducer;
import org.openeai.jms.producer.MessageProducer;

import javax.jms.JMSException;
import javax.jms.TextMessage;
import java.util.*;
import java.io.*;

import org.jdom.output.XMLOutputter;
import org.jdom.Document;
import org.jdom.Element;
import org.apache.log4j.*;
import org.openeai.transport.ProducerId;
//import org.openeai.transport.SyncService;

/**
* This is the parent class of all ScheduledCommands.  These commands are Java
* components that are used to execute specific business logic associated to a
* given Schedule.  It provides convenience methods for its decendants.
* <P>
* @author      Tod Jackson (tod@openeai.org)
* @author      Steve Wheat (steve@openeai.org)
* @version     3.0  - 28 January 2003
* @see Schedule Schedule
* @see ScheduledCommand
*/
public class ScheduledCommandImpl extends OpenEaiObject {

  public static Category logger;
  private HashMap m_msgComponents = new HashMap();
  private Vector m_appConfigs = new Vector();
  private AppConfig m_appConfig = null;
  private PubSubProducer m_syncErrorPublisher = null;
  private boolean m_inboundXmlValidation = false;
  private boolean m_outboundXmlValidation = false;
  private String m_syncErrorSyncPrimedDocumentUri = "";

  /**
   * Constructor
   */
  public ScheduledCommandImpl(CommandConfig cConfig) throws InstantiationException {
    setAppName(cConfig.getAppName());
    setAppConfig(cConfig.getAppConfig());
    setInboundXmlValidation(cConfig.getInboundXmlValidation());
    setOutboundXmlValidation(cConfig.getOutboundXmlValidation());

    try {
      LoggerConfig lConfig = new LoggerConfig();
      lConfig = (LoggerConfig)getAppConfig().getObjectByType(lConfig.getClass().getName());
      logger = Category.getInstance(getClass().getName().substring(0, getClass().getName().lastIndexOf('.')));
      PropertyConfigurator.configure(lConfig.getProperties());
    }
    catch (Exception e) {
      logger = org.openeai.OpenEaiObject.logger;
    }

    try {
      PropertyConfig pConfig = null;
      String uri = null;
      try {
        pConfig = (PropertyConfig)getAppConfig().getObject("SyncErrorSyncProperties");
      }
      catch (Exception e) {
        // ignoring this error and letting it fall through...
      }
      if (pConfig == null) {
        logger.warn("Missing 'SyncErrorSyncProperties' PropertyConfig element in configuration document.  Processing will continue.");
      }
      else {
        uri = pConfig.getProperties().getProperty("SyncErrorSyncPrimedDocumentUri",null);
      }
      if (uri == null) {
        logger.warn("Missing 'SyncErrorSyncPrimedDocumentUri' property in 'SyncErrorSyncProperties' PropertyConfig element.  Processing will continue.");
      }
      setSyncErrorSyncPrimedDocumentUri(uri);
    }
    catch (Exception e) {
      logger.fatal("[ScheduledCommandImpl] Exception occurred obtaining 'SyncErrorSyncPrimedDocumentUri' property.  Can't continue.");
      logger.fatal(e.getMessage(), e);
      throw new InstantiationException(e.getMessage());
    }

    // sync error publisher (if one exists)...
    try {
      PubSubProducer syncErrorPublisher = (PubSubProducer)getAppConfig().getObject("SyncErrorPublisher");
      if (syncErrorPublisher == null) {
        logger.warn("[ScheduledCommandImpl] no 'SyncErrorPublisher' in Config document.  Processing will continue.");
        return;
      }
      setSyncErrorPublisher(syncErrorPublisher);
      if (getSyncErrorPublisher().isStarted() == false) {
        try {
          if (getSyncErrorPublisher().startPublisher() == false) {
             String errorMessage = "[ScheduledCommandImpl] Could not start SyncErrorPublisher!";
            logger.fatal(errorMessage);
            throw new InstantiationException(errorMessage);
           }
        }
        catch (JMSException e) {
          String errorMessage = "[ScheduledCommandImpl] Exception starting SyncErrorPublisher!  Exception: " + e.getMessage();
          logger.fatal(errorMessage, e);
           throw new InstantiationException(errorMessage);
        }
      }
    }
    catch (Exception e) {
      String errorMessage = "[ScheduledCommandImpl] Could not find SyncErrorPublisher in AppConfig!  Exception: " + e.getMessage() + "  Processing will continue.";
      logger.warn(errorMessage);
    }
  }

/**
  *  Set inbound xml validation.  This is used to determine whether or not to
  *  validate xml.  Since Scheduled commands do not consume messages like
  * ConsumerCommands, this attribute can be used for general decision making
  * when considering whether or not to validate XML Documents that may exist as 
  * part of the Scheduled Command's execution.
  *  @param validate boolean
  */
  protected void setInboundXmlValidation(boolean validate) {
    m_inboundXmlValidation = validate;
  }
/**
  *  Get inbound xml validation.
  * @return  boolean
  */
  protected boolean getInboundXmlValidation() {
    return m_inboundXmlValidation;
  }

/**
  *  Set outbound xml validation.  This is used to determine whether or not to
  *  validate xml.  Since Scheduled commands do not return messages like
  * ConsumerCommands, this attribute can be used for general decision making
  * when considering whether or not to validate XML Documents that may exist as 
  * part of the Scheduled Command's execution.
  *  @param validate
  */
  protected void setOutboundXmlValidation(boolean validate) {
    m_outboundXmlValidation = validate;
  }
/**
  *  Get outbound xml validation.
  * @return  boolean
  */
  protected boolean getOutboundXmlValidation() {
    return m_outboundXmlValidation;
  }

  /**
  *  Set SyncErrorPublisher associated to this command.  This may be used by the
  *  Scheduled Command to notify enterprise services of errors that occur during
  * the execution of an unattended scheduled command.  It is not required.
  *  @param pubSub
  */
  private void setSyncErrorPublisher(PubSubProducer pubSub) {
    m_syncErrorPublisher = pubSub;
  }
/**
  *  Get SyncErrorPublisher associated to this command.  It is called by commands
  *  when they need to publish a sync error via the publishSyncError method also
  *  defined in ScheduledCommandImpl.
  *  @return  PubSubProducer
  */
  public final PubSubProducer getSyncErrorPublisher() {
    return m_syncErrorPublisher;
  }

/**
  *  Set AppConfig associated to this command.  It is called in the
  *  constructor of ScheculedCommandImpl.
  *  @param aConfig
  */
  protected void setAppConfig(AppConfig aConfig) {
    m_appConfig = aConfig;
  }
/**
  *  Get AppConfig associated to this command.  It is called by commands.
  *  @return  AppConfig
  */
  public final AppConfig getAppConfig() {
    return m_appConfig;
  }


/**
  * Returns the SyncErrorSync primed document that will be used if this ScheduledCommand
  * needs to publish a Sync-Error-Sync messages if errors occur during the execution of
  * the command.
  * @return String the document URI to the primed Sync-Error-Sync document
  */
  protected String getSyncErrorSyncPrimedDocumentUri() {
    return m_syncErrorSyncPrimedDocumentUri;
  }
/**
  * Sets the SyncErrorSync primed document that will be used if this ScheduledCommand
  * needs to publish a Sync-Error-Sync messages if errors occur during the execution of
  * the command.
  * @param uri String the document URI to the primed Sync-Error-Sync document
  */
  protected void setSyncErrorSyncPrimedDocumentUri(String uri) {
    m_syncErrorSyncPrimedDocumentUri = uri;
  }

/**
  *  This method is used to publish a Sync-Error-Sync message when/if the ScheduledCommand has
  *  any errors during processing (during the 'execute' method).
  *<P>
  @param action String the action being performed.  If a 'null' action is passed in, 'Unknown' is used.  This
  *  will cause the Sync-Error-Sync document being published to be invalid because the list of actions
  *  is constrained in SctSegments.
  *<P>
  @param errors java.util.List an ArrayList of org.openeai.moa.objects.Error objects that have
  *  been built with the appropriate error number, error type and error descriptions.
  *<P>
  @param e Throwable an exception that has occurred in the ScheduledCommand.  This exception will be added
  *  to the list of errors passed in.
  */
  protected void publishSyncError(String action, java.util.List errors, Throwable e) {
    org.openeai.moa.objects.resources.Error anError =
      new org.openeai.moa.objects.resources.Error();

    ByteArrayOutputStream bw = new ByteArrayOutputStream();
    PrintWriter pw = new PrintWriter(bw, true);
    e.printStackTrace(pw);
    String errMessage = "Exception: " + e.getMessage() + "\n" + bw.toString();

    anError.setType("system");
    anError.setErrorNumber("SCHEDULEDCOMMAND-1001");
    anError.setErrorDescription(errMessage);

    errors.add(anError);
    publishSyncError(action, errors);
  }
 
/**
  *  This method is used to publish a Sync-Error-Sync message when/if the ScheduledCommand has
  *  any errors during processing (during the 'execute' method).
  *<P>
  @param action String the action being performed.  If a 'null' action is passed in, 'Unknown' is used.  This
  *  will cause the Sync-Error-Sync document being published to be invalid because the list of actions
  *  is constrained in SctSegments.
  *<P>
  @param java.util.List a List of org.openeai.moa.objects.Error objects that have
  *  been built with the appropriate error number, error type and error descriptions.
  */
  protected void publishSyncError(String action, java.util.List errors) {

    XmlDocumentReader xmlReader = new XmlDocumentReader();
    Document syncErrorDoc = null;
    try {
      syncErrorDoc =
        xmlReader.initializeDocument(getSyncErrorSyncPrimedDocumentUri(), getOutboundXmlValidation());
      if (syncErrorDoc == null) {
        String errMessage = "[PublishSyncError] Missing 'SyncErrorSyncPrimedDocumentUri' property in configuration document.  Can't publish sync error.";
        logger.fatal(errMessage);
        return;
      }
    }
    catch (XmlDocumentReaderException e) {
      logger.fatal("[PublishSyncError] Error initializing Sync-Error-Sync primed document, could not publish the sync error sync message.");
      logger.fatal(e.getMessage(), e);
      return;
    }

    Element eControlArea = getControlArea(syncErrorDoc.getRootElement());

    Result aResult = new Result();
    ProcessedMessageId processedMsgId = new ProcessedMessageId();

    // Build the dynamic portion of the sync document's control area
    // Our sender information will go in the "Sender" element of the primed
    // document and in the ProcessedMessageId of the Result that gets built
    // Set the sender element

    // Build the ProcessedMessageId Object out of the contents of the
    // application that had the error.
    String messageSequence = Integer.toString(getSyncErrorPublisher().incrementMessageSequence());
    try {
      // processedMsgId is going to be the same as MessageId (built below)
      processedMsgId.setProducerId(getSyncErrorPublisher().getProducerId(null).getId());
      processedMsgId.setSenderAppId(getAppName());
      processedMsgId.setMessageSeq(messageSequence);
    }
    catch (Exception e) {
      logger.fatal("Error building ProcessedMessageId Element in Sync-Error-Sync message!");
      logger.fatal(e.getMessage(), e);
    }

    // This is the control area information relevant to this Gateway
    eControlArea.removeChild("Result");
    eControlArea.removeChild("Datetime");
    eControlArea.removeChild("Sender");

    Sender sender = new Sender();
    MessageId msgId = new MessageId();
    msgId.setProducerId(getSyncErrorPublisher().getProducerId(null).getId());
    msgId.setSenderAppId(getAppName());
    msgId.setMessageSeq(messageSequence);

    sender.setMessageId(msgId);
    Authentication auth = new Authentication();
    auth.setAuthUserId(getAppName());
    sender.setAuthentication(auth);
    Element eSender = null;
    try {
      eSender = (Element)sender.buildOutputFromObject();
    }
    catch (Exception e) {
      logger.fatal("[publishSyncError1] Exception occurred building an Element from the Sender object.  Can't publish Sync error.  Exception: " + e.getMessage());
      logger.fatal(e.getMessage(), e);
      return;
    }

    // Set the datetime element
    Datetime dt = new Datetime();
    Element eDatetime = null;
    try {
      eDatetime = (Element)dt.buildOutputFromObject();
    }
    catch (Exception e) {
      logger.fatal("[publishSyncError1] Exception occurred building an Element from the Datetime object.  Can't publish Sync error.  Exception: " + e.getMessage());
      logger.fatal(e.getMessage(), e);
      return;
    }

    eControlArea.addContent(eSender);
    eControlArea.addContent(eDatetime);

    if (action == null) {
      action = "Unknown";
    }
    aResult.setAction(action);
    aResult.setStatus("failure");
    aResult.setProcessedMessageId(processedMsgId);

    for (int i=0; i<errors.size(); i++) {
      org.openeai.moa.objects.resources.Error anError =
        (org.openeai.moa.objects.resources.Error)errors.get(i);
      aResult.addError(anError);
    }

    try {
      Element eResult = (Element)aResult.buildOutputFromObject();
      eControlArea.addContent(eResult);
      syncErrorDoc.getRootElement().removeContent(eControlArea);
      syncErrorDoc.getRootElement().addContent(eControlArea);
      TextMessage syncErrorMessage = getSyncErrorPublisher().createTextMessage();
      XMLOutputter xmlOut = new XMLOutputter();
      syncErrorMessage.setText(xmlOut.outputString(syncErrorDoc));
      if (getSyncErrorPublisher().getDefaultCommandName().length() == 0 ||
        getSyncErrorPublisher().getDefaultCommandName() == null) {
        getSyncErrorPublisher().setDefaultCommandName("EnterpriseSyncErrorSync");
      }
      syncErrorMessage.setStringProperty(MessageProducer.MESSAGE_ID,msgId.toString());
      syncErrorMessage.setStringProperty(MessageProducer.COMMAND_NAME,getSyncErrorPublisher().getDefaultCommandName());
        //TODO: change this...
//      getSyncErrorPublisher().publishMessage(syncErrorMessage);
    }
    catch (Exception e) {
      logger.fatal("Error publishing Sync-Error-Sync message!");
      logger.fatal(e.getMessage(), e);
    }
  }

  /**
   * Builds a single Error object that can be added to the ArrayList of errors (or for any other reason)
   * to pass to the publishSyncError method.
   *
   * @param errType String error Type  ('application' or 'system')
   * @param errNumber String error Number
   * @param errDescription String error Description
   *
   * @return          org.openeai.moa.objects.Error the error object that gets built.
   */
  protected org.openeai.moa.objects.resources.Error buildError(String errType, String errNumber, String errDescription) {
    org.openeai.moa.objects.resources.Error anError =
      new org.openeai.moa.objects.resources.Error();
    anError.setType(errType);
    anError.setErrorNumber(errNumber);
    anError.setErrorDescription(errDescription);
    return anError;
  }

  /**
   * This method looks at the document and returns the appropriate ControlArea.
   * Since there can be three different control areas based on the message
   * (ControlAreaRequest, ControlAreaReply and ControlAreaSync) we need to have
   * some intelligence built in when retrieving the element from the document.
   * Clients should never need to call this method directly.
   *
   * @param root  org.jdom.Element the root element of the document
   *
   * @return          Element the ControlArea element (may be ControlAreaRequest,
   *                  ControlAreaReply or ControlAreaSync depending on the doc)
   */
  protected Element getControlArea(Element root) {
    java.util.List cList = root.getChildren();
    Element retElem = null;
    for (int i=0; i<cList.size(); i++) {
      Element current = (Element)cList.get(i);
      if (current.getName().indexOf("ControlArea") != -1) {
        retElem = current;
      }
    }
    return retElem;
  }
 
  protected void addAppConfig(AppConfig aConfig) {
    m_appConfigs.add(aConfig);
  }
  protected Vector getAppConfigs() {
    return m_appConfigs;
  }

/**
  *  Sets the HashMap that is a list of Messaging Components (gateways) that this command
  *  needs to know about.  This is specifically used by gateways like Routers and Proxies
  *  which need to forward sync or request messages to an end point.  This is a list
  *  of AppConfig objects that correspond to that end point and contains message object,
  *  producers etc. that are needed to route/forward a message to that end point.
  *<P>
  * @param components HashMap a HashMap containing AppConfigs for end points of intrest to this command.
  *<P>
  * @return  void
  */
  public final void setMsgComponents(HashMap components) {
    m_msgComponents = components;
  }
/**
  *  Returns the HashMap that is a list of Messaging Components (gateways) that this command
  *  needs to know about.  This is specifically used by gateways like Routers and Proxies
  *  which need to forward sync or request messages to an end point.  This is a list
  *  of AppConfig objects that correspond to that end point and contains message object,
  *  producers etc. that are needed to route/forward a message to that end point.
  *<P>
  * @return  HashMap a HashMap containing AppConfigs for end points of intrest to this command.
  */
  public final HashMap getMsgComponents() {
    return m_msgComponents;
  }

  /**
  *
  **/
  public void shutdown() throws ScheduledCommandException {
    try {
      logger.info(getAppConfig().getName() + " shutting myself down.");
      getAppConfig().shutdown();
      for (int i=0; i<getAppConfigs().size(); i++) {
        AppConfig a = (AppConfig)getAppConfigs().get(i);
        logger.info(a.getName() + " shutting myself down.");
        a.shutdown();
      }
    }
    catch (Exception e) {
      throw new ScheduledCommandException(e.getMessage(), e);
    }
  }
}
TOP

Related Classes of org.openeai.afa.ScheduledCommandImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.