Mécanisme de gestion de protocole en Java

Les classes URL, URLConnection, URLStreamHandler, et URLStreamHandlerFactory nous permettent d'intecepter et de gérer les protocoles en Java. La manière dont ces classes interagissent peut sembler confuse, et un moyen de comprendre comment cela fonctionne est de résumer la séquence d'évènements :

  1. Le programme construit un objet URL qui représente un pointeur sur une ressource réseau.
    1. URL u = new URL("http://www.gaudry.be/infobrol.php");
  2. Le constructeur de l'objet URL détache la partie protocole de l'argument passé.
    Dans le cas de notre exemple : http
  3. Le constructeur de l'objet URL tente de trouver un URLStreamHandler en passant la partie protocole, de manière statique, à la méthode URLStreamHandler getURLStreamHandler(String protocol)1 de la classe URL.

    1. /**
    2. * Returns the Stream Handler.
    3. * @param protocol the protocol to use
    4. */
    5. static URLStreamHandler getURLStreamHandler(String protocol) {
    6.  
    7. URLStreamHandler handler = (URLStreamHandler)handlers.get(protocol);
    8. if (handler == null) {
    9.  
    10. boolean checkedWithFactory = false;
    11.  
    12. // Use the factory (if any)
    13. if (factory != null) {
    14. handler = factory.createURLStreamHandler(protocol);
    15. checkedWithFactory = true;
    16. }
    17.  
    18. // Try java protocol handler
    19. if (handler == null) {
    20. String packagePrefixList = null;
    21.  
    22. packagePrefixList
    23. = (String) java.security.AccessController.doPrivileged(
    24. new sun.security.action.GetPropertyAction(
    25. protocolPathProp,""));
    26. if (packagePrefixList != "") {
    27. packagePrefixList += "|";
    28. }
    29.  
    30. // REMIND: decide whether to allow the "null" class prefix
    31. // or not.
    32. packagePrefixList += "sun.net.www.protocol";
    33.  
    34. StringTokenizer packagePrefixIter =
    35. new StringTokenizer(packagePrefixList, "|");
    36.  
    37. while (handler == null && packagePrefixIter.hasMoreTokens()) {
    38.  
    39. String packagePrefix =
    40. packagePrefixIter.nextToken().trim();
    41. try {
    42. String clsName = packagePrefix + "." + protocol + ".Handler";
    43. Class cls = null;
    44. try {
    45. cls = Class.forName(clsName);
    46. } catch (ClassNotFoundException e) {
    47. ClassLoader cl = ClassLoader.getSystemClassLoader();
    48. if (cl != null) {
    49. cls = cl.loadClass(clsName);
    50. }
    51. }
    52. if (cls != null) {
    53. handler = (URLStreamHandler)cls.newInstance();
    54. }
    55. } catch (Exception e) {
    56. // any number of exceptions can get thrown here
    57. }
    58. }
    59. }
    60.  
    61. synchronized (streamHandlerLock) {
    62.  
    63. URLStreamHandler handler2 = null;
    64.  
    65. // Check again with hashtable just in case another
    66. // thread created a handler since we last checked
    67. handler2 = (URLStreamHandler)handlers.get(protocol);
    68.  
    69. if (handler2 != null) {
    70. return handler2;
    71. }
    72.  
    73. // Check with factory if another thread set a
    74. // factory since our last check
    75. if (!checkedWithFactory && factory != null) {
    76. handler2 = factory.createURLStreamHandler(protocol);
    77. }
    78.  
    79. if (handler2 != null) {
    80. // The handler from the factory must be given more
    81. // importance. Discard the default handler that
    82. // this thread created.
    83. handler = handler2;
    84. }
    85.  
    86. // Insert this handler into the hashtable
    87. if (handler != null) {
    88. handlers.put(protocol, handler);
    89. }
    90.  
    91. }
    92. }
    93.  
    94. return handler;
    95.  
    96. }

    Explications  :

    1. Si le protocole a déjà été utilisé auparavant, il est présent dans la HashTable statique nommée handlers.
    2. Autrement, si une URLStreamHandlerFactory a été mise en place, le protocole est passé à la méthode createURLStreamHandler() de l'URLStreamHandlerFactory.
      Un objet URLStreamHandler est installé en utilisant la méthode statique setURLStreamHandlerFactory() de URL.
    3. Si le protocole n'a encore jamais été rencontré et qu'aucune URLStreamHandlerFactory n'est présente, une tentative est faite pour instancier un objet URLStreamHandler nommé <nom-du-protocole>.Handler dans un des packages listés dans la propriété système java.protocol.handler.pkgs
      • Si la valeur de cette propriété système n'est pas vide (null), elle est interprétée comme une liste de packages séparés par un trait vertical (|).
      • Le constructeur tente de charger la classe nommée : <nom-du-package>.<nom-du-protocole>.Handler
        Si cette classe n'existe pas, ou n'est pas une sous-classe de URLStreamHandler, le package suivant de la liste est essayé.
    4. Si il est impossible de trouver un URLStreamHandler dans la liste, le constructeur tente d'instancier un objet URLStreamHandler nommé : <nom-du-protocole>.Handler dans le package sun.net.www.protocol.
    5. Si cette classe n'existe pas ou si elle n'est pas une sous-classe de URLStreamHandler, une exception de type MalformedURLException est lancée.
  4. A présent que l'objet URL possède son « gestionnaire de flux » (en anglais, “Stream handler”), il demande à ce dernier de terminer l'« analyse » (en anglais, “parsing”) de la chaîne de caractères de l'URL, pour en extraire les valeurs qui lui permettront de constituer les propriétés de l'objet URL. C'est parce que le format d'une URL dépend du protocole utilisé qu'une grande part du travail de découpe de l'URL est réservé à un URLStreamHandler, qui connait les particularités du protocole, et non l'objet URL qui est plus générique et n'a pas de connaissance particulière des protocoles.
  5. Le programme appelle la méthode openConnection() sur l'objet URL. Cette méthode appelle elle-même la méthode openConnection(URL u) de URLStreamHandler, pour enfin retourner l'objet URLConnection approprié pour cet objet URL. Si un problème survient, une exception de type IOException est lancée.

    Notion avancée

    Au lieu d'appeller openConnection(), le programme peut appeller getContent() ou getInputStream(). Dans ce cas, l'objet URLStreamHandler instanciera un objet URLConnection de la classe appropriée. Quoi qu'il en soit, au lieu de retourner l'objet URLConnection lui-même, l'URLStreamHandler retourne le résultatde getContent() de URLConnection ou la méthode getInputStream().
  6. Le programme utilise les méthodes de la classe URLConnection pour interagir avec la ressource distante.

Document créé le 02/11/2005, dernière modification le 02/08/2019
Source du document imprimé : https://www.gaudry.be/java-protocol-handler.html

L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.

Notes

  1.  getURLStreamHandler : La méthode URLStreamHandler getURLStreamHandler(String protocol) ne figure pas dans la JavaDoc, mais existe bien dans la source de la classe URL.

  2.  gestionnaire de flux : correspond à “Stream handler” en anglais

  3.  analyse : correspond à “parsing” en anglais

  4. a,b Uniform Resource Locator : correspond à « localisateur uniforme de ressource » en français

  5. a,b URL : “Uniform Resource Locator” (en français, « localisateur uniforme de ressource »)

Table des matières Haut