Substituting Java API classes for enhanced functionality (e.g. java.io.File)

Discussion in 'Java' started by Christian Schlichtherle, Jul 2, 2005.

  1. Hi,

    I have written a substitute for some java.io.* classes. My classes treat ZIP
    or JAR files exactly like directories, so that you can e.g. list ZIP files
    and arbitrarily read or write or delete their entries. My substitutes have
    the same name as in the java.io package, but live in their own package (e.g.
    de.schlichtherle.io.File instead of java.io.File). This provides 98% source
    code compatibility - most of the time a simple import statement at the top
    of a using class is enough to use the new functionality.

    To achieve 100% compatibility I would like to provide a modified classloader
    which loads my classes instead of the java.io.* classes. This is not a
    problem, as their is enough documentation on how to do it (basically you
    only need to override the loadClass(...) method). However, my classes
    delegate to the original java.io.* classes when e.g. encountering ordinary
    files.

    So how can I make an application using my classes as java.io.* when at the
    same time my classes need to delegate to the original java.io.* classes???

    Any hints would be helpful.

    With best regards,
    Christian
    Christian Schlichtherle, Jul 2, 2005
    #1
    1. Advertising

  2. Christian Schlichtherle

    Dale King Guest

    Re: Substituting Java API classes for enhanced functionality (e.g.java.io.File)

    Christian Schlichtherle wrote:
    > Hi,
    >
    > I have written a substitute for some java.io.* classes. My classes treat ZIP
    > or JAR files exactly like directories, so that you can e.g. list ZIP files
    > and arbitrarily read or write or delete their entries. My substitutes have
    > the same name as in the java.io package, but live in their own package (e.g.
    > de.schlichtherle.io.File instead of java.io.File). This provides 98% source
    > code compatibility - most of the time a simple import statement at the top
    > of a using class is enough to use the new functionality.
    >
    > To achieve 100% compatibility I would like to provide a modified classloader
    > which loads my classes instead of the java.io.* classes. This is not a
    > problem, as their is enough documentation on how to do it (basically you
    > only need to override the loadClass(...) method). However, my classes
    > delegate to the original java.io.* classes when e.g. encountering ordinary
    > files.
    >
    > So how can I make an application using my classes as java.io.* when at the
    > same time my classes need to delegate to the original java.io.* classes???


    Better reread the license for Java again. You'll find that such a thing
    would violate the license agreement:

    "Sun grants you a non-exclusive, non-transferable, limited license
    without fees to reproduce and distribute the Software, provided that...
    (iii) you do not distribute additional software intended to replace any
    component(s) of the Software..."

    --
    Dale King
    Dale King, Jul 2, 2005
    #2
    1. Advertising

  3. Re: Substituting Java API classes for enhanced functionality (e.g.java.io.File)

    Dale King wrote:
    > Christian Schlichtherle wrote:
    >
    >> Hi,
    >>
    >> I have written a substitute for some java.io.* classes. My classes
    >> treat ZIP or JAR files exactly like directories, so that you can e.g.
    >> list ZIP files and arbitrarily read or write or delete their entries.
    >> My substitutes have the same name as in the java.io package, but live
    >> in their own package (e.g. de.schlichtherle.io.File instead of
    >> java.io.File). This provides 98% source code compatibility - most of
    >> the time a simple import statement at the top of a using class is
    >> enough to use the new functionality.
    >>
    >> To achieve 100% compatibility I would like to provide a modified
    >> classloader which loads my classes instead of the java.io.* classes.
    >> This is not a problem, as their is enough documentation on how to do
    >> it (basically you only need to override the loadClass(...) method).
    >> However, my classes delegate to the original java.io.* classes when
    >> e.g. encountering ordinary files.
    >>
    >> So how can I make an application using my classes as java.io.* when at
    >> the same time my classes need to delegate to the original java.io.*
    >> classes???

    >
    >
    > Better reread the license for Java again. You'll find that such a thing
    > would violate the license agreement:
    >
    > "Sun grants you a non-exclusive, non-transferable, limited license
    > without fees to reproduce and distribute the Software, provided that...
    > (iii) you do not distribute additional software intended to replace any
    > component(s) of the Software..."
    >


    In addition to the license, there is a strong program readability
    objection to replacing java.lang classes.

    A reasonable Java programmer, seeing e.g. "import java.io.File;" at the
    top of a program, would expect references to type File in the code to
    mean the one in the normal API libraries.

    They would expect, for example, to be able to use features of a later
    version of File by merely installing a new JDK/JRE, with a new rt.jar.
    They would look at the Sun-distributed source code when trying to
    understand a NullPointerException with a java.io.File method in the
    stack trace.

    Patricia
    Patricia Shanahan, Jul 2, 2005
    #3
  4. Hi,

    I'm not breaking any of these statements as I would not redistribute Sun's
    JDK/JRE. My classes would simply be distributed as part of an application or
    a JAR library which requires the separately provided JDKJRE to run. There is
    actually no difference to any other application or library.

    Regards,
    Christian

    "Dale King" <> schrieb im Newsbeitrag
    news:Dqyxe.124533$nG6.98353@attbi_s22...
    > Christian Schlichtherle wrote:
    >> Hi,
    >>
    >> I have written a substitute for some java.io.* classes. My classes treat
    >> ZIP or JAR files exactly like directories, so that you can e.g. list ZIP
    >> files and arbitrarily read or write or delete their entries. My
    >> substitutes have the same name as in the java.io package, but live in
    >> their own package (e.g. de.schlichtherle.io.File instead of
    >> java.io.File). This provides 98% source code compatibility - most of the
    >> time a simple import statement at the top of a using class is enough to
    >> use the new functionality.
    >>
    >> To achieve 100% compatibility I would like to provide a modified
    >> classloader which loads my classes instead of the java.io.* classes. This
    >> is not a problem, as their is enough documentation on how to do it
    >> (basically you only need to override the loadClass(...) method). However,
    >> my classes delegate to the original java.io.* classes when e.g.
    >> encountering ordinary files.
    >>
    >> So how can I make an application using my classes as java.io.* when at
    >> the same time my classes need to delegate to the original java.io.*
    >> classes???

    >
    > Better reread the license for Java again. You'll find that such a thing
    > would violate the license agreement:
    >
    > "Sun grants you a non-exclusive, non-transferable, limited license without
    > fees to reproduce and distribute the Software, provided that... (iii) you
    > do not distribute additional software intended to replace any component(s)
    > of the Software..."
    >
    > --
    > Dale King
    Christian Schlichtherle, Jul 2, 2005
    #4
  5. Hi,

    please note that no application could use this code just by accident. There
    needs to be some static method call in front to replace the genuine
    java.io.File by installing a custom class loader for the running thread. It
    would actually work a bit like installing pluggable UI classes for Swing.
    Thus, whoever uses it does know that he is not dealing with a genuine
    java.io.File.

    Second, if someone wants to upgrade to a new JDK/JRE, fine: Just do it and
    my replacement classes will delegate to the updated JDK/JRE when needed
    (e.g. when working on ordinary files rather than ZIP files), so there is no
    need to worry about this.

    Third, thanks to the delegation, the whole API is tested to be 100% backward
    compatible with JDK 1.4.2 and JDK 1.5.0. Whatever you do with ordinary files
    and directories, my API will behave exactly the same as the genuine
    java.io.* classes (including exception throwing).

    Thinking in layers, here is how it works in terms of program flow:

    Application code -> substituted java.io.* -> genuine java.io.* (residing in
    rt.jar)

    As you can see, the rt.jar is not touched (reengineered or whatever) at all.
    My substitute is just an add-on. It needs to be installed once by any
    application who wants to use its enhanced features.

    Regards,
    Christian

    "Patricia Shanahan" <> schrieb im Newsbeitrag
    news:iAyxe.3000$...
    > Dale King wrote:
    >> Christian Schlichtherle wrote:
    >>
    >>> Hi,
    >>>
    >>> I have written a substitute for some java.io.* classes. My classes treat
    >>> ZIP or JAR files exactly like directories, so that you can e.g. list ZIP
    >>> files and arbitrarily read or write or delete their entries. My
    >>> substitutes have the same name as in the java.io package, but live in
    >>> their own package (e.g. de.schlichtherle.io.File instead of
    >>> java.io.File). This provides 98% source code compatibility - most of the
    >>> time a simple import statement at the top of a using class is enough to
    >>> use the new functionality.
    >>>
    >>> To achieve 100% compatibility I would like to provide a modified
    >>> classloader which loads my classes instead of the java.io.* classes.
    >>> This is not a problem, as their is enough documentation on how to do it
    >>> (basically you only need to override the loadClass(...) method).
    >>> However, my classes delegate to the original java.io.* classes when e.g.
    >>> encountering ordinary files.
    >>>
    >>> So how can I make an application using my classes as java.io.* when at
    >>> the same time my classes need to delegate to the original java.io.*
    >>> classes???

    >>
    >>
    >> Better reread the license for Java again. You'll find that such a thing
    >> would violate the license agreement:
    >>
    >> "Sun grants you a non-exclusive, non-transferable, limited license
    >> without fees to reproduce and distribute the Software, provided that...
    >> (iii) you do not distribute additional software intended to replace any
    >> component(s) of the Software..."
    >>

    >
    > In addition to the license, there is a strong program readability
    > objection to replacing java.lang classes.
    >
    > A reasonable Java programmer, seeing e.g. "import java.io.File;" at the
    > top of a program, would expect references to type File in the code to
    > mean the one in the normal API libraries.
    >
    > They would expect, for example, to be able to use features of a later
    > version of File by merely installing a new JDK/JRE, with a new rt.jar.
    > They would look at the Sun-distributed source code when trying to
    > understand a NullPointerException with a java.io.File method in the
    > stack trace.
    >
    > Patricia
    Christian Schlichtherle, Jul 2, 2005
    #5
  6. Re: Substituting Java API classes for enhanced functionality (e.g.java.io.File)

    Christian Schlichtherle wrote:
    > Hi,
    >
    > please note that no application could use this code just by accident. There
    > needs to be some static method call in front to replace the genuine
    > java.io.File by installing a custom class loader for the running thread. It
    > would actually work a bit like installing pluggable UI classes for Swing.
    > Thus, whoever uses it does know that he is not dealing with a genuine
    > java.io.File.


    I've done a lot of maintenance work, so I tend to think about
    programming in terms of picking up a large, unfamiliar program and
    attempting a bug fix or feature extension, rather than writing a program
    from scratch. In my model of programming, some other programmer, who I
    may never have met, did the work to use your code before I even knew the
    application existed. Even when I am writing from scratch, that model
    influences my programming.

    Most interesting programs are far too large for me to completely read
    and understand them before starting productive work. The better a
    programming style supports selective reading the better I like it.

    I would not expect to need to read the application initialization flow
    to understand what a java.io class does, for a Zip file or for any other
    sort of file. I find that out by reading the java.io javadocs.

    The requirement to put a distinguishing import statement in each file
    that depends on your package is a valuable feature, not a bug. The
    frustrating thing is that, with the import, your package looks very
    useful. Without it, it opens up fresh fields for code obfuscation in java.

    > Second, if someone wants to upgrade to a new JDK/JRE, fine: Just do it and
    > my replacement classes will delegate to the updated JDK/JRE when needed
    > (e.g. when working on ordinary files rather than ZIP files), so there is no
    > need to worry about this.


    How do you make sure the JVM will not object when I call a method that
    was added to a java.io class, say around JDK 1.8.2, but does not exist
    in the corresponding class in your package?

    On the licensing issue, how to do you interpret item C in "SUPPLEMENTAL
    LICENSE TERMS", in the JDK 1.5 license?

    Patricia
    Patricia Shanahan, Jul 2, 2005
    #6
  7. "Patricia Shanahan" <> schrieb im Newsbeitrag
    news:9LBxe.86$...
    > I would not expect to need to read the application initialization flow
    > to understand what a java.io class does, for a Zip file or for any other
    > sort of file. I find that out by reading the java.io javadocs.


    Although I understand your point (cause I do have the same experience), I'ld
    like to add something: Your criticism applies the same to the pluggable L&F
    of Swing and any other pluggable code based on Reflection. This feature
    really does make code harder to debug und understand, but looking at all the
    plugin code and all sorts of *Beans stuff, I also think that this kind of
    "dynamic linking" is one of the core advantages of Java compared to e.g.
    C++. Without this ability, we wouldn't have (Enterprise) JavaBeans or SPI
    code (like in the java.security package) at all. In essence, Java wouldn't
    be Java.

    >> Second, if someone wants to upgrade to a new JDK/JRE, fine: Just do it
    >> and my replacement classes will delegate to the updated JDK/JRE when
    >> needed (e.g. when working on ordinary files rather than ZIP files), so
    >> there is no need to worry about this.

    >
    > How do you make sure the JVM will not object when I call a method that
    > was added to a java.io class, say around JDK 1.8.2, but does not exist
    > in the corresponding class in your package?


    That's a fair point: If the classloader approach would work, all that is
    required for a normal application is to compile the code against the java.io
    package. If that changes, my plugin code would need to change as well. I
    might be able to provide this through the use of the Proxy class, but still
    this would leave the opportunity of my code to yield new methods which do
    not behave correctly when used within ZIP files.

    > On the licensing issue, how to do you interpret item C in "SUPPLEMENTAL
    > LICENSE TERMS", in the JDK 1.5 license?


    I would not (re)distribute JREs or JDKs, so that term doesn't apply at all.

    After all, the point about maintainability makes me rethink the strategy
    again: The existing de.schlichtherle.io package works fine for about nine
    months in daily use. But as it needs to inherit from java.io.File (in order
    for a JFileChooser to browse ZIP files), there are some subtle traps which I
    hoped to escape by turning the package into a pluggabe replacement for the
    java.io package...

    With best regards,
    Christian
    Christian Schlichtherle, Jul 2, 2005
    #7
  8. Christian Schlichtherle

    Joan Guest

    "Christian Schlichtherle" <> wrote in message
    news:da5pcf$l7i$...
    > Hi,
    >
    > I have written a substitute for some java.io.* classes. My classes treat

    ZIP
    > or JAR files exactly like directories, so that you can e.g. list ZIP files
    > and arbitrarily read or write or delete their entries.


    Why bother, microsoft "explorer" does this already.

    > My substitutes have
    > the same name as in the java.io package, but live in their own package

    (e.g.
    > de.schlichtherle.io.File instead of java.io.File). This provides 98%

    source
    > code compatibility - most of the time a simple import statement at the top
    > of a using class is enough to use the new functionality.
    >
    > To achieve 100% compatibility I would like to provide a modified

    classloader
    > which loads my classes instead of the java.io.* classes. This is not a
    > problem, as their is enough documentation on how to do it (basically you
    > only need to override the loadClass(...) method). However, my classes
    > delegate to the original java.io.* classes when e.g. encountering ordinary
    > files.
    >
    > So how can I make an application using my classes as java.io.* when at the
    > same time my classes need to delegate to the original java.io.* classes???
    >
    > Any hints would be helpful.
    >
    > With best regards,
    > Christian
    >
    >
    Joan, Jul 3, 2005
    #8
  9. Christian Schlichtherle

    John Currier Guest

    John Currier, Jul 5, 2005
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Andy Fish
    Replies:
    2
    Views:
    392
    Young Seeker
    Dec 29, 2003
  2. Marc Schellens

    enhanced file info

    Marc Schellens, Aug 24, 2004, in forum: C++
    Replies:
    2
    Views:
    324
    Thomas Matthews
    Aug 24, 2004
  3. Skip Montanaro
    Replies:
    0
    Views:
    454
    Skip Montanaro
    Nov 21, 2004
  4. Replies:
    2
    Views:
    121
Loading...

Share This Page