KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > ejb > cfg > EjbBean


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.ejb.cfg;
31
32 import com.caucho.bytecode.JClass;
33 import com.caucho.bytecode.JClassDependency;
34 import com.caucho.bytecode.JClassLoader;
35 import com.caucho.bytecode.JClassLoaderWrapper;
36 import com.caucho.bytecode.JClassWrapper;
37 import com.caucho.bytecode.JMethod;
38 import com.caucho.config.BuilderProgram;
39 import com.caucho.config.BuilderProgramContainer;
40 import com.caucho.config.ConfigException;
41 import com.caucho.config.DependencyBean;
42 import com.caucho.config.LineConfigException;
43 import com.caucho.config.types.Period;
44 import com.caucho.ejb.AbstractServer;
45 import com.caucho.ejb.EjbServerManager;
46 import com.caucho.ejb.amber.AmberConfig;
47 import com.caucho.ejb.gen.BeanAssembler;
48 import com.caucho.ejb.gen.TransactionChain;
49 import com.caucho.ejb.gen.UserInRoleChain;
50 import com.caucho.ejb.gen.ViewClass;
51 import com.caucho.java.gen.BaseClass;
52 import com.caucho.java.gen.BaseMethod;
53 import com.caucho.java.gen.CallChain;
54 import com.caucho.java.gen.GenClass;
55 import com.caucho.java.gen.JavaClassGenerator;
56 import com.caucho.java.gen.MethodCallChain;
57 import com.caucho.loader.EnvironmentBean;
58 import com.caucho.loader.EnvironmentLocal;
59 import com.caucho.log.Log;
60 import com.caucho.make.ClassDependency;
61 import com.caucho.util.L10N;
62 import com.caucho.vfs.Depend;
63 import com.caucho.vfs.Path;
64 import com.caucho.vfs.PersistentDependency;
65
66 import javax.annotation.PostConstruct;
67 import javax.ejb.EJBHome JavaDoc;
68 import javax.ejb.EJBLocalHome JavaDoc;
69 import javax.ejb.EJBLocalObject JavaDoc;
70 import javax.ejb.EJBObject JavaDoc;
71 import java.lang.ref.SoftReference JavaDoc;
72 import java.util.ArrayList JavaDoc;
73 import java.util.HashMap JavaDoc;
74 import java.util.Map JavaDoc;
75 import java.util.WeakHashMap JavaDoc;
76 import java.util.logging.Level JavaDoc;
77 import java.util.logging.Logger JavaDoc;
78
79 /**
80  * Configuration for an ejb bean.
81  */

82 public class EjbBean implements EnvironmentBean, DependencyBean {
83   private static Logger JavaDoc log = Log.open(EjbBean.class);
84   private static L10N L = new L10N(EjbBean.class);
85   
86   private static EnvironmentLocal<Map JavaDoc<JClass,SoftReference JavaDoc<JMethod[]>>> _methodCache
87     = new EnvironmentLocal<Map JavaDoc<JClass,SoftReference JavaDoc<JMethod[]>>>();
88
89   private final EjbConfig _ejbConfig;
90   private final String JavaDoc _ejbModuleName;
91
92   private ClassLoader JavaDoc _loader;
93
94   protected JClassLoader _jClassLoader;
95
96   private String JavaDoc _ejbName;
97   private String JavaDoc _jndiName;
98
99   private String JavaDoc _location = "";
100
101   // these classes are loaded with the parent (configuration) loader, not
102
// the server loader
103
private JClass _ejbClass;
104   
105   protected JClass _remoteHome;
106   protected JClass _remote;
107   protected JClass _localHome;
108   protected JClass _local;
109
110   protected EjbView _remoteHomeView;
111   protected EjbView _remoteView;
112   protected EjbView _localHomeView;
113   protected EjbView _localView;
114
115   private boolean _isAllowPOJO;
116
117   private boolean _isContainerTransaction = true;
118   
119   ArrayList JavaDoc<PersistentDependency> _dependList =
120     new ArrayList JavaDoc<PersistentDependency>();
121
122   ArrayList JavaDoc<PersistentDependency> _configDependList =
123     new ArrayList JavaDoc<PersistentDependency>();
124
125   ArrayList JavaDoc<String JavaDoc> _beanDependList = new ArrayList JavaDoc<String JavaDoc>();
126
127   ArrayList JavaDoc<EjbMethodPattern> _methodList = new ArrayList JavaDoc<EjbMethodPattern>();
128
129   private HashMap JavaDoc<String JavaDoc,EjbBaseMethod> _methodMap =
130     new HashMap JavaDoc<String JavaDoc,EjbBaseMethod>();
131
132   private BuilderProgramContainer _initProgram;
133   private BuilderProgramContainer _serverProgram;
134
135   private long _transactionTimeout;
136
137   /**
138    * Creates a new entity bean configuration.
139    */

140   public EjbBean(EjbConfig ejbConfig, String JavaDoc ejbModuleName)
141   {
142     _ejbConfig = ejbConfig;
143     _ejbModuleName = ejbModuleName;
144
145     _loader = Thread.currentThread().getContextClassLoader();
146
147     _jClassLoader = JClassLoaderWrapper.create(_loader);
148   }
149
150   /**
151    * Returns the owning config.
152    */

153   public EjbConfig getConfig()
154   {
155     return _ejbConfig;
156   }
157
158   public String JavaDoc getEJBModuleName()
159   {
160     return _ejbModuleName;
161   }
162
163   /**
164    * Returns the class loader.
165    */

166   public ClassLoader JavaDoc getClassLoader()
167   {
168     return _loader;
169   }
170
171   /**
172    * Sets the location
173    */

174   public void setConfigLocation(String JavaDoc filename, int line)
175   {
176     _location = filename + ":" + line + ": ";
177   }
178   
179   /**
180    * Sets the location
181    */

182   public void setLocation(String JavaDoc location)
183   {
184     _location = location;
185   }
186
187   /**
188    * Gets the location
189    */

190   public String JavaDoc getLocation()
191   {
192     return _location;
193   }
194
195   /**
196    * Sets true if POJO are allowed.
197    */

198   public void setAllowPOJO(boolean allowPOJO)
199   {
200     _isAllowPOJO = allowPOJO;
201   }
202
203   /**
204    * Return true if POJO are allowed.
205    */

206   public boolean isAllowPOJO()
207   {
208     return _isAllowPOJO;
209   }
210
211   /**
212    * Adds a description
213    */

214   public void addDescription(String JavaDoc description)
215   {
216   }
217
218   /**
219    * Adds a display name
220    */

221   public void addDisplayName(String JavaDoc displayName)
222   {
223   }
224
225   /**
226    * Adds a icon
227    */

228   public void addIcon(String JavaDoc icon)
229   {
230   }
231     
232   /**
233    * Sets the ejbName
234    */

235   public void setEJBName(String JavaDoc ejbName)
236   {
237     _ejbName = ejbName;
238   }
239
240   /**
241    * Gets the ejbName
242    */

243   public String JavaDoc getEJBName()
244   {
245     return _ejbName;
246   }
247     
248   /**
249    * Sets the jndiName
250    */

251   public void setJndiName(String JavaDoc jndiName)
252   {
253     _jndiName = jndiName;
254   }
255
256   /**
257    * Gets the jndiName
258    */

259   public String JavaDoc getJndiName()
260   {
261     return _jndiName;
262   }
263
264   /**
265    * Returns the kind of bean.
266    */

267   public String JavaDoc getEJBKind()
268   {
269     return "unknown";
270   }
271
272   /**
273    * Sets the ejb implementation class.
274    */

275   public void setEJBClass(Class JavaDoc ejbClass)
276     throws ConfigException
277   {
278     setEJBClassWrapper(new JClassWrapper(ejbClass, _jClassLoader));
279   }
280
281   /**
282    * Sets the ejb implementation class.
283    */

284   public void setEJBClassWrapper(JClass ejbClass)
285     throws ConfigException
286   {
287     if (_ejbClass != null && ! _ejbClass.getName().equals(ejbClass.getName()))
288       throw error(L.l("ejb-class '{0}' cannot be redefined. Old value is '{1}'.",
289               _ejbClass.getName(), ejbClass.getName()));
290
291       
292     _ejbClass = ejbClass;
293
294     if (! _ejbClass.isPublic())
295       throw error(L.l("`{0}' must be public. Bean implementations must be public.", ejbClass.getName()));
296
297     if (_ejbClass.isFinal())
298       throw error(L.l("`{0}' must not be final. Bean implementations must not be final.", ejbClass.getName()));
299
300     if (_ejbClass.isInterface())
301       throw error(L.l("`{0}' must not be an interface. Bean implementations must be classes.", ejbClass.getName()));
302
303     // ejb/02e5
304
JMethod constructor = null;
305     try {
306       constructor = ejbClass.getConstructor(new JClass[0]);
307     } catch (Throwable JavaDoc e) {
308       log.log(Level.FINE, e.toString(), e);
309     }
310
311     if (constructor == null)
312       throw error(L.l("`{0}' needs a public zero-arg constructor. Bean implementations need a public zero-argument constructor.", ejbClass.getName()));
313
314     JClass []exn = constructor.getExceptionTypes();
315     for (int i = 0; i < exn.length; i++) {
316       if (! exn[i].isAssignableTo(RuntimeException JavaDoc.class)) {
317         throw error(L.l("{0}: constructor must not throw `{1}'. Bean constructors must not throw checked exceptions.", ejbClass.getName(), exn[i].getName()));
318       }
319     }
320
321     JMethod method = ejbClass.getMethod("finalize", new JClass[0]);
322
323     if (method != null && ! method.getDeclaringClass().equals(JClass.OBJECT))
324       throw error(L.l("`{0}' may not implement finalize(). Bean implementations may not implement finalize().", ejbClass.getName()));
325   }
326
327   /**
328    * Gets the ejb implementation class.
329    */

330   public Class JavaDoc getEJBClass()
331   {
332     try {
333       if (_ejbClass == null)
334     return null;
335       
336       return Class.forName(_ejbClass.getName(), false, getClassLoader());
337     } catch (RuntimeException JavaDoc e) {
338       throw e;
339     } catch (Exception JavaDoc e) {
340       throw new ConfigException(e);
341     }
342   }
343
344   /**
345    * Gets the ejb implementation class.
346    */

347   public JClass getEJBClassWrapper()
348   {
349     return _ejbClass;
350   }
351
352   /**
353    * Gets the ejb implementation class.
354    */

355   public String JavaDoc getEJBFullClassName()
356   {
357     return _ejbClass.getName();
358   }
359
360   /**
361    * Gets the ejb implementation class.
362    */

363   public String JavaDoc getEJBClassName()
364   {
365     String JavaDoc s = _ejbClass.getName();
366     int p = s.lastIndexOf('.');
367
368     if (p > 0)
369       return s.substring(p + 1);
370     else
371       return s;
372   }
373
374   /**
375    * Gets the implementation class name.
376    */

377   public String JavaDoc getFullImplName()
378   {
379     return getEJBFullClassName();
380   }
381
382   /**
383    * Sets the remote home interface class.
384    */

385   public void setHome(Class JavaDoc home)
386     throws ConfigException
387   {
388     setHomeWrapper(new JClassWrapper(home, _jClassLoader));
389   }
390
391   /**
392    * Sets the remote home interface class.
393    */

394   public void setHomeWrapper(JClass remoteHome)
395     throws ConfigException
396   {
397     _remoteHome = remoteHome;
398
399     if (! remoteHome.isPublic())
400       throw error(L.l("`{0}' must be public. <home> interfaces must be public.", remoteHome.getName()));
401     
402     if (! remoteHome.isInterface())
403       throw error(L.l("`{0}' must be an interface. <home> interfaces must be interfaces.", remoteHome.getName()));
404
405     if (! remoteHome.isAssignableTo(EJBHome JavaDoc.class) && ! isAllowPOJO())
406       throw new ConfigException(L.l("`{0}' must extend EJBHome. <home> interfaces must extend javax.ejb.EJBHome.", remoteHome.getName()));
407     
408   }
409   /**
410    * Gets the ejb implementation class.
411    */

412   public JClass getRemoteHome()
413   {
414     return _remoteHome;
415   }
416
417   /**
418    * Gets the remote home class.
419    */

420   public Class JavaDoc getRemoteHomeClass()
421   {
422     if (_remoteHome == null)
423       return null;
424     
425     try {
426       return Class.forName(_remoteHome.getName(), false, getClassLoader());
427     } catch (Exception JavaDoc e) {
428       throw new RuntimeException JavaDoc(e);
429     }
430   }
431
432   /**
433    * Sets the ejb remote interface
434    */

435   public void setRemote(Class JavaDoc remote)
436     throws ConfigException
437   {
438     setRemoteWrapper(new JClassWrapper(remote, _jClassLoader));
439   }
440
441   /**
442    * Sets the remote interface class.
443    */

444   public void setRemoteWrapper(JClass remote)
445     throws ConfigException
446   {
447     _remote = remote;
448
449     if (! _remote.isPublic())
450       throw error(L.l("`{0}' must be public. <remote> interfaces must be public.", remote.getName()));
451     
452     if (! _remote.isInterface())
453       throw error(L.l("`{0}' must be an interface. <remote> interfaces must be interfaces.", remote.getName()));
454
455     if (! remote.isAssignableTo(EJBObject JavaDoc.class) && ! isAllowPOJO())
456       throw new ConfigException(L.l("`{0}' must extend EJBObject. <remote> interfaces must extend javax.ejb.EJBObject.", remote.getName()));
457     
458   }
459
460   /**
461    * Gets the remote interface class.
462    */

463   public JClass getRemote()
464   {
465     return _remote;
466   }
467
468   /**
469    * Gets the remote class.
470    */

471   public Class JavaDoc getRemoteClass()
472   {
473     if (_remote == null)
474       return null;
475     
476     try {
477       return Class.forName(_remote.getName(), false, getClassLoader());
478     } catch (Exception JavaDoc e) {
479       throw new RuntimeException JavaDoc(e);
480     }
481   }
482
483   /**
484    * Sets the ejb local home interface
485    */

486   public void setLocalHome(Class JavaDoc localHome)
487     throws ConfigException
488   {
489     setLocalHomeWrapper(new JClassWrapper(localHome, _jClassLoader));
490   }
491
492   /**
493    * Sets the local home interface class.
494    */

495   public void setLocalHomeWrapper(JClass localHome)
496     throws ConfigException
497   {
498     _localHome = localHome;
499
500     if (! localHome.isPublic())
501       throw error(L.l("`{0}' must be public. <local-home> interfaces must be public.", localHome.getName()));
502     
503     if (! localHome.isInterface())
504       throw error(L.l("`{0}' must be an interface. <local-home> interfaces must be interfaces.", localHome.getName()));
505
506     if (! localHome.isAssignableTo(EJBLocalHome JavaDoc.class) && ! isAllowPOJO())
507       throw new ConfigException(L.l("`{0}' must extend EJBLocalHome. <local-home> interfaces must extend javax.ejb.EJBLocalHome.", localHome.getName()));
508
509   }
510
511   /**
512    * Gets the local home interface class.
513    */

514   public JClass getLocalHome()
515   {
516     return _localHome;
517   }
518
519   /**
520    * Sets the ejb local interface
521    */

522   public void setLocal(Class JavaDoc local)
523     throws ConfigException
524   {
525     setLocalWrapper(new JClassWrapper(local, _jClassLoader));
526   }
527
528   /**
529    * Sets the local interface class.
530    */

531   public void setLocalWrapper(JClass local)
532     throws ConfigException
533   {
534     _local = local;
535
536     if (! local.isPublic())
537       throw error(L.l("`{0}' must be public. <local> interfaces must be public.", local.getName()));
538     
539     if (! local.isInterface())
540       throw error(L.l("`{0}' must be an interface. <local> interfaces must be interfaces.", local.getName()));
541
542     if (! local.isAssignableTo(EJBLocalObject JavaDoc.class) && ! isAllowPOJO())
543       throw new ConfigException(L.l("`{0}' must extend EJBLocalObject. <local> interfaces must extend javax.ejb.EJBLocalObject.", local.getName()));
544   }
545
546   /**
547    * Gets the local interface class.
548    */

549   public JClass getLocal()
550   {
551     return _local;
552   }
553
554   /**
555    * Returns true if the transaction type is container.
556    */

557   public boolean isContainerTransaction()
558   {
559     return _isContainerTransaction;
560   }
561
562   /**
563    * Adds a method.
564    */

565   public EjbMethodPattern createMethod(MethodSignature sig)
566   {
567     for (int i = 0; i < _methodList.size(); i++) {
568       EjbMethodPattern method = _methodList.get(i);
569
570       if (method.getSignature().equals(sig))
571     return method;
572     }
573
574     EjbMethodPattern method = new EjbMethodPattern(this, sig);
575     
576     _methodList.add(method);
577
578     return method;
579   }
580
581   /**
582    * Adds a method.
583    */

584   public void addMethod(EjbMethodPattern method)
585   {
586     _methodList.add(method);
587   }
588
589   /**
590    * Gets the best method.
591    */

592   public EjbMethodPattern getMethodPattern(JMethod method, String JavaDoc intf)
593   {
594     EjbMethodPattern bestMethod = null;
595     int bestCost = -1;
596
597     for (int i = 0; i < _methodList.size(); i++) {
598       EjbMethodPattern ejbMethod = _methodList.get(i);
599       MethodSignature sig = ejbMethod.getSignature();
600
601       if (sig.isMatch(method, intf) && bestCost < sig.getCost()) {
602         bestMethod = ejbMethod;
603         bestCost = sig.getCost();
604       }
605     }
606
607     return bestMethod;
608   }
609
610   /**
611    * returns the method list.
612    */

613   public ArrayList JavaDoc<EjbMethodPattern> getMethodList()
614   {
615     return _methodList;
616   }
617
618   /**
619    * Sets the transaction timeout.
620    */

621   public void setTransactionTimeout(Period timeout)
622   {
623     _transactionTimeout = timeout.getPeriod();
624   }
625
626   /**
627    * Gets the transaction timeout.
628    */

629   public long getTransactionTimeout()
630   {
631     return _transactionTimeout;
632   }
633
634   /**
635    * Sets the security identity
636    */

637   public void setSecurityIdentity(EjbSecurityIdentity securityIdentity)
638   {
639   }
640
641   /**
642    * Adds a list of dependencies.
643    */

644   public void addDependencyList(ArrayList JavaDoc<PersistentDependency> dependList)
645   {
646     for (int i = 0; dependList != null && i < dependList.size(); i++) {
647       addDependency(dependList.get(i));
648     }
649   }
650
651   /**
652    * Add a dependency.
653    */

654   public void addDepend(Path path)
655   {
656     addDependency(new Depend(path));
657   }
658
659   /**
660    * Add a dependency.
661    */

662   public void addDependency(PersistentDependency depend)
663   {
664     if (! _dependList.contains(depend))
665       _dependList.add(depend);
666   }
667
668   /**
669    * Add a dependency.
670    */

671   public void addDependency(Class JavaDoc cl)
672   {
673     addDependency(new ClassDependency(cl));
674   }
675
676   /**
677    * Gets the depend list.
678    */

679   public ArrayList JavaDoc<PersistentDependency> getDependList()
680   {
681     return _dependList;
682   }
683
684   /**
685    * Add a bean dependency.
686    */

687   public void addBeanDependency(String JavaDoc ejbName)
688   {
689     if (! _beanDependList.contains(ejbName))
690       _beanDependList.add(ejbName);
691   }
692
693   /**
694    * Gets the bean depend list.
695    */

696   public ArrayList JavaDoc<String JavaDoc> getBeanDependList()
697   {
698     return _beanDependList;
699   }
700
701   /**
702    * Adds an init program.
703    */

704   public void addInitProgram(BuilderProgram init)
705   {
706     if (_initProgram == null)
707       _initProgram = new BuilderProgramContainer();
708
709     _initProgram.addProgram(init);
710   }
711
712   /**
713    * Adds an undefined value, e.g. env-entry
714    */

715   public void addBuilderProgram(BuilderProgram init)
716   {
717     if (_serverProgram == null)
718       _serverProgram = new BuilderProgramContainer();
719
720     _serverProgram.addProgram(init);
721   }
722
723   /**
724    * Gets the init program.
725    */

726   public BuilderProgramContainer getInitProgram()
727   {
728     return _initProgram;
729   }
730
731   /**
732    * Gets the server program.
733    */

734   public BuilderProgramContainer getServerProgram()
735   {
736     return _serverProgram;
737   }
738
739   /**
740    * Configure initialization.
741    */

742   @PostConstruct
743   public void init()
744     throws ConfigException
745   {
746     try {
747       introspect();
748       
749       assembleBeanMethods();
750       
751       createViews();
752
753       /*
754       if (_jndiName == null) {
755         if (getRemoteHomeClass() != null)
756           _jndiName = getConfig().getRemoteJndiName() + "/" + _ejbName;
757         else
758           _jndiName = getConfig().getLocalJndiName() + "/" + _ejbName;
759       }
760       */

761     } catch (LineConfigException e) {
762       throw e;
763     } catch (ConfigException e) {
764       throw new LineConfigException(_location + e.getMessage(), e);
765     }
766   }
767
768   /**
769    * Configure initialization.
770    */

771   public void introspect()
772     throws ConfigException
773   {
774   }
775
776   /**
777    * Configure for amber.
778    */

779   public void configureAmber(AmberConfig config)
780     throws ConfigException
781   {
782   }
783
784   /**
785    * Creates the views.
786    */

787   protected void createViews()
788     throws ConfigException
789   {
790     if (_remoteHome != null) {
791       _remoteHomeView = createHomeView(_remoteHome, "RemoteHome");
792       _remoteHomeView.introspect();
793     }
794     
795     if (_remote != null) {
796       _remoteView = createObjectView(_remote, "Remote");
797       _remoteView.introspect();
798     }
799
800     if (_localHome != null) {
801       _localHomeView = createHomeView(_localHome, "LocalHome");
802       _localHomeView.introspect();
803     }
804     
805     if (_local != null) {
806       _localView = createObjectView(_local, "Local");
807       _localView.introspect();
808     }
809   }
810
811   /**
812    * Creates a home view.
813    */

814   protected EjbHomeView createHomeView(JClass homeClass, String JavaDoc prefix)
815     throws ConfigException
816   {
817     return new EjbHomeView(this, homeClass, prefix);
818   }
819
820   /**
821    * Creates an object view.
822    */

823   protected EjbObjectView createObjectView(JClass apiClass, String JavaDoc prefix)
824     throws ConfigException
825   {
826     return new EjbObjectView(this, apiClass, prefix);
827   }
828
829   /**
830    * Generates the class.
831    */

832   public void generate(JavaClassGenerator javaGen, boolean isAutoCompile)
833     throws Exception JavaDoc
834   {
835     String JavaDoc fullClassName = getSkeletonName();
836
837     if (javaGen.preload(fullClassName) != null) {
838     }
839     else if (isAutoCompile) {
840       GenClass genClass = assembleGenerator(fullClassName);
841
842       if (genClass != null)
843     javaGen.generate(genClass);
844     }
845   }
846
847   /**
848    * Deploys the bean.
849    */

850   public AbstractServer deployServer(EjbServerManager ejbManager,
851                      JavaClassGenerator javaGen)
852     throws ClassNotFoundException JavaDoc, ConfigException
853   {
854     throw new UnsupportedOperationException JavaDoc();
855   }
856      
857   /**
858    * Validates the remote interface.
859    */

860   protected void validateRemote(JClass objectClass)
861     throws ConfigException
862   {
863     JClass beanClass = getEJBClassWrapper();
864     String JavaDoc beanName = beanClass.getName();
865   
866     String JavaDoc objectName = objectClass.getName();
867
868     if (! objectClass.isPublic())
869       throw error(L.l("`{0}' must be public", objectName));
870   
871     if (! objectClass.isInterface())
872       throw error(L.l("`{0}' must be an interface", objectName));
873     
874     JMethod []methods = getMethods(objectClass);
875     for (int i = 0; i < methods.length; i++) {
876       JMethod method = methods[i];
877       String JavaDoc name = method.getName();
878       JClass []param = method.getParameterTypes();
879       JClass retType = method.getReturnType();
880
881       if (method.getDeclaringClass().isAssignableFrom(EJBObject JavaDoc.class))
882         continue;
883       if (method.getDeclaringClass().isAssignableFrom(EJBLocalObject JavaDoc.class))
884         continue;
885
886       if (objectClass.isAssignableTo(EJBObject JavaDoc.class))
887         validateException(method, java.rmi.RemoteException JavaDoc.class);
888       
889       if (name.startsWith("ejb")) {
890         throw error(L.l("`{0}' forbidden in {1}. Local or remote interfaces may not define ejbXXX methods.",
891                         getFullMethodName(method),
892                         objectName));
893       }
894
895       JClass returnType = method.getReturnType();
896         
897       if (objectClass.isAssignableTo(EJBObject JavaDoc.class) &&
898           (returnType.isAssignableTo(EJBLocalObject JavaDoc.class) ||
899            returnType.isAssignableTo(EJBLocalHome JavaDoc.class)))
900         throw error(L.l("`{0}' must not return `{1}' in {2}. Remote methods must not return local interfaces.",
901                         getFullMethodName(method),
902                         getShortClassName(returnType),
903                         objectClass.getName()));
904         
905       JMethod implMethod =
906         validateRemoteImplMethod(method.getName(), param,
907                                  method, objectClass);
908
909       if (! returnType.equals(implMethod.getReturnType())) {
910         throw error(L.l("{0}: `{1}' must return {2} to match {3}.{4}. Business methods must return the same type as the interface.",
911                         method.getDeclaringClass().getName(),
912                         getFullMethodName(method),
913                         implMethod.getReturnType().getName(),
914                         getShortClassName(implMethod.getDeclaringClass()),
915                         getFullMethodName(implMethod)));
916       }
917         
918       validateExceptions(method, implMethod.getExceptionTypes());
919     }
920   }
921
922   /**
923    * Check that a method exists, is public, not abstract.
924    *
925    * @param methodName the name of the method to check for
926    * @param args the expected method parameters
927    *
928    * @return the matching method
929    */

930   private JMethod validateRemoteImplMethod(String JavaDoc methodName,
931                        JClass []param,
932                        JMethod sourceMethod,
933                        JClass sourceClass)
934     throws ConfigException
935   {
936     JMethod method = null;
937     JClass beanClass = getEJBClassWrapper();
938
939     method = getMethod(beanClass, methodName, param);
940
941     if (method == null && sourceMethod != null) {
942       throw error(L.l("{0}: `{1}' expected to match {2}.{3}",
943                       beanClass.getName(),
944                       getFullMethodName(methodName, param),
945                       getShortClassName(sourceMethod.getDeclaringClass()),
946                       getFullMethodName(sourceMethod)));
947     }
948     else if (method == null) {
949       throw error(L.l("{0}: `{1}' expected",
950                       beanClass.getName(),
951                       getFullMethodName(methodName, param)));
952     }
953     /*
954     else if (Modifier.isAbstract(method.getModifiers()) &&
955              getBeanManagedPersistence()) {
956       throw error(L.l("{0}: `{1}' must not be abstract",
957                       beanClass.getName(),
958                       getFullMethodName(methodName, param)));
959     }
960     */

961     else if (! method.isPublic()) {
962       throw error(L.l("{0}: `{1}' must be public",
963                       beanClass.getName(),
964                       getFullMethodName(methodName, param)));
965     }
966     
967     if (method.isStatic()) {
968       throw error(L.l("{0}: `{1}' must not be static",
969                       beanClass.getName(),
970                       getFullMethodName(methodName, param)));
971     }
972     
973     if (method.isFinal()) {
974       throw error(L.l("{0}: `{1}' must not be final.",
975                       beanClass.getName(),
976                       getFullMethodName(methodName, param),
977                       beanClass.getName()));
978     }
979
980     return method;
981   }
982
983   JMethod validateNonFinalMethod(String JavaDoc methodName, JClass []param,
984                 boolean isOptional)
985     throws ConfigException
986   {
987     if (isOptional && getMethod(_ejbClass, methodName, param) == null)
988       return null;
989     else
990       return validateNonFinalMethod(methodName, param);
991   }
992
993   JMethod validateNonFinalMethod(String JavaDoc methodName, JClass []param)
994     throws ConfigException
995   {
996     return validateNonFinalMethod(methodName, param, null, null);
997   }
998     
999   JMethod validateNonFinalMethod(String JavaDoc methodName, JClass []param,
1000                 JMethod sourceMethod, JClass sourceClass)
1001    throws ConfigException
1002  {
1003    return validateNonFinalMethod(methodName, param,
1004                  sourceMethod, sourceClass, false);
1005  }
1006      
1007  /**
1008   * Check that a method exists, is public, not abstract, and not final.
1009   *
1010   * @param methodName the name of the method to check for
1011   * @param args the expected method parameters
1012   *
1013   * @return the matching method
1014   */

1015  JMethod validateNonFinalMethod(String JavaDoc methodName, JClass []param,
1016                 JMethod sourceMethod, JClass sourceClass,
1017                 boolean isOptional)
1018    throws ConfigException
1019  {
1020    JMethod method = validateMethod(methodName, param,
1021                    sourceMethod, sourceClass,
1022                    isOptional);
1023
1024    if (method == null && isOptional)
1025      return null;
1026
1027    if (method.isFinal())
1028      throw error(L.l("{0}: `{1}' must not be final",
1029                      _ejbClass.getName(),
1030                      getFullMethodName(method)));
1031
1032
1033    if (method.isStatic())
1034      throw error(L.l("{0}: `{1}' must not be static",
1035                      _ejbClass.getName(),
1036                      getFullMethodName(method)));
1037
1038    return method;
1039  }
1040
1041  JMethod validateMethod(String JavaDoc methodName, JClass []param)
1042    throws ConfigException
1043  {
1044    return validateMethod(methodName, param, null, null);
1045  }
1046
1047  /**
1048   * Check that a method exists, is public and is not abstract.
1049   *
1050   * @param methodName the name of the method to check for
1051   * @param args the expected method parameters
1052   *
1053   * @return the matching method
1054   */

1055  JMethod validateMethod(String JavaDoc methodName, JClass []param,
1056             JMethod sourceMethod, JClass sourceClass)
1057    throws ConfigException
1058  {
1059    return validateMethod(methodName, param, sourceMethod, sourceClass, false);
1060  }
1061
1062  /**
1063   * Check that a method exists, is public and is not abstract.
1064   *
1065   * @param methodName the name of the method to check for
1066   * @param args the expected method parameters
1067   *
1068   * @return the matching method
1069   */

1070  JMethod validateMethod(String JavaDoc methodName, JClass []param,
1071                        JMethod sourceMethod, JClass sourceClass,
1072            boolean isOptional)
1073    throws ConfigException
1074  {
1075    JMethod method = null;
1076    
1077    method = getMethod(_ejbClass, methodName, param);
1078
1079    if (method == null && isOptional)
1080      return null;
1081
1082    if (method == null && sourceMethod != null) {
1083      throw error(L.l("{0}: missing `{1}' needed to match {2}.{3}",
1084                      _ejbClass.getName(),
1085                      getFullMethodName(methodName, param),
1086                      getShortClassName(sourceClass),
1087                      getFullMethodName(sourceMethod)));
1088    }
1089    else if (method == null) {
1090      throw error(L.l("{0}: expected `{1}'",
1091                      _ejbClass.getName(),
1092                      getFullMethodName(methodName, param)));
1093    }
1094    
1095    JClass declaringClass = method.getDeclaringClass();
1096
1097    if (method.isAbstract()) {
1098      if (method.getDeclaringClass().getName().equals("javax.ejb.EntityBean"))
1099        throw error(L.l("{0}: `{1}' must not be abstract. Entity beans must implement the methods in EntityBean.",
1100                        _ejbClass.getName(),
1101                        getFullMethodName(methodName, param)));
1102      else if (method.getDeclaringClass().getName().equals("javax.ejb.SessionBean"))
1103        throw error(L.l("{0}: `{1}' must not be abstract. Session beans must implement the methods in SessionBean.",
1104                        _ejbClass.getName(),
1105                        getFullMethodName(methodName, param)));
1106      else if (sourceMethod != null)
1107        throw error(L.l("{0}: `{1}' must not be abstract. All methods from `{2}' must be implemented in the bean.",
1108                        _ejbClass.getName(),
1109                        getFullMethodName(methodName, param),
1110                        sourceClass.getName()));
1111      else
1112        throw error(L.l("{0}: `{1}' must not be abstract. Business methods must be implemented.",
1113                        _ejbClass.getName(),
1114                        getFullMethodName(methodName, param)));
1115    } else if (! method.isPublic()) {
1116      throw error(L.l("{0}: `{1}' must be public. Business method implementations must be public.",
1117                      _ejbClass.getName(),
1118                      getFullMethodName(methodName, param)));
1119    }
1120    if (method.isStatic()) {
1121      throw error(L.l("{0}: `{1}' must not be static. Business method implementations must not be static.",
1122                      _ejbClass.getName(),
1123                      getFullMethodName(method)));
1124    }
1125
1126    return method;
1127  }
1128
1129  protected String JavaDoc getSkeletonName()
1130  {
1131    String JavaDoc className = getEJBClass().getName();
1132    int p = className.lastIndexOf('.');
1133
1134    if (p > 0)
1135      className = className.substring(p + 1);
1136
1137    String JavaDoc ejbName = getEJBName();
1138
1139    String JavaDoc fullClassName = "_ejb." + ejbName + "." + className + "__EJB";
1140
1141    return JavaClassGenerator.cleanClassName(fullClassName);
1142  }
1143
1144  /**
1145   * Assembles the generator.
1146   */

1147  protected GenClass assembleGenerator(String JavaDoc fullClassName)
1148    throws NoSuchMethodException JavaDoc, ConfigException
1149  {
1150    int p = fullClassName.lastIndexOf('.');
1151    String JavaDoc className = fullClassName;
1152    if (p > 0)
1153      className = fullClassName.substring(p + 1);
1154
1155    BeanAssembler assembler = createAssembler(fullClassName);
1156
1157    if (assembler == null)
1158      return null;
1159
1160    addImports(assembler);
1161
1162    assembler.addHeaderComponent(getEJBClassWrapper(),
1163                 fullClassName,
1164                 getFullImplName());
1165
1166    assembleMethods(assembler, fullClassName);
1167    
1168    // getEJBClassName());
1169

1170    if (_remoteHomeView != null)
1171      _remoteHomeView.assembleView(assembler, fullClassName);
1172    
1173    if (_remoteView != null)
1174      _remoteView.assembleView(assembler, fullClassName);
1175
1176    if (_localHomeView != null)
1177      _localHomeView.assembleView(assembler, fullClassName);
1178    
1179    if (_localView != null)
1180      _localView.assembleView(assembler, fullClassName);
1181
1182    for (PersistentDependency depend : _dependList) {
1183      assembler.addDependency(depend);
1184    }
1185
1186    assembler.addDependency(new JClassDependency(_ejbClass));
1187
1188    if (_remoteHome != null)
1189      assembler.addDependency(new JClassDependency(_remoteHome));
1190
1191    if (_remote != null)
1192      assembler.addDependency(new JClassDependency(_remote));
1193
1194    if (_localHome != null)
1195      assembler.addDependency(new JClassDependency(_localHome));
1196
1197    if (_local != null)
1198      assembler.addDependency(new JClassDependency(_local));
1199
1200    return assembler.getAssembledGenerator();
1201  }
1202
1203  /**
1204   * Adds the assemblers.
1205   */

1206  protected void addImports(BeanAssembler assembler)
1207  {
1208    assembler.addImport("javax.ejb.*");
1209    assembler.addImport("com.caucho.vfs.*");
1210    
1211    assembler.addImport("com.caucho.ejb.xa.EjbTransactionManager");
1212    assembler.addImport("com.caucho.ejb.xa.TransactionContext");
1213    
1214    assembler.addImport("com.caucho.ejb.AbstractContext");
1215  }
1216
1217  /**
1218   * Creates the assembler for the bean.
1219   */

1220  protected BeanAssembler createAssembler(String JavaDoc fullClassName)
1221  {
1222    return null;
1223  }
1224
1225  /**
1226   * Introspects the bean's methods.
1227   */

1228  protected void assembleBeanMethods()
1229    throws ConfigException
1230  {
1231    // find API methods matching an implementation method
1232
JMethod []implMethods = getMethods(getEJBClassWrapper());
1233
1234    for (int i = 0; i < implMethods.length; i++) {
1235      JMethod method = implMethods[i];
1236
1237      EjbBaseMethod ejbMethod = null;
1238      
1239      String JavaDoc name = method.getName();
1240
1241      if (name.startsWith("ejb")) {
1242    ejbMethod = introspectEJBMethod(method);
1243
1244    if (ejbMethod != null)
1245      _methodMap.put(ejbMethod.getMethod().getFullName(), ejbMethod);
1246      }
1247      else
1248    validateImplMethod(method);
1249    }
1250  }
1251
1252  /**
1253   * Assembles the generator methods.
1254   */

1255  protected void assembleMethods(BeanAssembler assembler,
1256                 String JavaDoc fullClassName)
1257    throws ConfigException
1258  {
1259    for (EjbBaseMethod method : _methodMap.values()) {
1260      assembler.addMethod(method.assemble(assembler, fullClassName));
1261    }
1262  }
1263
1264  /**
1265   * Introspects an ejb method.
1266   */

1267  protected EjbBaseMethod introspectEJBMethod(JMethod method)
1268    throws ConfigException
1269  {
1270    return null;
1271  }
1272  
1273  /**
1274   * Validates an implementation method.
1275   */

1276  protected void validateImplMethod(JMethod method)
1277    throws ConfigException
1278  {
1279  }
1280  
1281  /**
1282   * Assembles methods.
1283   */

1284  protected void assembleMethods(BeanAssembler assembler,
1285                 ViewClass view,
1286                 String JavaDoc contextClassName,
1287                 JMethod []methods,
1288                 String JavaDoc prefix)
1289    throws NoSuchMethodException JavaDoc
1290  {
1291    for (int i = 0; i < methods.length; i++) {
1292      String JavaDoc className = methods[i].getDeclaringClass().getName();
1293      String JavaDoc methodName = methods[i].getName();
1294      JClass []args = methods[i].getParameterTypes();
1295
1296      if (className.startsWith("javax.ejb.")) {
1297      }
1298      else if (isOld(methods, methods[i], i)) {
1299      }
1300      else if (methodName.equals("equals") && args.length == 1 &&
1301           args[0].equals(JClass.OBJECT)) {
1302      }
1303      else if (methodName.equals("hashCode") && args.length == 0) {
1304      }
1305      else {
1306    JMethod beanMethod = null;
1307
1308    JClass ejbClass = getEJBClassWrapper();
1309      
1310    beanMethod = ejbClass.getMethod(methods[i].getName(),
1311                    methods[i].getParameterTypes());
1312
1313    if (beanMethod == null)
1314      throw new NoSuchMethodException JavaDoc("Can't find public method " +
1315                      methods[i].getFullName());
1316
1317    CallChain call = new MethodCallChain(beanMethod);
1318    call = view.createPoolChain(call);
1319    call = getTransactionChain(call, beanMethod, prefix);
1320    call = getSecurityChain(call, beanMethod, prefix);
1321
1322    view.addMethod(new BaseMethod(methods[i], call));
1323      }
1324    }
1325  }
1326
1327  protected void assembleHomeMethods(BeanAssembler assembler,
1328                     BaseClass baseClass,
1329                     String JavaDoc contextClassName,
1330                     JClass homeClass,
1331                     String JavaDoc prefix)
1332    throws NoSuchMethodException JavaDoc
1333  {
1334    JMethod []methods = getMethods(homeClass);
1335
1336    for (int i = 0; i < methods.length; i++) {
1337      String JavaDoc className = methods[i].getDeclaringClass().getName();
1338      String JavaDoc methodName = methods[i].getName();
1339
1340      if (className.startsWith("javax.ejb.")) {
1341      }
1342      else if (isOld(methods, methods[i], i)) {
1343      }
1344      else if (methodName.startsWith("create")) {
1345        JMethod beanMethod = null;
1346
1347        String JavaDoc name = ("ejbCreate" + Character.toUpperCase(methodName.charAt(0))
1348                       + methodName.substring(1));
1349
1350        try {
1351          beanMethod = getEJBClassWrapper().getMethod(name,
1352                           methods[i].getParameterTypes());
1353        } catch (Throwable JavaDoc e) {
1354        }
1355
1356    /*
1357    baseClass.addMethod(assembler.createCreateMethod(methods[i],
1358                             contextClassName,
1359                             prefix));
1360    */

1361
1362    /*
1363    if (isStateless()) {
1364    }
1365    else {
1366      CallChain call = new MethodCallChain(beanMethod);
1367      call = getTransactionChain(call, beanMethod, prefix);
1368
1369      baseClass.addMethod(new BaseMethod(methods[i], call));
1370    }
1371    */

1372    
1373        //printCreate(methods[i], prefix);
1374
}
1375      else if (methodName.startsWith("find")) {
1376        //printFind(methods[i], prefix);
1377
}
1378      else {
1379        JMethod beanMethod = null;
1380
1381        String JavaDoc name = ("ejbHome" + Character.toUpperCase(methodName.charAt(0))
1382                       + methodName.substring(1));
1383
1384        try {
1385          beanMethod = getEJBClassWrapper().getMethod(name,
1386                           methods[i].getParameterTypes());
1387        } catch (Exception JavaDoc e) {
1388          throw new NoSuchMethodException JavaDoc("can't find method " + name);
1389        }
1390
1391    CallChain call = new MethodCallChain(beanMethod);
1392    call = getTransactionChain(call, beanMethod, prefix);
1393    call = getSecurityChain(call, beanMethod, prefix);
1394
1395    baseClass.addMethod(new BaseMethod(methods[i], call));
1396      }
1397    }
1398  }
1399
1400  protected CallChain getTransactionChain(CallChain next,
1401                      JMethod method,
1402                      String JavaDoc prefix)
1403  {
1404    return TransactionChain.create(next, getTransactionAttribute(method, prefix));
1405  }
1406
1407  protected CallChain getSecurityChain(CallChain next,
1408                       JMethod method,
1409                       String JavaDoc prefix)
1410  {
1411    EjbMethodPattern ejbMethod = getMethodPattern(method, prefix);
1412
1413    ArrayList JavaDoc<String JavaDoc> roles = null;
1414
1415    if (ejbMethod != null)
1416      roles = ejbMethod.getRoles();
1417
1418    if (roles == null) {
1419      ejbMethod = getMethodPattern(null, prefix);
1420      if (ejbMethod != null)
1421    roles = ejbMethod.getRoles();
1422    }
1423
1424    if (roles == null) {
1425      ejbMethod = getMethodPattern(method, null);
1426      if (ejbMethod != null)
1427    roles = ejbMethod.getRoles();
1428    }
1429
1430    if (roles == null) {
1431      ejbMethod = getMethodPattern(null, null);
1432      if (ejbMethod != null)
1433    roles = ejbMethod.getRoles();
1434    }
1435
1436    if (roles != null)
1437      return new UserInRoleChain(next, roles);
1438    else
1439      return next;
1440  }
1441
1442  /**
1443   * Check that a method is public.
1444   *
1445   * @return the matching method
1446   */

1447  protected void validatePublicMethod(JMethod method)
1448    throws ConfigException
1449  {
1450    if (! method.isPublic()) {
1451      throw error(L.l("{0}: '{1}' must be public.",
1452                      _ejbClass.getName(),
1453                      getFullMethodName(method)));
1454    }
1455    else if (method.isStatic()) {
1456      throw error(L.l("{0}: `{1}' must not be static.",
1457                      _ejbClass.getName(),
1458                      getFullMethodName(method)));
1459    }
1460  }
1461
1462  /**
1463   * True if we've already handled the method.
1464   */

1465  static boolean isOld(JMethod []methods, JMethod method, int index)
1466  {
1467    for (int i = 0; i < index; i++) {
1468      if (isEquiv(methods[i], method))
1469        return true;
1470    }
1471
1472    return false;
1473  }
1474
1475  static boolean isEquiv(JMethod oldMethod, JMethod method)
1476  {
1477    if (! oldMethod.getName().equals(method.getName()))
1478      return false;
1479
1480    JClass []oldParam = oldMethod.getParameterTypes();
1481    JClass []param = method.getParameterTypes();
1482
1483    if (oldParam.length != param.length)
1484      return false;
1485
1486    for (int j = 0; j < param.length; j++) {
1487      if (! param[j].equals(oldParam[j]))
1488        return false;
1489    }
1490
1491    return true;
1492  }
1493
1494  /**
1495   * Returns the matching transaction attribute.
1496   */

1497  public int getTransactionAttribute(JMethod method, String JavaDoc intf)
1498  {
1499    if (! isContainerTransaction())
1500      return EjbMethod.TRANS_BEAN;
1501
1502    int transaction = EjbMethod.TRANS_REQUIRED;
1503    
1504    EjbMethodPattern ejbMethod = getMethodPattern(null, null);
1505
1506    if (ejbMethod != null)
1507      transaction = ejbMethod.getTransactionType();
1508    
1509    ejbMethod = getMethodPattern(method, null);
1510
1511    if (ejbMethod != null)
1512      transaction = ejbMethod.getTransactionType();
1513    
1514    ejbMethod = getMethodPattern(method, intf);
1515
1516    if (ejbMethod != null)
1517      transaction = ejbMethod.getTransactionType();
1518
1519    return transaction;
1520  }
1521
1522  /**
1523   * Finds the method in the class.
1524   *
1525   * @param cl owning class
1526   * @param method source method
1527   *
1528   * @return the matching method or null if non matches.
1529   */

1530  JMethod getMethod(String JavaDoc methodName, JClass []paramTypes)
1531  {
1532    return getMethod(getEJBClassWrapper(), methodName, paramTypes);
1533  }
1534
1535  /**
1536   * Finds the method in the class.
1537   *
1538   * @param cl owning class
1539   * @param method source method
1540   *
1541   * @return the matching method or null if non matches.
1542   */

1543  public static JMethod getMethod(JClass cl, JMethod sourceMethod)
1544  {
1545    return getMethod(cl, sourceMethod.getName(),
1546                     sourceMethod.getParameterTypes());
1547  }
1548  
1549  /**
1550   * Finds the method in the class.
1551   *
1552   * @param cl owning class
1553   * @param name method name to match
1554   * @param params method parameters to match
1555   *
1556   * @return the matching method or null if non matches.
1557   */

1558  public static JMethod getMethod(JClass cl, String JavaDoc name, JClass []param)
1559  {
1560    if (cl == null)
1561      return null;
1562    
1563    JMethod []methods = cl.getDeclaredMethods();
1564
1565    for (int i = 0; i < methods.length; i++) {
1566      if (isMatch(methods[i], name, param))
1567    return methods[i];
1568    }
1569    
1570    JMethod method = getMethod(cl.getSuperClass(), name, param);
1571    if (method != null)
1572      return method;
1573    
1574    for (JClass iface : cl.getInterfaces()) {
1575      method = getMethod(iface, name, param);
1576      if (method != null)
1577    return method;
1578    }
1579    
1580    return null;
1581  }
1582
1583  static boolean isMatch(JMethod methodA, JMethod methodB)
1584  {
1585    if (methodA == methodB)
1586      return true;
1587    else if (methodA == null || methodB == null)
1588      return false;
1589    else
1590      return isMatch(methodA, methodB.getName(), methodB.getParameterTypes());
1591  }
1592
1593  static boolean isMatch(JMethod method, String JavaDoc name, JClass []param)
1594  {
1595    if (! method.getName().equals(name))
1596      return false;
1597    
1598    JClass []mparam = method.getParameterTypes();
1599      
1600    if (mparam.length != param.length)
1601      return false;
1602    
1603    for (int j = 0; j < param.length; j++) {
1604      if (! mparam[j].equals(param[j]))
1605    return false;
1606    }
1607
1608    return true;
1609  }
1610  
1611  /**
1612   * Finds the method in the class.
1613   *
1614   * @param cl owning class
1615   * @param name method name to match
1616   * @param params method parameters to match
1617   *
1618   * @return the matching method or null if non matches.
1619   */

1620  static JMethod findMethod(MethodSignature sig, JClass cl, String JavaDoc intf)
1621  {
1622    if (cl == null)
1623      return null;
1624    
1625    JMethod []methods = getMethods(cl);
1626
1627    for (int i = 0; i < methods.length; i++) {
1628      if (sig.isMatch(methods[i], intf))
1629    return methods[i];
1630    }
1631
1632    return null;
1633  }
1634  
1635  /**
1636   * Returns all the method in the class.
1637   */

1638  static JMethod []getMethods(JClass cl)
1639  {
1640    Map JavaDoc<JClass,SoftReference JavaDoc<JMethod[]>> methodMap = _methodCache.get();
1641
1642    if (methodMap == null) {
1643      methodMap = new WeakHashMap JavaDoc<JClass,SoftReference JavaDoc<JMethod[]>>();
1644      _methodCache.set(methodMap);
1645    }
1646
1647    SoftReference JavaDoc<JMethod[]> methodArrayRef = methodMap.get(cl);
1648    JMethod []methodArray = null;
1649
1650    if (methodArrayRef != null) {
1651      methodArray = methodArrayRef.get();
1652
1653      if (methodArray != null)
1654    return methodArray;
1655    }
1656
1657    ArrayList JavaDoc<JMethod> methods = new ArrayList JavaDoc<JMethod>();
1658
1659    getMethods(methods, cl);
1660
1661    methodArray = methods.toArray(new JMethod[methods.size()]);
1662
1663    methodMap.put(cl, new SoftReference JavaDoc<JMethod[]>(methodArray));
1664    
1665    return methodArray;
1666  }
1667
1668  /**
1669   * Returns all the method in the class.
1670   */

1671  static void getMethods(ArrayList JavaDoc<JMethod> methods, JClass cl)
1672  {
1673    if (cl == null)
1674      return;
1675    
1676    JMethod []subMethods = cl.getDeclaredMethods();
1677
1678    for (int i = 0; i < subMethods.length; i++) {
1679      if (findMethod(methods, subMethods[i]) == null) {
1680        methods.add(subMethods[i]);
1681      }
1682    }
1683
1684    getMethods(methods, cl.getSuperClass());
1685
1686    JClass []interfaces = cl.getInterfaces();
1687    for (int i = 0; interfaces != null && i < interfaces.length; i++) {
1688      getMethods(methods, interfaces[i]);
1689    }
1690  }
1691
1692  /**
1693   * Finds the method in the class.
1694   *
1695   * @param cl owning class
1696   * @param method source method
1697   *
1698   * @return the matching method or null if non matches.
1699   */

1700  static JMethod findMethod(ArrayList JavaDoc<JMethod> methods, JMethod method)
1701  {
1702    loop:
1703    for (int i = 0; i < methods.size(); i++) {
1704      JMethod oldMethod = methods.get(i);
1705
1706      if (! method.getName().equals(oldMethod.getName()))
1707    continue loop;
1708
1709      JClass []aParamTypes = oldMethod.getParameterTypes();
1710      JClass []bParamTypes = method.getParameterTypes();
1711
1712      if (aParamTypes.length != bParamTypes.length)
1713    continue loop;
1714      
1715      for (int j = 0; j < aParamTypes.length; j++) {
1716    if (! aParamTypes[j].equals(bParamTypes[j]))
1717      continue loop;
1718      }
1719
1720      return oldMethod;
1721    }
1722
1723    return null;
1724  }
1725
1726  /**
1727   * Returns a full method name with arguments.
1728   */

1729  static String JavaDoc getFullMethodName(JMethod method)
1730  {
1731    return getFullMethodName(method.getName(), method.getParameterTypes());
1732  }
1733  
1734  /**
1735   * Returns a full method name with arguments.
1736   */

1737  static String JavaDoc getFullMethodName(String JavaDoc methodName, JClass []params)
1738  {
1739    String JavaDoc name = methodName + "(";
1740
1741    for (int i = 0; i < params.length; i++) {
1742      if (i != 0)
1743        name += ", ";
1744
1745      name += getShortClassName(params[i]);
1746    }
1747
1748    return name + ")";
1749  }
1750
1751  /**
1752   * Returns a printable version of a class.
1753   */

1754  static String JavaDoc getClassName(JClass cl)
1755  {
1756    if (cl == null)
1757      return "null";
1758    else if (cl.isArray())
1759      return getClassName(cl.getComponentType()) + "[]";
1760    else if (cl.getName().startsWith("java")) {
1761      int p = cl.getName().lastIndexOf('.');
1762
1763      return cl.getName().substring(p + 1);
1764    }
1765    else
1766      return cl.getName();
1767  }
1768
1769  /**
1770   * Returns a printable version of a class.
1771   */

1772  static String JavaDoc getShortClassName(JClass cl)
1773  {
1774    if (cl.isArray())
1775      return getShortClassName(cl.getComponentType()) + "[]";
1776    else {
1777      int p = cl.getName().lastIndexOf('.');
1778
1779      return cl.getName().substring(p + 1);
1780    }
1781  }
1782
1783  /**
1784   * Tests is a method is declared in a class.
1785   */

1786  boolean classHasMethod(JMethod method, JClass cl)
1787  {
1788    try {
1789      JMethod match = cl.getMethod(method.getName(),
1790                                  method.getParameterTypes());
1791      return match != null;
1792    } catch (Exception JavaDoc e) {
1793      return false;
1794    }
1795  }
1796  
1797  void validateException(JMethod method, Class JavaDoc e)
1798    throws ConfigException
1799  {
1800    validateException(method, new JClassWrapper(e, _jClassLoader));
1801  }
1802  
1803  void validateException(JMethod method, JClass e)
1804    throws ConfigException
1805  {
1806    validateExceptions(method, new JClass[] { e });
1807  }
1808  
1809  /**
1810   * Check that the method throws the expected exceptions.
1811   *
1812   * @param method the method to test
1813   * @param exn the expected exceptions
1814   */

1815  void validateExceptions(JMethod method, JClass []exn)
1816    throws ConfigException
1817  {
1818    JClass []methodExceptions = method.getExceptionTypes();
1819
1820    loop:
1821    for (int i = 0; i < exn.length; i++) {
1822      if (exn[i].isAssignableTo(RuntimeException JavaDoc.class))
1823        continue;
1824
1825      for (int j = 0; j < methodExceptions.length; j++) {
1826        if (methodExceptions[j].isAssignableFrom(exn[i]))
1827          continue loop;
1828      }
1829
1830      throw new ConfigException(L.l("{2}: `{0}' must throw {1}.",
1831                                    getFullMethodName(method),
1832                                    exn[i].getName(),
1833                                    method.getDeclaringClass().getName()));
1834    }
1835  }
1836
1837  void validateExceptions(JMethod caller, JMethod callee)
1838    throws ConfigException
1839  {
1840    JClass []exn = callee.getExceptionTypes();
1841    JClass missing = findMissingException(caller, exn);
1842    
1843    if (missing != null) {
1844      throw error(L.l("{0}: `{1}' must throw {2}.",
1845                      caller.getDeclaringClass().getName(),
1846                      getFullMethodName(caller),
1847                      getShortClassName(missing),
1848                      caller.getDeclaringClass().getName()) +
1849                  L.l(" {0} must throw all {1}.{2} exceptions.",
1850                      caller.getName(),
1851                      getShortClassName(callee.getDeclaringClass()),
1852                      callee.getName()));
1853    }
1854  }
1855
1856  /**
1857   * Finds any exception in the exception array that the method isn't
1858   * throwing.
1859   *
1860   * @param method the method which should throw a superset of exceptions.
1861   * @param exn an array of exceptions the method should throw.
1862   *
1863   * @return the first missing exception
1864   */

1865  JClass findMissingException(JMethod method, JClass []exn)
1866    throws ConfigException
1867  {
1868    JClass []methodExceptions = method.getExceptionTypes();
1869
1870    for (int i = 0; i < exn.length; i++) {
1871      if (! hasException(method, exn[i]) &&
1872          ! exn[i].isAssignableTo(RuntimeException JavaDoc.class))
1873        return exn[i];
1874    }
1875
1876    return null;
1877  }
1878  
1879  boolean hasException(JMethod method, JClass exn)
1880    throws ConfigException
1881  {
1882    JClass []methodExceptions = method.getExceptionTypes();
1883
1884    for (int j = 0; j < methodExceptions.length; j++) {
1885      if (methodExceptions[j].isAssignableFrom(exn))
1886        return true;
1887    }
1888
1889    return false;
1890  }
1891  
1892  boolean hasException(JMethod method, Class JavaDoc exn)
1893    throws ConfigException
1894  {
1895    JClass []methodExceptions = method.getExceptionTypes();
1896
1897    for (int j = 0; j < methodExceptions.length; j++) {
1898      if (methodExceptions[j].isAssignableFrom(exn))
1899        return true;
1900    }
1901
1902    return false;
1903  }
1904
1905  /**
1906   * Returns an error.
1907   */

1908  public ConfigException error(String JavaDoc msg)
1909  {
1910    return new ConfigException(msg);
1911  }
1912}
1913
Popular Tags