View Javadoc

1   /*
2    * @(#) FieldSignature.java Jan 12, 2004 Copyright (c) 2002-2005 Delft
3    * University of Technology Jaffalaan 5, 2628 BX Delft, the Netherlands. All
4    * rights reserved. This software is proprietary information of Delft University
5    * of Technology The code is published under the Lesser General Public License
6    */
7   package nl.tudelft.simulation.language.reflection;
8   
9   import java.io.Serializable;
10  import java.lang.reflect.Array;
11  import java.util.HashMap;
12  import java.util.Map;
13  
14  import nl.tudelft.simulation.language.primitives.Primitive;
15  
16  /***
17   * A field descriptor represents the type of a class, instance, or local
18   * variable. It is a series of characters generated by the grammar described at
19   * <a href =
20   * "http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#1169">
21   * The Java Virtual Machine Specification </a>.
22   * <p>
23   * (c) copyright 2002-2005 <a href="http://www.simulation.tudelft.nl">Delft
24   * University of Technology </a>, the Netherlands.
25   * <p>
26   * See for project information <a
27   * href="http://www.simulation.tudelft.nl/dsol/language">www.simulation.tudelft.nl/language
28   * </a> <br>
29   * License of use: <a href="http://www.gnu.org/copyleft/lesser.html">Lesser
30   * General Public License (LGPL) </a>, no warranty
31   * 
32   * @author <a href="http://www.peter-jacobs.com/index.htm">Peter Jacobs </a>, <a
33   *         href="mailto:nlang@fbk.eur.nl">Niels Lang </a><a
34   *         href="mailto:a.verbraeck@tbm.tudelft.nl">Alexander
35   *         Verbraeck </a>
36   * @version $Revision: 1.8 $ $Date: 2005/08/04 12:08:54 $
37   * @since 1.5
38   */
39  public class FieldSignature implements Serializable
40  {
41      /*** the CAHCHE */
42      private static final Map<String, Class> CACHE = new HashMap<String, Class>();
43  
44      /*** the value of the field descriptor */
45      private String value;
46  
47      /***
48       * constructs a new FieldSignature
49       * 
50       * @param value the value of the descriptor
51       */
52      public FieldSignature(final String value)
53      {
54          super();
55          this.value = value;
56      }
57  
58      /***
59       * constructs a new FieldSignature
60       * 
61       * @param clazz The class
62       */
63      public FieldSignature(final Class clazz)
64      {
65          this(FieldSignature.toDescriptor(clazz));
66      }
67  
68      /***
69       * @return Returns the value of the field descriptor
70       */
71      public String getStringValue()
72      {
73          return this.value;
74      }
75  
76      /***
77       * @return Returns the value of the field descriptor
78       * @throws ClassNotFoundException if the class cannot be found.
79       */
80      public Class getClassValue() throws ClassNotFoundException
81      {
82          return FieldSignature.toClass(this.value);
83      }
84  
85      /***
86       * @see java.lang.Object#toString()
87       */
88      @Override
89  	public String toString()
90      {
91          return this.value;
92      }
93  
94      /***
95       * converts an array of fields to its descriptor
96       * 
97       * @param classes the classes to represent
98       * @return String the descriptor String
99       */
100     public static final String toDescriptor(final Class[] classes)
101     {
102         String result = "";
103         for (int i = 0; i < classes.length; i++)
104         {
105             result = result + FieldSignature.toDescriptor(classes[i]);
106         }
107         return result;
108     }
109 
110     /***
111      * converts a field to its descriptor
112      * 
113      * @param clazz the clazz to represent
114      * @return String the descriptor String
115      */
116     public static final String toDescriptor(final Class clazz)
117     {
118         if (clazz.getName().startsWith("["))
119         {
120             return clazz.getName().replace('.', '/');
121         }
122         if (clazz.isPrimitive())
123         {
124             if (clazz.equals(int.class))
125             {
126                 return "I";
127             }
128             if (clazz.equals(double.class))
129             {
130                 return "D";
131             }
132             if (clazz.equals(boolean.class))
133             {
134                 return "Z";
135             }
136             if (clazz.equals(char.class))
137             {
138                 return "C";
139             }
140             if (clazz.equals(byte.class))
141             {
142                 return "B";
143             }
144             if (clazz.equals(float.class))
145             {
146                 return "F";
147             }
148             if (clazz.equals(long.class))
149             {
150                 return "J";
151             }
152             if (clazz.equals(short.class))
153             {
154                 return "S";
155             }
156             return "V";
157         }
158         return "L" + clazz.getName().replace('.', '/') + ";";
159     }
160 
161     /***
162      * converts a fieldDescriptor to its class representation
163      * 
164      * @param descriptor the descriptor
165      * @return Class the class
166      * @throws ClassNotFoundException on failure
167      */
168     public static final Class toClass(final String descriptor)
169             throws ClassNotFoundException
170     {
171         if (FieldSignature.CACHE.containsKey(descriptor))
172         {
173             return FieldSignature.CACHE.get(descriptor);
174         }
175         String className = descriptor;
176         Class result = null;
177         int array = 0;
178         while (className.charAt(array) == '[')
179         {
180             array++;
181         }
182         className = className.substring(array);
183         if (className.startsWith("L"))
184         {
185             className = className.replaceAll("/", ".");
186             className = className.substring(1, className.length() - 1);
187             try
188             {
189                 result = Class.forName(className);
190             } catch (Exception exception)
191             {
192                 result = Class.forName(className, true, Thread.currentThread()
193                         .getContextClassLoader());
194             }
195         } else
196         {
197             result = Primitive.forName(className);
198         }
199         if (result == null && !descriptor.startsWith("["))
200         {
201             // For some reason not all classes start with L and end with ;
202             return FieldSignature.toClass("L" + descriptor + ";");
203         }
204         if (array == 0)
205         {
206             FieldSignature.CACHE.put(descriptor, result);
207             return result;
208         }
209         try
210         {
211             int[] dimensions = new int[array];
212             result = Array.newInstance(result, dimensions).getClass();
213         } catch (Exception exception)
214         {
215             throw new ClassNotFoundException(result + " class not found");
216         }
217         FieldSignature.CACHE.put(descriptor, result);
218         return result;
219     }
220 }