/*
* Mobicents, Communications Middleware
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* 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 Lesser General Public License
* for more details.
*
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
*
* Boston, MA 02110-1301 USA
*/
package org.mobicents.slee.resource.diameter.sh.server;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.java.slee.resource.diameter.base.DiameterMessageFactory;
import net.java.slee.resource.diameter.base.NoSuchAvpException;
import net.java.slee.resource.diameter.base.events.DiameterHeader;
import net.java.slee.resource.diameter.base.events.DiameterMessage;
import net.java.slee.resource.diameter.base.events.avp.AvpNotAllowedException;
import net.java.slee.resource.diameter.base.events.avp.DiameterAvp;
import net.java.slee.resource.diameter.base.events.avp.DiameterAvpCodes;
import net.java.slee.resource.diameter.base.events.avp.DiameterIdentity;
import net.java.slee.resource.diameter.base.events.avp.GroupedAvp;
import net.java.slee.resource.diameter.sh.client.DiameterShAvpFactory;
import net.java.slee.resource.diameter.sh.client.MessageFactory;
import net.java.slee.resource.diameter.sh.client.events.ProfileUpdateAnswer;
import net.java.slee.resource.diameter.sh.client.events.PushNotificationRequest;
import net.java.slee.resource.diameter.sh.client.events.SubscribeNotificationsAnswer;
import net.java.slee.resource.diameter.sh.client.events.UserDataAnswer;
import net.java.slee.resource.diameter.sh.client.events.avp.UserIdentityAvp;
import net.java.slee.resource.diameter.sh.server.ShServerMessageFactory;
import net.java.slee.resource.diameter.sh.server.events.ProfileUpdateRequest;
import net.java.slee.resource.diameter.sh.server.events.SubscribeNotificationsRequest;
import net.java.slee.resource.diameter.sh.server.events.UserDataRequest;
import org.apache.log4j.Logger;
import org.jdiameter.api.ApplicationId;
import org.jdiameter.api.Avp;
import org.jdiameter.api.AvpSet;
import org.jdiameter.api.IllegalDiameterStateException;
import org.jdiameter.api.InternalException;
import org.jdiameter.api.Message;
import org.jdiameter.api.Session;
import org.jdiameter.api.Stack;
import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl;
import org.mobicents.slee.resource.diameter.sh.client.DiameterShAvpFactoryImpl;
import org.mobicents.slee.resource.diameter.sh.client.events.ProfileUpdateAnswerImpl;
import org.mobicents.slee.resource.diameter.sh.client.events.PushNotificationRequestImpl;
import org.mobicents.slee.resource.diameter.sh.client.events.SubscribeNotificationsAnswerImpl;
import org.mobicents.slee.resource.diameter.sh.client.events.UserDataAnswerImpl;
/**
*
* Start time:16:56:16 2009-05-23<br>
* Project: diameter-parent<br>
* Implementation of Sh Server Message factory.
*
* @author <a href="mailto:baranowb@gmail.com">Bartosz Baranowski </a>
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
* @see ShServerMessageFactory
*/
public class ShServerMessageFactoryImpl implements ShServerMessageFactory {
protected Session session;
protected Stack stack;
protected DiameterMessageFactoryImpl baseFactory = null;
protected DiameterShAvpFactoryImpl localFactory = null;
private static Logger logger = Logger.getLogger(ShServerMessageFactoryImpl.class);
protected ArrayList<DiameterAvp> avpList = new ArrayList<DiameterAvp>();
public ShServerMessageFactoryImpl(Session session, Stack stack) {
super();
this.session = session;
this.stack = stack;
this.baseFactory = new DiameterMessageFactoryImpl(this.session, this.stack);
}
public ShServerMessageFactoryImpl(Stack stack) {
super();
this.stack = stack;
this.baseFactory = new DiameterMessageFactoryImpl(this.stack);
}
public ShServerMessageFactoryImpl(DiameterMessageFactoryImpl baseMsgFactory, Session session, Stack stack, DiameterShAvpFactory localFactory) {
this.session = session;
this.stack = stack;
this.baseFactory = baseMsgFactory;
this.localFactory = (DiameterShAvpFactoryImpl) localFactory;
}
public ProfileUpdateAnswer createProfileUpdateAnswer(ProfileUpdateRequest request, long resultCode, boolean isExperimentalResult) {
ProfileUpdateAnswer pua = this.createProfileUpdateAnswer(request);
if (isExperimentalResult) {
pua.setExperimentalResult(this.localFactory.getBaseFactory().createExperimentalResult(0, resultCode));
}
else {
pua.setResultCode(resultCode);
}
return pua;
}
public ProfileUpdateAnswer createProfileUpdateAnswer(ProfileUpdateRequest request) {
List<DiameterAvp> avps = new ArrayList<DiameterAvp>();
DiameterAvp sessionIdAvp = null;
try {
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, request.getSessionId());
avps.add(sessionIdAvp);
}
catch (NoSuchAvpException e) {
logger.error("Unable to create Session-Id AVP.", e);
}
if (request.getUserIdentity() != null) {
avps.add(request.getUserIdentity());
}
Message msg = createShMessage(request.getHeader(), avps.toArray(new DiameterAvp[avps.size()]));
ProfileUpdateAnswerImpl answer = new ProfileUpdateAnswerImpl(msg);
if (request.hasRouteRecords()) {
answer.setRouteRecords(request.getRouteRecords());
}
// add more :) ?
//answer.setOriginHost(request.getOriginHost());
addOrigin(answer);
return answer;
}
public PushNotificationRequest createPushNotificationRequest(UserIdentityAvp userIdentity, byte[] userData) {
PushNotificationRequest pnr = this.createPushNotificationRequest();
pnr.setUserIdentity(userIdentity);
pnr.setUserData(new String(userData));
return pnr;
}
public PushNotificationRequest createPushNotificationRequest() {
List<DiameterAvp> avps = new ArrayList<DiameterAvp>();
if (session != null)
try {
DiameterAvp sessionIdAvp = null;
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, session.getSessionId());
avps.add(sessionIdAvp);
}
catch (NoSuchAvpException e) {
logger.error("Unable to create Session-Id AVP.", e);
}
Message msg = createShMessage(null, avps.toArray(new DiameterAvp[avps.size()]));
PushNotificationRequestImpl request = new PushNotificationRequestImpl(msg);
addOrigin(request);
return request;
}
public SubscribeNotificationsAnswer createSubscribeNotificationsAnswer(SubscribeNotificationsRequest request, long resultCode, boolean isExperimentalResult) {
SubscribeNotificationsAnswer sna = this.createSubscribeNotificationsAnswer(request);
if (isExperimentalResult) {
sna.setExperimentalResult(this.localFactory.getBaseFactory().createExperimentalResult(0, resultCode));
}
else {
sna.setResultCode(resultCode);
}
return sna;
}
public SubscribeNotificationsAnswer createSubscribeNotificationsAnswer(SubscribeNotificationsRequest request) {
// Message msg = createShMessage(UserDataAnswer.commandCode, session !=
// null ? session.getSessionId() : null, false);
List<DiameterAvp> avps = new ArrayList<DiameterAvp>();
DiameterAvp sessionIdAvp = null;
try {
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, request.getSessionId());
avps.add(sessionIdAvp);
}
catch (NoSuchAvpException e) {
logger.error("Unable to create Session-Id AVP.", e);
}
if (request.getUserIdentity() != null) {
avps.add(request.getUserIdentity());
}
Message msg = createShMessage(request.getHeader(), avps.toArray(new DiameterAvp[avps.size()]));
SubscribeNotificationsAnswerImpl answer = new SubscribeNotificationsAnswerImpl(msg);
if (request.hasRouteRecords()) {
answer.setRouteRecords(request.getRouteRecords());
}
// add more :) ?
addOrigin(answer);
return answer;
}
public UserDataAnswer createUserDataAnswer(UserDataRequest request, byte[] userData) {
UserDataAnswer uda = this.createUserDataAnswer(request);
uda.setUserData(new String(userData));
return uda;
}
public UserDataAnswer createUserDataAnswer(UserDataRequest request, long resultCode, boolean isExperimentalResult) {
UserDataAnswer uda = this.createUserDataAnswer(request);
if (isExperimentalResult) {
uda.setExperimentalResult(this.localFactory.getBaseFactory().createExperimentalResult(0, resultCode));
}
else {
uda.setResultCode(resultCode);
}
return uda;
}
public UserDataAnswer createUserDataAnswer(UserDataRequest request) {
// Message msg = createShMessage(UserDataAnswer.commandCode, session !=
// null ? session.getSessionId() : null, false);
List<DiameterAvp> avps = new ArrayList<DiameterAvp>();
DiameterAvp sessionIdAvp = null;
try {
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, request.getSessionId());
avps.add(sessionIdAvp);
}
catch (NoSuchAvpException e) {
logger.error("Unable to create Session-Id AVP.", e);
}
if (request.getUserIdentity() != null)
avps.add(request.getUserIdentity());
Message msg = createShMessage(request.getHeader(), avps.toArray(new DiameterAvp[avps.size()]));
UserDataAnswerImpl answer = new UserDataAnswerImpl(msg);
if (request.hasRouteRecords())
answer.setRouteRecords(request.getRouteRecords());
// add more :) ?
addOrigin(answer);
return answer;
}
public DiameterMessageFactory getBaseMessageFactory() {
return this.baseFactory;
}
public List<DiameterAvp> getInnerAvps() {
return this.avpList;
}
public void addAvpToInnerList(DiameterAvp avp) {
// Remove existing occurences...
removeAvpFromInnerList(avp.getCode());
this.avpList.add(avp);
}
public void removeAvpFromInnerList(int code) {
Iterator<DiameterAvp> it = this.avpList.iterator();
while (it.hasNext()) {
if (it.next().getCode() == code) {
it.remove();
}
}
}
// ���������������������
// �� PRIVATE METHODS ��
// ���������������������
private Message createShMessage(DiameterHeader diameterHeader, DiameterAvp[] avps) throws IllegalArgumentException {
// List<DiameterAvp> list = (List<DiameterAvp>) this.avpList.clone();
boolean isRequest = diameterHeader == null;
Message msg = null;
if (!isRequest) {
Message raw = createMessage(diameterHeader, avps);
raw.setProxiable(true);
raw.setRequest(false);
msg = raw;
}
else {
Message raw = createMessage(null, avps);
raw.setProxiable(true);
raw.setRequest(true);
msg = raw;
}
// now now we msut add VendorSpecific?
return msg;
}
protected Message createMessage(DiameterHeader header, DiameterAvp[] avps) throws AvpNotAllowedException {
try {
Message msg = createRawMessage(header);
AvpSet set = msg.getAvps();
for (DiameterAvp avp : avps) {
addAvp(avp, set);
}
if (msg.getAvps().getAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID) == null) {
DiameterAvp avpVendorId = this.localFactory.getBaseFactory().createAvp(Avp.VENDOR_ID, MessageFactory._SH_VENDOR_ID);
DiameterAvp avpAcctApplicationId = this.localFactory.getBaseFactory().createAvp(Avp.ACCT_APPLICATION_ID, MessageFactory._SH_APP_ID);
DiameterAvp vendorSpecific = this.localFactory.getBaseFactory().createAvp(Avp.VENDOR_SPECIFIC_APPLICATION_ID, new DiameterAvp[] { avpVendorId, avpAcctApplicationId });
msg.getAvps().addAvp(vendorSpecific.getCode(), vendorSpecific.byteArrayValue());
}
return msg;
}
catch (Exception e) {
logger.error("Failed to create message.", e);
}
return null;
}
protected Message createRawMessage(DiameterHeader header) {
int commandCode = 0;
long endToEndId = 0;
long hopByHopId = 0;
ApplicationId aid = null;
if (header != null) {
commandCode = header.getCommandCode();
endToEndId = header.getEndToEndId();
hopByHopId = header.getHopByHopId();
aid = ApplicationId.createByAuthAppId(header.getApplicationId());
}
else {
//FIXME: This is the only one ;[
commandCode = PushNotificationRequest.commandCode;
endToEndId = (long) (Math.random()*1000000);
hopByHopId = (long) (Math.random()*1000000)+1;
aid = ApplicationId.createByAuthAppId(_SH_VENDOR_ID, _SH_APP_ID);
}
try {
return stack.getSessionFactory().getNewRawSession().createMessage(commandCode, aid, hopByHopId, endToEndId);
}
catch (InternalException e) {
logger.error("Unable to create Raw Message.", e);
}
catch (IllegalDiameterStateException e) {
logger.error("Unable to create Raw Message.", e);
}
return null;
}
protected void addAvp(DiameterAvp avp, AvpSet set) {
// FIXME: alexandre: Should we look at the types and add them with proper function?
if (avp instanceof GroupedAvp) {
AvpSet avpSet = set.addGroupedAvp(avp.getCode(), avp.getVendorId(), avp.getMandatoryRule() == 1, avp.getProtectedRule() == 1);
DiameterAvp[] groupedAVPs = ((GroupedAvp) avp).getExtensionAvps();
for (DiameterAvp avpFromGroup : groupedAVPs) {
addAvp(avpFromGroup, avpSet);
}
}
else if (avp != null) {
set.addAvp(avp.getCode(), avp.byteArrayValue(), avp.getVendorId(), avp.getMandatoryRule() == 1, avp.getProtectedRule() == 1);
}
}
public void clean() {
session = null;
if (this.baseFactory != null) {
this.baseFactory.clean();
}
}
private void addOrigin(DiameterMessage msg) {
if(!msg.hasOriginHost()) {
msg.setOriginHost(new DiameterIdentity(stack.getMetaData().getLocalPeer().getUri().getFQDN().toString()));
}
if(!msg.hasOriginRealm()) {
msg.setOriginRealm(new DiameterIdentity(stack.getMetaData().getLocalPeer().getRealmName()));
}
}
}