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.util.Date;
8   import java.util.regex.Matcher;
9   import java.util.regex.Pattern;
10  
11  /**
12   * A <tt>Time</tt> represents a <b>t=<i>&lt;field value&gt;</i></b> field
13   * contained in a SDP message. A time field specifies the start and stop times
14   * for a SDP announce.
15   * 
16   * @since 0.1.0
17   * 
18   * @version 1.0
19   * 
20   * @author <a href="mailto:cdivita@users.sourceforge.net">Claudio Di Vita</a>
21   */
22  public class Time implements Field {
23  
24      /** The class Stream Unique Identifier, SUID */
25      private static final long serialVersionUID = -4529219101991941664L;
26  
27      /**
28       * Constant used to translate between NTP time used in SDP and "native" Java
29       * time. NTP time is defined as the number of seconds relative to midnight,
30       * January 1, 1900 and Java time is measured in number of milliseconds since
31       * midnight, January 1, 1970 UTC (see {@link System#currentTimeMillis()}).
32       * 
33       * <p>
34       * The value of this constant is 2208988800L. It can be used to convert
35       * between NTP and Java time using the following formulas:
36       * </p>
37       * 
38       * <ul>
39       * <li><code>ntpTime = (javaTime/1000) + Time.NTP_CONST;</code></li>
40       * <li><code>javaTime = (ntpTime - Time.NTP_CONST) * 1000;</code></li>
41       * </ul>
42       * 
43       * <p>
44       * The Network Time Protocol (NTP) is defined in <a
45       * href="http://www.ietf.org/rfc/rfc1035.txt">RFC 1305</a>.
46       * </p>
47       */
48      public static final long NTP_CONSTANT = 2208988800L;
49  
50      /** The pattern used to validate the field */
51      private static final Pattern fieldPattern = Pattern.compile("(([1-9](\\d){0,9})|0) (([1-9](\\d){0,9})|0)");
52  
53      /** The pattern used to validate a NTP value */
54      private static final Pattern ntpPattern = Pattern.compile("[1-9](\\d){0,9}");
55  
56      /** The session start time */
57      protected long start;
58  
59      /** The session stop time */
60      protected long stop;
61  
62      /**
63       * Creates a new <tt>Time</tt>. The session start and stop time are set
64       * to zero.
65       */
66      public Time() {
67  
68          super();
69          this.setZero();
70      }
71  
72      /**
73       * Creates a new <tt>Time</tt>.
74       * 
75       * @param start the session start time
76       * 
77       * @param stop the session stop time
78       * 
79       * @throws SDPException if the NTP representation of the session start
80       *         and/or stop time are negative
81       */
82      public Time(final Date start, final Date stop) throws SDPException {
83  
84          super();
85  
86          setStartTime(start);
87          setStopTime(stop);
88      }
89  
90      /**
91       * Creates a new <tt>Time</tt>.
92       * 
93       * @param start the session start time
94       * 
95       * @param stop the session stop time
96       * 
97       * @throws SDPException if the session start or stop time are negative
98       */
99      public Time(final long start, final long stop) throws SDPException {
100 
101         super();
102 
103         setStartTime(start);
104         setStopTime(stop);
105     }
106 
107     /**
108      * Returns a <tt>Date</tt> object for a given NTP date value.
109      * 
110      * @param ntpTime the NTP date value
111      * 
112      * @return a new <tt>Date</tt> instance that represents the given NTP date
113      *         value
114      */
115     public static Date getDateFromNtp(final long ntpTime) {
116 
117         return new Date((ntpTime - NTP_CONSTANT) * 1000);
118     }
119 
120     /**
121      * Transform a <tt>Date</tt> in a long containing the corresponding NTP
122      * value.
123      * 
124      * @param date the <tt>Date</tt> to transform
125      * 
126      * @return the NTP value of the given date
127      */
128     public static long getNTP(final Date date) {
129 
130         long result = 0;
131 
132         if (date == null) {
133             result = -1;
134         }
135         else {
136             result = (date.getTime() / 1000) + NTP_CONSTANT;
137         }
138 
139         return result;
140     }
141 
142     /**
143      * Indicates if a string represents a valid NTP value.
144      * 
145      * @param input the string to test
146      * 
147      * @return <tt>true</tt> if the specified string represents a valid NTP
148      *         value, <tt>false</tt> otherwise
149      */
150     public static boolean isValidNTP(final String input) {
151 
152         return ntpPattern.matcher(input).matches();
153     }
154 
155     /**
156      * Parse an input string and constructs the equivalent time field.
157      * 
158      * @param field the string to parse
159      * 
160      * @return a new <tt>Time</tt> instance
161      * 
162      * @throws SDPParseException if an error occurs while parsing
163      */
164     public static Time parse(final String field) throws SDPParseException {
165 
166         if (!field.startsWith("t=")) {
167             throw new SDPParseException("The string \"" + field + "\" isn't a time field");
168         }
169 
170         Time t = null;
171 
172         /* Create the matcher */
173         Matcher matcher = fieldPattern.matcher(field.substring(2));
174 
175         /* Test */
176         if (matcher.matches()) {
177 
178             try {
179                 /* Create the field */
180                 t = new Time(Long.parseLong(matcher.group(1)), Long.parseLong(matcher.group(4)));
181             }
182             catch (SDPException parseException) {
183                 throw new SDPParseException("The string \"" + field + "\" isn't a valid time field", parseException);
184             }
185         }
186         else {
187             throw new SDPParseException("The string \"" + field + "\" isn't a valid time field");
188         }
189 
190         return t;
191     }
192 
193     /**
194      * Returns a clone of this field.
195      * 
196      * @return a clone of this field
197      */
198     public Object clone() {
199 
200         Time field = new Time();
201         field.start = this.start;
202         field.stop = this.stop;
203 
204         return field;
205     }
206 
207     /**
208      * Returns the start time of the session.
209      * 
210      * @return the start time of the session
211      */
212     public Date getStartTime() {
213 
214         return getDateFromNtp(start);
215     }
216 
217     /**
218      * Returns the stop time of the session.
219      * 
220      * @return the stop time of the session
221      */
222     public Date getStopTime() {
223 
224         return getDateFromNtp(stop);
225     }
226 
227     /**
228      * Returns the type character for the field.
229      * 
230      * @return the field type character: <b>t</b>
231      */
232     public char getType() {
233 
234         return Field.TIME_FIELD;
235     }
236 
237     /**
238      * Returns whether the start and stop times were set to zero (in NTP).
239      * 
240      * @return <tt>true</tt> if the start and stop times are set to zero,
241      *         <tt>false</tt> otherwise
242      */
243     public boolean isZero() {
244 
245         return ((stop == 0) && (start == 0));
246     }
247 
248     /**
249      * Sets the start time of the session.
250      * 
251      * @param start the start time
252      * 
253      * @throws SDPException if the date is <tt>null</tt> or if his NTP
254      *         representation is negative
255      */
256     public void setStartTime(final Date start) throws SDPException {
257 
258         if (start == null) {
259             throw new SDPException("The start time cannot be null");
260         }
261 
262         setStartTime(getNTP(start));
263     }
264 
265     /**
266      * Sets the start time of the session.
267      * 
268      * @param start The start time
269      * 
270      * @throws SDPException If the start time is negative
271      */
272     public void setStartTime(final long start) throws SDPException {
273 
274         if (start < 0) {
275             throw new SDPException("The session start time cannot be negative");
276         }
277 
278         this.start = start;
279     }
280 
281     /**
282      * Sets the stop time of the session.
283      * 
284      * @param stop the stop time
285      * 
286      * @throws SDPException if the date is <tt>null</tt> or his NTP
287      *         representation is negative
288      */
289     public void setStopTime(final Date stop) throws SDPException {
290 
291         if (stop == null) {
292             throw new SDPException("The stop time cannot be null");
293         }
294 
295         setStopTime(getNTP(stop));
296     }
297 
298     /**
299      * Sets the stop time of the session.
300      * 
301      * @param stop the stop time
302      * 
303      * @throws SDPException if the stop time is negative
304      */
305     public void setStopTime(final long stop) throws SDPException {
306 
307         if (stop < 0) {
308             throw new SDPException("The session stop time cannot be negative");
309         }
310 
311         this.stop = stop;
312     }
313 
314     /**
315      * Sets the start and stop times to zero (in NTP).
316      */
317     public void setZero() {
318 
319         this.start = 0;
320         this.stop = 0;
321     }
322 
323     /**
324      * Returns a string representation of the field. The representation has the
325      * form: <b>t=<i>&lt;start time&gt;</i> <i>&lt;stop time&gt;</i></b>.
326      * 
327      * @return the string representation of the field
328      */
329     public String toString() {
330 
331         StringBuffer result = new StringBuffer(getType() + "=");
332         result.append(start);
333         result.append(" ");
334         result.append(stop);
335 
336         return result.toString();
337     }
338 }