Advertisement
Guest User

VELOCITY-12.patch

a guest
Mar 31st, 2011
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 27.15 KB | None | 0 0
  1. diff --git a/src/java/org/apache/velocity/runtime/parser/node/PublicFieldExecutor.java b/src/java/org/apache/velocity/runtime/parser/node/PublicFieldExecutor.java
  2. new file mode 100644
  3. index 0000000..f9fea30
  4. --- /dev/null
  5. +++ b/src/java/org/apache/velocity/runtime/parser/node/PublicFieldExecutor.java
  6. @@ -0,0 +1,141 @@
  7. +package org.apache.velocity.runtime.parser.node;
  8. +
  9. +/*
  10. + * Licensed to the Apache Software Foundation (ASF) under one
  11. + * or more contributor license agreements.  See the NOTICE file
  12. + * distributed with this work for additional information
  13. + * regarding copyright ownership.  The ASF licenses this file
  14. + * to you under the Apache License, Version 2.0 (the
  15. + * "License"); you may not use this file except in compliance
  16. + * with the License.  You may obtain a copy of the License at
  17. + *
  18. + *   http://www.apache.org/licenses/LICENSE-2.0
  19. + *
  20. + * Unless required by applicable law or agreed to in writing,
  21. + * software distributed under the License is distributed on an
  22. + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  23. + * KIND, either express or implied.  See the License for the
  24. + * specific language governing permissions and limitations
  25. + * under the License.
  26. + */
  27. +
  28. +import java.lang.reflect.Field;
  29. +import java.lang.reflect.InvocationTargetException;
  30. +
  31. +import org.apache.commons.lang.StringUtils;
  32. +import org.apache.velocity.exception.VelocityException;
  33. +import org.apache.velocity.runtime.RuntimeLogger;
  34. +import org.apache.velocity.runtime.log.Log;
  35. +import org.apache.velocity.runtime.log.RuntimeLoggerLog;
  36. +import org.apache.velocity.util.introspection.Introspector;
  37. +
  38. +/**
  39. + * Returns the value of a public field when executed.
  40. + */
  41. +public class PublicFieldExecutor extends AbstractExecutor
  42. +{
  43. +    private final Introspector introspector;
  44. +
  45. +    /**
  46. +     * Field to be accessed
  47. +     */
  48. +    private Field field = null;
  49. +
  50. +    /**
  51. +     * @param log
  52. +     * @param introspector
  53. +     * @param clazz
  54. +     * @param property
  55. +     * @since 1.5
  56. +     */
  57. +    public PublicFieldExecutor(final Log log, final Introspector introspector,
  58. +            final Class clazz, final String property)
  59. +    {
  60. +        this.log = log;
  61. +        this.introspector = introspector;
  62. +
  63. +        // Don't allow passing in the empty string or null because
  64. +        // it will either fail with a StringIndexOutOfBounds error
  65. +        // or the introspector will get confused.
  66. +        if (StringUtils.isNotEmpty(property))
  67. +        {
  68. +            discover(clazz, property);
  69. +        }
  70. +    }
  71. +
  72. +    /**
  73. +     * @param r
  74. +     * @param introspector
  75. +     * @param clazz
  76. +     * @param property
  77. +     * @deprecated RuntimeLogger is deprecated. Use the other constructor.
  78. +     */
  79. +    public PublicFieldExecutor(final RuntimeLogger r, final Introspector introspector,
  80. +            final Class clazz, final String property)
  81. +    {
  82. +        this(new RuntimeLoggerLog(r), introspector, clazz, property);
  83. +    }
  84. +
  85. +    public boolean isAlive() {
  86. +        return getField() != null;
  87. +    }
  88. +
  89. +    /**
  90. +     * @return The current field.
  91. +     */
  92. +    public Field getField()
  93. +    {
  94. +        return field;
  95. +    }
  96. +
  97. +    /**
  98. +     * @param field
  99. +     */
  100. +    protected void setField(final Field field)
  101. +    {
  102. +        this.field = field;
  103. +    }
  104. +
  105. +    /**
  106. +     * @return The current introspector.
  107. +     * @since 1.5
  108. +     */
  109. +    protected Introspector getIntrospector()
  110. +    {
  111. +        return this.introspector;
  112. +    }
  113. +
  114. +    /**
  115. +     * @param clazz
  116. +     * @param property
  117. +     */
  118. +    protected void discover(final Class clazz, final String property)
  119. +    {
  120. +        try
  121. +        {
  122. +            setField(introspector.getField(clazz, property));
  123. +        }
  124. +        /**
  125. +         * pass through application level runtime exceptions
  126. +         */
  127. +        catch( RuntimeException e )
  128. +        {
  129. +            throw e;
  130. +        }
  131. +        catch(Exception e)
  132. +        {
  133. +            String msg = "Exception while looking for public field '" + property;
  134. +            log.error(msg, e);
  135. +            throw new VelocityException(msg, e);
  136. +        }
  137. +    }
  138. +
  139. +    /**
  140. +     * @see org.apache.velocity.runtime.parser.node.AbstractExecutor#execute(java.lang.Object)
  141. +     */
  142. +    public Object execute(Object o)
  143. +        throws IllegalAccessException,  InvocationTargetException
  144. +    {
  145. +        return isAlive() ? getField().get(o) : null;
  146. +    }
  147. +}
  148. diff --git a/src/java/org/apache/velocity/runtime/parser/node/SetPublicFieldExecutor.java b/src/java/org/apache/velocity/runtime/parser/node/SetPublicFieldExecutor.java
  149. new file mode 100644
  150. index 0000000..9467e5c
  151. --- /dev/null
  152. +++ b/src/java/org/apache/velocity/runtime/parser/node/SetPublicFieldExecutor.java
  153. @@ -0,0 +1,147 @@
  154. +package org.apache.velocity.runtime.parser.node;
  155. +
  156. +/*
  157. + * Licensed to the Apache Software Foundation (ASF) under one
  158. + * or more contributor license agreements.  See the NOTICE file
  159. + * distributed with this work for additional information
  160. + * regarding copyright ownership.  The ASF licenses this file
  161. + * to you under the Apache License, Version 2.0 (the
  162. + * "License"); you may not use this file except in compliance
  163. + * with the License.  You may obtain a copy of the License at
  164. + *
  165. + *   http://www.apache.org/licenses/LICENSE-2.0
  166. + *
  167. + * Unless required by applicable law or agreed to in writing,
  168. + * software distributed under the License is distributed on an
  169. + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  170. + * KIND, either express or implied.  See the License for the
  171. + * specific language governing permissions and limitations
  172. + * under the License.
  173. + */
  174. +
  175. +import java.lang.reflect.Field;
  176. +import java.lang.reflect.InvocationTargetException;
  177. +import java.lang.reflect.Modifier;
  178. +
  179. +import org.apache.commons.lang.StringUtils;
  180. +import org.apache.velocity.exception.VelocityException;
  181. +import org.apache.velocity.runtime.log.Log;
  182. +import org.apache.velocity.util.introspection.Introspector;
  183. +
  184. +/**
  185. + * Executor for setting public fields in objects
  186. + *
  187. + * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  188. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  189. + */
  190. +public class SetPublicFieldExecutor
  191. +        extends SetExecutor
  192. +{
  193. +    private final Introspector introspector;
  194. +
  195. +    /**
  196. +     * Field to be accessed
  197. +     */
  198. +    private Field field = null;
  199. +
  200. +    /**
  201. +     * @param log
  202. +     * @param introspector
  203. +     * @param clazz
  204. +     * @param property
  205. +     * @param arg
  206. +     */
  207. +    public SetPublicFieldExecutor(final Log log, final Introspector introspector,
  208. +            final Class clazz, final String property, final Object arg)
  209. +    {
  210. +        this.log = log;
  211. +        this.introspector = introspector;
  212. +
  213. +        // Don't allow passing in the empty string or null because
  214. +        // it will either fail with a StringIndexOutOfBounds error
  215. +        // or the introspector will get confused.
  216. +        if (StringUtils.isNotEmpty(property))
  217. +        {
  218. +            discover(clazz, property, arg);
  219. +        }
  220. +    }
  221. +
  222. +    public boolean isAlive() {
  223. +        return getField() != null;
  224. +    }
  225. +
  226. +    /**
  227. +     * @return The current field.
  228. +     */
  229. +    public Field getField()
  230. +    {
  231. +        return field;
  232. +    }
  233. +
  234. +    /**
  235. +     * @param field
  236. +     */
  237. +    protected void setField(final Field field)
  238. +    {
  239. +        this.field = field;
  240. +    }
  241. +
  242. +    /**
  243. +     * @return The current introspector.
  244. +     */
  245. +    protected Introspector getIntrospector()
  246. +    {
  247. +        return this.introspector;
  248. +    }
  249. +
  250. +    /**
  251. +     * @param clazz
  252. +     * @param property
  253. +     * @param arg
  254. +     */
  255. +    protected void discover(final Class clazz, final String property, final Object arg)
  256. +    {
  257. +        try
  258. +        {
  259. +            Field field = introspector.getField(clazz, property);
  260. +            if(!Modifier.isFinal(field.getModifiers()))
  261. +            {
  262. +                setField(field);
  263. +            }
  264. +        }
  265. +        /**
  266. +         * pass through application level runtime exceptions
  267. +         */
  268. +        catch( RuntimeException e )
  269. +        {
  270. +            throw e;
  271. +        }
  272. +        catch(Exception e)
  273. +        {
  274. +            String msg = "Exception while looking for public field '" + property;
  275. +            log.error(msg, e);
  276. +            throw new VelocityException(msg, e);
  277. +        }
  278. +    }
  279. +
  280. +    /**
  281. +     * Execute method against context.
  282. +     * @param o
  283. +     * @param value
  284. +     * @return The value of the invocation.
  285. +     * @throws IllegalAccessException
  286. +     * @throws InvocationTargetException
  287. +     */
  288. +    public Object execute(final Object o, final Object value)
  289. +        throws IllegalAccessException,  InvocationTargetException
  290. +    {
  291. +        if (isAlive())
  292. +        {
  293. +            Object oldValue = getField().get(o);
  294. +            getField().set(o, value);
  295. +            return oldValue;
  296. +        }
  297. +        else
  298. +            return null;
  299. +    }
  300. +}
  301. diff --git a/src/java/org/apache/velocity/util/introspection/ClassFieldMap.java b/src/java/org/apache/velocity/util/introspection/ClassFieldMap.java
  302. new file mode 100644
  303. index 0000000..5597ebe
  304. --- /dev/null
  305. +++ b/src/java/org/apache/velocity/util/introspection/ClassFieldMap.java
  306. @@ -0,0 +1,175 @@
  307. +package org.apache.velocity.util.introspection;
  308. +
  309. +/*
  310. + * Licensed to the Apache Software Foundation (ASF) under one
  311. + * or more contributor license agreements.  See the NOTICE file
  312. + * distributed with this work for additional information
  313. + * regarding copyright ownership.  The ASF licenses this file
  314. + * to you under the Apache License, Version 2.0 (the
  315. + * "License"); you may not use this file except in compliance
  316. + * with the License.  You may obtain a copy of the License at
  317. + *
  318. + *   http://www.apache.org/licenses/LICENSE-2.0
  319. + *
  320. + * Unless required by applicable law or agreed to in writing,
  321. + * software distributed under the License is distributed on an
  322. + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  323. + * KIND, either express or implied.  See the License for the
  324. + * specific language governing permissions and limitations
  325. + * under the License.
  326. + */
  327. +
  328. +import java.lang.reflect.Field;
  329. +import java.lang.reflect.Modifier;
  330. +import java.util.Map;
  331. +import org.apache.velocity.runtime.log.Log;
  332. +import org.apache.velocity.util.MapFactory;
  333. +
  334. +/**
  335. + * A cache of introspection information for a specific class instance.
  336. + * Keys {@link java.lang.reflect.Field} objects by the field names.
  337. + *
  338. + * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
  339. + * @author <a href="mailto:bob@werken.com">Bob McWhirter</a>
  340. + * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
  341. + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  342. + * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  343. + * @author Nathan Bubna
  344. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  345. + */
  346. +public class ClassFieldMap
  347. +{
  348. +    /** Set true if you want to debug the reflection code */
  349. +    private static final boolean debugReflection = false;
  350. +
  351. +    /** Class logger */
  352. +    private final Log log;
  353. +
  354. +    /**
  355. +     * Class passed into the constructor used to as
  356. +     * the basis for the Field map.
  357. +     */
  358. +    private final Class clazz;
  359. +
  360. +    /**
  361. +     * String --&gt; Field map, the key is the field name
  362. +     */
  363. +    private final Map fieldCache;
  364. +
  365. +    /**
  366. +     * Standard constructor
  367. +     * @param clazz The class for which this ClassMap gets constructed.
  368. +     */
  369. +    public ClassFieldMap(final Class clazz, final Log log)
  370. +    {
  371. +        this.clazz = clazz;
  372. +        this.log = log;
  373. +
  374. +        if (debugReflection && log.isDebugEnabled())
  375. +        {
  376. +            log.debug("=================================================================");
  377. +            log.debug("== Class: " + clazz);
  378. +        }
  379. +
  380. +        fieldCache = createFieldCache();
  381. +
  382. +        if (debugReflection && log.isDebugEnabled())
  383. +        {
  384. +            log.debug("=================================================================");
  385. +        }
  386. +    }
  387. +
  388. +    /**
  389. +     * Returns the class object whose fields are cached by this map.
  390. +     *
  391. +     * @return The class object whose fields are cached by this map.
  392. +     */
  393. +    public Class getCachedClass()
  394. +    {
  395. +        return clazz;
  396. +    }
  397. +
  398. +    /**
  399. +     * Find a Field using the field name.
  400. +     *
  401. +     * @param name The field name to look up.
  402. +     * @return A Field object representing the field to invoke or null.
  403. +     */
  404. +    public Field findField(final String name)
  405. +    {
  406. +        return (Field)fieldCache.get(name);
  407. +    }
  408. +
  409. +    /**
  410. +     * Populate the Map of direct hits. These
  411. +     * are taken from all the public fields
  412. +     * that our class, its parents and their implemented interfaces provide.
  413. +     */
  414. +    private Map createFieldCache()
  415. +    {
  416. +        Map fieldCache = MapFactory.create(false);
  417. +   //
  418. +   // Looks through all elements in the class hierarchy.
  419. +   //
  420. +   // We ignore all SecurityExceptions that might happen due to SecurityManager restrictions (prominently
  421. +   // hit with Tomcat 5.5).
  422. +        // Ah, the miracles of Java for(;;) ...
  423. +        for (Class classToReflect = getCachedClass(); classToReflect != null ; classToReflect = classToReflect.getSuperclass())
  424. +        {
  425. +            if (Modifier.isPublic(classToReflect.getModifiers()))
  426. +            {
  427. +                populateFieldCacheWith(fieldCache, classToReflect);
  428. +            }
  429. +            Class [] interfaces = classToReflect.getInterfaces();
  430. +            for (int i = 0; i < interfaces.length; i++)
  431. +            {
  432. +                populateFieldCacheWithInterface(fieldCache, interfaces[i]);
  433. +            }
  434. +        }
  435. +        // return the already initialized cache
  436. +        return fieldCache;
  437. +    }
  438. +
  439. +    /* recurses up interface heirarchy to get all super interfaces (VELOCITY-689) */
  440. +    private void populateFieldCacheWithInterface(Map fieldCache, Class iface)
  441. +    {
  442. +        if (Modifier.isPublic(iface.getModifiers()))
  443. +        {
  444. +            populateFieldCacheWith(fieldCache, iface);
  445. +        }
  446. +        Class[] supers = iface.getInterfaces();
  447. +        for (int i=0; i < supers.length; i++)
  448. +        {
  449. +            populateFieldCacheWithInterface(fieldCache, supers[i]);
  450. +        }
  451. +    }
  452. +
  453. +    private void populateFieldCacheWith(Map fieldCache, Class classToReflect)
  454. +    {
  455. +        if (debugReflection && log.isDebugEnabled())
  456. +        {
  457. +            log.debug("Reflecting " + classToReflect);
  458. +        }
  459. +
  460. +        try
  461. +        {
  462. +            Field[] fields = classToReflect.getDeclaredFields();
  463. +            for (int i = 0; i < fields.length; i++)
  464. +            {
  465. +                int modifiers = fields[i].getModifiers();
  466. +                if (Modifier.isPublic(modifiers))
  467. +                {
  468. +                    fieldCache.put(fields[i].getName(), fields[i]);
  469. +                }
  470. +            }
  471. +        }
  472. +        catch (SecurityException se) // Everybody feels better with...
  473. +        {
  474. +            if (log.isDebugEnabled())
  475. +            {
  476. +                log.debug("While accessing fields of " + classToReflect + ": ", se);
  477. +            }
  478. +        }
  479. +    }
  480. +
  481. +}
  482. diff --git a/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java b/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
  483. index db6031f..48f469d 100644
  484. --- a/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
  485. +++ b/src/java/org/apache/velocity/util/introspection/IntrospectorBase.java
  486. @@ -19,6 +19,7 @@ package org.apache.velocity.util.introspection;
  487.   * under the License.    
  488.   */
  489.  
  490. +import java.lang.reflect.Field;
  491.  import java.lang.reflect.Method;
  492.  
  493.  import org.apache.velocity.runtime.log.Log;
  494. @@ -49,6 +50,7 @@ import org.apache.velocity.runtime.log.Log;
  495.   * @author <a href="mailto:szegedia@freemail.hu">Attila Szegedi</a>
  496.   * @author <a href="mailto:paulo.gaspar@krankikom.de">Paulo Gaspar</a>
  497.   * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  498. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  499.   * @version $Id: IntrospectorBase.java 685685 2008-08-13 21:43:27Z nbubna $
  500.   */
  501.  public abstract class IntrospectorBase
  502. @@ -106,6 +108,35 @@ public abstract class IntrospectorBase
  503.      }
  504.  
  505.      /**
  506. +     * Gets the field defined by <code>name</code>.
  507. +     *
  508. +     * @param c Class in which the method search is taking place
  509. +     * @param name Name of the field being searched for
  510. +     *
  511. +     * @return The desired Field object.
  512. +     * @throws IllegalArgumentException When the parameters passed in can not be used for introspection.
  513. +     */
  514. +    public Field getField(final Class c, final String name)
  515. +            throws IllegalArgumentException
  516. +    {
  517. +        if (c == null)
  518. +        {
  519. +            throw new IllegalArgumentException("class object is null!");
  520. +        }
  521. +
  522. +        IntrospectorCache ic = getIntrospectorCache();
  523. +
  524. +        ClassFieldMap classFieldMap = ic.getFieldMap(c);
  525. +        if (classFieldMap == null)
  526. +        {
  527. +            ic.put(c);
  528. +            classFieldMap = ic.getFieldMap(c);
  529. +        }
  530. +
  531. +        return classFieldMap.findField(name);
  532. +    }
  533. +
  534. +    /**
  535.       * Return the internal IntrospectorCache object.
  536.       *
  537.       * @return The internal IntrospectorCache object.
  538. diff --git a/src/java/org/apache/velocity/util/introspection/IntrospectorCache.java b/src/java/org/apache/velocity/util/introspection/IntrospectorCache.java
  539. index 3b70728..a730996 100644
  540. --- a/src/java/org/apache/velocity/util/introspection/IntrospectorCache.java
  541. +++ b/src/java/org/apache/velocity/util/introspection/IntrospectorCache.java
  542. @@ -23,6 +23,7 @@ package org.apache.velocity.util.introspection;
  543.   * The introspector cache API definition.
  544.   *
  545.   * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  546. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  547.   * @version $Id: IntrospectorCache.java 685685 2008-08-13 21:43:27Z nbubna $
  548.   * @since 1.5
  549.   */
  550. @@ -44,6 +45,16 @@ public interface IntrospectorCache {
  551.      ClassMap get(Class c);
  552.  
  553.      /**
  554. +     * Lookup a given Class object in the cache. If it does not exist,
  555. +     * check whether this is due to a class change and purge the caches
  556. +     * eventually.
  557. +     *
  558. +     * @param c The class to look up.
  559. +     * @return A ClassFieldMap object or null if it does not exist in the cache.
  560. +     */
  561. +    ClassFieldMap getFieldMap(final Class c);
  562. +
  563. +    /**
  564.       * Creates a class map for specific class and registers it in the
  565.       * cache.  Also adds the qualified name to the name-&gt;class map
  566.       * for later Classloader change detection.
  567. diff --git a/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java b/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
  568. index 1dbe9cd..6b7ebab 100644
  569. --- a/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
  570. +++ b/src/java/org/apache/velocity/util/introspection/IntrospectorCacheImpl.java
  571. @@ -30,6 +30,7 @@ import org.apache.velocity.runtime.log.Log;
  572.   * This is the internal introspector cache implementation.
  573.   *
  574.   * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  575. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  576.   * @version $Id: IntrospectorCacheImpl.java 898032 2010-01-11 19:51:03Z nbubna $
  577.   * @since 1.5
  578.   */
  579. @@ -50,6 +51,11 @@ public final class IntrospectorCacheImpl implements IntrospectorCache
  580.      private final Map classMapCache = new HashMap();
  581.  
  582.      /**
  583. +     * Holds the field maps for the classes we know about. Map: Class --&gt; ClassFieldMap object.
  584. +     */
  585. +    private final Map classFieldMapCache = new HashMap();
  586. +
  587. +    /**
  588.       * Keep the names of the classes in another map. This is needed for a multi-classloader environment where it is possible
  589.       * to have Class 'Foo' loaded by a classloader and then get asked to introspect on 'Foo' from another class loader. While these
  590.       * two Class objects have the same name, a <code>classMethodMaps.get(Foo.class)</code> will return null. For that case, we
  591. @@ -73,13 +79,14 @@ public final class IntrospectorCacheImpl implements IntrospectorCache
  592.          synchronized (classMapCache)
  593.          {
  594.              classMapCache.clear();
  595. +            classFieldMapCache.clear();
  596.              classNameCache.clear();
  597.              log.debug(CACHEDUMP_MSG);
  598.          }
  599.      }
  600.  
  601.      /**
  602. -     * Lookup a given Class object in the cache. If it does not exist,
  603. +     * Lookup a given Class object in the cache. If it does not exist,
  604.       * check whether this is due to a class change and purge the caches
  605.       * eventually.
  606.       *
  607. @@ -114,6 +121,41 @@ public final class IntrospectorCacheImpl implements IntrospectorCache
  608.      }
  609.  
  610.      /**
  611. +     * Lookup a given Class object in the cache. If it does not exist,
  612. +     * check whether this is due to a class change and purge the caches
  613. +     * eventually.
  614. +     *
  615. +     * @param c The class to look up.
  616. +     * @return A ClassFieldMap object or null if it does not exist in the cache.
  617. +     */
  618. +    public ClassFieldMap getFieldMap(final Class c)
  619. +    {
  620. +        if (c == null)
  621. +        {
  622. +            throw new IllegalArgumentException("class is null!");
  623. +        }
  624. +
  625. +        ClassFieldMap classFieldMap = (ClassFieldMap)classFieldMapCache.get(c);
  626. +        if (classFieldMap == null)
  627. +        {
  628. +            /*
  629. +             * check to see if we have it by name.
  630. +             * if so, then we have an object with the same
  631. +             * name but loaded through a different class loader.
  632. +             * In that case, we will just dump the cache to be sure.
  633. +             */
  634. +            synchronized (classMapCache)
  635. +            {
  636. +                if (classNameCache.contains(c.getName()))
  637. +                {
  638. +                    clear();
  639. +                }
  640. +            }
  641. +        }
  642. +        return classFieldMap;
  643. +    }
  644. +
  645. +    /**
  646.       * Creates a class map for specific class and registers it in the
  647.       * cache.  Also adds the qualified name to the name-&gt;class map
  648.       * for later Classloader change detection.
  649. @@ -124,9 +166,11 @@ public final class IntrospectorCacheImpl implements IntrospectorCache
  650.      public ClassMap put(final Class c)
  651.      {
  652.          final ClassMap classMap = new ClassMap(c, log);
  653. +        final ClassFieldMap classFieldMap = new ClassFieldMap(c, log);
  654.          synchronized (classMapCache)
  655.          {
  656.              classMapCache.put(c, classMap);
  657. +            classFieldMapCache.put(c, classFieldMap);
  658.              classNameCache.add(c.getName());
  659.          }
  660.          return classMap;
  661. diff --git a/src/java/org/apache/velocity/util/introspection/UberspectPublicFields.java b/src/java/org/apache/velocity/util/introspection/UberspectPublicFields.java
  662. new file mode 100644
  663. index 0000000..e854e67
  664. --- /dev/null
  665. +++ b/src/java/org/apache/velocity/util/introspection/UberspectPublicFields.java
  666. @@ -0,0 +1,137 @@
  667. +/*
  668. + * Licensed to the Apache Software Foundation (ASF) under one
  669. + * or more contributor license agreements.  See the NOTICE file
  670. + * distributed with this work for additional information
  671. + * regarding copyright ownership.  The ASF licenses this file
  672. + * to you under the Apache License, Version 2.0 (the
  673. + * "License"); you may not use this file except in compliance
  674. + * with the License.  You may obtain a copy of the License at
  675. + *
  676. + *   http://www.apache.org/licenses/LICENSE-2.0
  677. + *
  678. + * Unless required by applicable law or agreed to in writing,
  679. + * software distributed under the License is distributed on an
  680. + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  681. + * KIND, either express or implied.  See the License for the
  682. + * specific language governing permissions and limitations
  683. + * under the License.
  684. + */
  685. +
  686. +package org.apache.velocity.util.introspection;
  687. +
  688. +import java.util.Iterator;
  689. +import org.apache.velocity.runtime.RuntimeLogger;
  690. +import org.apache.velocity.runtime.log.Log;
  691. +import org.apache.velocity.runtime.log.RuntimeLoggerLog;
  692. +import org.apache.velocity.runtime.parser.node.PublicFieldExecutor;
  693. +import org.apache.velocity.runtime.parser.node.SetPublicFieldExecutor;
  694. +import org.apache.velocity.util.introspection.UberspectImpl.VelGetterImpl;
  695. +import org.apache.velocity.util.introspection.UberspectImpl.VelSetterImpl;
  696. +
  697. +/**
  698. + * Implementation of Uberspect to additionally provide access to public fields.
  699. + *
  700. + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
  701. + * @author <a href="mailto:henning@apache.org">Henning P. Schmiedehausen</a>
  702. + * @author <a href="mailto:cdauth@cdauth.eu">Candid Dauth</a>
  703. + */
  704. +public class UberspectPublicFields implements Uberspect, UberspectLoggable
  705. +{
  706. +    /**
  707. +     *  Our runtime logger.
  708. +     */
  709. +    protected Log log;
  710. +
  711. +    /**
  712. +     *  the default Velocity introspector
  713. +     */
  714. +    protected Introspector introspector;
  715. +
  716. +    /**
  717. +     *  init - generates the Introspector. As the setup code
  718. +     *  makes sure that the log gets set before this is called,
  719. +     *  we can initialize the Introspector using the log object.
  720. +     */
  721. +    public void init()
  722. +    {
  723. +        introspector = new Introspector(log);
  724. +    }
  725. +
  726. +    /**
  727. +     *  Sets the runtime logger - this must be called before anything
  728. +     *  else.
  729. +     *
  730. +     * @param log The logger instance to use.
  731. +     * @since 1.5
  732. +     */
  733. +    public void setLog(Log log)
  734. +    {
  735. +        this.log = log;
  736. +    }
  737. +
  738. +    /**
  739. +     * @param runtimeLogger
  740. +     * @deprecated Use setLog(Log log) instead.
  741. +     */
  742. +    public void setRuntimeLogger(RuntimeLogger runtimeLogger)
  743. +    {
  744. +        // in the off chance anyone still uses this method
  745. +        // directly, use this hack to keep it working
  746. +        setLog(new RuntimeLoggerLog(runtimeLogger));
  747. +    }
  748. +
  749. +    /**
  750. +     * Property getter
  751. +     * @param obj
  752. +     * @param identifier
  753. +     * @param i
  754. +     * @return A Velocity Getter Method.
  755. +     * @throws Exception
  756. +     */
  757. +    public VelPropertyGet getPropertyGet(Object obj, String identifier, Info i) throws Exception
  758. +    {
  759. +        if (obj == null)
  760. +        {
  761. +            return null;
  762. +        }
  763. +
  764. +        Class claz = obj.getClass();
  765. +
  766. +        PublicFieldExecutor executor = new PublicFieldExecutor(log, introspector, claz, identifier);
  767. +
  768. +        return (executor.isAlive()) ? new VelGetterImpl(executor) : null;
  769. +    }
  770. +
  771. +    /**
  772. +     * Property setter
  773. +     * @param obj
  774. +     * @param identifier
  775. +     * @param arg
  776. +     * @param i
  777. +     * @return A Velocity Setter method.
  778. +     * @throws Exception
  779. +     */
  780. +    public VelPropertySet getPropertySet(Object obj, String identifier, Object arg, Info i) throws Exception {
  781. +        if (obj == null)
  782. +        {
  783. +            return null;
  784. +        }
  785. +
  786. +        Class claz = obj.getClass();
  787. +
  788. +        SetPublicFieldExecutor executor = new SetPublicFieldExecutor(log, introspector, claz, identifier, arg);
  789. +
  790. +        return (executor.isAlive()) ? new VelSetterImpl(executor) : null;
  791. +    }
  792. +
  793. +    public Iterator getIterator(Object obj, Info info) throws Exception
  794. +    {
  795. +        return null;
  796. +    }
  797. +
  798. +    public VelMethod getMethod(Object obj, String method, Object[] args, Info info) throws Exception
  799. +    {
  800. +        return null;
  801. +    }
  802. +
  803. +}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement