Update der Swing JIDE Komponenten auf Version 3.3.4

Kleine Änderungen bei den http://www.jidesoft.com/products/component.htm:

  • (Common) Added CheckBoxListSelectionModel#setCheckAllEntry() to control the default behavior of CheckBoxList for "all" entry.
  • (Common) Added isEnsureFontExistence to FontNameConverter.
  • (Common) Added IconBorder class which can paint an icon as part of the border which is perfect to be used in the table cell through the CellStyle feature.
  • (Common) Added a new component StyledToolTip.
  • (Component) Set tooltip to the PregressStatusBarItem so that the message can still be shown even when the message is too long.
  • (Grids) Fixed so that CellStyleTableHeader could support the new StyledToolTip.
  • (Grids) Added overlayCellPainter and underlayCellPainter to CellStyle.
  • (Grids) Added HeaderLineWrapModel interface to configure the line wrap properties for column header easier.
  • (Grids) Added paintCellUnderlay method to paint the cell background below the cell content.
  • (Grids) Added JideTableTransferHandler to accept importing data by default.
  • (Grids) Added MarginExpandablePanel#getIcon(Node) to customize the icon easier.
  • (Pivot) Added two APIs in PivotTablePane to customize the data table selection behavior. See the enhancement request here.
  • (TreeMap) Improved robustness of colormap creation.
  • (TreeMap) Added support for opening File instances through context menu.
  • (TreeMap) Added support for ordering by ascending sizes.

Mehr unter http://www.jidesoft.com/history/.

Freies Buch “The Architecture of Open Source Applications”

http://www.aosabook.org/en/index.html:

Inhalt:

 

Introduction

Amy Brown and Greg Wilson

ix

1.

Asterisk

Russell Bryant

1

2.

Audacity

James Crook

15

3.

The Bourne-Again Shell

Chet Ramey

29

4.

Berkeley DB

Margo Seltzer and Keith Bostic

45

5.

CMake

Bill Hoffman and Kenneth Martin

67

6.

Eclipse

Kim Moir

77

7.

Graphite

Chris Davis

101

8.

The Hadoop Distributed
File System

Robert Chansler, Hairong Kuang, Sanjay Radia,
Konstantin Shvachko, and Suresh Srinivas

111

9.

Continuous Integration

C. Titus Brown and Rosangela Canino-Koning

125

10.

Jitsi

Emil Ivov

139

11.

LLVM

Chris Lattner

155

12.

Mercurial

Dirkjan Ochtman

171

13.

The NoSQL Ecosystem

Adam Marcus

185

14.

Python Packaging

Tarek Ziadé

205

15.

Riak and Erlang/OTP

Francesco Cesarini, Andy Gross, and Justin Sheehy

229

16.

Selenium WebDriver

Simon Stewart

245

17.

Sendmail

Eric Allman

271

18.

SnowFlock

Roy Bryant and Andrés Lagar-Cavilla

291

19.

SocialCalc

Audrey Tang

303

20.

Telepathy

Danielle Madeley

325

21.

Thousand Parsec

Alan Laudicina and Aaron Mavrinac

345

22.

Violet

Cay Horstmann

361

23.

VisTrails

Juliana Freire, David Koop, Emanuele Santos,
Carlos Scheidegger, Claudio Silva, and Huy T. Vo

377

24.

VTK

Berk Geveci and Will Schroeder

395

25.

Battle For Wesnoth

Richard Shimooka and David White

411

 

Bibliography

   
 

Making Software

   

Diagnose Kommandos kommen in Java 8 und Java 7u4

Das werden wir im nächsten Build bekommen, Quellen schon mal hier: http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/0194fe5ca404.

A diagnostic command is an action that can be invoked dynamically mainly for troubleshooting and diagnosis.

Die Idee ist also, das man ein Kommandozeilentool jcmd hat, mit dem man Kommandos an die JVM schicken kann. Dabei sind unterschiedliche Kommandos vordefiniert. Mit dem Argument PerfCounter.perf werden Performance-Kenngrößen ausgegeben.

NetBeans 7.1 Code-Transformation nach Java 7

Wähle im Menü Refactor > Inspect and Transform … und dann im Dialog bei Use:/Configuration: den Eintrag Convert to Java 7 aus. Ein Klick auf Inspect startet die Suche und listet Änderungsmöglichkeiten auf und bietet an, die Stellen automatisch zu beheben.

Ich habe das Tool auf den Beispielen meines Buches angewendet und die meisten Hinweise beziehen sich auf Diamond und natürlich im IO-Kapitel auf auf try-mit-Ressourcen. Damit habe ich heute den ganzen Tag verbracht und auch noch ein paar kleine Fehler gefunden. Eine Stelle ist interessant:

XMLOutputFactory factory = XMLOutputFactory.newInstance();
XMLStreamWriter writer = factory.createXMLStreamWriter( new FileOutputStream( "writenParty.xml" ) );

XMLStreamWriter hat close() aber kein AutoCloseable. Kann man als Fehler ansehen.

Das hier formt der Konverter nicht um, er beginnt erst bei “fett” mit dem switch, das liegt am zweiten if, was nicht als if else formuliert ist.

if ( "Ende".equals(e.getActionCommand()) )
  System.exit( 0 );
if ( "fett".equals(e.getActionCommand()) )
  t.setFont( font = font.deriveFont( font.getStyle() ^ Font.BOLD ) );
else if ( "kursiv".equals(e.getActionCommand()) )
  t.setFont( font = font.deriveFont( font.getStyle() ^ Font.ITALIC ) );

Inselupdate: Vererbung und Überschattung von statischen Variablen

Die Konstanten einer Schnittstelle können einer anderen Schnittstelle vererbt werden. Dabei gibt es einige kleine Einschränkungen. Wir wollen an einem Beispiel sehen, wie sich die Vererbung auswirkt, wenn gleiche Bezeichner in den Unterschnittstellen erneut verwendet werden. Als Basis unseres Beispiels steht eine Schnittstelle BaseColors mit ein paar Deklarationen von Farben. Zwei Unterschnittstellen erweiterten BaseColor, einmal CarColors und PlaneColors, die für Farbdeklarationen für Autos und Flugzeuge stehen. Eine besondere Schnittstelle FlyingCarColors erweitert die beiden Schnittstelen CarColors und PlaneColors, denn es gibt auch fliegende Autos, die eine Farbe haben können.

interface BaseColors
{
  int WHITE   = 0;
  int BLACK   = 1;
  int GREY    = 2;
}

interface CarColors extends BaseColors
{
  int WHITE   = 1;
  int BLACK   = 0;
}

interface PlaneColors extends BaseColors
{
  int WHITE   = 0;
  int GREY    = 2;
}

interface FlyingCarColors extends CarColors, PlaneColors
{
}

public class Colors
{
  public static void main( String[] args )
  {
    System.out.println( BaseColors.GREY );      // 2
    System.out.println( CarColors.GREY );       // 2
    System.out.println( BaseColors.BLACK );     // 1
    System.out.println( CarColors.BLACK );      // 0
    System.out.println( PlaneColors.BLACK );    // 1

    System.out.println( FlyingCarColors.WHITE );//  The field FlyingCarColors.WHITE is ambiguous
    System.out.println( FlyingCarColors.GREY ); //  The field FlyingCarColors.GREY is ambiguous
  }
}

Die erste wichtige Tatsache ist, dass unsere drei Schnittstellen ohne Fehler übersetzt werden können, aber nicht die Klasse Colors. Das Programm und der Compiler zeigen folgendes Verhalten:

  • Schnittstellen vererben ihre Eigenschaften an die Unterschnittstellen. CarColors und auch PlaneColors erbten die Farbe WHITE, BLACK und GREY aus BaseColors.
  • Konstanten dürfen überschattet werden. CarColors vertauscht die Farbdeklarationen von WHITE und BLACK und gibt ihnen neue Werte. Wird jetzt der Wert CarColors.BLACK verlangt, liefert die Umgebung den Wert 0, während CarColors.BLACK 1 ergibt. Auch PlaneColor überdeckt die Konstanten WHITE und GREY obwohl sie Farbe mit dem gleichen Wert belegt sind.
  • Erbt eine Schnittstelle von mehreren Oberschnittstellen, so ist es zulässig, wenn die Oberschnittstellen jeweils ein gleichlautendes Attribut haben. So erbt etwa FlyingCarColors von CarColors und PlaneColors den Eintrag WHITE, BLACK und GREY.
  • Unterschnittstellen können aus zwei Oberschnittstellen die Attribute gleichen Namens übernehmen, auch wenn sie einen unterschiedlichen Wert haben. Das testet der Compiler nicht. FlyingCarColors bekommt aus CarColors ein WHITE mit 1 aber aus PlaneColors das Weiß mit 0. Daher ist auch der Zugriff FlyingCarColors.WHITE in dem Beispiel Colors auch nicht möglich und führt zu einem Compilerfehler. Bei der Benutzung muss ein unmissverständlicher qualifizierter Name verwendet werden, der deutlich macht, welches Attribut gemeint ist, also zum Beispiel CarColors.WHITE oder PlaneColors.WHITE. Ähnliches gilt für die Farbe GREY. Obwohl Grau durch die ursprüngliche Deklaration bei BaseColor und auch bei der Überschattung in PlaneColors immer Zwei ist, ist die Nutzung durch FlyingCarColors.GREY nicht zulässig. Das ist ein guter Schutz gegen Fehler, denn wenn der Compiler dies durchließe, könnte sich im Nachhinein die Belegung von GREY in BaseColors oder PlaneColors ohne Neuübersetzung aller Klassen ändern, und zu Schwierigkeiten führen. Diesen Fehler – die Oberschnittstellen haben für eine Konstante unterschiedliche Werte – müsste die Laufzeitumgebung erkennen. Doch das ist nicht möglich und in der Regel setzt der Compiler die Werte auch direkt in die Aufrufstelle ein und ein Zugriff auf die Konstantenwerte der Schnittstelle findet nicht mehr statt.

Google Guava: Delete all files in a directory (now deprecated)

The java.io.File class can delete a file but not a collection of files or a whole directory including its containing files. com.google.common.io.Files declares two methods to do this job:

  • static void deleteDirectoryContents(File directory)
    Delete all the files within a directory but not the directory itself. If the contents of this or any subdirectory can’t be listed an IOException("Error listing files for " + directory) will be thrown.
  • static void deleteRecursively(File file) throws IOException
    Delete a file or directory and all contents recursively. This methods calls deleteDirectoryContents() first and then file.delete(). If this directory can’t be deleted an IOException("Failed to delete " + file) will be thrown.

Because a file can be a symbolic link it is important to understand the semantics of these methods. If a containing file or directory is a symbolic link will the symbolic link itself be deleted or will the method follow the link and delete the target? None of the methods follow symbolic links because it’s simply not possible with the JDK. If these methods find a symbolic link then just the link will be deleted. But what if the methods are called on a directory which is itself a symbolic link?

If deleteDirectoryContents() is called on a File object which is a symbolic link to a directory nothing will happen at all because as already mentioned symbolic links are not followed; so deleteDirectoryContents() will not delete the directory the method was called on. If on the other site deleteRecursively() is called on a symbolic link then just the symbolic link to this directory is deleted but not the target directory itself. That’s just how symbolic links works in Java and has nothing to do with the actual deleteXXX()-methods.

 

Alternative: Use NIO.2 from Java 7 or copy the old source code to your project.

Google Guava 11

Neues unter http://code.google.com/p/guava-libraries/wiki/Release11, genauer http://docs.guava-libraries.googlecode.com/git-history/v11.0/jdiff/changes.html. 2 neue Pakete sind:

Mit der neuen MathInt Klasse beschäftigt sich ausführlicher der Blogpost http://marxsoftware.blogspot.com/2011/12/guava-release-11s-intmath.html.

Guava AppendableWriter (internal class) and CharStream.asWriter()

With the current version the class is now package visible! If you want to use the class, copy it in your project and make it public. Or make use of CharStream.asWriter().

 

The classes StringWriter, CharArrayWriter and ByteArrayOutputStream have two things in common: a) They are sinks and when you write into them you ask these classes for the collected result; b) the internal buffer always starts empty. So for getting the result the classes offer different methods:

  • StringWriter: toString() return the buffer’s current value as a string.
  • CharArrayWriter: toCharArray() returns a copy of the input data as a char array; toString() returns the input data as a String.
  • ByteArrayOutputStream: toByteArray() returns a newly allocated byte array with a copy of the stream data. toString(String enc) converts the buffer’s contents into a String object, translating bytes into characters according to the given character encoding. The parameter less methode toString() uses the default encoding.

One can see the second point, that every of these sink classes starts with an empty buffer, as a disadvantage. If one wants to append to an existing String or char or byte array this has to be done in a second step. It would be nice to have a class, lets say StringBuilderWriter, which writes into a mutable StringBuilder. But Java SE doesn’t offer such a class.

The Google Collection library provides a class AppendableWriter which writes into an Appendable. The Appendable interface was introduced in Java 5 and is implemented by classes to whom you can append chars or Strings to. It dictates three methods:

  • Appendable append(char c)
  • Appendable append(CharSequence csq)
  • Appendable append(CharSequence csq, int start, int end)

Implementing classes are among others:

  • StringBuilder, StringBuffer
  • Every Writer-class; the base class implements Appendable (this was retrofitted in Java 5)

So to write into a StringBuilder all you have to do is:

StringBuilder sb = new StringBuilder( "start-" );
Writer w = new AppendableWriter( sb );
w.write( "middle" );
w.close();
sb.append( "-end" );
System.out.println( sb ); // start-middle-end

So with AppendableWriter its easy to represent every Appendable as a Writer. This is exactly what the static method asWriter() in the utility class CharStreams does:

public static Writer asWriter(Appendable target) {
 if (target instanceof Writer) {
  return (Writer) target;
 }
 return new AppendableWriter(target);
}

If the Appendable is already of subtype Writer it does not make sense to wrap it in an AppendableWriter again, so the target is directly returned. But what happens if you call close() or flush() on this special Writer—an Appendable doesn’t have close() neither flush()? The answer is simple: If you call close()/flush() on an AppendableWriter the implementation checks if the constructor argument implements Closeable/Flushable and calls close()/flush() accordingly. That means if you close/flush this Writer the close()/flush() operation will be delegated otherwise—for example in the case of StringBuilder with does neither implement Closeable nor Flushable—nothing happens.

FindBugs 2 ist da

Nach dem auf der Mailingliste schon seit längerem eine Version 2 angekündigt wurde, mussten Entwickler doch noch längere Zeit warten. Jetzt ist es soweit. Infos unter http://findbugs.sourceforge.net/findbugs2.html und http://code.google.com/p/findbugs/w/list.

Die Version 2 kann man gleich über JNLP mit ein paar Sourcen ausprobieren:

Im JDK finden sich immer noch einige Fehler, toll, was FindBugs so findet. Das hier zum Beispiel:

  • if (name != null || name.length > 0).  Ist name == null, wird name.length zu einer NPE führen. Hier muss ein && statt ||.

oder

  • if (lookbehind.length() == 1) {
      char c0 = (lookbehind == null) ? ‚|‘ : lookbehind.charAt(0);

oder

  • if (!wellformed){
      if (!wellformed){

oder

if ((parent instanceof LiteralElement) ||
        (parent instanceof LiteralElement)) {

oder

  • boolean isInitValueValid(int v) {
       if ((v < 0) || (v > SnmpUnsignedInt.MAX_VALUE)) {

COOL!

Erster Draft von JSR-335 (Lambda) verfügbar + Devoxx Folien

Siehe http://mail.openjdk.java.net/pipermail/lambda-dev/2011-November/004191.html bzw. http://jcp.org/en/jsr/detail?id=335.

Folien zur aktuellen Lambda-Version von der Konferenz sind hier: http://blogs.oracle.com/briangoetz/resource/devoxx-lang-lib-vm-co-evol.pdf.

Der aktuelle Compiler weist aber noch Unterschiede auf, sie werden hier diskutiert: http://mail.openjdk.java.net/pipermail/lambda-dev/2011-November/004253.html.