1// Copyright 2003-2005 Arthur van Hoff, Rick Blair
2// Licensed under Apache License version 2.0
3// Original license LGPL
4package javax.jmdns;
5
6import java.net.Inet4Address;
7import java.net.Inet6Address;
8import java.net.InetAddress;
9import java.util.Enumeration;
10import java.util.Map;
11
12import javax.jmdns.impl.ServiceInfoImpl;
13
14/**
15 * <p>
16 * The fully qualified service name is build using up to 5 components with the following structure:
17 *
18 * <pre>
19 *            &lt;app&gt;.&lt;protocol&gt;.&lt;servicedomain&gt;.&lt;parentdomain&gt;.<br/>
20 * &lt;Instance&gt;.&lt;app&gt;.&lt;protocol&gt;.&lt;servicedomain&gt;.&lt;parentdomain&gt;.<br/>
21 * &lt;sub&gt;._sub.&lt;app&gt;.&lt;protocol&gt;.&lt;servicedomain&gt;.&lt;parentdomain&gt;.
22 * </pre>
23 *
24 * <ol>
25 * <li>&lt;servicedomain&gt;.&lt;parentdomain&gt;: This is the domain scope of the service typically "local.", but this can also be something similar to "in-addr.arpa." or "ip6.arpa."</li>
26 * <li>&lt;protocol&gt;: This is either "_tcp" or "_udp"</li>
27 * <li>&lt;app&gt;: This define the application protocol. Typical example are "_http", "_ftp", etc.</li>
28 * <li>&lt;Instance&gt;: This is the service name</li>
29 * <li>&lt;sub&gt;: This is the subtype for the application protocol</li>
30 * </ol>
31 * </p>
32 */
33public abstract class ServiceInfo implements Cloneable {
34
35    /**
36     * This is the no value text byte. According top the specification it is one byte with 0 value.
37     */
38    public static final byte[] NO_VALUE = new byte[0];
39
40    /**
41     * Fields for the fully qualified map.
42     */
43    public enum Fields {
44        /**
45         * Domain Field.
46         */
47        Domain,
48        /**
49         * Protocol Field.
50         */
51        Protocol,
52        /**
53         * Application Field.
54         */
55        Application,
56        /**
57         * Instance Field.
58         */
59        Instance,
60        /**
61         * Subtype Field.
62         */
63        Subtype
64    }
65
66    /**
67     * Construct a service description for registering with JmDNS.
68     *
69     * @param type
70     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
71     * @param name
72     *            unqualified service instance name, such as <code>foobar</code>
73     * @param port
74     *            the local port on which the service runs
75     * @param text
76     *            string describing the service
77     * @return new service info
78     */
79    public static ServiceInfo create(final String type, final String name, final int port, final String text) {
80        return new ServiceInfoImpl(type, name, "", port, 0, 0, false, text);
81    }
82
83    /**
84     * Construct a service description for registering with JmDNS.
85     *
86     * @param type
87     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
88     * @param name
89     *            unqualified service instance name, such as <code>foobar</code>
90     * @param subtype
91     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
92     * @param port
93     *            the local port on which the service runs
94     * @param text
95     *            string describing the service
96     * @return new service info
97     */
98    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final String text) {
99        return new ServiceInfoImpl(type, name, subtype, port, 0, 0, false, text);
100    }
101
102    /**
103     * Construct a service description for registering with JmDNS.
104     *
105     * @param type
106     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
107     * @param name
108     *            unqualified service instance name, such as <code>foobar</code>
109     * @param port
110     *            the local port on which the service runs
111     * @param weight
112     *            weight of the service
113     * @param priority
114     *            priority of the service
115     * @param text
116     *            string describing the service
117     * @return new service info
118     */
119    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final String text) {
120        return new ServiceInfoImpl(type, name, "", port, weight, priority, false, text);
121    }
122
123    /**
124     * Construct a service description for registering with JmDNS.
125     *
126     * @param type
127     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
128     * @param name
129     *            unqualified service instance name, such as <code>foobar</code>
130     * @param subtype
131     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
132     * @param port
133     *            the local port on which the service runs
134     * @param weight
135     *            weight of the service
136     * @param priority
137     *            priority of the service
138     * @param text
139     *            string describing the service
140     * @return new service info
141     */
142    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final String text) {
143        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, false, text);
144    }
145
146    /**
147     * Construct a service description for registering with JmDNS. The properties hashtable must map property names to either Strings or byte arrays describing the property values.
148     *
149     * @param type
150     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
151     * @param name
152     *            unqualified service instance name, such as <code>foobar</code>
153     * @param port
154     *            the local port on which the service runs
155     * @param weight
156     *            weight of the service
157     * @param priority
158     *            priority of the service
159     * @param props
160     *            properties describing the service
161     * @return new service info
162     */
163    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final Map<String, ?> props) {
164        return new ServiceInfoImpl(type, name, "", port, weight, priority, false, props);
165    }
166
167    /**
168     * Construct a service description for registering with JmDNS. The properties hashtable must map property names to either Strings or byte arrays describing the property values.
169     *
170     * @param type
171     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
172     * @param name
173     *            unqualified service instance name, such as <code>foobar</code>
174     * @param subtype
175     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
176     * @param port
177     *            the local port on which the service runs
178     * @param weight
179     *            weight of the service
180     * @param priority
181     *            priority of the service
182     * @param props
183     *            properties describing the service
184     * @return new service info
185     */
186    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final Map<String, ?> props) {
187        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, false, props);
188    }
189
190    /**
191     * Construct a service description for registering with JmDNS.
192     *
193     * @param type
194     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
195     * @param name
196     *            unqualified service instance name, such as <code>foobar</code>
197     * @param port
198     *            the local port on which the service runs
199     * @param weight
200     *            weight of the service
201     * @param priority
202     *            priority of the service
203     * @param text
204     *            bytes describing the service
205     * @return new service info
206     */
207    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final byte[] text) {
208        return new ServiceInfoImpl(type, name, "", port, weight, priority, false, text);
209    }
210
211    /**
212     * Construct a service description for registering with JmDNS.
213     *
214     * @param type
215     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
216     * @param name
217     *            unqualified service instance name, such as <code>foobar</code>
218     * @param subtype
219     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
220     * @param port
221     *            the local port on which the service runs
222     * @param weight
223     *            weight of the service
224     * @param priority
225     *            priority of the service
226     * @param text
227     *            bytes describing the service
228     * @return new service info
229     */
230    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final byte[] text) {
231        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, false, text);
232    }
233
234    /**
235     * Construct a service description for registering with JmDNS.
236     *
237     * @param type
238     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
239     * @param name
240     *            unqualified service instance name, such as <code>foobar</code>
241     * @param port
242     *            the local port on which the service runs
243     * @param weight
244     *            weight of the service
245     * @param priority
246     *            priority of the service
247     * @param persistent
248     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
249     * @param text
250     *            string describing the service
251     * @return new service info
252     */
253    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final boolean persistent, final String text) {
254        return new ServiceInfoImpl(type, name, "", port, weight, priority, persistent, text);
255    }
256
257    /**
258     * Construct a service description for registering with JmDNS.
259     *
260     * @param type
261     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
262     * @param name
263     *            unqualified service instance name, such as <code>foobar</code>
264     * @param subtype
265     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
266     * @param port
267     *            the local port on which the service runs
268     * @param weight
269     *            weight of the service
270     * @param priority
271     *            priority of the service
272     * @param persistent
273     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
274     * @param text
275     *            string describing the service
276     * @return new service info
277     */
278    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final boolean persistent, final String text) {
279        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, persistent, text);
280    }
281
282    /**
283     * Construct a service description for registering with JmDNS. The properties hashtable must map property names to either Strings or byte arrays describing the property values.
284     *
285     * @param type
286     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
287     * @param name
288     *            unqualified service instance name, such as <code>foobar</code>
289     * @param port
290     *            the local port on which the service runs
291     * @param weight
292     *            weight of the service
293     * @param priority
294     *            priority of the service
295     * @param persistent
296     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
297     * @param props
298     *            properties describing the service
299     * @return new service info
300     */
301    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final boolean persistent, final Map<String, ?> props) {
302        return new ServiceInfoImpl(type, name, "", port, weight, priority, persistent, props);
303    }
304
305    /**
306     * Construct a service description for registering with JmDNS. The properties hashtable must map property names to either Strings or byte arrays describing the property values.
307     *
308     * @param type
309     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
310     * @param name
311     *            unqualified service instance name, such as <code>foobar</code>
312     * @param subtype
313     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
314     * @param port
315     *            the local port on which the service runs
316     * @param weight
317     *            weight of the service
318     * @param priority
319     *            priority of the service
320     * @param persistent
321     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
322     * @param props
323     *            properties describing the service
324     * @return new service info
325     */
326    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final boolean persistent, final Map<String, ?> props) {
327        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, persistent, props);
328    }
329
330    /**
331     * Construct a service description for registering with JmDNS.
332     *
333     * @param type
334     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
335     * @param name
336     *            unqualified service instance name, such as <code>foobar</code>
337     * @param port
338     *            the local port on which the service runs
339     * @param weight
340     *            weight of the service
341     * @param priority
342     *            priority of the service
343     * @param persistent
344     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
345     * @param text
346     *            bytes describing the service
347     * @return new service info
348     */
349    public static ServiceInfo create(final String type, final String name, final int port, final int weight, final int priority, final boolean persistent, final byte[] text) {
350        return new ServiceInfoImpl(type, name, "", port, weight, priority, persistent, text);
351    }
352
353    /**
354     * Construct a service description for registering with JmDNS.
355     *
356     * @param type
357     *            fully qualified service type name, such as <code>_http._tcp.local.</code>.
358     * @param name
359     *            unqualified service instance name, such as <code>foobar</code>
360     * @param subtype
361     *            service subtype see draft-cheshire-dnsext-dns-sd-06.txt chapter 7.1 Selective Instance Enumeration
362     * @param port
363     *            the local port on which the service runs
364     * @param weight
365     *            weight of the service
366     * @param priority
367     *            priority of the service
368     * @param persistent
369     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
370     * @param text
371     *            bytes describing the service
372     * @return new service info
373     */
374    public static ServiceInfo create(final String type, final String name, final String subtype, final int port, final int weight, final int priority, final boolean persistent, final byte[] text) {
375        return new ServiceInfoImpl(type, name, subtype, port, weight, priority, persistent, text);
376    }
377
378    /**
379     * Construct a service description for registering with JmDNS. The properties hashtable must map property names to either Strings or byte arrays describing the property values.
380     *
381     * @param qualifiedNameMap
382     *            dictionary of values to build the fully qualified service name. Mandatory keys are Application and Instance. The Domain default is local, the Protocol default is tcp and the subtype default is none.
383     * @param port
384     *            the local port on which the service runs
385     * @param weight
386     *            weight of the service
387     * @param priority
388     *            priority of the service
389     * @param persistent
390     *            if <code>true</code> ServiceListener.resolveService will be called whenever new new information is received.
391     * @param props
392     *            properties describing the service
393     * @return new service info
394     */
395    public static ServiceInfo create(final Map<Fields, String> qualifiedNameMap, final int port, final int weight, final int priority, final boolean persistent, final Map<String, ?> props) {
396        return new ServiceInfoImpl(qualifiedNameMap, port, weight, priority, persistent, props);
397    }
398
399    /**
400     * Returns true if the service info is filled with data.
401     *
402     * @return <code>true</code> if the service info has data, <code>false</code> otherwise.
403     */
404    public abstract boolean hasData();
405
406    /**
407     * Fully qualified service type name, such as <code>_http._tcp.local.</code>
408     *
409     * @return service type name
410     */
411    public abstract String getType();
412
413    /**
414     * Fully qualified service type name with the subtype if appropriate, such as <code>_printer._sub._http._tcp.local.</code>
415     *
416     * @return service type name
417     */
418    public abstract String getTypeWithSubtype();
419
420    /**
421     * Unqualified service instance name, such as <code>foobar</code> .
422     *
423     * @return service name
424     */
425    public abstract String getName();
426
427    /**
428     * The key is used to retrieve service info in hash tables.<br/>
429     * The key is the lower case qualified name.
430     *
431     * @return the key
432     */
433    public abstract String getKey();
434
435    /**
436     * Fully qualified service name, such as <code>foobar._http._tcp.local.</code> .
437     *
438     * @return qualified service name
439     */
440    public abstract String getQualifiedName();
441
442    /**
443     * Get the name of the server.
444     *
445     * @return server name
446     */
447    public abstract String getServer();
448
449    /**
450     * Returns the host IP address string in textual presentation.<br/>
451     * <b>Note:</b> This can be either an IPv4 or an IPv6 representation.
452     *
453     * @return the host raw IP address in a string format.
454     * @deprecated since 3.2.3
455     * @see #getHostAddresses()
456     */
457    @Deprecated
458    public abstract String getHostAddress();
459
460    /**
461     * Returns the host IP addresses string in textual presentation.
462     *
463     * @return list of host raw IP address in a string format.
464     */
465    public abstract String[] getHostAddresses();
466
467    /**
468     * Get the host address of the service.<br/>
469     *
470     * @return host Internet address
471     * @deprecated since 3.1.8
472     * @see #getInetAddresses()
473     */
474    @Deprecated
475    public abstract InetAddress getAddress();
476
477    /**
478     * Get the InetAddress of the service. This will return the IPv4 if it exist, otherwise it return the IPv6 if set.<br/>
479     * <b>Note:</b> This return null if the service IP address cannot be resolved.
480     *
481     * @return Internet address
482     * @deprecated since 3.2.3
483     * @see #getInetAddresses()
484     */
485    @Deprecated
486    public abstract InetAddress getInetAddress();
487
488    /**
489     * Get the IPv4 InetAddress of the service.<br/>
490     * <b>Note:</b> This return null if the service IPv4 address cannot be resolved.
491     *
492     * @return Internet address
493     * @deprecated since 3.2.3
494     * @see #getInet4Addresses()
495     */
496    @Deprecated
497    public abstract Inet4Address getInet4Address();
498
499    /**
500     * Get the IPv6 InetAddress of the service.<br/>
501     * <b>Note:</b> This return null if the service IPv6 address cannot be resolved.
502     *
503     * @return Internet address
504     * @deprecated since 3.2.3
505     * @see #getInet6Addresses()
506     */
507    @Deprecated
508    public abstract Inet6Address getInet6Address();
509
510    /**
511     * Returns a list of all InetAddresses that can be used for this service.
512     * <p>
513     * In a multi-homed environment service info can be associated with more than one address.
514     * </p>
515     *
516     * @return list of InetAddress objects
517     */
518    public abstract InetAddress[] getInetAddresses();
519
520    /**
521     * Returns a list of all IPv4 InetAddresses that can be used for this service.
522     * <p>
523     * In a multi-homed environment service info can be associated with more than one address.
524     * </p>
525     *
526     * @return list of InetAddress objects
527     */
528    public abstract Inet4Address[] getInet4Addresses();
529
530    /**
531     * Returns a list of all IPv6 InetAddresses that can be used for this service.
532     * <p>
533     * In a multi-homed environment service info can be associated with more than one address.
534     * </p>
535     *
536     * @return list of InetAddress objects
537     */
538    public abstract Inet6Address[] getInet6Addresses();
539
540    /**
541     * Get the port for the service.
542     *
543     * @return service port
544     */
545    public abstract int getPort();
546
547    /**
548     * Get the priority of the service.
549     *
550     * @return service priority
551     */
552    public abstract int getPriority();
553
554    /**
555     * Get the weight of the service.
556     *
557     * @return service weight
558     */
559    public abstract int getWeight();
560
561    /**
562     * Get the text for the service as raw bytes.
563     *
564     * @return raw service text
565     */
566    public abstract byte[] getTextBytes();
567
568    /**
569     * Get the text for the service. This will interpret the text bytes as a UTF8 encoded string. Will return null if the bytes are not a valid UTF8 encoded string.<br/>
570     * <b>Note:</b> Do not use. This method make the assumption that the TXT record is one string. This is false. The TXT record is a series of key value pairs.
571     *
572     * @return service text
573     * @see #getPropertyNames()
574     * @see #getPropertyBytes(String)
575     * @see #getPropertyString(String)
576     * @deprecated since 3.1.7
577     */
578    @Deprecated
579    public abstract String getTextString();
580
581    /**
582     * Get the URL for this service. An http URL is created by combining the address, port, and path properties.
583     *
584     * @return service URL
585     * @deprecated since 3.2.3
586     * @see #getURLs()
587     */
588    @Deprecated
589    public abstract String getURL();
590
591    /**
592     * Get the list of URL for this service. An http URL is created by combining the address, port, and path properties.
593     *
594     * @return list of service URL
595     */
596    public abstract String[] getURLs();
597
598    /**
599     * Get the URL for this service. An URL is created by combining the protocol, address, port, and path properties.
600     *
601     * @param protocol
602     *            requested protocol
603     * @return service URL
604     * @deprecated since 3.2.3
605     * @see #getURLs()
606     */
607    @Deprecated
608    public abstract String getURL(String protocol);
609
610    /**
611     * Get the list of URL for this service. An URL is created by combining the protocol, address, port, and path properties.
612     *
613     * @param protocol
614     *            requested protocol
615     * @return list of service URL
616     */
617    public abstract String[] getURLs(String protocol);
618
619    /**
620     * Get a property of the service. This involves decoding the text bytes into a property list. Returns null if the property is not found or the text data could not be decoded correctly.
621     *
622     * @param name
623     *            property name
624     * @return raw property text
625     */
626    public abstract byte[] getPropertyBytes(final String name);
627
628    /**
629     * Get a property of the service. This involves decoding the text bytes into a property list. Returns null if the property is not found, the text data could not be decoded correctly, or the resulting bytes are not a valid UTF8 string.
630     *
631     * @param name
632     *            property name
633     * @return property text
634     */
635    public abstract String getPropertyString(final String name);
636
637    /**
638     * Enumeration of the property names.
639     *
640     * @return property name enumeration
641     */
642    public abstract Enumeration<String> getPropertyNames();
643
644    /**
645     * Returns a description of the service info suitable for printing.
646     *
647     * @return service info description
648     */
649    public abstract String getNiceTextString();
650
651    /**
652     * Set the text for the service. Setting the text will fore a re-announce of the service.
653     *
654     * @param text
655     *            the raw byte representation of the text field.
656     * @exception IllegalStateException
657     *                if attempting to set the text for a non persistent service info.
658     */
659    public abstract void setText(final byte[] text) throws IllegalStateException;
660
661    /**
662     * Set the text for the service. Setting the text will fore a re-announce of the service.
663     *
664     * @param props
665     *            a key=value map that will be encoded into raw bytes.
666     * @exception IllegalStateException
667     *                if attempting to set the text for a non persistent service info.
668     */
669    public abstract void setText(final Map<String, ?> props) throws IllegalStateException;
670
671    /**
672     * Returns <code>true</code> if ServiceListener.resolveService will be called whenever new new information is received.
673     *
674     * @return the persistent
675     */
676    public abstract boolean isPersistent();
677
678    /**
679     * Returns the domain of the service info suitable for printing.
680     *
681     * @return service domain
682     */
683    public abstract String getDomain();
684
685    /**
686     * Returns the protocol of the service info suitable for printing.
687     *
688     * @return service protocol
689     */
690    public abstract String getProtocol();
691
692    /**
693     * Returns the application of the service info suitable for printing.
694     *
695     * @return service application
696     */
697    public abstract String getApplication();
698
699    /**
700     * Returns the sub type of the service info suitable for printing.
701     *
702     * @return service sub type
703     */
704    public abstract String getSubtype();
705
706    /**
707     * Returns a dictionary of the fully qualified name component of this service.
708     *
709     * @return dictionary of the fully qualified name components
710     */
711    public abstract Map<Fields, String> getQualifiedNameMap();
712
713    /*
714     * (non-Javadoc)
715     * @see java.lang.Object#clone()
716     */
717    @Override
718    public ServiceInfo clone() {
719        try {
720            return (ServiceInfo) super.clone();
721        } catch (CloneNotSupportedException exception) {
722            // clone is supported
723            return null;
724        }
725    }
726
727}
728