Clover Coverage Report - EasyMock 3.0
Coverage timestamp: sam. mai 8 2010 14:37:27 CEST
../../../img/srcFileCovDistChart10.png 0% of files have more coverage
48   206   22   6
12   115   0,46   8
8     2,75  
1    
21,8% of code in this file is excluded from these metrics.
 
  DefaultClassInstantiator       Line # 30 48 21,8% 22 0 100% 1.0
 
  (24)
 
1    /**
2    * Copyright 2001-2010 the original author or authors.
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    package org.easymock.internal;
18   
19    import java.io.*;
20    import java.lang.reflect.*;
21   
22    import org.easymock.EasyMock;
23   
24    /**
25    * Default class instantiator that is pretty limited. It just hope that the
26    * mocked class has a public empty constructor.
27    *
28    * @author Henri Tremblay
29    */
 
30    public class DefaultClassInstantiator implements IClassInstantiator {
31   
32    /**
33    * Try to instantiate a class without using a special constructor. See
34    * documentation for the algorithm.
35    *
36    * @param c
37    * Class to instantiate
38    */
 
39  32 toggle public Object newInstance(final Class<?> c) throws InstantiationException {
40   
41  32 if (isSerializable(c)) {
42  8 try {
43  8 return readObject(getSerializedBytes(c));
44    // ///CLOVER:OFF
45    } catch (final IOException e) {
46    throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: "
47    + e.getMessage());
48    } catch (final ClassNotFoundException e) {
49    throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: "
50    + e.getMessage());
51    }
52    // ///CLOVER:ON
53    }
54   
55  24 final Constructor<?> constructor = getConstructorToUse(c);
56  20 final Object[] params = getArgsForTypes(constructor.getParameterTypes());
57  20 try {
58  20 return constructor.newInstance(params);
59    // ///CLOVER:OFF
60    } catch (final IllegalArgumentException e) {
61    throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: " + e.getMessage());
62    } catch (final IllegalAccessException e) {
63    throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: " + e.getMessage());
64    // ///CLOVER:ON
65    } catch (final InvocationTargetException e) {
66  2 throw new RuntimeException("Failed to instantiate " + c.getName() + "'s mock: " + e.getMessage());
67    }
68    }
69   
70    /**
71    * Tells if the provided class is serializable
72    *
73    * @param clazz
74    * Class to check
75    * @return If the class is serializable
76    */
 
77  32 toggle private boolean isSerializable(final Class<?> clazz) {
78  32 return Serializable.class.isAssignableFrom(clazz);
79    }
80   
81    /**
82    * Return the constructor considered the best to use with this class.
83    * Algorithm is: No args constructor and then first constructor defined in
84    * the class
85    *
86    * @param clazz
87    * Class in which constructor is searched
88    * @return Constructor to use
89    */
 
90  24 toggle private Constructor<?> getConstructorToUse(final Class<?> clazz) {
91    // First try to use the empty constructor
92  24 try {
93  24 return clazz.getConstructor(new Class[0]);
94    } catch (final NoSuchMethodException e) {
95    // If it fails just use the first one
96  16 if (clazz.getConstructors().length == 0) {
97  4 throw new IllegalArgumentException("No visible constructors in class " + clazz.getName());
98    }
99  12 return clazz.getConstructors()[0];
100    }
101    }
102   
103    /**
104    * Get some default instances of provided classes
105    *
106    * @param methodTypes
107    * Classes to instantiate
108    * @return Instances of methodTypes in order
109    */
 
110  20 toggle private Object[] getArgsForTypes(final Class<?>[] methodTypes) throws InstantiationException {
111  20 final Object[] methodArgs = new Object[methodTypes.length];
112   
113  32 for (int i = 0; i < methodTypes.length; i++) {
114   
115  12 if (methodTypes[i].isPrimitive()) {
116    // Return a nice wrapped primitive type
117  4 methodArgs[i] = RecordState.emptyReturnValueFor(methodTypes[i]);
118  8 } else if (Modifier.isFinal(methodTypes[i].getModifiers())) {
119    // Instantiate the class using the best constructor we can find
120    // (because it's not
121    // possible to mock a final class)
122  4 methodArgs[i] = newInstance(methodTypes[i]);
123    } else {
124    // For all classes and interfaces, just return a nice mock
125  4 final Object mock = EasyMock.createNiceMock(methodTypes[i]);
126  4 EasyMock.replay(mock);
127  4 methodArgs[i] = mock;
128    }
129    }
130  20 return methodArgs;
131    }
132   
 
133  8 toggle private static byte[] getSerializedBytes(final Class<?> clazz) throws IOException {
134  8 final ByteArrayOutputStream baos = new ByteArrayOutputStream();
135  8 final DataOutputStream data = new DataOutputStream(baos);
136  8 data.writeShort(ObjectStreamConstants.STREAM_MAGIC);
137  8 data.writeShort(ObjectStreamConstants.STREAM_VERSION);
138  8 data.writeByte(ObjectStreamConstants.TC_OBJECT);
139  8 data.writeByte(ObjectStreamConstants.TC_CLASSDESC);
140  8 data.writeUTF(clazz.getName());
141   
142  8 final Long suid = getSerializableUID(clazz);
143   
144  8 data.writeLong(suid.longValue());
145   
146  8 data.writeByte(2); // classDescFlags (2 = Serializable)
147  8 data.writeShort(0); // field count
148  8 data.writeByte(ObjectStreamConstants.TC_ENDBLOCKDATA);
149  8 data.writeByte(ObjectStreamConstants.TC_NULL);
150  8 return baos.toByteArray();
151    }
152   
 
153  8 toggle private static Long getSerializableUID(final Class<?> clazz) {
154   
155  8 try {
156  8 final Field f = clazz.getDeclaredField("serialVersionUID");
157  6 final int mask = Modifier.STATIC | Modifier.FINAL;
158  6 if ((f.getModifiers() & mask) == mask) {
159  4 f.setAccessible(true);
160  4 return Long.valueOf(f.getLong(null));
161    }
162    } catch (final NoSuchFieldException e) {
163    // It's not there, compute it then
164    } catch (final IllegalAccessException e) {
165    // ///CLOVER:OFF
166    throw new RuntimeException("Should have been able to get serialVersionUID since it's there");
167    // ///CLOVER:ON
168    }
169    // ///CLOVER:OFF
170    return callLongMethod(clazz,
171    ClassInstantiatorFactory.is1_3Specifications() ? "computeSerialVersionUID"
172    : "computeDefaultSUID");
173    // ///CLOVER:ON
174    }
175   
 
176  4 toggle private static Long callLongMethod(final Class<?> clazz, final String methodName) {
177   
178  4 Method method;
179    // ///CLOVER:OFF
180    try {
181    method = ObjectStreamClass.class.getDeclaredMethod(methodName, new Class[] { Class.class });
182    } catch (final NoSuchMethodException e) {
183    throw new InternalError("ObjectStreamClass." + methodName + " seems to have vanished");
184    }
185    final boolean accessible = method.isAccessible();
186    method.setAccessible(true);
187    Long suid;
188    try {
189    suid = (Long) method.invoke(null, new Object[] { clazz });
190    } catch (final IllegalAccessException e) {
191    throw new InternalError("ObjectStreamClass." + methodName + " should have been accessible");
192    } catch (final InvocationTargetException e) {
193    throw new InternalError("ObjectStreamClass." + methodName + " failled to be called: "
194    + e.getMessage());
195    }
196    method.setAccessible(accessible);
197    // ///CLOVER:ON
198  4 return suid;
199    }
200   
 
201  8 toggle private static Object readObject(final byte[] bytes) throws IOException, ClassNotFoundException {
202  8 final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
203  8 return in.readObject();
204    }
205   
206    }