web_algo.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:12k
- /*
- * ===========================================================================
- * PRODUCTION $Log: web_algo.cpp,v $
- * PRODUCTION Revision 1000.2 2004/06/01 20:56:13 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: web_algo.cpp,v 1000.2 2004/06/01 20:56:13 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Josh Cherry
- *
- * File Description: Plugin to call remote procedure via cgi
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbistd.hpp>
- // http stuff
- #include <connect/ncbi_conn_stream.hpp>
- #include <connect/ncbi_core_cxx.hpp>
- #include <connect/ncbi_util.h>
- #include "../basic/output_dlg.hpp"
- #include <gui/core/idocument.hpp>
- #include <gui/core/plugin_utils.hpp>
- #include <gui/plugin/PluginRequest.hpp>
- #include <gui/plugin/PluginInfo.hpp>
- #include <gui/plugin/PluginCommandSet.hpp>
- #include <gui/plugin/PluginValueConstraint.hpp>
- #include <gui/core/version.hpp>
- #include <gui/objutils/utils.hpp>
- #include <gui/utils/browser_utils.hpp>
- #include "web_algo.hpp"
- #include "plugin_args_as_strs.hpp"
- #include <objmgr/util/sequence.hpp>
- #include <objmgr/scope.hpp>
- #include <objmgr/seq_vector.hpp>
- #include <objmgr/util/sequence.hpp>
- #include <objtools/readers/readfeat.hpp>
- #include <objects/seqloc/Seq_loc.hpp>
- #include <objects/general/Object_id.hpp>
- #include <connect/ncbi_pipe.hpp>
- #include <serial/serial.hpp>
- #include <serial/objostr.hpp>
- #include <serial/objistr.hpp>
- #include <cgi/ncbicgi.hpp>
- #include <util/regexp.hpp>
- BEGIN_NCBI_SCOPE
- USING_SCOPE(objects);
- void CAlgoWebService::GetInfo(CPluginInfo& info)
- {
- info.Reset();
- // version info macro
- info.SetInfo(CPluginVersion::eMajor, CPluginVersion::eMinor, 0,
- string(__DATE__) + " " + string(__TIME__),
- "CAlgoWebService", "", "", "");
- // command info
- CPluginCommandSet& cmds = info.SetCommands();
- CPluginCommand& args = cmds.AddAlgoCommand(eAlgoCommand_run);
- args.AddArgument("locs", "Sequences to evaluate",
- CSeq_loc::GetTypeInfo(),
- CPluginArg::TData::e_Array);
- args.SetConstraint("locs",
- *CPluginValueConstraint::CreateSeqSameMol());
- args.AddArgument("__url", "url",
- CPluginArg::eString);
- }
- void CAlgoWebService::RunCommand(CPluginMessage& msg)
- {
- const CPluginCommand& args = msg.GetRequest().GetCommand();
- CPluginReply& reply = msg.SetReply();
- _TRACE("CAlgoWebService::Run()");
- if ( !m_OutputDlg.get() ) {
- m_OutputDlg.reset(new COutputDlg());
- }
- m_OutputDlg->SetTitle("Results of calling web algorithm");
- const CPluginArgSet::Tdata& argset = args.GetArgs().Get();
- vector<string> keys, values;
- try {
- PluginArgsAsStrs(argset, keys, values);
- }
- catch (exception& e) {
- LOG_POST(Info << "CAlgoWebService: couldn't convert to string rep: "
- << e.what());
- reply.SetStatus(eMessageStatus_failed);
- return;
- }
- catch (...) {
- LOG_POST(Info << "CAlgoWebService: couldn't convert to string rep");
- reply.SetStatus(eMessageStatus_failed);
- return;
- }
- keys.push_back("action");
- values.push_back("run");
- string query;
- for (unsigned int i = 0; i < keys.size(); i++) {
- if (i > 0) {
- query += '&';
- }
- query += URL_EncodeString(keys[i]) + "=" + URL_EncodeString(values[i]);
- }
-
- string body;
- string headers;
- string base;
- if (args.HasArgument("__url") &&
- CPluginUtils::IsValid(args["__url"])) {
- x_DoPost(args["__url"].AsString(), query,
- body, headers);
- base = args["__url"].AsString();
- } else {
- throw runtime_error("CAlgoWebService::run: no url");
- }
- // see if we have a Content-type; if so, act appropriately
- string content_type = x_GetContentType(headers);
- if (content_type == "chemical/ncbi-asn1-ascii" ||
- content_type == "chemical/ncbi-asn1-binary" ||
- content_type == "chemical/ncbi-xml" ||
- content_type == "chemical/ncbi-five-col") {
- // in these cases we'll try to make an annot
- CRef<CSeq_annot> annot;
- CNcbiIstrstream is(body.c_str(), body.size());
- if (content_type == "chemical/ncbi-asn1-ascii" ||
- content_type == "chemical/ncbi-asn1-binary" ||
- content_type == "chemical/ncbi-xml") {
- ESerialDataFormat serial_format;
- if (content_type == "chemical/ncbi-asn1-ascii") {
- serial_format = eSerial_AsnText;
- } else if (content_type == "chemical/ncbi-asn1-binary") {
- serial_format = eSerial_AsnBinary;
- } else if (content_type == "chemical/ncbi-xml") {
- serial_format = eSerial_Xml;
- }
- auto_ptr<CObjectIStream>
- istr(CObjectIStream::Open(serial_format, is));
- annot.Reset(new CSeq_annot);
- *istr >> *annot;
- } else if (content_type == "chemical/ncbi-five-col") {
- annot = CFeature_table_reader::ReadSequinFeatureTable(is);
- }
- try {
- x_DealWithAnnot(annot, args, reply);
- }
- catch (exception& e) {
- LOG_POST(Error << e.what());
- reply.SetStatus(eMessageStatus_failed);
- return;
- }
- reply.AddAction(CPluginReplyAction::e_Add_to_document);
- } else if (content_type == "text/html") {
- if (!base.empty()) {
- CBrowserUtils::AddBaseTag(body, base);
- }
- CBrowserUtils::SendToBrowser(body);
- } else if (content_type == "text/plain" ||
- content_type.empty()) {
- string str;
- str += "Output:nn";
- str += body + "nn";
- m_OutputDlg->SetText(str);
- m_OutputDlg->Show();
- } else {
- CBrowserUtils::SendToBrowser(body, content_type);
- }
- reply.SetStatus(eMessageStatus_success);
- }
- void CAlgoWebService::x_DealWithAnnot(CRef<CSeq_annot> annot,
- const CPluginCommand& args,
- CPluginReply& reply)
- {
- // figure out which argument this annot belongs to
- CSeq_annot::TData::TFtable& ftable = annot->SetData().SetFtable();
- const CSeq_id& orig_id = sequence::GetId(ftable.front()->GetLocation());
- const string& orig_id_str = orig_id.GetLocal().GetStr();
- const CSeq_loc *loc;
- const IDocument *doc;
- // if it has the form name[integer], interpret it as array member
- CRegexp re("(.*)\[ *([0-9]+) *\]");
- if (!re.GetMatch(orig_id_str.c_str(), 0).empty()) {
- const int *name_range = re.GetResults(1);
- string name = orig_id_str.substr(name_range[0], name_range[1]);
- const int *index_range = re.GetResults(2);
- unsigned int index =
- NStr::StringToInt(orig_id_str
- .substr(index_range[0],
- index_range[1] - index_range[0]));
- plugin_args::TLocList loc_list;
- GetArgValue(args[name], loc_list);
- if (index > loc_list.size() - 1) {
- throw runtime_error(orig_id_str + " does not exist; "
- + name + " has only " +
- NStr::IntToString(loc_list.size())
- + " elements");
- }
- plugin_args::TLocList::iterator iter = loc_list.begin();
- advance(iter, index);
- loc = iter->second;
- doc = iter->first;
- } else {
- const CPluginArg& arg = args[orig_id_str];
- loc = dynamic_cast<const CSeq_loc*> (&arg.AsObject());
- doc = arg.GetDocument();
- }
- // now set the ids and remap
- NON_CONST_ITERATE (list<CRef<CSeq_feat> >, feat, ftable) {
- CSeq_loc& feat_loc = (*feat)->SetLocation();
- feat_loc.SetId(sequence::GetId(*loc));
- (*feat)->SetLocation(*CSeqUtils::RemapChildToParent(*loc, feat_loc));
- }
-
- reply.AddObject(*doc, *annot);
- m_OutputDlg->SetText("Annotations added to " + doc->GetShortTitle());
- m_OutputDlg->Show();
- }
- string CAlgoWebService::x_GetContentType(const string& headers)
- {
- list<string> lines;
- string content_type;
- NStr::Split(headers, "n", lines);
- ITERATE (list<string>, line, lines) {
- if (NStr::StartsWith(*line, "content-type:", NStr::eNocase)) {
- content_type = line->substr(string("content-type:").size());
- content_type = NStr::TruncateSpaces(content_type);
- NStr::ToLower(content_type);
- break;
- }
- }
- return content_type;
- }
- void CAlgoWebService::x_DoPost(const string& url, const string& query,
- string& body, string& headers)
- {
- body.erase();
- headers.erase();
- SConnNetInfo* net_info = ConnNetInfo_Create(0);
- if (!net_info) {
- throw runtime_error("ConnNetInfo_Create(0) returned null");
- }
- ConnNetInfo_ParseURL(net_info, url.c_str());
- net_info->req_method = eReqMethod_Post;
- // pretend to be a 'real' web browser; some servers
- // care about this
- string user_header =
- "User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; "
- "Windows NT 5.0; (R1 1.1))";
- user_header = "Content-type: application/x-www-form-urlencodedn";
- CConn_HttpStream http(net_info, user_header,
- fHCC_AutoReconnect | fHCC_KeepHeader);
- ConnNetInfo_Destroy(net_info);
- // write the query string to server
- http << query;
- // now read
- char buf[1024];
- string line;
- while (getline(http, line)) {
- if (line.find_first_not_of(" tnrfv") == string::npos) {
- break;
- }
- headers += line + 'n';
- }
- while (!http.fail()) {
- http.read(buf, 1024);
- body.append(buf, http.gcount());
- }
- }
- END_NCBI_SCOPE
- /*
- * ===========================================================================
- * $Log: web_algo.cpp,v $
- * Revision 1000.2 2004/06/01 20:56:13 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.7
- *
- * Revision 1.7 2004/05/21 22:27:47 gorelenk
- * Added PCH ncbi_pch.hpp
- *
- * Revision 1.6 2004/05/03 13:05:42 dicuccio
- * gui/utils --> gui/objutils where needed
- *
- * Revision 1.5 2004/01/27 18:45:25 dicuccio
- * Added missing header files
- *
- * Revision 1.4 2003/12/19 18:38:18 jcherry
- * Alert the user when annotations are added
- *
- * Revision 1.3 2003/12/01 23:22:00 jcherry
- * Added registry file format for plugin info
- *
- * Revision 1.2 2003/11/26 17:13:08 dicuccio
- * Lots of code clean-up. CHanged names of algorithms to CAlgoWebServices{Init}
- *
- * Revision 1.1 2003/11/25 19:08:50 jcherry
- * Initial version
- *
- * ===========================================================================
- */