Use new style xml parsing, instead of inheriting from XMLParser.
Signed-off-by: Yehuda Sadeh <yehuda@redhat.com>
ObjectSection(Formatter& f, const char *name) : formatter(f) {
formatter.open_object_section(name);
}
+ ObjectSection(Formatter& f, const char *name, const char *ns) : formatter(f) {
+ formatter.open_object_section_in_ns(name, ns);
+ }
~ObjectSection() {
formatter.close_section();
}
ArraySection(Formatter& f, const char *name) : formatter(f) {
formatter.open_array_section(name);
}
+ ArraySection(Formatter& f, const char *name, const char *ns) : formatter(f) {
+ formatter.open_array_section_in_ns(name, ns);
+ }
~ArraySection() {
formatter.close_section();
}
lc_processing,
lc_failed,
lc_complete,
-}LC_BUCKET_STATUS;
+} LC_BUCKET_STATUS;
class LCExpiration
{
string date;
public:
LCExpiration() {}
- ~LCExpiration() {}
+ LCExpiration(const string& _days, const string& _date) : days(_days), date(_date) {}
void encode(bufferlist& bl) const {
ENCODE_START(3, 2, bl);
return true;
}
};
-WRITE_CLASS_ENCODER(LCExpiration);
+WRITE_CLASS_ENCODER(LCExpiration)
class LCTransition
{
}
void dump(Formatter *f) const;
};
-WRITE_CLASS_ENCODER(LCTransition);
+WRITE_CLASS_ENCODER(LCTransition)
class LCFilter
{
}
void dump(Formatter *f) const;
};
-WRITE_CLASS_ENCODER(LCFilter);
+WRITE_CLASS_ENCODER(LCFilter)
return true;
}
-bool LCExpiration_S3::xml_end(const char * el) {
- LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
- LCDeleteMarker_S3 *lc_dm = static_cast<LCDeleteMarker_S3 *>(find_first("ExpiredObjectDeleteMarker"));
- LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
+void LCExpiration_S3::dump_xml(Formatter *f) const {
+ if (dm_expiration) {
+ encode_xml("ExpiredObjectDeleteMarker", "true", f);
+ } else if (!days.empty()) {
+ encode_xml("Days", days, f);
+ } else {
+ encode_xml("Date", date, f);
+ }
+}
- if ((!lc_days && !lc_dm && !lc_date) || (lc_days && lc_dm)
- || (lc_days && lc_date) || (lc_dm && lc_date)) {
- return false;
+void LCExpiration_S3::decode_xml(XMLObj *obj)
+{
+ bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj);
+ bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj);
+ string dm;
+ bool has_dm = RGWXMLDecoder::decode_xml("ExpiredObjectDeleteMarker", dm, obj);
+
+ if ((!has_days && !has_dm && !has_date) || (has_days && has_dm)
+ || (has_days && has_date) || (has_dm && has_date)) {
+ throw RGWXMLDecoder::err("bad Expiration section");
}
- if (lc_days) {
- days = lc_days->get_data();
- } else if (lc_dm) {
- dm_expiration = lc_dm->get_data().compare("true") == 0;
- if (!dm_expiration) {
- return false;
- }
- } else {
- date = lc_date->get_data();
+
+ if (has_date && !check_date(date)) {
//We need return xml error according to S3
- if (!check_date(date)) {
- return false;
- }
+ throw RGWXMLDecoder::err("bad date in Date section");
}
- return true;
}
-bool LCNoncurExpiration_S3::xml_end(const char *el) {
- LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
- if (!lc_noncur_days) {
- return false;
- }
- days = lc_noncur_days->get_data();
- return true;
+void LCNoncurExpiration_S3::decode_xml(XMLObj *obj)
+{
+ RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj, true);
}
-bool LCMPExpiration_S3::xml_end(const char *el) {
- LCDays_S3 *lc_mp_days = static_cast<LCDays_S3 *>(find_first("DaysAfterInitiation"));
- if (!lc_mp_days) {
- return false;
- }
- days = lc_mp_days->get_data();
- return true;
+void LCNoncurExpiration_S3::dump_xml(Formatter *f) const
+{
+ encode_xml("NoncurrentDays", days, f);
}
-bool RGWLifecycleConfiguration_S3::xml_end(const char *el) {
- XMLObjIter iter = find("Rule");
- LCRule_S3 *rule = static_cast<LCRule_S3 *>(iter.get_next());
- if (!rule)
- return false;
- while (rule) {
- add_rule(rule);
- rule = static_cast<LCRule_S3 *>(iter.get_next());
+void LCMPExpiration_S3::decode_xml(XMLObj *obj)
+{
+ RGWXMLDecoder::decode_xml("DaysAfterInitiation", days, obj, true);
+}
+
+void LCMPExpiration_S3::dump_xml(Formatter *f) const
+{
+ encode_xml("DaysAfterInitiation", days, f);
+}
+
+void RGWLifecycleConfiguration_S3::decode_xml(XMLObj *obj)
+{
+ vector<LCRule_S3> rules;
+
+ RGWXMLDecoder::decode_xml("Rule", rules, obj, true);
+
+ for (auto& rule : rules) {
+ add_rule(&rule);
}
+
if (cct->_conf->rgw_lc_max_rules < rule_map.size()) {
- ldout(cct, 5) << "Warn: The lifecycle config has too many rules, rule number is:"
- << rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules << dendl;
- return false;
+ stringstream ss;
+ ss << "Warn: The lifecycle config has too many rules, rule number is:"
+ << rule_map.size() << ", max number is:" << cct->_conf->rgw_lc_max_rules;
+ throw RGWXMLDecoder::err(ss.str());
}
- return true;
}
-bool LCFilter_S3::xml_end(const char* el) {
+void LCFilter_S3::dump_xml(Formatter *f) const
+{
+ if (has_prefix()) {
+ encode_xml("Prefix", prefix, f);
+ }
+ bool multi = has_multi_condition();
+ if (multi) {
+ f->open_array_section("And");
+ }
+ if (has_tags()) {
+ const auto& tagset_s3 = static_cast<const RGWObjTagSet_S3 &>(obj_tags);
+ tagset_s3.dump_xml(f);
+ }
+ if (multi) {
+ f->close_section();
+ }
+}
- XMLObj *o = find_first("And");
+void LCFilter_S3::decode_xml(XMLObj *obj)
+{
+ XMLObj *o = obj->find_first("And");
bool single_cond = false;
int num_conditions = 0;
// If there is an AND condition, every tag is a child of and
// else we only support single conditions and return false if we see multiple
if (o == nullptr){
- o = this;
+ o = obj;
single_cond = true;
}
num_conditions++;
}
- return !(single_cond && num_conditions > 1);
+ if (single_cond && num_conditions > 1) {
+ throw RGWXMLDecoder::err("Bad filter: badly formed multiple conditions");
+ }
}
-bool LCTransition_S3::xml_end(const char* el) {
- LCDays_S3 *lc_days = static_cast<LCDays_S3 *>(find_first("Days"));
- LCDate_S3 *lc_date = static_cast<LCDate_S3 *>(find_first("Date"));
- if ((lc_days && lc_date) || (!lc_days && !lc_date)) {
- return false;
+void LCTransition_S3::decode_xml(XMLObj *obj)
+{
+ bool has_days = RGWXMLDecoder::decode_xml("Days", days, obj);
+ bool has_date = RGWXMLDecoder::decode_xml("Date", date, obj);
+ if ((has_days && has_date) || (!has_days && !has_date)) {
+ throw RGWXMLDecoder::err("bad Transition section");
}
- if (lc_days) {
- days = lc_days->get_data();
- } else {
- date = lc_date->get_data();
+
+ if (has_date && !check_date(date)) {
//We need return xml error according to S3
- if (!check_date(date)) {
- return false;
- }
+ throw RGWXMLDecoder::err("bad Date in Transition section");
}
- LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(find_first("StorageClass"));
- if (!lc_storage_class) {
- return false;
- }
- storage_class = lc_storage_class->get_data();
- if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 &&
- storage_class.compare("GLACIER") != 0) {
- return false;
+
+ if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) {
+ throw RGWXMLDecoder::err("missing StorageClass in Transition section");
}
- return true;
}
-bool LCNoncurTransition_S3::xml_end(const char* el) {
- LCDays_S3 *lc_noncur_days = static_cast<LCDays_S3 *>(find_first("NoncurrentDays"));
- if (!lc_noncur_days) {
- return false;
+void LCTransition_S3::dump_xml(Formatter *f) const {
+ if (!days.empty()) {
+ encode_xml("Days", days, f);
+ } else {
+ encode_xml("Date", date, f);
}
- days = lc_noncur_days->get_data();
- LCStorageClass_S3 *lc_storage_class = static_cast<LCStorageClass_S3 *>(find_first("StorageClass"));
- if (!lc_storage_class) {
- return false;
+ encode_xml("StorageClass", storage_class, f);
+}
+
+void LCNoncurTransition_S3::decode_xml(XMLObj *obj)
+{
+ if (!RGWXMLDecoder::decode_xml("NoncurrentDays", days, obj)) {
+ throw RGWXMLDecoder::err("missing NoncurrentDays in NoncurrentVersionTransition section");
}
- storage_class = lc_storage_class->get_data();
- if (storage_class.compare("STANDARD_IA") != 0 && storage_class.compare("ONEZONE_IA") != 0 &&
- storage_class.compare("GLACIER") != 0) {
- return false;
+ if (!RGWXMLDecoder::decode_xml("StorageClass", storage_class, obj)) {
+ throw RGWXMLDecoder::err("missing StorageClass in NoncurrentVersionTransition section");
}
- return true;
}
+void LCNoncurTransition_S3::dump_xml(Formatter *f) const
+{
+ encode_xml("NoncurrentDays", days, f);
+ encode_xml("StorageClass", storage_class, f);
+}
-bool LCRule_S3::xml_end(const char *el) {
- LCID_S3 *lc_id;
- LCPrefix_S3 *lc_prefix;
- LCStatus_S3 *lc_status;
- LCExpiration_S3 *lc_expiration;
- LCNoncurExpiration_S3 *lc_noncur_expiration;
- LCMPExpiration_S3 *lc_mp_expiration;
- LCFilter_S3 *lc_filter;
- LCTransition_S3 *lc_transition;
- LCNoncurTransition_S3 *lc_noncur_transition;
+void LCRule_S3::decode_xml(XMLObj *obj)
+{
id.clear();
prefix.clear();
status.clear();
// S3 generates a 48 bit random ID, maybe we could generate shorter IDs
static constexpr auto LC_ID_LENGTH = 48;
- lc_id = static_cast<LCID_S3 *>(find_first("ID"));
- if (lc_id){
- id = lc_id->get_data();
- } else {
+ if (!RGWXMLDecoder::decode_xml("ID", id, obj)) {
gen_rand_alphanumeric_lower(cct, &id, LC_ID_LENGTH);
}
-
- lc_filter = static_cast<LCFilter_S3 *>(find_first("Filter"));
-
- if (lc_filter){
- filter = *lc_filter;
- } else {
+ LCFilter_S3 filter_s3;
+ if (!RGWXMLDecoder::decode_xml("Filter", filter_s3, obj)) {
// Ideally the following code should be deprecated and we should return
// False here, The new S3 LC configuration xml spec. makes Filter mandatory
// and Prefix optional. However older clients including boto2 still generate
// argument. A day will come when S3 enforces their own xml-spec, but it is
// not this day
- lc_prefix = static_cast<LCPrefix_S3 *>(find_first("Prefix"));
-
- if (!lc_prefix){
- return false;
+ if (!RGWXMLDecoder::decode_xml("Prefix", prefix, obj)) {
+ throw RGWXMLDecoder::err("missing Prefix in Filter");
}
+ }
+ filter = (LCFilter)filter_s3;
- prefix = lc_prefix->get_data();
+ if (!RGWXMLDecoder::decode_xml("Status", status, obj)) {
+ throw RGWXMLDecoder::err("missing Status in Filter");
+ }
+ if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0) {
+ throw RGWXMLDecoder::err("bad Status in Filter");
}
- lc_status = static_cast<LCStatus_S3 *>(find_first("Status"));
- if (!lc_status)
- return false;
- status = lc_status->get_data();
- if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0)
- return false;
+ LCExpiration_S3 s3_expiration;
+ LCExpiration_S3 s3_noncur_expiration;
+ LCExpiration_S3 s3_mp_expiration;
+ LCFilter_S3 s3_filter;
- lc_expiration = static_cast<LCExpiration_S3 *>(find_first("Expiration"));
- lc_noncur_expiration = static_cast<LCNoncurExpiration_S3 *>(find_first("NoncurrentVersionExpiration"));
- lc_mp_expiration = static_cast<LCMPExpiration_S3 *>(find_first("AbortIncompleteMultipartUpload"));
+ bool has_expiration = RGWXMLDecoder::decode_xml("Expiration", s3_expiration, obj);
+ bool has_noncur_expiration = RGWXMLDecoder::decode_xml("NoncurrentVersionExpiration", s3_noncur_expiration, obj);
+ bool has_mp_expiration = RGWXMLDecoder::decode_xml("AbortIncompleteMultipartUpload", s3_mp_expiration, obj);
- XMLObjIter iter = find("Transition");
- lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
- XMLObjIter noncur_iter = find("NoncurrentVersionTransition");
- lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
+ vector<LCTransition_S3> transitions;
+ vector<LCNoncurTransition_S3> noncur_transitions;
- if (!lc_expiration && !lc_noncur_expiration && !lc_mp_expiration && !lc_transition && !lc_noncur_transition) {
- return false;
- } else {
- if (lc_expiration) {
- if (lc_expiration->has_days()) {
- expiration.set_days(lc_expiration->get_days_str());
- } else if (lc_expiration->has_date()) {
- expiration.set_date(lc_expiration->get_date());
- } else {
- dm_expiration = lc_expiration->get_dm_expiration();
- }
- }
- if (lc_noncur_expiration) {
- noncur_expiration = *lc_noncur_expiration;
- }
- if (lc_mp_expiration) {
- mp_expiration = *lc_mp_expiration;
+ bool has_transition = RGWXMLDecoder::decode_xml("Transition", transitions, obj);
+ bool has_noncur_transition = RGWXMLDecoder::decode_xml("NoncurrentVersionTransition", noncur_transitions, obj);
+
+ if (!has_expiration &&
+ !has_noncur_expiration &&
+ !has_mp_expiration &&
+ !has_transition &&
+ !has_noncur_transition) {
+ throw RGWXMLDecoder::err("bad Rule");
+ }
+
+ if (has_expiration) {
+ if (s3_expiration.has_days() ||
+ s3_expiration.has_date()) {
+ expiration = s3_expiration;
+ } else {
+ dm_expiration = s3_expiration.get_dm_expiration();
}
- while (lc_transition) {
- if (!add_transition(lc_transition)) {
- return false;
- }
- lc_transition = static_cast<LCTransition_S3 *>(iter.get_next());
+ }
+ if (has_noncur_expiration) {
+ noncur_expiration = s3_noncur_expiration;
+ }
+ if (has_mp_expiration) {
+ mp_expiration = s3_mp_expiration;
+ }
+ for (auto& t : transitions) {
+ if (!add_transition(&t)) {
+ throw RGWXMLDecoder::err("Failed to add transition");
}
- while (lc_noncur_transition) {
- if (!add_noncur_transition(lc_noncur_transition)) {
- return false;
- }
- lc_noncur_transition = static_cast<LCNoncurTransition_S3 *>(noncur_iter.get_next());
+ }
+ for (auto& t : noncur_transitions) {
+ if (!add_noncur_transition(&t)) {
+ throw RGWXMLDecoder::err("Failed to add non-current version transition");
}
}
- return true;
}
-void LCRule_S3::to_xml(ostream& out) {
- out << "<Rule>" ;
- out << "<ID>" << id << "</ID>";
+void LCRule_S3::dump_xml(Formatter *f) const {
+ encode_xml("ID", id, f);
+ // In case of an empty filter and an empty Prefix, we defer to Prefix.
if (!filter.empty()) {
- LCFilter_S3& lc_filter = static_cast<LCFilter_S3&>(filter);
- lc_filter.to_xml(out);
+ const LCFilter_S3& lc_filter = static_cast<const LCFilter_S3&>(filter);
+ encode_xml("Filter", lc_filter, f);
} else {
- out << "<Prefix>" << prefix << "</Prefix>";
+ encode_xml("Prefix", prefix, f);
}
- out << "<Status>" << status << "</Status>";
+ encode_xml("Status", status, f);
if (!expiration.empty() || dm_expiration) {
LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration);
- expir.to_xml(out);
+ encode_xml("Expiration", expir, f);
}
if (!noncur_expiration.empty()) {
- LCNoncurExpiration_S3& noncur_expir = static_cast<LCNoncurExpiration_S3&>(noncur_expiration);
- noncur_expir.to_xml(out);
+ const LCNoncurExpiration_S3& noncur_expir = static_cast<const LCNoncurExpiration_S3&>(noncur_expiration);
+ encode_xml("NoncurrentVersionExpiration", noncur_expir, f);
}
if (!mp_expiration.empty()) {
- LCMPExpiration_S3& mp_expir = static_cast<LCMPExpiration_S3&>(mp_expiration);
- mp_expir.to_xml(out);
+ const LCMPExpiration_S3& mp_expir = static_cast<const LCMPExpiration_S3&>(mp_expiration);
+ encode_xml("AbortIncompleteMultipartUpload", mp_expir, f);
}
if (!transitions.empty()) {
for (auto &elem : transitions) {
- LCTransition_S3& tran = static_cast<LCTransition_S3&>(elem.second);
- tran.to_xml(out);
+ const LCTransition_S3& tran = static_cast<const LCTransition_S3&>(elem.second);
+ encode_xml("Transition", tran, f);
}
}
if (!noncur_transitions.empty()) {
for (auto &elem : noncur_transitions) {
- LCNoncurTransition_S3& noncur_tran = static_cast<LCNoncurTransition_S3&>(elem.second);
- noncur_tran.to_xml(out);
+ const LCNoncurTransition_S3& noncur_tran = static_cast<const LCNoncurTransition_S3&>(elem.second);
+ encode_xml("NoncurrentVersionTransition", noncur_tran, f);
}
}
- out << "</Rule>";
}
int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfiguration& dest)
}
-
void RGWLifecycleConfiguration_S3::dump_xml(Formatter *f) const
{
- f->open_object_section_in_ns("LifecycleConfiguration", XMLNS_AWS_S3);
-
- for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
- const LCRule_S3& rule = static_cast<const LCRule_S3&>(iter->second);
- rule.dump_xml(f);
- }
-
- f->close_section(); // Lifecycle
-}
-
-XMLObj *RGWLCXMLParser_S3::alloc_obj(const char *el)
-{
- XMLObj * obj = NULL;
- if (strcmp(el, "LifecycleConfiguration") == 0) {
- obj = new RGWLifecycleConfiguration_S3(cct);
- } else if (strcmp(el, "Rule") == 0) {
- obj = new LCRule_S3(cct);
- } else if (strcmp(el, "ID") == 0) {
- obj = new LCID_S3();
- } else if (strcmp(el, "Prefix") == 0) {
- obj = new LCPrefix_S3();
- } else if (strcmp(el, "Filter") == 0) {
- obj = new LCFilter_S3();
- } else if (strcmp(el, "Status") == 0) {
- obj = new LCStatus_S3();
- } else if (strcmp(el, "Expiration") == 0) {
- obj = new LCExpiration_S3();
- } else if (strcmp(el, "Days") == 0) {
- obj = new LCDays_S3();
- } else if (strcmp(el, "Date") == 0) {
- obj = new LCDate_S3();
- } else if (strcmp(el, "ExpiredObjectDeleteMarker") == 0) {
- obj = new LCDeleteMarker_S3();
- } else if (strcmp(el, "NoncurrentVersionExpiration") == 0) {
- obj = new LCNoncurExpiration_S3();
- } else if (strcmp(el, "NoncurrentDays") == 0) {
- obj = new LCDays_S3();
- } else if (strcmp(el, "AbortIncompleteMultipartUpload") == 0) {
- obj = new LCMPExpiration_S3();
- } else if (strcmp(el, "DaysAfterInitiation") == 0) {
- obj = new LCDays_S3();
- } else if (strcmp(el, "StorageClass") == 0) {
- obj = new LCStorageClass_S3();
- } else if (strcmp(el, "Transition") == 0) {
- obj = new LCTransition_S3();
- } else if (strcmp(el, "NoncurrentVersionTransition") == 0) {
- obj = new LCNoncurTransition_S3();
- }
- return obj;
+ for (auto iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
+ const LCRule_S3& rule = static_cast<const LCRule_S3&>(iter->second);
+ encode_xml("Rule", rule, f);
+ }
}
-
#include "rgw_xml.h"
#include "rgw_tag_s3.h"
-class LCID_S3 : public XMLObj
+class LCFilter_S3 : public LCFilter
{
public:
- LCID_S3() {}
- ~LCID_S3() override {}
- string& to_str() { return data; }
-};
-
-class LCPrefix_S3 : public XMLObj
-{
-public:
- LCPrefix_S3() {}
- ~LCPrefix_S3() override {}
- string& to_str() { return data; }
-};
-
-class LCFilter_S3 : public LCFilter, public XMLObj
-{
- public:
- ~LCFilter_S3() override {}
- string& to_str() { return data; }
- void to_xml(ostream& out){
- out << "<Filter>";
- stringstream ss;
- if (has_prefix())
- out << "<Prefix>" << prefix << "</Prefix>";
- if (has_tags()){
- for (const auto&kv : obj_tags.get_tags()){
- ss << "<Tag>";
- ss << "<Key>" << kv.first << "</Key>";
- ss << "<Value>" << kv.second << "</Value>";
- ss << "</Tag>";
- }
- }
-
- if (has_multi_condition()) {
- out << "<And>" << ss.str() << "</And>";
- } else {
- out << ss.str();
- }
-
- out << "</Filter>";
- }
- void dump_xml(Formatter *f) const {
- f->open_object_section("Filter");
- if (has_multi_condition())
- f->open_object_section("And");
- if (!prefix.empty())
- encode_xml("Prefix", prefix, f);
- if (has_tags()){
- const auto& tagset_s3 = static_cast<const RGWObjTagSet_S3 &>(obj_tags);
- tagset_s3.dump_xml(f);
- }
- if (has_multi_condition())
- f->close_section(); // And;
- f->close_section(); // Filter
- }
- bool xml_end(const char *el) override;
-};
-
-class LCStatus_S3 : public XMLObj
-{
-public:
- LCStatus_S3() {}
- ~LCStatus_S3() override {}
- string& to_str() { return data; }
-};
-
-class LCDays_S3 : public XMLObj
-{
-public:
- LCDays_S3() {}
- ~LCDays_S3() override {}
- string& to_str() { return data; }
-};
-
-class LCDate_S3 : public XMLObj
-{
-public:
- LCDate_S3() {}
- ~LCDate_S3() override {}
- string& to_str() { return data; }
-};
-
-class LCDeleteMarker_S3 : public XMLObj
-{
-public:
- LCDeleteMarker_S3() {}
- ~LCDeleteMarker_S3() override {}
- string& to_str() { return data; }
+ void dump_xml(Formatter *f) const;
+ void decode_xml(XMLObj *obj);
};
-class LCExpiration_S3 : public LCExpiration, public XMLObj
+class LCExpiration_S3 : public LCExpiration
{
private:
- bool dm_expiration;
+ bool dm_expiration{false};
public:
- LCExpiration_S3(): dm_expiration(false) {}
- LCExpiration_S3(string _days, string _date, bool _dm_expiration) {
- days = _days;
- date = _date;
- dm_expiration = _dm_expiration;
- }
- ~LCExpiration_S3() override {}
+ LCExpiration_S3() {}
+ LCExpiration_S3(string _days, string _date, bool _dm_expiration) : LCExpiration(_days, _date), dm_expiration(_dm_expiration) {}
- bool xml_end(const char *el) override;
- void to_xml(ostream& out) {
- out << "<Expiration>";
- if (dm_expiration) {
- out << "<ExpiredObjectDeleteMarker>" << "true" << "</ExpiredObjectDeleteMarker>";
- } else if (!days.empty()){
- out << "<Days>" << days << "</Days>";
- } else {
- out << "<Date>" << date << "</Date>";
- }
- out << "</Expiration>";
- }
- void dump_xml(Formatter *f) const {
- f->open_object_section("Expiration");
- if (dm_expiration) {
- encode_xml("ExpiredObjectDeleteMarker", "true", f);
- } else if (!days.empty()) {
- encode_xml("Days", days, f);
- } else {
- encode_xml("Date", date, f);
- }
- f->close_section(); // Expiration
- }
+ void dump_xml(Formatter *f) const;
+ void decode_xml(XMLObj *obj);
void set_dm_expiration(bool _dm_expiration) {
dm_expiration = _dm_expiration;
}
};
-class LCNoncurExpiration_S3 : public LCExpiration, public XMLObj
+class LCNoncurExpiration_S3 : public LCExpiration
{
public:
LCNoncurExpiration_S3() {}
- ~LCNoncurExpiration_S3() override {}
- bool xml_end(const char *el) override;
- void to_xml(ostream& out) {
- out << "<NoncurrentVersionExpiration>" << "<NoncurrentDays>" << days << "</NoncurrentDays>"<< "</NoncurrentVersionExpiration>";
- }
- void dump_xml(Formatter *f) const {
- f->open_object_section("NoncurrentVersionExpiration");
- encode_xml("NoncurrentDays", days, f);
- f->close_section();
- }
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
};
-class LCMPExpiration_S3 : public LCExpiration, public XMLObj
+class LCMPExpiration_S3 : public LCExpiration
{
public:
LCMPExpiration_S3() {}
- ~LCMPExpiration_S3() {}
- bool xml_end(const char *el) override;
- void to_xml(ostream& out) {
- out << "<AbortIncompleteMultipartUpload>" << "<DaysAfterInitiation>" << days << "</DaysAfterInitiation>" << "</AbortIncompleteMultipartUpload>";
- }
- void dump_xml(Formatter *f) const {
- f->open_object_section("AbortIncompleteMultipartUpload");
- encode_xml("DaysAfterInitiation", days, f);
- f->close_section();
- }
-};
-
-class LCStorageClass_S3 : public XMLObj
-{
-public:
- LCStorageClass_S3() {}
- ~LCStorageClass_S3() override {}
- string& to_str() { return data; }
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
};
-class LCTransition_S3 : public LCTransition, public XMLObj
+class LCTransition_S3 : public LCTransition
{
public:
LCTransition_S3() {}
- ~LCTransition_S3() {}
- bool xml_end(const char *el) override;
- void to_xml(ostream& out) {
- out << "<Transition>";
- if (!days.empty()) {
- out << "<Days>" << days << "</Days>";
- } else {
- out << "<Date>" << date << "</Date>";
- }
- out << "<StorageClass>" << storage_class << "</StorageClass>" << "</Transition>";
- }
-
- void dump_xml(Formatter *f) const {
- f->open_object_section("Transition");
- if (!days.empty()) {
- encode_xml("Days", days, f);
- } else {
- encode_xml("Date", date, f);
- }
- encode_xml("StorageClass", storage_class, f);
- f->close_section();
- }
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
};
-class LCNoncurTransition_S3 : public LCTransition, public XMLObj
+class LCNoncurTransition_S3 : public LCTransition
{
public:
LCNoncurTransition_S3() {}
~LCNoncurTransition_S3() {}
- bool xml_end(const char *el) override;
- void to_xml(ostream& out) {
- out << "<NoncurrentVersionTransition>" << "<NoncurrentDays>" << days << "</NoncurrentDays>"
- << "<StorageClass>" << storage_class << "</StorageClass>" << "</NoncurrentVersionTransition>";
- }
-
- void dump_xml(Formatter *f) const {
- f->open_object_section("NoncurrentVersionTransition");
- encode_xml("NoncurrentDays", days, f);
- encode_xml("StorageClass", storage_class, f);
- f->close_section();
- }
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
};
-class LCRule_S3 : public LCRule, public XMLObj
+class LCRule_S3 : public LCRule
{
private:
CephContext *cct;
public:
LCRule_S3(): cct(nullptr) {}
explicit LCRule_S3(CephContext *_cct): cct(_cct) {}
- ~LCRule_S3() override {}
- void to_xml(ostream& out);
- bool xml_end(const char *el) override;
- bool xml_start(const char *el, const char **attr);
- void dump_xml(Formatter *f) const {
- f->open_object_section("Rule");
- encode_xml("ID", id, f);
- // In case of an empty filter and an empty Prefix, we defer to Prefix.
- if (!filter.empty()) {
- const LCFilter_S3& lc_filter = static_cast<const LCFilter_S3&>(filter);
- lc_filter.dump_xml(f);
- } else {
- encode_xml("Prefix", prefix, f);
- }
- encode_xml("Status", status, f);
- if (!expiration.empty() || dm_expiration) {
- LCExpiration_S3 expir(expiration.get_days_str(), expiration.get_date(), dm_expiration);
- expir.dump_xml(f);
- }
- if (!noncur_expiration.empty()) {
- const LCNoncurExpiration_S3& noncur_expir = static_cast<const LCNoncurExpiration_S3&>(noncur_expiration);
- noncur_expir.dump_xml(f);
- }
- if (!mp_expiration.empty()) {
- const LCMPExpiration_S3& mp_expir = static_cast<const LCMPExpiration_S3&>(mp_expiration);
- mp_expir.dump_xml(f);
- }
- if (!transitions.empty()) {
- for (auto &elem : transitions) {
- const LCTransition_S3& tran = static_cast<const LCTransition_S3&>(elem.second);
- tran.dump_xml(f);
- }
- }
- if (!noncur_transitions.empty()) {
- for (auto &elem : noncur_transitions) {
- const LCNoncurTransition_S3& noncur_tran = static_cast<const LCNoncurTransition_S3&>(elem.second);
- noncur_tran.dump_xml(f);
- }
- }
- f->close_section(); // Rule
- }
+ void dump_xml(Formatter *f) const;
+ void decode_xml(XMLObj *obj);
void set_ctx(CephContext *ctx) {
cct = ctx;
}
};
-class RGWLCXMLParser_S3 : public RGWXMLParser
-{
- CephContext *cct;
-
- XMLObj *alloc_obj(const char *el) override;
-public:
- explicit RGWLCXMLParser_S3(CephContext *_cct) : cct(_cct) {}
-};
-
-class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration, public XMLObj
+class RGWLifecycleConfiguration_S3 : public RGWLifecycleConfiguration
{
public:
explicit RGWLifecycleConfiguration_S3(CephContext *_cct) : RGWLifecycleConfiguration(_cct) {}
- RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(NULL) {}
- ~RGWLifecycleConfiguration_S3() override {}
-
- bool xml_end(const char *el) override;
+ RGWLifecycleConfiguration_S3() : RGWLifecycleConfiguration(nullptr) {}
- void to_xml(ostream& out) {
- out << "<LifecycleConfiguration xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\">";
- multimap<string, LCRule>::iterator iter;
- for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) {
- LCRule_S3& rule = static_cast<LCRule_S3&>(iter->second);
- rule.to_xml(out);
- }
- out << "</LifecycleConfiguration>";
- }
+ void decode_xml(XMLObj *obj);
int rebuild(RGWRados *store, RGWLifecycleConfiguration& dest);
void dump_xml(Formatter *f) const;
};
{
bufferlist bl;
- RGWLifecycleConfiguration_S3 *config = NULL;
- RGWLCXMLParser_S3 parser(s->cct);
+ RGWLifecycleConfiguration_S3 config;
+ RGWXMLParser parser;
RGWLifecycleConfiguration_S3 new_config(s->cct);
content_md5 = s->info.env->get("HTTP_CONTENT_MD5");
op_ret = -ERR_MALFORMED_XML;
return;
}
- config = static_cast<RGWLifecycleConfiguration_S3 *>(parser.find_first("LifecycleConfiguration"));
- if (!config) {
- op_ret = -ERR_MALFORMED_XML;
+
+ try {
+ RGWXMLDecoder::decode_xml("LifecycleConfiguration", config, &parser);
+ } catch (RGWXMLDecoder::err& err) {
+ ldpp_dout(this, 5) << "Bad lifecycle configuration: " << err << dendl;
+ op_ret = -EINVAL;
return;
}
- op_ret = config->rebuild(store, new_config);
+ op_ret = config.rebuild(store, new_config);
if (op_ret < 0)
return;
if (s->cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
- ldpp_dout(this, 15) << "New LifecycleConfiguration:";
- new_config.to_xml(*_dout);
- *_dout << dendl;
+ XMLFormatter xf;
+ new_config.dump_xml(&xf);
+ stringstream ss;
+ xf.flush(ss);
+ ldpp_dout(this, 15) << "New LifecycleConfiguration:" << ss.str() << dendl;
}
op_ret = store->get_lc()->set_bucket_config(s->bucket_info, s->bucket_attrs, &new_config);
int RGWPutObjTags_ObjStore_S3::get_params()
{
- RGWObjTagsXMLParser parser;
+ RGWXMLParser parser;
if (!parser.init()){
return -EINVAL;
return -ERR_MALFORMED_XML;
}
- RGWObjTagSet_S3 *obj_tags_s3;
- RGWObjTagging_S3 *tagging;
+ RGWObjTagging_S3 tagging;
- tagging = static_cast<RGWObjTagging_S3 *>(parser.find_first("Tagging"));
- obj_tags_s3 = static_cast<RGWObjTagSet_S3 *>(tagging->find_first("TagSet"));
- if(!obj_tags_s3){
+ try {
+ RGWXMLDecoder::decode_xml("Tagging", tagging, &parser);
+ } catch (RGWXMLDecoder::err& err) {
+ ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl;
return -ERR_MALFORMED_XML;
}
RGWObjTags obj_tags;
- r = obj_tags_s3->rebuild(obj_tags);
+ r = tagging.rebuild(obj_tags);
if (r < 0)
return r;
{
string tags_str;
if (part_str(parts, "tagging", &tags_str)) {
- RGWObjTagsXMLParser parser;
+ RGWXMLParser parser;
if (!parser.init()){
ldout(s->cct, 0) << "Couldn't init RGWObjTags XML parser" << dendl;
err_msg = "Server couldn't process the request";
return -EINVAL;
}
- RGWObjTagSet_S3 *obj_tags_s3;
- RGWObjTagging_S3 *tagging;
+ RGWObjTagging_S3 tagging;
- tagging = static_cast<RGWObjTagging_S3 *>(parser.find_first("Tagging"));
- obj_tags_s3 = static_cast<RGWObjTagSet_S3 *>(tagging->find_first("TagSet"));
- if(!obj_tags_s3){
- return -ERR_MALFORMED_XML;
+ try {
+ RGWXMLDecoder::decode_xml("Tagging", tagging, &parser);
+ } catch (RGWXMLDecoder::err& err) {
+ ldout(s->cct, 5) << "Malformed tagging request: " << err << dendl;
+ return -EINVAL;
}
RGWObjTags obj_tags;
- int r = obj_tags_s3->rebuild(obj_tags);
+ int r = tagging.rebuild(obj_tags);
if (r < 0)
return r;
#include "rgw_tag_s3.h"
-bool RGWObjTagEntry_S3::xml_end(const char*){
- RGWObjTagKey_S3 *key_obj = static_cast<RGWObjTagKey_S3 *>(find_first("Key"));
- RGWObjTagValue_S3 *val_obj = static_cast<RGWObjTagValue_S3 *>(find_first("Value"));
+void RGWObjTagEntry_S3::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("Key", key, obj, true);
+ RGWXMLDecoder::decode_xml("Value", val, obj, true);
+}
- if (!key_obj)
- return false;
+void RGWObjTagEntry_S3::dump_xml(Formatter *f) const {
+ encode_xml("Key", key, f);
+ encode_xml("Value", val, f);
- string s = key_obj->get_data();
- if (s.empty()){
- return false;
+ if (key.empty()) {
+ throw RGWXMLDecoder::err("empty key");
}
- key = s;
- if (val_obj) {
- val = val_obj->get_data();
+ if (val.empty()) {
+ throw RGWXMLDecoder::err("empty val");
}
-
- return true;
}
-bool RGWObjTagSet_S3::xml_end(const char*){
- XMLObjIter iter = find("Tag");
- RGWObjTagEntry_S3 *tagentry = static_cast<RGWObjTagEntry_S3 *>(iter.get_next());
- while (tagentry) {
- const std::string& key = tagentry->get_key();
- const std::string& val = tagentry->get_val();
- if (!add_tag(key,val))
- return false;
+void RGWObjTagSet_S3::decode_xml(XMLObj *obj) {
+ vector<RGWObjTagEntry_S3> entries;
- tagentry = static_cast<RGWObjTagEntry_S3 *>(iter.get_next());
+ RGWXMLDecoder::decode_xml("Tag", entries, obj, true);
+
+ for (auto& entry : entries) {
+ const std::string& key = entry.get_key();
+ const std::string& val = entry.get_val();
+ if (!add_tag(key,val)) {
+ throw RGWXMLDecoder::err("failed to add tag");
+ }
}
- return true;
}
-int RGWObjTagSet_S3::rebuild(RGWObjTags& dest){
+int RGWObjTagSet_S3::rebuild(RGWObjTags& dest) {
int ret;
- for (const auto &it: tag_map){
+ for (const auto &it : tag_map){
ret = dest.check_and_add_tag(it.first, it.second);
if (ret < 0)
return ret;
return 0;
}
-bool RGWObjTagging_S3::xml_end(const char*){
- RGWObjTagSet_S3 *tagset = static_cast<RGWObjTagSet_S3 *> (find_first("TagSet"));
- return tagset != nullptr;
-
+void RGWObjTagging_S3::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("TagSet", tagset, obj, true);
}
void RGWObjTagSet_S3::dump_xml(Formatter *f) const {
- for (const auto& tag: tag_map){
- f->open_object_section("Tag");
- f->dump_string("Key", tag.first);
- f->dump_string("Value", tag.second);
- f->close_section();
+ for (const auto& tag : tag_map){
+ Formatter::ObjectSection os(*f, "Tag");
+ encode_xml("Key", tag.first, f);
+ encode_xml("Value", tag.second, f);
}
}
-XMLObj *RGWObjTagsXMLParser::alloc_obj(const char *el){
- XMLObj* obj = nullptr;
- if(strcmp(el,"Tagging") == 0) {
- obj = new RGWObjTagging_S3();
- } else if (strcmp(el,"TagSet") == 0) {
- obj = new RGWObjTagSet_S3();
- } else if (strcmp(el,"Tag") == 0) {
- obj = new RGWObjTagEntry_S3();
- } else if (strcmp(el,"Key") == 0) {
- obj = new RGWObjTagKey_S3();
- } else if (strcmp(el,"Value") == 0) {
- obj = new RGWObjTagValue_S3();
- }
-
- return obj;
-}
#include "rgw_tag.h"
#include "rgw_xml.h"
-struct RGWObjTagKey_S3: public XMLObj
-{
-};
-
-struct RGWObjTagValue_S3: public XMLObj
-{
-};
-
-class RGWObjTagEntry_S3: public XMLObj
+class RGWObjTagEntry_S3
{
std::string key;
std::string val;
RGWObjTagEntry_S3(const std::string &k, const std::string &v):key(k),val(v) {};
~RGWObjTagEntry_S3() {}
- bool xml_end(const char*) override;
- const std::string& get_key () const { return key;}
- const std::string& get_val () const { return val;}
- //void to_xml(CephContext *cct, ostream& out) const;
-};
+ const std::string& get_key () const { return key; }
+ const std::string& get_val () const { return val; }
-class RGWObjTagSet_S3: public RGWObjTags, public XMLObj
-{
-public:
- bool xml_end(const char*) override;
void dump_xml(Formatter *f) const;
- int rebuild(RGWObjTags& dest);
+ void decode_xml(XMLObj *obj);
};
-class RGWObjTagging_S3: public XMLObj
+class RGWObjTagSet_S3: public RGWObjTags
{
public:
- bool xml_end(const char*) override;
+ int rebuild(RGWObjTags& dest);
+
+ void dump_xml(Formatter *f) const;
+ void decode_xml(XMLObj *obj);
};
-class RGWObjTagsXMLParser : public RGWXMLParser
+class RGWObjTagging_S3
{
- XMLObj *alloc_obj(const char *el) override;
+ RGWObjTagSet_S3 tagset;
public:
- RGWObjTagsXMLParser() {}
- ~RGWObjTagsXMLParser() {}
+ void decode_xml(XMLObj *obj);
+ int rebuild(RGWObjTags& dest) {
+ return tagset.rebuild(dest);
+ }
};
+
#endif /* RGW_TAG_S3_H */
return iter;
}
+XMLObjIter XMLObj::find_first()
+{
+ XMLObjIter iter;
+ map<string, XMLObj *>::iterator first;
+ map<string, XMLObj *>::iterator last;
+ first = children.begin();
+ if (first != children.end()) {
+ last = children.upper_bound(first->first);
+ }else
+ last = children.end();
+ iter.set(first, last);
+ return iter;
+}
+
XMLObj *XMLObj::
find_first(string name)
{
void add_child(string el, XMLObj *obj);
bool get_attr(string name, string& attr);
XMLObjIter find(string name);
+ XMLObjIter find_first();
XMLObj *find_first(string name);
friend ostream& operator<<(ostream &out, const XMLObj &obj);
static void decode_xml(const char *name, T& val, T& default_val, XMLObj *obj);
};
+static inline ostream& operator<<(ostream &out, RGWXMLDecoder::err& err)
+{
+ return out << err.message;
+}
+
template<class T>
void decode_xml_obj(T& val, XMLObj *obj)
{
}
template<class T>
-void do_decode_xml_obj(vector<T>& l, const string& name, XMLObj *obj)
+void decode_xml_obj(std::vector<T>& v, XMLObj *obj)
{
- l.clear();
+ v.clear();
- XMLObjIter iter = obj->find(name);
+ XMLObjIter iter = obj->find_first();
XMLObj *o;
- while (o = iter.get_next()) {
+ while ((o = iter.get_next())) {
T val;
decode_xml_obj(val, o);
- l.push_back(val);
+ v.push_back(val);
}
}