Slashdot Mirror


LGPL is Viral for Java

carlfish writes "According to this post to POI-dev, Dave Turner (Mr License) of the FSF has decreed that the steps required to use an LGPL'd Java library will actually infect client code with substantial GNU-ness via Section 6 of the LGPL. (The "Lesser" GPL is supposed to protect only the Library, without infecting code using the library) This, as you might imagine, puts a few LGPL Java projects that previously thought they were embeddable without being viral in a bit of a bind. Various weblogs have further coverage." Update: 07/18 02:44 GMT by CN : The FSF's Executive Director, Brad Kuhn adds "LGPL's S. 6 allows you to make new works that link with the LGPL'ed code, and license them any way you see fit. Only the LGPL'ed code itself must remain Free. Such 'client code' can even be proprietary; it need not be LGPL'ed."

2 of 717 comments (clear)

  1. Re:The GPL is like a Vaccine by William+Tanksley · · Score: 4, Interesting

    If I decide to write a program and contribute it to free software, the GPL assures me that it will stay free software forever.

    Nope; if every copy disappears or becomes useless it's not free software (perhaps it's free, but it's arguably not software). That happens all the time with many different programs -- although by definition few of us have heard of them. (There's a LOT of them on Sourceforge right now.)

    Neither BSD nor GPL protects against that -- although the BSD license does have the possibility of attracting more users and developers due to the fact that it can be used as part of proprietary work. The only problem is that these developers can be invisible, never releasing their improvements; but that's a problem with not understanding the benefits and uses of open source.

    The BSD license lets people apply almost any license to my software, including most non-free licenses.

    Nope! It lets people apply almost any license to _derivative works_ of your work (including the trivial derivative work of simple redistribution). Your original work is yours until your copyright expires; they can't take it from you.

    Some of these pro-GPL arguments are as bad as the RIAA. "Help! They're STEALING OUR CODE!!!" At least you're not as bad as SCO: "We own all licensing rights for all derived works, but WE get to decide what's derived."

    I've thought about organizing a GPL-ed thread derived from the body of existing BSD-licensed work, just to illustrate a lesson about the BSD license. That would really piss people off, but it would be legal.

    The price of freedom is having to put up with knaves.

    Frankly, I'd be pissed if you forked my project, but it would be the needless fork that pissed me off, not the license (that doesn't apply to me because I'm BSD).

    Anyone who was pissed off would probably be so because you substituted a less freely usable license for a more free one.

    -Billy

  2. Re:Misleading article by CustomDesigned · · Score: 4, Interesting
    The 'import' statement in Java doesn't actually link anything - it is just a namespace declaration. However, when you refer at compile time to methods, fields, and constants in another class, the compiler actually reads in that class and does the equivalent of '#include done right'. This makes Java code that directly refers at compile time to LGPL code a derivative work.

    However, you can use a plugin model to use an LGPL library without directly importing it. You write an interface that your code imports, and write an implementation that imports both your interface and the LGPL library. The implementation of your plugin interface is now LGPL, inherited from the LGPL library. However, your code that that simply imports the interface is not LGPL.

    If you are wondering how the implementation class every gets instantiated without refering to it at compile time, then you are not an experienced Java programmer :-) The answer is that your factory class reads a config file to get the name of the implementation class, and then loads it via Class.forName() (or one of the more complex ClassLoader APIs).

    Now, your application has avoided becoming LGPL (except for the small class that implements the plugin API). Furthermore, you are conforming to the spirit of the LGPL because users of your application can easily adapt any future version of the LGPL library - or even their own innovation implementation - using your plugin API, and the working source you provide to 'plugin' the LGPL library.

    For illustration, suppose there is an LGPL library to translate any text from one language to another. It provides a Translator class (sorry, Slashdot doesn't seem to let me indent the code):

    /* LGPL license */
    package fsf.goodies;
    import java.util.Locale;
    public class C3P0 {
    public String translate(String msg,Locale src,Locale dst) {
    /* magic AI code here */
    }
    }
    Now, you want to use this in your BSD license UberChat application. You can't just use Translator, because then your app would need to be LGPL as well. Instead, you define an interface:
    /* BSD license */
    package org.bsd.uberchat;

    import java.util.Locale;

    public interface Translator {
    String translate(String msg,Locale src,Locale dst);
    }
    Then, you make a plugin that implements the Translator interface. Your plug in is LGPL because it uses the LGPL library.
    /* LGPL */
    import fsf.goodies.C3P0;
    public class C3P0Plugin implements Translator {
    /* in this trivial example (except for C3P0, that is), nothing more is required. In real life, you might need to massage arguments and do other processsing to match the interface with the implementation. */
    }
    Finally, you need a factory class to obtain a Translator instance:
    package org.bsd.uberchat;

    public class TranslatorFactory {
    /* Actually, there are more exceptions that needs to be handled in a real factory class. */
    static public Translator getTranslator() {
    Config config = new Config("uberchat");
    String cname = config.getString("translator");
    Object trans = Class.forName(cname);
    if (trans instanceof Translator)
    return (Translator)trans;
    throw new RuntimeException("translator plugin does not implement the proper interface");
    }
    }
    Finally, using the plugin is simple:
    package org.bsd.uberchat;
    import java.util.Locale;

    public class Foo {
    static public void main(String[] argv) {
    Translator t = TranslatorFactory.getTranslator();
    String msg = t.translate(argv[0],Locale.US,Local.GERMAN);
    &nbs p; System.out.println(msg);
    }
    }
    And, while none of this is tested, presumably with "fsf.goodies.C3P0" as the value of the "translator" property in your configuration framework (now included with Java 1.4), running
    java org.bsd.Foo "Good Day!"
    should result in an output of:
    Guten Tag!