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 java.util.Iterator;
022import java.util.Map.Entry;
023
024import lucee.commons.lang.ExceptionUtil;
025import lucee.commons.lang.StringUtil;
026import lucee.runtime.exp.ApplicationException;
027import lucee.runtime.exp.CatchBlock;
028import lucee.runtime.exp.CustomTypeException;
029import lucee.runtime.exp.ExpressionException;
030import lucee.runtime.exp.PageException;
031import lucee.runtime.exp.PageExceptionImpl;
032import lucee.runtime.ext.tag.TagImpl;
033import lucee.runtime.op.Caster;
034import lucee.runtime.type.Collection.Key;
035import lucee.runtime.type.ObjectWrap;
036import lucee.runtime.type.Struct;
037import lucee.runtime.type.util.KeyConstants;
038
039/**
040* The cfthrow tag raises a developer-specified exception that can be caught with cfcatch tag 
041*   having any of the following type specifications - cfcatch type = 'custom_type', cfcatch type = 'Application'
042*   'cfcatch' type = 'Any'
043*
044*
045*
046**/
047public final class Throw extends TagImpl {
048
049        /** A custom error code that you supply. */
050        private String extendedinfo=null;
051
052        private String type="application";
053
054        private String detail="";
055
056        /** A message that describes the exceptional event. */
057        private Object message;
058
059        /** A custom error code that you supply. */
060        private String errorcode="";
061
062        private Object object;
063
064        private int level=1;
065
066        @Override
067        public void release()   {
068                super.release();
069                extendedinfo=null;
070                type="application";
071                detail="";
072                message=null;
073                errorcode="";
074                object=null;
075                level=1;
076        }
077
078
079
080        /** set the value extendedinfo
081        *  A custom error code that you supply.
082        * @param extendedinfo value to set
083        **/
084        public void setExtendedinfo(String extendedinfo)        {
085                this.extendedinfo=extendedinfo;
086        }
087
088        /** set the value type
089        * @param type value to set
090        **/
091        public void setType(String type)        {
092                this.type=type;
093        }
094
095        /** set the value detail
096        * @param detail value to set
097        **/
098        public void setDetail(String detail)    {
099                this.detail=detail;
100        }
101
102        /** set the value message
103        *  A message that describes the exceptional event.
104        * @param message value to set
105        **/
106        public void setMessage(Object message)  {
107                this.message=message;
108        }
109        
110        /**
111         * @deprecated this method should no longer be used.
112         * */
113        public void setMessage(String message)  {
114                this.message=message;
115        }
116
117        /** set the value errorcode
118        *  A custom error code that you supply.
119        * @param errorcode value to set
120        **/
121        public void setErrorcode(String errorcode)      {
122                this.errorcode=errorcode;
123        }
124
125        /** set the value object
126        *  a native java exception Object, if this attribute is defined all other will be ignored.
127        * @param object object to set
128         * @throws PageException
129        **/
130        public void setObject(Object object) throws PageException       {
131                this.object=object;     
132        }
133
134        public void setContextlevel(double level){
135                this.level=(int)level;
136        }
137
138        public static PageException toPageException(Object object, PageException defaultValue) throws PageException {
139                if((object instanceof ObjectWrap))
140                        return toPageException(((ObjectWrap)object).getEmbededObject(),defaultValue);
141                
142                
143                if(object instanceof CatchBlock) {
144                        CatchBlock cb = (CatchBlock)object;
145                        return cb.getPageException();
146                }
147                if(object instanceof PageException) return (PageException)object;
148                if(object instanceof Throwable) {
149                        Throwable t=(Throwable)object;
150                        ExceptionUtil.rethrowIfNecessary(t);
151                        return new CustomTypeException(t.getMessage(),"","",t.getClass().getName(),"");
152                }
153                if(object instanceof Struct){
154                        Struct sct=(Struct) object;
155                        String type=Caster.toString(sct.get(KeyConstants._type,""),"").trim();
156                        String msg=Caster.toString(sct.get(KeyConstants._message,null),null);
157                        if(!StringUtil.isEmpty(msg, true)) {
158                                String detail=Caster.toString(sct.get(KeyConstants._detail,null),null);
159                                String errCode=Caster.toString(sct.get("ErrorCode",null),null);
160                                String extInfo=Caster.toString(sct.get("ExtendedInfo",null),null);
161                                
162                                PageException pe=null;
163                                if("application".equalsIgnoreCase(type)) 
164                                        pe = new ApplicationException(msg, detail);
165                                else if("expression".equalsIgnoreCase(type)) 
166                                        pe = new ExpressionException(msg, detail);
167                                else 
168                                        pe=new CustomTypeException(msg, detail, errCode, type, extInfo);
169                                
170                                // Extended Info
171                                if(!StringUtil.isEmpty(extInfo,true))pe.setExtendedInfo(extInfo);
172        
173                                // Error Code
174                                if(!StringUtil.isEmpty(errCode,true))pe.setErrorCode(errCode);
175                                
176                                // Additional
177                                if(pe instanceof PageExceptionImpl) {
178                                        PageExceptionImpl pei=(PageExceptionImpl) pe;
179                                        sct=Caster.toStruct(sct.get("additional",null),null);
180                                        if(sct!=null) {
181                                                Iterator<Entry<Key, Object>> it = sct.entryIterator();
182                                                Entry<Key, Object> e;
183                                                while(it.hasNext()){
184                                                        e = it.next();
185                                                        pei.setAdditional(e.getKey(), e.getValue());
186                                                }
187                                        }
188                                }
189                                return pe;
190                        }
191                }
192                
193                return defaultValue;
194                
195        }
196
197
198
199        @Override
200        public int doStartTag() throws PageException    {
201                
202                _doStartTag(message);
203                _doStartTag(object);
204                
205                throw new CustomTypeException( "",detail,errorcode,type,extendedinfo,level);
206        }
207
208        private void _doStartTag(Object obj) throws PageException {
209                if(!StringUtil.isEmpty(obj)){
210                        PageException pe = toPageException(obj,null);
211                        if(pe!=null) throw pe;
212                        
213                        CustomTypeException exception = new CustomTypeException(Caster.toString(obj),detail,errorcode,type,extendedinfo,level);
214                        throw exception;
215                }
216        }
217
218
219
220        @Override
221        public int doEndTag()   {
222                return EVAL_PAGE;
223        }
224}