aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri')
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java413
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java112
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java121
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java126
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java93
5 files changed, 865 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java
new file mode 100644
index 0000000..8b964af
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java
@@ -0,0 +1,413 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * The IQ used to control conference recording with Jibri component.
+ *
+ * Start the recording:
+ *
+ * 1. Send Jibri IQ with {@link Action#START} to Jibri.
+ * 2. Jibri replies with RESULT and status {@link Status#PENDING}.
+ * 3. Jibri sends SET IQ with status {@link Status#ON} once recording actually
+ * starts.
+ *
+ * Stop the recording:
+ *
+ * 1. Send Jibri IQ with {@link Action#STOP} to Jibri.
+ * 2. Jibri replies with {@link Status#OFF} immediately if the recording has
+ * been stopped already or sends separate Jibri SET IQ later on if it takes
+ * more time.
+ *
+ * @author lishunyang
+ * @author Pawel Domas
+ */
+public class JibriIq
+ extends IQ
+{
+ /**
+ * Attribute name of "action".
+ */
+ public static final String ACTION_ATTR_NAME = "action";
+
+ /**
+ * XML element name of the Jibri IQ.
+ */
+ public static final String ELEMENT_NAME = "jibri";
+
+ /**
+ * XML namespace of the Jibri IQ.
+ */
+ public static final String NAMESPACE = "http://jitsi.org/protocol/jibri";
+
+ /**
+ * The name of XML attribute which stores the recording status.
+ */
+ static final String STATUS_ATTR_NAME = "status";
+
+ /**
+ * The name of XML attribute which stores the stream id.
+ */
+ static final String STREAM_ID_ATTR_NAME = "streamid";
+
+ /**
+ * The name of XML attribute which stores the name of the conference room to
+ * be recorded.
+ */
+ static final String ROOM_ATTR_NAME = "room";
+
+ /**
+ * Holds the action.
+ */
+ private Action action = Action.UNDEFINED;
+
+ /**
+ * XMPPError stores error details for {@link Status#FAILED}.
+ */
+ private XMPPError error;
+
+ /**
+ * Holds recording status.
+ */
+ private Status status = Status.UNDEFINED;
+
+ /**
+ * The ID of the stream which will be used to record the conference. The
+ * value depends on recording service provider.
+ */
+ private String streamId = null;
+
+ /**
+ * The name of the conference room to be recorded.
+ */
+ private String room = null;
+
+ /**
+ * Returns the value of {@link #STREAM_ID_ATTR_NAME} attribute.
+ * @return a <tt>String</tt> which contains the value of "stream id"
+ * attribute or <tt>null</tt> if empty.
+ */
+ public String getStreamId()
+ {
+ return streamId;
+ }
+
+ /**
+ * Sets the value for {@link #STREAM_ID_ATTR_NAME} attribute.
+ * @param streamId a <tt>String</tt> for the stream id attribute or
+ * <tt>null</tt> to remove it from XML element.
+ */
+ public void setStreamId(String streamId)
+ {
+ this.streamId = streamId;
+ }
+
+ /**
+ * Returns the value of {@link #ROOM_ATTR_NAME} attribute.
+ * @return a <tt>String</tt> which contains the value of the room attribute
+ * or <tt>null</tt> if empty.
+ * @see #room
+ */
+ public String getRoom()
+ {
+ return room;
+ }
+
+ /**
+ * Sets the value for {@link #ROOM_ATTR_NAME} attribute.
+ * @param room a <tt>String</tt> for the room attribute or <tt>null</tt> to
+ * remove it from XML element.
+ * @see #room
+ */
+ public void setRoom(String room)
+ {
+ this.room = room;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getChildElementXML()
+ {
+ StringBuilder xml = new StringBuilder();
+
+ xml.append('<').append(ELEMENT_NAME);
+ xml.append(" xmlns='").append(NAMESPACE).append("' ");
+
+ if (action != Action.UNDEFINED)
+ {
+ printStringAttribute(xml, ACTION_ATTR_NAME, action.toString());
+ }
+
+ if (status != Status.UNDEFINED)
+ {
+ printStringAttribute(xml, STATUS_ATTR_NAME, status.toString());
+ }
+
+ if (room != null)
+ {
+ printStringAttribute(xml, ROOM_ATTR_NAME, room);
+ }
+
+ if (streamId != null)
+ {
+ printStringAttribute(xml, STREAM_ID_ATTR_NAME, streamId);
+ }
+
+ Collection<PacketExtension> extensions = getExtensions();
+ if (extensions.size() > 0)
+ {
+ xml.append(">");
+ for (PacketExtension extension : extensions)
+ {
+ xml.append(extension.toXML());
+ }
+ xml.append("</").append(ELEMENT_NAME).append(">");
+ }
+ else
+ {
+ xml.append("/>");
+ }
+
+ return xml.toString();
+ }
+
+ private void printStringAttribute(
+ StringBuilder xml, String attrName, String attr)
+ {
+ if (!StringUtils.isNullOrEmpty(attr))
+ {
+ attr = org.jivesoftware.smack.util.StringUtils.escapeForXML(attr);
+ xml.append(attrName).append("='")
+ .append(attr).append("' ");
+ }
+ }
+
+ /**
+ * Sets the value of 'action' attribute.
+ *
+ * @param action the value to be set as 'action' attribute of this IQ.
+ */
+ public void setAction(Action action)
+ {
+ this.action = action;
+ }
+
+ /**
+ * Returns the value of 'action' attribute.
+ */
+ public Action getAction()
+ {
+ return action;
+ }
+
+ /**
+ * Sets the value of 'status' attribute.
+ */
+ public void setStatus(Status status)
+ {
+ this.status = status;
+ }
+
+ /**
+ * Returns the value of 'status' attribute.
+ */
+ public Status getStatus()
+ {
+ return status;
+ }
+
+ /**
+ * Sets the <tt>XMPPError</tt> which will provide details about Jibri
+ * failure. It is expected to be set when this IQ's status value is
+ * {@link Status#FAILED}.
+ *
+ * @param error <tt>XMPPError</tt> to be set on this <tt>JibriIq</tt>
+ * instance.
+ */
+ public void setXMPPError(XMPPError error)
+ {
+ this.error = error;
+ }
+
+ /**
+ * Returns {@link XMPPError} with Jibri error details when the status is
+ * {@link Status#FAILED}.
+ */
+ public XMPPError getError()
+ {
+ return error;
+ }
+
+ /**
+ * Enumerative value of attribute "action" in recording extension.
+ *
+ * @author lishunyang
+ * @author Pawel Domas
+ *
+ */
+ public enum Action
+ {
+ /**
+ * Start the recording.
+ */
+ START("start"),
+ /**
+ * Stop the recording.
+ */
+ STOP("stop"),
+ /**
+ * Unknown/uninitialized
+ */
+ UNDEFINED("undefined");
+
+ private String name;
+
+ Action(String name)
+ {
+ this.name = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Action</tt> from given string.
+ *
+ * @param action the string representation of <tt>Action</tt>.
+ *
+ * @return <tt>Action</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Action parse(String action)
+ {
+ if (StringUtils.isNullOrEmpty(action))
+ return UNDEFINED;
+
+ try
+ {
+ return Action.valueOf(action.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+
+ /**
+ * The enumeration of recording status values.
+ */
+ public enum Status
+ {
+ /**
+ * Recording is in progress.
+ */
+ ON("on"),
+
+ /**
+ * Recording stopped.
+ */
+ OFF("off"),
+
+ /**
+ * Starting the recording process.
+ */
+ PENDING("pending"),
+
+ /**
+ * The recorder has failed and the service is retrying on another
+ * instance.
+ */
+ RETRYING("retrying"),
+
+ /**
+ * An error occurred any point during startup, recording or shutdown.
+ */
+ FAILED("failed"),
+
+ /**
+ * There are Jibri instances connected to the system, but all of them
+ * are currently busy.
+ */
+ BUSY("busy"),
+
+ /**
+ * Unknown/uninitialized.
+ */
+ UNDEFINED("undefined");
+
+ /**
+ * Status name holder.
+ */
+ private String name;
+
+ /**
+ * Creates new {@link Status} instance.
+ * @param name a string corresponding to one of {@link Status} values.
+ */
+ Status(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Status</tt> from given string.
+ *
+ * @param status the string representation of <tt>Status</tt>.
+ *
+ * @return <tt>Status</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Status parse(String status)
+ {
+ if (StringUtils.isNullOrEmpty(status))
+ return UNDEFINED;
+
+ try
+ {
+ return Status.valueOf(status.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java
new file mode 100644
index 0000000..155853c
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java
@@ -0,0 +1,112 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.packet.*;
+import org.jivesoftware.smack.provider.*;
+import org.jivesoftware.smack.util.PacketParserUtils;
+
+import org.xmlpull.v1.*;
+
+/**
+ * Parses {@link JibriIq}.
+ */
+public class JibriIqProvider
+ implements IQProvider
+{
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IQ parseIQ(XmlPullParser parser)
+ throws Exception
+ {
+ String namespace = parser.getNamespace();
+
+ // Check the namespace
+ if (!JibriIq.NAMESPACE.equals(namespace))
+ {
+ return null;
+ }
+
+ String rootElement = parser.getName();
+
+ JibriIq iq;
+
+ if (JibriIq.ELEMENT_NAME.equals(rootElement))
+ {
+ iq = new JibriIq();
+
+ String action
+ = parser.getAttributeValue("", JibriIq.ACTION_ATTR_NAME);
+ iq.setAction(JibriIq.Action.parse(action));
+
+ String status
+ = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME);
+ iq.setStatus(JibriIq.Status.parse(status));
+
+ String room
+ = parser.getAttributeValue("", JibriIq.ROOM_ATTR_NAME);
+ if (!StringUtils.isNullOrEmpty(room))
+ iq.setRoom(room);
+
+ String streamId
+ = parser.getAttributeValue("", JibriIq.STREAM_ID_ATTR_NAME);
+ if (!StringUtils.isNullOrEmpty(streamId))
+ iq.setStreamId(streamId);
+ }
+ else
+ {
+ return null;
+ }
+
+ boolean done = false;
+
+ while (!done)
+ {
+ switch (parser.next())
+ {
+ case XmlPullParser.START_TAG:
+ {
+ String name = parser.getName();
+
+ if ("error".equals(name))
+ {
+ XMPPError error = PacketParserUtils.parseError(parser);
+ iq.setXMPPError(error);
+ }
+ break;
+ }
+ case XmlPullParser.END_TAG:
+ {
+ String name = parser.getName();
+
+ if (rootElement.equals(name))
+ {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+
+ return iq;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java
new file mode 100644
index 0000000..e046b68
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java
@@ -0,0 +1,121 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.provider.*;
+
+/**
+ * Status extension included in MUC presence by Jibri to indicate it's status.
+ * One of:
+ * <li>idle</li> - the instance is idle and can be used for recording
+ * <li>busy</li> - the instance is currently recording or doing something very
+ * important and should not be disturbed
+ *
+ *
+ */
+public class JibriStatusPacketExt
+ extends AbstractPacketExtension
+{
+ /**
+ * The namespace of this packet extension.
+ */
+ public static final String NAMESPACE = JibriIq.NAMESPACE;
+
+ /**
+ * XML element name of this packet extension.
+ */
+ public static final String ELEMENT_NAME = "jibri-status";
+
+ private static final String STATUS_ATTRIBUTE = "status";
+
+ /**
+ * Creates new instance of <tt>VideoMutedExtension</tt>.
+ */
+ public JibriStatusPacketExt()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ static public void registerExtensionProvider()
+ {
+ ProviderManager.getInstance().addExtensionProvider(
+ ELEMENT_NAME,
+ NAMESPACE,
+ new DefaultPacketExtensionProvider<JibriStatusPacketExt>(
+ JibriStatusPacketExt.class)
+ );
+ }
+
+ public Status getStatus()
+ {
+ return Status.parse(getAttributeAsString(STATUS_ATTRIBUTE));
+ }
+
+ public void setStatus(Status status)
+ {
+ setAttribute(STATUS_ATTRIBUTE, String.valueOf(status));
+ }
+
+ public enum Status
+ {
+ IDLE("idle"),
+ BUSY("busy"),
+ UNDEFINED("undefined");
+
+ private String name;
+
+ Status(String name)
+ {
+ this.name = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Status</tt> from given string.
+ *
+ * @param status the string representation of <tt>Status</tt>.
+ *
+ * @return <tt>Status</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Status parse(String status)
+ {
+ if (StringUtils.isNullOrEmpty(status))
+ return UNDEFINED;
+
+ try
+ {
+ return Status.valueOf(status.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java
new file mode 100644
index 0000000..13177cf
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java
@@ -0,0 +1,126 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * The packet extension added to Jicofo MUC presence to broadcast current
+ * recording status to all conference participants.
+ *
+ * Status meaning:
+ * <tt>{@link JibriIq.Status#UNDEFINED}</tt> - recording not available
+ * <tt>{@link JibriIq.Status#OFF}</tt> - recording stopped(available to start)
+ * <tt>{@link JibriIq.Status#PENDING}</tt> - starting recording
+ * <tt>{@link JibriIq.Status#ON}</tt> - recording in progress
+ */
+public class RecordingStatus
+ extends AbstractPacketExtension
+{
+ /**
+ * The namespace of this packet extension.
+ */
+ public static final String NAMESPACE = JibriIq.NAMESPACE;
+
+ /**
+ * XML element name of this packet extension.
+ */
+ public static final String ELEMENT_NAME = "jibri-recording-status";
+
+ /**
+ * The name of XML attribute which holds the recording status.
+ */
+ private static final String STATUS_ATTRIBUTE = "status";
+
+ public RecordingStatus()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Returns the value of current recording status stored in it's attribute.
+ * @return one of {@link JibriIq.Status}
+ */
+ public JibriIq.Status getStatus()
+ {
+ String statusAttr = getAttributeAsString(STATUS_ATTRIBUTE);
+
+ return JibriIq.Status.parse(statusAttr);
+ }
+
+ /**
+ * Sets new value for the recording status.
+ * @param status one of {@link JibriIq.Status}
+ */
+ public void setStatus(JibriIq.Status status)
+ {
+ setAttribute(STATUS_ATTRIBUTE, String.valueOf(status));
+ }
+
+ /**
+ * Returns <tt>XMPPError</tt> associated with current
+ * {@link RecordingStatus}.
+ */
+ public XMPPError getError()
+ {
+ XMPPErrorPE errorPe = getErrorPE();
+ return errorPe != null ? errorPe.getError() : null;
+ }
+
+ /**
+ * Gets <tt>{@link XMPPErrorPE}</tt> from the list of child packet
+ * extensions.
+ * @return {@link XMPPErrorPE} or <tt>null</tt> if not found.
+ */
+ private XMPPErrorPE getErrorPE()
+ {
+ List<? extends PacketExtension> errorPe
+ = getChildExtensionsOfType(XMPPErrorPE.class);
+
+ return (XMPPErrorPE) (!errorPe.isEmpty() ? errorPe.get(0) : null);
+ }
+
+ /**
+ * Sets <tt>XMPPError</tt> on this <tt>RecordingStatus</tt>.
+ * @param error <tt>XMPPError</tt> to add error details to this
+ * <tt>RecordingStatus</tt> instance or <tt>null</tt> to have it removed.
+ */
+ public void setError(XMPPError error)
+ {
+ if (error != null)
+ {
+ // Wrap and add XMPPError as packet extension
+ XMPPErrorPE errorPe = getErrorPE();
+ if (errorPe == null)
+ {
+ errorPe = new XMPPErrorPE(error);
+ addChildExtension(errorPe);
+ }
+ errorPe.setError(error);
+ }
+ else
+ {
+ // Remove error PE
+ getChildExtensions().remove(getErrorPE());
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java
new file mode 100644
index 0000000..a72f310
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java
@@ -0,0 +1,93 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * Wraps Smack's <tt>XMPPError</tt> into <tt>PacketExtension</tt>, so that it
+ * can be easily inserted into {@link RecordingStatus}.
+ */
+public class XMPPErrorPE
+ implements PacketExtension
+{
+ /**
+ * <tt>XMPPError</tt> wrapped into this <tt>XMPPErrorPE</tt>.
+ */
+ private XMPPError error;
+
+ /**
+ * Creates new instance of <tt>XMPPErrorPE</tt>.
+ * @param xmppError the instance of <tt>XMPPError</tt> that will be wrapped
+ * by the newly created <tt>XMPPErrorPE</tt>.
+ */
+ public XMPPErrorPE(XMPPError xmppError)
+ {
+ setError(xmppError);
+ }
+
+ /**
+ * Returns the underlying instance of <tt>XMPPError</tt>.
+ */
+ public XMPPError getError()
+ {
+ return error;
+ }
+
+ /**
+ * Sets new instance of <tt>XMPPError</tt> to be wrapped by this
+ * <tt>XMPPErrorPE</tt>.
+ * @param error <tt>XMPPError</tt> that will be wrapped by this
+ * <TT>XMPPErrorPE</TT>.
+ */
+ public void setError(XMPPError error)
+ {
+ Objects.requireNonNull(error, "error");
+
+ this.error = error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getElementName()
+ {
+ return "error";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getNamespace()
+ {
+ return "";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toXML()
+ {
+ return error.toXML();
+ }
+}