001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.com;
020
021import java.lang.reflect.Method;
022
023import lucee.commons.lang.ExceptionUtil;
024import lucee.runtime.exp.ExpressionException;
025import lucee.runtime.op.Caster;
026import lucee.runtime.type.ArrayImpl;
027import lucee.runtime.type.dt.DateTimeImpl;
028
029import com.jacob.com.Variant;
030
031/**
032 * 
033 */
034public final class COMUtil {
035        
036
037    /**
038     * translate a Variant Object to Object, when it is a Dispatch translate it to COMWrapper
039     * @param parent 
040     * @param variant
041     * @param key
042     * @return Object from Variant
043     */
044    public static Object toObject(COMObject parent, Variant variant, String key, Object defaultValue) {
045        try {
046                return toObject(parent, variant,key);
047        }
048        catch(ExpressionException ee) {
049            return defaultValue;
050        }
051    }
052    
053    /**
054     * translate a Variant Object to Object, when it is a Dispatch translate it to COMWrapper
055     * @param parent
056     * @param variant
057     * @param key
058     * @return Object from Variant
059     * @throws ExpressionException
060     */
061    public static Object toObject(COMObject parent,Variant variant, String key) throws ExpressionException {
062        short type=variant.getvt();
063        //print.ln(key+" -> variant.getvt("+toStringType(type)+")");
064                
065                /*
066                TODO impl this
067                Variant.VariantByref;
068                Variant.VariantError;
069                Variant.VariantTypeMask;
070                */
071                
072                
073                if(type==Variant.VariantEmpty) return null;
074                else if(type==Variant.VariantNull) return null;
075                else if(type==Variant.VariantShort) return Short.valueOf(variant.getShort());
076                else if(type==Variant.VariantInt) return Integer.valueOf(variant.getInt());
077                else if(type==Variant.VariantFloat) return new Float(variant.getFloat());
078                else if(type==Variant.VariantDouble) return new Double(variant.getDouble());
079                else if(type==Variant.VariantCurrency) {
080                        long l;
081                        try{
082                                l=variant.getCurrency().longValue();
083                        }
084                        // this reflection allows support for old and new jacob version
085                        catch(Throwable t){
086                ExceptionUtil.rethrowIfNecessary(t);
087                                try{
088                                        Method toCurrency = variant.getClass().getMethod("toCurrency", new Class[0]);
089                                        Object curreny = toCurrency.invoke(variant, new Object[0]);
090                                        
091                                        Method longValue = curreny.getClass().getMethod("longValue", new Class[0]);
092                                        l=Caster.toLongValue(longValue.invoke(curreny, new Object[0]),0);
093                                }
094                                catch(Throwable t2){
095                        ExceptionUtil.rethrowIfNecessary(t2);
096                                        l=0;
097                                }
098                        }
099                        return Long.valueOf(l);
100                }
101                else if(type==Variant.VariantObject) return variant.toEnumVariant();
102                else if(type==Variant.VariantDate) return new DateTimeImpl((long)variant.getDate(),true);
103                else if(type==Variant.VariantString) return variant.getString();
104                else if(type==Variant.VariantBoolean) return variant.getBoolean()?Boolean.TRUE:Boolean.FALSE;
105                else if(type==Variant.VariantByte) return new Byte(variant.getByte());
106                else if(type==Variant.VariantVariant) {
107                    throw new ExpressionException("type variant is not supported");
108                    //return toObject(variant.getV.get());
109                }
110                else if(type==Variant.VariantArray) {
111                        Variant[] varr = variant.getVariantArrayRef();
112                        Object[] oarr = new Object[varr.length];
113                        for(int i=0;i<varr.length;i++) {
114                                oarr[i]=toObject(parent,varr[i],Caster.toString(i));
115                        }
116                        return new ArrayImpl(oarr);
117                }
118                else if(type==Variant.VariantDispatch) {
119                    
120                    return new COMObject(variant,variant.toDispatch(),parent.getName()+"."+key);
121                }
122                // TODO  ?? else if(type==Variant.VariantError) return variant.toError();
123
124                throw new ExpressionException("COM Type ["+toStringType(type)+"] not supported");
125    }
126    
127
128        /**
129         * translate a short Variant Type Defintion to a String (string,empty,null,short ...)
130         * @param type
131         * @return String Variant Type
132         */
133        public static String toStringType(short type) {
134                if(type==Variant.VariantEmpty) return "empty";
135                else if(type==Variant.VariantNull) return "null";
136                else if(type==Variant.VariantShort) return "Short";
137                else if(type==Variant.VariantInt) return "Integer";
138                else if(type==Variant.VariantFloat) return "Float";
139                else if(type==Variant.VariantDouble) return "Double";
140                else if(type==Variant.VariantCurrency) return "Currency";
141                else if(type==Variant.VariantDate) return "Date";
142                else if(type==Variant.VariantString) return "String";
143                else if(type==Variant.VariantBoolean) return "Boolean";
144                else if(type==Variant.VariantByte) return "Byte";
145                else if(type==Variant.VariantArray) return "Array";
146                else if(type==Variant.VariantDispatch) return "Dispatch";
147                else if(type==Variant.VariantByref) return "Byref";
148                else if(type==Variant.VariantCurrency) return "Currency";
149                else if(type==Variant.VariantError) return "Error";
150                else if(type==Variant.VariantInt) return "int";
151                else if(type==Variant.VariantObject) return "Object";
152                else if(type==Variant.VariantTypeMask) return "TypeMask";
153                else if(type==Variant.VariantVariant) return "Variant";
154                else return "unknow";
155        }
156
157}