KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > env > QuercusClass


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.quercus.env;
31
32 import com.caucho.quercus.QuercusRuntimeException;
33 import com.caucho.quercus.expr.*;
34 import com.caucho.quercus.program.AbstractFunction;
35 import com.caucho.quercus.program.ClassDef;
36 import com.caucho.quercus.program.Function;
37 import com.caucho.quercus.program.InstanceInitializer;
38 import com.caucho.util.IdentityIntMap;
39 import com.caucho.util.L10N;
40
41 import java.util.ArrayList JavaDoc;
42 import java.util.HashMap JavaDoc;
43 import java.util.IdentityHashMap JavaDoc;
44 import java.util.LinkedHashMap JavaDoc;
45 import java.util.Map JavaDoc;
46 import java.util.Set JavaDoc;
47 import java.util.logging.Logger JavaDoc;
48
49 /**
50  * Represents a Quercus runtime class.
51  */

52 public class QuercusClass {
53   private final L10N L = new L10N(QuercusClass.class);
54   private final Logger JavaDoc log = Logger.getLogger(QuercusClass.class.getName());
55
56   private final ClassDef _classDef;
57   
58   private ClassDef []_classDefList;
59
60   private QuercusClass _parent;
61
62   private AbstractFunction _constructor;
63   
64   private AbstractFunction _get;
65   private AbstractFunction _set;
66   private AbstractFunction _call;
67   
68   private final ArrayList JavaDoc<InstanceInitializer> _initializers
69     = new ArrayList JavaDoc<InstanceInitializer>();
70   
71   private final ArrayList JavaDoc<String JavaDoc> _fieldNames
72     = new ArrayList JavaDoc<String JavaDoc>();
73   
74   private final IdentityIntMap _fieldMap
75     = new IdentityIntMap();
76   
77   private final HashMap JavaDoc<StringValue,Expr> _fieldInitMap
78     = new HashMap JavaDoc<StringValue,Expr>();
79   
80   private final IdentityHashMap JavaDoc<String JavaDoc,AbstractFunction> _methodMap
81     = new IdentityHashMap JavaDoc<String JavaDoc,AbstractFunction>();
82   
83   private final HashMap JavaDoc<String JavaDoc,AbstractFunction> _lowerMethodMap
84     = new HashMap JavaDoc<String JavaDoc,AbstractFunction>();
85
86   private final IdentityHashMap JavaDoc<String JavaDoc,Expr> _constMap
87     = new IdentityHashMap JavaDoc<String JavaDoc,Expr>();
88
89   private final HashMap JavaDoc<String JavaDoc,Expr> _staticFieldMap
90     = new LinkedHashMap JavaDoc<String JavaDoc,Expr>();
91   
92   public QuercusClass(ClassDef classDef, QuercusClass parent)
93   {
94     _classDef = classDef;
95     _parent = parent;
96
97     ClassDef []classDefList;
98     
99     if (_parent != null) {
100       classDefList = new ClassDef[parent._classDefList.length + 1];
101
102       System.arraycopy(parent._classDefList, 0, classDefList, 1,
103                parent._classDefList.length);
104
105       classDefList[0] = classDef;
106     }
107     else {
108       classDefList = new ClassDef[] { classDef };
109     }
110     
111     _classDefList = classDefList;
112
113     for (int i = classDefList.length - 1; i >= 0; i--) {
114       classDefList[i].initClass(this);
115     }
116   }
117
118   /**
119    * Returns the name.
120    */

121   public String JavaDoc getName()
122   {
123     return _classDef.getName();
124   }
125
126   /**
127    * Returns the parent class.
128    */

129   public QuercusClass getParent()
130   {
131     return _parent;
132   }
133
134   /**
135    * Sets the constructor.
136    */

137   public void setConstructor(AbstractFunction fun)
138   {
139     _constructor = fun;
140   }
141
142   /**
143    * Sets the __get
144    */

145   public void setGet(AbstractFunction fun)
146   {
147     _get = fun;
148   }
149
150   /**
151    * Sets the __set
152    */

153   public void setSet(AbstractFunction fun)
154   {
155     _set = fun;
156   }
157
158   /**
159    * Sets the __set
160    */

161   public AbstractFunction getSetField()
162   {
163     return _set;
164   }
165
166   /**
167    * Sets the __call
168    */

169   public void setCall(AbstractFunction fun)
170   {
171     _call = fun;
172   }
173
174   /**
175    * Sets the __call
176    */

177   public AbstractFunction getCall()
178   {
179     return _call;
180   }
181
182   /**
183    * Adds an initializer
184    */

185   public void addInitializer(InstanceInitializer init)
186   {
187     _initializers.add(init);
188   }
189
190   /**
191    * Adds a field.
192    */

193   public void addField(String JavaDoc name, int index, Expr initExpr)
194   {
195     _fieldNames.add(name);
196     _fieldMap.put(name, index);
197     _fieldInitMap.put(new StringValueImpl(name), initExpr);
198   }
199
200   /**
201    * Adds a field.
202    */

203   public int addFieldIndex(String JavaDoc name)
204   {
205     int index = _fieldMap.get(name);
206
207     if (index >= 0)
208       return index;
209     else {
210       index = _fieldNames.size();
211     
212       _fieldMap.put(name, index);
213       _fieldNames.add(name);
214
215       return index;
216     }
217   }
218   
219   /**
220    * Returns a set of the fields and their initial values
221    */

222   public HashMap JavaDoc<StringValue,Expr> getClassVars()
223   {
224     return _fieldInitMap;
225   }
226   
227   /**
228    * Returns a set of the method names and their values
229    * @return a set of the method names and their values
230    */

231   public Set JavaDoc<Map.Entry<String JavaDoc, AbstractFunction>> getClassMethods()
232   {
233     return _classDef.functionSet();
234   }
235
236   /**
237    * Adds a method.
238    */

239   public void addMethod(String JavaDoc name, AbstractFunction fun)
240   {
241     _methodMap.put(name.intern(), fun);
242     _lowerMethodMap.put(name.toLowerCase(), fun);
243   }
244
245   /**
246    * Adds a static field
247    */

248   public void addStaticField(String JavaDoc name, Expr expr)
249   {
250     _staticFieldMap.put(name, expr);
251   }
252
253   /**
254    * Adds a constant definition
255    */

256   public void addConstant(String JavaDoc name, Expr expr)
257   {
258     _constMap.put(name, expr);
259   }
260
261   /**
262    * Returns the number of fields.
263    */

264   public int getFieldSize()
265   {
266     return _fieldNames.size();
267   }
268
269   /**
270    * Returns the field index.
271    */

272   public int findFieldIndex(String JavaDoc name)
273   {
274     return _fieldMap.get(name);
275   }
276
277   /**
278    * Returns the key set.
279    */

280   public ArrayList JavaDoc<String JavaDoc> getFieldNames()
281   {
282     return _fieldNames;
283   }
284
285   public void validate(Env env)
286   {
287     if (! _classDef.isAbstract() && ! _classDef.isInterface()) {
288       for (AbstractFunction absFun : _methodMap.values()) {
289     if (! (absFun instanceof Function))
290       continue;
291
292     Function fun = (Function) absFun;
293
294     if (fun.isAbstract())
295       throw env.errorException(L.l("Abstract function '{0}' must be implemented in concrete class {1}.",
296                   fun.getName(), getName()));
297       }
298     }
299   }
300
301   public void init(Env env)
302   {
303     for (Map.Entry<String JavaDoc,Expr> entry : _staticFieldMap.entrySet()) {
304       Value val;
305       Expr expr = entry.getValue();
306
307       //php/096f
308
if (expr instanceof ClassConstExpr)
309         val = ((ClassConstExpr)expr).eval(env, this);
310       else
311         val = expr.eval(env);
312
313       env.setGlobalValue(entry.getKey(), val);
314     }
315   }
316
317   //
318
// Constructors
319
//
320

321   /**
322    * Creates a new instance.
323    */

324   public Value callNew(Env env, Expr []args)
325   {
326     Value object = _classDef.callNew(env, args);
327
328     if (object != null)
329       return object;
330     
331     object = newInstance(env);
332
333     AbstractFunction fun = findConstructor();
334
335     if (fun != null) {
336       fun.callMethod(env, object, args);
337     }
338
339     return object;
340   }
341
342   /**
343    * Creates a new instance.
344    */

345   public Value callNew(Env env, Value []args)
346   {
347     Value object = _classDef.callNew(env, args);
348
349     if (object != null)
350       return object;
351     
352     object = newInstance(env);
353
354     AbstractFunction fun = findConstructor();
355
356     if (fun != null)
357       fun.callMethod(env, object, args);
358     else {
359       // if expr
360
}
361
362     return object;
363   }
364
365   /**
366    * Returns the parent class.
367    */

368   public String JavaDoc getParentName()
369   {
370     return _classDefList[0].getParentName();
371   }
372
373   /**
374    * Returns true for an implementation of a class
375    */

376   public boolean isA(String JavaDoc name)
377   {
378     for (int i = _classDefList.length - 1; i >= 0; i--) {
379       if (_classDefList[i].isA(name))
380     return true;
381     }
382
383     return false;
384   }
385
386   /**
387    * Creates a new instance.
388    */

389   public Value newInstance(Env env)
390   {
391     Value obj = _classDef.newInstance(env, this);
392     
393     for (int i = 0; i < _initializers.size(); i++) {
394       _initializers.get(i).initInstance(env, obj);
395     }
396     
397     return obj;
398   }
399
400   /**
401    * Finds the matching constructor.
402    */

403   public AbstractFunction findConstructor()
404   {
405     return _constructor;
406   }
407
408   //
409
// Fields
410
//
411

412   /**
413    * Implements the __get method call.
414    */

415   public Value getField(Env env, Value qThis, String JavaDoc field)
416   {
417     if (_get != null)
418       return _get.callMethod(env, qThis, new StringValueImpl(field));
419     else
420       return UnsetValue.UNSET;
421   }
422
423   /**
424    * Implements the __set method call.
425    */

426   public void setField(Env env, Value qThis, String JavaDoc field, Value value)
427   {
428     if (_set != null)
429       _set.callMethod(env, qThis, new StringValueImpl(field), value);
430   }
431
432   /**
433    * Finds the matching function.
434    */

435   public AbstractFunction findFunction(String JavaDoc name)
436   {
437     AbstractFunction fun = _methodMap.get(name);
438
439     if (fun == null)
440       fun = _lowerMethodMap.get(name.toLowerCase());
441
442     return fun;
443   }
444
445   /**
446    * Finds the matching function.
447    */

448   public AbstractFunction findFunctionExact(String JavaDoc name)
449   {
450     return _methodMap.get(name);
451   }
452
453   /**
454    * Finds the matching function.
455    */

456   public AbstractFunction findFunctionLowerCase(String JavaDoc name)
457   {
458     return _lowerMethodMap.get(name.toLowerCase());
459   }
460
461   /**
462    * Finds the matching function.
463    */

464   public AbstractFunction findStaticFunction(String JavaDoc name)
465   {
466     return findFunction(name);
467   }
468
469   /**
470    * Finds the matching function.
471    */

472   public final AbstractFunction getFunction(String JavaDoc name)
473   {
474     AbstractFunction fun = findFunction(name);
475
476     if (fun != null)
477       return fun;
478
479     fun = findFunctionLowerCase(name.toLowerCase());
480     
481     if (fun != null)
482       return fun;
483     else {
484       throw new QuercusRuntimeException(L.l("{0}::{1} is an unknown method",
485                     getName(), name));
486     }
487   }
488
489   /**
490    * calls the function.
491    */

492   public Value callMethod(Env env,
493               Value thisValue,
494               String JavaDoc methodName,
495               Expr []args)
496   {
497     AbstractFunction fun = findFunction(methodName);
498     
499     if (fun != null)
500       return fun.callMethod(env, thisValue, args);
501     else if (getCall() != null) {
502       Expr []newArgs = new Expr[args.length + 1];
503       newArgs[0] = new StringLiteralExpr(methodName);
504       System.arraycopy(args, 0, newArgs, 1, args.length);
505       
506       return getCall().callMethod(env, thisValue, newArgs);
507     }
508     else
509       return env.error(L.l("Call to undefined method {0}::{1}",
510                            getName(), methodName));
511   }
512
513   /**
514    * calls the function.
515    */

516   public Value callMethod(Env env, Value thisValue, String JavaDoc name, Value []args)
517   {
518     return getFunction(name).callMethod(env, thisValue, args);
519   }
520
521   /**
522    * calls the function.
523    */

524   public Value callMethod(Env env, Value thisValue, String JavaDoc name)
525   {
526     return getFunction(name).callMethod(env, thisValue);
527   }
528
529   /**
530    * calls the function.
531    */

532   public Value callMethod(Env env,
533               Value thisValue,
534               String JavaDoc methodName,
535               Value a1)
536   {
537     AbstractFunction fun = findFunction(methodName);
538
539     if (fun != null)
540       return fun.callMethod(env, thisValue, a1);
541     else if (getCall() != null) {
542       return getCall().callMethod(env,
543                   thisValue,
544                   new StringValueImpl(methodName),
545                   new ArrayValueImpl()
546                   .append(a1));
547     }
548     else
549       return env.error(L.l("Call to undefined method {0}::{1}()",
550                            getName(), methodName));
551   }
552
553   /**
554    * calls the function.
555    */

556   public Value callMethod(Env env, Value thisValue, String JavaDoc name,
557               Value a1, Value a2)
558   {
559     return getFunction(name).callMethod(env, thisValue, a1, a2);
560   }
561
562   /**
563    * calls the function.
564    */

565   public Value callMethod(Env env, Value thisValue, String JavaDoc name,
566               Value a1, Value a2, Value a3)
567   {
568     return getFunction(name).callMethod(env, thisValue, a1, a2, a3);
569   }
570
571   /**
572    * calls the function.
573    */

574   public Value callMethod(Env env, Value thisValue, String JavaDoc name,
575               Value a1, Value a2, Value a3, Value a4)
576   {
577     return getFunction(name).callMethod(env, thisValue, a1, a2, a3, a4);
578   }
579
580   /**
581    * calls the function.
582    */

583   public Value callMethod(Env env, Value thisValue, String JavaDoc name,
584               Value a1, Value a2, Value a3, Value a4, Value a5)
585   {
586     return getFunction(name).callMethod(env, thisValue, a1, a2, a3, a4, a5);
587   }
588
589   /**
590    * calls the function.
591    */

592   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name, Expr []args)
593   {
594     return getFunction(name).callMethodRef(env, thisValue, args);
595   }
596
597   /**
598    * calls the function.
599    */

600   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name, Value []args)
601   {
602     return getFunction(name).callMethodRef(env, thisValue, args);
603   }
604
605   /**
606    * calls the function.
607    */

608   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name)
609   {
610     return getFunction(name).callMethodRef(env, thisValue);
611   }
612
613   /**
614    * calls the function.
615    */

616   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name,
617               Value a1)
618   {
619     return getFunction(name).callMethodRef(env, thisValue, a1);
620   }
621
622   /**
623    * calls the function.
624    */

625   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name,
626               Value a1, Value a2)
627   {
628     return getFunction(name).callMethodRef(env, thisValue, a1, a2);
629   }
630
631   /**
632    * calls the function.
633    */

634   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name,
635               Value a1, Value a2, Value a3)
636   {
637     return getFunction(name).callMethodRef(env, thisValue, a1, a2, a3);
638   }
639
640   /**
641    * calls the function.
642    */

643   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name,
644               Value a1, Value a2, Value a3, Value a4)
645   {
646     return getFunction(name).callMethodRef(env, thisValue, a1, a2, a3, a4);
647   }
648
649   /**
650    * calls the function.
651    */

652   public Value callMethodRef(Env env, Value thisValue, String JavaDoc name,
653               Value a1, Value a2, Value a3, Value a4, Value a5)
654   {
655     return getFunction(name).callMethodRef(env, thisValue, a1, a2, a3, a4, a5);
656   }
657
658   /**
659    * Finds a function.
660    */

661   public AbstractFunction findStaticFunctionLowerCase(String JavaDoc name)
662   {
663     return null;
664   }
665
666   /**
667    * Finds the matching function.
668    */

669   public final AbstractFunction getStaticFunction(String JavaDoc name)
670   {
671     AbstractFunction fun = findStaticFunction(name);
672
673     if (fun != null)
674       return fun;
675
676     fun = findStaticFunctionLowerCase(name.toLowerCase());
677     
678     if (fun != null)
679       return fun;
680     else {
681       throw new QuercusRuntimeException(L.l("{0}::{1} is an unknown method",
682                     getName(), name));
683     }
684   }
685
686   /**
687    * Finds the matching constant
688    */

689   public final Value getConstant(Env env, String JavaDoc name)
690   {
691     Expr expr = _constMap.get(name);
692
693     if (expr != null)
694       return expr.eval(env);
695
696     throw new QuercusRuntimeException(L.l("{0}::{1} is an unknown constant",
697                     getName(), name));
698   }
699
700   public String JavaDoc toString()
701   {
702     return "QuercusClass[" + getName() + "]";
703   }
704 }
705
706
Popular Tags