001: /*
002: Copyright (c) 2003-2005, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.binding.classes;
030:
031: import org.apache.bcel.Constants;
032: import org.apache.bcel.generic.*;
033: import org.jibx.runtime.JiBXException;
034:
035: /**
036: * Unmarshalling method builder. Tracks the creation of an unmarshalling method,
037: * including special handling of exceptions that may be generated by object
038: * accesses during the unmarshalling process.
039: *
040: * @author Dennis M. Sosnoski
041: * @version 1.0
042: */
043:
044: public class UnmarshalBuilder extends MarshalUnmarshalBuilder {
045: //
046: // Constants for code generation.
047:
048: private static final String UNMARSHALCONTEXT_CLASS = "org.jibx.runtime.impl.UnmarshallingContext";
049: protected static final String UNMARSHAL_EXCEPTION_TEXT = "Error while unmarshalling ";
050: protected static final String UNMARSHALLING_POSITION_METHOD = "org.jibx.runtime.impl.UnmarshallingContext.buildPositionString";
051: protected static final String UNMARSHALLING_POSITION_SIGNATURE = "()Ljava/lang/String;";
052: protected static final Type[] UNMARSHAL_METHOD_ARGS = { new ObjectType(
053: "org.jibx.runtime.impl.UnmarshallingContext") };
054: protected static final Type[] SINGLE_STRING_ARGS = { Type.STRING };
055:
056: /**
057: * Constructor. This sets up for constructing a virtual unmarshalling method
058: * with public access and wrapped exception handling. If the method is being
059: * generated directly to the class being unmarshalled it's built as a
060: * virtual method; otherwise, it's done as a static method.
061: *
062: * @param name method name to be built
063: * @param cf unmarshal class file information
064: * @param mf method generation class file information
065: * @throws JiBXException on error in initializing method construction
066: */
067:
068: public UnmarshalBuilder(String name, ClassFile cf, ClassFile mf)
069: throws JiBXException {
070: super (name, cf.getType(),
071: (mf == cf) ? UNMARSHAL_METHOD_ARGS : new Type[] {
072: cf.getType(), UNMARSHAL_METHOD_ARGS[0] }, mf,
073: (mf == cf) ? Constants.ACC_PUBLIC | Constants.ACC_FINAL
074: : Constants.ACC_PUBLIC | Constants.ACC_STATIC,
075: 0, cf.getName(), 1, UNMARSHALCONTEXT_CLASS);
076: }
077:
078: /**
079: * Add exception handler code. The implementation of this abstract base
080: * class method provides handling specific to an unmarshalling method.
081: *
082: * @return handle for first instruction in handler
083: * @throws JiBXException on error in creating exception handler
084: */
085:
086: public InstructionHandle genExceptionHandler() throws JiBXException {
087:
088: // first part of instruction sequence is create new exception object,
089: // duplicate two down (below caught exception), swap (so order is new,
090: // new, caught)
091: initStackState(new String[] { "java.lang.Exception" });
092: InstructionHandle start = internalAppendCreateNew(FRAMEWORK_EXCEPTION_CLASS);
093: appendDUP_X1();
094: appendSWAP();
095:
096: // second part of sequence is build StringBuffer, duplicate, load lead
097: // String, call constructor with String argument, load unmarshalling
098: // context, call position String method, call StringBuffer append,
099: // call StringBuffer toString
100: appendCreateNew("java.lang.StringBuffer");
101: appendDUP();
102: appendLoadConstant(UNMARSHAL_EXCEPTION_TEXT);
103: appendCallInit("java.lang.StringBuffer",
104: "(Ljava/lang/String;)V");
105: loadContext();
106: appendCallVirtual(UNMARSHALLING_POSITION_METHOD,
107: UNMARSHALLING_POSITION_SIGNATURE);
108: appendCallVirtual("java.lang.StringBuffer.append",
109: "(Ljava/lang/String;)Ljava/lang/StringBuffer;");
110: appendCallVirtual("java.lang.StringBuffer.toString",
111: "()Ljava/lang/String;");
112:
113: // final part of sequence is swap to get arguments in correct order,
114: // invoke exception constructor, throw exception
115: appendSWAP();
116: appendCallInit(FRAMEWORK_EXCEPTION_CLASS,
117: EXCEPTION_CONSTRUCTOR_SIGNATURE2);
118: appendThrow();
119: return start;
120: }
121: }
|