Source Code Cross Referenced for CompoundName.java in  » 6.0-JDK-Core » naming » javax » naming » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » naming » javax.naming 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1999-2004 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.naming;
027
028        import java.util.Enumeration;
029        import java.util.Properties;
030
031        /**
032         * This class represents a compound name -- a name from
033         * a hierarchical name space.  
034         * Each component in a compound name is an atomic name.
035         * <p>
036         * The components of a compound name are numbered.  The indexes of a
037         * compound name with N components range from 0 up to, but not including, N.
038         * This range may be written as [0,N).
039         * The most significant component is at index 0.
040         * An empty compound name has no components.
041         *<p> 
042         * <h4>Compound Name Syntax</h4>
043         * The syntax of a compound name is specified using a set of properties:
044         *<dl>
045         *  <dt>jndi.syntax.direction
046         *  <dd>Direction for parsing ("right_to_left", "left_to_right", "flat"). 
047         *      If unspecified, defaults to "flat", which means the namespace is flat
048         *      with no hierarchical structure.
049         * 
050         *  <dt>jndi.syntax.separator
051         *  <dd>Separator between atomic name components.  
052         *      Required unless direction is "flat".
053         *
054         *  <dt>jndi.syntax.ignorecase
055         *  <dd>If present, "true" means ignore the case when comparing name 
056         *      components. If its value is not "true", or if the property is not
057         *      present, case is considered when comparing name components.
058         *
059         *  <dt>jndi.syntax.escape
060         *  <dd>If present, specifies the escape string for overriding separator, 
061         *      escapes and quotes.
062         *
063         *  <dt>jndi.syntax.beginquote
064         *  <dd>If present, specifies the string delimiting start of a quoted string.
065         * 
066         *  <dt>jndi.syntax.endquote
067         *  <dd>String delimiting end of quoted string.
068         *      If present, specifies the string delimiting the end of a quoted string.
069         *	If not present, use syntax.beginquote as end quote.
070         *  <dt>jndi.syntax.beginquote2
071         *  <dd>Alternative set of begin/end quotes.
072         * 
073         *  <dt>jndi.syntax.endquote2
074         *  <dd>Alternative set of begin/end quotes.
075         *
076         *  <dt>jndi.syntax.trimblanks
077         *  <dd>If present, "true" means trim any leading and trailing whitespaces 
078         *      in a name component for comparison purposes. If its value is not
079         *      "true", or if the property is not present, blanks are significant.
080         *  <dt>jndi.syntax.separator.ava
081         *  <dd>If present, specifies the string that separates 
082         *      attribute-value-assertions when specifying multiple attribute/value
083         *      pairs. (e.g. ","  in age=65,gender=male).
084         *  <dt>jndi.syntax.separator.typeval
085         *  <dd>If present, specifies the string that separators attribute
086         *		from value (e.g. "=" in "age=65")
087         *</dl>
088         * These properties are interpreted according to the following rules:
089         *<ol>
090         *<li>
091         * In a string without quotes or escapes, any instance of the 
092         * separator delimits two atomic names. Each atomic name is referred
093         * to as a <em>component</em>.
094         *<li>
095         * A separator, quote or escape is escaped if preceded immediately 
096         * (on the left) by the escape.
097         *<li>
098         * If there are two sets of quotes, a specific begin-quote must be matched
099         * by its corresponding end-quote.
100         *<li>
101         * A non-escaped begin-quote which precedes a component must be
102         * matched by a non-escaped end-quote at the end of the component.
103         * A component thus quoted is referred to as a 
104         * <em>quoted component</em>. It is parsed by
105         * removing the being- and end- quotes, and by treating the intervening
106         * characters as ordinary characters unless one of the rules involving
107         * quoted components listed below applies.
108         *<li>
109         * Quotes embedded in non-quoted components are treated as ordinary strings
110         * and need not be matched.
111         *<li>
112         * A separator that is escaped or appears between non-escaped 
113         * quotes is treated as an ordinary string and not a separator.
114         *<li>
115         * An escape string within a quoted component acts as an escape only when
116         * followed by the corresponding end-quote string.
117         * This can be used to embed an escaped quote within a quoted component.
118         *<li>
119         * An escaped escape string is not treated as an escape string.
120         *<li>
121         * An escape string that does not precede a meta string (quotes or separator)
122         * and is not at the end of a component is treated as an ordinary string.
123         *<li>
124         * A leading separator (the compound name string begins with
125         * a separator) denotes a leading empty atomic component (consisting
126         * of an empty string).
127         * A trailing separator (the compound name string ends with
128         * a separator) denotes a trailing empty atomic component.
129         * Adjacent separators denote an empty atomic component.
130         *</ol>
131         * <p>
132         * The string form of the compound name follows the syntax described above.
133         * When the components of the compound name are turned into their
134         * string representation, the reserved syntax rules described above are
135         * applied (e.g. embedded separators are escaped or quoted)
136         * so that when the same string is parsed, it will yield the same components
137         * of the original compound name.
138         *<p>
139         *<h4>Multithreaded Access</h4>
140         * A <tt>CompoundName</tt> instance is not synchronized against concurrent
141         * multithreaded access. Multiple threads trying to access and modify a
142         * <tt>CompoundName</tt> should lock the object.
143         *
144         * @author Rosanna Lee
145         * @author Scott Seligman
146         * @version 1.18 07/05/05
147         * @since 1.3
148         */
149
150        public class CompoundName implements  Name {
151
152            /**
153             * Implementation of this compound name.
154             * This field is initialized by the constructors and cannot be null.
155             * It should be treated as a read-only variable by subclasses.
156             */
157            protected transient NameImpl impl;
158            /**
159             * Syntax properties for this compound name.
160             * This field is initialized by the constructors and cannot be null.
161             * It should be treated as a read-only variable by subclasses.
162             * Any necessary changes to mySyntax should be made within constructors
163             * and not after the compound name has been instantiated.
164             */
165            protected transient Properties mySyntax;
166
167            /**
168             * Constructs a new compound name instance using the components
169             * specified in comps and syntax. This protected method is intended to be
170             * to be used by subclasses of CompoundName when they override
171             * methods such as clone(), getPrefix(), getSuffix().
172             *
173             * @param comps  A non-null enumeration of the components to add.
174             *   Each element of the enumeration is of class String.
175             *               The enumeration will be consumed to extract its
176             *               elements. 
177             * @param syntax	A non-null properties that specify the syntax of
178             *			this compound name. See class description for
179             *			contents of properties.
180             */
181            protected CompoundName(Enumeration<String> comps, Properties syntax) {
182                if (syntax == null) {
183                    throw new NullPointerException();
184                }
185                mySyntax = syntax;
186                impl = new NameImpl(syntax, comps);
187            }
188
189            /**
190             * Constructs a new compound name instance by parsing the string n
191             * using the syntax specified by the syntax properties supplied.
192             *
193             * @param	n	The non-null string to parse.
194             * @param syntax	A non-null list of properties that specify the syntax of
195             *			this compound name.  See class description for
196             *			contents of properties.
197             * @exception	InvalidNameException If 'n' violates the syntax specified
198             *			by <code>syntax</code>.
199             */
200            public CompoundName(String n, Properties syntax)
201                    throws InvalidNameException {
202                if (syntax == null) {
203                    throw new NullPointerException();
204                }
205                mySyntax = syntax;
206                impl = new NameImpl(syntax, n);
207            }
208
209            /**
210             * Generates the string representation of this compound name, using
211             * the syntax rules of the compound name. The syntax rules
212             * are described in the class description.
213             * An empty component is represented by an empty string.
214             *
215             * The string representation thus generated can be passed to
216             * the CompoundName constructor with the same syntax properties
217             * to create a new equivalent compound name.
218             *
219             * @return A non-null string representation of this compound name.
220             */
221            public String toString() {
222                return (impl.toString());
223            }
224
225            /**
226             * Determines whether obj is syntactically equal to this compound name.
227             * If obj is null or not a CompoundName, false is returned.
228             * Two compound names are equal if each component in one is "equal"
229             * to the corresponding component in the other. 
230             *<p>
231             * Equality is also defined in terms of the syntax of this compound name.
232             * The default implementation of CompoundName uses the syntax properties
233             * jndi.syntax.ignorecase and jndi.syntax.trimblanks when comparing
234             * two components for equality.  If case is ignored, two strings
235             * with the same sequence of characters but with different cases
236             * are considered equal. If blanks are being trimmed, leading and trailing
237             * blanks are ignored for the purpose of the comparison.
238             *<p>
239             * Both compound names must have the same number of components.
240             *<p>
241             * Implementation note: Currently the syntax properties of the two compound
242             * names are not compared for equality. They might be in the future.
243             *
244             * @param	obj	The possibly null object to compare against.
245             * @return	true if obj is equal to this compound name, false otherwise.
246             * @see #compareTo(java.lang.Object obj)
247             */
248            public boolean equals(Object obj) {
249                // %%% check syntax too?
250                return (obj != null && obj instanceof  CompoundName && impl
251                        .equals(((CompoundName) obj).impl));
252            }
253
254            /**
255             * Computes the hash code of this compound name.
256             * The hash code is the sum of the hash codes of the "canonicalized" 
257             * forms of individual components of this compound name.
258             * Each component is "canonicalized" according to the 
259             * compound name's syntax before its hash code is computed.
260             * For a case-insensitive name, for example, the uppercased form of 
261             * a name has the same hash code as its lowercased equivalent.
262             * 
263             * @return An int representing the hash code of this name.
264             */
265            public int hashCode() {
266                return impl.hashCode();
267            }
268
269            /**
270             * Creates a copy of this compound name.
271             * Changes to the components of this compound name won't
272             * affect the new copy and vice versa.
273             * The clone and this compound name share the same syntax.
274             *
275             * @return	A non-null copy of this compound name.
276             */
277            public Object clone() {
278                return (new CompoundName(getAll(), mySyntax));
279            }
280
281            /**
282             * Compares this CompoundName with the specified Object for order.  
283             * Returns a
284             * negative integer, zero, or a positive integer as this Name is less
285             * than, equal to, or greater than the given Object. 
286             * <p>
287             * If obj is null or not an instance of CompoundName, ClassCastException
288             * is thrown.
289             * <p>
290             * See equals() for what it means for two compound names to be equal.
291             * If two compound names are equal, 0 is returned.
292             *<p>
293             * Ordering of compound names depend on the syntax of the compound name.
294             * By default, they follow lexicographical rules for string comparison
295             * with the extension that this applies to all the components in the
296             * compound name and that comparison of individual components is
297             * affected by the jndi.syntax.ignorecase and jndi.syntax.trimblanks
298             * properties, identical to how they affect equals().
299             * If this compound name is "lexicographically" lesser than obj,
300             * a negative number is returned.
301             * If this compound name is "lexicographically" greater than obj,
302             * a positive number is returned.
303             *<p>
304             * Implementation note: Currently the syntax properties of the two compound
305             * names are not compared when checking order. They might be in the future.
306             * @param	obj	The non-null object to compare against.
307             * @return  a negative integer, zero, or a positive integer as this Name
308             *		is less than, equal to, or greater than the given Object.
309             * @exception ClassCastException if obj is not a CompoundName.
310             * @see #equals(java.lang.Object)
311             */
312            public int compareTo(Object obj) {
313                if (!(obj instanceof  CompoundName)) {
314                    throw new ClassCastException("Not a CompoundName");
315                }
316                return impl.compareTo(((CompoundName) obj).impl);
317            }
318
319            /**
320             * Retrieves the number of components in this compound name.
321             *
322             * @return The nonnegative number of components in this compound name.
323             */
324            public int size() {
325                return (impl.size());
326            }
327
328            /**
329             * Determines whether this compound name is empty.
330             * A compound name is empty if it has zero components.
331             *
332             * @return true if this compound name is empty, false otherwise.
333             */
334            public boolean isEmpty() {
335                return (impl.isEmpty());
336            }
337
338            /**
339             * Retrieves the components of this compound name as an enumeration
340             * of strings.
341             * The effects of updates to this compound name on this enumeration
342             * is undefined.
343             *
344             * @return	A non-null enumeration of the components of this
345             * compound name. Each element of the enumeration is of class String.
346             */
347            public Enumeration<String> getAll() {
348                return (impl.getAll());
349            }
350
351            /**
352             * Retrieves a component of this compound name.
353             *
354             * @param	posn	The 0-based index of the component to retrieve.
355             *			Must be in the range [0,size()).
356             * @return The component at index posn.
357             * @exception ArrayIndexOutOfBoundsException if posn is outside the
358             * 	specified range.
359             */
360            public String get(int posn) {
361                return (impl.get(posn));
362            }
363
364            /**
365             * Creates a compound name whose components consist of a prefix of the
366             * components in this compound name.
367             * The result and this compound name share the same syntax.
368             * Subsequent changes to
369             * this compound name does not affect the name that is returned and
370             * vice versa.
371             *
372             * @param	posn	The 0-based index of the component at which to stop.
373             *			Must be in the range [0,size()].
374             * @return	A compound name consisting of the components at indexes in
375             *		the range [0,posn).
376             * @exception ArrayIndexOutOfBoundsException
377             *		If posn is outside the specified range.
378             */
379            public Name getPrefix(int posn) {
380                Enumeration comps = impl.getPrefix(posn);
381                return (new CompoundName(comps, mySyntax));
382            }
383
384            /**
385             * Creates a compound name whose components consist of a suffix of the
386             * components in this compound name.
387             * The result and this compound name share the same syntax.
388             * Subsequent changes to
389             * this compound name does not affect the name that is returned.
390             *
391             * @param	posn	The 0-based index of the component at which to start.
392             *			Must be in the range [0,size()].
393             * @return	A compound name consisting of the components at indexes in
394             *		the range [posn,size()).  If posn is equal to 
395             * 	size(), an empty compound name is returned.
396             * @exception ArrayIndexOutOfBoundsException
397             *		If posn is outside the specified range.
398             */
399            public Name getSuffix(int posn) {
400                Enumeration comps = impl.getSuffix(posn);
401                return (new CompoundName(comps, mySyntax));
402            }
403
404            /**
405             * Determines whether a compound name is a prefix of this compound name.
406             * A compound name 'n' is a prefix if it is equal to 
407             * getPrefix(n.size())--in other words, this compound name
408             * starts with 'n'.
409             * If n is null or not a compound name, false is returned.
410             *<p>
411             * Implementation note: Currently the syntax properties of n
412             *  are not used when doing the comparison. They might be in the future.
413             * @param	n	The possibly null compound name to check.
414             * @return	true if n is a CompoundName and
415             * 		is a prefix of this compound name, false otherwise.
416             */
417            public boolean startsWith(Name n) {
418                if (n instanceof  CompoundName) {
419                    return (impl.startsWith(n.size(), n.getAll()));
420                } else {
421                    return false;
422                }
423            }
424
425            /**
426             * Determines whether a compound name is a suffix of this compound name.
427             * A compound name 'n' is a suffix if it it is equal to
428             * getSuffix(size()-n.size())--in other words, this
429             * compound name ends with 'n'.
430             * If n is null or not a compound name, false is returned.
431             *<p>
432             * Implementation note: Currently the syntax properties of n
433             *  are not used when doing the comparison. They might be in the future.
434             * @param	n	The possibly null compound name to check.
435             * @return	true if n is a CompoundName and
436             * 	is a suffix of this compound name, false otherwise.
437             */
438            public boolean endsWith(Name n) {
439                if (n instanceof  CompoundName) {
440                    return (impl.endsWith(n.size(), n.getAll()));
441                } else {
442                    return false;
443                }
444            }
445
446            /**
447             * Adds the components of a compound name -- in order -- to the end of
448             * this compound name.
449             *<p>
450             * Implementation note: Currently the syntax properties of suffix
451             *  is not used or checked. They might be in the future.
452             * @param suffix	The non-null components to add.
453             * @return The updated CompoundName, not a new one. Cannot be null.
454             * @exception InvalidNameException If suffix is not a compound name,
455             *		   or if the addition of the components violates the syntax
456             *		   of this compound name (e.g. exceeding number of components).
457             */
458            public Name addAll(Name suffix) throws InvalidNameException {
459                if (suffix instanceof  CompoundName) {
460                    impl.addAll(suffix.getAll());
461                    return this ;
462                } else {
463                    throw new InvalidNameException("Not a compound name: "
464                            + suffix.toString());
465                }
466            }
467
468            /**
469             * Adds the components of a compound name -- in order -- at a specified
470             * position within this compound name.
471             * Components of this compound name at or after the index of the first
472             * new component are shifted up (away from index 0)
473             * to accommodate the new components.
474             *<p>
475             * Implementation note: Currently the syntax properties of suffix
476             *  is not used or checked. They might be in the future.
477             *
478             * @param n 	The non-null components to add.
479             * @param posn	The index in this name at which to add the new
480             *			components.  Must be in the range [0,size()].
481             * @return The updated CompoundName, not a new one. Cannot be null.
482             * @exception ArrayIndexOutOfBoundsException
483             *		If posn is outside the specified range.
484             * @exception InvalidNameException If n is not a compound name,
485             *		   or if the addition of the components violates the syntax
486             *		   of this compound name (e.g. exceeding number of components).
487             */
488            public Name addAll(int posn, Name n) throws InvalidNameException {
489                if (n instanceof  CompoundName) {
490                    impl.addAll(posn, n.getAll());
491                    return this ;
492                } else {
493                    throw new InvalidNameException("Not a compound name: "
494                            + n.toString());
495                }
496            }
497
498            /**
499             * Adds a single component to the end of this compound name.
500             *
501             * @param comp	The non-null component to add.
502             * @return The updated CompoundName, not a new one. Cannot be null.
503             * @exception InvalidNameException If adding comp at end of the name
504             *				would violate the compound name's syntax.
505             */
506            public Name add(String comp) throws InvalidNameException {
507                impl.add(comp);
508                return this ;
509            }
510
511            /**
512             * Adds a single component at a specified position within this
513             * compound name.
514             * Components of this compound name at or after the index of the new
515             * component are shifted up by one (away from index 0)
516             * to accommodate the new component.
517             *
518             * @param 	comp	The non-null component to add.
519             * @param	posn	The index at which to add the new component.
520             *			Must be in the range [0,size()].
521             * @exception ArrayIndexOutOfBoundsException
522             *		If posn is outside the specified range.
523             * @return The updated CompoundName, not a new one. Cannot be null.
524             * @exception InvalidNameException If adding comp at the specified position
525             *				would violate the compound name's syntax.
526             */
527            public Name add(int posn, String comp) throws InvalidNameException {
528                impl.add(posn, comp);
529                return this ;
530            }
531
532            /**
533             * Deletes a component from this compound name.
534             * The component of this compound name at position 'posn' is removed,
535             * and components at indices greater than 'posn'
536             * are shifted down (towards index 0) by one.
537             *
538             * @param	posn	The index of the component to delete.
539             *			Must be in the range [0,size()).
540             * @return The component removed (a String).
541             * @exception ArrayIndexOutOfBoundsException
542             *		If posn is outside the specified range (includes case where
543             *		compound name is empty).
544             * @exception InvalidNameException If deleting the component
545             *				would violate the compound name's syntax.
546             */
547            public Object remove(int posn) throws InvalidNameException {
548                return impl.remove(posn);
549            }
550
551            /**
552             * Overridden to avoid implementation dependency.
553             * @serialData The syntax <tt>Properties</tt>, followed by
554             * the number of components (an <tt>int</tt>), and the individual
555             * components (each a <tt>String</tt>).
556             */
557            private void writeObject(java.io.ObjectOutputStream s)
558                    throws java.io.IOException {
559                s.writeObject(mySyntax);
560                s.writeInt(size());
561                Enumeration comps = getAll();
562                while (comps.hasMoreElements()) {
563                    s.writeObject(comps.nextElement());
564                }
565            }
566
567            /**
568             * Overridden to avoid implementation dependency.
569             */
570            private void readObject(java.io.ObjectInputStream s)
571                    throws java.io.IOException, ClassNotFoundException {
572                mySyntax = (Properties) s.readObject();
573                impl = new NameImpl(mySyntax);
574                int n = s.readInt(); // number of components
575                try {
576                    while (--n >= 0) {
577                        add((String) s.readObject());
578                    }
579                } catch (InvalidNameException e) {
580                    throw (new java.io.StreamCorruptedException("Invalid name"));
581                }
582            }
583
584            /**
585             * Use serialVersionUID from JNDI 1.1.1 for interoperability
586             */
587            private static final long serialVersionUID = 3513100557083972036L;
588
589            /*
590             //   For testing
591
592             public static void main(String[] args) {
593             Properties dotSyntax = new Properties();
594             dotSyntax.put("jndi.syntax.direction", "right_to_left");
595             dotSyntax.put("jndi.syntax.separator", ".");
596             dotSyntax.put("jndi.syntax.ignorecase", "true");
597             dotSyntax.put("jndi.syntax.escape", "\\");
598             //	dotSyntax.put("jndi.syntax.beginquote", "\"");
599             //	dotSyntax.put("jndi.syntax.beginquote2", "'");
600
601             Name first = null;
602             try {
603             for (int i = 0; i < args.length; i++) {
604             Name name;
605             Enumeration e;
606             System.out.println("Given name: " + args[i]);
607             name = new CompoundName(args[i], dotSyntax);
608             if (first == null) {
609             first = name;
610             }
611             e = name.getComponents();
612             while (e.hasMoreElements()) {
613             System.out.println("Element: " + e.nextElement());
614             }
615             System.out.println("Constructed name: " + name.toString());
616
617             System.out.println("Compare " + first.toString() + " with "
618             + name.toString() + " = " + first.compareTo(name));
619             }
620             } catch (Exception ne) {
621             ne.printStackTrace();
622             }
623             }
624             */
625        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.