UltraViolet: Death of digital content

29. July, 2010

UV radiation is invisible but extended exposure causes sunburn. It can also cause skin cancer which leads to certain death if not treated immediately. What an appropriate name for a new DRM system.

My guess is that it will help to kill sales of digital media like no technology before it. Why?

  1. It is supported by most of the important companies, so in a few years, you won’t be able to find consumer devices which don’t support it. Outside the OSS world that is.
  2. Did you know that you buy products because you like them? If that is so, then the products you buy tell about your psyche. In which mood are you today? Did you buy ABBA or Motörhead? Hmm… Imagine who might long for such information and how much.
  3. Finally you don’t have to spend hours selecting music for a friend, a coupon is enough. You can’t buy the music for them anymore because you can’t give it away anymore. Anything you buy will be yours. And yours only. Except if they are members of your family. Finally children can know what their parents read. And which movies the parents watch after the children were sent to bed. Did you know that most parents turn to their children for help with electronic devices?
  4. At long last DVDs and BlueRay disks will “just work“. No more sitting in front of a black screen because your DVD player can’t play the disk in the drive. And you won’t get an FBI warning either. They will know where you live the instant you try to play “content” you didn’t buy and sue you. Or kick your door in. Whatever they feel like. You’re just a petty criminal, like the molesters, thieves, murderers and other scum.
  5. UV will be anywhere (like in daylight). There will be no way to avoid it. Unless you stop buying. What an odd idea. Why would you stop giving money to greed…great companies who sue toddlers? Babies stink anyway. Stop making them. They only pollute the planet even more, they take room, breathe our air, eat our food and then refuse to pay for our pension. Buy more music instead! In UV2, we’ll figure out a way to sell condoms, too. Everything for our consumers!
  6. Of course this is a very complex technology, so the company behind it has meticulously created a roadmap which makes sure the most important features are available first. Which will be the ones that are paid for. By the companies using the technology to sell you stuff. But don’t worry. Eventually, when they run out of ideas how to spend the fortune they’ll make, they will eventually consider adding features for consumers. Eventually. Housing on the moon is so expensive. But well worth it: You can’t hear the complaints. And the view is priceless.
  7. Only very few, unimportant companies like Apple and Disney aren’t on the big, happy bandwagon. But don’t fear. In a short time, they will either be out of business (like they deserve) or see the light like everyone else.

Doesn’t that sound great? At last no more aggravation that you can’t play music on your Linux PC because the MP3 codec isn’t installed. No, finally you can be sure that no digital content, even if you bought it on a DVD and physically carried it home, will be owned by you. Or can be played on Linux. The Linux community, which has been spread like a virus for years, will be reduced again to the weirdos, sociopaths and communists. McCarthy would be so happy.

There is just one tiny problem. In Europe, there are some people called “data protection commissioners”. Unlike the name suggests, they are purely evil and as soon as they learn what the companies behind UV can do with the data they collect about the valued customers, they might try to outlaw the technology! Fret not, dear reader, the stupi…insight of the masses have always worked in our favor.

It won’t take long before new governments will be elected by careful persuasion of you with a little help of the, say, more “private” or, well, “odd” purchases you make. And if that doesn’t work, it should be possible to extrapolate your income this way and gently nudge the IRS who will be thankful of the service rendered by the law-abiding[*] companies behind the great new technology Ultraviolet!

[*] Read “we are the law”! And don’t you forget it! Now buy! The tires on my Ferrari are already dusty from the ride this morning! Yuck! I need a new one! Life is so … so … unjust!


Dependency Injection and Reference Passing

21. July, 2010

When you start using dependency injection (DI), you probably come from the painful world of singletons. Singletons are a lie. When we were doing structured programming (remember? What we did before OO?), that was called “global variable” and everyone knew they were bad. But hey, OO came along and we had the same problem and to solve it … we used global variables. Only we didn’t name them that. We said “It’s a Singleton!” and everybody was happy.

Except that the mighty singleton has the same problems as the global variable – because they are the same thing.

A solution was sought and DI was invented. When people start to use DI, they are still in the “Singleton” mind because you can’t get rid of an idea that has served you (more or less) well over many years. Since a human can’t simply forget what he’s been doing for a long time (it’s traditional), singletons leaked into DI leading to odd design which felt wrong.

Software developers are paid for their brains. If something feels wrong, it usually is. Most of the early code we come up with then starting with DI violates the Law of Demeter.

A common solution to the problems with many singletons is to replace them with a single singleton (for example one which loads and offers the application context in Spring). While this is convenient, we still have a global variable left.

Another solution is to write constructors that take 27 parameters so you can pass in all the parameters. If you avoid that trap, then your class will have 27 setters. Holy Ugly, Batman.

How to solve that? Use more DI. Most of the 27 ex-singletons will be passed on to other worker classes. So instead of passing on the singletons to create the worker classes deep down in the code, create the worker classes using DI (so the DI framework can fill in all the ex-singletons they need) and then pass in the 2-3 workers.

For some code, see this article: Dependency Injection Myth: Reference Passing


FreeType with hinting after patent expires

19. July, 2010

From the announcement:

Since May 2010, all patents regarding the TrueType bytecode interpreter have expired worldwide. Consequently, we now define TT_CONFIG_OPTION_BYTECODE_INTERPRETER by default (and undefine TT_CONFIG_OPTION_UNPATENTED_HINTING).

Finally.


Using the FindBugs plugin for Maven with Java 5

16. July, 2010

If you use the Maven 2 FindBugs plugin with Java 5 code, you will get a lot of errors like:

    Can't use annotations when running in JDK 1.4 mode!
    Can't use JDK 1.5 for loop syntax when running in JDK 1.4 mode!
    Can't use generics unless running in JDK 1.5 mode!
    Can't use enum as a keyword in pre-JDK 1.5 target

The solution is to set the targetJdk (even though this option isn’t mentioned in the docs and even mvn help:describe can’t find it):

                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>findbugs-maven-plugin</artifactId>
                    <version>2.3.1</version>
                    <configuration>
                        <targetJdk>1.5</targetJdk>
                    </configuration>
                </plugin>

Note that you should clean your project; otherwise the new option may not be used for some reason.


Debugging BIRT: How do I enable logging for OSGi/Equinox?

12. July, 2010

If you ever tried to enable logging for OSGi (Equinox) because starting the BIRT engine fails for mysterious reasons, you will have noticed that BIRT removes all osgi.* options from the System.properties before it launches (see ).

Instead, it expects these options in config.ini (which must be in the current folder):

# Specify the file with the debug options. See the .options file in the org.eclipse.osgi*.jar for examples
osgi.debug=/path/to/file/with/debug.options
# Change the classloader. Possible values are: "app", "fwk", "boot" (default)
# app: Use the current SystemClassLoader
# boot: Use the boot classloader
# fwk: Use the classloader which was used to load OSGi.
#osgi.parentClassloader=fwk

Use fwk if you see errors because of missing XML parser classes. The Java runtime has a private static field which contains the XML parser factory and if you touch any XML code before you start OSGi, then that field will be set and OSGi will be forced to use this XML parser — only the default boot classloader can’t see the parser. Bummer.


Ubunutu is safer than Windows

17. June, 2010

At least according to Dell.

See point 6 (“Ubuntu is safer than Microsoft® Windows®”). Let’s see how long the page will be available.

Update 21st of June 2010: The page is still there but it now just reads “Ubuntu is secure” and instead of “The vast majority of viruses and spyware written by hackers are not designed to target and attack Linux”, it just says “According to industry reports, Ubuntu is unaffected by the vast majority of viruses and spyware” 😉


Fluent Java library for collections: op4j

29. May, 2010

op4j is a nice little library for all those of us who need to work with collections. Here is a little example:

  Calendar now = Calendar.getInstance();
  Set<Calendar> set = 
      Op.on(list)
      .toSet()
      .map(FnString.toCalendar("dd/MM/yyyy"))
      .removeAllNullOrTrue(FnCalendar.after(now))
      .get();

That takes a list of strings, converts them to Calendar instances and removes all dates which are null or in the future. Questions?


Type-safe object map

28. May, 2010

Wouldn’t it be nice if you could do this:

        TypedMap map = new TypedMap();
        
        String expected = "Hallo";
        map.set( KEY1, expected );
        String value = map.get( KEY1 ); // Look Ma, no cast!
        assertEquals( expected, value );
        
        List<String> list = new ArrayList<String> ();
        map.set( KEY2, list );
        List<String> valueList = map.get( KEY2 ); // Even with generics
        assertEquals( list, valueList );

Note: The type checking is at compile time. No runtime cost!

As you can see, I get different types from the map without casting. How is that possible? Well, Generics can be your friends. The magic is in the key:

    final static TypedMapKey<String> KEY1 = new TypedMapKey<String>( "key1" );
    final static TypedMapKey<List<String>> KEY2 = new TypedMapKey<List<String>>( "key2" );

The keys contains two pieces of information: The actual key (a string) and the type which the value of the key has. The class for the key is completely braindead:

public class TypedMapKey<T> {
    private String name;
    
    public TypedMapKey(String name) {
        this.name = name;
    }
    
    public String name() {
        return name;
    }
}

The trick is to use the auto-resolution of the type at compile time in TypedMap. As you can see below, I need to suppress warnings about a typecast but the nice thing is: I only have to do it in this central place and the annotation is always correct (well, until you start to use set(String)).

As you can also see, I use delegation. I could have extended map but I wanted to show a pattern which you can use in other places … like HttpRequest or HttpSession.

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class TypedMap implements Map<String, Object> {
    private Map<String, Object> delegate;
    
    public TypedMap( Map<String, Object> delegate ) {
        this.delegate = delegate;
    }

    public TypedMap() {
        this.delegate = new HashMap<String, Object>();
    }
    
    @SuppressWarnings( "unchecked" )
    public <T> T get( TypedMapKey<T> key ) {
        return (T) delegate.get( key.name() );
    }
    
    @SuppressWarnings( "unchecked" )
    public <T> T remove( TypedMapKey<T> key ) {
        return (T) delegate.remove( key.name() );
    }
    
    public <T> void put( TypedMapKey<T> key, T value ) {
        delegate.put( key.name(), value );
    }
    
    // --- Only calls to delegates below
    
    public void clear() {
        delegate.clear();
    }

    public boolean containsKey( Object key ) {
        return delegate.containsKey( key );
    }

    public boolean containsValue( Object value ) {
        return delegate.containsValue( value );
    }

    public Set<java.util.Map.Entry<String, Object>> entrySet() {
        return delegate.entrySet();
    }

    public boolean equals( Object o ) {
        return delegate.equals( o );
    }

    public Object get( Object key ) {
        return delegate.get( key );
    }

    public int hashCode() {
        return delegate.hashCode();
    }

    public boolean isEmpty() {
        return delegate.isEmpty();
    }

    public Set<String> keySet() {
        return delegate.keySet();
    }

    public Object put( String key, Object value ) {
        return delegate.put( key, value );
    }

    public void putAll( Map<? extends String, ? extends Object> m ) {
        delegate.putAll( m );
    }

    public Object remove( Object key ) {
        return delegate.remove( key );
    }

    public int size() {
        return delegate.size();
    }

    public Collection<Object> values() {
        return delegate.values();
    }
}

Update 28. June 2010: As noticed by a couple of people on StackOverflow, this isn’t type safe if you define two keys with the same name.

Note that the code above is to wrap an existing map with a more type-safe API. If you want to make this even more type safe, create the map like so:

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class TypedMap implements Map<TypedMapKey<?>, Object> {
    private Map<TypedMapKey<?>, Object> delegate;
    
    public TypedMap( Map<TypedMapKey<?>, Object> delegate ) {
        this.delegate = delegate;
    }

    public TypedMap() {
        this.delegate = new HashMap<TypedMapKey<?>, Object>();
    }
    
    @SuppressWarnings( "unchecked" )
    public <T> T get( TypedMapKey<T> key ) {
        return (T) delegate.get( key.name() );
    }
...
}

Gall’s Law

21. May, 2010

I just stumbled over Gall’s Law:

“A complex system that works is invariably found to have evolved from a simple system that worked. The inverse proposition also appears to be true: A complex system designed from scratch never works and cannot be made to work. You have to start over, beginning with a working simple system.”

I you ever join a software project and someone mentions “complete rewrite”, you know two things for a fact:

  1. The current software sucks
  2. The rewrite will suck more.

Not convinced? See what Joel Spolsky has to say: Things You Should NEVER Do, Part I

If you still won’t believe, come back after the complete rewrite.


hg convert and “abort: Interrupted system call”

20. May, 2010

If you get “abort: Interrupted system call” when running “hg convert”, then see this issue for a workaround.