1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: EntryPoint.java,v 1.7 2004/02/17 04:24:21 minchau Exp $
  18. */
  19. package com.sun.org.apache.xml.internal.utils.synthetic.reflection;
  20. import com.sun.org.apache.xml.internal.utils.synthetic.SynthesisException;
  21. /*
  22. * OPEN ISSUES:
  23. * Reflection doesn't tell us about deprecation; if we want
  24. * that info, MFC advises mousing our way into the class (ugh).
  25. * Should we at least model that for synthetics?
  26. */
  27. /**
  28. * API/behaviors shared between Constructors and Methods.
  29. * They're mostly similar, except for what they proxy and
  30. * a few specific calls (name, invoke/getInstance).
  31. * @xsl.usage internal
  32. */
  33. abstract public class EntryPoint implements Member
  34. {
  35. /** Field realep */
  36. protected Object realep;
  37. /** Field declaringclass */
  38. private com.sun.org.apache.xml.internal.utils.synthetic.Class declaringclass = null;
  39. /** Field returntype */
  40. protected com.sun.org.apache.xml.internal.utils.synthetic.Class returntype = null;
  41. /** Field parameternames */
  42. private String[] parameternames = new String[0];
  43. /** Field parametertypes */
  44. private com.sun.org.apache.xml.internal.utils.synthetic.Class[] parametertypes =
  45. new com.sun.org.apache.xml.internal.utils.synthetic.Class[0];
  46. /** Field exceptiontypes */
  47. private com.sun.org.apache.xml.internal.utils.synthetic.Class[] exceptiontypes =
  48. new com.sun.org.apache.xml.internal.utils.synthetic.Class[0];
  49. ;
  50. /** Field modifiers */
  51. private int modifiers;
  52. /** Field name */
  53. protected String name = null; // for Methods
  54. // For synthesis:
  55. /** Field body */
  56. private StringBuffer body = null;
  57. /** Field language */
  58. private String language = null;
  59. // For reifying:
  60. /** Field realE, realP */
  61. Class[] realE, realP;
  62. /**
  63. * Insert the method's description here.
  64. * <p>
  65. * Creation date: (12-27-99 2:31:39 PM)
  66. * @param realConstructor java.lang.reflect.Constructor
  67. *
  68. * @param declaringclass
  69. */
  70. public EntryPoint(com.sun.org.apache.xml.internal.utils.synthetic.Class declaringclass)
  71. {
  72. this.declaringclass = declaringclass;
  73. }
  74. /**
  75. * Nonpublic constructor. Wrap this to appropriate "real" type
  76. *
  77. * @param ep
  78. * @param declaringclass
  79. *
  80. * @throws IllegalArgumentException
  81. */
  82. protected EntryPoint(
  83. Object ep, com.sun.org.apache.xml.internal.utils.synthetic.Class declaringclass)
  84. throws IllegalArgumentException
  85. {
  86. realep = ep;
  87. this.declaringclass = declaringclass;
  88. if (ep instanceof java.lang.reflect.Method)
  89. {
  90. java.lang.reflect.Method m = (java.lang.reflect.Method) ep;
  91. if (declaringclass == null)
  92. {
  93. declaringclass = com.sun.org.apache.xml.internal.utils.synthetic.Class.forClass(
  94. m.getDeclaringClass());
  95. }
  96. name = m.getName();
  97. modifiers = m.getModifiers();
  98. returntype =
  99. com.sun.org.apache.xml.internal.utils.synthetic.Class.forClass(m.getReturnType());
  100. realP = m.getParameterTypes();
  101. realE = m.getExceptionTypes();
  102. }
  103. else if (ep instanceof java.lang.reflect.Constructor)
  104. {
  105. java.lang.reflect.Constructor c = (java.lang.reflect.Constructor) ep;
  106. if (declaringclass == null)
  107. {
  108. declaringclass = com.sun.org.apache.xml.internal.utils.synthetic.Class.forClass(
  109. c.getDeclaringClass());
  110. }
  111. name = declaringclass.getShortName();
  112. modifiers = c.getModifiers();
  113. returntype = declaringclass;
  114. realP = c.getParameterTypes();
  115. realE = c.getExceptionTypes();
  116. }
  117. else
  118. throw new IllegalArgumentException();
  119. }
  120. /**
  121. * Nonpublic constructor. Wrap this to appropriate "real" type
  122. *
  123. * @param ep
  124. *
  125. * @throws IllegalArgumentException
  126. */
  127. protected EntryPoint(Object ep) throws IllegalArgumentException
  128. {
  129. this(ep, null);
  130. }
  131. /**
  132. * Compares this against the specified
  133. * object. Returns true if the objects are the same.
  134. * Two EntryPoints are the same if they were
  135. * declared by the same class, have the same name
  136. * (or are both ctors) and have the same
  137. * formal parameter types.
  138. *
  139. * @param obj
  140. *
  141. */
  142. public boolean equals(Object obj)
  143. {
  144. EntryPoint otherep = null;
  145. if (obj instanceof EntryPoint)
  146. otherep = (EntryPoint) obj;
  147. else if (obj instanceof java.lang.reflect.Constructor
  148. || obj instanceof java.lang.reflect.Method)
  149. otherep = (EntryPoint) obj;
  150. return (otherep != null && ((this instanceof Constructor && otherep instanceof Constructor) || (this instanceof Method && otherep instanceof Method && this.getName().equals(
  151. otherep.getName()))) && otherep.getDeclaringClass().equals(
  152. declaringclass) && otherep.getParameterTypes().equals(
  153. parametertypes));
  154. }
  155. /**
  156. * Returns the Class object representing the class that
  157. * declares the constructor represented by this
  158. * Constructor object.
  159. *
  160. */
  161. public com.sun.org.apache.xml.internal.utils.synthetic.Class getDeclaringClass()
  162. {
  163. return declaringclass;
  164. }
  165. /**
  166. * Returns the Class object representing the class that
  167. * will be returned by this EntryPoint. Needed by the Method
  168. * API, but made meaningful for Constructors as well.
  169. *
  170. */
  171. public com.sun.org.apache.xml.internal.utils.synthetic.Class getReturnType()
  172. {
  173. return returntype;
  174. }
  175. /**
  176. * Returns an array of Class objects that represent the
  177. * types of the checked exceptions thrown by the
  178. * underlying constructor represented by this
  179. * Constructor object. Returns an array of length 0 if
  180. * the constructor throws no checked exceptions.
  181. *
  182. */
  183. public com.sun.org.apache.xml.internal.utils.synthetic.Class[] getExceptionTypes()
  184. {
  185. if (realep != null && exceptiontypes == null)
  186. {
  187. exceptiontypes =
  188. new com.sun.org.apache.xml.internal.utils.synthetic.Class[realE.length];
  189. for (int i = 0; i < realE.length; ++i)
  190. {
  191. exceptiontypes[i] =
  192. com.sun.org.apache.xml.internal.utils.synthetic.Class.forClass(realE[i]);
  193. }
  194. realE = null;
  195. }
  196. return exceptiontypes;
  197. }
  198. /**
  199. * Method addExceptionType
  200. *
  201. *
  202. * @param exception
  203. *
  204. * @throws SynthesisException
  205. */
  206. public void addExceptionType(
  207. com.sun.org.apache.xml.internal.utils.synthetic.Class exception)
  208. throws SynthesisException
  209. {
  210. if (realep != null)
  211. throw new SynthesisException(SynthesisException.REIFIED);
  212. com.sun.org.apache.xml.internal.utils.synthetic.Class[] e =
  213. new com.sun.org.apache.xml.internal.utils.synthetic.Class[exceptiontypes.length + 1];
  214. System.arraycopy(exceptiontypes, 0, e, 0, exceptiontypes.length);
  215. e[exceptiontypes.length] = exception;
  216. exceptiontypes = e;
  217. }
  218. /**
  219. * Returns the Java language modifiers for the
  220. * constructor represented by this Constructor object,
  221. * as an integer. The Modifier class should be used to
  222. * decode the modifiers.
  223. *
  224. */
  225. public int getModifiers()
  226. {
  227. return modifiers;
  228. }
  229. /**
  230. * Member method. C'tor's name is always that of the defining class.
  231. * Methods have a "real" name.
  232. * Creation date: (12-25-99 1:32:06 PM)
  233. * @return java.lang.String
  234. */
  235. public java.lang.String getName()
  236. {
  237. if (this instanceof Constructor)
  238. return declaringclass.getShortName();
  239. return name;
  240. }
  241. /**
  242. * Member method. C'tor's name is always that of the defining class.
  243. * Methods have a "real" name.
  244. * Creation date: (12-25-99 1:32:06 PM)
  245. *
  246. * @param name
  247. * @return java.lang.String
  248. *
  249. * @throws SynthesisException
  250. */
  251. public void setName(String name) throws SynthesisException
  252. {
  253. if (realep != null)
  254. throw new SynthesisException(SynthesisException.REIFIED);
  255. this.name = name;
  256. }
  257. /**
  258. * Returns an array of Class objects that represent the
  259. * formal parameter types, in declaration order, of the
  260. * constructor represented by this Constructor object.
  261. * Returns an array of length 0 if the underlying
  262. * constructor takes no parameters.
  263. *
  264. */
  265. public com.sun.org.apache.xml.internal.utils.synthetic.Class[] getParameterTypes()
  266. {
  267. if (realep != null && parametertypes == null)
  268. {
  269. parametertypes =
  270. new com.sun.org.apache.xml.internal.utils.synthetic.Class[realP.length];
  271. for (int i = 0; i < realP.length; ++i)
  272. {
  273. parametertypes[i] =
  274. com.sun.org.apache.xml.internal.utils.synthetic.Class.forClass(realP[i]);
  275. }
  276. realP = null;
  277. }
  278. return parametertypes;
  279. }
  280. /**
  281. * Method getParameterNames
  282. *
  283. *
  284. * (getParameterNames) @return
  285. */
  286. public String[] getParameterNames()
  287. {
  288. return parameternames;
  289. }
  290. /**
  291. * Method addParameter
  292. *
  293. *
  294. * @param type
  295. * @param name
  296. *
  297. * @throws SynthesisException
  298. */
  299. public void addParameter(
  300. com.sun.org.apache.xml.internal.utils.synthetic.Class type, String name)
  301. throws SynthesisException
  302. {
  303. if (realep != null)
  304. throw new SynthesisException(SynthesisException.REIFIED);
  305. com.sun.org.apache.xml.internal.utils.synthetic.Class[] types =
  306. new com.sun.org.apache.xml.internal.utils.synthetic.Class[parametertypes.length + 1];
  307. System.arraycopy(parametertypes, 0, types, 0, parametertypes.length);
  308. types[parametertypes.length] = type;
  309. parametertypes = types;
  310. String[] names = new String[parameternames.length + 1];
  311. System.arraycopy(parameternames, 0, names, 0, parameternames.length);
  312. names[parameternames.length] = name;
  313. parameternames = names;
  314. }
  315. /**
  316. * Returns a hashcode for this Constructor. The
  317. * hashcode is the same as the hashcode for the
  318. * underlying constructor's declaring class name,
  319. * xor'ed (for Methods) with the method name.
  320. * (Implemented in the subclasses rather than here.)
  321. *
  322. */
  323. abstract public int hashCode();
  324. /**
  325. * Assert the Class object representing the class that
  326. * declares the constructor represented by this
  327. * Constructor object.
  328. *
  329. * @param declaringClass
  330. *
  331. * @throws SynthesisException
  332. */
  333. public void setDeclaringClass(
  334. com.sun.org.apache.xml.internal.utils.synthetic.Class declaringClass)
  335. throws SynthesisException
  336. {
  337. if (realep != null)
  338. throw new SynthesisException(SynthesisException.REIFIED);
  339. this.declaringclass = declaringClass;
  340. }
  341. /**
  342. * Should only be accepted before a "real" entrypoint is bound.
  343. * Creation date: (12-25-99 1:28:28 PM)
  344. * @return int
  345. * @param modifiers int
  346. *
  347. * @throws SynthesisException
  348. */
  349. public void setModifiers(int modifiers) throws SynthesisException
  350. {
  351. if (realep != null)
  352. throw new SynthesisException(SynthesisException.REIFIED);
  353. this.modifiers = modifiers;
  354. }
  355. /**
  356. * Return a string describing this Constructor. The
  357. * string is formatted as the constructor access
  358. * modifiers, if any, followed by the fully-qualified
  359. * name of the declaring class, followed by a
  360. * parenthesized, comma-separated list of the
  361. * constructor's formal parameter types. For example:
  362. * <code>
  363. * public java.util.Hashtable(int,float)
  364. * </code>
  365. * <p>
  366. * The only possible modifiers for constructors are
  367. * the access modifiers public, protected or
  368. * private. Only one of these may appear, or none
  369. * if the constructor has default (package) access.
  370. * <p>
  371. * Methods will also display their checked exceptions.
  372. *
  373. */
  374. public String toString()
  375. {
  376. StringBuffer sb =
  377. new StringBuffer(java.lang.reflect.Modifier.toString(getModifiers()));
  378. if (this instanceof com.sun.org.apache.xml.internal.utils.synthetic.reflection.Method)
  379. sb.append(' ').append(getReturnType()).append(
  380. getDeclaringClass().getName()).append('.').append(getName());
  381. else
  382. sb.append(getDeclaringClass().getName());
  383. sb.append('(');
  384. com.sun.org.apache.xml.internal.utils.synthetic.Class[] p = getParameterTypes();
  385. if (p != null && p.length > 0)
  386. {
  387. sb.append(p[0].getName());
  388. for (int i = 1; i < p.length; ++i)
  389. {
  390. sb.append(',').append(p[i].getName());
  391. }
  392. }
  393. sb.append(')');
  394. if (this instanceof com.sun.org.apache.xml.internal.utils.synthetic.reflection.Method)
  395. {
  396. p = getExceptionTypes();
  397. if (p != null && p.length > 0)
  398. {
  399. sb.append(" throws ").append(p[0].getName());
  400. for (int i = 1; i < p.length; ++i)
  401. {
  402. sb.append(',').append(p[i].getName());
  403. }
  404. }
  405. }
  406. return sb.toString();
  407. }
  408. /**
  409. * Extension: For synthesis, we need a place to hang a
  410. * method body.
  411. *
  412. * @param language
  413. * @param body
  414. *
  415. * @throws SynthesisException
  416. */
  417. public void setBody(String language, StringBuffer body)
  418. throws SynthesisException
  419. {
  420. if (realep != null)
  421. throw new SynthesisException(SynthesisException.REIFIED);
  422. this.language = language;
  423. this.body = body;
  424. }
  425. /**
  426. * Extension: For synthesis, we need a place to hang a
  427. * method body. Note that this returns a mutable object,
  428. * for editing etc. Slightly sloppy first cut.
  429. *
  430. */
  431. public StringBuffer getBody()
  432. {
  433. if (body == null)
  434. body = new StringBuffer();
  435. return body;
  436. }
  437. /**
  438. * Extension: For synthesis, we need a place to hang a
  439. * method body.
  440. *
  441. */
  442. public String getLanguage()
  443. {
  444. return language;
  445. }
  446. /**
  447. * Generate Java code
  448. *
  449. * @param basetab
  450. *
  451. */
  452. public String toSource(String basetab)
  453. {
  454. StringBuffer sb = new StringBuffer();
  455. sb.append(basetab).append(
  456. java.lang.reflect.Modifier.toString(getModifiers()));
  457. if (this instanceof com.sun.org.apache.xml.internal.utils.synthetic.reflection.Method)
  458. {
  459. if (returntype != null)
  460. sb.append(" ").append(getReturnType().getJavaName());
  461. else
  462. sb.append(" void");
  463. }
  464. sb.append(" ").append(getName()).append("(");
  465. com.sun.org.apache.xml.internal.utils.synthetic.Class[] types = getParameterTypes();
  466. if (types != null & types.length > 0)
  467. {
  468. sb.append(types[0].getJavaName());
  469. if (parameternames != null)
  470. sb.append(' ').append(parameternames[0]);
  471. for (int i = 1; i < types.length; ++i)
  472. {
  473. sb.append(',').append(types[i].getJavaName());
  474. if (parameternames != null)
  475. sb.append(' ').append(parameternames[i]);
  476. }
  477. }
  478. sb.append(')');
  479. types = getExceptionTypes();
  480. if (types != null & types.length > 0)
  481. {
  482. sb.append(" throws ").append(types[0].getJavaName());
  483. for (int i = 1; i < types.length; ++i)
  484. {
  485. sb.append(',').append(types[i].getJavaName());
  486. }
  487. }
  488. if (body == null)
  489. sb.append("; // No method body available\n");
  490. else
  491. {
  492. sb.append("\n" + basetab + "{\n");
  493. if (language == null || "java".equals(language))
  494. {
  495. sb.append(basetab + "// ***** Should prettyprint this code...\n");
  496. sb.append(basetab + body + "\n");
  497. }
  498. else
  499. {
  500. sb.append(basetab + "// ***** Generate BSF invocation!?\n");
  501. }
  502. sb.append(basetab + "}\n");
  503. }
  504. return sb.toString();
  505. }
  506. }