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><field value></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><start time></i> <i><stop time></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 }