001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: ObjectType.java 468649 2006-10-28 07:00:55Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler.util;
023    
024    import org.apache.bcel.generic.ALOAD;
025    import org.apache.bcel.generic.ASTORE;
026    import org.apache.bcel.generic.BranchHandle;
027    import org.apache.bcel.generic.ConstantPoolGen;
028    import org.apache.bcel.generic.GOTO;
029    import org.apache.bcel.generic.IFNULL;
030    import org.apache.bcel.generic.INVOKEVIRTUAL;
031    import org.apache.bcel.generic.Instruction;
032    import org.apache.bcel.generic.InstructionList;
033    import org.apache.bcel.generic.PUSH;
034    import org.apache.xalan.xsltc.compiler.Constants;
035    
036    /**
037     * @author Todd Miller
038     * @author Santiago Pericas-Geertsen
039     */
040    public final class ObjectType extends Type {
041        
042        private String _javaClassName = "java.lang.Object";
043        private Class  _clazz = java.lang.Object.class;
044    
045        /**
046         * Used to represent a Java Class type such is required to support 
047         * non-static java functions. 
048         * @param javaClassName name of the class such as 'com.foo.Processor'
049         */
050        protected ObjectType(String javaClassName) {
051            _javaClassName = javaClassName;
052    
053            try {
054              _clazz = ObjectFactory.findProviderClass(
055                javaClassName, ObjectFactory.findClassLoader(), true);
056            }
057            catch (ClassNotFoundException e) {
058              _clazz = null;
059            }
060        }
061        
062        protected ObjectType(Class clazz) {
063            _clazz = clazz;
064            _javaClassName = clazz.getName();       
065        }
066        
067        /**
068         * Must return the same value for all ObjectType instances. This is
069         * needed in CastExpr to ensure the mapping table is used correctly.
070         */
071        public int hashCode() {
072            return java.lang.Object.class.hashCode();
073        }
074        
075        public boolean equals(Object obj) {
076            return (obj instanceof ObjectType);
077        }
078    
079        public String getJavaClassName() {
080            return _javaClassName;
081        }
082        
083        public Class getJavaClass() {
084            return _clazz;  
085        }
086    
087        public String toString() {
088            return _javaClassName;
089        }
090    
091        public boolean identicalTo(Type other) {
092            return this == other;
093        }
094    
095        public String toSignature() {
096            final StringBuffer result = new StringBuffer("L");
097            result.append(_javaClassName.replace('.', '/')).append(';');
098            return result.toString();
099        }
100    
101        public org.apache.bcel.generic.Type toJCType() {
102            return Util.getJCRefType(toSignature());
103        }
104    
105        /**
106         * Translates a void into an object of internal type <code>type</code>.
107         * This translation is needed when calling external functions
108         * that return void.
109         *
110         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
111         */
112        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
113                                Type type) {
114            if (type == Type.String) {
115                translateTo(classGen, methodGen, (StringType) type);
116            }
117            else {
118                ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
119                                            toString(), type.toString());
120                classGen.getParser().reportError(Constants.FATAL, err);
121            }
122        }
123    
124        /**
125         * Expects an integer on the stack and pushes its string value by calling
126         * <code>Integer.toString(int i)</code>.
127         *
128         * @see     org.apache.xalan.xsltc.compiler.util.Type#translateTo
129         */
130        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
131                                StringType type) {
132            final ConstantPoolGen cpg = classGen.getConstantPool();
133            final InstructionList il = methodGen.getInstructionList();
134    
135            il.append(DUP);
136            final BranchHandle ifNull = il.append(new IFNULL(null));
137            il.append(new INVOKEVIRTUAL(cpg.addMethodref(_javaClassName,
138                                                        "toString",
139                                                        "()" + STRING_SIG)));
140            final BranchHandle gotobh = il.append(new GOTO(null));
141            ifNull.setTarget(il.append(POP));
142            il.append(new PUSH(cpg, ""));
143            gotobh.setTarget(il.append(NOP));
144        }
145    
146        /**
147         * Translates an object of this type to the external (Java) type denoted
148         * by <code>clazz</code>. This method is used to translate parameters 
149         * when external functions are called.
150         */ 
151        public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 
152                                Class clazz) {
153            if (clazz.isAssignableFrom(_clazz))
154                methodGen.getInstructionList().append(NOP);
155            else {
156                ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
157                                   toString(), clazz.getClass().toString());
158                classGen.getParser().reportError(Constants.FATAL, err);             
159            }
160        }
161            
162        /**
163         * Translates an external Java type into an Object type 
164         */
165        public void translateFrom(ClassGenerator classGen, 
166                                  MethodGenerator methodGen, Class clazz) {
167            methodGen.getInstructionList().append(NOP);
168        }
169    
170        public Instruction LOAD(int slot) {
171            return new ALOAD(slot);
172        }
173            
174        public Instruction STORE(int slot) {
175            return new ASTORE(slot);
176        }
177    }