in plugins/convention/src/main/java/org/apache/struts2/convention/PackageBasedActionConfigBuilder.java [681:795]
protected void buildConfiguration(Set<Class<?>> classes) {
Map<String, PackageConfig.Builder> packageConfigs = new HashMap<>();
for (Class<?> actionClass : classes) {
Actions actionsAnnotation = actionClass.getAnnotation(Actions.class);
Action actionAnnotation = actionClass.getAnnotation(Action.class);
// Skip classes that can't be instantiated
if (cannotInstantiate(actionClass)) {
LOG.trace("Class [{}] did not pass the instantiation test and will be ignored", actionClass.getName());
continue;
}
if (eagerLoading) {
// Tell the ObjectFactory about this class
try {
objectFactory.getClassInstance(actionClass.getName());
} catch (ClassNotFoundException e) {
LOG.error("Object Factory was unable to load class [{}]", actionClass.getName(), e);
throw new StrutsException("Object Factory was unable to load class " + actionClass.getName(), e);
}
}
// Determine the action package
String actionPackage = actionClass.getPackage().getName();
LOG.debug("Processing class [{}] in package [{}]", actionClass.getName(), actionPackage);
Set<String> allowedMethods = getAllowedMethods(actionClass);
// Determine the default namespace and action name
List<String> namespaces = determineActionNamespace(actionClass);
for (String namespace : namespaces) {
String defaultActionName = determineActionName(actionClass);
PackageConfig.Builder defaultPackageConfig = getPackageConfig(packageConfigs, namespace,
actionPackage, actionClass, null);
// Verify that the annotations have no errors and also determine if the default action
// configuration should still be built or not.
Map<String, List<Action>> map = getActionAnnotations(actionClass);
Set<String> actionNames = new HashSet<>();
boolean hasDefaultMethod = ReflectionTools.containsMethod(actionClass, DEFAULT_METHOD);
if (!map.containsKey(DEFAULT_METHOD)
&& hasDefaultMethod
&& actionAnnotation == null && actionsAnnotation == null
&& (alwaysMapExecute || map.isEmpty())) {
boolean found = false;
for (List<Action> actions : map.values()) {
for (Action action : actions) {
// Check if there are duplicate action names in the annotations.
String actionName = action.value().equals(Action.DEFAULT_VALUE) ? defaultActionName : action.value();
if (actionNames.contains(actionName)) {
throw new ConfigurationException("The action class [" + actionClass +
"] contains two methods with an action name annotation whose value " +
"is the same (they both might be empty as well).");
} else {
actionNames.add(actionName);
}
// Check this annotation is the default action
if (action.value().equals(Action.DEFAULT_VALUE)) {
found = true;
}
}
}
// Build the default
if (!found) {
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, DEFAULT_METHOD, null, allowedMethods);
}
}
// Build the actions for the annotations
for (Map.Entry<String, List<Action>> entry : map.entrySet()) {
String method = entry.getKey();
List<Action> actions = entry.getValue();
for (Action action : actions) {
PackageConfig.Builder pkgCfg = defaultPackageConfig;
if (action.value().contains("/") && !slashesInActionNames) {
pkgCfg = getPackageConfig(packageConfigs, namespace, actionPackage,
actionClass, action);
}
createActionConfig(pkgCfg, actionClass, defaultActionName, method, action, allowedMethods);
}
}
// some actions will not have any @Action or a default method, like the rest actions
// where the action mapper is the one that finds the right method at runtime
if (map.isEmpty() && mapAllMatches && actionAnnotation == null && actionsAnnotation == null) {
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, null, actionAnnotation, allowedMethods);
}
//if there are @Actions or @Action at the class level, create the mappings for them
String methodName = hasDefaultMethod ? DEFAULT_METHOD : null;
if (actionsAnnotation != null) {
List<Action> actionAnnotations = checkActionsAnnotation(actionsAnnotation);
for (Action actionAnnotation2 : actionAnnotations)
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, methodName, actionAnnotation2, allowedMethods);
} else if (actionAnnotation != null)
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, methodName, actionAnnotation, allowedMethods);
}
allowlistClasses.addAll(ConfigurationUtil.getAllClassTypes(actionClass));
}
providerAllowlist.registerAllowlist(this, allowlistClasses);
buildIndexActions(packageConfigs);
// Add the new actions to the configuration
Set<String> packageNames = packageConfigs.keySet();
for (String packageName : packageNames) {
configuration.addPackageConfig(packageName, packageConfigs.get(packageName).build());
}
}