wxp.cpp

00001 
00002 // Name:        wxp.cpp
00003 // Purpose:     wxPackageXML, wxPresetXMLDescriptor, wxIfNodeListManager,
00004 //              wxPackageRepositoryXMLDescriptor
00005 // Author:      Francesco Montorsi
00006 // Modified by:
00007 // Created:     2006-06-29
00008 // RCS-ID:      $Id: wxp.cpp,v 1.8 2007/01/31 13:27:46 frm Exp $
00009 // Copyright:   (c) Francesco Montorsi
00010 // Licence:     wxWidgets licence
00012 
00013 
00014 // For compilers that support precompilation, includes "wx/wx.h".
00015 #include "wx/wxprec.h"
00016 
00017 #ifdef __BORLANDC__
00018 #pragma hdrstop
00019 #endif
00020 
00021 #ifndef WX_PRECOMP
00022 #include "wx/wx.h"
00023 #endif
00024 
00025 // includes
00026 #include <wx/fileconf.h>
00027 #include <wx/mstream.h>
00028 #include <wx/apptrait.h>
00029 #include <wx/zstream.h>
00030 
00031 #if wxUSE_GUI
00032     #include <wx/progdlg.h>
00033 #endif
00034 
00035 #include "wxp/wxp.h"
00036 #include "wxp/packagewxp.h"
00037 
00038 
00039 // RTTI
00040 IMPLEMENT_DYNAMIC_CLASS(wxPackageXML, wxXmlDocument)
00041 IMPLEMENT_DYNAMIC_CLASS(wxPresetXMLDescriptor, wxPackageXML)
00042 IMPLEMENT_DYNAMIC_CLASS(wxPackageRepositoryXMLDescriptor, wxXmlDocument)
00043 
00044 // global objects
00045 wxPackageCommandOptionArrayHashMap wxPresetXMLDescriptor::s_hashmapOptions;
00046 wxPackageCommandSetHashMap wxPresetXMLDescriptor::s_hashmapCommands;
00047 
00048 
00049 
00050 // ----------------------------------------------------------------------------
00051 // wxPackageXML
00052 // ----------------------------------------------------------------------------
00053 
00054 void wxPackageXML::HandleUnknownTag(wxXmlNode *node)
00055 {
00056     if (node->GetType() != wxXML_COMMENT_NODE &&
00057         (node->GetType() != wxXML_TEXT_NODE || !node->IsWhitespaceOnly()))
00058     {
00059         wxLogWarning(wxT("Discarding unknown/misplaced tag <%s> found in <%s>"),
00060                      node->GetName().c_str(), node->GetParent()->GetName().c_str());
00061 
00062         // remove it so that later, when eventually this document will be saved,
00063         // this error won't be saved, too
00064         node->GetParent()->RemoveChild(node);
00065     }
00066 }
00067 
00068 wxString wxPackageXML::GetStrippedNodeContent(const wxXmlNode *n) const
00069 {
00070     // IMPORTANT: do not do any substitution otherwise we would be unable
00071     //            to save back this node with the $(...) keys preserved!
00072     //  wxString str = wxPackageInfo::SubstituteStandard(n->GetNodeContent());
00073     wxString str = n->GetNodeContent();
00074 
00075     // we never want leading/trailing whitespaces!
00076     return str.Strip(wxString::both);
00077 }
00078 
00079 wxPackageCondition wxPackageXML::LoadCondition(const wxXmlNode *n)
00080 {
00081     wxString buildsys(n->GetPropVal(wxT("buildsys"), wxEmptyString));
00082     wxString formats(n->GetPropVal(wxT("formats"), wxEmptyString));
00083     wxString platforms(n->GetPropVal(wxT("platforms"), wxEmptyString));
00084     wxString stages(n->GetPropVal(wxT("stages"), wxEmptyString));
00085 
00086     // strings -> lists
00087     long b = wxString2PackageBuildSystemTypeList(buildsys);
00088     long f = wxString2PackageCompilerFormatList(formats);
00089     long p = wxString2PortIdList(platforms);
00090     long s = wxString2PackageBuildSystemStageList(stages);
00091 
00092     // if no build systems were listed, we consider
00093     // that all build systems satisfy this condition;
00094     // the same for formats,platforms,stages
00095     if (b == 0) b = wxGetFullPackageBuildSystemTypeList();
00096     if (f == 0) f = wxGetFullPackageCompilerFormatList();
00097     if (p == 0) p = wxGetFullPortIdList();
00098     if (s == 0) s = wxGetFullPackageBuildSystemStageList();
00099 
00100     return wxPackageCondition(p, f, b, s);
00101 }
00102 
00103 wxPackageCommandOptionArray wxPackageXML::LoadOptions(const wxXmlNode *n)
00104 {
00105     // this function is used to load both <option-set> and <options> tags
00106     if (n->GetName() != wxT("option-set") &&
00107         n->GetName() != wxT("options"))
00108         return wxEmptyPackageCommandOptionArray;
00109 
00110     wxPackageCommandOptionArray ret;
00111     wxXmlNode *cond = n->GetChildren();
00112     while (cond)
00113     {
00114         if (cond->GetName() == wxT("if"))
00115         {
00116             wxPackageCondition c = LoadCondition(cond);
00117 
00118             // load this IF block even if the running platform does not coincide
00119             // with the platform specified in the <if> block.
00120             // this is because we must be able to save the wxPackageCommandOptionArray
00121             // we are building, later and without any data loss
00122             wxXmlNode *optnode = cond->GetChildren();
00123             while (optnode)
00124             {
00125                 if (optnode->GetName() == wxT("option"))
00126                 {
00127                     wxPackageCommandOption opt = LoadOption(optnode);
00128                     opt.SetCondition(c);
00129 
00130                     // duplicate options will be automatically discarded by
00131                     // wxPackageCommandOptionArray::Add
00132                     if (opt.IsOk())
00133                         ret.Add(opt);
00134                     else
00135                         wxLogWarning(wxT("Discarding invalid option named '%s'"),
00136                                      opt.GetName().c_str());
00137                 }
00138                 else
00139                     HandleUnknownTag(optnode);
00140 
00141                 optnode = optnode->GetNext();
00142             }
00143         }
00144         else if (cond->GetName() == wxT("option"))
00145         {
00146             // a non-conditional option!
00147 
00148             wxPackageCommandOption opt = LoadOption(cond);
00149             if (opt.IsOk())
00150                 ret.Add(opt);
00151             else
00152                 wxLogWarning(wxT("Discarding invalid option named '%s'"), 
00153                              opt.GetName().c_str());
00154         }
00155         else
00156             HandleUnknownTag(cond);
00157 
00158         // proceed
00159         cond = cond->GetNext();
00160     }
00161 
00162     return ret;
00163 }
00164 
00165 wxPackageCommandOption wxPackageXML::LoadOption(const wxXmlNode *n)
00166 {
00167     if (n->GetName() != wxT("option") ||
00168         !n->HasProp(wxT("name")))
00169         return wxEmptyPackageCommandOption;
00170 
00171     wxString name(n->GetPropVal(wxT("name"), wxEmptyString));
00172     wxString category(n->GetPropVal(wxT("category"), wxEmptyString));
00173     wxString defvalue, description, group, values, valuesdesc, value;
00174 
00175     wxXmlNode *child = n->GetChildren();
00176     while (child)
00177     {
00178         if (child->GetName() == wxT("default-value"))
00179         {
00180             defvalue = GetStrippedNodeContent(child);
00181         }
00182         else if (child->GetName() == wxT("description"))
00183         {
00184             description = GetStrippedNodeContent(child);
00185             description.Trim(false);
00186             description.Trim(true);
00187         }
00188         else if (child->GetName() == wxT("group"))
00189         {
00190             group = GetStrippedNodeContent(child);
00191         }
00192         else if (child->GetName() == wxT("values"))
00193         {
00194             values = GetStrippedNodeContent(child);
00195         }
00196         else if (child->GetName() == wxT("values-description"))
00197         {
00198             valuesdesc = GetStrippedNodeContent(child);
00199         }
00200         else if (child->GetName() == wxT("value"))
00201         {
00202             // this node is 'special': it's not in bakefile <option> syntax
00203             // (like also 'group') but, more important, it can be
00204             // used to specify the current value of the option which can be
00205             // different from the default value.
00206             value = GetStrippedNodeContent(child);
00207         }
00208         else
00209             HandleUnknownTag(child);
00210 
00211         // proceed
00212         child = child->GetNext();
00213     }
00214 
00215     // fill in the holes
00216     if (group == wxEmptyString)
00217         group = wxT("Ungrouped");
00218     if (value == wxEmptyString)
00219         value = defvalue;
00220 
00221     // we have now gathered all we need for building this option
00222     wxPackageCommandOptionCategory cat = wxString2PackageCommandOptionCategory(category);
00223     wxPackageCommandOption opt(name, values, value, defvalue, valuesdesc,
00224                             description, group, cat);
00225 
00226     // this can be done only after the option has been created
00227     if (cat == wxPCOC_INVALID && !n->HasProp(wxT("category")))
00228         opt.AutodetectCategory();   // try some smart heuristic
00229 
00230     // by default an option can always be used.
00231     // if this option is inside an <if> tag the caller will adjust the
00232     // condition associated with opt:
00233     opt.GetCondition().SetAlwaysTrue();
00234 
00235     return opt;
00236 }
00237 
00238 wxPackageCommand wxPackageXML::LoadCommand(const wxXmlNode *n)
00239 {
00240     wxPackageCommand ret(GetStrippedNodeContent(n),
00241                         n->GetPropVal(wxT("path"), wxEmptyString));
00242 
00243     // by default a command can always be used.
00244     // if this option is inside an <if> tag the caller will adjust the
00245     // condition associated with opt:
00246     ret.GetCondition().SetAlwaysTrue();
00247     return ret;
00248 }
00249 
00250 wxXmlNode *wxPackageXML::AddChildIndentation(wxXmlNode *node, int level)
00251 {
00252     wxASSERT(node);
00253     if (m_nIndentationStep < 0)
00254         return node->GetChildren();
00255 
00256     wxXmlNode *indent = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString,
00257                                       wxT("\n") + wxString(wxT(' '), 
00258                                       level*m_nIndentationStep));
00259     node->AddChild(indent);
00260     return indent;
00261 }
00262 
00263 wxXmlNode *wxPackageXML::InsertChildIndentation(wxXmlNode *node, 
00264                                                 wxXmlNode *before_node, 
00265                                                 int level)
00266 {    
00267     wxASSERT(node);
00268     if (m_nIndentationStep < 0)
00269         return node->GetChildren();
00270 
00271     wxXmlNode *indent = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString,
00272                                       wxT("\n") + wxString(wxT(' '), 
00273                                       level*m_nIndentationStep));
00274     node->InsertChild(indent, before_node);
00275     return indent;
00276 }
00277 
00278 wxXmlNode *wxPackageXML::AddSiblingIndentation(wxXmlNode *node, int level)
00279 {
00280     wxASSERT(node);
00281     if (m_nIndentationStep < 0)
00282         return node;
00283 
00284     wxXmlNode *indent = new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString,
00285                                       wxT("\n") + wxString(wxT(' '), 
00286                                       level*m_nIndentationStep));
00287     indent->SetParent(node->GetParent());
00288 
00289     wxXmlNode *oldnext = node->GetNext();
00290     node->SetNext(indent);
00291     indent->SetNext(oldnext);
00292     return indent;
00293 }
00294 
00295 wxXmlNode *wxPackageXML::SaveCondition(const wxPackageCondition &cond, int WXUNUSED(level))
00296 {
00297     // NOTE: indentation level is unused since the <if> node does
00298     //       not need any children subnode - at least at this point
00299     //       of XML tree creation
00300 
00301     wxXmlNode *ret = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("if"));
00302 
00303     wxString fmt,plat,bs,stages;
00304 
00305     if (cond.GetFormats() != wxGetFullPackageCompilerFormatList())
00306         fmt = cond.GetFormatsStr();
00307     if (cond.GetPlatforms() != wxGetFullPortIdList())
00308         plat = cond.GetPlatformsStr();
00309     if (cond.GetBuildSystems() != wxGetFullPackageBuildSystemTypeList())
00310         bs = cond.GetBuildSystemsStr();
00311     if (cond.GetStages() != wxGetFullPackageBuildSystemStageList())
00312         stages = cond.GetStagesStr();
00313 
00314     if (!fmt.IsEmpty()) ret->AddProperty(wxT("formats"), fmt.Lower());
00315     if (!plat.IsEmpty()) ret->AddProperty(wxT("platforms"), plat.Lower());
00316     if (!bs.IsEmpty()) ret->AddProperty(wxT("buildsys"), bs.Lower());
00317     if (!stages.IsEmpty()) ret->AddProperty(wxT("stages"), stages.Lower());
00318 
00319     return ret;
00320 }
00321 
00322 wxXmlNode *wxPackageXML::SaveOption(const wxPackageCommandOption &opt, int level)
00323 {
00324 #define wxADD_CHILD_WITH_TEXT(name, text)                               \
00325     if (!text.IsEmpty())                                                \
00326     {                                                                   \
00327         wxXmlNode *node = new wxXmlNode(wxXML_ELEMENT_NODE, name);      \
00328         node->AddChild(new wxXmlNode(wxXML_TEXT_NODE, name, text));     \
00329         AddChildIndentation(optnode, level+1);                          \
00330         optnode->AddChild(node);                                        \
00331     }
00332 
00333     wxXmlNode *optnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option"));
00334     optnode->AddProperty(wxT("name"), opt.GetName());
00335 
00336     if (opt.GetCategory() != wxPCOC_LISTED_VALUES)
00337         optnode->AddProperty(wxT("category"),
00338                              wxPackageCommandOptionCategory2String(opt.GetCategory()));
00339 
00340     // save value only if different from default value
00341     if (opt.IsChanged())
00342         wxADD_CHILD_WITH_TEXT(wxT("value"), opt.GetValue());
00343 
00344     wxADD_CHILD_WITH_TEXT(wxT("default-value"), opt.GetDefaultValue());
00345     wxADD_CHILD_WITH_TEXT(wxT("values"), opt.GetAllowedValues());
00346     wxADD_CHILD_WITH_TEXT(wxT("values-description"), opt.GetValueDesc());
00347     wxADD_CHILD_WITH_TEXT(wxT("description"), opt.GetDescription());
00348     wxADD_CHILD_WITH_TEXT(wxT("group"), opt.GetGroup());
00349     AddChildIndentation(optnode, level);
00350 
00351     return optnode;
00352 }
00353 
00354 wxXmlNode *wxPackageXML::SaveCommand(const wxPackageCommand &cmd, int WXUNUSED(level))
00355 {
00356     // NOTE: indentation level is unused since the <cmd> node does
00357     //       not need any children subnode
00358 
00359     // create command node
00360     wxXmlNode *cmdnode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("cmd"));
00361     cmdnode->AddChild(new wxXmlNode(wxXML_TEXT_NODE, wxT("cmd"), cmd.GetCommand()));
00362 
00363     if (!cmd.GetWorkingPath().IsEmpty())
00364         cmdnode->AddProperty(wxT("path"), cmd.GetWorkingPath());
00365     return cmdnode;
00366 }
00367 
00368 
00369 
00370 
00371 
00372 // ----------------------------------------------------------------------------
00373 // wxIfNodeListManager
00374 // ----------------------------------------------------------------------------
00375 
00376 void wxIfNodeListManager::SmartAppend(wxXmlNode *n, const wxPackageCondition &cnd, int level)
00377 {
00378     if (m_previousif == NULL)
00379     {
00380         // previous node did not use an <if> block
00381         if (cnd != wxEmptyPackageCondition && !cnd.IsAlwaysTrue())
00382         {
00383             // this node needs an <if> block...
00384             m_previouscond = cnd;
00385             m_previousif = m_doc->SaveCondition(cnd, level);
00386 
00387             // add given node to this new <if> child
00388             m_previousif->AddChild(n);
00389 
00390             // indent the <if> child and add it to the parent
00391             m_doc->AddChildIndentation(m_parent, level);
00392             m_parent->AddChild(m_previousif);
00393         }
00394         else
00395         {
00396             // also this node does not need an <if> block...
00397             m_doc->AddChildIndentation(m_parent, level);
00398             m_parent->AddChild(n);
00399 
00400             // let m_previousif to NULL
00401             wxASSERT(m_previouscond == wxEmptyPackageCondition);
00402         }
00403     }
00404     else
00405     {
00406         // previous node used an <if> block
00407         if (cnd != wxEmptyPackageCondition && !cnd.IsAlwaysTrue())
00408         {
00409             if (cnd != m_previouscond)
00410             {
00411                 // cannot reuse previous <if> !
00412                 m_previouscond = cnd;
00413                 m_previousif = m_doc->SaveCondition(cnd, level);
00414 
00415                 // indent the <if> child:
00416                 m_doc->AddChildIndentation(m_previousif, level+1);
00417                 m_previousif->AddChild(n);
00418                 m_doc->AddChildIndentation(m_previousif, level+1);
00419 
00420                 m_parent->AddChild(m_previousif);
00421             }
00422             else
00423             {
00424                 // previous <if> can be reused!
00425                 m_doc->AddChildIndentation(m_previousif, level+1);
00426                 m_previousif->AddChild(n);
00427                 m_doc->AddChildIndentation(m_previousif, level+1);
00428 
00429                 m_previouscond = cnd;
00430             }
00431         }
00432         else
00433         {
00434             // this node does not need an <if> block...
00435             m_doc->AddChildIndentation(m_previousif, level);
00436             m_parent->AddChild(n);
00437             m_doc->AddChildIndentation(m_previousif, level);
00438 
00439             m_previousif = NULL;
00440             m_previouscond = wxEmptyPackageCondition;
00441         }
00442     }
00443 }
00444 
00445 void wxIfNodeListManager::SaveOptions(const wxPackageCommandOptionArray &arr, int level)
00446 {
00447     for (size_t i=0; i < arr.GetCount(); i++)
00448     {
00449         // wxIfNodeListManager will concatenate the <option> node
00450         // to the previous <if>, if possible
00451         wxXmlNode *newnode = m_doc->SaveOption(arr[i], level);
00452         SmartAppend(newnode, arr[i].GetCondition(), level);
00453     }
00454 }
00455 
00456 void wxIfNodeListManager::SaveCommands(const wxPackageCommandArray &arr, int level)
00457 {
00458     for (size_t i=0; i < arr.GetCount(); i++)
00459     {
00460         // wxIfNodeListManager will concatenate the <cmd> node
00461         // to the previous <if>, if possible
00462         wxXmlNode *newnode = m_doc->SaveCommand(arr[i], level);
00463         SmartAppend(newnode, arr[i].GetCondition(), level);
00464     }
00465 }
00466 
00467 
00468 
00469 
00470 // ----------------------------------------------------------------------------
00471 // wxPresetXMLDescriptor
00472 // ----------------------------------------------------------------------------
00473 
00474 #ifdef __WXDEBUG__
00475 // static
00476 void wxPresetXMLDescriptor::Dump()
00477 {
00478     // dump loaded option sets
00479     wxPackageCommandOptionArrayHashMap::iterator it;
00480     for( it = s_hashmapOptions.begin(); it != s_hashmapOptions.end(); ++it )
00481     {
00482         wxString key = it->first;
00483         wxPackageCommandOptionArray &value = it->second;
00484 
00485         for (size_t i=0; i<value.GetCount(); i++)
00486             wxLogDebug(wxT("Optionset [%s] - option '%s' - default value '%s'"),
00487                     key.c_str(), value[i].GetName().c_str(),
00488                     value[i].GetDefaultValue().c_str());
00489     }
00490 
00491     // dump loaded command sets
00492     wxPackageCommandSetHashMap::iterator it2;
00493     for( it2 = s_hashmapCommands.begin(); it2 != s_hashmapCommands.end(); ++it2 )
00494     {
00495         wxString key = it2->first;
00496         wxPackageCommandSet &value = it2->second;
00497 
00498         for (size_t i=0; i<value.GetCount(); i++)
00499             wxLogDebug(wxT("Commandset [%s] - command '%s'"),
00500                     key.c_str(), value[i].GetCommand().c_str());
00501     }
00502 }
00503 #endif
00504 
00505 // static
00506 bool wxPresetXMLDescriptor::Load(const wxString &filename)
00507 {
00508     wxFileInputStream stream(filename);
00509     if (!stream.Ok())
00510         return false;
00511 
00512     // the XML parsed by the following instance will be
00513     // saved in static vars and thus nothing will be lost
00514     wxPresetXMLDescriptor doc;
00515     return doc.Load(stream);
00516 }
00517 
00518 bool wxPresetXMLDescriptor::Load(wxInputStream &input)
00519 {
00520     wxXmlDocument doc;
00521 
00522     if (!doc.Load(input))
00523         return false;
00524 
00525     if (!doc.GetRoot() ||
00526         doc.GetRoot()->GetName() != wxT("wxpackage-presets") ||
00527         doc.GetRoot()->GetPropVal(wxT("version"), wxT("1.0")) != wxT("1.0"))
00528         return false;
00529 
00530     wxXmlNode *child = doc.GetRoot()->GetChildren();
00531     while (child)
00532     {
00533         if (child->GetName() == wxT("option-set") &&
00534             child->HasProp(wxT("name")))
00535         {
00536             // load name & description of this preset
00537             wxString name = child->GetPropVal(wxT("name"), wxEmptyString);
00538             wxString desc = child->GetPropVal(wxT("description"), wxEmptyString);
00539 
00540             // load options it contains
00541             wxPackageCommandOptionArray preset(LoadOptions(child));
00542             preset.SetDescription(desc);
00543 
00544             if (preset.IsOk())
00545                 s_hashmapOptions[name] = preset;
00546             else
00547                 wxLogWarning(wxT("Discarding invalid option set named '%s'"), 
00548                              name.c_str());
00549         }
00550         else if (child->GetName() == wxT("command-set") &&
00551                 child->HasProp(wxT("name")))
00552         {
00553             // load name & description of this preset
00554             wxString name = child->GetPropVal(wxT("name"), wxEmptyString);
00555             wxString desc = child->GetPropVal(wxT("description"), wxEmptyString);
00556 
00557             // load commands it contains
00558             wxPackageCommandSet cmdset(LoadCommandSet(child));
00559             cmdset.SetDescription(desc);
00560 
00561             if (cmdset.IsOk())
00562                 s_hashmapCommands[name] = cmdset;
00563             else
00564                 wxLogWarning(wxT("Discarding invalid command set named '%s'"), 
00565                              name.c_str());
00566         }
00567         else
00568             HandleUnknownTag(child);
00569 
00570         // proceed
00571         child = child->GetNext();
00572     }
00573 
00574     return true;
00575 }
00576 
00577 wxPackageCommandSet wxPresetXMLDescriptor::LoadCommandSet(const wxXmlNode *n)
00578 {
00579     wxPackageCommandSet ret;
00580 
00581     wxString buildsys = n->GetPropVal(wxT("buildsys"), wxEmptyString);
00582     wxString vars = n->GetPropVal(wxT("vars"), wxEmptyString);
00583 
00584     ret.SetBuildSystemType(wxString2PackageBuildSystemType(buildsys));
00585     ret.SetVars(vars);
00586 
00587     wxXmlNode *child = n->GetChildren();
00588     while (child)
00589     {
00590         if (child->GetName() == wxT("if"))
00591         {
00592             wxPackageCondition current = LoadCondition(child);
00593 
00594             // command sets are already buildsystem-specific thus
00595             // having a buildsys attribute in this <if> node does
00596             // not make sense!
00597             if (!child->HasProp(wxT("buildsys")))
00598             {
00599                 wxXmlNode *cmd = child->GetChildren();
00600                 while (cmd)
00601                 {
00602                     if (cmd->GetName() == wxT("cmd"))
00603                     {
00604                         wxPackageCommand c(LoadCommand(cmd));
00605                         c.SetCondition(current);
00606                         if (c.IsOk())
00607                             ret.Add(c);
00608                         else
00609                             wxLogWarning(wxT("Discarding invalid <cmd> '%s'"),
00610                                          c.GetCommand().c_str());
00611                     }
00612                     else
00613                         HandleUnknownTag(cmd);
00614 
00615                     cmd = cmd->GetNext();
00616                 }
00617             }
00618             else
00619                 wxLogWarning(wxT("Discarding invalid <if> command"));
00620         }
00621         else if (child->GetName() == wxT("cmd"))
00622         {
00623             wxPackageCommand c(LoadCommand(child));
00624             if (c.IsOk())
00625                 ret.Add(c);
00626             else
00627                 wxLogWarning(wxT("Discarding invalid <cmd> '%s'"),
00628                              c.GetCommand().c_str());
00629         }
00630         else
00631             HandleUnknownTag(child);
00632 
00633         // proceed
00634         child = child->GetNext();
00635     }
00636 
00637     return ret;
00638 }
00639 
00640 // static
00641 bool wxPresetXMLDescriptor::SavePresets(const wxString &filename)
00642 {
00643     // skip this save if all arrays are marked as "clean"
00644     // NB: this kind of check cannot be done in the other overload of
00645     //     SavePresets() as we need to do it *before* creating the
00646     //     wxFileOutputStream for given filename (which resets the contents
00647     //     of that file if it already exists).
00648     bool allclean = true;
00649     for( wxPackageCommandOptionArrayHashMap::iterator it = s_hashmapOptions.begin();
00650         it != s_hashmapOptions.end(); ++it )
00651     {
00652         if (s_hashmapOptions[it->first].IsDirty())
00653         {
00654             allclean = false;
00655             break;
00656         }
00657     }
00658 
00659     if (allclean)
00660         return true;
00661 
00662     wxFileOutputStream stream(filename);
00663     if (!stream.Ok())
00664         return false;
00665 
00666     // the XML parsed by the following instance will be
00667     // saved in static vars and thus nothing will be lost
00668     wxPresetXMLDescriptor doc;
00669     return doc.SavePresets(stream);
00670 }
00671 
00672 bool wxPresetXMLDescriptor::SavePresets(wxOutputStream &out)
00673 {
00674     wxXmlNode *root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("wxpackage-presets"));
00675     root->AddProperty(wxT("version"), wxT("1.0"));
00676 
00677     // place a std comment at the beginning
00678     root->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, wxEmptyString,
00679                    wxString::Format(wxT(" Preset file for the wxWidgets Package Manager. Automatically generated in date %s. "),
00680                                     wxDateTime::Now().Format(wxT("%d %b %Y")).c_str())));
00681     root->AddChild(new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, wxT("\n\n")));
00682 
00683     // create all <option-set> nodes
00684     root->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, wxEmptyString,
00685                                 wxT(" The option presets: ")));
00686     for( wxPackageCommandOptionArrayHashMap::iterator it = s_hashmapOptions.begin();
00687         it != s_hashmapOptions.end(); ++it )
00688     {
00689         wxPackageCommandOptionArray &arr = it->second;
00690 
00691         // if this option set is empty skip it completely!
00692         if (arr.GetCount() == 0)
00693             continue;
00694 
00695         wxXmlNode *child = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("option-set"));
00696         child->AddProperty(wxT("name"), it->first);
00697         child->AddProperty(wxT("description"), arr.GetDescription());
00698 
00699         // add <if> nodes with <option> children
00700         wxIfNodeListManager list(this, child);
00701         list.SaveOptions(arr);
00702 
00703         // link with parent
00704         root->AddChild(child);
00705     }
00706 
00707     // create all <command-set> nodes
00708     root->AddChild(new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, wxT("\n\n")));
00709     root->AddChild(new wxXmlNode(wxXML_COMMENT_NODE, wxEmptyString,
00710                                 wxT(" The command presets: ")));
00711     for( wxPackageCommandSetHashMap::iterator it = s_hashmapCommands.begin();
00712         it != s_hashmapCommands.end(); ++it )
00713     {
00714         wxPackageCommandSet &arr = it->second;
00715 
00716         // if this option set is empty skip it completely!
00717         if (arr.GetCount() == 0)
00718             continue;
00719 
00720         wxXmlNode *child = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("command-set"));
00721         child->AddProperty(wxT("name"), it->first);
00722         child->AddProperty(wxT("description"), arr.GetDescription());
00723 
00724         // create property strings
00725         child->AddProperty(wxT("vars"),
00726                         wxArray2String(arr.GetVars()));
00727         child->AddProperty(wxT("buildsys"),
00728             wxPackageBuildSystemType2String(arr.GetBuildSystemType()));
00729 
00730         // add <if> nodes with <cmd> children
00731         wxIfNodeListManager list(this, child);
00732         list.SaveCommands(arr);
00733 
00734         // link with parent
00735         root->AddChild(child);
00736     }
00737 
00738     // finally, save the document
00739     wxXmlDocument doc;
00740     doc.SetRoot(root);
00741     return doc.Save(out, 2 /* default indentation level */);
00742 }
00743 
00744 
00745 
00746 // ----------------------------------------------------------------------------
00747 // wxPackageRepositoryXMLDescriptor
00748 // ----------------------------------------------------------------------------
00749 
00750 bool wxPackageRepositoryXMLDescriptor::Load(const wxString &filename)
00751 {
00752     wxFFileInputStream input(filename);
00753     if (!input.IsOk())
00754         return false;
00755 
00756     // WXL files are gzipped:
00757     wxZlibInputStream unzipped(input);
00758     return wxPackageXML::Load(unzipped);
00759 }
00760 
00761 bool wxPackageRepositoryXMLDescriptor::AddPackage(const wxString &pkgfile)
00762 {
00763     wxPackage pkg;
00764     if (!pkg.LoadCompressedPackage(pkgfile))
00765     {
00766         wxLogError(wxT("Cannot load the '%s' package."), pkgfile.c_str());
00767         return false;
00768     }
00769 
00770     // the UpdateMD5() and UpdateCompressedSize() functions
00771     // have been already called on 'pkg' by LoadCompressedPackage
00772 
00773     if (!GetRoot())
00774     {
00775         // create our root first
00776         SetRoot(new wxXmlNode(wxXML_ELEMENT_NODE, wxT("wxpackagelist")));
00777         GetRoot()->AddProperty(wxT("version"), wxT("1.0"));
00778     }
00779 
00780     // SetPackageInfo will create all the XML tree for the given package.
00781     // NB: the XML document created won't have any comment in it but this
00782     //     is good for us as WXL are not going to be read by humans and
00783     //     leaving out comments makes them smaller and faster to download !
00784     wxPackageXMLDescriptor wxp;
00785     wxp.SetPackageInfo(pkg);
00786 
00787     // don't copy the entire package XML tree; detach it from
00788     // the wxPackageXMLDescriptor and attach it to our tree
00789     wxXmlNode *root = wxp.DetachRoot();
00790     GetRoot()->AddChild(root);
00791 
00792     root->AddProperty(wxT("size"), pkg.GetCompressedSize().ToString());
00793     root->AddProperty(wxT("md5"), pkg.GetMD5());
00794     root->AddProperty(wxT("file"), wxFileName(pkgfile).GetFullName());
00795 
00796     return true;
00797 }
00798 
00799 wxPackageArray wxPackageRepositoryXMLDescriptor::GetPackageArray(const wxString &repourl)
00800 {
00801     wxPackageArray ret;
00802 
00803     // parse this package list
00804     if (!GetRoot() ||
00805         GetRoot()->GetName() != wxT("wxpackagelist") ||
00806         GetRoot()->GetPropVal(wxT("version"), wxT("1.0")) != wxT("1.0"))
00807         return wxEmptyPackageArray;
00808 
00809     // if the repository is at e.g. http://wxwpm.sourceforge.net/packages/packages.wxl
00810     // we want to use as download link for package "abc.wxz" the URL:
00811     // http://wxwpm.sourceforge.net/packages/abc.wxz
00812     wxString baseurl = repourl.BeforeLast(wxT('/'));
00813 
00814     wxXmlNode *child = GetRoot()->GetChildren();
00815     while (child)
00816     {
00817         if (child->GetName() == wxT("wxpackage"))
00818         {
00819             wxPackageXMLDescriptor wxp;
00820 
00821             // don't copy the 'child' node owned by *this
00822             wxp.SetRoot(child);
00823 
00824             // do parse the XML
00825             if (wxp.Parse())
00826             {
00827                 // get package info data and complete it with some
00828                 // properties only present in the <wxpackage> tags which
00829                 // are children of the <wxpackagelist> tag
00830                 wxPackage pkg(wxp.GetPackageInfo());
00831 
00832                 wxString url, filename = child->GetPropVal(wxT("file"), wxEmptyString);
00833                 if (!baseurl.IsEmpty() && !filename.IsEmpty())
00834                      url = baseurl + wxT("/") + filename;
00835 
00836                 pkg.SetRepoDownloadLink(url);
00837                 pkg.SetMD5(child->GetPropVal(wxT("md5"), wxEmptyString));
00838 
00839                 if (child->HasProp(wxT("size")))
00840                 {
00841                     unsigned long sz;
00842                     if (child->GetPropVal(wxT("size"), wxEmptyString).ToULong(&sz))
00843                         pkg.SetCompressedSize(sz);
00844                 }
00845 
00846                 if (pkg.IsOk())
00847                 {
00848                     pkg.SetRemoteStatus();
00849                     ret.Add(pkg);
00850                 }
00851                 else
00852                     wxLogWarning(wxT("Discarding invalid package named '%s'"),
00853                                  pkg.GetName().c_str());
00854             }
00855 
00856             // before the wxPackageXMLDescriptor gets destroyed,
00857             // remove our child from the root of that instance
00858             wxp.DetachRoot();
00859         }
00860         else
00861             HandleUnknownTag(child);
00862 
00863         // proceed
00864         child = child->GetNext();
00865     }
00866 
00867     if (!ret.IsOk())
00868         return wxEmptyPackageArray;
00869     return ret;
00870 }
00871 

Generated on Thu Feb 1 22:14:31 2007 for wxWidgets Package Manager by  doxygen 1.5.1-p1