package org.mobicents.slee.xdm.server;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.slee.ActivityContextInterface;
import javax.slee.ChildRelation;
import javax.slee.CreateException;
import javax.slee.RolledBackContext;
import javax.slee.Sbb;
import javax.slee.SbbContext;
import org.apache.log4j.Logger;
import org.openxdm.xcap.common.error.ConflictException;
import org.openxdm.xcap.common.error.NoParentConflictException;
import org.openxdm.xcap.common.error.RequestException;
import org.openxdm.xcap.common.key.XcapUriKey;
import org.openxdm.xcap.common.uri.DocumentSelector;
import org.openxdm.xcap.server.etag.ETagValidator;
import org.openxdm.xcap.server.etag.IfMatchETagValidator;
import org.openxdm.xcap.server.etag.IfNoneMatchETagValidator;
import org.openxdm.xcap.server.result.ReadResult;
import org.openxdm.xcap.server.result.WriteResult;
import org.openxdm.xcap.server.slee.RequestProcessorSbbLocalObject;
import org.openxdm.xcap.server.slee.resource.datasource.AppUsageActivity;
import org.openxdm.xcap.server.slee.resource.datasource.AttributeUpdatedEvent;
import org.openxdm.xcap.server.slee.resource.datasource.DataSourceActivityContextInterfaceFactory;
import org.openxdm.xcap.server.slee.resource.datasource.DataSourceSbbInterface;
import org.openxdm.xcap.server.slee.resource.datasource.DocumentActivity;
import org.openxdm.xcap.server.slee.resource.datasource.DocumentUpdatedEvent;
import org.openxdm.xcap.server.slee.resource.datasource.ElementUpdatedEvent;
public abstract class InternalXDMClientControlSbb implements Sbb,
XDMClientControlSbbLocalObject {
private static Logger logger = Logger
.getLogger(InternalXDMClientControlSbb.class);
private SbbContext sbbContext = null; // This SBB's context
private DataSourceSbbInterface dataSourceSbbInterface = null;
private DataSourceActivityContextInterfaceFactory dataSourceACIF = null;
/**
* Called when an sbb object is created and enters the pooled state.
*/
public void setSbbContext(SbbContext sbbContext) {
this.sbbContext = sbbContext;
try {
Context context = (Context) new InitialContext()
.lookup("java:comp/env");
dataSourceSbbInterface = (DataSourceSbbInterface) context
.lookup("slee/resources/xdm/datasource/sbbrainterface");
dataSourceACIF = (DataSourceActivityContextInterfaceFactory) context
.lookup("slee/resources/xdm/datasource/1.0/acif");
} catch (NamingException e) {
logger.error("Can't set sbb context.", e);
}
}
public abstract ChildRelation getRequestProcessorChildRelation();
public abstract void setRequestProcessorSbbLocalObjectCMP(
RequestProcessorSbbLocalObject value);
public abstract RequestProcessorSbbLocalObject getRequestProcessorSbbLocalObjectCMP();
protected RequestProcessorSbbLocalObject getRequestProcessor() {
RequestProcessorSbbLocalObject childSbb = getRequestProcessorSbbLocalObjectCMP();
if (childSbb == null) {
try {
childSbb = (RequestProcessorSbbLocalObject) getRequestProcessorChildRelation()
.create();
} catch (Exception e) {
logger.error("failed to create child sbb", e);
}
setRequestProcessorSbbLocalObjectCMP(childSbb);
}
return childSbb;
}
// -- SBB LOCAL OBJECT METHODS
private void delete(XcapUriKey key, ETagValidator eTagValidator, String user) {
if (logger.isInfoEnabled()) {
logger.info("Deleting " + key);
}
int responseCode = -1;
String eTag = null;
String responseContent = null;
try {
WriteResult writeResult = getRequestProcessor().delete(
key.getResourceSelector(), null,
ServerConfiguration.XCAP_ROOT,user);
responseCode = writeResult.getResponseStatus();
eTag = writeResult.getResponseEntityTag();
} catch (ConflictException e) {
responseCode = e.getResponseStatus();
responseContent = e.getResponseContent();
} catch (RequestException e) {
responseCode = e.getResponseStatus();
}
getParentSbbCMP().deleteResponse(key, responseCode, responseContent, eTag);
}
public void delete(XcapUriKey key) {
delete(key, null);
}
public void deleteIfMatch(XcapUriKey key, String tag, String user) {
delete(key, new IfMatchETagValidator(tag),user);
}
public void deleteIfNoneMatch(XcapUriKey key, String tag, String user) {
delete(key, new IfNoneMatchETagValidator(tag),user);
}
public void get(XcapUriKey key, String user) {
if (logger.isInfoEnabled()) {
logger.info("Retreiving " + key);
}
int responseCode = -1;
String mimetype = null;
String content = null;
String eTag = null;
try {
ReadResult readResult = getRequestProcessor().get(
key.getResourceSelector(),user);
responseCode = 200;
mimetype = readResult.getResponseDataObject().getMimetype();
content = readResult.getResponseDataObject().toXML();
eTag = readResult.getResponseEntityTag();
} catch (RequestException e) {
if (logger.isDebugEnabled()) {
logger.debug("Exception processing request", e);
}
responseCode = e.getResponseStatus();
}
getParentSbbCMP().getResponse(key, responseCode, mimetype, content,
eTag);
}
private void put(XcapUriKey key, String mimetype, byte[] content,
ETagValidator eTagValidator, String user) {
if (logger.isInfoEnabled()) {
logger.info("Putting content with mimetype "+mimetype+" at " + key);
}
ByteArrayInputStream bais = new ByteArrayInputStream(content);
int responseCode = -1;
String eTag = null;
String responseContent = null;
try {
WriteResult writeResult = getRequestProcessor().put(
key.getResourceSelector(), mimetype, bais, eTagValidator,
ServerConfiguration.XCAP_ROOT,user);
responseCode = writeResult.getResponseStatus();
eTag = writeResult.getResponseEntityTag();
} catch (NoParentConflictException e) {
// add base uri
e
.setSchemeAndAuthorityURI(ServerConfiguration.SCHEME_AND_AUTHORITY_URI);
responseCode = e.getResponseStatus();
responseContent = e.getResponseContent();
} catch (ConflictException e) {
responseCode = e.getResponseStatus();
responseContent = e.getResponseContent();
} catch (RequestException e) {
responseCode = e.getResponseStatus();
} finally {
try {
bais.close();
} catch (IOException e) {
// ignore
logger.error(e.getMessage(),e);
}
}
getParentSbbCMP().putResponse(key, responseCode, responseContent, eTag);
}
public void put(XcapUriKey key, String mimetype, byte[] content, String user) {
put(key, mimetype, content, null,user);
}
public void putIfMatch(XcapUriKey key, String tag, String mimetype,
byte[] content, String user) {
put(key, mimetype, content, new IfMatchETagValidator(tag),user);
}
public void putIfNoneMatch(XcapUriKey key, String tag, String mimetype,
byte[] content, String user) {
put(key, mimetype, content, new IfNoneMatchETagValidator(tag), user);
}
// --- subscribe/unsubscribe interface methods
public void setParentSbb(XDMClientControlParentSbbLocalObject parentSbb) {
setParentSbbCMP(parentSbb);
}
public void subscribeDocument(DocumentSelector documentSelector) {
try {
DocumentActivity activity = dataSourceSbbInterface
.createDocumentActivity(documentSelector);
ActivityContextInterface aci = dataSourceACIF
.getActivityContextInterface(activity);
aci.attach(this.sbbContext.getSbbLocalObject());
if (logger.isInfoEnabled()) {
logger.info("Subscribed document " + documentSelector);
}
} catch (Exception e) {
logger.error("Failed to subscribe document resource", e);
}
}
public void unsubscribeDocument(DocumentSelector documentSelector) {
for (ActivityContextInterface aci : sbbContext.getActivities()) {
Object object = aci.getActivity();
if (object instanceof DocumentActivity) {
DocumentActivity activity = (DocumentActivity) object;
if (activity.getDocumentSelector().equals(
documentSelector.toString())) {
aci.detach(sbbContext.getSbbLocalObject());
activity.remove();
if (logger.isInfoEnabled()) {
logger.info("Unsubscribed document " + documentSelector);
}
return;
}
}
}
if (logger.isInfoEnabled()) {
logger.info("Didn't unsubscribe, did not found subscription for "
+ documentSelector);
}
}
public void subscribeAppUsage(String auid) {
try {
AppUsageActivity activity = dataSourceSbbInterface
.createAppUsageActivity(auid);
ActivityContextInterface aci = dataSourceACIF
.getActivityContextInterface(activity);
aci.attach(this.sbbContext.getSbbLocalObject());
if (logger.isInfoEnabled()) {
logger.info("Subscribed app usage " + auid);
}
} catch (Exception e) {
logger.error("Failed to subscribe document resource", e);
}
}
public void unsubscribeAppUsage(String auid) {
for (ActivityContextInterface aci : sbbContext.getActivities()) {
Object object = aci.getActivity();
if (object instanceof AppUsageActivity) {
AppUsageActivity activity = (AppUsageActivity) object;
if (activity.getAUID().equals(auid)) {
aci.detach(sbbContext.getSbbLocalObject());
activity.remove();
if (logger.isInfoEnabled()) {
logger.info("Unsubscribed app usage" + auid);
}
return;
}
}
}
if (logger.isInfoEnabled()) {
logger.info("Didn't unsubscribe, did not found subscription for "
+ auid);
}
}
// EVENT HANDLER METHODS
public void onAttributeUpdatedEvent(AttributeUpdatedEvent event,
ActivityContextInterface aci) {
if (logger.isInfoEnabled()) {
logger.info("Attribute updated at " + event.getDocumentSelector());
}
getParentSbbCMP().attributeUpdated(event.getDocumentSelector(),
event.getNodeSelector(), event.getAttributeSelector(),
event.getNamespaces(), event.getOldETag(), event.getNewETag(),
event.getDocumentAsString(), event.getAttributeValue());
}
public void onDocumentUpdatedEvent(DocumentUpdatedEvent event,
ActivityContextInterface aci) {
if (logger.isInfoEnabled()) {
logger.info("Document updated at " + event.getDocumentSelector());
}
getParentSbbCMP().documentUpdated(event.getDocumentSelector(),
event.getOldETag(), event.getNewETag(),
event.getDocumentAsString());
}
public void onElementUpdatedEvent(ElementUpdatedEvent event,
ActivityContextInterface aci) {
if (logger.isInfoEnabled()) {
logger.info("Element updated at " + event.getDocumentSelector());
}
getParentSbbCMP().elementUpdated(event.getDocumentSelector(),
event.getNodeSelector(), event.getNamespaces(),
event.getOldETag(), event.getNewETag(),
event.getDocumentAsString(), event.getElementAsString());
}
// CMP FIELDs
public abstract void setParentSbbCMP(
XDMClientControlParentSbbLocalObject parentSbb);
public abstract XDMClientControlParentSbbLocalObject getParentSbbCMP();
// SBB OBJECT LIFECYCLE METHODS
public void sbbActivate() {
}
public void sbbCreate() throws CreateException {
}
public void sbbExceptionThrown(Exception arg0, Object arg1,
ActivityContextInterface arg2) {
}
public void sbbLoad() {
}
public void sbbPassivate() {
}
public void sbbPostCreate() throws CreateException {
}
public void sbbRemove() {
}
public void sbbRolledBack(RolledBackContext arg0) {
}
public void sbbStore() {
}
public void unsetSbbContext() {
this.sbbContext = null;
}
}