/******************************************************************************* * Copyright (c) 2009-2014 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.cdi.internal.core.validation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import org.jboss.tools.cdi.core.CDICorePlugin; import org.jboss.tools.cdi.core.CDIVersion; /** * This class collects CDI validation messages for all available versions, * provided by contributor classes CDIValidationMessagesXX that are * usually initialized with NLS. * * For each validation message included in at least one contributor class, * there is a field with the same name in this class. * * Currently all field values in this class obey the rule as follows: * - Each value is an array with length equal to CDIVersion.versions().length, * that has to be accessed with version.getIndex() for element * corresponding to given CDIVersion version; * - Each element (say i-th element) in the array is either null * or equals to the value of the field with the same name from * contribution CDIValidationMessagesXX corresponding to version with * index j such that j <= i and j is maximal among indexes j' <= i of * contributions declaring such field. * * This rule is checked by org.jboss.tools.cdi.core.test.CDIValidationMessagesTest * * For consistency it is strongly advisable to keep to this rule in future. * For example: * - if a new version is added, increase length of each array by 1, * and either set value to null when rule is irrelevant, or set it to * previous contribution when message fits well, or otherwise declare * new message in the contribution for the new version. * - if a new validation rule is added in the next version, * new array constant for it will start with null values for all previous * versions. * * Method init() implements this rule. To support it during development * - All contributions CDIValidationMessagesXX should be included * to class array 'versionMessages' in the beginning of init(). * - Declarations of fields for validation rules relevant in a range of versions * should be assigned to template by invoking createTemplate(sinceIndex, untilIndex). * * - For messages that by some (strongly discouraged) reason do not fit into these rules, * values are to be assigned explicitly in the end of init(). * * @author Alexey Kazakov and Viacheslav Kabanovich */ public class CDIValidationMessages { public static String[] STEREOTYPE_DECLARES_NON_EMPTY_NAME; public static String[] RESOURCE_PRODUCER_FIELD_SETS_EL_NAME; public static String[] PARAM_INJECTION_DECLARES_EMPTY_NAME; public static String[] INTERCEPTOR_HAS_NAME; public static String[] DECORATOR_HAS_NAME; public static String[] UNSATISFIED_INJECTION_POINTS; public static String[] AMBIGUOUS_INJECTION_POINTS; public static String[] UNPROXYABLE_BEAN_ARRAY_TYPE; public static String[] UNPROXYABLE_BEAN_PRIMITIVE_TYPE; public static String[] UNPROXYABLE_BEAN_TYPE_WITH_NPC; public static String[] UNPROXYABLE_BEAN_FINAL_TYPE; public static String[] UNPROXYABLE_BEAN_TYPE_WITH_FM; public static String[] UNPROXYABLE_BEAN_ARRAY_TYPE_2; public static String[] UNPROXYABLE_BEAN_PRIMITIVE_TYPE_2; public static String[] UNPROXYABLE_BEAN_TYPE_WITH_NPC_2; public static String[] UNPROXYABLE_BEAN_FINAL_TYPE_2; public static String[] UNPROXYABLE_BEAN_TYPE_WITH_FM_2; public static String[] DECORATOR_RESOLVES_TO_FINAL_CLASS; public static String[] DECORATOR_RESOLVES_TO_FINAL_METHOD; public static String[] DUPLCICATE_EL_NAME; public static String[] UNRESOLVABLE_EL_NAME; public static String[] ILLEGAL_TYPE_IN_TYPED_DECLARATION; public static String[] PRODUCER_METHOD_RETURN_TYPE_HAS_WILDCARD; public static String[] PRODUCER_METHOD_RETURN_TYPE_IS_VARIABLE; public static String[] PRODUCER_FIELD_TYPE_HAS_WILDCARD; public static String[] PRODUCER_FIELD_TYPE_IS_VARIABLE; public static String[] PRODUCER_FIELD_TYPE_DOES_NOT_MATCH_JAVA_EE_OBJECT; public static String[] INJECT_RESOLVES_TO_NULLABLE_BEAN; public static String[] INJECTION_TYPE_IS_VARIABLE; public static String[] STEREOTYPE_IS_ANNOTATED_TYPED; public static String[] MISSING_NONBINDING_FOR_ANNOTATION_VALUE_IN_QUALIFIER_TYPE_MEMBER; public static String[] MISSING_NONBINDING_FOR_ARRAY_VALUE_IN_QUALIFIER_TYPE_MEMBER; public static String[] MISSING_NONBINDING_FOR_ANNOTATION_VALUE_IN_INTERCEPTOR_BINDING_TYPE_MEMBER; public static String[] MISSING_NONBINDING_FOR_ARRAY_VALUE_IN_INTERCEPTOR_BINDING_TYPE_MEMBER; public static String[] MISSING_TARGET_ANNOTATION_IN_QUALIFIER_TYPE = createTemplate(0, 0); public static String[] MISSING_RETENTION_ANNOTATION_IN_QUALIFIER_TYPE; public static String[] MISSING_TARGET_ANNOTATION_IN_STEREOTYPE_TYPE = createTemplate(0, 0); public static String[] MISSING_RETENTION_ANNOTATION_IN_STEREOTYPE_TYPE; public static String[] MISSING_TARGET_ANNOTATION_IN_SCOPE_TYPE = createTemplate(0, 0); public static String[] MISSING_RETENTION_ANNOTATION_IN_SCOPE_TYPE; public static String[] ILLEGAL_TARGET_IN_STEREOTYPE_TYPE_TMF; public static String[] ILLEGAL_TARGET_IN_STEREOTYPE_TYPE_M; public static String[] ILLEGAL_TARGET_IN_STEREOTYPE_TYPE_F; public static String[] ILLEGAL_TARGET_IN_STEREOTYPE_TYPE_MF; public static String[] ILLEGAL_TARGET_IN_INTERCEPTOR_BINDING_TYPE; public static String[] ILLEGAL_TARGET_IN_INTERCEPTOR_BINDING_TYPE_FOR_STEREOTYPE; public static String[] NOT_PASSIVATION_CAPABLE_BEAN; public static String[] MULTIPLE_SCOPE_TYPE_ANNOTATIONS; public static String[] MULTIPLE_SCOPE_TYPE_ANNOTATIONS_IN_BEAN_CLASS; public static String[] MULTIPLE_SCOPE_TYPE_ANNOTATIONS_IN_PRODUCER_METHOD; public static String[] MULTIPLE_SCOPE_TYPE_ANNOTATIONS_IN_PRODUCER_FIELD; public static String[] MISSING_SCOPE_WHEN_THERE_IS_NO_DEFAULT_SCOPE; public static String[] STEREOTYPE_DECLARES_MORE_THAN_ONE_SCOPE; public static String[] ILLEGAL_SCOPE_FOR_MANAGED_BEAN_WITH_PUBLIC_FIELD; public static String[] ILLEGAL_SCOPE_FOR_MANAGED_BEAN_WITH_GENERIC_TYPE; public static String[] ILLEGAL_SCOPE_FOR_SESSION_BEAN_WITH_GENERIC_TYPE; public static String[] ILLEGAL_SCOPE_FOR_STATELESS_SESSION_BEAN; public static String[] ILLEGAL_SCOPE_FOR_SINGLETON_SESSION_BEAN; public static String[] ILLEGAL_SCOPE_FOR_PRODUCER_METHOD; public static String[] ILLEGAL_SCOPE_FOR_PRODUCER_FIELD; public static String[] ILLEGAL_SCOPE_WHEN_TYPE_INJECTIONPOINT_IS_INJECTED; public static String[] ILLEGAL_SCOPE_FOR_INTERCEPTOR; public static String[] ILLEGAL_SCOPE_FOR_DECORATOR; public static String[] PRODUCER_ANNOTATED_INJECT; public static String[] PRODUCER_PARAMETER_ILLEGALLY_ANNOTATED_DISPOSES; public static String[] PRODUCER_PARAMETER_ILLEGALLY_ANNOTATED_OBSERVES; public static String[] OBSERVER_ANNOTATED_INJECT; public static String[] OBSERVER_PARAMETER_ILLEGALLY_ANNOTATED; public static String[] ILLEGAL_PRODUCER_METHOD_IN_SESSION_BEAN; public static String[] MULTIPLE_DISPOSING_PARAMETERS; public static String[] DISPOSER_ANNOTATED_INJECT; public static String[] ILLEGAL_DISPOSER_IN_SESSION_BEAN; public static String[] NO_PRODUCER_MATCHING_DISPOSER; public static String[] MULTIPLE_DISPOSERS_FOR_PRODUCER; public static String[] ILLEGAL_PRODUCER_FIELD_IN_SESSION_BEAN; public static String[] MULTIPLE_INJECTION_CONSTRUCTORS; public static String[] CONSTRUCTOR_PARAMETER_ANNOTATED_OBSERVES; public static String[] CONSTRUCTOR_PARAMETER_ANNOTATED_DISPOSES; public static String[] GENERIC_METHOD_ANNOTATED_INJECT; public static String[] STATIC_METHOD_ANNOTATED_INJECT; public static String[] MULTIPLE_OBSERVING_PARAMETERS; public static String[] ILLEGAL_OBSERVER_IN_SESSION_BEAN; public static String[] ILLEGAL_CONDITIONAL_OBSERVER; public static String[] BOTH_INTERCEPTOR_AND_DECORATOR; public static String[] SESSION_BEAN_ANNOTATED_INTERCEPTOR; public static String[] SESSION_BEAN_ANNOTATED_DECORATOR; public static String[] PRODUCER_IN_INTERCEPTOR; public static String[] PRODUCER_IN_DECORATOR; public static String[] DISPOSER_IN_INTERCEPTOR; public static String[] DISPOSER_IN_DECORATOR; public static String[] MULTIPLE_DELEGATE; public static String[] MISSING_DELEGATE; public static String[] ILLEGAL_INJECTION_POINT_DELEGATE; public static String[] ILLEGAL_BEAN_DECLARING_DELEGATE; public static String[] DELEGATE_HAS_ILLEGAL_TYPE; public static String[] ILLEGAL_LIFECYCLE_CALLBACK_INTERCEPTOR_BINDING; public static String[] ILLEGAL_INTERCEPTOR_BINDING_CLASS; public static String[] ILLEGAL_INTERCEPTOR_BINDING_METHOD; public static String[] CONFLICTING_INTERCEPTOR_BINDINGS; public static String[] OBSERVER_IN_INTERCEPTOR; public static String[] OBSERVER_IN_DECORATOR; public static String[] INTERCEPTOR_IS_ALTERNATIVE; public static String[] DECORATOR_IS_ALTERNATIVE; public static String[] MISSING_INTERCEPTOR_BINDING; public static String[] ILLEGAL_SPECIALIZING_MANAGED_BEAN; public static String[] ILLEGAL_SPECIALIZING_SESSION_BEAN; public static String[] ILLEGAL_SPECIALIZING_PRODUCER_STATIC; public static String[] ILLEGAL_SPECIALIZING_PRODUCER_OVERRIDE; public static String[] MISSING_TYPE_IN_SPECIALIZING_BEAN; public static String[] CONFLICTING_NAME_IN_SPECIALIZING_BEAN; public static String[] INTERCEPTOR_ANNOTATED_SPECIALIZES; public static String[] DECORATOR_ANNOTATED_SPECIALIZES; public static String[] INCONSISTENT_SPECIALIZATION; public static String[] ILLEGAL_INJECTING_USERTRANSACTION_TYPE; public static String[] ILLEGAL_INJECTING_INJECTIONPOINT_TYPE; public static String[] ILLEGAL_QUALIFIER_IN_STEREOTYPE; public static String[] EMPTY_ALTERNATIVE_BEAN_CLASS_NAME; public static String[] UNKNOWN_ALTERNATIVE_BEAN_CLASS_NAME; public static String[] ILLEGAL_ALTERNATIVE_BEAN_CLASS; public static String[] EMPTY_ALTERNATIVE_ANNOTATION_NAME; public static String[] UNKNOWN_ALTERNATIVE_ANNOTATION_NAME; public static String[] ILLEGAL_ALTERNATIVE_ANNOTATION; public static String[] DUPLICATE_ALTERNATIVE_TYPE; public static String[] EMPTY_DECORATOR_BEAN_CLASS_NAME; public static String[] UNKNOWN_DECORATOR_BEAN_CLASS_NAME; public static String[] ILLEGAL_DECORATOR_BEAN_CLASS; public static String[] DUPLICATE_DECORATOR_CLASS; public static String[] EMPTY_INTERCEPTOR_CLASS_NAME; public static String[] UNKNOWN_INTERCEPTOR_CLASS_NAME; public static String[] ILLEGAL_INTERCEPTOR_CLASS; public static String[] DUPLICATE_INTERCEPTOR_CLASS; public static String[] MISSING_BEANS_XML = createTemplate(0, 0); static { try { init(); } catch (NoSuchFieldException e) { CDICorePlugin.getDefault().logError(e); } catch (IllegalAccessException e) { CDICorePlugin.getDefault().logError(e); } } /** * null values in template stand for null values in the final result built in init(). * non-nulls in template stand for values to be initialized in init() by default rules. * * @param sinceIndex minimal version index for which validation rule is relevant * @param untilIndex maximum version index for which validation rule is relevant * @return */ static String[] createTemplate(int sinceIndex, int untilIndex) { String[] result = new String[CDIVersion.getVersionCount()]; for (int i = sinceIndex; i <= untilIndex; i++) { result[i] = ""; } return result; } static void init() throws NoSuchFieldException, IllegalAccessException { Class<?>[] versionMessages = { CDIValidationMessages10.class, CDIValidationMessages11.class, CDIValidationMessages12.class }; for (Field f: CDIValidationMessages.class.getFields()) { if(!Modifier.isStatic(f.getModifiers())) { continue; } String name = f.getName(); f.setAccessible(true); String[] template = (String[])f.get(null); String[] values = new String[CDIVersion.getVersionCount()]; f.set(null, values); String[] contributions = new String[values.length]; for (int i = 0; i < values.length; i++) { try { Field fi = versionMessages[i].getField(name); fi.setAccessible(true); contributions[i] = (String)fi.get(null); } catch (NoSuchFieldException e) { //field may be missing, it is not an error. } } for (int i = 0; i < values.length; i++) { if(template != null && template[i] == null) { continue; } for (int j = i; values[i] == null && j >= 0; j--) { if(contributions[j] != null) { values[i] = contributions[j]; } } } } } }