001/**
002 *
003 * Copyright 2013-2014 Georg Lukas, 2020-2021 Florian Schmaus
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.carbons.packet;
018
019import javax.xml.namespace.QName;
020
021import org.jivesoftware.smack.packet.ExtensionElement;
022import org.jivesoftware.smack.packet.Message;
023import org.jivesoftware.smack.packet.MessageBuilder;
024import org.jivesoftware.smack.packet.XmlElement;
025import org.jivesoftware.smack.util.XmlStringBuilder;
026
027import org.jivesoftware.smackx.forward.packet.Forwarded;
028
029/**
030 * Stanza extension for XEP-0280: Message Carbons. The extension
031 * <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a> is
032 * meant to synchronize a message flow to multiple presences of a user.
033 *
034 * <p>
035 * It accomplishes this by wrapping a {@link Forwarded} stanza in a <b>sent</b>
036 * or <b>received</b> element
037 *
038 * @author Georg Lukas
039 */
040public class CarbonExtension implements XmlElement {
041    public static final String NAMESPACE = Carbon.NAMESPACE;
042
043    private final Direction dir;
044    private final Forwarded<Message> fwd;
045
046    /**
047     * Construct a Carbon message extension.
048     *
049     * @param dir Determines if the carbon is being sent/received
050     * @param fwd The forwarded message.
051     */
052    public CarbonExtension(Direction dir, Forwarded<Message> fwd) {
053        this.dir = dir;
054        this.fwd = fwd;
055    }
056
057    /**
058     * Get the direction (sent or received) of the carbon.
059     *
060     * @return the {@link Direction} of the carbon.
061     */
062    public Direction getDirection() {
063        return dir;
064    }
065
066    /**
067     * Get the forwarded packet.
068     *
069     * @return the {@link Forwarded} message contained in this Carbon.
070     */
071    public Forwarded<Message> getForwarded() {
072        return fwd;
073    }
074
075    @Override
076    public String getElementName() {
077        return dir.name();
078    }
079
080    @Override
081    public String getNamespace() {
082        return NAMESPACE;
083    }
084
085    @Override
086    public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
087        XmlStringBuilder xml = new XmlStringBuilder(this);
088        xml.rightAngleBracket();
089        xml.append(fwd.toXML());
090        xml.closeElement(this);
091        return xml;
092    }
093
094    /**
095     * Obtain a Carbon from a message, if available.
096     * <p>
097     * Only {@link Message} instances can contain a Carbon extensions.
098     * </p>
099     *
100     * @param msg Message object to check for carbons
101     *
102     * @return a Carbon if available, null otherwise.
103     * @deprecated use {@link #from(Message)} instead
104     */
105    @Deprecated
106    public static CarbonExtension getFrom(Message msg) {
107        return from(msg);
108    }
109
110    /**
111     * Obtain a Carbon from a message, if available.
112     * <p>
113     * Only {@link Message} instances can contain a Carbon extensions.
114     * </p>
115     *
116     * @param msg Message object to check for carbons
117     *
118     * @return a Carbon if available, null otherwise.
119     */
120    public static CarbonExtension from(Message msg) {
121        CarbonExtension cc = (CarbonExtension) msg.getExtensionElement(Direction.received.name(), NAMESPACE);
122        if (cc == null)
123            cc = (CarbonExtension) msg.getExtensionElement(Direction.sent.name(), NAMESPACE);
124        return cc;
125    }
126
127    /**
128     * Defines the direction of a {@link CarbonExtension} message.
129     */
130    public enum Direction {
131        received,
132        sent
133    }
134
135    /**
136     * Stanza extension indicating that a message may not be carbon-copied.  Adding this
137     * extension to any message will disallow that message from being copied.
138     */
139    public static final class Private implements ExtensionElement {
140        public static final Private INSTANCE = new Private();
141        public static final String ELEMENT = "private";
142        public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
143
144        private Private() {
145        }
146
147        @Override
148        public String getElementName() {
149            return ELEMENT;
150        }
151
152        @Override
153        public String getNamespace() {
154            return NAMESPACE;
155        }
156
157        @Override
158        public String toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
159            return "<" + ELEMENT + " xmlns='" + NAMESPACE + "'/>";
160        }
161
162        /**
163         * Marks a message "private", so that it will not be carbon-copied, by adding private packet
164         * extension to the message.
165         *
166         * @param messageBuilder the message to add the private extension to
167         */
168        public static void addTo(MessageBuilder messageBuilder) {
169            messageBuilder.addExtension(INSTANCE);
170        }
171
172        /**
173         * Marks a message "private", so that it will not be carbon-copied, by adding private packet
174         * extension to the message.
175         *
176         * @param message the message to add the private extension to
177         * @deprecated use {@link #addTo(MessageBuilder)} instead.
178         */
179        // TODO: Remove in Smack 4.6
180        @Deprecated
181        public static void addTo(Message message) {
182            message.addExtension(INSTANCE);
183        }
184    }
185}