001 /*
002 Copyright (c) 1996-2012, Damon Hart-Davis
003 All rights reserved.
004
005 Redistribution and use in source and binary forms, with or without
006 modification, are permitted provided that the following conditions are
007 met:
008
009 * Redistributions of source code must retain the above copyright
010 notice, this list of conditions and the following disclaimer.
011
012 * Redistributions in binary form must reproduce the above copyright
013 notice, this list of conditions and the following disclaimer in the
014 documentation and/or other materials provided with the
015 distribution.
016
017 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
018 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
019 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
020 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
021 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
022 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
024 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
025 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
026 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
027 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028 */
029 package org.hd.d.pg2k.svrCore;
030
031 import org.hd.d.pg2k.svrCore.location.GeoUtils.CCTLD;
032
033 /**Some simple common host-name utilities.
034 */
035 public final class HostUtils
036 {
037 /**Prevent construction of an instance. */
038 private HostUtils() { }
039
040 /**Normalise host (Web server) name (ours or a third-party one).
041 * This converts the host name to lower-case and
042 * strips any "www." or "mirror-CC-name." prefix and/or
043 * "." suffix.
044 * <p>
045 * If the name is already normalised,
046 * it is returned unchanged.
047 *
048 * @throws IllegalArgumentException if arguments are malformed
049 */
050 public static String normaliseVirtualHostName(String name)
051 {
052 if(name == null) { throw new IllegalArgumentException(); }
053
054 // Must be at least of form "a.b" and is limited by RFC rules not to be huge.
055 if((name.length() < 3) || (name.length() > 255))
056 { throw new IllegalArgumentException(); }
057
058 // Force names to lower-case.
059 name = name.toLowerCase();
060
061 final int firstDot = name.indexOf('.');
062
063 // Strip off standard prefixes...
064 if(name.startsWith("www."))
065 { name = name.substring(4); }
066 else if(isSpecialName(name))
067 { name = name.substring(firstDot+1); }
068 else if(name.startsWith("mmm.")) // "Mobile" prefix.
069 { name = name.substring(4); }
070
071 // Strip off redundant trailing dot(s)...
072 while(name.endsWith("."))
073 { name = name.substring(0, name.length() - 1); }
074
075 // Normalised...
076 return(name);
077 }
078
079 /**Returns true if this looks like a mirror domain-name.
080 * This is a canonical name prefixed with something of the form:
081 * <samp>mirror-cc-x."</samp>
082 * where "cc" is the two-letter country code where the mirror is hosted
083 * (eg uk or us or fr)
084 * and "x" is a descriptive short tag to indicate which mirror instance.
085 *
086 * @param name host name, must be lower-case and non-null
087 */
088 public static boolean isMirrorName(final String name)
089 {
090 if(!name.startsWith("mirror-")) { return(false); }
091 final int firstDot = name.indexOf('.');
092 if(firstDot <= 10) { return(false); } /* At least "mirror-cc-x." */
093 return(true);
094 }
095
096 /**Returns true if this appears to be the domain-name of a primary local mirror.
097 * This mirror will be assumed to be the primary mirror
098 * in its geographical area (and thus worth allowing to be spidered by SEs)
099 * iff its name ends with a '1',
100 * so, 'mirror-uk-ww1.something' is a primary mirror and 'mirror-uk-ww2.something' is not.
101 * <p>
102 * (Thus 'mirror-uk-ww11.something' would also be primary, but we don't care yet.)
103 * <p>
104 * This returns true for the full domain name iff
105 * isPrimaryMirrorTag() would return true for the embedded mirror tag.
106 *
107 * @param name host name, must be lower-case and non-null
108 */
109 public static boolean isPrimaryMirrorName(final String name)
110 {
111 if(!isMirrorName(name)) { return(false); }
112 return(name.charAt(name.indexOf('.') - 1) == '1');
113 }
114
115 /**Returns true if this tag (initial domain-name component) appears to for a primary local mirror.
116 * A mirror with this tag will be assumed to be the primary mirror
117 * in its geographical area (and thus worth allowing to be spidered by SEs)
118 * iff its name ends with a '1',
119 * so, 'mirror-uk-ww1' is a primary mirror and 'mirror-uk-ww2' is not.
120 * <p>
121 * (Thus 'mirror-uk-ww11' would also be primary, but we don't care yet.)
122 * <p>
123 * This returns true for the tag iff
124 * isPrimaryMirrorName() would return true for the whole name,
125 * though a null tag will cause this routine to return false for simplicity.
126 *
127 * @param mirror tag, must be lower-case
128 */
129 public static boolean isPrimaryMirrorTag(final String tag)
130 {
131 if(null == tag) { return(false); }
132 return(tag.charAt(tag.length() - 1) == '1');
133 }
134
135 /**Extract mirror tag from mirror URL/prefix; null if none.
136 * The mirror tag extracted should be of the form
137 * returned by LocalProps.getMirrorTag() for a well-formed server name.
138 */
139 public static String getMirrorTag(final String name)
140 {
141 if(!isMirrorName(name)) { return(null); }
142 final String cc = name.substring(7, 9);
143 if(!CCTLD.isSyntaticallyValidCcTLD(cc)) { return(null); }
144 return(name.substring(7, name.indexOf('.')));
145 }
146
147 /**Extract country code from mirror URL/prefix; null if none. */
148 public static CCTLD getMirrorCC(final String name)
149 {
150 if(!name.startsWith("mirror-")) { return(null); }
151 if(name.length() < 11) { return(null); }
152 final String cc = name.substring(7, 9);
153 if(!CCTLD.isSyntaticallyValidCcTLD(cc)) { return(null); }
154 return(new CCTLD(cc));
155 }
156
157 /**Returns true if this looks like a "master" server domain-name.
158 * This is a canonical name prefixed with "master."
159 * and indicates a central server, eg on which uploads are permitted.
160 *
161 * @param name host name, must be lower-case and non-null
162 */
163 public static boolean isMasterName(final String name)
164 { return(name.startsWith("master.")); }
165
166 /**Returns true if this looks like a special (mirror or master) domain-name.
167 * @param name host name, must be lower-case and non-null
168 */
169 public static boolean isSpecialName(final String name)
170 { return(isMirrorName(name) || isMasterName(name)); }
171
172 /**Make mirror version of standard "generic" domain-name; never null.
173 * Generates hostname of form "mirror-tag.gallery.hd.org".
174 *
175 * @param tag valid non-null mirror tag
176 */
177 public static String makeMirrorNameGeneric(final String tag)
178 { return("mirror-" + tag + "." + CoreConsts.MAIN_DATA_HOST); }
179 }