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.tag;
020
021import lucee.commons.lang.StringUtil;
022import lucee.runtime.PageContext;
023import lucee.runtime.exp.ApplicationException;
024import lucee.runtime.exp.PageException;
025import lucee.runtime.ext.tag.BodyTagImpl;
026import lucee.runtime.ext.tag.DynamicAttributes;
027import lucee.runtime.net.proxy.ProxyData;
028import lucee.runtime.net.proxy.ProxyDataImpl;
029import lucee.runtime.net.rpc.client.WSClient;
030import lucee.runtime.op.Caster;
031import lucee.runtime.type.KeyImpl;
032import lucee.runtime.type.Struct;
033import lucee.runtime.type.StructImpl;
034import lucee.runtime.type.UDF;
035
036/*
037 * FUTURE tag invoke
038 * Attributes: servicePort,timeout
039 * */
040
041
042/**
043* Invokes component methods from within a page or component. 
044*                       You use this tag to reference a WSDL file and consume a web service from within a block of CFML code.
045*
046*
047*
048**/
049public final class Invoke  extends BodyTagImpl implements DynamicAttributes {
050
051        private Struct data=new StructImpl(StructImpl.TYPE_LINKED);
052        //private Map attributes = new HashTable();
053        //private HashSet keys = new HashSet();
054        
055        private boolean hasBody;
056        
057        private Object component;
058        private String method;
059        private String returnvariable;
060        private String username;
061        private String password;
062        private String webservice;
063        private int timeout=-1;
064        private String serviceport;
065        private ProxyData proxy=new ProxyDataImpl();
066
067
068        @Override
069        public void release()   {
070                super.release();
071                data.clear();
072                component=null;
073                method=null;
074                returnvariable=null;
075                username=null;
076                password=null;
077                webservice=null;
078                timeout=-1;
079                serviceport=null;
080                proxy.release();
081        }
082
083
084        /**
085         * @param component the component to set
086         */
087        public void setComponent(Object component) {
088                this.component = component;
089        }
090
091
092        /**
093         * @param method the method to set
094         */
095        public void setMethod(String method) {
096                this.method = method;
097        }
098
099
100        /**
101         * @param password the password to set
102         */
103        public void setPassword(String password) {
104                this.password = password;
105        }
106
107        /**
108         * @param proxyserver the proxyserver to set
109         */
110        public void setProxyserver(String proxyserver) {
111                proxy.setServer(proxyserver);
112        }
113
114        /**
115         * @param proxyport the proxyport to set
116         */
117        public void setProxyport(double proxyport) {
118                proxy.setPort((int)proxyport);
119        }
120
121        /**
122         * @param proxyuser the proxyuser to set
123         */
124        public void setProxyuser(String proxyuser) {
125                proxy.setUsername(proxyuser);
126        }
127
128        /**
129         * @param proxypassword the proxypassword to set
130         */
131        public void setProxypassword(String proxypassword) {
132                proxy.setPassword(proxypassword);
133        }
134
135        /**
136         * @param returnvariable the returnvariable to set
137         */
138        public void setReturnvariable(String returnvariable) {
139                this.returnvariable = returnvariable.trim();
140        }
141
142
143        /**
144         * @param serviceport the serviceport to set
145         */
146        public void setServiceport(String serviceport) {
147                this.serviceport = serviceport;
148        }
149
150
151        /**
152         * @param timeout the timeout to set
153         */
154        public void setTimeout(double timeout) {
155                this.timeout = (int) timeout;
156        }
157
158
159        /**
160         * @param username the username to set
161         */
162        public void setUsername(String username) {
163                this.username = username;
164        }
165
166
167        /**
168         * @param webservice the webservice to set
169         */
170        public void setWebservice(String webservice) {
171                this.webservice = webservice.trim();
172        }
173        
174        @Override
175        public void setDynamicAttribute(String uri, String localName, Object value) {
176                setDynamicAttribute(uri, KeyImpl.init(localName), value);
177        }
178        
179        @Override
180        public void setDynamicAttribute(String uri, lucee.runtime.type.Collection.Key localName, Object value) {
181                data.setEL(localName, value);
182        }
183
184
185        @Override
186        public int doStartTag() throws PageException    {
187            return EVAL_BODY_INCLUDE;
188        }
189
190        @Override
191        public int doEndTag() throws PageException      {
192                // CFC
193                if(component!=null){
194                        doComponent(component);
195                }
196                // Webservice
197                else if(!StringUtil.isEmpty(webservice)){
198                        doWebService(webservice);
199                }
200                // call active cfc or component
201                else {
202            doFunction(pageContext);
203        }
204                return EVAL_PAGE;
205        }
206
207
208
209        /**
210         * @param oComponent
211         * @throws PageException
212         */
213        private void doComponent(Object oComponent) throws PageException {
214                lucee.runtime.Component component=null;
215                if(oComponent instanceof lucee.runtime.Component)
216                        component=(lucee.runtime.Component)oComponent;
217                else
218                        component=pageContext.loadComponent(Caster.toString(oComponent));
219                        
220                // execute
221                Object rtn=component.callWithNamedValues(pageContext,method,data);
222                
223                // return 
224                if(!StringUtil.isEmpty(returnvariable)) pageContext.setVariable(returnvariable,rtn);
225        }
226        
227        private void doFunction(PageContext pc) throws PageException {
228                        
229                // execute
230                if(StringUtil.isEmpty(method,true))
231                        throw new ApplicationException("Attribute [method] for tag [invoke] is required in this context.");
232                
233                Object oUDF=pc.getVariable(method);
234                if(!(oUDF instanceof UDF))throw new ApplicationException("there is no function with name "+method); 
235                Object rtn = ((UDF)oUDF).callWithNamedValues(pageContext, data, false);
236                
237                
238                // return 
239                if(!StringUtil.isEmpty(returnvariable)) pageContext.setVariable(returnvariable,rtn);
240        }
241
242        /**
243         * @param webservice
244         * @throws PageException
245         */
246        private void doWebService(String webservice) throws PageException {
247        if(username!=null)   {
248            if(password==null)password = "";
249        }
250        ProxyData pd=StringUtil.isEmpty(proxy.getServer())?null:proxy;
251        WSClient ws = username!=null?WSClient.getInstance(pageContext,webservice,username,password,pd):WSClient.getInstance(pageContext,webservice,null,null,pd);
252        Object rtn = ws.callWithNamedValues(pageContext,KeyImpl.init(method),data);
253        
254        // return
255        if(!StringUtil.isEmpty(returnvariable)) pageContext.setVariable(returnvariable,rtn);
256        
257        //throw new ApplicationException("type webservice is not yet implemented for tag invoke");
258        }
259
260        /**
261         * @param name
262         * @param value
263         * @throws PageException
264         */
265        public void setArgument(String name,Object value) throws PageException {
266                data.set(name,value);           
267        }
268        
269        /**
270         * sets if taf has a body or not
271         * @param hasBody
272         */
273        public void hasBody(boolean hasBody) {
274                this.hasBody=hasBody;
275        }
276
277}