View | Details | Raw Unified | Return to bug 395897 | Differences between
and this patch

Collapse All | Expand All

(-)a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Accessor.java (+380 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.util;
12
13
import java.lang.reflect.Constructor;
14
import java.lang.reflect.Field;
15
import java.lang.reflect.InvocationTargetException;
16
import java.lang.reflect.Method;
17
import java.lang.reflect.Modifier;
18
19
import org.eclipse.core.runtime.Assert;
20
21
22
/**
23
 * Helper class for accessing classes and members which cannot be accessed using standard Java
24
 * access control like private or package visible elements.
25
 * <p>
26
 * <strong>Note:</strong> Copied from org.eclipse.text.tests.
27
 * </p>
28
 * 
29
 * @since 3.5
30
 */
31
public class Accessor {
32
33
	/** The class to access. */
34
	private Class fClass;
35
	/** The instance to access. */
36
	private Object fInstance;
37
38
	/**
39
	 * Creates an accessor for the given <code>instance</code> and
40
	 * <code>class</code>. Only non-inherited members that particular
41
	 * <code>class</code> can be accessed.
42
	 *
43
	 * @param instance the instance
44
	 * @param clazz the class
45
	 */
46
	public Accessor(Object instance, Class clazz) {
47
		org.eclipse.core.runtime.Assert.isNotNull(instance);
48
		Assert.isNotNull(clazz);
49
		fInstance= instance;
50
		fClass= clazz;
51
	}
52
53
	/**
54
	 * Creates an accessor for the given <code>instance</code> and
55
	 * <code>class</code>. Only non-inherited members that particular
56
	 * <code>class</code> can be accessed.
57
	 *
58
	 * @param instance the instance
59
	 * @param className the name of the class
60
	 * @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
61
	 */
62
	public Accessor(Object instance, String className, ClassLoader classLoader) {
63
		Assert.isNotNull(instance);
64
		Assert.isNotNull(className);
65
		Assert.isNotNull(classLoader);
66
		fInstance= instance;
67
		try {
68
			fClass= Class.forName(className, true, classLoader);
69
		} catch (ClassNotFoundException e) {
70
			fail();
71
		} catch (ExceptionInInitializerError e) {
72
			fail();
73
		}
74
	}
75
76
	/**
77
	 * Creates an accessor for the given class.
78
	 * <p>
79
	 * In order to get the type information from the given
80
	 * arguments they must all be instanceof Object. Use
81
	 * {@link #Accessor(String, ClassLoader, Class[], Object[])} if this
82
	 * is not the case.</p>
83
	 *
84
	 * @param className the name of the class
85
	 * @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
86
	 * @param constructorArgs the constructor arguments which must all be instance of Object
87
	 */
88
	public Accessor(String className, ClassLoader classLoader, Object[] constructorArgs) {
89
		this(className, classLoader, getTypes(constructorArgs), constructorArgs);
90
	}
91
92
	/**
93
	 * Creates an accessor for the given class.
94
	 *
95
	 * @param className the name of the class
96
	 * @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
97
	 * @param constructorTypes the types of the constructor arguments
98
	 * @param constructorArgs the constructor arguments
99
	 */
100
	public Accessor(String className, ClassLoader classLoader, Class[] constructorTypes, Object[] constructorArgs) {
101
		try {
102
			fClass= Class.forName(className, true, classLoader);
103
		} catch (ClassNotFoundException e) {
104
			fail();
105
		} catch (ExceptionInInitializerError e) {
106
			fail();
107
		}
108
		Constructor constructor= null;
109
		try {
110
			constructor= fClass.getDeclaredConstructor(constructorTypes);
111
		} catch (SecurityException e2) {
112
			fail();
113
		} catch (NoSuchMethodException e2) {
114
			fail();
115
		}
116
		Assert.isNotNull(constructor);
117
		constructor.setAccessible(true);
118
		try {
119
			fInstance= constructor.newInstance(constructorArgs);
120
		} catch (IllegalArgumentException e) {
121
			fail();
122
		} catch (InvocationTargetException e) {
123
			fail();
124
		} catch (InstantiationException e) {
125
			fail();
126
		} catch (IllegalAccessException e) {
127
			fail();
128
		}
129
	}
130
131
	/**
132
	 * Creates an accessor for the given class.
133
	 * <p>
134
	 * This constructor is used to access static stuff.
135
	 * </p>
136
	 *
137
	 * @param className the name of the class
138
	 * @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
139
	 */
140
	public Accessor(String className, ClassLoader classLoader) {
141
		try {
142
			fClass= Class.forName(className, true, classLoader);
143
		} catch (ClassNotFoundException e) {
144
			fail();
145
		} catch (ExceptionInInitializerError e) {
146
			fail();
147
		}
148
	}
149
150
	/**
151
	 * Invokes the method with the given method name and arguments.
152
	 * <p>
153
	 * In order to get the type information from the given
154
	 * arguments all those arguments must be instance of Object. Use
155
	 * {@link #invoke(String, Class[], Object[])} if this
156
	 * is not the case.</p>
157
	 *
158
	 * @param methodName the method name
159
	 * @param arguments the method arguments which must all be instance of Object
160
	 * @return the method return value
161
	 */
162
	public Object invoke(String methodName, Object[] arguments) {
163
		return invoke(methodName, getTypes(arguments), arguments);
164
	}
165
166
	/**
167
	 * Invokes the method with the given method name and arguments.
168
	 *
169
	 * @param methodName the method name
170
	 * @param types the argument types
171
	 * @param arguments the method arguments
172
	 * @return the method return value
173
	 */
174
	public Object invoke(String methodName, Class[] types, Object[] arguments) {
175
		Method method= null;
176
		try {
177
			method= fClass.getDeclaredMethod(methodName, types);
178
		} catch (SecurityException e) {
179
			fail();
180
		} catch (NoSuchMethodException ex) {
181
			fail();
182
		}
183
		Assert.isNotNull(method);
184
		method.setAccessible(true);
185
		try {
186
			return method.invoke(fInstance, arguments);
187
		} catch (IllegalArgumentException e) {
188
			fail();
189
		} catch (InvocationTargetException e) {
190
			fail();
191
		} catch (IllegalAccessException e) {
192
			fail();
193
		}
194
		return null;
195
	}
196
197
	/**
198
	 * Assigns the given value to the field with the given name.
199
	 *
200
	 * @param fieldName the field name
201
	 * @param value the value to assign to the field
202
	 */
203
	public void set(String fieldName, Object value) {
204
		Field field= getField(fieldName);
205
		try {
206
			field.set(fInstance, value);
207
		} catch (IllegalArgumentException e) {
208
			fail();
209
		} catch (IllegalAccessException e) {
210
			fail();
211
		}
212
	}
213
214
	public void setFinal(String fieldName, boolean value) {
215
216
		Field field= getField(fieldName);
217
		Field modifiersField = getFieldModifiers();
218
		boolean isFinal = false;
219
		try {
220
			// ensure the field is not final so that it can be modified
221
			modifiersField.setAccessible(true);
222
			isFinal = (field.getModifiers() & Modifier.FINAL) == Modifier.FINAL;
223
			if(isFinal) {
224
				modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
225
			}
226
			field.setBoolean(fInstance, value);
227
		} catch (IllegalArgumentException e) {
228
			fail();
229
		} catch (IllegalAccessException e) {
230
			fail();
231
		} catch (SecurityException e) {
232
			fail();
233
		}
234
		finally {
235
			// re-apply the final modifier
236
			if(isFinal) {
237
				try {
238
					modifiersField.setInt(field, field.getModifiers() | Modifier.FINAL);
239
				} catch (IllegalArgumentException e) {
240
					fail();
241
				} catch (IllegalAccessException e) {
242
					fail();
243
				}
244
			}
245
		}
246
	}
247
	
248
	/**
249
	 * Assigns the given value to the field with the given name.
250
	 *
251
	 * @param fieldName the field name
252
	 * @param value the value to assign to the field
253
	 */
254
	public void set(String fieldName, boolean value) {
255
		Field field= getField(fieldName);
256
		try {
257
			field.setBoolean(fInstance, value);
258
		} catch (IllegalArgumentException e) {
259
			fail();
260
		} catch (IllegalAccessException e) {
261
			fail();
262
		}
263
	}
264
265
	/**
266
	 * Assigns the given value to the field with the given name.
267
	 *
268
	 * @param fieldName the field name
269
	 * @param value the value to assign to the field
270
	 */
271
	public void set(String fieldName, int value) {
272
		Field field= getField(fieldName);
273
		try {
274
			field.setInt(fInstance, value);
275
		} catch (IllegalArgumentException e) {
276
			fail();
277
		} catch (IllegalAccessException e) {
278
			fail();
279
		}
280
	}
281
282
	/**
283
	 * Returns the value of the field with the given name.
284
	 *
285
	 * @param fieldName the field name
286
	 * @return the value of the field
287
	 */
288
	public Object get(String fieldName) {
289
		Field field= getField(fieldName);
290
		try {
291
			return field.get(fInstance);
292
		} catch (IllegalArgumentException e) {
293
			fail();
294
		} catch (IllegalAccessException e) {
295
			fail();
296
		}
297
		// Unreachable code
298
		return null;
299
	}
300
301
	/**
302
	 * Returns the value of the field with the given name.
303
	 *
304
	 * @param fieldName the field name
305
	 * @return the value of the field
306
	 */
307
	public boolean getBoolean(String fieldName) {
308
		Field field= getField(fieldName);
309
		try {
310
			return field.getBoolean(fInstance);
311
		} catch (IllegalArgumentException e) {
312
			fail();
313
		} catch (IllegalAccessException e) {
314
			fail();
315
		}
316
		// Unreachable code
317
		return false;
318
	}
319
320
	/**
321
	 * Returns the value of the field with the given name.
322
	 *
323
	 * @param fieldName the field name
324
	 * @return the value of the field
325
	 */
326
	public int getInt(String fieldName) {
327
		Field field= getField(fieldName);
328
		try {
329
			return field.getInt(fInstance);
330
		} catch (IllegalArgumentException e) {
331
			fail();
332
		} catch (IllegalAccessException e) {
333
			fail();
334
		}
335
		// Unreachable code
336
		return 0;
337
	}
338
339
	private Field getFieldModifiers() {
340
		Field field= null;
341
		try {
342
			field= Field.class.getDeclaredField("modifiers");
343
		} catch (SecurityException e) {
344
			fail();
345
		} catch (NoSuchFieldException e) {
346
			fail();
347
		}
348
		return field;
349
	}
350
	
351
	private Field getField(String fieldName) {
352
		Field field= null;
353
		try {
354
			field= fClass.getDeclaredField(fieldName);
355
		} catch (SecurityException e) {
356
			fail();
357
		} catch (NoSuchFieldException e) {
358
			fail();
359
		}
360
		field.setAccessible(true);
361
		return field;
362
	}
363
	
364
	private static Class[] getTypes(Object[] objects) {
365
		if (objects == null)
366
			return null;
367
368
		int length= objects.length;
369
		Class[] classes= new Class[length];
370
		for (int i= 0; i < length; i++) {
371
			Assert.isNotNull(objects[i]);
372
			classes[i]= objects[i].getClass();
373
		}
374
		return classes;
375
	}
376
377
	private void fail() {
378
		Assert.isTrue(false);
379
	}
380
}
(-)a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaIndexTests.java (-3 / +67 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2012 IBM Corporation and others.
2
 * Copyright (c) 2012, 2013 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 28-38 Link Here
28
import org.eclipse.jdt.core.IJavaElement;
28
import org.eclipse.jdt.core.IJavaElement;
29
import org.eclipse.jdt.core.IJavaProject;
29
import org.eclipse.jdt.core.IJavaProject;
30
import org.eclipse.jdt.core.JavaCore;
30
import org.eclipse.jdt.core.JavaCore;
31
import org.eclipse.jdt.core.index.*;
31
import org.eclipse.jdt.core.index.JavaIndexer;
32
import org.eclipse.jdt.core.search.SearchEngine;
32
import org.eclipse.jdt.core.search.SearchEngine;
33
import org.eclipse.jdt.core.tests.util.Accessor;
33
import org.eclipse.jdt.core.tests.util.Util;
34
import org.eclipse.jdt.core.tests.util.Util;
34
import org.eclipse.jdt.internal.core.JavaModelManager;
35
import org.eclipse.jdt.internal.core.JavaModelManager;
35
import org.eclipse.jdt.internal.core.UserLibraryClasspathContainer;
36
import org.eclipse.jdt.internal.core.UserLibraryClasspathContainer;
37
import org.eclipse.jdt.internal.core.search.indexing.IndexManager;
36
import org.osgi.service.prefs.BackingStoreException;
38
import org.osgi.service.prefs.BackingStoreException;
37
39
38
public class JavaIndexTests extends AbstractJavaSearchTests  {
40
public class JavaIndexTests extends AbstractJavaSearchTests  {
Lines 863-866 Link Here
863
			deleteProject("ForIndex");
865
			deleteProject("ForIndex");
864
		}
866
		}
865
	}
867
	}
866
}
868
	public void testManagingPreBuildIndexFile() throws CoreException, IOException {
869
870
		// create the pre-built index
871
		File indexFile = null;
872
		String jarFilePath = getExternalResourcePath("Test.jar");
873
		File jarFile = new File(jarFilePath);
874
		IJavaProject p = null;
875
		try {
876
			createJar(new String[] {
877
					"pkg/Test.java",
878
					"package pkg;\n" +
879
					"public class Test {\n" +
880
					"  protected Test(int i) {}\n" +
881
					"  protected void helloWorld() {}\n" +
882
					"}"}, jarFilePath);
883
			indexFile = new File(getExternalResourcePath("Test.index"));
884
			JavaIndexer.generateIndexForJar(jarFilePath, indexFile.getAbsolutePath());
885
			// create project P and add the Test.jar to the classpath (associate the index to it)
886
			p = createJavaProject("P");
887
			Path libPath = new Path(jarFilePath);
888
			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.INDEX_LOCATION_ATTRIBUTE_NAME, indexFile.toURI().toURL().toString());
889
			IClasspathEntry entry = JavaCore.newLibraryEntry(libPath, null, null, null, new IClasspathAttribute[]{attribute}, false);
890
			this.setClasspath(p, new IClasspathEntry[] {entry});
891
			AbstractJavaModelTests.waitUntilIndexesReady();
892
			// verify the current index is correct
893
			this.resultCollector = new JavaSearchResultCollector();
894
			this.search("helloWorld", METHOD, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
895
			this.assertSearchResults(getExternalPath() + "Test.jar void pkg.Test.helloWorld()");
896
			// restart the product so the index manager enables management of pre-build indexes
897
			Accessor accessor = new Accessor(JavaModelManager.getIndexManager(), IndexManager.class);
898
			accessor.setFinal("IS_MANAGING_PRODUCT_INDEXES_PROPERTY", Boolean.TRUE.booleanValue());
899
			// update the class file (when the product is not running) by changing
900
			// the method signature (simulate the contents of a JAR file changing)
901
			createJar(new String[] {
902
					"pkg/Test.java",
903
					"package pkg;\n" +
904
					"public class Test {\n" +
905
					"  protected Test(int i) {}\n" +
906
					"  protected void helloWorld(int i) {}\n" +
907
					"}"}, jarFilePath);
908
			// refresh external archives - this will cause the Test.index to be re-built based on the new content
909
			JavaModelManager.getJavaModelManager().getJavaModel().refreshExternalArchives(new IJavaElement[] { p }, null);
910
			AbstractJavaModelTests.waitUntilIndexesReady();
911
			// verify that the index is updated
912
			this.resultCollector = new JavaSearchResultCollector();
913
			this.search("helloWorld", METHOD, DECLARATIONS, EXACT_RULE, SearchEngine.createJavaSearchScope(new IJavaElement[]{p}));
914
			this.assertSearchResults(getExternalPath() + "Test.jar void pkg.Test.helloWorld(int)");
915
		}
916
		finally {
917
			// restart the product so the index manager disables management of pre-build indexes
918
			Accessor accessor = new Accessor(JavaModelManager.getIndexManager(), IndexManager.class);
919
			accessor.setFinal("IS_MANAGING_PRODUCT_INDEXES_PROPERTY", Boolean.FALSE.booleanValue());
920
			// clean-up artifacts that were created
921
			if(p != null) {
922
				deleteProject("P");
923
			}
924
			if (indexFile != null) {
925
				indexFile.delete();
926
			}
927
			jarFile.delete();
928
		}
929
	}
930
}

Return to bug 395897