1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999 The Apache Software Foundation. All rights
  6. * reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xalan" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, Lotus
  53. * Development Corporation., http://www.lotus.com. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package org.apache.xml.utils.synthetic.reflection;
  58. import java.lang.reflect.InvocationTargetException;
  59. import org.apache.xml.utils.synthetic.SynthesisException;
  60. /*
  61. * OPEN ISSUES:
  62. * Reflection doesn't tell us about deprecation; if we want
  63. * that info, MFC advises mousing our way into the class (ugh).
  64. * Should we at least model that for synthetics?
  65. */
  66. /**
  67. * <meta name="usage" content="internal"/>
  68. * API/behaviors shared between Constructors and Methods.
  69. * They're mostly similar, except for what they proxy and
  70. * a few specific calls (name, invoke/getInstance).
  71. */
  72. abstract public class EntryPoint implements Member
  73. {
  74. /** Field realep */
  75. protected Object realep;
  76. /** Field declaringclass */
  77. private org.apache.xml.utils.synthetic.Class declaringclass = null;
  78. /** Field returntype */
  79. protected org.apache.xml.utils.synthetic.Class returntype = null;
  80. /** Field parameternames */
  81. private String[] parameternames = new String[0];
  82. /** Field parametertypes */
  83. private org.apache.xml.utils.synthetic.Class[] parametertypes =
  84. new org.apache.xml.utils.synthetic.Class[0];
  85. /** Field exceptiontypes */
  86. private org.apache.xml.utils.synthetic.Class[] exceptiontypes =
  87. new org.apache.xml.utils.synthetic.Class[0];
  88. ;
  89. /** Field modifiers */
  90. private int modifiers;
  91. /** Field name */
  92. protected String name = null; // for Methods
  93. // For synthesis:
  94. /** Field body */
  95. private StringBuffer body = null;
  96. /** Field language */
  97. private String language = null;
  98. // For reifying:
  99. /** Field realE, realP */
  100. Class[] realE, realP;
  101. /**
  102. * Insert the method's description here.
  103. * <p>
  104. * Creation date: (12-27-99 2:31:39 PM)
  105. * @param realConstructor java.lang.reflect.Constructor
  106. *
  107. * @param declaringclass
  108. */
  109. public EntryPoint(org.apache.xml.utils.synthetic.Class declaringclass)
  110. {
  111. this.declaringclass = declaringclass;
  112. }
  113. /**
  114. * Nonpublic constructor. Wrap this to appropriate "real" type
  115. *
  116. * @param ep
  117. * @param declaringclass
  118. *
  119. * @throws IllegalArgumentException
  120. */
  121. protected EntryPoint(
  122. Object ep, org.apache.xml.utils.synthetic.Class declaringclass)
  123. throws IllegalArgumentException
  124. {
  125. realep = ep;
  126. this.declaringclass = declaringclass;
  127. if (ep instanceof java.lang.reflect.Method)
  128. {
  129. java.lang.reflect.Method m = (java.lang.reflect.Method) ep;
  130. if (declaringclass == null)
  131. {
  132. declaringclass = org.apache.xml.utils.synthetic.Class.forClass(
  133. m.getDeclaringClass());
  134. }
  135. name = m.getName();
  136. modifiers = m.getModifiers();
  137. returntype =
  138. org.apache.xml.utils.synthetic.Class.forClass(m.getReturnType());
  139. realP = m.getParameterTypes();
  140. realE = m.getExceptionTypes();
  141. }
  142. else if (ep instanceof java.lang.reflect.Constructor)
  143. {
  144. java.lang.reflect.Constructor c = (java.lang.reflect.Constructor) ep;
  145. if (declaringclass == null)
  146. {
  147. declaringclass = org.apache.xml.utils.synthetic.Class.forClass(
  148. c.getDeclaringClass());
  149. }
  150. name = declaringclass.getShortName();
  151. modifiers = c.getModifiers();
  152. returntype = declaringclass;
  153. realP = c.getParameterTypes();
  154. realE = c.getExceptionTypes();
  155. }
  156. else
  157. throw new IllegalArgumentException();
  158. }
  159. /**
  160. * Nonpublic constructor. Wrap this to appropriate "real" type
  161. *
  162. * @param ep
  163. *
  164. * @throws IllegalArgumentException
  165. */
  166. protected EntryPoint(Object ep) throws IllegalArgumentException
  167. {
  168. this(ep, null);
  169. }
  170. /**
  171. * Compares this against the specified
  172. * object. Returns true if the objects are the same.
  173. * Two EntryPoints are the same if they were
  174. * declared by the same class, have the same name
  175. * (or are both ctors) and have the same
  176. * formal parameter types.
  177. *
  178. * @param obj
  179. *
  180. */
  181. public boolean equals(Object obj)
  182. {
  183. EntryPoint otherep = null;
  184. if (obj instanceof EntryPoint)
  185. otherep = (EntryPoint) obj;
  186. else if (obj instanceof java.lang.reflect.Constructor
  187. || obj instanceof java.lang.reflect.Method)
  188. otherep = (EntryPoint) obj;
  189. return (otherep != null && ((this instanceof Constructor && otherep instanceof Constructor) || (this instanceof Method && otherep instanceof Method && this.getName().equals(
  190. otherep.getName()))) && otherep.getDeclaringClass().equals(
  191. declaringclass) && otherep.getParameterTypes().equals(
  192. parametertypes));
  193. }
  194. /**
  195. * Returns the Class object representing the class that
  196. * declares the constructor represented by this
  197. * Constructor object.
  198. *
  199. */
  200. public org.apache.xml.utils.synthetic.Class getDeclaringClass()
  201. {
  202. return declaringclass;
  203. }
  204. /**
  205. * Returns the Class object representing the class that
  206. * will be returned by this EntryPoint. Needed by the Method
  207. * API, but made meaningful for Constructors as well.
  208. *
  209. */
  210. public org.apache.xml.utils.synthetic.Class getReturnType()
  211. {
  212. return returntype;
  213. }
  214. /**
  215. * Returns an array of Class objects that represent the
  216. * types of the checked exceptions thrown by the
  217. * underlying constructor represented by this
  218. * Constructor object. Returns an array of length 0 if
  219. * the constructor throws no checked exceptions.
  220. *
  221. */
  222. public org.apache.xml.utils.synthetic.Class[] getExceptionTypes()
  223. {
  224. if (realep != null && exceptiontypes == null)
  225. {
  226. exceptiontypes =
  227. new org.apache.xml.utils.synthetic.Class[realE.length];
  228. for (int i = 0; i < realE.length; ++i)
  229. {
  230. exceptiontypes[i] =
  231. org.apache.xml.utils.synthetic.Class.forClass(realE[i]);
  232. }
  233. realE = null;
  234. }
  235. return exceptiontypes;
  236. }
  237. /**
  238. * Method addExceptionType
  239. *
  240. *
  241. * @param exception
  242. *
  243. * @throws SynthesisException
  244. */
  245. public void addExceptionType(
  246. org.apache.xml.utils.synthetic.Class exception)
  247. throws SynthesisException
  248. {
  249. if (realep != null)
  250. throw new SynthesisException(SynthesisException.REIFIED);
  251. org.apache.xml.utils.synthetic.Class[] e =
  252. new org.apache.xml.utils.synthetic.Class[exceptiontypes.length + 1];
  253. System.arraycopy(exceptiontypes, 0, e, 0, exceptiontypes.length);
  254. e[exceptiontypes.length] = exception;
  255. exceptiontypes = e;
  256. }
  257. /**
  258. * Returns the Java language modifiers for the
  259. * constructor represented by this Constructor object,
  260. * as an integer. The Modifier class should be used to
  261. * decode the modifiers.
  262. *
  263. */
  264. public int getModifiers()
  265. {
  266. return modifiers;
  267. }
  268. /**
  269. * Member method. C'tor's name is always that of the defining class.
  270. * Methods have a "real" name.
  271. * Creation date: (12-25-99 1:32:06 PM)
  272. * @return java.lang.String
  273. */
  274. public java.lang.String getName()
  275. {
  276. if (this instanceof Constructor)
  277. return declaringclass.getShortName();
  278. return name;
  279. }
  280. /**
  281. * Member method. C'tor's name is always that of the defining class.
  282. * Methods have a "real" name.
  283. * Creation date: (12-25-99 1:32:06 PM)
  284. *
  285. * @param name
  286. * @return java.lang.String
  287. *
  288. * @throws SynthesisException
  289. */
  290. public void setName(String name) throws SynthesisException
  291. {
  292. if (realep != null)
  293. throw new SynthesisException(SynthesisException.REIFIED);
  294. this.name = name;
  295. }
  296. /**
  297. * Returns an array of Class objects that represent the
  298. * formal parameter types, in declaration order, of the
  299. * constructor represented by this Constructor object.
  300. * Returns an array of length 0 if the underlying
  301. * constructor takes no parameters.
  302. *
  303. */
  304. public org.apache.xml.utils.synthetic.Class[] getParameterTypes()
  305. {
  306. if (realep != null && parametertypes == null)
  307. {
  308. parametertypes =
  309. new org.apache.xml.utils.synthetic.Class[realP.length];
  310. for (int i = 0; i < realP.length; ++i)
  311. {
  312. parametertypes[i] =
  313. org.apache.xml.utils.synthetic.Class.forClass(realP[i]);
  314. }
  315. realP = null;
  316. }
  317. return parametertypes;
  318. }
  319. /**
  320. * Method getParameterNames
  321. *
  322. *
  323. * (getParameterNames) @return
  324. */
  325. public String[] getParameterNames()
  326. {
  327. return parameternames;
  328. }
  329. /**
  330. * Method addParameter
  331. *
  332. *
  333. * @param type
  334. * @param name
  335. *
  336. * @throws SynthesisException
  337. */
  338. public void addParameter(
  339. org.apache.xml.utils.synthetic.Class type, String name)
  340. throws SynthesisException
  341. {
  342. if (realep != null)
  343. throw new SynthesisException(SynthesisException.REIFIED);
  344. org.apache.xml.utils.synthetic.Class[] types =
  345. new org.apache.xml.utils.synthetic.Class[parametertypes.length + 1];
  346. System.arraycopy(parametertypes, 0, types, 0, parametertypes.length);
  347. types[parametertypes.length] = type;
  348. parametertypes = types;
  349. String[] names = new String[parameternames.length + 1];
  350. System.arraycopy(parameternames, 0, names, 0, parameternames.length);
  351. names[parameternames.length] = name;
  352. parameternames = names;
  353. }
  354. /**
  355. * Returns a hashcode for this Constructor. The
  356. * hashcode is the same as the hashcode for the
  357. * underlying constructor's declaring class name,
  358. * xor'ed (for Methods) with the method name.
  359. * (Implemented in the subclasses rather than here.)
  360. *
  361. */
  362. abstract public int hashCode();
  363. /**
  364. * Assert the Class object representing the class that
  365. * declares the constructor represented by this
  366. * Constructor object.
  367. *
  368. * @param declaringClass
  369. *
  370. * @throws SynthesisException
  371. */
  372. public void setDeclaringClass(
  373. org.apache.xml.utils.synthetic.Class declaringClass)
  374. throws SynthesisException
  375. {
  376. if (realep != null)
  377. throw new SynthesisException(SynthesisException.REIFIED);
  378. this.declaringclass = declaringClass;
  379. }
  380. /**
  381. * Should only be accepted before a "real" entrypoint is bound.
  382. * Creation date: (12-25-99 1:28:28 PM)
  383. * @return int
  384. * @param modifiers int
  385. *
  386. * @throws SynthesisException
  387. */
  388. public void setModifiers(int modifiers) throws SynthesisException
  389. {
  390. if (realep != null)
  391. throw new SynthesisException(SynthesisException.REIFIED);
  392. this.modifiers = modifiers;
  393. }
  394. /**
  395. * Return a string describing this Constructor. The
  396. * string is formatted as the constructor access
  397. * modifiers, if any, followed by the fully-qualified
  398. * name of the declaring class, followed by a
  399. * parenthesized, comma-separated list of the
  400. * constructor's formal parameter types. For example:
  401. * <code>
  402. * public java.util.Hashtable(int,float)
  403. * </code>
  404. * <p>
  405. * The only possible modifiers for constructors are
  406. * the access modifiers public, protected or
  407. * private. Only one of these may appear, or none
  408. * if the constructor has default (package) access.
  409. * <p>
  410. * Methods will also display their checked exceptions.
  411. *
  412. */
  413. public String toString()
  414. {
  415. StringBuffer sb =
  416. new StringBuffer(java.lang.reflect.Modifier.toString(getModifiers()));
  417. if (this instanceof org.apache.xml.utils.synthetic.reflection.Method)
  418. sb.append(' ').append(getReturnType()).append(
  419. getDeclaringClass().getName()).append('.').append(getName());
  420. else
  421. sb.append(getDeclaringClass().getName());
  422. sb.append('(');
  423. org.apache.xml.utils.synthetic.Class[] p = getParameterTypes();
  424. if (p != null && p.length > 0)
  425. {
  426. sb.append(p[0].getName());
  427. for (int i = 1; i < p.length; ++i)
  428. {
  429. sb.append(',').append(p[i].getName());
  430. }
  431. }
  432. sb.append(')');
  433. if (this instanceof org.apache.xml.utils.synthetic.reflection.Method)
  434. {
  435. p = getExceptionTypes();
  436. if (p != null && p.length > 0)
  437. {
  438. sb.append(" throws ").append(p[0].getName());
  439. for (int i = 1; i < p.length; ++i)
  440. {
  441. sb.append(',').append(p[i].getName());
  442. }
  443. }
  444. }
  445. return sb.toString();
  446. }
  447. /**
  448. * Extension: For synthesis, we need a place to hang a
  449. * method body.
  450. *
  451. * @param language
  452. * @param body
  453. *
  454. * @throws SynthesisException
  455. */
  456. public void setBody(String language, StringBuffer body)
  457. throws SynthesisException
  458. {
  459. if (realep != null)
  460. throw new SynthesisException(SynthesisException.REIFIED);
  461. this.language = language;
  462. this.body = body;
  463. }
  464. /**
  465. * Extension: For synthesis, we need a place to hang a
  466. * method body. Note that this returns a mutable object,
  467. * for editing etc. Slightly sloppy first cut.
  468. *
  469. */
  470. public StringBuffer getBody()
  471. {
  472. if (body == null)
  473. body = new StringBuffer();
  474. return body;
  475. }
  476. /**
  477. * Extension: For synthesis, we need a place to hang a
  478. * method body.
  479. *
  480. */
  481. public String getLanguage()
  482. {
  483. return language;
  484. }
  485. /**
  486. * Generate Java code
  487. *
  488. * @param basetab
  489. *
  490. */
  491. public String toSource(String basetab)
  492. {
  493. StringBuffer sb = new StringBuffer();
  494. sb.append(basetab).append(
  495. java.lang.reflect.Modifier.toString(getModifiers()));
  496. if (this instanceof org.apache.xml.utils.synthetic.reflection.Method)
  497. {
  498. if (returntype != null)
  499. sb.append(" ").append(getReturnType().getJavaName());
  500. else
  501. sb.append(" void");
  502. }
  503. sb.append(" ").append(getName()).append("(");
  504. org.apache.xml.utils.synthetic.Class[] types = getParameterTypes();
  505. if (types != null & types.length > 0)
  506. {
  507. sb.append(types[0].getJavaName());
  508. if (parameternames != null)
  509. sb.append(' ').append(parameternames[0]);
  510. for (int i = 1; i < types.length; ++i)
  511. {
  512. sb.append(',').append(types[i].getJavaName());
  513. if (parameternames != null)
  514. sb.append(' ').append(parameternames[i]);
  515. }
  516. }
  517. sb.append(')');
  518. types = getExceptionTypes();
  519. if (types != null & types.length > 0)
  520. {
  521. sb.append(" throws ").append(types[0].getJavaName());
  522. for (int i = 1; i < types.length; ++i)
  523. {
  524. sb.append(',').append(types[i].getJavaName());
  525. }
  526. }
  527. if (body == null)
  528. sb.append("; // No method body available\n");
  529. else
  530. {
  531. sb.append("\n" + basetab + "{\n");
  532. if (language == null || "java".equals(language))
  533. {
  534. sb.append(basetab + "// ***** Should prettyprint this code...\n");
  535. sb.append(basetab + body + "\n");
  536. }
  537. else
  538. {
  539. sb.append(basetab + "// ***** Generate BSF invocation!?\n");
  540. }
  541. sb.append(basetab + "}\n");
  542. }
  543. return sb.toString();
  544. }
  545. }