KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > iiop > rmi > ValueAnalysis


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.iiop.rmi;
23
24 import org.omg.CORBA.portable.IDLEntity JavaDoc;
25 import org.omg.CORBA.portable.ValueBase JavaDoc;
26
27 import java.rmi.Remote JavaDoc;
28
29 import java.io.Serializable JavaDoc;
30 import java.io.Externalizable JavaDoc;
31 import java.io.ObjectStreamField JavaDoc;
32
33 import java.util.ArrayList JavaDoc;
34 import java.util.SortedSet JavaDoc;
35 import java.util.TreeSet JavaDoc;
36 import java.util.Comparator JavaDoc;
37
38 import java.lang.reflect.Method JavaDoc;
39 import java.lang.reflect.Field JavaDoc;
40 import java.lang.reflect.Modifier JavaDoc;
41
42 /**
43  * Value analysis.
44  *
45  * Routines here are conforming to the "Java(TM) Language to IDL Mapping
46  * Specification", version 1.1 (01-06-07).
47  *
48  * @author <a HREF="mailto:osh@sparre.dk">Ole Husgaard</a>
49  * @version $Revision: 37459 $
50  */

51 public class ValueAnalysis
52    extends ContainerAnalysis
53 {
54    // Constants -----------------------------------------------------
55

56    // Attributes ----------------------------------------------------
57

58    // Static --------------------------------------------------------
59

60    private static final org.jboss.logging.Logger logger =
61                org.jboss.logging.Logger.getLogger(ValueAnalysis.class);
62
63    private static WorkCacheManager cache
64                                = new WorkCacheManager(ValueAnalysis.class);
65  
66    public static ValueAnalysis getValueAnalysis(Class JavaDoc cls)
67       throws RMIIIOPViolationException
68    {
69       return (ValueAnalysis)cache.getAnalysis(cls);
70    }
71  
72    // Constructors --------------------------------------------------
73

74    protected ValueAnalysis(Class JavaDoc cls)
75    {
76       super(cls);
77       logger.debug("ValueAnalysis(\""+cls.getName()+"\") entered.");
78    }
79
80    public String JavaDoc getIDLModuleName()
81    {
82       String JavaDoc result = super.getIDLModuleName();
83
84       // Checked for boxedIDL 1.3.9
85
Class JavaDoc clazz = getCls();
86       if (IDLEntity JavaDoc.class.isAssignableFrom(clazz) && ValueBase JavaDoc.class.isAssignableFrom(clazz) == false)
87          result = "::org::omg::boxedIDL" + result;
88       return result;
89    }
90  
91    protected void doAnalyze()
92       throws RMIIIOPViolationException
93    {
94       super.doAnalyze();
95
96       if (cls == String JavaDoc.class)
97          throw new IllegalArgumentException JavaDoc(
98                              "Cannot analyze java.lang.String here: It is a " +
99                              "special case."); // 1.3.5.11
100

101       if (cls == Class JavaDoc.class)
102          throw new IllegalArgumentException JavaDoc(
103                              "Cannot analyze java.lang.Class here: It is a " +
104                              "special case."); // 1.3.5.10
105

106       if (Remote JavaDoc.class.isAssignableFrom(cls))
107          throw new RMIIIOPViolationException(
108                              "Value type " + cls.getName() +
109                              " cannot implement java.rmi.Remote.", "1.2.4");
110
111       if (cls.getName().indexOf('$') != -1)
112          throw new RMIIIOPNotImplementedException(
113                              "Class " + cls.getName() + " has a '$', like " +
114                              "proxies or inner classes.");
115
116       externalizable = Externalizable JavaDoc.class.isAssignableFrom(cls);
117
118       if (!externalizable) {
119          // Look for serialPersistentFields field.
120
Field JavaDoc spf = null;
121          try {
122             spf = cls.getField("serialPersistentFields");
123          } catch (NoSuchFieldException JavaDoc ex) {
124             // ignore
125
}
126          if (spf != null) { // Right modifiers?
127
int mods = spf.getModifiers();
128             if (!Modifier.isFinal(mods) || !Modifier.isStatic(mods) ||
129                 !Modifier.isPrivate(mods))
130               spf = null; // wrong modifiers
131
}
132          if (spf != null) { // Right type?
133
Class JavaDoc type = spf.getType();
134             if (type.isArray()) {
135                type = type.getComponentType();
136                if (type != ObjectStreamField JavaDoc.class)
137                  spf = null; // Array of wrong type
138
} else
139                spf = null; // Wrong type: Not an array
140
}
141          if (spf != null) {
142             // We have the serialPersistentFields field
143

144             // Get this constant
145
try {
146                serialPersistentFields = (ObjectStreamField JavaDoc[])spf.get(null);
147             } catch (IllegalAccessException JavaDoc ex) {
148                throw new RuntimeException JavaDoc("Unexpected IllegalException: " +
149                                           ex.toString());
150             }
151
152             // Mark this in the fields array
153
for (int i = 0; i < fields.length; ++i) {
154                if (fields[i] == spf) {
155                   f_flags[i] |= F_SPFFIELD;
156                   break;
157                }
158             }
159          }
160
161          // Look for a writeObject Method
162
Method JavaDoc wo = null;
163          try {
164             wo = cls.getMethod("writeObject",
165                                new Class JavaDoc[] {java.io.OutputStream JavaDoc[].class} );
166          } catch (NoSuchMethodException JavaDoc ex) {
167             // ignore
168
}
169          if (wo != null) { // Right return type?
170
if (wo.getReturnType() != Void.TYPE)
171                wo = null; // Wrong return type
172
}
173          if (wo != null) { // Right modifiers?
174
int mods = spf.getModifiers();
175             if (!Modifier.isPrivate(mods))
176               wo = null; // wrong modifiers
177
}
178          if (wo != null) { // Right arguments?
179
Class JavaDoc[] paramTypes = wo.getParameterTypes();
180             if (paramTypes.length != 1)
181                wo = null; // Bad number of parameters
182
else if (paramTypes[0] != java.io.OutputStream JavaDoc.class)
183                wo = null; // Bad parameter type
184
}
185          if (wo != null) {
186             // We have the writeObject() method.
187
hasWriteObjectMethod = true;
188
189             // Mark this in the methods array
190
for (int i = 0; i < methods.length; ++i) {
191                if (methods[i] == wo) {
192                   m_flags[i] |= M_WRITEOBJECT;
193                   break;
194                }
195             }
196          }
197       }
198
199       // Map all fields not flagged constant or serialPersistentField.
200
SortedSet JavaDoc m = new TreeSet JavaDoc(new ValueMemberComparator());
201
202       logger.debug("ValueAnalysis(\""+cls.getName()+"\"): " +
203                    "fields.length="+fields.length);
204       for (int i = 0; i < fields.length; ++i) {
205          logger.debug("ValueAnalysis(\""+cls.getName()+"\"): " +
206                       "Considering field["+i+"] \"" + fields[i].getName() +
207                       "\"" + " f_flags=" + f_flags[i]);
208          if (f_flags[i] != 0)
209             continue; // flagged
210

211          int mods = fields[i].getModifiers();
212          logger.debug("ValueAnalysis(\""+cls.getName()+"\"): mods=" + mods);
213          if (Modifier.isStatic(mods) || Modifier.isTransient(mods))
214             continue; // don't map this
215

216          ValueMemberAnalysis vma;
217          vma = new ValueMemberAnalysis(fields[i].getName(),
218                                        fields[i].getType(),
219                                        Modifier.isPublic(mods));
220          m.add(vma);
221       }
222
223       members = new ValueMemberAnalysis[m.size()];
224       members = (ValueMemberAnalysis[])m.toArray(members);
225       logger.debug("ValueAnalysis(\""+cls.getName()+"\") value member count: "
226                    + members.length);
227       
228       // Get superclass analysis
229
Class JavaDoc superClass = cls.getSuperclass();
230       if (superClass == java.lang.Object JavaDoc.class)
231          superClass = null;
232       if (superClass == null)
233          superAnalysis = null;
234       else {
235          logger.debug("ValueAnalysis(\""+cls.getName()+"\"): superclass: " +
236                       superClass.getName());
237          superAnalysis = getValueAnalysis(superClass);
238       }
239
240       if (!Serializable JavaDoc.class.isAssignableFrom(cls))
241          abstractValue = true;
242
243       fixupCaseNames();
244
245       logger.debug("ValueAnalysis(\""+cls.getName()+"\") done.");
246    }
247
248    // Public --------------------------------------------------------
249

250    /**
251     * Returns the superclass analysis, or null if this inherits from
252     * java.lang.Object.
253     */

254    public ValueAnalysis getSuperAnalysis()
255    {
256       return superAnalysis;
257    }
258
259    /**
260     * Returns true if this value is abstract.
261     */

262    public boolean isAbstractValue()
263    {
264       return abstractValue;
265    }
266
267    /**
268     * Returns true if this value is custom.
269     */

270    public boolean isCustom()
271    {
272       return externalizable || hasWriteObjectMethod;
273    }
274
275    /**
276     * Returns true if this value implements java.io.Externalizable.
277     */

278    public boolean isExternalizable()
279    {
280       return externalizable;
281    }
282
283    /**
284     * Return the value members of this value class.
285     */

286    public ValueMemberAnalysis[] getMembers()
287    {
288       return (ValueMemberAnalysis[])members.clone();
289    }
290
291
292    // Protected -----------------------------------------------------
293

294    /**
295     * Analyse attributes.
296     * This will fill in the <code>attributes</code> array.
297     * Here we override the implementation in ContainerAnalysis and create an
298     * empty array, because for valuetypes we don't want to analyse IDL
299     * attributes or operations (as in "rmic -idl -noValueMethods").
300     */

301    protected void analyzeAttributes()
302       throws RMIIIOPViolationException
303    {
304       attributes = new AttributeAnalysis[0];
305    }
306
307    /**
308     * Return a list of all the entries contained here.
309     *
310     * @param entries The list of entries contained here. Entries in this list
311     * are subclasses of <code>AbstractAnalysis</code>.
312     */

313    protected ArrayList JavaDoc getContainedEntries()
314    {
315       ArrayList JavaDoc ret = new ArrayList JavaDoc(constants.length +
316                                     attributes.length +
317                                     members.length);
318  
319       for (int i = 0; i < constants.length; ++i)
320          ret.add(constants[i]);
321       for (int i = 0; i < attributes.length; ++i)
322          ret.add(attributes[i]);
323       for (int i = 0; i < members.length; ++i)
324          ret.add(members[i]);
325
326       return ret;
327    }
328
329
330    // Private -------------------------------------------------------
331

332    /**
333     * Analysis of our superclass, of null if our superclass is
334     * java.lang.Object.
335     */

336    ValueAnalysis superAnalysis;
337
338    /**
339     * Flags that this is an abstract value.
340     */

341    private boolean abstractValue = false;
342
343    /**
344     * Flags that this implements <code>java.io.Externalizable</code>.
345     */

346    private boolean externalizable = false;
347
348    /**
349     * Flags that this has a <code>writeObject()</code> method.
350     */

351    private boolean hasWriteObjectMethod = false;
352
353    /**
354     * The <code>serialPersistentFields of the value, or <code>null</code>
355     * if the value does not have this field.
356     */

357    private ObjectStreamField JavaDoc[] serialPersistentFields;
358
359    /**
360     * The value members of this value class.
361     */

362    private ValueMemberAnalysis[] members;
363
364
365    // Inner classes ------------------------------------------------
366

367    /**
368     * A <code>Comparator</code> for the field ordering specified at the
369     * end of section 1.3.5.6.
370     */

371    private static class ValueMemberComparator
372       implements Comparator JavaDoc
373    {
374       public int compare(Object JavaDoc o1, Object JavaDoc o2)
375       {
376          if (o1 == o2)
377             return 0;
378
379          ValueMemberAnalysis m1 = (ValueMemberAnalysis)o1;
380          ValueMemberAnalysis m2 = (ValueMemberAnalysis)o2;
381
382          boolean p1 = m1.getCls().isPrimitive();
383          boolean p2 = m2.getCls().isPrimitive();
384
385          if (p1 && !p2)
386             return -1;
387          if (!p1 && p2)
388             return 1;
389
390          return m1.getJavaName().compareTo(m2.getJavaName());
391       }
392    }
393 }
394
Popular Tags