From c10eb2c17b46be4b8ce9e1014757f17a5d4a23b7 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Mon, 11 Oct 2010 01:30:42 +0900 Subject: java: add the code for checking a null pointer to DynamicCodeGen.java --- .../java/org/msgpack/util/codegen/Constants.java | 24 +++++--- .../org/msgpack/util/codegen/DynamicCodeGen.java | 51 ++++++++++------- .../msgpack/util/codegen/DynamicCodeGenBase.java | 65 ++++++++++++++++++++-- 3 files changed, 106 insertions(+), 34 deletions(-) (limited to 'java/src/main') diff --git a/java/src/main/java/org/msgpack/util/codegen/Constants.java b/java/src/main/java/org/msgpack/util/codegen/Constants.java index e61f039..e32e6ad 100644 --- a/java/src/main/java/org/msgpack/util/codegen/Constants.java +++ b/java/src/main/java/org/msgpack/util/codegen/Constants.java @@ -207,21 +207,27 @@ public interface Constants { String STATEMENT_PACKER_PACKERMETHODBODY_04 = "$1.pack(((java.lang.Enum)_$$_t).ordinal()); "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_01 = "%s _$$_t = new %s(); "; + String STATEMENT_PACKER_PACKERMETHODBODY_05 = "if (_$$_nullCheck && $2 == null) { $1.packNil(); return; } "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_02 = "$1.unpackArray(); "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_01 = "%s _$$_t = new %s(); "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_03 = "_$$_t.%s = %s(%s)_$$_templates[%d].unpack($1)%s; "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_02 = "$1.unpackArray(); "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_04 = "return _$$_t; "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_03 = "if (!_$$_nullCheck || !$1.tryUnpackNull()) { _$$_t.%s = %s(%s)_$$_templates[%d].unpack($1)%s; } "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_05 = "int i = $1.unpackInt(); "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_04 = "return _$$_t; "; - String STATEMENT_PACKER_UNPACKERMETHODBODY_06 = "return %s.class.getEnumConstants()[i]; "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_05 = "int i = $1.unpackInt(); "; - String STATEMENT_PACKER_CONVERTMETHODBODY_01 = "%s _$$_ary = $1.asArray(); "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_06 = "return %s.class.getEnumConstants()[i]; "; - String STATEMENT_PACKER_CONVERTMETHODBODY_02 = "_$$_t.%s = %s(%s)_$$_templates[%d].convert(_$$_ary[%d])%s; "; + String STATEMENT_TMPL_UNPACKERMETHODBODY_07 = "if (_$$_nullCheck && $1.tryUnpackNull()) { return null; } "; - String STATEMENT_PACKER_CONVERTMETHODBODY_03 = "int i = _$$_ary[0].asInt(); "; + String STATEMENT_TMPL_CONVERTMETHODBODY_01 = "%s _$$_ary = $1.asArray(); "; + + String STATEMENT_TMPL_CONVERTMETHODBODY_02 = "if (!_$$_nullCheck || !_$$_ary[%d].isNil()) { _$$_t.%s = %s(%s)_$$_templates[%d].convert(_$$_ary[%d])%s; } "; + + String STATEMENT_TMPL_CONVERTMETHODBODY_03 = "int i = _$$_ary[0].asInt(); "; + + String STATEMENT_TMPL_CONVERTMETHODBODY_04 = "if (_$$_nullCheck && $1.isNil()) { return null; } "; } diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java index 3954f17..9ba7ec6 100644 --- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java +++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGen.java @@ -72,6 +72,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { checkTypeValidation(origClass); checkDefaultConstructorValidation(origClass); CtClass packerCtClass = pool.makeClass(packerName); + setSuperclass(packerCtClass, NullCheckerImpl.class); setInterface(packerCtClass, MessagePacker.class); addDefaultConstructor(packerCtClass); Field[] fields = getDeclaredFields(origClass); @@ -96,6 +97,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { String packerName = origName + POSTFIX_TYPE_NAME_PACKER + inc(); checkTypeValidation(origClass); CtClass packerCtClass = pool.makeClass(packerName); + setSuperclass(packerCtClass, NullCheckerImpl.class); setInterface(packerCtClass, MessagePacker.class); addDefaultConstructor(packerCtClass); addPackMethod(packerCtClass, origClass, null, true); @@ -120,14 +122,12 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { checkTypeValidation(origClass); checkDefaultConstructorValidation(origClass); CtClass tmplCtClass = pool.makeClass(tmplName); + setSuperclass(tmplCtClass, TemplateTemplate.class); setInterface(tmplCtClass, Template.class); - setInterface(tmplCtClass, DynamicCodeGenBase.TemplateAccessor.class); addDefaultConstructor(tmplCtClass); Field[] fields = getDeclaredFields(origClass); Template[] tmpls = createTemplates(fields); setTemplates(origClass, tmpls); - addTemplateArrayField(tmplCtClass); - addSetTemplatesMethod(tmplCtClass); addUnpackMethod(tmplCtClass, origClass, fields, false); addConvertMethod(tmplCtClass, origClass, fields, false); Class tmplClass = createClass(tmplCtClass); @@ -154,11 +154,11 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { checkTypeValidation(origClass); String tmplName = origName + POSTFIX_TYPE_NAME_TEMPLATE + inc(); CtClass tmplCtClass = pool.makeClass(tmplName); + setSuperclass(tmplCtClass, TemplateTemplate.class); setInterface(tmplCtClass, Template.class); addDefaultConstructor(tmplCtClass); addUnpackMethod(tmplCtClass, origClass, null, true); addConvertMethod(tmplCtClass, origClass, null, true); - // addConvertMethodForOrdinalEnumTypes(tmplCtClass, origClass); Class tmplClass = createClass(tmplCtClass); LOG.debug("generated an enum template class for " + origClass.getName()); @@ -218,7 +218,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { checkFieldValidation(field, allFields); allFields.add(field); } catch (DynamicCodeGenException e) { // ignore - LOG.error(e.getMessage(), e); + LOG.trace(e.getMessage(), e); } } nextClass = nextClass.getSuperclass(); @@ -299,6 +299,8 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { // void pack(Packer packer, Object target) throws IOException; sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); sb.append(CHAR_NAME_SPACE); + Object[] args2 = new Object[0]; + sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_05, args2)); String typeName = classToString(type); Object[] args0 = new Object[] { typeName, typeName }; sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_01, args0)); @@ -357,6 +359,8 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { // void pack(Packer packer, Object target) throws IOException; sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); sb.append(CHAR_NAME_SPACE); + Object[] args3 = new Object[0]; + sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_05, args3)); String typeName = classToString(c); Object[] args0 = new Object[] { typeName, typeName }; sb.append(String.format(STATEMENT_PACKER_PACKERMETHODBODY_01, args0)); @@ -410,15 +414,17 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { sb.append(CHAR_NAME_SPACE); // Foo _$$_t = new Foo(); String typeName = classToString(type); + Object[] args3 = new Object[0]; + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_07, args3)); Object[] args0 = new Object[] { typeName, typeName }; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_01, args0)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_01, args0)); // $1.unpackArray(); Object[] args1 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_02, args1)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_02, args1)); insertCodeOfUnpackMethodCalls(sb, fields); // return _$$_t; Object[] args2 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_04, args2)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_04, args2)); sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); } @@ -441,7 +447,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { i, isPrim ? ")." + getPrimTypeValueMethodName(returnType) + "()" : "" }; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_03, args)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_03, args)); } private void insertCodeOfUnpackMethodCallForMsgUnpackableType( @@ -499,15 +505,17 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { // Object unpack(Unpacker u) throws IOException, MessageTypeException; sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); sb.append(CHAR_NAME_SPACE); + Object[] args3 = new Object[0]; + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_07, args3)); // $1.unpackArray(); Object[] args0 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_02, args0)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_02, args0)); // int i = $1.unapckInt(); Object[] args1 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_05, args1)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_05, args1)); // return Foo.class.getEnumConstants()[i]; Object[] args2 = new Object[] { classToString(type) }; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_06, args2)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_06, args2)); sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); } @@ -550,17 +558,19 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { // Object convert(MessagePackObject mpo) throws MessageTypeException; sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); sb.append(CHAR_NAME_SPACE); + Object[] args3 = new Object[0]; + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_04, args3)); // Foo _$$_t = new Foo(); String typeName = classToString(type); Object[] args0 = new Object[] { typeName, typeName }; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_01, args0)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_01, args0)); // MessagePackObject[] _$$_ary = $1.asArray(); Object[] args1 = new Object[] { classToString(MessagePackObject[].class) }; - sb.append(String.format(STATEMENT_PACKER_CONVERTMETHODBODY_01, args1)); + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_01, args1)); insertCodeOfConvertMethodCalls(sb, fields); // return _$$_t; Object[] args2 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_04, args2)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_04, args2)); sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); } @@ -575,6 +585,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { Class returnType = field.getType(); boolean isPrim = returnType.isPrimitive(); Object[] args = new Object[] { + i, field.getName(), isPrim ? "(" : "", isPrim ? getPrimToWrapperType(returnType).getName() @@ -583,7 +594,7 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { i, isPrim ? ")." + getPrimTypeValueMethodName(returnType) + "()" : "" }; - sb.append(String.format(STATEMENT_PACKER_CONVERTMETHODBODY_02, args)); + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_02, args)); } private void insertCodeOfMessageConvertCallForMsgConvtblType( @@ -640,15 +651,17 @@ class DynamicCodeGen extends DynamicCodeGenBase implements Constants { // Object convert(MessagePackObject mpo) throws MessageTypeException; sb.append(CHAR_NAME_LEFT_CURLY_BRACKET); sb.append(CHAR_NAME_SPACE); + Object[] args3 = new Object[0]; + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_04, args3)); // MessagePackObject[] _$$_ary = $1.asArray(); Object[] args0 = new Object[] { classToString(MessagePackObject[].class) }; - sb.append(String.format(STATEMENT_PACKER_CONVERTMETHODBODY_01, args0)); + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_01, args0)); // int i = _$$_ary[0].asInt(); Object[] args1 = new Object[0]; - sb.append(String.format(STATEMENT_PACKER_CONVERTMETHODBODY_03, args1)); + sb.append(String.format(STATEMENT_TMPL_CONVERTMETHODBODY_03, args1)); // return Foo.class.getEnumConstants()[i]; Object[] args2 = new Object[] { classToString(type) }; - sb.append(String.format(STATEMENT_PACKER_UNPACKERMETHODBODY_06, args2)); + sb.append(String.format(STATEMENT_TMPL_UNPACKERMETHODBODY_06, args2)); sb.append(CHAR_NAME_RIGHT_CURLY_BRACKET); } } diff --git a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java index 4bfea8c..0f39427 100644 --- a/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java +++ b/java/src/main/java/org/msgpack/util/codegen/DynamicCodeGenBase.java @@ -32,11 +32,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DynamicCodeGenBase implements Constants { + + public static interface NullChecker { + void setNullCheck(boolean nullCheck); + } + + public static class NullCheckerImpl implements NullChecker { + public boolean _$$_nullCheck = true; + + public void setNullCheck(boolean _$$_check) { + _$$_nullCheck = _$$_check; + } + } + public static interface TemplateAccessor { void setTemplates(Template[] templates); } - - public static class TemplateAccessorImpl implements TemplateAccessor { + + public static class TemplateTemplate extends NullCheckerImpl implements TemplateAccessor { public Template[] _$$_templates; public void setTemplates(Template[] _$$_tmpls) { @@ -111,10 +124,50 @@ public class DynamicCodeGenBase implements Constants { throw e; } - protected void setInterface(CtClass packerCtClass, Class infClass) + enum Color { + // TODO + RED, BLUE + } + + public static void main(String[] args) throws Exception { + // TODO + class Foo { + } + class Bar extends Foo { + } + Color c = Color.RED; + Color c1 = null; + + ClassPool pool = ClassPool.getDefault(); + CtClass barCtClass = pool.get(Bar.class.getName()); + CtClass sbarCtClass = barCtClass.getSuperclass(); + System.out.println("bar: " + sbarCtClass.getName()); + CtClass fooCtClass = pool.get(Foo.class.getName()); + CtClass sfooCtClass = fooCtClass.getSuperclass(); + System.out.println("foo: " + sfooCtClass.getName()); + } + + protected void setSuperclass(CtClass newCtClass, Class superClass) + throws NotFoundException, CannotCompileException { + // check the specified super class + if (superClass.isInterface() || superClass.isEnum() + || superClass.isAnnotation() || superClass.isArray() + || superClass.isPrimitive()) { + throwTypeValidationException(superClass, "Fatal error"); + } + + // check the base class + if (!newCtClass.getSuperclass().equals(classToCtClass(Object.class))) { + throwTypeValidationException(superClass, "Fatal error"); + } + CtClass superCtClass = pool.get(superClass.getName()); + newCtClass.setSuperclass(superCtClass); + } + + protected void setInterface(CtClass newCtClass, Class infClass) throws NotFoundException { CtClass infCtClass = pool.get(infClass.getName()); - packerCtClass.addInterface(infCtClass); + newCtClass.addInterface(infCtClass); } protected void addDefaultConstructor(CtClass enhancedCtClass) @@ -126,7 +179,7 @@ public class DynamicCodeGenBase implements Constants { protected void addTemplateArrayField(CtClass newCtClass) throws NotFoundException, CannotCompileException { - CtClass acsCtClass = pool.get(TemplateAccessorImpl.class.getName()); + CtClass acsCtClass = pool.get(TemplateTemplate.class.getName()); CtField tmplsField = acsCtClass .getDeclaredField(VARIABLE_NAME_TEMPLATES); CtField tmplsField2 = new CtField(tmplsField.getType(), tmplsField @@ -136,7 +189,7 @@ public class DynamicCodeGenBase implements Constants { protected void addSetTemplatesMethod(CtClass newCtClass) throws NotFoundException, CannotCompileException { - CtClass acsCtClass = pool.get(TemplateAccessorImpl.class.getName()); + CtClass acsCtClass = pool.get(TemplateTemplate.class.getName()); CtMethod settmplsMethod = acsCtClass .getDeclaredMethod(METHOD_NAME_SETTEMPLATES); CtMethod settmplsMethod2 = CtNewMethod.copy(settmplsMethod, newCtClass, -- cgit v1.2.1