summaryrefslogtreecommitdiff
path: root/cpp/src/Transform/Data.cpp
diff options
context:
space:
mode:
authorMark Spruiell <mes@zeroc.com>2003-10-23 20:07:31 +0000
committerMark Spruiell <mes@zeroc.com>2003-10-23 20:07:31 +0000
commite3b075090db02132b94ebb3432f539157c20caef (patch)
tree24d5dcead61974cd4906301c1d5bf8fb4550ec38 /cpp/src/Transform/Data.cpp
parentfix (diff)
downloadice-e3b075090db02132b94ebb3432f539157c20caef.tar.bz2
ice-e3b075090db02132b94ebb3432f539157c20caef.tar.xz
ice-e3b075090db02132b94ebb3432f539157c20caef.zip
handle missing classes; bug fixes; clean up
Diffstat (limited to 'cpp/src/Transform/Data.cpp')
-rw-r--r--cpp/src/Transform/Data.cpp186
1 files changed, 151 insertions, 35 deletions
diff --git a/cpp/src/Transform/Data.cpp b/cpp/src/Transform/Data.cpp
index 55e282190a2..a149d5c531d 100644
--- a/cpp/src/Transform/Data.cpp
+++ b/cpp/src/Transform/Data.cpp
@@ -222,14 +222,9 @@ Transform::DataPtr
Transform::DataFactory::create(const Slice::TypePtr& type, bool readOnly)
{
DataPtr data = createImpl(type, readOnly);
- if(_initializersEnabled && !readOnly)
+ if(!readOnly)
{
- string name = typeName(type);
- InitMap::iterator p = _initializers.find(name);
- if(p != _initializers.end())
- {
- p->second->initialize(this, data, _communicator);
- }
+ initialize(data);
}
return data;
}
@@ -237,31 +232,94 @@ Transform::DataFactory::create(const Slice::TypePtr& type, bool readOnly)
Transform::DataPtr
Transform::DataFactory::createBoolean(bool b, bool readOnly)
{
- return new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b);
+ DataPtr data = new BooleanData(getBuiltin(Slice::Builtin::KindBool), _errorReporter, readOnly, b);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createInteger(Ice::Long i, bool readOnly)
{
- return new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i);
+ DataPtr data = new IntegerData(getBuiltin(Slice::Builtin::KindLong), _errorReporter, readOnly, i);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createDouble(double d, bool readOnly)
{
- return new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d);
+ DataPtr data = new DoubleData(getBuiltin(Slice::Builtin::KindDouble), _errorReporter, readOnly, d);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createString(const string& s, bool readOnly)
{
- return new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s);
+ DataPtr data = new StringData(this, getBuiltin(Slice::Builtin::KindString), _errorReporter, readOnly, s);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
}
Transform::DataPtr
Transform::DataFactory::createNil(bool readOnly)
{
- return new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly);
+ DataPtr data = new ObjectRef(this, getBuiltin(Slice::Builtin::KindObject), readOnly);
+ if(!readOnly)
+ {
+ initialize(data);
+ }
+ return data;
+}
+
+Transform::DataPtr
+Transform::DataFactory::createObject(const Slice::TypePtr& type, bool readOnly)
+{
+ ObjectRefPtr obj;
+ Slice::ClassDeclPtr cl = Slice::ClassDeclPtr::dynamicCast(type);
+ if(cl)
+ {
+ Slice::ClassDefPtr def = cl->definition();
+ if(!def)
+ {
+ _errorReporter->error("class " + cl->scoped() + " declared but not defined");
+ }
+ obj = new ObjectRef(this, cl, readOnly);
+ }
+ else
+ {
+ Slice::BuiltinPtr b = Slice::BuiltinPtr::dynamicCast(type);
+ if(b && b->kind() == Slice::Builtin::KindObject)
+ {
+ obj = new ObjectRef(this, b, readOnly);
+ }
+ }
+
+ if(!obj)
+ {
+ _errorReporter->error("type `" + typeName(type) + "' is not a class");
+ }
+
+ obj->instantiate();
+
+ if(!readOnly)
+ {
+ initialize(obj);
+ }
+
+ return obj;
}
Slice::BuiltinPtr
@@ -374,6 +432,20 @@ Transform::DataFactory::createImpl(const Slice::TypePtr& type, bool readOnly)
return 0;
}
+void
+Transform::DataFactory::initialize(const DataPtr& data)
+{
+ if(_initializersEnabled)
+ {
+ string name = typeName(data->getType());
+ InitMap::iterator p = _initializers.find(name);
+ if(p != _initializers.end())
+ {
+ p->second->initialize(this, data, _communicator);
+ }
+ }
+}
+
//
// Data
//
@@ -1587,12 +1659,6 @@ Transform::DataPtr
Transform::ProxyData::getMember(const string& member) const
{
// TODO: Support members (id, facet, etc.)?
-#if 0
- if(member == "length")
- {
- return new IntegerData(_value.length());
- }
-#endif
return 0;
}
@@ -2296,12 +2362,28 @@ Transform::SequenceData::transformI(const DataPtr& data, DataInterceptor& interc
for(DataList::const_iterator p = s->_elements.begin(); p != s->_elements.end(); ++p)
{
DataPtr element = _factory->create(_type->type(), _readOnly);
- //
- // We add the element regardless of whether transform() succeeds in order to
- // preserve the original sequence size and order.
- //
- element->transform((*p), interceptor);
- elements.push_back(element);
+ Destroyer<DataPtr> elementDestroyer(element);
+ try
+ {
+ element->transform((*p), interceptor);
+ elements.push_back(element);
+ elementDestroyer.release();
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the sequence element fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the sequence) or raise the exception again.
+ //
+ if(!interceptor.purgeObjects())
+ {
+ throw;
+ }
+ _errorReporter->warning("purging element of sequence " + typeName(_type) +
+ " due to missing class type " + ex.id);
+ }
}
_elements = elements;
_length = _factory->createInteger(static_cast<Ice::Long>(_elements.size()), true);
@@ -2631,8 +2713,6 @@ Transform::DictionaryData::getMember(const string& member) const
Transform::DataPtr
Transform::DictionaryData::getElement(const DataPtr& element) const
{
- // TODO: Validate element's type
-
DataMap::const_iterator p = _map.find(element);
if(p != _map.end())
{
@@ -2824,9 +2904,33 @@ Transform::DictionaryData::transformI(const DataPtr& data, DataInterceptor& inte
for(DataMap::const_iterator p = d->_map.begin(); p != d->_map.end(); ++p)
{
DataPtr key = _factory->create(_type->keyType(), _readOnly);
+ Destroyer<DataPtr> keyDestroyer(key);
DataPtr value = _factory->create(_type->valueType(), _readOnly);
+ Destroyer<DataPtr> valueDestroyer(value);
+
key->transform(p->first, interceptor);
- value->transform(p->second, interceptor);
+
+ try
+ {
+ value->transform(p->second, interceptor);
+ }
+ catch(const ClassNotFoundException& ex)
+ {
+ //
+ // If transformation of the dictionary value fails because a class
+ // could not be found, then we invoke purgeObjects() to determine
+ // whether we should ignore the situation (and remove the element
+ // from the dictionary) or raise the exception again.
+ //
+ if(!interceptor.purgeObjects())
+ {
+ throw;
+ }
+ _errorReporter->warning("purging element of dictionary " + typeName(_type) +
+ " due to missing class type " + ex.id);
+ continue;
+ }
+
DataMap::const_iterator q = m.find(key);
if(q != m.end())
{
@@ -2839,6 +2943,8 @@ Transform::DictionaryData::transformI(const DataPtr& data, DataInterceptor& inte
else
{
m.insert(DataMap::value_type(key, value));
+ keyDestroyer.release();
+ valueDestroyer.release();
}
}
_map = m;
@@ -3018,6 +3124,7 @@ Transform::ObjectData::transform(const DataPtr& data, DataInterceptor& intercept
}
catch(...)
{
+ objectMap.erase(p);
objectMap.insert(ObjectDataMap::value_type(o.get(), 0));
throw;
}
@@ -3208,11 +3315,6 @@ Transform::ObjectRef::operator!=(const Data& rhs) const
_errorReporter->typeMismatchError(_type, rhs.getType(), true);
}
- if(!_value || !r->_value)
- {
- return !_value && r->_value;
- }
-
//
// Reference comparison.
//
@@ -3429,8 +3531,7 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept
Slice::TypeList l = _type->unit()->lookupType(name, false);
if(l.empty())
{
- // TODO: Slice object? Or missing type exception?
- _errorReporter->warning("type `" + name + "' not found");
+ throw ClassNotFoundException(name);
}
else
{
@@ -3443,9 +3544,24 @@ Transform::ObjectRef::transformI(const DataPtr& data, DataInterceptor& intercept
_errorReporter->error("no definition for " + name);
}
}
+ //
+ // Create a new object and increment its reference count. We do this
+ // because it's possible for its reference count to be manipulated
+ // during transformation, and we don't want it to be destroyed.
+ //
ObjectDataPtr data = new ObjectData(_factory, l.front(), _readOnly);
- data->transform(o->_value, interceptor);
+ data->incRef();
+ try
+ {
+ data->transform(o->_value, interceptor);
+ }
+ catch(...)
+ {
+ data->decRef();
+ throw;
+ }
setValue(data);
+ data->decRef();
}
}
}