/* license-start
*
* Copyright (C) 2008 - 2013 Crispico, <http://www.crispico.com/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details, at <http://www.gnu.org/licenses/>.
*
* Contributors:
* Crispico - Initial API and implementation
*
* license-end
*/
package org.flowerplatform.web.security.sandbox;
import java.security.Policy;
import java.util.ArrayList;
import java.util.List;
import org.flowerplatform.common.util.RunnableWithParam;
import org.flowerplatform.communication.CommunicationPlugin;
import org.flowerplatform.communication.channel.CommunicationChannel;
import org.flowerplatform.web.entity.Entity;
import org.flowerplatform.web.entity.ISecurityEntity;
import org.flowerplatform.web.entity.PermissionEntity;
import org.flowerplatform.web.entity.User;
import org.hibernate.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
/**
* Responsibility of this class is to listen for modifications
* of entities like permissions, users, groups and organizations
* and to clear the caches of {@link FlowerWebPolicy} accordingly.
*
* @author Cristi
* @author Florin
* @author Mariana
*
*
*/
public class SecurityEntityListener implements
PostInsertEventListener, PostDeleteEventListener, PostUpdateEventListener, PreDeleteEventListener {
private static final long serialVersionUID = 1377271602960613446L;
/**
*
*/
@Override
public void onPostInsert(PostInsertEvent evt) {
Object entity = evt.getEntity();
if (!(Policy.getPolicy() instanceof FlowerWebPolicy)) {
return;
}
if (!(entity instanceof PermissionEntity)) {
return;
}
FlowerWebPolicy policy = (FlowerWebPolicy) Policy.getPolicy();
policy.updateCachesFor((PermissionEntity) entity);
}
/**
* When an ISecurityEntity or a PermissionEntity is updated or deleted, the
* policy needs to properly clear its caches.
*
* @author Florin
* @author Cristi
*
*/
@Override
public void onPostUpdate(PostUpdateEvent evt) {
if (evt.getEntity() instanceof User) {
final Entity entity = (Entity) evt.getEntity();
// when user is deleted we do not clear it from the principal, because the can still be logged on
CommunicationPlugin.getInstance().getCommunicationChannelManager().iterateCommunicationChannels(new RunnableWithParam<Boolean, CommunicationChannel>() {
@Override
public Boolean run(CommunicationChannel param) {
if (param.getPrincipal() != null && param.getPrincipal().getUserId() == entity.getId()) {
param.getPrincipal().clearCachedUser();
}
return null;
}
});
}
entityUpdatedOrDeleted(evt.getEntity());
}
/**
* @author Florin
* @author Cristi
* @return
*
*/
@Override
public boolean onPreDelete(PreDeleteEvent evt) {
if (evt.getEntity() instanceof User) {
final Entity entity = (Entity) evt.getEntity();
if (CommunicationPlugin.getInstance().getCommunicationChannelManager() != null) { // condition for junit tests
final List<CommunicationChannel> clientsToDisconnect = new ArrayList<CommunicationChannel>();
CommunicationPlugin.getInstance().getCommunicationChannelManager().iterateCommunicationChannels(new RunnableWithParam<Boolean, CommunicationChannel>() {
@Override
public Boolean run(CommunicationChannel param) {
if (param.getPrincipal().getUserId() == entity.getId()) {
clientsToDisconnect.add((CommunicationChannel) param);
}
return null;
}
});
// we do this here, after the loop, to avoid ConcurrentModifException
for (CommunicationChannel channel : clientsToDisconnect) {
channel.disconnect();
}
}
}
return false;
}
/**
*
*/
@Override
public void onPostDelete(PostDeleteEvent evt) {
entityUpdatedOrDeleted(evt.getEntity());
}
/**
*
*/
private void entityUpdatedOrDeleted(Object entity) {
if (!(Policy.getPolicy() instanceof FlowerWebPolicy)) {
return;
}
FlowerWebPolicy policy = (FlowerWebPolicy) Policy.getPolicy();
if (entity instanceof ISecurityEntity) {
policy.updateCachesFor((ISecurityEntity) entity);
} else if (entity instanceof PermissionEntity) {
policy.updateCachesFor((PermissionEntity) entity);
}
}
}