Example #1
0
void AOSOutputExecutor::execute(AOSContext& context)
{
  AString command;
  if (
    context.useRequestParameterPairs().exists(OVERRIDE_OUTPUT)
    && m_Services.useConfiguration().isOutputOverrideAllowed()
  )
  {
    //a_Override requested and allowed
    context.useRequestParameterPairs().get(OVERRIDE_OUTPUT, command);
  }
  else
  {
    command = context.getOutputCommand();
    if (context.useEventVisitor().isLogging(AEventVisitor::EL_DEBUG))
    {
      ARope rope("Default output generator overridden to: ",40);
      rope.append(command);
      context.useEventVisitor().startEvent(rope, AEventVisitor::EL_DEBUG);
    }
  }

  if (command.equals("NOP"))
  {
    //a_If NOP was used force XML
    m_Services.useConfiguration().setMimeTypeFromExt(ASW("xml",3), context);
    if (context.useEventVisitor().isLogging(AEventVisitor::EL_DEBUG))
      context.useEventVisitor().startEvent(ASWNL("NOP detected, defaulting to XML output"), AEventVisitor::EL_DEBUG);
  }

  if (command.isEmpty())
  {
    if (!m_Services.useConfiguration().getAosDefaultOutputGenerator().isEmpty())
    {
      command.assign(m_Services.useConfiguration().getAosDefaultOutputGenerator());
      if (context.useEventVisitor().isLogging(AEventVisitor::EL_DEBUG))
      {
        ARope rope("No output generator specified, defaulting to: ",46);
        rope.append(command);
        context.useEventVisitor().startEvent(rope, AEventVisitor::EL_DEBUG);
      }
    }
    else
    {
      if (context.useEventVisitor().isLogging(AEventVisitor::EL_DEBUG))
        context.useEventVisitor().startEvent(ASW("No output generator, defaulting to XML",38), AEventVisitor::EL_DEBUG);
      return;
    }
  }

  try
  {
    //a_Find input command, if not found execute the default
    OutputGeneratorContainer::iterator it = m_OutputGenerators.find(command);
    if (it == m_OutputGenerators.end())
    {
      if (context.useEventVisitor().isLogging(AEventVisitor::EL_WARN))
      {
        ARope rope("Skipping unknown output generator: ",35);
        rope.append(command);
        context.useEventVisitor().startEvent(rope, AEventVisitor::EL_WARN);
      }
    }
    else
    {
      ATimer timer(true);

      //a_Generate output
      if (context.useEventVisitor().isLogging(AEventVisitor::EL_INFO))
      {
        ARope rope("Generating output: ",19);
        rope.append((*it).first);
        context.useEventVisitor().startEvent(rope, AEventVisitor::EL_INFO);
      }

      if (context.useContextFlags().isClear(AOSContext::CTXFLAG_IS_AJAX))
      {
        context.useModel().overwriteElement(ASW("execute/output", 14)).addData(command);

        //a_Publish timers
        context.getRequestTimer().emitXml(context.useModel().overwriteElement(ASW("request_time",12)));
        context.getContextTimer().emitXml(context.useModel().overwriteElement(ASW("context_time",12)));
      }

      //a_Generate output
      AOSContext::ReturnCode ret = (*it).second->execute(context);
      switch (ret)
      {
        case AOSContext::RETURN_OK:
        break;

        case AOSContext::RETURN_REDIRECT:
          if (context.useEventVisitor().isLogging(AEventVisitor::EL_INFO))
          {
            context.useEventVisitor().startEvent(ASWNL("Output generator has done a redirect"), AEventVisitor::EL_DEBUG);
          }
        break;
      
        default:
          context.addError((*it).second->getClass(), ASWNL("Output generator returned neither OK nor REDIRECT"));
        return;
      }

      //a_Event over
      context.useEventVisitor().endEvent();

      //a_Add execution time
      (*it).second->addExecutionTimeSample(timer.getInterval());
    }
  }
  catch(AException& ex)
  {
    AString strWhere("AOSOutputExecutor::execute(", 27);
    strWhere.append(command);
    strWhere.append(')');
    context.addError(strWhere, ex.what());

    AXmlElement& element = context.useModel().addElement("output_error");
    element.addElement("where", strWhere);
    element.addElement("exception", ex);
  }
  catch(...)
  {
    AString strWhere("AOSOutputExecutor::execute(", 27);
    strWhere.append(command);
    strWhere.append(')');
    context.addError(strWhere, ASWNL("Unknown Exception"));

    context.useModel().addElement("output_error").addData("Unknown Exception");
  }
}
Example #2
0
u4 AOSContextQueue_ErrorExecutor::_threadproc(AThread& thread)
{
  AOSContextQueue_ErrorExecutor *pThis = dynamic_cast<AOSContextQueue_ErrorExecutor *>(thread.getThis());
  AASSERT(&thread, pThis);
  AOSContext *pContext = NULL;

  thread.setRunning(true);
  while(thread.isRun())
  {
    try
    {
      while (pContext = pThis->_nextContext()) 
      {
#ifndef NDEBUG
        if (!ADebugDumpable::isPointerValid(pContext))
        {
          AString error("AOSContext pointer is invalid: ");
          error.append(AString::fromPointer(pContext));
          AASSERT_EX(NULL, false, error);
          continue;
        }
#endif
        pContext->useEventVisitor().startEvent(ASW("AOSContextQueue_ErrorExecutor: Processing error condition", 57));

        //a_Should only be here if an error occured, if status not set >200, then assume 500
        if (pContext->useResponseHeader().getStatusCode() == AHTTPResponseHeader::SC_200_Ok)
          pContext->useResponseHeader().setStatusCode(AHTTPResponseHeader::SC_500_Internal_Server_Error);

        //a_Check is socket was closed, if so do nothing else, we are done
        if (pContext->useConnectionFlags().isSet(AOSContext::CONFLAG_IS_SOCKET_ERROR))
        {
          //a_Proceed
          m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
          continue;
        }

        if (
             pContext->useContextFlags().isSet(AOSContext::CTXFLAG_IS_RESPONSE_HEADER_SENT)
          || pContext->useContextFlags().isSet(AOSContext::CTXFLAG_IS_OUTPUT_SENT)
        )
        {
          //a_Log to file, output is done already
          m_Services.useLog().add(pContext->useEventVisitor(), ALog::EVENT_FAILURE);
        }
        else
        {          

          //a_Add XSLT stylesheet for the error XML
          //if (m_Services.useConfiguration().exists(ASW("/config/server/error-stylesheet",31)))
          //{
          //  AString errorStylesheet;
          //  m_Services.useConfiguration().emitString(ASW("/config/server/error-stylesheet",31), errorStylesheet);
          //  pContext->useModelXmlDocument().addInstruction(AXmlInstruction::XML_STYLESHEET)
          //    .addAttribute(ASW("type",4), ASW("text/xsl",8))
          //    .addAttribute(ASW("href",4), errorStylesheet);
          //}

          //a_Add request header to result XML
          if (!pContext->useModel().exists(ASW("REQUEST",7)))
            pContext->useRequestHeader().emitXml(pContext->useModel().overwriteElement(ASW("REQUEST",7)));
          pContext->useResponseHeader().emitXml(pContext->useModel().overwriteElement(ASW("RESPONSE",8)));

          //a_Check if dumpContext is specified to override and emit XML
          int dumpContextLevel = pContext->getDumpContextLevel();
          pContext->dumpContext(dumpContextLevel);
          if (dumpContextLevel > 0)
          {
            //a_Write contents of the output XML instead of output buffer
            m_Services.useConfiguration().setMimeTypeFromExt(ASW("xml",3), *pContext);
            pContext->useResponseHeader().setStatusCode(AHTTPResponseHeader::SC_200_Ok);
            pContext->writeOutputBuffer(true);
          }
          else
          {
            //a_Set the current content type as text/html
            pContext->useResponseHeader().set(AHTTPHeader::HT_ENT_Content_Type, ASW("text/html; charset=utf-8",24));

            int statusCode = pContext->useResponseHeader().getStatusCode();
            
            AAutoPtr<ATemplate> pTemplate(NULL, false);  //a_Call to cache manager will set a template
            pContext->clearOutputBuffer();
            if (m_Services.useCacheManager().getStatusTemplate(statusCode, pTemplate))
            {
              //a_Template for this status code is found, so process and emit into output buffer
              pTemplate->process(pContext->useLuaTemplateContext(), pContext->useOutputBuffer());
              if (pContext->useEventVisitor().isLogging(AEventVisitor::EL_DEBUG))
              {
                ARope rope("Using error template for status ");
                rope.append(AString::fromInt(statusCode));
                pContext->useEventVisitor().startEvent(rope, AEventVisitor::EL_DEBUG);
              }
            }
            else
            {
              if (pContext->useEventVisitor().isLogging(AEventVisitor::EL_WARN))
              {
                ARope rope("Did not find error template for status ");
                rope.append(AString::fromInt(statusCode));
                pContext->useEventVisitor().startEvent(rope, AEventVisitor::EL_WARN);
              }
            }

            if (pContext->isOutputBufferEmpty())
            {
              AString strError(1024, 256);
              strError.assign("Error ",6);
              strError.append(AString::fromInt(pContext->useResponseHeader().getStatusCode()));
              strError.append(": ", 2);
              strError.append(pContext->useResponseHeader().getStatusCodeReasonPhrase(pContext->useResponseHeader().getStatusCode()));

              //a_Put some generic stuff since there is no error template
              pContext->useOutputBuffer().append("<html><head><title>",19);
              pContext->useOutputBuffer().append(strError);
              pContext->useOutputBuffer().append("</title></head>",15);
              pContext->useOutputBuffer().append("<body>",6);
              pContext->useOutputBuffer().append(strError);
              pContext->useOutputBuffer().append("</body></html>",14);
            }

            try
            {
              pContext->writeOutputBuffer();
            }
            catch(ASocketException& ex)
            {
              pContext->useEventVisitor().addEvent(ex, AEventVisitor::EL_ERROR);
              pContext->useConnectionFlags().setBit(AOSContext::CONFLAG_IS_SOCKET_ERROR);
              m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
              continue;
            }
          }
        }

        //a_Close connection
        pContext->useSocket().close();

        //a_Proceed
        m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
        continue;
      }
      AThread::sleep(pThis->m_SleepDelay);  //a_Empty queue, avoid thrashing
    }
    catch(AException& e)
    {
      pContext->useEventVisitor().addEvent(e, AEventVisitor::EL_ERROR);
      m_Services.useLog().add(pContext->useEventVisitor(), ALog::EVENT_FAILURE);
      m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
    }
    catch(std::exception& e)
    {
      pContext->useEventVisitor().addEvent(ASWNL(e.what()), AEventVisitor::EL_ERROR);
      m_Services.useLog().add(pContext->useEventVisitor(), ALog::EVENT_FAILURE);
      m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
    }
    catch(...)
    {
      m_Services.useLog().add(pContext->useEventVisitor(), ALog::EVENT_FAILURE);
      pContext->useEventVisitor().addEvent(ASWNL("Unknown exception caught in AOSContextQueue_ErrorExecutor::_threadproc"), AEventVisitor::EL_ERROR);
      m_Services.useContextManager().changeQueueState(AOSContextManager::STATE_TERMINATE, &pContext);
      break;
    }
  }

  thread.setRunning(false);
  return 0;
}