[prev in list] [next in list] [prev in thread] [next in thread]
List: xmlbeans-dev
Subject: [jira] Updated: (XMLBEANS-207) Big issue with bad validation of interfaces when .xsdconfig file is u
From: "Denis Anisimov (JIRA)" <xmlbeans-dev () xml ! apache ! org>
Date: 2005-09-26 13:51:05
Message-ID: 246974971.1127742665872.JavaMail.jira () ajax ! apache ! org
[Download RAW message or body]
[ http://issues.apache.org/jira/browse/XMLBEANS-207?page=all ]
Denis Anisimov updated XMLBEANS-207:
------------------------------------
Attachment: InterfaceExtensionImpl.java
> Big issue with bad validation of interfaces when .xsdconfig file is used
> ------------------------------------------------------------------------
>
> Key: XMLBEANS-207
> URL: http://issues.apache.org/jira/browse/XMLBEANS-207
> Project: XMLBeans
> Type: Bug
> Components: Compiler
> Versions: Version 2
> Reporter: Denis Anisimov
> Attachments: InterfaceExtensionImpl.java, SchemaTypeCodePrinter.java, \
> SchemaTypeImpl.java, SchemaTypeSystemCompiler.java
> The main problem here is inside InterfaceExtensionImpl when methods \
> validateMethods() and validateMethod() are called. The perform validation against \
> just interface without any knowing of bean schema class which will be used for \
> extention. Lets imagine the situation when schema have type "tOne" and "tTwo" and \
> "tTwo" extends "tOne" <complexType name="tTwo">
> <complexContent>
> <extension base="tOne"/>
> </complexContent>
> </complexType>
> In this case generated bean TOne will extends TTwo.
> I want to create extention for TOne and TTwo. I want: TOne extends interface \
> First, TTwo extends interface Second. But also I want to keep original schema \
> hierarchy , so I want also interface Second extends First. Original implementation \
> doesn't allow to me handle this situation : see bug \
> http://issues.apache.org/jira/browse/XMLBEANS-205. If this bug will be resolved \
> then anyway I will need to create corresponding methods in SecondHandler methods \
> that will be responsible for delegation methods from First interface because all \
> methods in First interface also exist in Second. BUT TTwo already extends TOne and \
> I don't need to create static methods for delegation them from First interface. \
> They already exists in TTwo because it originally extends TOne. And those methods \
> delegated already in handler for First. But configuration file knows nothing about \
> schema extentions and validate methiods just against handlers and interfaces as \
> couple. So we have the problem. I suggest some changes in \
> InterfaceExtensionImpl.java, SchemaTypeImpl.java, SchemaTypeSystemCompiler.java. \
> Possibly this is not best fix but it works and more appropriate fix wil need \
> changes in architecture...... ( I suggest that bug \
> http://issues.apache.org/jira/browse/XMLBEANS-205 already fixed as described ) ( \
> changes marked with "!" ) changes in SchemaTypeSystemCompiler.java :
> public static boolean generateTypes(SchemaTypeSystem system, Filer filer, \
> XmlOptions options) {
> // partial type systems not allowed to be saved
> if (system instanceof SchemaTypeSystemImpl && \
> ((SchemaTypeSystemImpl)system).isIncomplete()) return false;
>
> boolean success = true;
> List types = new ArrayList();
> types.addAll(Arrays.asList(system.globalTypes()));
> types.addAll(Arrays.asList(system.documentTypes()));
> types.addAll(Arrays.asList(system.attributeTypes()));
> for (Iterator i = types.iterator(); i.hasNext(); )
> {
> SchemaType type = (SchemaType)i.next();
> if (type.isBuiltinType())
> continue;
> if (type.getFullJavaName() == null)
> continue;
> String fjn = type.getFullJavaName();
> Writer writer = null;
>
> ! // here we perform validation for interfaces that should extends
> ! // this type. We check whether all methods in interfaces will be
> ! // present or some methods will be present in supertype, in this case
> ! // this also Ok.
> ! if (!((SchemaTypeImpl)type).validateMethods() ){
> ! System.err.println("Was found unimplemented methods. See above \
> information");
> ! return false;
> !
> ! }
> try
> {
> // Generate interface class
> writer = filer.createSourceFile(fjn);
> SchemaTypeCodePrinter.printType(writer, type, options);
> }
> catch (IOException e)
> {
> System.err.println("IO Error " + e);
> success = false;
> }
> finally {
> try { if (writer != null) writer.close(); } catch (IOException e) {}
> }
> try
> {
> // Generate Implementation class
> fjn = type.getFullJavaImplName();
> writer = filer.createSourceFile(fjn);
> SchemaTypeCodePrinter.printTypeImpl(writer, type, options);
> }
> catch (IOException e)
> {
> System.err.println("IO Error " + e);
> success = false;
> }
> finally {
> try { if (writer != null) writer.close(); } catch (IOException e) {}
> }
> }
> return success;
> }
> This block is new in SchemaTypeImpl.java :
> /**
> * This method should be called instead of \
> <code>InterfaceExtension.validateMethods()</code>
> * for validation interfaces for THIS type.
> * The reason why <code>InterfaceExtension.validateMethods()</code> is bad :
> * methods from interface can be already implemented in base type. So
> * we don't need to implement them .
> */
> public boolean validateMethods(){
> InterfaceExtension[] extension = getInterfaceExtensions();
> for (int i = 0; i < extension.length; i++) {
> if ( !validateMethods( (InterfaceExtensionImpl)extension[i])) {
> return false;
> }
> }
> return true;
> }
>
> private boolean validateMethods(InterfaceExtensionImpl extensionImpl) {
> InterfaceExtension.MethodSignature[] methods = extensionImpl.getAbsentMethods();
> InterfaceExtension.MethodSignature[] inherited = getAllInheritedMethods();
> for (int i = 0; i < methods.length; i++) {
> InterfaceExtension.MethodSignature method = methods[i];
> boolean flag = false;
> for (int j = 0; j < inherited.length; j++) {
> if ( extensionImpl.equals( method, inherited[j])){
> flag = true;
> }
> }
> if ( !flag ){
> extensionImpl.error( method );
> return false;
> }
> }
> return true;
> }
>
> private InterfaceExtension.MethodSignature[] getAllInheritedMethods(){
> List list = new LinkedList();
> SchemaType type = getBaseType();
> while ( type!= null ){
> if (type instanceof SchemaTypeImpl) {
> SchemaTypeImpl typeImpl = (SchemaTypeImpl) type;
> InterfaceExtension[] extensions = typeImpl.getInterfaceExtensions();
> if (extensions != null) {
> for (int i = 0; i < extensions.length; i++) {
> list.addAll(Arrays.asList(extensions[i].getMethods()));
> }
> }
> }
> type = type.getBaseType();
> }
>
> return (InterfaceExtension.MethodSignature[])
> list.toArray( new InterfaceExtension.MethodSignature[list.size()]);
> }
> Changes in InterfaceExtensionImpl.java :
> New attributes :
> private List myNotFoundMethods = new LinkedList();
> private XmlObject myXMLObject ;
> Inside method : static InterfaceExtensionImpl newInstance(JamClassLoader loader, \
> NameSet xbeanSet, Extensionconfig.Interface intfXO)
> result.myXMLObject = intfXO;
> Changed block ( three new methods and changed old methods validateMethod() and \
> validateMethods():
> public void error( MethodSignature signature){
> BindingConfigImpl.error("Handler class '" +
> _delegateToClassName + "' does not contain method " +
> ((MethodSignatureImpl)signature).getSignature(),
> myXMLObject);
> }
>
> /**
> * This method perform "light" comparison for two methods signature
> * based only on methods names and signatures. Real comperison in
> * MethodSignatureImpl perform also checking for outer class name.
> * @param method1
> * @param method2
> * @return
> */
> public boolean equals( InterfaceExtension.MethodSignature method1 ,
> InterfaceExtension.MethodSignature method2 ){
>
> return ( (MethodSignatureImpl)method1).lightEqual( method2 );
> }
>
> /**
> * Changed - will always return true.
> * This is incorrect place for determining correctness of interface.
> * Validation logic is moved into SchemaTypeImpl.validateMethods()
> * @param interfaceJClass
> * @param delegateJClass
> * @param loc
> * @return
> */
> private boolean validateMethods(JClass interfaceJClass, JClass delegateJClass, \
> XmlObject loc) {
> //assert _delegateToClass != null : "Delegate to class handler expected.";
> boolean valid = true;
> JMethod[] interfaceMethods = interfaceJClass.getMethods();
> List list = new LinkedList();
> //_methods = new MethodSignatureImpl[interfaceMethods.length];
> for (int i = 0; i < interfaceMethods.length; i++)
> {
> JMethod method;
> try {
> method = validateMethod(interfaceJClass, delegateJClass, interfaceMethods[i], \
> loc); if (method != null) {
> //_methods[i] = new MethodSignatureImpl(getStaticHandler(), \
> method);
> list.add(new MethodSignatureImpl(getStaticHandler(), method));
> }
> else {
> valid = false;
> }
> }
> catch (MethodNotFoundException e) {
> // we didn't find method. If method was not found in static handler
> // by name and signature - then it was placed in myNotFoundMethods list.
> // in this case validation will be performed later. And we don't
> // get this exception. But if method was actually found in handler,
> // but its return type or exceptions that it can throws is not
> // the same as declared in interface then we got this exception
> // and we should stop.
> return false;
> }
> }
> _methods = (MethodSignatureImpl[])list.toArray( new MethodSignatureImpl[ \
> list.size()] ); //return valid;
> return true;
> }
> /**
> * Changed.
> * Incorrect place for decision about valid method.
> * Validation logic is moved into SchemaTypeImpl.validateMethods()
> * @param interfaceJClass
> * @param delegateJClass
> * @param method
> * @param loc
> * @return
> */
> private JMethod validateMethod(JClass interfaceJClass, JClass delegateJClass, \
> JMethod method, XmlObject loc) throws MethodNotFoundException {
> String methodName = method.getSimpleName();
> JParameter[] params = method.getParameters();
> JClass returnType = method.getReturnType();
> JClass[] delegateParams = new JClass[params.length+1];
> delegateParams[0] = returnType.forName("org.apache.xmlbeans.XmlObject");
> for (int i = 1; i < delegateParams.length; i++)
> {
> delegateParams[i] = params[i-1].getType();
> }
> JMethod handlerMethod = null;
> handlerMethod = getMethod(delegateJClass, methodName, delegateParams);
> if (handlerMethod==null)
> {
> MethodSignatureImpl signature = new MethodSignatureImpl( "", method);
> myNotFoundMethods.add( signature );
> // BindingConfigImpl.error("Handler class '" + \
> delegateJClass.getQualifiedName() + "' does not contain method " + methodName + "(" \
> + listTypes(delegateParams) + ")", loc); return null;
> }
> // check for throws exceptions
> JClass[] intfExceptions = method.getExceptionTypes();
> JClass[] delegateExceptions = handlerMethod.getExceptionTypes();
> if ( delegateExceptions.length!=intfExceptions.length )
> {
> BindingConfigImpl.error("Handler method '" + delegateJClass.getQualifiedName() + \
> "." + methodName + "(" + listTypes(delegateParams) + ")' must declare the same \
> exceptions as the interface method '" + interfaceJClass.getQualifiedName() + "." + \
> methodName + "(" + listTypes(params), loc); throw new MethodNotFoundException();
> //return null;
> }
> for (int i = 0; i < delegateExceptions.length; i++)
> {
> if ( delegateExceptions[i]!=intfExceptions[i] )
> {
> BindingConfigImpl.error("Handler method '" + delegateJClass.getQualifiedName() + \
> "." + methodName + "(" + listTypes(delegateParams) + ")' must declare the same \
> exceptions as the interface method '" + interfaceJClass.getQualifiedName() + "." + \
> methodName + "(" + listTypes(params), loc); throw new MethodNotFoundException();
> //return null;
> }
> }
> if (!handlerMethod.isPublic() || !handlerMethod.isStatic())
> {
> BindingConfigImpl.error("Method '" + delegateJClass.getQualifiedName() + "." + \
> methodName + "(" + listTypes(delegateParams) + ")' must be declared public and \
> static.", loc); throw new MethodNotFoundException();
> //return null;
> }
> if (!returnType.equals(handlerMethod.getReturnType()))
> {
> BindingConfigImpl.error("Return type for method '" + handlerMethod.getReturnType() \
> + " " + delegateJClass.getQualifiedName() + "." + methodName + "(" + \
> listTypes(delegateParams) + ")' does not match the return type of the interface \
> method :'" + returnType + "'.", loc); throw new MethodNotFoundException();
> //return null;
> }
> return method;
> }
> public InterfaceExtensionImpl.MethodSignatureImpl[] getAbsentMethods(){
> return (InterfaceExtensionImpl.MethodSignatureImpl[])
> myNotFoundMethods.toArray(
> new InterfaceExtensionImpl.MethodSignatureImpl[myNotFoundMethods.size()]);
> }
>
>
> /**
> * This exception will be thrown if method was FOUND in handler
> * via name and signature but it have wrong return type, exceptions that
> * can be thrown , etc.
> * @author ads
> *
> */
> private class MethodNotFoundException extends Exception{
>
> }
> I can also send all these changed java files .
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: dev-help@xmlbeans.apache.org
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic