Skip to main content
summaryrefslogtreecommitdiffstats
blob: 7a82502f70ed1ce347143a695064867b2904ac76 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
/*******************************************************************************
 * Copyright (c) 2001, 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.j2ee.model.internal.validation;


import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;

import org.eclipse.jem.java.Field;
import org.eclipse.jem.java.JavaClass;
import org.eclipse.jem.java.JavaParameter;
import org.eclipse.jem.java.Method;
import org.eclipse.jem.util.logger.LogEntry;
import org.eclipse.jem.util.logger.proxy.Logger;
import org.eclipse.jst.j2ee.ejb.EnterpriseBean;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;

/**
 * Insert the type's description here.
 * Creation date: (1/5/01 11:51:09 AM)
 * @author: Administrator
 */
public abstract class AValidateEJB extends AValidationRule {
	private List roleMethodNames;
	
	@Override
	public void reset() {
		super.reset();
		if(roleMethodNames != null) {
			roleMethodNames.clear();
			roleMethodNames = null; // in this case, clearing the list isn't enough, because it is legal to have zero role names. Must be null or we'll keep trying to reload the role names just because there are zero role names.
		}
	}
	
	/**
	 * Insert the method's description here.
	 * Creation date: (9/5/2001 12:36:39 PM)
	 * @return java.util.List
	 */
	protected List getRoleMethodNames(IEJBValidationContext vc, EnterpriseBean bean) {
		try {
			if (roleMethodNames == null && bean != null) {
				roleMethodNames = getRoleMethodNamesExtended(bean);
			}
			return roleMethodNames;
		}
		catch (Throwable exc) {
			Logger logger = vc.getMsgLogger();
			if (logger != null && logger.isLoggingLevel(Level.FINER)) {
				logger.write(Level.FINER, exc);
			}
			return Collections.EMPTY_LIST;
		}
	}
	
	protected boolean isEjbRelationshipRoleMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) {
		if (method == null)
			return false;
		List aRoleMethodNames = getRoleMethodNames(vc, bean);
		if(aRoleMethodNames != null && !aRoleMethodNames.isEmpty())
		  return aRoleMethodNames.contains(method.getName());
		return false;
	}
	
	/**
	 * Return true if the field can, and should, be validated.
	 * Filter out faulty fields (i.e., null), and fields which
	 * belong to the base type, whatever that is. (e.g. java.lang.Object)
	 */
	protected boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldsExtendedLists) throws InvalidInputException {
		// The following call checks if the type reflected properly
		ValidationRuleUtility.isValidType(ValidationRuleUtility.getType(field));

		if (field.getName().equals(IMethodAndFieldConstants.FIELDNAME_SERIALVERSIONUID)) {
			return false;
		}

		return true;
	}
	
	/**
	 * Return true if the method can, and should, be validated.
	 * Filter out faulty methods (i.e., null), and methods which
	 * belong to the base type, whatever that is. (e.g. java.lang.Object)
	 */
	protected boolean isValid(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, List[] methodsExtendedList) throws InvalidInputException {
		if (method == null) {
			throw new InvalidInputException();
		}
		return true;
	}

	/**
	 * This method actually does the validation. Since many of the classes do
	 * not validate fields now, implement this method as a no-op so that the
	 * classes compile. 
	 */
	public void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field) throws InvalidInputException {
		//Default
	}
	
	/**
	 * This method actually does the validation.
	 */
	public abstract void primValidate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException;
	
	/**
	 * This method does the actual checking (if ejbMethod exists).
	 */
	protected abstract void primValidateExistence(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod) throws InvalidInputException;
	
	protected abstract List[] getMethodsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz);
	protected abstract List[] getFieldsExtended(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz);
	
	protected final void reflectionError(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz)  {
		vc.removeMessages(clazz);
	
		IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2907, IEJBValidationContext.ERROR, bean, clazz, new String[]{clazz.getQualifiedName()}, this);
		vc.addMessage(message);
	}
	
	protected final void reflectionWarning(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, InvalidInputException e) {
		// One of two cases where we care if the type is on this class or not (i.e., not leaving it up to MessageUtility)
		String[] msgParm = null;
		String javaClassName = (e.getJavaClass() == null) ? "?" : e.getJavaClass().getQualifiedName(); //$NON-NLS-1$
		if(ValidationRuleUtility.onClass(clazz, field)) {
			msgParm = new String[] {String.valueOf(field.getName()), String.valueOf(javaClassName)};
		}
		else {
			msgParm = new String[] {javaClassName}; // MessageUtility will substitute in the name of the field
		}
		IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2433, IEJBValidationContext.WARNING, bean, clazz, field, msgParm, this);
		vc.addMessage(message);
	}
	
	protected final void reflectionWarning(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method, InvalidInputException e) {
		// One of two cases where we care if the type is on this class or not (i.e., not leaving it up to MessageUtility)
		String[] msgParm = null;
		String javaClassName = (e.getJavaClass() == null) ? "?" : e.getJavaClass().getQualifiedName(); //$NON-NLS-1$
		if(ValidationRuleUtility.onClass(clazz, method)) {
			msgParm = new String[] {method.getMethodElementSignature(), javaClassName};
		}
		else {
			msgParm = new String[] {javaClassName}; // MessageUtility will substitute in the name of the field
		}
		IMessage message = MessageUtility.getUtility().getMessage(vc, IEJBValidatorMessageConstants.CHKJ2433, IEJBValidationContext.WARNING, bean, clazz, method, msgParm, this);
		vc.addMessage(message);
	}
	
	public final void validate(IEJBValidationContext vc, Object targetParent, Object target) throws ValidationException {
		vc.terminateIfCancelled();
		
		EnterpriseBean bean = (EnterpriseBean)targetParent;
		JavaClass clazz = (JavaClass)target;
		
		try {
			// check if all of the types in the bean reflected properly
			ValidationRuleUtility.isValidTypeHierarchy(bean, clazz);
			
			vc.subtask(IEJBValidatorConstants.STATUS_VALIDATING, new String[]{clazz.getQualifiedName()});
			validateClass(vc, bean, clazz);
			validateMethods(vc, bean, clazz);
			validateFields(vc, bean, clazz);
		}
		catch(InvalidInputException e) {
			reflectionError(vc, bean, clazz);
			return;
		}
		catch(ValidationCancelledException e) {
			throw e;
		}
	}

	/**
	 * This method should be called to avoid validating a Field more
	 * than once.  This is not used for checking the existence of a field.
	 */
	public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Field field, List[] fieldsExtendedList) throws InvalidInputException {
		if (isValid(vc, bean, clazz, field, fieldsExtendedList)) {
			primValidate(vc, bean, clazz, field);
		}
	}
	
	/**
	 * This method should be called to avoid validating a Method more
	 * than once.  This is not used for checking the existence of a method.
	 */
	public final void validate(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod, List[] methodsExtendedList) throws InvalidInputException {
		if (isValid(vc, bean, clazz, ejbMethod, methodsExtendedList)) {
			primValidate(vc, bean, clazz, ejbMethod);
		}
	}
	/**
	 * Checks to see if @ejbMethod is one of the required methods.
	 */
	protected final void validateExistence(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method ejbMethod, List[] methodsExtendedList) throws InvalidInputException {
		if (isValid(vc, bean, clazz, ejbMethod, methodsExtendedList)) {
			primValidateExistence(vc, bean, clazz, ejbMethod);
		}
	}
	
	public void validateClass(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException {
		//Default
	}
	
	public final void validateFields(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz)  throws ValidationCancelledException, InvalidInputException, ValidationException {
		vc.terminateIfCancelled();

		// Whenever looping over an entire list, always use an 
		// iterator instead of a for loop, for performance reasons. 
		// If the list is an instance of a linked list, for example,
		// the get(i) call can take  a long time. 
		List fields = clazz.getFieldsExtended();
		Iterator iterator = fields.iterator();
		Field field = null;
		List[] fieldsExtendedList = getFieldsExtended(vc, bean, clazz);
		while (iterator.hasNext()) {
			vc.terminateIfCancelled();
			field = (Field) iterator.next();
			if (field == null) {
				Logger logger = vc.getMsgLogger();
				if (logger != null && logger.isLoggingLevel(Level.FINEST)) {
					LogEntry entry = vc.getLogEntry();
					entry.setSourceID("AValidateEJB.validateFields()"); //$NON-NLS-1$
					entry.setText("A field is null on " + clazz); //$NON-NLS-1$
					logger.write(Level.FINEST, entry);
				}
				continue;
			}
			try {
				validate(vc, bean, clazz, field, fieldsExtendedList);
			}
			catch (InvalidInputException e) {
				reflectionWarning(vc, bean, clazz, field, e);
			}
		}
		vc.terminateIfCancelled();
	}
	
	/**
	 * Verifies that a given method is RMI legal.
	 * This means that their argument and return values must be of valid types 
	 * for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
	 */
	public final void validateLegalRMIMethod(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();
		validateLegalRMIMethodWithoutExceptions(vc, bean, clazz, method);
		validateLegalRMIMethodExceptions(vc, bean, clazz, method);
	}
	
	/**
	 * Verifies that a given method is RMI legal.
	 * This means that their argument and return values must be of valid types 
	 * for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
	 */
	public final void validateLegalRMIMethodArguments(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();

		if (method == null) {
			return;
		}

		JavaParameter[] args = method.listParametersWithoutReturn();
		for (int i = 0; i < args.length; i++) {
			vc.terminateIfCancelled();

			if (!ValidationRuleUtility.isLegalRMI_IIOPType(bean, args[i].getJavaType())) {
				IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2413, IEJBValidationContext.INFO, bean, clazz, method, new String[]{args[i].getQualifiedName()}, this);
				vc.addMessage(message);
			}
		}
	}
	
	/**
	 * Verifies that a given method is RMI legal.
	 * This means that their argument and return values must be of valid types 
	 * for RMI/IIOP, and their throws clause must include the java.rmi.RemoteException.
	 */
	public final void validateLegalRMIMethodExceptions(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();

		if (method == null) {
			return;
		}

		if (!ValidationRuleUtility.throwsRemoteExceptionOrParent(bean, method)) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2414, IEJBValidationContext.ERROR, bean, clazz, method, new String[]{ITypeConstants.CLASSNAME_JAVA_RMI_REMOTEEXCEPTION}, this);
			vc.addMessage(message);
		}
	}
	
	/**
	 * Verifies that a given method is RMI legal, but doesn't check the exceptions.
	 * This means that the method's argument and return values must be of valid types 
	 * for RMI/IIOP.
	 */
	public final void validateLegalRMIMethodReturnType(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();
		if (method == null) {
			return;
		}

		if (!ValidationRuleUtility.isLegalRMI_IIOPType(bean, method.getReturnType())) {
			IMessage message = MessageUtility.getUtility().getMessage(vc, IMessagePrefixEjb11Constants.CHKJ2412, IEJBValidationContext.INFO, bean, clazz, method, this);
			vc.addMessage(message);
		}
	}
	
	/**
	 * Verifies that a given method is RMI legal, but doesn't check the exceptions.
	 * This means that the method's argument and return values must be of valid types 
	 * for RMI/IIOP.
	 */
	public final void validateLegalRMIMethodWithoutExceptions(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz, Method method) throws InvalidInputException {
		vc.terminateIfCancelled();
		validateLegalRMIMethodArguments(vc, bean, clazz, method);
		validateLegalRMIMethodReturnType(vc, bean, clazz, method);
	}
	
	/**
	 * Final check to see if required methods were detected.
	 */
	protected abstract void validateMethodExists(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz) throws InvalidInputException;
	
	public final void validateMethods(IEJBValidationContext vc, EnterpriseBean bean, JavaClass clazz)  throws ValidationCancelledException, InvalidInputException, ValidationException {
		vc.terminateIfCancelled();

		// Whenever looping over an entire list, always use an 
		// iterator instead of a for loop, for performance reasons. 
		// If the list is an instance of a linked list, for example,
		// the get(i) call can take  a long time. 
		Method[] ejbMethods = clazz.listMethodExtended();
		Method method = null;
		List[] methodsExtendedList = getMethodsExtended(vc, bean, clazz);
		for(int i=0; i<ejbMethods.length; i++) {
			vc.terminateIfCancelled();
			method = ejbMethods[i];
			if (method == null) {
				// No point adding a validation message, because the user can't do anything.
				// Log this condition.
				Logger logger = vc.getMsgLogger();
				if (logger != null && logger.isLoggingLevel(Level.FINEST)) {
					LogEntry entry = vc.getLogEntry();
					entry.setSourceID("AValidateEJB.validateMethods()"); //$NON-NLS-1$
					entry.setText("On " + clazz + ", there is a null method."); //$NON-NLS-1$  //$NON-NLS-2$
					logger.write(Level.FINEST, entry);
				}
				continue;
			}
			try {
				validateExistence(vc, bean, clazz, method, methodsExtendedList);
				validate(vc, bean, clazz, method, methodsExtendedList);
			}
			catch (InvalidInputException e) {
				reflectionWarning(vc, bean, clazz, method, e);
			}
		}
		validateMethodExists(vc, bean, clazz);
		vc.terminateIfCancelled();
	}
}

Back to the top