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.net.rpc.server;
020
021import javax.xml.rpc.encoding.TypeMapping;
022
023import lucee.commons.lang.CFTypes;
024import lucee.commons.lang.ExceptionUtil;
025import lucee.runtime.Component;
026import lucee.runtime.PageContext;
027import lucee.runtime.exp.ApplicationException;
028import lucee.runtime.exp.PageException;
029import lucee.runtime.net.rpc.AxisCaster;
030import lucee.runtime.net.rpc.TypeMappingUtil;
031import lucee.runtime.op.Caster;
032import lucee.runtime.type.Collection.Key;
033import lucee.runtime.type.FunctionArgument;
034import lucee.runtime.type.UDF;
035
036import org.apache.axis.AxisFault;
037import org.apache.axis.MessageContext;
038
039/**
040 * 
041 */
042public final class ComponentController {
043
044        private static ThreadLocal<Component> component=new ThreadLocal<Component>();
045        private static ThreadLocal<PageContext> pagecontext=new ThreadLocal<PageContext>();
046        private static ThreadLocal<MessageContext> messageContext=new ThreadLocal<MessageContext>();
047
048        /**
049         * invokes thread local component
050         * @param name
051         * @param args
052         * @return
053         * @throws AxisFault 
054         * @throws PageException
055         */
056        public static Object invoke(String name, Object[] args) throws AxisFault {
057                try {
058                        return _invoke(name, args);
059                } 
060                catch (Throwable t) {
061                        ExceptionUtil.rethrowIfNecessary(t);
062                        throw AxisFault.makeFault((Caster.toPageException(t)));
063                }
064        }
065        private static Object _invoke(String name, Object[] args) throws PageException {
066                Key key = Caster.toKey(name);
067                Component c=component.get();
068                PageContext p=pagecontext.get();
069                MessageContext mc = messageContext.get();
070                if(c==null) throw new ApplicationException("missing component");
071                if(p==null) throw new ApplicationException("missing pagecontext");
072                
073                UDF udf = Caster.toFunction(c.get(p,key,null),null);
074                FunctionArgument[] fa=null;
075                if(udf!=null) fa = udf.getFunctionArguments();
076                
077                for(int i=0;i<args.length;i++) {
078                        if(fa!=null && i<fa.length && fa[i].getType()==CFTypes.TYPE_UNKNOW) {
079                                args[i]=AxisCaster.toLuceeType(p,fa[i].getTypeAsString(),args[i]);
080                        }
081                        else
082                                args[i]=AxisCaster.toLuceeType(p,args[i]);
083                }
084                        
085                
086                // return type
087                String rtnType=udf!=null?udf.getReturnTypeAsString():"any";
088                
089                
090                Object rtn = c.call(p, key, args);
091                
092                // cast return value to Axis type
093                try {
094                        RPCServer server = RPCServer.getInstance(p.getId(),p.getServletContext());
095                        TypeMapping tm = mc!=null?mc.getTypeMapping():TypeMappingUtil.getServerTypeMapping(server.getEngine().getTypeMappingRegistry());
096                        rtn=Caster.castTo(p, rtnType, rtn, false);
097                        Class<?> clazz = Caster.cfTypeToClass(rtnType);
098                        return AxisCaster.toAxisType(tm,rtn,clazz.getComponentType()!=null?clazz:null);
099                } 
100                catch (Throwable t) {
101                        ExceptionUtil.rethrowIfNecessary(t);
102                        throw Caster.toPageException(t);
103                }
104        }
105
106        /**
107         * removes PageContext and Component
108         * sets component and pageContext to invoke
109         * @param p
110         * @param c
111         */
112        public static void set(PageContext p,Component c) {
113                pagecontext.set(p);
114                component.set(c);
115        }
116        public static void set(MessageContext mc) {
117                messageContext.set(mc);
118        }
119        
120        /**
121         * 
122         */
123        public static void release() {
124                pagecontext.set(null);
125                component.set(null);
126                messageContext.set(null);
127        }
128}