1 /*
2 * jSDP: A Java implementation of SDP protocol Copyright (C) 2007 Claudio Di
3 * Vita
4 */
5 package net.sourceforge.jsdp;
6
7 import java.net.InetAddress;
8 import java.net.UnknownHostException;
9 import java.util.Date;
10 import java.util.regex.Matcher;
11 import java.util.regex.Pattern;
12
13 import net.sourceforge.jsdp.util.Address;
14
15 /**
16 * An <tt>Origin</tt> represents an <b>o=<i><field value></i></b>
17 * field contained in a SDP message. The origin field identifies the originator
18 * of the session, that is not necessarily the same entity who is involved in
19 * the session. This field contains:
20 * <ul>
21 * <li>The name of the user originating the session</li>
22 * <li>An unique session identifier</li>
23 * <li>An unique version for the session</li>
24 * <li>The network type</li>
25 * <li>The ddress type</li>
26 * <li>The address of the originator</li>
27 * </ul>
28 * <p>
29 * These fields should uniquely identify the session.
30 * </p>
31 *
32 * @since 0.1.0
33 *
34 * @version 1.0
35 *
36 * @author <a href="mailto:cdivita@users.sourceforge.net">Claudio Di Vita</a>
37 */
38 public class Origin implements Field {
39
40 /** The class Stream Unique Identifier, SUID */
41 private static final long serialVersionUID = 8892230839201408790L;
42
43 /** The pattern used to parse the field */
44 private static final Pattern fieldPattern = Pattern.compile("([^ ]+) (\\d+) (\\d+) IN (IP4|IP6) (([^ ]+))");
45
46 /** The pattern used to validate the user name */
47 private static final Pattern userPattern = Pattern.compile("[\\w'-\\./:?#\\$&\\*;=@\\[\\]\\^_`\\{\\}\\|\\+\\~]+");
48
49 /** The name of the session originator */
50 private String user;
51
52 /** The session identifier */
53 private long sessionID;
54
55 /** The session version */
56 private long sessionVersion;
57
58 /** The originator's host information */
59 private Address address;
60
61 /**
62 * Creates a new <tt>Origin</tt>. The values are sets as follows:
63 * <p>
64 * <code>
65 * o=<i><user> <current time as NTP> <current time as NTP> <localhost name></i><br/>
66 * </code>
67 * </p>
68 * The <i><user></i> value is the name of the OS user that invokes
69 * this method.
70 *
71 * @throws SDPException if no IP address for the local host could be found,
72 * or the current user name contains characters that are not allowed
73 */
74 public Origin() throws SDPException {
75
76 super();
77
78 setUser(System.getProperty("user.name"));
79
80 this.sessionID = Time.getNTP(new Date());
81 this.sessionVersion = Time.getNTP(new Date());
82
83 try {
84 this.address = new Address(InetAddress.getLocalHost().getHostName());
85 }
86 catch (UnknownHostException noLocalHost) {
87 throw new SDPException("Cannot find the localhost name");
88 }
89 }
90
91 /**
92 * Creates a new <tt>Origin</tt>. The session id was generated
93 * automatically using NTP and the user value is set with the name of the OS
94 * user that invokes this constructor.
95 *
96 * @param sessionVersion the session version
97 *
98 * @param address the session originator host address
99 *
100 * @throws SDPException if one or more parameter provided are not valid
101 */
102 public Origin(final long sessionVersion, final String address) throws SDPException {
103
104 super();
105
106 setUser(System.getProperty("user.name"));
107 this.sessionID = Time.getNTP(new Date());
108 setSessionVersion(sessionVersion);
109
110 this.address = new Address(address);
111 }
112
113 /**
114 * Creates a new <tt>Origin</tt>. This constructor is used to implement
115 * the {@link #clone()} method, because this class has a default constructor
116 * that performs some operations that aren't required while cloning a field.
117 *
118 * @param origin the <tt>Origin</tt> to clone
119 */
120 protected Origin(final Origin origin) {
121
122 super();
123
124 this.user = new String(origin.user);
125 this.sessionID = origin.sessionID;
126 this.sessionVersion = origin.sessionVersion;
127 this.address = (Address) origin.address.clone();
128 }
129
130 /**
131 * Creates a new <tt>Origin</tt>. Both session identifier and session
132 * version were generated automatically using NTP and the user value is set
133 * with the name of the OS user that invokes this constructor.
134 *
135 * @param address the session originator host address
136 *
137 * @throws SDPException if the address are not valid
138 */
139 public Origin(final String address) throws SDPException {
140
141 super();
142
143 setUser(System.getProperty("user.name"));
144 this.sessionID = Time.getNTP(new Date());
145 this.sessionVersion = Time.getNTP(new Date());
146
147 this.address = new Address(address);
148 }
149
150 /**
151 * Creates a new <tt>Origin</tt>.
152 *
153 * @param user the name of the session originator
154 *
155 * @param sessionID the session identifier
156 *
157 * @param sessionVersion the session version
158 *
159 * @param address the session originator host address
160 *
161 * @throws SDPException if one or more parameter provided are not valid
162 */
163 public Origin(final String user, final long sessionID, final long sessionVersion, final String address) throws SDPException {
164
165 super();
166
167 setUser(user);
168 setSessionID(sessionID);
169 setSessionVersion(sessionVersion);
170
171 this.address = new Address(address);
172 }
173
174 /**
175 * Creates a new <tt>Origin</tt>.
176 *
177 * @param user the name of the session originator
178 *
179 * @param sessionVersion the session version
180 *
181 * @param address the session originator host address
182 *
183 * @throws SDPException if one or more parameter provided are not valid
184 */
185 public Origin(final String user, final long sessionVersion, final String address) throws SDPException {
186
187 super();
188
189 setUser(user);
190 this.sessionID = Time.getNTP(new Date());
191 setSessionVersion(sessionVersion);
192
193 this.address = new Address(address);
194 }
195
196 /**
197 * Parse an input string and constructs the equivalent origin field.
198 *
199 * @param field the string to parse
200 *
201 * @return a new <tt>Origin</tt> instance
202 *
203 * @throws SDPParseException if an error occurs while parsing
204 */
205 public static Origin parse(final String field) throws SDPParseException {
206
207 if (!field.startsWith("o=")) {
208 throw new SDPParseException("The string \"" + field + "\" isn't an origin field");
209 }
210
211 Origin o = null;
212
213 /* Create the matcher */
214 Matcher matcher = fieldPattern.matcher(field.substring(2));
215
216 /* Test */
217 if (matcher.matches()) {
218 try {
219
220 String type = matcher.group(4);
221 o = new Origin(matcher.group(1), Long.parseLong(matcher.group(2)), Long.parseLong(matcher.group(3)), matcher.group(5));
222
223 if (!o.getAddressType().equals(type)) {
224 throw new SDPParseException("The address " + o.getAddress() + " isn't an " + type + " address");
225 }
226 }
227 catch (SDPException parseException) {
228 throw new SDPParseException("The string \"" + field + "\" isn't a valid origin field", parseException);
229 }
230 }
231 else {
232 throw new SDPParseException("The string \"" + field + "\" isn't a valid origin field");
233 }
234
235 return o;
236 }
237
238 /**
239 * Returns a clone of this field.
240 *
241 * @return a clone of this field
242 */
243 public Object clone() {
244
245 return new Origin(this);
246 }
247
248 /**
249 * Returns the session originator host address.
250 *
251 * @return the session originator host address
252 */
253 public String getAddress() {
254
255 return address.getAddress();
256 }
257
258 /**
259 * Returns the address type.
260 *
261 * @return the address type
262 */
263 public String getAddressType() {
264
265 return address.getAddressType();
266 }
267
268 /**
269 * Returns the network type.
270 *
271 * @return the network type. Because SDP was used in Internet, this method
272 * always returns <b>IN</b>
273 */
274 public String getNetType() {
275
276 return Address.IN;
277 }
278
279 /**
280 * Returns the session identifier.
281 *
282 * @return the session identifier
283 */
284 public long getSessionID() {
285
286 return sessionID;
287 }
288
289 /**
290 * Returns the session version.
291 *
292 * @return the session version
293 */
294 public long getSessionVersion() {
295
296 return sessionVersion;
297 }
298
299 /**
300 * Returns the type character for the field
301 *
302 * @return The field type character: <b>o</b>
303 */
304 public char getType() {
305
306 return Field.ORIGIN_FIELD;
307 }
308
309 /**
310 * Returns the name of the session originator.
311 *
312 * @return the session originator's name
313 */
314 public String getUser() {
315
316 return user;
317 }
318
319 /**
320 * Sets the session originator host address.
321 *
322 * @param address the session originator host address
323 *
324 * @throws SDPException if the address is not valid
325 */
326 public void setAddress(final String address) throws SDPException {
327
328 this.address.setAddress(address);
329 }
330
331 /**
332 * Sets the session identifier.
333 *
334 * @param sessionID the session identifier
335 *
336 * @throws SDPException if the session identifier is negative
337 */
338 public void setSessionID(final long sessionID) throws SDPException {
339
340 if (sessionID < 0) {
341 throw new SDPException("Session id cannot be negative");
342 }
343
344 this.sessionID = sessionID;
345 }
346
347 /**
348 * Sets the session version.
349 *
350 * @param sessionVersion the session version
351 *
352 * @throws SDPException if the session version is negative
353 */
354 public void setSessionVersion(final long sessionVersion) throws SDPException {
355
356 if (sessionVersion < 0) {
357 throw new SDPException("Session version cannot be negative");
358 }
359
360 this.sessionVersion = sessionVersion;
361 }
362
363 /**
364 * Sets the name of the session originator.
365 *
366 * @param user the name of the session creator
367 *
368 * @throws SDPException if the name is not valid (for example it contains
369 * spaces)
370 */
371 public void setUser(final String user) throws SDPException {
372
373 if (!userPattern.matcher(user).matches()) {
374 throw new SDPException("Invalid user name: " + user);
375 }
376
377 this.user = user;
378 }
379
380 /**
381 * Returns a string representation of the field. The representation has the
382 * form: <b><i><type></i>=<i><value></i></b>.
383 *
384 * @return the string representation of the field
385 */
386 public String toString() {
387
388 StringBuffer result = new StringBuffer(getType() + "=");
389
390 result.append(this.user + " ");
391 result.append(this.sessionID + " ");
392 result.append(this.sessionVersion);
393 result.append(" IN ");
394 result.append(address.toString());
395
396 return result.toString();
397 }
398 }