1/*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2014-2017 Christian Schudt
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25package rocks.xmpp.addr;
26
27import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
28import java.io.Serializable;
29
30/**
31 * Represents the JID as described in <a href="https://tools.ietf.org/html/rfc7622">Extensible Messaging and Presence Protocol (XMPP): Address Format</a>.
32 * <p>
33 * A JID consists of three parts:
34 * <p>
35 * [ localpart "@" ] domainpart [ "/" resourcepart ]
36 * </p>
37 * The easiest way to create a JID is to use the {@link #of(CharSequence)} method:
38 * ```java
39 * Jid jid = Jid.of("juliet@capulet.lit/balcony");
40 * ```
41 * You can then get the parts from it via the respective methods:
42 * ```java
43 * String local = jid.getLocal(); // juliet
44 * String domain = jid.getDomain(); // capulet.lit
45 * String resource = jid.getResource(); // balcony
46 * ```
47 * Implementations of this interface should override <code>equals()</code> and <code>hashCode()</code>, so that different instances with the same value are equal:
48 * ```java
49 * Jid.of("romeo@capulet.lit/balcony").equals(Jid.of("romeo@capulet.lit/balcony")); // true
50 * ```
51 * The default implementation of this class also supports <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>, i.e.
52 * ```java
53 * Jid.of("d'artagnan@musketeers.lit")
54 * ```
55 * is escaped as <code>d\\27artagnan@musketeers.lit</code>.
56 * <p>
57 * Implementations of this interface should be thread-safe and immutable.
58 *
59 * @author Christian Schudt
60 * @see <a href="https://tools.ietf.org/html/rfc7622">RFC 7622 - Extensible Messaging and Presence Protocol (XMPP): Address Format</a>
61 */
62@XmlJavaTypeAdapter(JidAdapter.class)
63public interface Jid extends Comparable<Jid>, Serializable, CharSequence {
64
65 /**
66 * The maximal length of a full JID, which is 3071.
67 * <blockquote>
68 * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.1">3.1. Fundamentals</a></cite></p>
69 * <p>Each allowable portion of a JID (localpart, domainpart, and
70 * resourcepart) is 1 to 1023 octets in length, resulting in a maximum
71 * total size (including the '@' and '/' separators) of 3071 octets.
72 * </p>
73 * </blockquote>
74 * Note that the length is based on bytes, not characters.
75 *
76 * @see #MAX_BARE_JID_LENGTH
77 */
78 int MAX_FULL_JID_LENGTH = 3071;
79
80 /**
81 * The maximal length of a bare JID, which is 2047 (1023 + 1 + 1023).
82 * Note that the length is based on bytes, not characters.
83 *
84 * @see #MAX_FULL_JID_LENGTH
85 */
86 int MAX_BARE_JID_LENGTH = 2047;
87
88 /**
89 * The service discovery feature used for determining support of JID escaping (<code>jid\20escaping</code>).
90 */
91 String ESCAPING_FEATURE = "jid\\20escaping";
92
93 /**
94 * Returns a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
95 *
96 * @param local The local part.
97 * @param domain The domain.
98 * @param resource The resource part.
99 * @return The JID.
100 * @throws NullPointerException If the domain is null.
101 * @throws IllegalArgumentException If the domain, local or resource part are not valid.
102 */
103 static Jid of(CharSequence local, CharSequence domain, CharSequence resource) {
104 return new FullJid(local, domain, resource);
105 }
106
107 /**
108 * Creates a bare JID with only the domain part, e.g. <code>capulet.com</code>
109 *
110 * @param domain The domain.
111 * @return The JID.
112 * @throws NullPointerException If the domain is null.
113 * @throws IllegalArgumentException If the domain or local part are not valid.
114 */
115 static Jid ofDomain(CharSequence domain) {
116 return new FullJid(null, domain, null);
117 }
118
119 /**
120 * Creates a bare JID with a local and domain part, e.g. <code>juliet@capulet.com</code>
121 *
122 * @param local The local part.
123 * @param domain The domain.
124 * @return The JID.
125 * @throws NullPointerException If the domain is null.
126 * @throws IllegalArgumentException If the domain or local part are not valid.
127 */
128 static Jid ofLocalAndDomain(CharSequence local, CharSequence domain) {
129 return new FullJid(local, domain, null);
130 }
131
132 /**
133 * Creates a full JID with a domain and resource part, e.g. <code>capulet.com/balcony</code>
134 *
135 * @param domain The domain.
136 * @param resource The resource part.
137 * @return The JID.
138 * @throws NullPointerException If the domain is null.
139 * @throws IllegalArgumentException If the domain or resource are not valid.
140 */
141 static Jid ofDomainAndResource(CharSequence domain, CharSequence resource) {
142 return new FullJid(null, domain, resource);
143 }
144
145 /**
146 * Creates a JID from an unescaped string. The format must be
147 * <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
148 * The input string will be escaped.
149 *
150 * @param jid The JID.
151 * @return The JID.
152 * @throws NullPointerException If the jid is null.
153 * @throws IllegalArgumentException If the jid could not be parsed or is not valid.
154 * @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
155 */
156 static Jid of(CharSequence jid) {
157 if (jid instanceof Jid) {
158 return (Jid) jid;
159 }
160 return FullJid.of(jid.toString(), false);
161 }
162
163 /**
164 * Creates a JID from a escaped JID string. The format must be
165 * <blockquote><p>[ localpart "@" ] domainpart [ "/" resourcepart ]</p></blockquote>
166 * This method should be used, when parsing JIDs from the XMPP stream.
167 *
168 * @param jid The JID.
169 * @return The JID.
170 * @throws NullPointerException If the jid is null.
171 * @throws IllegalArgumentException If the jid could not be parsed or is not valid.
172 * @see <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>
173 */
174 static Jid ofEscaped(CharSequence jid) {
175 return FullJid.of(jid.toString(), true);
176 }
177
178 /**
179 * Checks if the JID is a full JID.
180 * <blockquote>
181 * <p>The term "full JID" refers to an XMPP address of the form <localpart@domainpart/resourcepart> (for a particular authorized client or device associated with an account) or of the form <domainpart/resourcepart> (for a particular resource or script associated with a server).</p>
182 * </blockquote>
183 *
184 * @return True, if the JID is a full JID; otherwise false.
185 */
186 boolean isFullJid();
187
188 /**
189 * Checks if the JID is a bare JID.
190 * <blockquote>
191 * <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
192 * </blockquote>
193 *
194 * @return True, if the JID is a bare JID; otherwise false.
195 */
196 boolean isBareJid();
197
198 /**
199 * Checks if the JID is a domain JID, i.e. if it has no local part.
200 *
201 * @return True, if the JID is a domain JID, i.e. if it has no local part.
202 */
203 boolean isDomainJid();
204
205 /**
206 * Gets the bare JID representation of this JID, i.e. removes the resource part.
207 * <blockquote>
208 * <p>The term "bare JID" refers to an XMPP address of the form <localpart@domainpart> (for an account at a server) or of the form <domainpart> (for a server).</p>
209 * </blockquote>
210 *
211 * @return The bare JID.
212 * @see #withResource(CharSequence)
213 */
214 Jid asBareJid();
215
216 /**
217 * Creates a new JID with a new local part and the same domain and resource part of the current JID.
218 *
219 * @param local The local part.
220 * @return The JID with a new local part.
221 * @throws IllegalArgumentException If the local is not a valid local part.
222 * @see #withResource(CharSequence)
223 */
224 Jid withLocal(CharSequence local);
225
226 /**
227 * Creates a new full JID with a resource and the same local and domain part of the current JID.
228 *
229 * @param resource The resource.
230 * @return The full JID with a resource.
231 * @throws IllegalArgumentException If the resource is not a valid resource part.
232 * @see #asBareJid()
233 * @see #withLocal(CharSequence)
234 */
235 Jid withResource(CharSequence resource);
236
237 /**
238 * Creates a new JID at a subdomain and at the same domain as this JID.
239 *
240 * @param subdomain The subdomain.
241 * @return The JID at a subdomain.
242 * @throws NullPointerException If subdomain is null.
243 * @throws IllegalArgumentException If subdomain is not a valid subdomain name.
244 */
245 Jid atSubdomain(CharSequence subdomain);
246
247 /**
248 * Gets the local part of the JID, also known as the name or node.
249 * <blockquote>
250 * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.3">3.3. Localpart</a></cite></p>
251 * <p>The localpart of a JID is an optional identifier placed before the
252 * domainpart and separated from the latter by the '@' character.
253 * Typically, a localpart uniquely identifies the entity requesting and
254 * using network access provided by a server (i.e., a local account),
255 * although it can also represent other kinds of entities (e.g., a
256 * chatroom associated with a multi-user chat service [XEP-0045]). The
257 * entity represented by an XMPP localpart is addressed within the
258 * context of a specific domain (i.e., <localpart@domainpart>).</p>
259 * </blockquote>
260 *
261 * @return The local part or null.
262 * @see #getEscapedLocal()
263 */
264 String getLocal();
265
266 /**
267 * Gets the escaped local part of the JID.
268 *
269 * @return The escaped local part or null.
270 * @see #getLocal()
271 * @since 0.8.0
272 */
273 String getEscapedLocal();
274
275 /**
276 * Gets the domain part.
277 * <blockquote>
278 * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.2">3.2. Domainpart</a></cite></p>
279 * <p>The domainpart is the primary identifier and is the only REQUIRED
280 * element of a JID (a mere domainpart is a valid JID). Typically,
281 * a domainpart identifies the "home" server to which clients connect
282 * for XML routing and data management functionality.</p>
283 * </blockquote>
284 *
285 * @return The domain part.
286 */
287 String getDomain();
288
289 /**
290 * Gets the resource part.
291 * <blockquote>
292 * <p><cite><a href="https://tools.ietf.org/html/rfc7622#section-3.4">3.4. Resourcepart</a></cite></p>
293 * <p>The resourcepart of a JID is an optional identifier placed after the
294 * domainpart and separated from the latter by the '/' character. A
295 * resourcepart can modify either a <localpart@domainpart> address or a
296 * mere <domainpart> address. Typically, a resourcepart uniquely
297 * identifies a specific connection (e.g., a device or location) or
298 * object (e.g., an occupant in a multi-user chatroom [XEP-0045])
299 * belonging to the entity associated with an XMPP localpart at a domain
300 * (i.e., <localpart@domainpart/resourcepart>).</p>
301 * </blockquote>
302 *
303 * @return The resource part or null.
304 */
305 String getResource();
306
307 /**
308 * Returns the JID in escaped form as described in <a href="https://xmpp.org/extensions/xep-0106.html">XEP-0106: JID Escaping</a>.
309 *
310 * @return The escaped JID.
311 * @see #toString()
312 */
313 String toEscapedString();
314}