/*
*
* This is a simple Content Management System (CMS)
* Copyright (C) 2011 Imran M Yousuf (imyousuf@smartitengineering.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, either version 3 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.smartitengineering.cms.spi.impl.events;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.smartitengineering.cms.api.content.Content;
import com.smartitengineering.cms.api.content.ContentId;
import com.smartitengineering.cms.api.event.Event;
import com.smartitengineering.cms.api.event.Event.EventType;
import com.smartitengineering.cms.api.event.Event.Type;
import com.smartitengineering.cms.api.event.EventListener;
import com.smartitengineering.cms.api.factory.SmartContentAPI;
import com.smartitengineering.cms.api.type.ContentType;
import com.smartitengineering.cms.api.type.ContentTypeId;
import com.smartitengineering.cms.api.workspace.Sequence;
import com.smartitengineering.cms.api.workspace.SequenceId;
import com.smartitengineering.cms.api.workspace.WorkspaceId;
import com.smartitengineering.dao.solr.SolrWriteDao;
import com.smartitengineering.events.async.api.EventConsumer;
import java.io.BufferedReader;
import java.io.StringReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author imyousuf
*/
@Singleton
public class EventConsumerImpl implements EventConsumer {
@Inject
private EventListener<Content> contentListener;
@Inject
private EventListener<ContentType> contentTypeListener;
@Inject
private EventListener<Sequence> sequenceListener;
@Inject
private SolrWriteDao solrWriteDao;
private final transient Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void consume(String eventContentType, String eventMessage) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new StringReader(eventMessage));
final Type sourceType = Type.valueOf(reader.readLine());
final EventType type = EventType.valueOf(reader.readLine());
if (logger.isDebugEnabled()) {
logger.debug("Event source type " + sourceType);
logger.debug("Event type " + type);
}
final StringBuilder idStr = new StringBuilder("");
String line;
do {
line = reader.readLine();
if (StringUtils.isNotBlank(line)) {
idStr.append(line).append('\n');
}
}
while (StringUtils.isNotBlank(line));
final byte[] decodedIdString = Base64.decodeBase64(idStr.toString());
final String idString = org.apache.commons.codec.binary.StringUtils.newStringUtf8(decodedIdString);
if (logger.isInfoEnabled()) {
logger.info("ID String from message " + idString);
}
switch (sourceType) {
case CONTENT: {
final ContentId contentId;
final String[] idParams = idString.split("\n");
if (idParams.length < 3) {
logger.warn("Insufficient params for forming content id in id string. Thus ignoring the following message " +
idString);
return;
}
final byte[] contentIdBytes = org.apache.commons.codec.binary.StringUtils.getBytesUtf8(idParams[2]);
final WorkspaceId workspaceId = SmartContentAPI.getInstance().getWorkspaceApi().createWorkspaceId(idParams[0],
idParams[1]);
contentId = SmartContentAPI.getInstance().getContentLoader().createContentId(workspaceId, contentIdBytes);
Content content = contentId.getContent();
if (content == null && EventType.DELETE.equals(type)) {
content =
(Content) Proxy.newProxyInstance(Content.class.getClassLoader(), new Class[]{Content.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getContentId")) {
return contentId;
}
return null;
}
});
}
if (content == null) {
logger.warn("No Content for event thus ignoring it - " + idString);
return;
}
final Event<Content> event = SmartContentAPI.getInstance().getEventRegistrar().<Content>createEvent(type,
sourceType,
content);
contentListener.notify(event);
}
break;
case CONTENT_TYPE: {
final ContentTypeId typeId;
final String[] idParams = idString.split("\n");
if (idParams.length < 4) {
logger.error("Insufficient params for forming content type id in id string. Thus ignoring the following message " +
idString);
return;
}
final WorkspaceId workspaceId = SmartContentAPI.getInstance().getWorkspaceApi().createWorkspaceId(idParams[0],
idParams[1]);
typeId = SmartContentAPI.getInstance().getContentTypeLoader().createContentTypeId(workspaceId, idParams[2],
idParams[3]);
ContentType contentType = typeId.getContentType();
if (contentType == null && EventType.DELETE.equals(type)) {
contentType = (ContentType) Proxy.newProxyInstance(ContentType.class.getClassLoader(), new Class[]{
ContentType.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getContentTypeID")) {
return typeId;
}
return null;
}
});
}
if (contentType == null) {
logger.warn("No Content Type for event thus ignoring it - " + idString);
return;
}
final Event<ContentType> event =
SmartContentAPI.getInstance().getEventRegistrar().<ContentType>createEvent(type,
sourceType,
contentType);
contentTypeListener.notify(event);
}
break;
case SEQUENCE: {
final SequenceId seqId;
final String[] idParams = idString.split("\n");
if (idParams.length < 3) {
logger.error("Insufficient params for forming sequence id in id string. Thus ignoring the following message " +
idString);
return;
}
final WorkspaceId workspaceId = SmartContentAPI.getInstance().getWorkspaceApi().createWorkspaceId(idParams[0],
idParams[1]);
seqId = SmartContentAPI.getInstance().getWorkspaceApi().createSequenceId(workspaceId, idParams[2]);
Sequence sequence = seqId.getSequence();
if (sequence == null && EventType.DELETE.equals(type)) {
sequence = (Sequence) Proxy.newProxyInstance(Sequence.class.getClassLoader(), new Class[]{
Sequence.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getSequenceId")) {
return seqId;
}
return null;
}
});
}
if (sequence == null) {
logger.warn("No Sequence for event thus ignoring it - " + idString);
return;
}
final Event<Sequence> event =
SmartContentAPI.getInstance().getEventRegistrar().<Sequence>createEvent(type,
sourceType,
sequence);
sequenceListener.notify(event);
}
break;
default:
logger.info(new StringBuilder("Ignoring event source type ").append(sourceType).toString());
}
}
catch (Exception ex) {
logger.warn("Could not persist content ID!", ex);
throw new RuntimeException(ex);
}
finally {
try {
reader.close();
}
catch (Exception ex) {
logger.warn("Could not close reader!", ex);
}
}
}
@Override
public void startConsumption() {
}
@Override
public void endConsumption(boolean prematureEnd) {
if (prematureEnd) {
solrWriteDao.rollback();
}
else {
solrWriteDao.commit();
}
}
}