001    package railo.runtime.java;
002    
003    import java.lang.reflect.Field;
004    import java.lang.reflect.InvocationTargetException;
005    import java.lang.reflect.Modifier;
006    import java.util.ArrayList;
007    import java.util.Date;
008    import java.util.Iterator;
009    import java.util.List;
010    
011    import railo.runtime.PageContext;
012    import railo.runtime.dump.DumpData;
013    import railo.runtime.dump.DumpProperties;
014    import railo.runtime.dump.DumpUtil;
015    import railo.runtime.exp.ExpressionException;
016    import railo.runtime.exp.PageException;
017    import railo.runtime.op.Caster;
018    import railo.runtime.op.Operator;
019    import railo.runtime.op.date.DateCaster;
020    import railo.runtime.reflection.Reflector;
021    import railo.runtime.reflection.pairs.MethodInstance;
022    import railo.runtime.type.Collection;
023    import railo.runtime.type.ObjectWrap;
024    import railo.runtime.type.Objects;
025    import railo.runtime.type.Struct;
026    import railo.runtime.type.dt.DateTime;
027    import railo.runtime.type.util.ArrayUtil;
028    import railo.runtime.util.VariableUtil;
029    import railo.runtime.util.VariableUtilImpl;
030    
031    
032    /**
033     * class to handle initialising and call native object from railo
034     */
035    public class JavaObject implements Objects,ObjectWrap {
036            
037            private Class clazz;
038            private boolean isInit=false;
039            private Object object;
040        private VariableUtil variableUtil;
041        
042            /**
043             * constructor with className to load
044             * @param variableUtil
045             * @param clazz
046             * @throws ExpressionException
047             */
048            public JavaObject(VariableUtil variableUtil,Class clazz) {
049                this.variableUtil=variableUtil;
050                    this.clazz=clazz;
051            }
052    
053    
054            public JavaObject(VariableUtil variableUtil,Object object) {
055                this.variableUtil=variableUtil;
056                    this.clazz=object.getClass();
057                    this.object=object;
058                    isInit=true;
059            }
060    
061            public Object get(PageContext pc, String propertyName) throws PageException {
062            if(isInit) {
063                return variableUtil.get(pc,object,propertyName);
064            }
065                
066            // Check Field
067                Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null);
068                if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) {
069                            try {
070                        return fields[0].get(null);
071                    } 
072                    catch (Exception e) {
073                        throw Caster.toPageException(e);
074                    }
075                    }
076            // Getter
077                MethodInstance mi = Reflector.getGetterEL(clazz,propertyName);
078                if(mi!=null) {
079                    if(Modifier.isStatic(mi.getMethod().getModifiers())) {
080                        try {
081                            return mi.invoke(null);
082                        } 
083                        catch (IllegalAccessException e) {
084                            throw Caster.toPageException(e);
085                        } 
086                        catch (InvocationTargetException e) {
087                            throw Caster.toPageException(e.getTargetException());
088                        }    
089                    }
090                }
091            // male Instance
092            return variableUtil.get(pc,init(),propertyName);  
093            }
094    
095            @Override
096            public Object get(PageContext pc, Collection.Key key) throws PageException {
097                    return get(pc, key.getString());
098            }
099    
100        public Object get(PageContext pc, String propertyName, Object defaultValue) {
101            if(isInit) {
102                return variableUtil.get(pc,object,propertyName,defaultValue);  
103            }
104            // Field
105            Field[] fields = Reflector.getFieldsIgnoreCase(clazz,propertyName,null);
106            if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) {
107                            try {
108                    return fields[0].get(null);
109                } catch (Exception e) {}
110                    }
111            // Getter
112            MethodInstance mi = Reflector.getGetterEL(clazz,propertyName);
113            if(mi!=null) {
114                if(Modifier.isStatic(mi.getMethod().getModifiers())) {
115                    try {
116                        return mi.invoke(null);
117                    } 
118                    catch (Exception e) {}    
119                }
120            }
121            try {
122                return variableUtil.get(pc,init(),propertyName,defaultValue);  
123            } catch (PageException e1) {
124                return defaultValue;
125            }         
126        }
127    
128            @Override
129            public Object get(PageContext pc, Collection.Key key, Object defaultValue) {
130                    return get(pc, key.getString(), defaultValue);
131            }
132    
133            @Override
134            public Object set(PageContext pc, Collection.Key propertyName, Object value) throws PageException  {
135                    if(isInit) {
136                        return ((VariableUtilImpl)variableUtil).set(pc,object,propertyName,value);
137                    }
138                // Field
139                    Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null);
140                    if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) {
141                            try {
142                    fields[0].set(null,value);
143                    return value;
144                } catch (Exception e) {
145                    Caster.toPageException(e);
146                }
147                    }
148            // Getter
149            MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null);
150            if(mi!=null) {
151                if(Modifier.isStatic(mi.getMethod().getModifiers())) {
152                    try {
153                        return mi.invoke(null);
154                    } 
155                    catch (IllegalAccessException e) {
156                        throw Caster.toPageException(e);
157                    } 
158                    catch (InvocationTargetException e) {
159                        throw Caster.toPageException(e.getTargetException());
160                    }    
161                }
162            }
163            
164    
165                return ((VariableUtilImpl)variableUtil).set(pc,init(),propertyName,value);
166            }
167    
168        @Override
169        public Object setEL(PageContext pc, Collection.Key propertyName, Object value) {
170                    if(isInit) {
171                        return variableUtil.setEL(pc,object,propertyName,value);
172                    }
173                // Field
174                    Field[] fields=Reflector.getFieldsIgnoreCase(clazz,propertyName.getString(),null);
175                    if(!ArrayUtil.isEmpty(fields) && Modifier.isStatic(fields[0].getModifiers())) {
176                            try {
177                    fields[0].set(null,value);
178                } catch (Exception e) {}
179                            return value;
180                    }
181            // Getter
182            MethodInstance mi = Reflector.getSetter(clazz,propertyName.getString(),value,null);
183            if(mi!=null) {
184                if(Modifier.isStatic(mi.getMethod().getModifiers())) {
185                    try {
186                        return mi.invoke(null);
187                    } 
188                    catch (Exception e) {}    
189                }
190            }
191               
192            try {
193                return variableUtil.setEL(pc,init(),propertyName,value);
194            } catch (PageException e1) {
195                return value;
196            }
197        }
198    
199            public Object call(PageContext pc, String methodName, Object[] arguments) throws PageException {
200            if(arguments==null)arguments=new Object[0];
201            
202            // init
203            if(methodName.equalsIgnoreCase("init")) {
204                return init(arguments);
205            }
206            else if(isInit) {
207                        return Reflector.callMethod(object,methodName,arguments);
208                    }
209            
210            
211                try {
212                        // get method
213                        MethodInstance mi = Reflector.getMethodInstance(clazz,methodName,arguments);
214                            // call static method if exist
215                        if(Modifier.isStatic(mi.getMethod().getModifiers())) {
216                                    return mi.invoke(null);
217                            }
218                        
219                        if(arguments.length==0 && methodName.equalsIgnoreCase("getClass")){
220                            return clazz;
221                        }
222                        
223                        // invoke constructor and call instance method
224                            return mi.invoke(init());
225                    }
226                    catch(InvocationTargetException e) {
227                            Throwable target = e.getTargetException();
228                            if(target instanceof PageException) throw (PageException)target;
229                            throw Caster.toPageException(e.getTargetException());
230                    }
231                    catch(Exception e) {
232                            throw Caster.toPageException(e);
233                    }
234            }
235    
236            @Override
237            public Object call(PageContext pc, Collection.Key methodName, Object[] arguments) throws PageException {
238                    return call(pc, methodName.getString(), arguments);
239            }
240    
241        public Object callWithNamedValues(PageContext pc, String methodName, Struct args) throws PageException {
242            Iterator<Object> it = args.valueIterator();
243            List<Object> values=new ArrayList<Object>();
244            while(it.hasNext()) {
245                values.add(it.next());
246            }   
247            return call(pc,methodName,values.toArray(new Object[values.size()]));
248        }
249    
250            public Object callWithNamedValues(PageContext pc, Collection.Key methodName, Struct args) throws PageException {
251                    return callWithNamedValues(pc, methodName.getString(), args);
252            }
253    
254            /**
255             * initialize method (default no object)
256             * @return initialize object
257             * @throws PageException
258             */
259            private Object init() throws PageException {
260                    return init(new Object[0]);
261            }
262            
263            private Object init(Object defaultValue) {
264                    return init(new Object[0],defaultValue);
265            }
266            
267            /**
268             * initialize method
269             * @param arguments
270             * @return Initalised Object
271             * @throws PageException
272             */
273            private Object init(Object[] arguments) throws PageException {
274                    object=Reflector.callConstructor(clazz,arguments);
275                    isInit=true;
276                    return object;
277            }
278            private Object init(Object[] arguments, Object defaultValue) {
279                    object=Reflector.callConstructor(clazz,arguments,defaultValue);
280                    isInit=object!=defaultValue;
281                    return object;
282            }
283    
284    
285            @Override
286            public Object getEmbededObject() throws PageException {
287                    if(object==null)init();
288                    return object;
289            }
290    
291            @Override
292            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties props) {
293                    try {
294                            return DumpUtil.toDumpData(getEmbededObject(), pageContext,maxlevel,props);
295                    } catch (PageException e) {
296                            return DumpUtil.toDumpData(clazz, pageContext,maxlevel,props);
297                    }
298            }
299            
300            /**
301             * @return the containing Class
302             */
303            public Class getClazz() {return clazz;}
304    
305        public boolean isInitalized() {
306            return isInit;
307        }
308    
309        @Override
310        public String castToString() throws PageException {
311            return Caster.toString(getEmbededObject());
312        }
313        
314    
315    
316        @Override
317        public String castToString(String defaultValue) {
318            try {
319                            return Caster.toString(getEmbededObject(),defaultValue);
320                    } catch (PageException e) {
321                            return defaultValue;
322                    }
323        }
324        
325    
326        @Override
327        public boolean castToBooleanValue() throws PageException {
328            return Caster.toBooleanValue(getEmbededObject());
329        }
330        
331        @Override
332        public Boolean castToBoolean(Boolean defaultValue) {
333            try {
334                            return Caster.toBoolean(getEmbededObject(),defaultValue);
335                    } catch (PageException e) {
336                            return defaultValue;
337                    }
338        }
339    
340        @Override
341        public double castToDoubleValue() throws PageException {
342            return Caster.toDoubleValue(getEmbededObject());
343        }
344        
345        @Override
346        public double castToDoubleValue(double defaultValue) {
347            try {
348                            return Caster.toDoubleValue(getEmbededObject(),defaultValue);
349                    } catch (PageException e) {
350                            return defaultValue;
351                    }
352        }
353    
354        @Override
355        public DateTime castToDateTime() throws PageException {
356            return Caster.toDatetime(getEmbededObject(),null);
357        }
358        
359        @Override
360        public DateTime castToDateTime(DateTime defaultValue) {
361            try {
362                            return DateCaster.toDateAdvanced(getEmbededObject(),true,null,defaultValue);
363                    } catch (PageException e) {
364                            return defaultValue;
365                    }
366        }
367    
368        @Override
369        public Object getEmbededObject(Object def) {
370            if(object==null)init(def);
371                    return object;
372        }
373    
374            /**
375             * @return the object
376             */
377            public Object getObject() {
378                    return object;
379            }
380    
381            @Override
382            public int compareTo(boolean b) throws PageException {
383                    return Operator.compare(castToBooleanValue(), b);
384            }
385    
386            @Override
387            public int compareTo(DateTime dt) throws PageException {
388                    return Operator.compare((Date)castToDateTime(), (Date)dt);
389            }
390    
391            @Override
392            public int compareTo(double d) throws PageException {
393                    return Operator.compare(castToDoubleValue(), d);
394            }
395    
396            @Override
397            public int compareTo(String str) throws PageException {
398                    return Operator.compare(castToString(), str);
399            }
400    
401    }