| 1 7 8 package java.awt.datatransfer; 9 10 import java.awt.Toolkit ; 11 12 import java.lang.ref.SoftReference ; 13 14 import java.io.BufferedReader ; 15 import java.io.File ; 16 import java.io.InputStreamReader ; 17 import java.io.IOException ; 18 19 import java.net.URL ; 20 import java.net.MalformedURLException ; 21 22 import java.util.ArrayList ; 23 import java.util.HashMap ; 24 import java.util.HashSet ; 25 import java.util.Iterator ; 26 import java.util.LinkedList ; 27 import java.util.List ; 28 import java.util.Map ; 29 import java.util.Set ; 30 import java.util.WeakHashMap ; 31 32 import sun.awt.datatransfer.DataTransferer; 33 34 35 51 public final class SystemFlavorMap implements FlavorMap , FlavorTable { 52 53 57 private static String JavaMIME = "JAVA_DATAFLAVOR:"; 58 59 62 private static final WeakHashMap flavorMaps = new WeakHashMap (); 63 64 67 private static final String keyValueSeparators = "=: \t\r\n\f"; 68 private static final String strictKeyValueSeparators = "=:"; 69 private static final String whiteSpaceChars = " \t\r\n\f"; 70 71 75 private static final String [] UNICODE_TEXT_CLASSES = { 76 "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\"" 77 }; 78 79 83 private static final String [] ENCODED_TEXT_CLASSES = { 84 "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\"" 85 }; 86 87 90 private static final String TEXT_PLAIN_BASE_TYPE = "text/plain"; 91 92 98 private static final boolean SYNTHESIZE_IF_NOT_FOUND = true; 99 100 104 private Map nativeToFlavor = new HashMap (); 105 106 110 private Map flavorToNative = new HashMap (); 111 112 116 private Map getNativesForFlavorCache = new HashMap (); 117 118 122 private Map getFlavorsForNativeCache = new HashMap (); 123 124 130 private Set disabledMappingGenerationKeys = new HashSet (); 131 132 135 public static FlavorMap getDefaultFlavorMap() { 136 ClassLoader contextClassLoader = 137 Thread.currentThread().getContextClassLoader(); 138 if (contextClassLoader == null) { 139 contextClassLoader = ClassLoader.getSystemClassLoader(); 140 } 141 142 FlavorMap fm; 143 144 synchronized(flavorMaps) { 145 fm = (FlavorMap )flavorMaps.get(contextClassLoader); 146 if (fm == null) { 147 fm = new SystemFlavorMap (); 148 flavorMaps.put(contextClassLoader, fm); 149 } 150 } 151 152 return fm; 153 } 154 155 159 private SystemFlavorMap() { 160 BufferedReader flavormapDotProperties = (BufferedReader ) 161 java.security.AccessController.doPrivileged( 162 new java.security.PrivilegedAction () { 163 public Object run() { 164 String fileName = 165 System.getProperty("java.home") + 166 File.separator + 167 "lib" + 168 File.separator + 169 "flavormap.properties"; 170 try { 171 return new BufferedReader  172 (new InputStreamReader  173 (new File (fileName).toURI().toURL().openStream(), "ISO-8859-1")); 174 } catch (MalformedURLException e) { 175 System.err.println("MalformedURLException:" + e + " while loading default flavormap.properties file:" + fileName); 176 } catch (IOException e) { 177 System.err.println("IOException:" + e + " while loading default flavormap.properties file:" + fileName); 178 } 179 return null; 180 } 181 }); 182 183 BufferedReader flavormapURL = (BufferedReader ) 184 java.security.AccessController.doPrivileged( 185 new java.security.PrivilegedAction () { 186 public Object run() { 187 String url = Toolkit.getDefaultToolkit().getProperty 188 ("AWT.DnD.flavorMapFileURL", null); 189 190 if (url == null) { 191 return null; 192 } 193 194 try { 195 return new BufferedReader  196 (new InputStreamReader  197 (new URL (url).openStream(), "ISO-8859-1")); 198 } catch (MalformedURLException e) { 199 System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); 200 } catch (IOException e) { 201 System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url); 202 } 203 return null; 204 } 205 }); 206 207 if (flavormapDotProperties != null) { 208 try { 209 parseAndStoreReader(flavormapDotProperties); 210 } catch (IOException e) { 211 System.err.println("IOException:" + e + " while parsing default flavormap.properties file"); 212 } 213 } 214 215 if (flavormapURL != null) { 216 try { 217 parseAndStoreReader(flavormapURL); 218 } catch (IOException e) { 219 System.err.println("IOException:" + e + " while parsing AWT.DnD.flavorMapFileURL"); 220 } 221 } 222 } 223 224 228 private void parseAndStoreReader(BufferedReader in) throws IOException { 229 while (true) { 230 String line = in.readLine(); 232 if (line == null) { 233 return; 234 } 235 236 if (line.length() > 0) { 237 char firstChar = line.charAt(0); 239 if (firstChar != '#' && firstChar != '!') { 240 while (continueLine(line)) { 241 String nextLine = in.readLine(); 242 if (nextLine == null) { 243 nextLine = new String (""); 244 } 245 String loppedLine = 246 line.substring(0, line.length() - 1); 247 int startIndex = 0; 249 for(; startIndex < nextLine.length(); startIndex++) { 250 if (whiteSpaceChars. 251 indexOf(nextLine.charAt(startIndex)) == -1) 252 { 253 break; 254 } 255 } 256 nextLine = nextLine.substring(startIndex, 257 nextLine.length()); 258 line = new String (loppedLine+nextLine); 259 } 260 261 int len = line.length(); 263 int keyStart = 0; 264 for(; keyStart < len; keyStart++) { 265 if(whiteSpaceChars. 266 indexOf(line.charAt(keyStart)) == -1) { 267 break; 268 } 269 } 270 271 if (keyStart == len) { 273 continue; 274 } 275 276 int separatorIndex = keyStart; 278 for(; separatorIndex < len; separatorIndex++) { 279 char currentChar = line.charAt(separatorIndex); 280 if (currentChar == '\\') { 281 separatorIndex++; 282 } else if (keyValueSeparators. 283 indexOf(currentChar) != -1) { 284 break; 285 } 286 } 287 288 int valueIndex = separatorIndex; 290 for (; valueIndex < len; valueIndex++) { 291 if (whiteSpaceChars. 292 indexOf(line.charAt(valueIndex)) == -1) { 293 break; 294 } 295 } 296 297 if (valueIndex < len) { 299 if (strictKeyValueSeparators. 300 indexOf(line.charAt(valueIndex)) != -1) { 301 valueIndex++; 302 } 303 } 304 305 while (valueIndex < len) { 307 if (whiteSpaceChars. 308 indexOf(line.charAt(valueIndex)) == -1) { 309 break; 310 } 311 valueIndex++; 312 } 313 314 String key = line.substring(keyStart, separatorIndex); 315 String value = (separatorIndex < len) 316 ? line.substring(valueIndex, len) 317 : ""; 318 319 key = loadConvert(key); 321 value = loadConvert(value); 322 323 try { 324 MimeType mime = new MimeType (value); 325 if ("text".equals(mime.getPrimaryType())) { 326 String charset = mime.getParameter("charset"); 327 if (DataTransferer.doesSubtypeSupportCharset 328 (mime.getSubType(), charset)) 329 { 330 DataTransferer transferer = 335 DataTransferer.getInstance(); 336 if (transferer != null) { 337 transferer.registerTextFlavorProperties 338 (key, charset, 339 mime.getParameter("eoln"), 340 mime.getParameter("terminators")); 341 } 342 } 343 344 mime.removeParameter("charset"); 349 mime.removeParameter("class"); 350 mime.removeParameter("eoln"); 351 mime.removeParameter("terminators"); 352 value = mime.toString(); 353 } 354 } catch (MimeTypeParseException e) { 355 e.printStackTrace(); 356 continue; 357 } 358 359 DataFlavor flavor; 360 try { 361 flavor = new DataFlavor (value); 362 } catch (Exception e) { 363 try { 364 flavor = new DataFlavor (value, (String )null); 365 } catch (Exception ee) { 366 ee.printStackTrace(); 367 continue; 368 } 369 } 370 371 if ("text".equals(flavor.getPrimaryType())) { 374 store(value, key, flavorToNative); 375 store(key, value, nativeToFlavor); 376 } else { 377 store(flavor, key, flavorToNative); 378 store(key, flavor, nativeToFlavor); 379 } 380 } 381 } 382 } 383 } 384 385 388 private boolean continueLine (String line) { 389 int slashCount = 0; 390 int index = line.length() - 1; 391 while((index >= 0) && (line.charAt(index--) == '\\')) { 392 slashCount++; 393 } 394 return (slashCount % 2 == 1); 395 } 396 397 400 private String loadConvert(String theString) { 401 char aChar; 402 int len = theString.length(); 403 StringBuffer outBuffer = new StringBuffer (len); 404 405 for (int x = 0; x < len; ) { 406 aChar = theString.charAt(x++); 407 if (aChar == '\\') { 408 aChar = theString.charAt(x++); 409 if (aChar == 'u') { 410 int value = 0; 412 for (int i = 0; i < 4; i++) { 413 aChar = theString.charAt(x++); 414 switch (aChar) { 415 case '0': case '1': case '2': case '3': case '4': 416 case '5': case '6': case '7': case '8': case '9': { 417 value = (value << 4) + aChar - '0'; 418 break; 419 } 420 case 'a': case 'b': case 'c': 421 case 'd': case 'e': case 'f': { 422 value = (value << 4) + 10 + aChar - 'a'; 423 break; 424 } 425 case 'A': case 'B': case 'C': 426 case 'D': case 'E': case 'F': { 427 value = (value << 4) + 10 + aChar - 'A'; 428 break; 429 } 430 default: { 431 throw new IllegalArgumentException ( 432 "Malformed \\uxxxx encoding."); 433 } 434 } 435 } 436 outBuffer.append((char)value); 437 } else { 438 if (aChar == 't') { 439 aChar = '\t'; 440 } else if (aChar == 'r') { 441 aChar = '\r'; 442 } else if (aChar == 'n') { 443 aChar = '\n'; 444 } else if (aChar == 'f') { 445 aChar = '\f'; 446 } 447 outBuffer.append(aChar); 448 } 449 } else { 450 outBuffer.append(aChar); 451 } 452 } 453 return outBuffer.toString(); 454 } 455 456 462 private void store(Object hashed, Object listed, Map map) { 463 List list = (List )map.get(hashed); 464 if (list == null) { 465 list = new ArrayList (1); 466 map.put(hashed, list); 467 } 468 if (!list.contains(listed)) { 469 list.add(listed); 470 } 471 } 472 473 479 private List nativeToFlavorLookup(String nat) { 480 List flavors = (List )nativeToFlavor.get(nat); 481 482 if (nat != null && !disabledMappingGenerationKeys.contains(nat)) { 483 DataTransferer transferer = DataTransferer.getInstance(); 484 if (transferer != null) { 485 List platformFlavors = 486 transferer.getPlatformMappingsForNative(nat); 487 if (!platformFlavors.isEmpty()) { 488 if (flavors != null) { 489 platformFlavors.removeAll(new HashSet (flavors)); 490 platformFlavors.addAll(flavors); 495 } 496 flavors = platformFlavors; 497 } 498 } 499 } 500 501 if (flavors == null && isJavaMIMEType(nat)) { 502 String decoded = decodeJavaMIMEType(nat); 503 DataFlavor flavor = null; 504 505 try { 506 flavor = new DataFlavor (decoded); 507 } catch (Exception e) { 508 System.err.println("Exception \"" + e.getClass().getName() + 509 ": " + e.getMessage() + 510 "\"while constructing DataFlavor for: " + 511 decoded); 512 } 513 514 if (flavor != null) { 515 flavors = new ArrayList (1); 516 nativeToFlavor.put(nat, flavors); 517 flavors.add(flavor); 518 getFlavorsForNativeCache.remove(nat); 519 getFlavorsForNativeCache.remove(null); 520 521 List natives = (List )flavorToNative.get(flavor); 522 if (natives == null) { 523 natives = new ArrayList (1); 524 flavorToNative.put(flavor, natives); 525 } 526 natives.add(nat); 527 getNativesForFlavorCache.remove(flavor); 528 getNativesForFlavorCache.remove(null); 529 } 530 } 531 532 return (flavors != null) ? flavors : new ArrayList (0); 533 } 534 535 543 private List flavorToNativeLookup(final DataFlavor flav, 544 final boolean synthesize) { 545 List natives = (List )flavorToNative.get(flav); 546 547 if (flav != null && !disabledMappingGenerationKeys.contains(flav)) { 548 DataTransferer transferer = DataTransferer.getInstance(); 549 if (transferer != null) { 550 List platformNatives = 551 transferer.getPlatformMappingsForFlavor(flav); 552 if (!platformNatives.isEmpty()) { 553 if (natives != null) { 554 platformNatives.removeAll(new HashSet (natives)); 555 platformNatives.addAll(natives); 560 } 561 natives = platformNatives; 562 } 563 } 564 } 565 566 if (natives == null) { 567 if (synthesize) { 568 String encoded = encodeDataFlavor(flav); 569 natives = new ArrayList (1); 570 flavorToNative.put(flav, natives); 571 natives.add(encoded); 572 getNativesForFlavorCache.remove(flav); 573 getNativesForFlavorCache.remove(null); 574 575 List flavors = (List )nativeToFlavor.get(encoded); 576 if (flavors == null) { 577 flavors = new ArrayList (1); 578 nativeToFlavor.put(encoded, flavors); 579 } 580 flavors.add(flav); 581 getFlavorsForNativeCache.remove(encoded); 582 getFlavorsForNativeCache.remove(null); 583 } else { 584 natives = new ArrayList (0); 585 } 586 } 587 588 return natives; 589 } 590 591 616 public synchronized List <String > getNativesForFlavor(DataFlavor flav) { 617 List retval = null; 618 619 SoftReference ref = (SoftReference )getNativesForFlavorCache.get(flav); 621 if (ref != null) { 622 retval = (List )ref.get(); 623 if (retval != null) { 624 return new ArrayList (retval); 627 } 628 } 629 630 if (flav == null) { 631 retval = new ArrayList (nativeToFlavor.keySet()); 632 } else if (disabledMappingGenerationKeys.contains(flav)) { 633 retval = flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); 636 } else if (DataTransferer.isFlavorCharsetTextType(flav)) { 637 638 if ("text".equals(flav.getPrimaryType())) { 641 retval = (List )flavorToNative.get(flav.mimeType.getBaseType()); 642 if (retval != null) { 643 retval = new ArrayList (retval); 645 |