*/
SpecificationReference specification = parseSpecificationReference(name, element, ATT_SPECIFICATION, false);
String versionRange = parseString(name, element, ATT_REQUIRE_VERSION, false);
VersionedReference<SpecificationDeclaration> specificationVersion = specification != null ? VersionedReference.range(specification,versionRange) : null;
AtomicImplementationDeclaration declaration = new AtomicImplementationDeclaration(name, specificationVersion, instrumentedClass);
parseComponent(element, declaration);
/*
* Parse message producer method interception
*/
String messageMethods = parseString(name, element, ATT_PUSH, false);
for (String messageMethod : list(messageMethods,true)) {
/*
* Parse optionally specified method signature
*/
String methodName = messageMethod.trim();
String methodSignature = null;
if (methodName.indexOf("(") != -1 && methodName.endsWith(")")) {
methodSignature = methodName.substring(methodName.indexOf("(") + 1, methodName.length() - 1);
methodName = methodName.substring(0, methodName.indexOf("("));
}
ProviderInstrumentation instrumentation = new ProviderInstrumentation.MessageProviderMethodInterception(declaration, methodName, methodSignature);
if (!instrumentation.isValidInstrumentation()) {
errorHandler.report(Severity.ERROR, name + " : the specified method \"" + instrumentation.getName() + "\" in \"" + ATT_PUSH + "\" is invalid or not found");
}
declaration.getProviderInstrumentation().add(instrumentation);
}
/*
* Verify that at least one method is intercepted for each declared produced message.
*/
for (MessageReference message : declaration.getProvidedResources(MessageReference.class)) {
boolean declared = declaration.getProviderInstrumentation().size() > 0;
boolean injected = false;
boolean defined = false;
for (ProviderInstrumentation providerInstrumentation : declaration.getProviderInstrumentation()) {
ResourceReference instrumentedResource = providerInstrumentation.getProvidedResource();
if (instrumentedResource instanceof UnknownReference) {
continue;
}
defined = true;
if (!instrumentedResource.equals(message)) {
continue;
}
injected = true;
break;
}
/*
* If we could determine the method types and there was no injection then signal error
*
* NOTE Notice that some errors will not be detected at build time since all the reflection information
* is not available, and validation must be delayed until run time
*/
if (!declared || (defined && !injected)) {
errorHandler.report(Severity.ERROR, "Apam component " + name + ": " + " message of type " + message.getJavaType() + " is not produced by any push method");
}
}
/*
* if not explicitly provided, get all the implemented interfaces.
*/
if (declaration.getProvidedResources(InterfaceReference.class).isEmpty() && (pojoMetadata != null)) {
for (String implementedInterface : pojoMetadata.getInterfaces()) {
declaration.getProvidedResources().add(new InterfaceReference(implementedInterface));
}
}
/*
* If not explicitly provided, get all produced messages from the declared intercepted methods
*/
if (declaration.getProvidedResources(MessageReference.class).isEmpty()) {
for (ProviderInstrumentation providerInstrumentation : declaration.getProviderInstrumentation()) {
MessageReference instrumentedMessage = providerInstrumentation.getProvidedResource().as(MessageReference.class);
if (instrumentedMessage != null) {
declaration.getProvidedResources().add(instrumentedMessage);
}
}
}
/*
* If instrumented code is provided verify that all provided resources reference accessible classes
*/
if (introspector != null) {
for (ResourceReference providedResource : declaration.getProvidedResources()) {
if (providedResource instanceof UnknownReference || providedResource instanceof PackageReference) {
continue;
}
// TODO : check the provided package (one class belonging to this package should exists)
try {
introspector.getInstrumentedClass(providedResource.getJavaType());
} catch (ClassNotFoundException e) {
errorHandler.report(Severity.ERROR, "Apam component " + name + ": " + "the provided resource " + providedResource.getJavaType() + " can not be loaded");
}
}
}
/*
* Iterate over all sub elements looking for callback declarations
*/
for (Element callback : optional(element.getElements(CALLBACK, APAM))) {
String onInit = parseString(name, callback, ATT_ON_INIT, false);
String onRemove = parseString(name, callback, ATT_ON_REMOVE, false);
if (onInit != null) {
declaration.addCallback(AtomicImplementationDeclaration.Event.INIT, parseCallback(declaration, onInit));
}
if (onRemove != null) {
declaration.addCallback(AtomicImplementationDeclaration.Event.REMOVE, parseCallback(declaration, onRemove));
}
}
return declaration;