diff --git a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Author_Group.adoc b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Author_Group.adoc
index e69de29bb..4f750db0a 100644
--- a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Author_Group.adoc
+++ b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Author_Group.adoc
@@ -0,0 +1,6 @@
+[[_author_group]]
+= Authors
+
+ Amit Bhayani {author-email-amit}
+
+ Grzegorz Figiel ProIDS www.pro-ids.com grzegorz.figiel (at) pro-ids.com
\ No newline at end of file
diff --git a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Chapter-Graceful_Stop.adoc b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Chapter-Graceful_Stop.adoc
new file mode 100644
index 000000000..4c36984e5
--- /dev/null
+++ b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Chapter-Graceful_Stop.adoc
@@ -0,0 +1,13 @@
+[[_ra_graceful_stop]]
+= Graceful Stop
+
+[[_ra_graceful_stop_support]]
+== Graceful Stop support
+
+The RA supports Graceful container stop feature. In Graceful Stop state the RA rejects incoming initial events - it rejects new activities creation.
+
+[[_ra_graceful_stop_response]]
+== Graceful Stop reject support
+
+When the RA is in Graceful Stopping mode the `TC_ABORT` is send as a response for every new `TC_BEGIN` TCAP message.
+`CAP-U-ABORT-REASON: no-reason-given (1)` is used as a u-abort-reason parameter value.
diff --git a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Revision_History.adoc b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Revision_History.adoc
index f45aaf6a0..264ec3205 100644
--- a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Revision_History.adoc
+++ b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/Revision_History.adoc
@@ -1,9 +1,15 @@
-
-:sectnums!:
-
-[appendix]
-= Revision History
-
-
-
+
+:sectnums!:
+
+[appendix]
+= Revision History
+
+.Revision History
+[cols="1,1,1,1", frame="all", options="header"]
+|===
+| Revision number | Date | Author | Description
+| 1.0 | 2012-01-21 | Amit Bhayani | Creation of the {this-platform} JAIN SLEE CAP RA User Guide..
+| 1.1 | 2016-09-29 | Grzegorz Figiel | Graceful Stop feature chapter added.
+|===
+
:sectnums:
\ No newline at end of file
diff --git a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/User_Guide.adoc b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/User_Guide.adoc
index ef9e8648a..7dfe04a2d 100644
--- a/resources/cap/docs/sources-asciidoc/src/main/asciidoc/User_Guide.adoc
+++ b/resources/cap/docs/sources-asciidoc/src/main/asciidoc/User_Guide.adoc
@@ -1,51 +1,57 @@
-= User Guide to {this-platform} {this-application} {this-ra} RA {project-version}
-:doctype: book
-:sectnums:
-:toc: left
-:icons: font
-:experimental:
-:sourcedir: .
-:toclevels: 3
-:sectnumlevels: 4
-
-:leveloffset: 1
-
-include::Book_Info.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::Common_Content/Preface.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::Chapter-Introduction.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::ra-type/Chapter-Resource_Adaptor_Type.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::ra/Chapter-Resource_Adaptor.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::Chapter-Setup.adoc[]
-
-:leveloffset: 0
-
-:leveloffset: 1
-
-include::Revision_History.adoc[]
-
-:leveloffset: 0
+= User Guide to {this-platform} {this-application} {this-ra} RA {project-version}
+:doctype: book
+:sectnums:
+:toc: left
+:icons: font
+:experimental:
+:sourcedir: .
+:toclevels: 3
+:sectnumlevels: 4
+
+:leveloffset: 1
+
+include::Book_Info.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::Common_Content/Preface.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::Chapter-Introduction.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::ra-type/Chapter-Resource_Adaptor_Type.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::ra/Chapter-Resource_Adaptor.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::Chapter-Setup.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::Chapter-Graceful_Stop.adoc[]
+
+:leveloffset: 0
+
+:leveloffset: 1
+
+include::Revision_History.adoc[]
+
+:leveloffset: 0
diff --git a/resources/cap/docs/sources/src/main/resources/en-US/Author_Group.xml b/resources/cap/docs/sources/src/main/resources/en-US/Author_Group.xml
index 9304b23ee..ea498ead2 100644
--- a/resources/cap/docs/sources/src/main/resources/en-US/Author_Group.xml
+++ b/resources/cap/docs/sources/src/main/resources/en-US/Author_Group.xml
@@ -1,5 +1,8 @@
-
%BOOK_ENTITIES;
]>
+
+%BOOK_ENTITIES;
+]>
@@ -7,5 +10,11 @@
Bhayani
&AUTHOR.EMAIL.AMIT;
+
+ Grzegorz
+ Figiel
+ ProIDS www.pro-ids.com
+ grzegorz.figiel (at) pro-ids.com
+
diff --git a/resources/cap/docs/sources/src/main/resources/en-US/Chapter-Graceful_Stop.xml b/resources/cap/docs/sources/src/main/resources/en-US/Chapter-Graceful_Stop.xml
new file mode 100644
index 000000000..3ae094f7f
--- /dev/null
+++ b/resources/cap/docs/sources/src/main/resources/en-US/Chapter-Graceful_Stop.xml
@@ -0,0 +1,18 @@
+
+
+%BOOK_ENTITIES;
+]>
+
+ Graceful Stop
+
+ Graceful Stop support
+ The RA supports Graceful container stop feature. In Graceful Stop state the RA rejects incoming initial events - it rejects new activities creation.
+
+
+ Graceful Stop reject support
+ When the RA is in Graceful Stopping mode the TC_ABORT is send as a response for every new TC_BEGIN TCAP message.
+ CAP-U-ABORT-REASON: no-reason-given (1) is used as a u-abort-reason parameter value.
+
+
+
diff --git a/resources/cap/docs/sources/src/main/resources/en-US/Revision_History.xml b/resources/cap/docs/sources/src/main/resources/en-US/Revision_History.xml
index 05a29b47c..abd7d0d69 100644
--- a/resources/cap/docs/sources/src/main/resources/en-US/Revision_History.xml
+++ b/resources/cap/docs/sources/src/main/resources/en-US/Revision_History.xml
@@ -1,5 +1,8 @@
-
%BOOK_ENTITIES;
]>
+
+%BOOK_ENTITIES;
+]>
Revision History
@@ -18,6 +21,19 @@
+
+ 1.1
+ 2016-09-29
+
+ Grzegorz
+ Figiel
+
+
+
+ Graceful Stop feature chapter added
+
+
+
diff --git a/resources/cap/docs/sources/src/main/resources/en-US/User_Guide.xml b/resources/cap/docs/sources/src/main/resources/en-US/User_Guide.xml
index 04851431e..4f03aa622 100644
--- a/resources/cap/docs/sources/src/main/resources/en-US/User_Guide.xml
+++ b/resources/cap/docs/sources/src/main/resources/en-US/User_Guide.xml
@@ -1,30 +1,33 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/cap/ra/pom.xml b/resources/cap/ra/pom.xml
index df6fa56b3..3aa778a95 100644
--- a/resources/cap/ra/pom.xml
+++ b/resources/cap/ra/pom.xml
@@ -1,5 +1,17 @@
4.0.0
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 1.7
+ 1.7
+
+
+
+
restcomm-slee-ra-cap
@@ -9,6 +21,11 @@
restcomm-slee-ra-cap-ra
+
+
+ 2.8.0-SNAPSHOT
+
+
${project.groupId}
@@ -20,6 +37,11 @@
javolution
${javolution.version}
+
+ org.mobicents.servers.jainslee.core
+ spi
+ ${restcomm.jain.slee.version}
+
diff --git a/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/CAPResourceAdaptor.java b/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/CAPResourceAdaptor.java
index e8d2faf91..030dc47d2 100755
--- a/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/CAPResourceAdaptor.java
+++ b/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/CAPResourceAdaptor.java
@@ -22,30 +22,7 @@
package org.mobicents.slee.resource.cap;
-import javax.naming.InitialContext;
-import javax.slee.Address;
-import javax.slee.AddressPlan;
-import javax.slee.SLEEException;
-import javax.slee.facilities.Tracer;
-import javax.slee.resource.ActivityAlreadyExistsException;
-import javax.slee.resource.ActivityFlags;
-import javax.slee.resource.ActivityHandle;
-import javax.slee.resource.ActivityIsEndingException;
-import javax.slee.resource.ConfigProperties;
-import javax.slee.resource.EventFlags;
-import javax.slee.resource.FailureReason;
-import javax.slee.resource.FireEventException;
-import javax.slee.resource.FireableEventType;
-import javax.slee.resource.IllegalEventException;
-import javax.slee.resource.InvalidConfigurationException;
-import javax.slee.resource.Marshaler;
-import javax.slee.resource.ReceivableService;
-import javax.slee.resource.ResourceAdaptor;
-import javax.slee.resource.ResourceAdaptorContext;
-import javax.slee.resource.SleeEndpoint;
-import javax.slee.resource.StartActivityException;
-import javax.slee.resource.UnrecognizedActivityHandleException;
-
+import org.apache.log4j.Logger;
import org.mobicents.protocols.ss7.cap.api.CAPDialog;
import org.mobicents.protocols.ss7.cap.api.CAPDialogListener;
import org.mobicents.protocols.ss7.cap.api.CAPMessage;
@@ -125,6 +102,7 @@
import org.mobicents.protocols.ss7.cap.api.service.sms.ResetTimerSMSRequest;
import org.mobicents.protocols.ss7.tcap.asn.comp.PAbortCauseType;
import org.mobicents.protocols.ss7.tcap.asn.comp.Problem;
+import org.mobicents.slee.container.resource.GracefullyStopableResourceAdaptor;
import org.mobicents.slee.resource.cap.events.CAPEvent;
import org.mobicents.slee.resource.cap.events.DialogAccept;
import org.mobicents.slee.resource.cap.events.DialogClose;
@@ -205,15 +183,40 @@
import org.mobicents.slee.resource.cap.wrappers.CAPDialogWrapper;
import org.mobicents.slee.resource.cap.wrappers.CAPProviderWrapper;
+import javax.naming.InitialContext;
+import javax.slee.Address;
+import javax.slee.AddressPlan;
+import javax.slee.SLEEException;
+import javax.slee.facilities.Tracer;
+import javax.slee.resource.ActivityAlreadyExistsException;
+import javax.slee.resource.ActivityFlags;
+import javax.slee.resource.ActivityHandle;
+import javax.slee.resource.ActivityIsEndingException;
+import javax.slee.resource.ConfigProperties;
+import javax.slee.resource.EventFlags;
+import javax.slee.resource.FailureReason;
+import javax.slee.resource.FireEventException;
+import javax.slee.resource.FireableEventType;
+import javax.slee.resource.IllegalEventException;
+import javax.slee.resource.InvalidConfigurationException;
+import javax.slee.resource.Marshaler;
+import javax.slee.resource.ReceivableService;
+import javax.slee.resource.ResourceAdaptor;
+import javax.slee.resource.ResourceAdaptorContext;
+import javax.slee.resource.SleeEndpoint;
+import javax.slee.resource.StartActivityException;
+import javax.slee.resource.UnrecognizedActivityHandleException;
+
/**
*
* @author amit bhayani
* @author baranowb
* @author sergey vetyutnev
+ * @author ProIDS sp. z o.o.
*
*/
public class CAPResourceAdaptor implements ResourceAdaptor, CAPDialogListener, CAPServiceCircuitSwitchedCallListener,
- CAPServiceGprsListener, CAPServiceSmsListener {
+ CAPServiceGprsListener, CAPServiceSmsListener, GracefullyStopableResourceAdaptor {
/**
* for all events we are interested in knowing when the event failed to be
* processed
@@ -247,6 +250,8 @@ public class CAPResourceAdaptor implements ResourceAdaptor, CAPDialogListener, C
private String capJndi = null;
private transient static final Address address = new Address(AddressPlan.IP, "localhost");
+ boolean raIsStopping = false;
+
public CAPResourceAdaptor() {
this.capProvider = new CAPProviderWrapper(this);
}
@@ -374,6 +379,7 @@ public void raActive() {
} catch (Exception e) {
this.tracer.severe("Failed to activate CAP RA ", e);
}
+ raIsStopping = false;
}
public void raConfigurationUpdate(ConfigProperties properties) {
@@ -403,9 +409,22 @@ public void raInactive() {
this.realProvider.removeCAPDialogListener(this);
}
- public void raStopping() {
- // TODO Auto-generated method stub
+ /*
+ * (non-Javadoc)
+ * @see org.mobicents.slee.container.resource.GracefullyStopableResourceAdaptor#gracefulRaStopping()
+ */
+ public void gracefulRaStopping() {
+ if (tracer.isFineEnabled()) {
+ tracer.fine("Graceful stop requested for " + this.resourceAdaptorContext.getEntityName());
+ }
+ raStopping();
+ }
+ public void raStopping() {
+ if (tracer.isInfoEnabled()) {
+ tracer.info("raStopping request received for " + this.resourceAdaptorContext.getEntityName());
+ }
+ raIsStopping = true;
}
public void raUnconfigure() {
@@ -520,7 +539,11 @@ private CAPDialogActivityHandle onEvent(String eventName, CAPDialogWrapper dw, C
private CAPDialogActivityHandle onEvent(String eventName, CAPDialogWrapper dw, CAPEvent event, int flags) {
if (dw == null) {
- this.tracer.severe(String.format("Firing %s but CAPDialogWrapper userObject is null", eventName));
+ if(!raIsStopping) {
+ this.tracer.severe(String.format("Skip firing %s as CAPDialogWrapper userObject is null", eventName));
+ } else {
+ this.tracer.fine(String.format("Skip firing %s as CAPDialogWrapper userObject is null, but RA is stopping", eventName));
+ }
return null;
}
@@ -591,6 +614,19 @@ private void handleDialogRequest(CAPDialog capDialog, CAPGprsReferenceNumber cap
this.tracer.fine(String.format("Received onDialogRequest id=%d ", capDialog.getLocalDialogId()));
}
+ if (raIsStopping) {
+ this.tracer.warning(String.format(this.resourceAdaptorContext.getEntityName() +" RA is in graceful shutdown mode, dropping new dialog request (otid=%d, dtid=%d)",
+ capDialog.getRemoteDialogId(),
+ capDialog.getLocalDialogId()));
+ try {
+ capDialog.abort(CAPUserAbortReason.no_reason_given);
+ }
+ catch (Exception ex) {
+ this.tracer.warning("Error while aborting dialog due to raStopping: " + ex.getMessage(), ex);
+ }
+ return;
+ }
+
CAPDialogActivityHandle activityHandle = new CAPDialogActivityHandle(capDialog.getLocalDialogId());
CAPDialogWrapper capDialogWrapper = null;
@@ -630,7 +666,9 @@ public void onDialogRelease(CAPDialog capDialog) {
CAPDialogActivityHandle handle = onEvent(dialogRelease.getEventTypeName(), capDialogWrapper, dialogRelease);
// End Activity
- this.sleeEndpoint.endActivity(handle);
+ if (handle!=null) {
+ this.sleeEndpoint.endActivity(handle);
+ }
} catch (Exception e) {
this.tracer.severe(String.format(
"onDialogRelease : Exception while trying to end activity for CAPDialog=%s", capDialog), e);
@@ -706,6 +744,9 @@ public void onCAPMessage(CAPMessage capMessage) {
@Override
public void onInitialDPRequest(InitialDPRequest ind) {
+ if (this.tracer.isFineEnabled()) {
+ this.tracer.fine(String.format("Received onInitialDPRequest id=%d ", ind.getCAPDialog().getLocalDialogId()));
+ }
CAPDialogCircuitSwitchedCallWrapper capDialogCircuitSwitchedCallWrapper = (CAPDialogCircuitSwitchedCallWrapper) ind
.getCAPDialog().getUserObject();
InitialDPRequestWrapper event = new InitialDPRequestWrapper(capDialogCircuitSwitchedCallWrapper, ind);
diff --git a/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/service/circuitSwitchedCall/wrappers/CAPServiceCircuitSwitchedCallWrapper.java b/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/service/circuitSwitchedCall/wrappers/CAPServiceCircuitSwitchedCallWrapper.java
index 3e92532ee..1aabdd392 100644
--- a/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/service/circuitSwitchedCall/wrappers/CAPServiceCircuitSwitchedCallWrapper.java
+++ b/resources/cap/ra/src/main/java/org/mobicents/slee/resource/cap/service/circuitSwitchedCall/wrappers/CAPServiceCircuitSwitchedCallWrapper.java
@@ -45,7 +45,8 @@ public class CAPServiceCircuitSwitchedCallWrapper implements CAPServiceCircuitSw
protected CAPProviderWrapper capProviderWrapper;
/**
- * @param CAPServiceCircuitSwitchedCall
+ * @param capProviderWrapper
+ * @param capServiceCircuitSwitchedCall
*/
public CAPServiceCircuitSwitchedCallWrapper(CAPProviderWrapper capProviderWrapper, CAPServiceCircuitSwitchedCall capServiceCircuitSwitchedCall) {
this.wrappedCircuitSwitchedCall = capServiceCircuitSwitchedCall;