if (discoveredResourceDetails == null) {
log.info("Plugin Error: During manual add, discovery component method ["
+ discoveryComponent.getClass().getName() + ".discoverResource()] returned null "
+ "(either the Resource type was blacklisted or the plugin developer "
+ "did not implement support for manually discovered Resources correctly).");
throw new PluginContainerException("The [" + resourceType.getPlugin()
+ "] plugin does not properly support manual addition of [" + resourceType.getName()
+ "] Resources.");
}
} else {
// The plugin is using the old manual add API, which we must continue to support to maintain
// backward compatibility.
log.info("Plugin Warning: Resource type '" + resourceType.getName() + "' from '"
+ resourceType.getPlugin() + "' is still using the deprecated manual Resource add API, "
+ "rather than the new ManualAddFacet interface.");
List<Configuration> pluginConfigurations = new ArrayList<Configuration>(1);
pluginConfigurations.add(pluginConfiguration);
ResourceDiscoveryContext<ResourceComponent<?>> discoveryContext = new ResourceDiscoveryContext<ResourceComponent<?>>(
resourceType, parentResourceComponent, parentResourceContainer.getResourceContext(),
SystemInfoFactory.createSystemInfo(), new ArrayList<ProcessScanResult>(0), pluginConfigurations,
this.configuration.getContainerName(), this.configuration.getPluginContainerDeployment());
// Ask the plugin's discovery component to find the new resource, throwing exceptions if it cannot be
// found at all.
try {
Set<DiscoveredResourceDetails> discoveredResources = invokeDiscoveryComponent(
parentResourceContainer, discoveryComponent, discoveryContext);
if ((discoveredResources == null) || discoveredResources.isEmpty()) {
log.info("Plugin Error: During manual add, discovery component method ["
+ discoveryComponent.getClass().getName() + ".discoverResources()] returned "
+ discoveredResources + " when passed a single plugin configuration "
+ "(either the resource type was blacklisted or the plugin developer "
+ "did not implement support for manually discovered resources correctly).");
throw new PluginContainerException("The [" + resourceType.getPlugin()
+ "] plugin does not properly support manual addition of [" + resourceType.getName()
+ "] resources.");
}
discoveredResourceDetails = discoveredResources.iterator().next();
} catch (DiscoverySuspendedException e) {
String message = "The discovery class ["
+ discoveryComponent.getClass().getName()
+ "]"
+ " uses a legacy implementation of \"manual add\" functionality. Some of the child resources"
+ " with the resource type ["
+ resourceType
+ "] under the parent resource ["
+ parentResourceContainer.getResource()
+ "]"
+ " failed to upgrade, which makes it impossible to support the legacy manual-add implementation. Either upgrade the plugin ["
+ resourceType.getPlugin()
+ "] to successfully upgrade all resources or consider implementing the ManualAdd facet.";
log.info(message);
throw new PluginContainerException(message, e);
}
}
// Create the new Resource and add it to inventory if it isn't already there.
resource = createNewResource(discoveredResourceDetails);
Resource parentResource = getResourceContainer(parentResourceId).getResource();
Resource existingResource = findMatchingChildResource(resource, parentResource);
if (existingResource != null) {
if (log.isDebugEnabled()) {
log.debug("Manual add for resource type [" + resourceType.getName() + "] and parent resource id ["
+ parentResourceId
+ "] found a resource that already exists in inventory - updating existing resource ["
+ existingResource + "]");
}
resourceAlreadyExisted = true;
resource = existingResource;
if (resource.getInventoryStatus() != InventoryStatus.COMMITTED) {
resource.setPluginConfiguration(pluginConfiguration);
}
} else {
if (log.isDebugEnabled()) {
log.debug("Adding manually discovered resource [" + resource + "] to inventory...");
}
resource.setInventoryStatus(InventoryStatus.COMMITTED);
parentResource.addChildResourceWithoutAncestry(resource);
initResourceContainer(resource);
}
// Make sure the resource's component is activated (i.e. started).
boolean newPluginConfig = true;
ResourceContainer resourceContainer = getResourceContainer(resource);
if (log.isDebugEnabled()) {
log.debug("Activating resource [" + resource + "]...");
}
// NOTE: We don't mess with inventory status - that's the server's responsibility.
// Tell the server to merge the resource into its inventory.
DiscoveryServerService discoveryServerService = this.configuration.getServerServices()
.getDiscoveryServerService();
mergeResourceResponse = discoveryServerService.addResource(resource, ownerSubjectId);
// Sync our local resource up with the one now in server inventory. Treat this like a newlyCommittedResource
// - set mtime (same as ctime for a new resource) to ensure this does not get picked up in an inventory sync
// pass, we know we're currently in sync with the server.
resource.setId(mergeResourceResponse.getResourceId());
resource.setMtime(mergeResourceResponse.getMtime());
Set newResources = new LinkedHashSet<Resource>();
newResources.add(resource);
postProcessNewlyCommittedResources(newResources);
performServiceScan(resource.getId());
// Note that it is important to activate the resource *AFTER* it has been synced with the
// server so that the resource has a valid id (which is needed by at least the content
// subsystem).
try {
activateResource(resource, resourceContainer, newPluginConfig);
} catch (Throwable t) {
// if it fails to start keep going, we already have the resource in inventory and
// we are in sync with the server. The new resource will be unavailable but at least
// it will be accessible and editable by the user. Report the start exception at the end.
handleInvalidPluginConfigurationResourceError(resource, t);
throw new PluginContainerException("The resource [" + resource
+ "] has been added but could not be started. Verify the supplied configuration values: ", t);
}
}
// Catch any other RuntimeExceptions or Errors, so the server doesn't have to worry about deserializing or
// catching them. Before rethrowing, wrap them in a WrappedRemotingException and then wrap that in either an
// InvalidPluginConfigurationException or a PluginContainerException.
catch (Throwable t) {
if ((resource != null) && !resourceAlreadyExisted && (getResourceContainer(resource) != null)) {
// If the resource got added to inventory, roll it back (i.e. deactivate it, then remove it from inventory).
if (log.isDebugEnabled()) {
log.debug("Rolling back manual add of resource of type [" + resourceType.getName()
+ "] - removing resource with id [" + resource.getId() + "] from inventory...");
}
deactivateResource(resource);
uninventoryResource(resource.getId());
}
if (t instanceof InvalidPluginConfigurationException) {
String errorMessage = "Unable to connect to managed resource of type [" + resourceType.getName()
+ "] using the specified connection properties - resource will not be added to inventory.";
log.info(errorMessage, t);
// In the exception we throw over to the server, strip the InvalidPluginConfigurationException out of the
// stack trace, but append the message from that exception to the message of the exception we throw. This
// will make for a nicer error message for the server to display in the UI.
errorMessage += ((t.getLocalizedMessage() != null) ? (" " + t.getLocalizedMessage()) : "");
throw new InvalidPluginConfigurationClientException(errorMessage,
(t.getCause() != null) ? new WrappedRemotingException(t.getCause()) : null);
} else {
log.error("Manual add failed for resource of type [" + resourceType.getName()
+ "] and parent resource id [" + parentResourceId + "]", t);
throw new PluginContainerException("Failed to add resource with type [" + resourceType.getName()
+ "] and parent resource id [" + parentResourceId + "]", new WrappedRemotingException(t));
}
}
return mergeResourceResponse;