Timmy: URL "normalisieren"

Hi,

Gibt es in (oder für) Java (se) eine Möglichkeit oder ein Tool um URLs aufzulösen? also dass aus

http://example.com/asdf/asdf2/./../../bla2/xy.html

das hier wird:

http://example.com/bla2/xy.html

  1. Hallo,

    Gibt es in (oder für) Java (se) eine Möglichkeit oder ein Tool um URLs aufzulösen? also dass aus

    Probier mal URI.normalize().

    Gruß
    Slyh

    1. Probier mal URI.normalize().

      Danke!
      Jetzt müsste ich nur mehr noch den unterschied zw. java.net.URI und java.net.URL wissen und wieso das eine nicht vom anderen erbt...

      1. Hi!

        Jetzt müsste ich nur mehr noch den unterschied zw. java.net.URI und java.net.URL wissen

        Das steht doch dort (Abschnitt: "URIs, URLs, and URNs").

        und wieso das eine nicht vom anderen erbt...

        URI: Since Java 1.4
        URL: Since Java 1.0

        Daher: Wegen der Abwärtskompatibilät?

        Gruß
        Bernhard

        1. Abwärtskompatibilät

          Hach Gott, wie dumm. Da hat die Rechtschreibprüfung noch gemeckert, aber keinen Verbesserungsvorschlag gemacht. Ist aber auch ein schwieriges Wort... ;-)

          "Abwärtskompatibilität" wird aber (gottlob) nicht bemeckert.

          Gruß
          Bernhard

        2. Hallo Bernhard,

          Daher: Wegen der Abwärtskompatibilität?

          Nein, dann wäre URL als deprecated markiert.
          URLs sind URIs die Resourcen auf eine direkt auflösbare Weise identifizieren. Die enthaltene Information reicht aus, um eine Verbindung aufzubauen und die Resource zu laden. Deswegen hat URL auch eine Methode openConnection, die URI nicht hat.
          URLs (im sinne der Java-Klasse) sind zudem immer absolut und normalisiert.
          Wenn man einfach mir URIs arbeiten muss in den verschiedenen möglichen varianten, sollte man also die URI-Klasse verwenden.
          Sobald man eine zugehörige Resource abrufen will, muss man dann eine URL daraus erzeugten (mit toURL()). Das geht natürlich nur bei URI-Instanzen, die absolut sind und eben URLs im Sinne des RFCs sind.

          Grüße

          Daniel

          1. Hi!

            Daher: Wegen der Abwärtskompatibilität?
            Nein, dann wäre URL als deprecated markiert.

            Wieso sollte URL deprecated sein? Das Konzept existiert nach wie vor. Früher hat man halt die generalisierte Variante (URI) noch nicht gekannt/implementiert/was auch immer.

            URLs sind URIs die Resourcen auf eine direkt auflösbare Weise identifizieren. Die enthaltene Information reicht aus, um eine Verbindung aufzubauen und die Resource zu laden. Deswegen hat URL auch eine Methode openConnection, die URI nicht hat.
            URLs (im sinne der Java-Klasse) sind zudem immer absolut und normalisiert.
            Wenn man einfach mir URIs arbeiten muss in den verschiedenen möglichen varianten, sollte man also die URI-Klasse verwenden.
            Sobald man eine zugehörige Resource abrufen will, muss man dann eine URL daraus erzeugten (mit toURL()). Das geht natürlich nur bei URI-Instanzen, die absolut sind und eben URLs im Sinne des RFCs sind.

            Alles schön und gut, aber: Warum verhindert das, dass URL von URI abgeleitet sein sollte?

            Gruß
            Bernhard

            1. Hallo Bernhard,

              Alles schön und gut, aber: Warum verhindert das, dass URL von URI abgeleitet sein sollte?

              Achso Dir geht es nur um die Vererbung.
              Kompatibilitätsgründe verhindern eigentlich nicht, dass man die Vererbungshierarchie in dieser Weise ändert. Auf Code der URL benutzt, hätte das ja keine Auswirkungen. Aber natürlich ist es schwierig, da die Schnittstelle von URL nie so entworfen wurde, dass man das von URI ableiten könnte. In soweit könnte das eine Rolle spielen.

              Die Frage ist, ob man das ableiten könnte, würde man es neu schreiben. Vermutlich wäre es keine gute Idee, da URL eine ziemlich andere Datenstruktur ist. URL ist immer normalisiert. Eine von URI abgeleitete Implementierung würde sich also ziemlich anders verhalten, als URI das eigentlich tut. Das sollte man bei Vererbung vermeiden, da Code der eine URI verwendet, sich ja nicht nur darauf verlässt, dass es die gleichen Methoden hat, sondern auch darauf, dass die das gleiche oder etwas sehr ähnliches tun.
              Das equals von URL ist auch etwas merkwürdig, da es irgendwie Domainnamen auflöst und IP-Adressen vergleicht. Hat mich mal ganz gut nerven gekostet ;-) Hatte irgendwelche Class-Loading und Sicherheitsgründe. Ok, das könnte man bei einem Redesign vielleicht schlauer machen.
              URL in der Funktionalität kann man also kaum von URI ableiten, evtl hätte man irgendwie URL als Wrapper für URIs entwerfen können oder ein gleiches Interface implementieren lassen.
              Zusammengefasst: Wahrscheinlich liegt es nicht nur daran, das URL einfach alt ist ;-)

              Grüße

              Daniel

              1. Hi!

                Alles schön und gut, aber: Warum verhindert das, dass URL von URI abgeleitet sein sollte?
                Kompatibilitätsgründe verhindern eigentlich nicht, dass man die Vererbungshierarchie in dieser Weise ändert. Auf Code der URL benutzt, hätte das ja keine Auswirkungen.

                Bist du da sicher?

                Ich denke mir folgendes: Fügt man URI als Oberklasse für URL hinzu, würde sich garantiert die Größe (im Sinne von Speicherbedarf) eines URL-Objektes ändern. Wenn man ein Java-Programm hat, welches noch mit einer älteren Java-Version, die URI als Oberklasse _nicht_ kennt, kompiliert wurde, und dieses einem neueren Interpreter verfüttert, kommt der dann zur Laufzeit einfach so mit den alten URL-Objekten zurecht?

                Aber natürlich ist es schwierig, da die Schnittstelle von URL nie so entworfen wurde, dass man das von URI ableiten könnte.

                Das wäre auf jeden Fall ein Problem.

                Die Frage ist, ob man das ableiten könnte, würde man es neu schreiben. Vermutlich wäre es keine gute Idee, da URL eine ziemlich andere Datenstruktur ist. URL ist immer normalisiert. Eine von URI abgeleitete Implementierung würde sich also ziemlich anders verhalten, als URI das eigentlich tut. Das sollte man bei Vererbung vermeiden, da Code der eine URI verwendet, sich ja nicht nur darauf verlässt, dass es die gleichen Methoden hat, sondern auch darauf, dass die das gleiche oder etwas sehr ähnliches tun.

                Den letzten Satz halte ich für falsch. Der Sinn der objektorientierten Programmierung ist ja gerade Polymorphismus, also die Möglichkeit, Unterklassen zu bilden und Methoden zu überschreiben und dass die jeweils zum konkreten Objekt passende zur Laufzeit aufgerufen wird ("dynamic binding"), auch wenn nur der Typ der Oberklasse bekannt ist. Dass diese Methode alles mögliche machen kann, sollte jeder OO-Programmierer wissen.

                Und Fakt bleibt einfach: Jeder URL ist ein URI.

                Gruß
                Bernhard

                1. Hallo Bernhard,

                  Kompatibilitätsgründe verhindern eigentlich nicht, dass man die Vererbungshierarchie in dieser Weise ändert. Auf Code der URL benutzt, hätte das ja keine Auswirkungen.
                  Bist du da sicher?

                  Naja, fast ;-) Bei Serialisierung bin ich mir nicht sicher, da würde es wohl knallen. Das würde es allerdings auch bei jedem zusätzlichen neuen Feld o.ä.  jedenfalls, wenn man nicht zusätzlich Code für die Deserialisierung von altem Kram schreibt.

                  Ich denke mir folgendes: Fügt man URI als Oberklasse für URL hinzu, würde sich garantiert die Größe (im Sinne von Speicherbedarf) eines URL-Objektes ändern.

                  Die Größe eines Objektes ist nicht garantiert. Du hast auch keine Chance herauszufinden, wie viel Speicherplatz ein Objekt wirklich belegt und wie es im Speicher abgelegt ist. Bei anderen Sprachen könnte das vielleicht ein Problem sein, bei Java aber nicht.

                  Wenn man ein Java-Programm hat, welches noch mit einer älteren Java-Version, die URI als Oberklasse _nicht_ kennt, kompiliert wurde, und dieses einem neueren Interpreter verfüttert, kommt der dann zur Laufzeit einfach so mit den alten URL-Objekten zurecht?

                  Ja das sollte es. Da steht ja nur drin, welche Klasse geladen werden soll (java.net.URL in dem Fall). Die VM wird die neue Klasse laden und so lang die Schnittstelle kompatibel ist, wird da nichts passieren.

                  Das sollte man bei Vererbung vermeiden, da Code der eine URI verwendet, sich ja nicht nur darauf verlässt, dass es die gleichen Methoden hat, sondern auch darauf, dass die das gleiche oder etwas sehr ähnliches tun.
                  Den letzten Satz halte ich für falsch. Der Sinn der objektorientierten Programmierung ist ja gerade Polymorphismus, also die Möglichkeit, Unterklassen zu bilden und Methoden zu überschreiben und dass die jeweils zum konkreten Objekt passende zur Laufzeit aufgerufen wird ("dynamic binding"), auch wenn nur der Typ der Oberklasse bekannt ist. Dass diese Methode alles mögliche machen kann, sollte jeder OO-Programmierer wissen.

                  Vielleicht hätte ich es genauer ausdrücken sollen. Natürlich darf eine erweiternde Klasse etwas anderes tun, das ist ja der Sinn. Allerdings haben Methoden neben ihrer Signatur in der Regel eine Spezifikation, die beschreibt, was sie tut. toString() gibt z.B. eine String-Darstellung eines Objektes zurück. Es wäre falsch, ihn ihrer Implementierung System.exit(0); aufzurufen. Natürlich kann man das tun und kein Compiler verhindert das, aber es verletzt die Vereinbarungen, die in der Dokumentation stehen bzw. von der Beschreibung dort her erwartet werden.
                  Viele andere Methoden haben noch viel genauere, auch explizit aufgeschriebene Spezifikationen.
                  Ein schönes, praktisches Beispiel sind hashCode() und equals(Object). Die werden öfter mal nicht ganz korrekt implementiert, was dann zu absolut unnachvollziehbarem Verhalten von HashSets u.ä. führt.

                  Bei URI kann man nun z.B. relative Pfade setzen oder auch nicht normalisierte. Wenn nun eine Klasse stattdessen RuntimeExceptions wirft, solche aufrufe ignoriert, oder sonst irgend etwas macht, wird Code, der sich darauf verlässt, nicht mehr funktionieren. Und man muss sich auf solche Vereinbarungen verlassen, sonst würde man ja nur noch hypothetische Ausnahmesituationen berücksichtigen.

                  Grüße

                  Daniel