/*
* Copyright (c) 2010-2013 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.evolveum.midpoint.provisioning.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.Validate;
import org.springframework.stereotype.Component;
import com.evolveum.midpoint.provisioning.api.ChangeNotificationDispatcher;
import com.evolveum.midpoint.provisioning.api.GenericConnectorException;
import com.evolveum.midpoint.provisioning.api.ResourceEventDescription;
import com.evolveum.midpoint.provisioning.api.ResourceEventListener;
import com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener;
import com.evolveum.midpoint.provisioning.api.ResourceObjectShadowChangeDescription;
import com.evolveum.midpoint.provisioning.api.ResourceOperationDescription;
import com.evolveum.midpoint.provisioning.api.ResourceOperationListener;
import com.evolveum.midpoint.schema.internals.InternalsConfig;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
/**
* @author Radovan Semancik
*
*/
@Component
public class ChangeNotificationDispatcherImpl implements ChangeNotificationDispatcher {
private boolean filterProtectedObjects = true;
private List<ResourceObjectChangeListener> changeListeners = new ArrayList<ResourceObjectChangeListener>();
private List<ResourceOperationListener> operationListeners = new ArrayList<ResourceOperationListener>();
private List<ResourceEventListener> eventListeners = new ArrayList<ResourceEventListener>();
private static final Trace LOGGER = TraceManager.getTrace(ChangeNotificationDispatcherImpl.class);
public boolean isFilterProtectedObjects() {
return filterProtectedObjects;
}
public void setFilterProtectedObjects(boolean filterProtectedObjects) {
this.filterProtectedObjects = filterProtectedObjects;
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeNotificationManager#registerNotificationListener(com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener)
*/
@Override
public synchronized void registerNotificationListener(ResourceObjectChangeListener listener) {
if (changeListeners.contains(listener)) {
LOGGER.warn(
"Resource object change listener '{}' is already registered. Subsequent registration is ignored",
listener);
} else {
changeListeners.add(listener);
}
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeNotificationManager#registerNotificationListener(com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener)
*/
@Override
public synchronized void registerNotificationListener(ResourceOperationListener listener) {
if (operationListeners.contains(listener)) {
LOGGER.warn(
"Resource operation listener '{}' is already registered. Subsequent registration is ignored",
listener);
} else {
operationListeners.add(listener);
}
}
@Override
public synchronized void registerNotificationListener(ResourceEventListener listener) {
if (eventListeners.contains(listener)) {
LOGGER.warn(
"Resource event listener '{}' is already registered. Subsequent registration is ignored",
listener);
} else {
eventListeners.add(listener);
}
}
@Override
public void unregisterNotificationListener(ResourceEventListener listener) {
eventListeners.remove(listener);
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeNotificationManager#unregisterNotificationListener(com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener)
*/
@Override
public synchronized void unregisterNotificationListener(ResourceOperationListener listener) {
changeListeners.remove(listener);
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeNotificationManager#unregisterNotificationListener(com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener)
*/
@Override
public synchronized void unregisterNotificationListener(ResourceObjectChangeListener listener) {
operationListeners.remove(listener);
}
@Override
public void notifyChange(ResourceObjectShadowChangeDescription change, Task task, OperationResult parentResult) {
Validate.notNull(change, "Change description of resource object shadow must not be null.");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("SYNCHRONIZATION change notification\n{} ", change.debugDump());
}
if (InternalsConfig.consistencyChecks) change.checkConsistence();
if ((null != changeListeners) && (!changeListeners.isEmpty())) {
for (ResourceObjectChangeListener listener : new ArrayList<>(changeListeners)) { // sometimes there is registration/deregistration from within
//LOGGER.trace("Listener: {}", listener.getClass().getSimpleName());
try {
listener.notifyChange(change, task, parentResult);
} catch (RuntimeException e) {
LOGGER.error("Exception {} thrown by object change listener {}: {}", e.getClass(), listener.getName(),
e.getMessage(), e);
parentResult.createSubresult(CLASS_NAME_WITH_DOT + "notifyChange").recordWarning("Change listener has thrown unexpected exception", e);
throw e;
}
}
} else {
LOGGER.warn("Change notification received but listener list is empty, there is nobody to get the message");
}
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener#notifyFailure(com.evolveum.midpoint.provisioning.api.ResourceObjectShadowFailureDescription, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult)
*/
@Override
public void notifyFailure(ResourceOperationDescription failureDescription,
Task task, OperationResult parentResult) {
Validate.notNull(failureDescription, "Operation description of resource object shadow must not be null.");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Resource operation failure notification\n{} ", failureDescription.debugDump());
}
failureDescription.checkConsistence();
if ((null != changeListeners) && (!changeListeners.isEmpty())) {
for (ResourceOperationListener listener : new ArrayList<>(operationListeners)) { // sometimes there is registration/deregistration from within
//LOGGER.trace("Listener: {}", listener.getClass().getSimpleName());
try {
listener.notifyFailure(failureDescription, task, parentResult);
} catch (RuntimeException e) {
LOGGER.error("Exception {} thrown by operation failure listener {}: {}", new Object[]{
e.getClass(), listener.getName(), e.getMessage(), e });
parentResult.createSubresult(CLASS_NAME_WITH_DOT + "notifyFailure").recordWarning("Operation failure listener has thrown unexpected exception", e);
}
}
} else {
LOGGER.debug("Operation failure received but listener list is empty, there is nobody to get the message");
}
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener#notifyFailure(com.evolveum.midpoint.provisioning.api.ResourceObjectShadowFailureDescription, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult)
*/
@Override
public void notifySuccess(ResourceOperationDescription failureDescription,
Task task, OperationResult parentResult) {
Validate.notNull(failureDescription, "Operation description of resource object shadow must not be null.");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Resource operation success notification\n{} ", failureDescription.debugDump());
}
failureDescription.checkConsistence();
if ((null != changeListeners) && (!changeListeners.isEmpty())) {
for (ResourceOperationListener listener : new ArrayList<>(operationListeners)) { // sometimes there is registration/deregistration from within
//LOGGER.trace("Listener: {}", listener.getClass().getSimpleName());
try {
listener.notifySuccess(failureDescription, task, parentResult);
} catch (RuntimeException e) {
LOGGER.error("Exception {} thrown by operation success listener {}: {}", new Object[]{
e.getClass(), listener.getName(), e.getMessage(), e });
parentResult.createSubresult(CLASS_NAME_WITH_DOT + "notifySuccess").recordWarning("Operation success listener has thrown unexpected exception", e);
}
}
} else {
LOGGER.debug("Operation success received but listener list is empty, there is nobody to get the message");
}
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener#notifyFailure(com.evolveum.midpoint.provisioning.api.ResourceObjectShadowFailureDescription, com.evolveum.midpoint.task.api.Task, com.evolveum.midpoint.schema.result.OperationResult)
*/
@Override
public void notifyInProgress(ResourceOperationDescription failureDescription,
Task task, OperationResult parentResult) {
Validate.notNull(failureDescription, "Operation description of resource object shadow must not be null.");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Resource operation in-progress notification\n{} ", failureDescription.debugDump());
}
failureDescription.checkConsistence();
if ((null != changeListeners) && (!changeListeners.isEmpty())) {
for (ResourceOperationListener listener : new ArrayList<>(operationListeners)) { // sometimes there is registration/deregistration from within
//LOGGER.trace("Listener: {}", listener.getClass().getSimpleName());
try {
listener.notifyInProgress(failureDescription, task, parentResult);
} catch (RuntimeException e) {
LOGGER.error("Exception {} thrown by operation in-progress listener {}: {}", new Object[]{
e.getClass(), listener.getName(), e.getMessage(), e });
parentResult.createSubresult(CLASS_NAME_WITH_DOT + "notifyInProgress").recordWarning("Operation in-progress listener has thrown unexpected exception", e);
}
}
} else {
LOGGER.debug("Operation in-progress received but listener list is empty, there is nobody to get the message");
}
}
/* (non-Javadoc)
* @see com.evolveum.midpoint.provisioning.api.ResourceObjectChangeListener#getName()
*/
@Override
public String getName() {
return "object change notification dispatcher";
}
@Override
public void notifyEvent(ResourceEventDescription eventDescription,
Task task, OperationResult parentResult) throws SchemaException,
CommunicationException, ConfigurationException,
SecurityViolationException, ObjectNotFoundException,
GenericConnectorException, ObjectAlreadyExistsException {
Validate.notNull(eventDescription, "Event description must not be null.");
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("SYNCHRONIZATION change notification\n{} ", eventDescription.debugDump());
}
if (filterProtectedObjects && eventDescription.isProtected()) {
LOGGER.trace("Skipping dispatching of {} because it is protected", eventDescription);
return;
}
// if (InternalsConfig.consistencyChecks) eventDescription.checkConsistence();
if ((null != eventListeners) && (!eventListeners.isEmpty())) {
for (ResourceEventListener listener : new ArrayList<>(eventListeners)) { // sometimes there is registration/deregistration from within
//LOGGER.trace("Listener: {}", listener.getClass().getSimpleName());
try {
listener.notifyEvent(eventDescription, task, parentResult);
} catch (RuntimeException e) {
LOGGER.error("Exception {} thrown by event listener {}: {}", new Object[]{
e.getClass(), listener.getName(), e.getMessage(), e });
parentResult.createSubresult(CLASS_NAME_WITH_DOT + "notifyEvent").recordWarning("Event listener has thrown unexpected exception", e);
throw e;
}
}
} else {
LOGGER.warn("Event notification received but listener list is empty, there is nobody to get the message");
}
}
}