diff options
Diffstat (limited to 'cpp/src/Slice/JavaUtil.cpp')
-rw-r--r-- | cpp/src/Slice/JavaUtil.cpp | 388 |
1 files changed, 302 insertions, 86 deletions
diff --git a/cpp/src/Slice/JavaUtil.cpp b/cpp/src/Slice/JavaUtil.cpp index b67f36055a4..e1ca7fdbba0 100644 --- a/cpp/src/Slice/JavaUtil.cpp +++ b/cpp/src/Slice/JavaUtil.cpp @@ -10,6 +10,7 @@ #include <IceUtil/DisableWarnings.h> #include <Slice/JavaUtil.h> #include <Slice/FileTracker.h> +#include <Slice/Util.h> #include <IceUtil/Functional.h> #include <IceUtil/DisableWarnings.h> @@ -371,25 +372,44 @@ Slice::JavaGenerator::convertScopedName(const string& scoped, const string& pref } string +Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont) const +{ + UnitPtr unit = cont->container()->unit(); + string file = cont->file(); + assert(!file.empty()); + + map<string, string>::const_iterator p = _filePackagePrefix.find(file); + if(p != _filePackagePrefix.end()) + { + return p->second; + } + + static const string prefix = "java:package:"; + DefinitionContextPtr dc = unit->findDefinitionContext(file); + assert(dc); + string q = dc->findMetaData(prefix); + if(!q.empty()) + { + q = q.substr(prefix.size()); + } + _filePackagePrefix[file] = q; + return q; +} + +string Slice::JavaGenerator::getPackage(const ContainedPtr& cont) const { string scope = convertScopedName(cont->scope()); - - DefinitionContextPtr dc = cont->definitionContext(); - if(dc) + string prefix = getPackagePrefix(cont); + if(!prefix.empty()) { - static const string prefix = "java:package:"; - string package = dc->findMetaData(prefix); - if(!package.empty()) + if(!scope.empty()) { - if(!scope.empty()) - { - return package.substr(prefix.size()) + "." + scope; - } - else - { - return package.substr(prefix.size()); - } + return prefix + "." + scope; + } + else + { + return prefix; } } @@ -550,6 +570,22 @@ Slice::JavaGenerator::typeToString(const TypePtr& type, } else { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string prefix = "java:serializable:"; + string meta; + if(seq->findMetaData(prefix, meta)) + { + return string("Ice.Holder<") + meta.substr(prefix.size()) + " >"; + } + prefix = "java:protobuf:"; + if(seq->findMetaData(prefix, meta)) + { + return string("Ice.Holder<") + meta.substr(prefix.size()) + " >"; + } + } + // // Only use the type's generated holder if the instance and // formal types match. @@ -594,6 +630,22 @@ Slice::JavaGenerator::typeToString(const TypePtr& type, } else { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string prefix = "java:serializable:"; + string meta; + if(seq->findMetaData(prefix, meta)) + { + return meta.substr(prefix.size()); + } + prefix = "java:protobuf:"; + if(seq->findMetaData(prefix, meta)) + { + return meta.substr(prefix.size()); + } + } + string instanceType, formalType; getSequenceTypes(seq, package, metaData, instanceType, formalType); return formal ? formalType : instanceType; @@ -1240,15 +1292,64 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode(Output& out, { string stream = marshal ? "__os" : "__is"; string v = param; + bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; + + // + // If the sequence is a byte sequence, check if there's the serializable or protobuf metadata to + // get rid of these two easy cases first. + // + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string meta; + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; + if(seq->findMetaData(serializable, meta)) + { + if(marshal) + { + out << nl << stream << ".writeSerializable(" << v << ");"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << v << " = (" << type << ")" << stream << ".readSerializable();"; + } + return; + } + else if(seq->findMetaData(protobuf, meta)) + { + if(marshal) + { + out << nl << "if(!" << v << ".isInitialized())"; + out << sb; + out << nl << "throw new Ice.MarshalException(\"type not fully initialized\");"; + out << eb; + out << nl << stream << ".writeByteSeq(" << v << ".toByteArray());"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << "try"; + out << sb; + out << nl << v << " = " << type << ".parseFrom(" << stream << ".readByteSeq());"; + out << eb; + out << nl << "catch(com.google.protobuf.InvalidProtocolBufferException __ex)"; + out << sb; + out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();"; + out << nl << "__mex.initCause(__ex);"; + out << nl << "throw __mex;"; + out << eb; + } + return; + } + } - bool java2 = false; bool customType = false; string instanceType; if(_featureProfile != Slice::IceE) { - java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; - // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal @@ -1299,7 +1400,7 @@ Slice::JavaGenerator::writeSequenceMarshalUnmarshalCode(Output& out, while(s) { // - // Stop if the inner sequence type has a custom type. + // Stop if the inner sequence type has a custom, serializable or protobuf type. // if(hasTypeMetaData(s) && _featureProfile != Slice::IceE) { @@ -2495,10 +2596,60 @@ Slice::JavaGenerator::writeStreamSequenceMarshalUnmarshalCode(Output& out, { string stream = marshal ? "__outS" : "__inS"; string v = param; - bool java2 = seq->definitionContext()->findMetaData(_java2MetaData) == _java2MetaData; // + // If the sequence is a byte sequence, check if there's the serializable or protobuf metadata to + // get rid of these two easy cases first. + // + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + string meta; + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; + if(seq->findMetaData(serializable, meta)) + { + if(marshal) + { + out << nl << stream << ".writeSerializable(" << v << ");"; + } + else + { + string type = typeToString(seq, TypeModeIn, package); + out << nl << v << " = (" << type << ")" << stream << ".readSerializable();"; + } + return; + } + else if(seq->findMetaData(protobuf, meta)) + { + if(marshal) + { + out << nl << "if(!" << v << ".isInitialized())"; + out << sb; + out << nl << "throw new Ice.MarshalException(\"type not fully initialized\");"; + out << eb; + out << nl << stream << ".writeByteSeq(" << v << ".toByteArray());"; + } + else + { + string type = meta.substr(protobuf.size()); + out << nl << "try"; + out << sb; + out << nl << v << " = " << type << ".parseFrom(" << stream << ".readByteSeq());"; + out << eb; + out << nl << "catch(com.google.protobuf.InvalidProtocolBufferException __ex)"; + out << sb; + out << nl << "Ice.MarshalException __mex = new Ice.MarshalException();"; + out << nl << "__mex.initCause(__ex);"; + out << nl << "throw __mex;"; + out << eb; + } + return; + } + } + + // // We have to determine whether it's possible to use the // type's generated helper class for this marshal/unmarshal // task. Since the user may have specified a custom type in @@ -2547,7 +2698,7 @@ Slice::JavaGenerator::writeStreamSequenceMarshalUnmarshalCode(Output& out, while(s) { // - // Stop if the inner sequence type has a custom type. + // Stop if the inner sequence type has a custom, serializable or protobuf type. // if(hasTypeMetaData(s)) { @@ -3144,6 +3295,18 @@ Slice::JavaGenerator::hasTypeMetaData(const TypePtr& type, const StringList& loc { return true; } + else if(str.find("java:protobuf:") == 0 || str.find("java:serializable:") == 0) + { + SequencePtr seq = SequencePtr::dynamicCast(cont); + if(seq) + { + BuiltinPtr builtin = BuiltinPtr::dynamicCast(seq->type()); + if(builtin && builtin->kind() == Builtin::KindByte) + { + return true; + } + } + } } } @@ -3391,51 +3554,62 @@ Slice::JavaGenerator::validateMetaData(const UnitPtr& u) } bool -Slice::JavaGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) +Slice::JavaGenerator::MetaDataVisitor::visitUnitStart(const UnitPtr& p) { + static const string prefix = "java:"; + // - // Validate global metadata. + // Validate global metadata in the top-level file and all included files. // - DefinitionContextPtr dc = p->definitionContext(); - assert(dc); - StringList globalMetaData = dc->getMetaData(); - string file = dc->filename(); - static const string prefix = "java:"; - for(StringList::const_iterator q = globalMetaData.begin(); q != globalMetaData.end(); ++q) + StringList files = p->allFiles(); + + for(StringList::iterator q = files.begin(); q != files.end(); ++q) { - string s = *q; - if(_history.count(s) == 0) + string file = *q; + DefinitionContextPtr dc = p->findDefinitionContext(file); + assert(dc); + StringList globalMetaData = dc->getMetaData(); + for(StringList::const_iterator r = globalMetaData.begin(); r != globalMetaData.end(); ++r) { - if(s.find(prefix) == 0) + string s = *r; + if(_history.count(s) == 0) { - bool ok = false; - - static const string packagePrefix = "java:package:"; - if(s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) - { - ok = true; - } - else if(s == _java2MetaData) + if(s.find(prefix) == 0) { - ok = true; - } - else if(s == _java5MetaData) - { - ok = true; - } + bool ok = false; - if(!ok) - { - cerr << file << ": warning: ignoring invalid global metadata `" << s << "'" << endl; + static const string packagePrefix = "java:package:"; + if(s.find(packagePrefix) == 0 && s.size() > packagePrefix.size()) + { + ok = true; + } + else if(s == _java2MetaData) + { + ok = true; + } + else if(s == _java5MetaData) + { + ok = true; + } + + if(!ok) + { + emitWarning(file, "", "ignoring invalid global metadata `" + s + "'"); + } } + _history.insert(s); } - _history.insert(s); } } + return true; +} +bool +Slice::JavaGenerator::MetaDataVisitor::visitModuleStart(const ModulePtr& p) +{ StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); return true; } @@ -3443,16 +3617,16 @@ void Slice::JavaGenerator::MetaDataVisitor::visitClassDecl(const ClassDeclPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } bool Slice::JavaGenerator::MetaDataVisitor::visitClassDefStart(const ClassDefPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); return true; } @@ -3460,8 +3634,8 @@ bool Slice::JavaGenerator::MetaDataVisitor::visitExceptionStart(const ExceptionPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); return true; } @@ -3469,8 +3643,8 @@ bool Slice::JavaGenerator::MetaDataVisitor::visitStructStart(const StructPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); return true; } @@ -3482,10 +3656,11 @@ Slice::JavaGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) ClassDefPtr cl = ClassDefPtr::dynamicCast(p->container()); if(!cl->isLocal()) { - cerr << p->definitionContext()->filename() << ":" << p->line() - << ": warning: metadata directive `UserException' applies only to local operations " - << "but enclosing " << (cl->isInterface() ? "interface" : "class") << "`" << cl->name() - << "' is not local" << endl; + ostringstream os; + os << "ignoring invalid metadata `UserException': directive applies only to local operations " + << "but enclosing " << (cl->isInterface() ? "interface" : "class") << " `" << cl->name() + << "' is not local"; + emitWarning(p->file(), p->line(), os.str()); } } StringList metaData = getMetaData(p); @@ -3498,15 +3673,15 @@ Slice::JavaGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) { if(q->find("java:type:", 0) == 0) { - cerr << p->definitionContext()->filename() << ":" << p->line() - << ": warning: invalid metadata for operation" << endl; + emitWarning(p->file(), p->line(), "ignoring invalid metadata `" + *q + + "' for operation with void return type"); break; } } } else { - validateType(returnType, metaData, p->definitionContext()->filename(), p->line()); + validateType(returnType, metaData, p->file(), p->line()); } } @@ -3514,62 +3689,86 @@ Slice::JavaGenerator::MetaDataVisitor::visitOperation(const OperationPtr& p) for(ParamDeclList::iterator q = params.begin(); q != params.end(); ++q) { metaData = getMetaData(*q); - validateType((*q)->type(), metaData, p->definitionContext()->filename(), (*q)->line()); + validateType((*q)->type(), metaData, p->file(), (*q)->line()); } - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitDataMember(const DataMemberPtr& p) { StringList metaData = getMetaData(p); - validateType(p->type(), metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p->type(), metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitSequence(const SequencePtr& p) { + static const string protobuf = "java:protobuf:"; + static const string serializable = "java:serializable:"; StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + const string file = p->file(); + const string line = p->line(); + for(StringList::const_iterator q = metaData.begin(); q != metaData.end(); ) + { + string s = *q++; + if(_history.count(s) == 0) // Don't complain about the same metadata more than once. + { + if(s.find(protobuf) == 0 || s.find(serializable) == 0) + { + // + // Remove from list so validateType does not try to handle as well. + // + metaData.remove(s); + + BuiltinPtr builtin = BuiltinPtr::dynamicCast(p->type()); + if(!builtin || builtin->kind() != Builtin::KindByte) + { + _history.insert(s); + emitWarning(file, line, "ignoring invalid metadata `" + s + "': " + + "this metadata can only be used with a byte sequence"); + } + } + } + } + + validateType(p, metaData, file, line); + validateGetSet(p, metaData, file, line); } void Slice::JavaGenerator::MetaDataVisitor::visitDictionary(const DictionaryPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitEnum(const EnumPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } void Slice::JavaGenerator::MetaDataVisitor::visitConst(const ConstPtr& p) { StringList metaData = getMetaData(p); - validateType(p, metaData, p->definitionContext()->filename(), p->line()); - validateGetSet(p, metaData, p->definitionContext()->filename(), p->line()); + validateType(p, metaData, p->file(), p->line()); + validateGetSet(p, metaData, p->file(), p->line()); } StringList Slice::JavaGenerator::MetaDataVisitor::getMetaData(const ContainedPtr& cont) { - StringList metaData = cont->getMetaData(); - DefinitionContextPtr dc = cont->definitionContext(); - assert(dc); - string file = dc->filename(); + static const string prefix = "java:"; + StringList metaData = cont->getMetaData(); StringList result; - static const string prefix = "java:"; for(StringList::const_iterator p = metaData.begin(); p != metaData.end(); ++p) { @@ -3596,8 +3795,18 @@ Slice::JavaGenerator::MetaDataVisitor::getMetaData(const ContainedPtr& cont) result.push_back(s); continue; } + else if(s.substr(prefix.size(), pos - prefix.size()) == "serializable") + { + result.push_back(s); + continue; + } + else if(s.substr(prefix.size(), pos - prefix.size()) == "protobuf") + { + result.push_back(s); + continue; + } - cerr << file << ":" << cont->line() << ": warning: ignoring invalid metadata `" << s << "'" << endl; + emitWarning(cont->file(), cont->line(), "ignoring invalid metadata `" + s + "'"); } _history.insert(s); @@ -3630,7 +3839,14 @@ Slice::JavaGenerator::MetaDataVisitor::validateType(const SyntaxTreeBasePtr& p, assert(b); str = b->typeId(); } - cerr << file << ":" << line << ": warning: invalid metadata for " << str << endl; + emitWarning(file, line, "invalid metadata for " + str); + } + else if(i->find("java:protobuf:") == 0 || i->find("java:serializable:") == 0) + { + // + // Only valid in sequence defintion which is checked in visitSequence + // + emitWarning(file, line, "ignoring invalid metadata `" + *i + "'"); } } } @@ -3660,7 +3876,7 @@ Slice::JavaGenerator::MetaDataVisitor::validateGetSet(const SyntaxTreeBasePtr& p assert(b); str = b->typeId(); } - cerr << file << ":" << line << ": warning: invalid metadata for " << str << endl; + emitWarning(file, line, "invalid metadata for " + str); } } } |