View Javadoc

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>&lt;field value&gt;</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>&lt;user&gt; &lt;current time as NTP&gt; &lt;current time as NTP&gt; &lt;localhost name&gt;</i><br/>
66       * </code>
67       * </p>
68       * The <i>&lt;user&gt;</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>&lt;type&gt;</i>=<i>&lt;value&gt;</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 }