String field = dep.getField();
DependencyCallback[] callbacks = dep.getCallbacks();
int index = dep.getConstructorParameterIndex();
if (callbacks == null && field == null && index == -1) {
throw new ConfigurationException("A service requirement requires at least binding methods, " +
"a field or a constructor parameter");
}
for (int i = 0; callbacks != null && i < callbacks.length; i++) {
MethodMetadata[] mets = manipulation.getMethods(callbacks[i].getMethodName());
if (mets.length == 0) {
debug("A requirement callback " + callbacks[i].getMethodName() + " does not exist in the implementation class, will try the super classes");
} else {
if (mets[0].getMethodArguments().length > 2) {
throw new ConfigurationException("Requirement Callback : A requirement callback "
+ callbacks[i].getMethodName()
+ " must have 0, 1 or 2 arguments");
}
callbacks[i].setArgument(mets[0].getMethodArguments());
if (mets[0].getMethodArguments().length == 1) {
if (!mets[0].getMethodArguments()[0].equals(ServiceReference.class.getName())) {
// The callback receives the service object.
setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
}
} else if (mets[0].getMethodArguments().length == 2) {
// The callback receives service object, service reference. Check that the second argument is a service reference
if (!(mets[0].getMethodArguments()[1].equals(ServiceReference.class.getName()) // callback with (service object, service reference)
|| mets[0].getMethodArguments()[1].equals(Dictionary.class.getName()) // callback with (service object, service properties in a dictionary)
|| mets[0].getMethodArguments()[1].equals(Map.class.getName()))) { // callback with (service object, service properties in a map)
String message =
"The requirement callback " + callbacks[i].getMethodName() + " must have a ServiceReference, a Dictionary or a Map as the second argument";
throw new ConfigurationException(message);
}
setSpecification(dep, mets[0].getMethodArguments()[0], false); // Just warn if a mismatch is discovered.
}
}
}
if (field != null) {
FieldMetadata meta = manipulation.getField(field);
if (meta == null) {
throw new ConfigurationException("Requirement Callback : A requirement field "
+ field
+ " does not exist in the implementation class");
}
String type = meta.getFieldType();
if (type.endsWith("[]")) {
if (dep.isProxy()) {
info("Arrays cannot be used for proxied dependencies - Disabling the proxy mode");
dep.setProxy(false);
}
// Set the dependency to multiple
dep.setAggregate(true);
type = type.substring(0, type.length() - 2);
} else if (type.equals(List.class.getName()) || type.equals(Collection.class.getName())) {
dep.setType(LIST);
type = null;
} else if (type.equals(Vector.class.getName())) {
dep.setType(VECTOR);
if (dep.isProxy()) {
warn("Vectors cannot be used for proxied dependencies - Disabling the proxy mode");
dep.setProxy(false);
}
type = null;
} else if (type.equals(Set.class.getName())) {
dep.setType(SET);
type = null;
} else {
if (dep.isAggregate()) {
throw new ConfigurationException("A required service is not correct : the field "
+ meta.getFieldName()
+ " must be an array to support aggregate injections");
}
}
setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
}
// Constructor parameter
if (index != -1) {
if (! dep.isProxy()) {
throw new ConfigurationException("Services injected into constructor must be proxied");
}
MethodMetadata[] cts = manipulation.getConstructors();
// If we don't have a type, try to get the first constructor and get the type of the parameter
// we the index 'index'.
if (cts.length > 0 && cts[0].getMethodArguments().length > index) {
String type = cts[0].getMethodArguments()[index];
if (type.endsWith("[]")) {
throw new ConfigurationException("Services injected into constructor cannot be arrays");
} else if (type.equals(List.class.getName()) || type.equals(Collection.class.getName())) {
dep.setType(LIST);
type = null;
} else if (type.equals(Vector.class.getName())) {
throw new ConfigurationException("Services injected into constructor cannot be Vectors");
} else if (type.equals(Set.class.getName())) {
dep.setType(SET);
type = null;
} else {
if (dep.isAggregate()) {
throw new ConfigurationException("A required service is not correct : the constructor parameter "
+ index
+ " must be an aggregate type to support aggregate injections");
}
}
setSpecification(dep, type, true); // Throws an exception if the field type mismatch.
} else {
throw new ConfigurationException("Cannot determine the specification of the dependency " + index +
", please use the specification attribute");
}
}
// Disable proxy on scalar dependency targeting non-interface specification