package org.mobicents.slee.resource.diameter.cca;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
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.cca.CreditControlAVPFactory;
import net.java.slee.resource.diameter.cca.CreditControlMessageFactory;
import net.java.slee.resource.diameter.cca.events.CreditControlAnswer;
import net.java.slee.resource.diameter.cca.events.CreditControlMessage;
import net.java.slee.resource.diameter.cca.events.CreditControlRequest;
import net.java.slee.resource.diameter.cca.events.avp.CreditControlAVPCodes;
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.Request;
import org.jdiameter.api.Session;
import org.jdiameter.api.Stack;
import org.mobicents.slee.resource.diameter.base.DiameterMessageFactoryImpl;
import org.mobicents.slee.resource.diameter.cca.events.CreditControlAnswerImpl;
import org.mobicents.slee.resource.diameter.cca.events.CreditControlRequestImpl;
/**
* Start time:11:16:00 2008-12-09<br>
* Project: mobicents-diameter-parent<br>
*
* @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
*/
public class CreditControlMessageFactoryImpl implements CreditControlMessageFactory {
protected DiameterMessageFactoryImpl baseFactory = null;
protected Session session;
protected Stack stack;
protected Logger logger = Logger.getLogger(this.getClass());
protected CreditControlAVPFactoryImpl localFactory = null;
protected ArrayList<DiameterAvp> avpList = new ArrayList<DiameterAvp>();
public CreditControlMessageFactoryImpl(DiameterMessageFactoryImpl baseFactory, Session session, Stack stack, CreditControlAVPFactory localFactory)
{
super();
this.baseFactory = baseFactory;
this.session = session;
this.stack = stack;
this.localFactory = (CreditControlAVPFactoryImpl) localFactory;
}
protected final static Set<Integer> ids;
static
{
Set<Integer> _ids = new HashSet<Integer>();
//SessionId
//_ids.add(Avp.SESSION_ID);
//Sub-Session-Id
_ids.add(CreditControlAVPCodes.CC_Sub_Session_Id);
//{ Origin-Host }
//_ids.add(Avp.ORIGIN_HOST);
//{ Origin-Realm }
// _ids.add(Avp.ORIGIN_REALM);
//{ Destination-Realm }
// _ids.add(Avp.DESTINATION_REALM);
//_ids.add(Avp.DESTINATION_HOST);
//{ Auth-Application-Id }
//_ids.add(Avp.AUTH_APPLICATION_ID);
//{ Service-Context-Id }
_ids.add(CreditControlAVPCodes.Service_Context_Id);
//{ CC-Request-Type }
_ids.add(CreditControlAVPCodes.CC_Request_Type);
//{ CC-Request-Number }
_ids.add(CreditControlAVPCodes.CC_Request_Number);
//[ Acct-Multi-Session-Id ]
_ids.add(Avp.ACC_MULTI_SESSION_ID);
//[ Origin-State-Id ]
_ids.add(Avp.ORIGIN_STATE_ID);
//[ Event-Timestamp ]
_ids.add(Avp.EVENT_TIMESTAMP);
//xx*[ Proxy-Info ]
//xx*[ Route-Record ]
ids = Collections.unmodifiableSet(_ids);
}
/*
* (non-Javadoc)
*
* @see net.java.slee.resource.diameter.cca.CreditControlMessageFactory#createCreditControlAnswer
* (net.java.slee.resource.diameter.cca.events.CreditControlRequest)
*/
public CreditControlAnswer createCreditControlAnswer(CreditControlRequest request) {
// Create the answer from the request
CreditControlRequestImpl ccr = (CreditControlRequestImpl) request;
Request req = (Request) ccr.getGenericData();
// Message msg = session.createRequest(req);
DiameterAvp sessionIdAvp = null;
try {
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, this.session.getSessionId());
} catch (NoSuchAvpException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
CreditControlAnswerImpl msg = (CreditControlAnswerImpl) createCreditControlMessage(ccr.getHeader(), new DiameterAvp[] { sessionIdAvp });
// msg.setRequest(false);
// ((MessageImpl)msg.getGenericData()).setEndToEndIdentifier(req.getEndToEndIdentifier());
// ((MessageImpl)msg.getGenericData()).setHopByHopIdentifier(req.getHopByHopIdentifier());
msg.getGenericData().getAvps().removeAvp(DiameterAvpCodes.DESTINATION_HOST);
msg.getGenericData().getAvps().removeAvp(DiameterAvpCodes.DESTINATION_REALM);
msg.getGenericData().getAvps().removeAvp(DiameterAvpCodes.ORIGIN_HOST);
msg.getGenericData().getAvps().removeAvp(DiameterAvpCodes.ORIGIN_REALM);
// Now copy the needed AVPs
DiameterAvp[] messageAvps = request.getAvps();
if (messageAvps != null) {
for (DiameterAvp a : messageAvps) {
try {
if (ids.contains(a.getCode())) {
msg.addAvp(a);
}
} catch (Exception e) {
logger.error("Failed to add AVP to answer. Code[" + a.getCode() + "]", e);
}
}
}
addOrigin(msg);
return msg;
}
/*
* (non-Javadoc)
*
* @see net.java.slee.resource.diameter.cca.CreditControlMessageFactory#createCreditControlRequest()
*/
public CreditControlRequest createCreditControlRequest()
{
CreditControlRequest req = (CreditControlRequest) createCreditControlMessage( null, new DiameterAvp[0] );
req.setOriginRealm(new DiameterIdentity(stack.getMetaData().getLocalPeer().getRealmName()));
req.setOriginHost(new DiameterIdentity(stack.getMetaData().getLocalPeer().getUri().getFQDN().toString()));
if(session!=null)
req.setSessionId(session.getSessionId());
return req;
}
/*
* (non-Javadoc)
*
* @see net.java.slee.resource.diameter.cca.CreditControlMessageFactory#createCreditControlRequest(java.lang.String)
*/
public CreditControlRequest createCreditControlRequest(String sessionId) throws IllegalArgumentException {
try {
DiameterAvp sessionIdAvp;
sessionIdAvp = localFactory.getBaseFactory().createAvp(0, DiameterAvpCodes.SESSION_ID, sessionId);
CreditControlRequest req = (CreditControlRequest) createCreditControlMessage(null, new DiameterAvp[] { sessionIdAvp });
addOrigin(req);
return req;
} catch (NoSuchAvpException e) {
throw new IllegalArgumentException(e);
}
}
/*
* (non-Javadoc)
*
* @see net.java.slee.resource.diameter.cca.CreditControlMessageFactory#
* getBaseMessageFactory()
*/
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 CreditControlMessage createCreditControlMessage(DiameterHeader diameterHeader, DiameterAvp[] avps) throws IllegalArgumentException
{
//List<DiameterAvp> list = (List<DiameterAvp>) this.avpList.clone();
boolean isRequest = diameterHeader == null;
CreditControlMessage msg = null;
if(!isRequest)
{
Message raw=createMessage(diameterHeader,avps);
raw.setProxiable(true);
raw.setRequest(false);
msg = new CreditControlAnswerImpl(raw);
}else
{
Message raw=createMessage(null,avps);
raw.setProxiable(true);
raw.setRequest(true);
msg = new CreditControlRequestImpl(raw);
}
return msg;
}
public Message createMessage(DiameterHeader header, DiameterAvp[] avps) throws AvpNotAllowedException {
try {
Message msg =createRawMessage(header);
AvpSet set = msg.getAvps();
for (DiameterAvp avp : avps)
addAvp(avp, set);
return msg;
}catch(Exception e)
{
e.printStackTrace();
}
return null;
}
protected Message createRawMessage(DiameterHeader header)
{
int commandCode = 0;
long endToEndId = 0;
long hopByHopId = 0;
ApplicationId aid = ApplicationId.createByAuthAppId(_CCA_VENDOR, _CCA_AUTH_APP_ID);
if(header !=null)
{
//Answer
commandCode = header.getCommandCode();
endToEndId = header.getEndToEndId();
hopByHopId = header.getHopByHopId();
//aid = ApplicationId.createByAuthAppId(header.getApplicationId());
}else
{
commandCode = CreditControlRequest.commandCode;
//endToEndId = (long) (Math.random()*1000000);
//hopByHopId = (long) (Math.random()*1000000)+1;
}
try {
if(header!=null)
return stack.getSessionFactory().getNewRawSession().createMessage(commandCode, aid, hopByHopId, endToEndId);
else
return stack.getSessionFactory().getNewRawSession().createMessage(commandCode, aid);
} catch (InternalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalDiameterStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
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);
}
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()));
}
}