1 /*
   2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package jnlp.converter.parser;
  25 
  26 import java.util.Locale;
  27 import java.util.ArrayList;
  28 import java.util.StringTokenizer;
  29 import java.io.BufferedInputStream;
  30 import java.io.IOException;
  31 import java.io.InputStream;
  32 import java.net.MalformedURLException;
  33 import java.net.URL;
  34 
  35 /**
  36  * Handy class to add some utility methods for dealing with property matching
  37  * etc.
  38  */
  39 public class GeneralUtil {
  40 
  41     public static boolean prefixMatchStringList(String[] prefixList, String target) {
  42         // No prefixes matches everything
  43         if (prefixList == null) {
  44             return true;
  45         }
  46         // No target, but a prefix list does not match anything
  47         if (target == null) {
  48             return false;
  49         }
  50         for (String prefix : prefixList) {
  51             if (target.startsWith(prefix)) {
  52                 return true;
  53             }
  54         }
  55         return false;
  56     }
  57 
  58     private static String getOSArch() {
  59         return System.getProperty("os.arch");
  60     }
  61 
  62     public static boolean prefixMatchArch(String[] prefixList) {
  63         // No prefixes matches everything
  64         if (prefixList == null) {
  65             return true;
  66         }
  67 
  68         // check for the current arch
  69         String arch = getOSArch();
  70         for (String prefix : prefixList) {
  71             if (arch.startsWith(prefix)) {
  72                 return true;
  73             }
  74         }
  75 
  76         return false;
  77     }
  78 
  79     /**
  80      * Converts a space delimited string to a list of strings
  81      */
  82     public static String[] getStringList(String str) {
  83         if (str == null) {
  84             return null;
  85         }
  86         ArrayList<String> list = new ArrayList<>();
  87         int i = 0;
  88         int length = str.length();
  89         StringBuffer sb = null;
  90         while (i < length) {
  91             char ch = str.charAt(i);
  92             switch (ch) {
  93                 case ' ':
  94                     // A space was hit. Add string to list
  95                     if (sb != null) {
  96                         list.add(sb.toString());
  97                         sb = null;
  98                     }
  99                     break;
 100                 case '\\':
 101                     // It is a delimiter. Add next character
 102                     if (i + 1 < length) {
 103                         ch = str.charAt(++i);
 104                         if (sb == null) {
 105                             sb = new StringBuffer();
 106                         }
 107                         sb.append(ch);
 108                     }
 109                     break;
 110                 default:
 111                     if (sb == null) {
 112                         sb = new StringBuffer();
 113                     }   sb.append(ch);
 114                     break;
 115             }
 116             i++; // Next character
 117         }
 118         // Make sure to add the last part to the list too
 119         if (sb != null) {
 120             list.add(sb.toString());
 121         }
 122         if (list.isEmpty()) {
 123             return null;
 124         }
 125         String[] results = new String[list.size()];
 126         return list.toArray(results);
 127     }
 128 
 129     /**
 130      * Checks if string list matches default locale
 131      */
 132     public static boolean matchLocale(String[] localeList, Locale locale) {
 133         // No locale specified matches everything
 134         if (localeList == null) {
 135             return true;
 136         }
 137         for (String localeList1 : localeList) {
 138             if (matchLocale(localeList1, locale)) {
 139                 return true;
 140             }
 141         }
 142         return false;
 143     }
 144 
 145     /**
 146      * Checks if string matches default locale
 147      */
 148     public static boolean matchLocale(String localeStr, Locale locale) {
 149         if (localeStr == null || localeStr.length() == 0) {
 150             return true;
 151         }
 152 
 153         // Compare against default locale
 154         String language;
 155         String country;
 156         String variant;
 157 
 158         // The locale string is of the form language_country_variant
 159         StringTokenizer st = new StringTokenizer(localeStr, "_", false);
 160         if (st.hasMoreElements() && locale.getLanguage().length() > 0) {
 161             language = st.nextToken();
 162             if (!language.equalsIgnoreCase(locale.getLanguage())) {
 163                 return false;
 164             }
 165         }
 166         if (st.hasMoreElements() && locale.getCountry().length() > 0) {
 167             country = st.nextToken();
 168             if (!country.equalsIgnoreCase(locale.getCountry())) {
 169                 return false;
 170             }
 171         }
 172         if (st.hasMoreElements() && locale.getVariant().length() > 0) {
 173             variant = st.nextToken();
 174             if (!variant.equalsIgnoreCase(locale.getVariant())) {
 175                 return false;
 176             }
 177         }
 178 
 179         return true;
 180     }
 181 
 182     public static long heapValToLong(String heapValue) {
 183         if (heapValue == null) {
 184             return -1;
 185         }
 186         long multiplier = 1;
 187         if (heapValue.toLowerCase().lastIndexOf('m') != -1) {
 188             // units are megabytes, 1 megabyte = 1024 * 1024 bytes
 189             multiplier = 1024 * 1024;
 190             heapValue = heapValue.substring(0, heapValue.length() - 1);
 191         } else if (heapValue.toLowerCase().lastIndexOf('k') != -1) {
 192             // units are kilobytes, 1 kilobyte = 1024 bytes
 193             multiplier = 1024;
 194             heapValue = heapValue.substring(0, heapValue.length() - 1);
 195         }
 196         long theValue;
 197         try {
 198             theValue = Long.parseLong(heapValue);
 199             theValue = theValue * multiplier;
 200         } catch (NumberFormatException e) {
 201             theValue = -1;
 202         }
 203         return theValue;
 204     }
 205 
 206     public static byte[] readBytes(InputStream is, long size) throws IOException {
 207         // Sanity on file size (restrict to 1M)
 208         if (size > 1024 * 1024) {
 209             throw new IOException("File too large");
 210         }
 211 
 212         BufferedInputStream bis;
 213         if (is instanceof BufferedInputStream) {
 214             bis = (BufferedInputStream) is;
 215         } else {
 216             bis = new BufferedInputStream(is);
 217         }
 218 
 219         if (size <= 0) {
 220             size = 10 * 1024; // Default to 10K
 221         }
 222         byte[] b = new byte[(int) size];
 223         int n;
 224         int bytesRead = 0;
 225         n = bis.read(b, bytesRead, b.length - bytesRead);
 226         while (n != -1) {
 227             bytesRead += n;
 228             // Still room in array
 229             if (b.length == bytesRead) {
 230                 byte[] bb = new byte[b.length * 2];
 231                 System.arraycopy(b, 0, bb, 0, b.length);
 232                 b = bb;
 233             }
 234             // Read next line
 235             n = bis.read(b, bytesRead, b.length - bytesRead);
 236         }
 237         bis.close();
 238         is.close();
 239 
 240         if (bytesRead != b.length) {
 241             byte[] bb = new byte[bytesRead];
 242             System.arraycopy(b, 0, bb, 0, bytesRead);
 243             b = bb;
 244         }
 245         return b;
 246     }
 247 
 248     public static String getOSFullName() {
 249         return System.getProperty("os.name");
 250     }
 251 
 252     /**
 253      * Makes sure a URL is a path URL, i.e., ends with '/'
 254      */
 255     public static URL asPathURL(URL url) {
 256         if (url == null) {
 257             return null;
 258         }
 259 
 260         String path = url.getFile();
 261         if (path != null && !path.endsWith("/")) {
 262             try {
 263                 return new URL(url.getProtocol(),
 264                         url.getHost(),
 265                         url.getPort(),
 266                         url.getFile() + "/");
 267             } catch (MalformedURLException mue) {
 268                 // Should not happen
 269             }
 270         }
 271         // Just return same URl
 272         return url;
 273     }
 274 
 275     public static Locale getDefaultLocale() {
 276         return Locale.getDefault();
 277     }
 278 
 279     public static String toNormalizedString(URL u) {
 280         if (u == null) {
 281             return "";
 282         }
 283 
 284         try {
 285             if (u.getPort() == u.getDefaultPort()) {
 286                 u = new URL(u.getProtocol().toLowerCase(),
 287                         u.getHost().toLowerCase(), -1, u.getFile());
 288             } else {
 289                 u = new URL(u.getProtocol().toLowerCase(),
 290                         u.getHost().toLowerCase(), u.getPort(), u.getFile());
 291             }
 292         } catch (MalformedURLException ex) {
 293         }
 294         return u.toExternalForm();
 295     }
 296 
 297     public static boolean sameURLs(URL u1, URL u2) {
 298         if (u1 == null || u2 == null || (u1 == u2)) {
 299             return (u1 == u2);
 300         }
 301         //NB: do not use URL.sameFile() as it will do DNS lookup
 302         // Also, do quick check before slow string comparisons
 303         String f1 = u1.getFile();
 304         String f2 = u2.getFile();
 305         return (f1.length() == f2.length()) && sameBase(u1, u2)
 306                 && f1.equalsIgnoreCase(f2);
 307     }
 308 
 309     public static boolean sameBase(URL u1, URL u2) {
 310         return u1 != null && u2 != null &&
 311                 sameHost(u1, u2) && samePort(u1, u2) && sameProtocol(u1, u2);
 312     }
 313 
 314     private static boolean sameProtocol(URL u1, URL u2) {
 315         //protocols are known to be lowercase
 316         return u1.getProtocol().equals(u2.getProtocol());
 317     }
 318 
 319     private static boolean sameHost(URL u1, URL u2) {
 320         String host = u1.getHost();
 321         String otherHost = u2.getHost();
 322         if (host == null || otherHost == null) {
 323             return (host == null && otherHost == null);
 324         } else {
 325             //avoid slow comparison for strings of different length
 326             return ((host.length() == otherHost.length())
 327                        && host.equalsIgnoreCase(otherHost));
 328         }
 329     }
 330 
 331     private static boolean samePort(URL u1, URL u2) {
 332         return getPort(u1) == getPort(u2);
 333     }
 334 
 335     public static int getPort(URL u) {
 336         if (u.getPort() != -1) {
 337             return u.getPort();
 338         } else {
 339             return u.getDefaultPort();
 340         }
 341     }
 342 
 343     public static URL getBase(URL url) {
 344         if (url == null) return null;
 345         String file = url.getFile();
 346         if (file != null) {
 347             int idx = file.lastIndexOf('/');
 348             if (idx != -1 ) {
 349                 file = file.substring(0, idx + 1);
 350             }
 351             try {
 352                 return new URL(
 353                     url.getProtocol(),
 354                     url.getHost(),
 355                     url.getPort(),
 356                     file);
 357             } catch(MalformedURLException mue) {
 358                 System.err.println(mue.getMessage());
 359             }
 360         }
 361         // Just return same URL
 362         return url;
 363     }
 364 
 365     private static String getEmbeddedVersionPath(String path, String version) {
 366         int index = path.lastIndexOf("/");
 367         String filename = path.substring(index + 1);
 368         path = path.substring(0, index + 1);
 369 
 370         String ext = null;
 371         index = filename.lastIndexOf(".");
 372         if (index != -1) {
 373             ext = filename.substring(index + 1);
 374             filename = filename.substring(0, index);
 375         }
 376 
 377         StringBuilder filenameSB = new StringBuilder(filename);
 378         if (version != null) {
 379             filenameSB.append("__V");
 380             filenameSB.append(version);
 381         }
 382         if (ext != null) {
 383             filenameSB.append(".");
 384             filenameSB.append(ext);
 385         }
 386 
 387         path += filenameSB.toString();
 388         return path;
 389     }
 390 
 391     public static URL getEmbeddedVersionURL(URL u, String version) throws Exception {
 392         if (u == null) {
 393             return null;
 394         }
 395 
 396         if (version == null || version.indexOf("*") != -1
 397                 || version.indexOf("+") != -1) {
 398             // Do not support * or + in version string
 399             return u;
 400         }
 401 
 402         URL versionURL = null;
 403 
 404         String protocol = u.getProtocol();
 405         String host = u.getHost();
 406         int port = u.getPort();
 407         String path = u.getPath();
 408 
 409         path = getEmbeddedVersionPath(path, version);
 410 
 411         versionURL = new URL(protocol, host, port, path);
 412 
 413         return versionURL;
 414     }
 415 }