Snippet: JAXB and CDATA ContentHandler with CharacterEscapeHandler

Main program:

package com.tutego.jaxb;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.PrintWriter;

public class App {
  public static void main( String[] args ) throws Exception {
    Dog dog = new Dog();
    dog.name = "Wüffi";
    Flea flea = new Flea();
    flea.name = "<><> Böser Floh <><>";
    dog.flea = flea;

    JAXBContext jaxbContext = JAXBContext.newInstance( dog.getClass() );
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    jaxbMarshaller.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, true );
    jaxbMarshaller.marshal( dog, new CDATAContentHandler( new PrintWriter( System.out ) ) );
  }
}

Dog and Flea:

package com.tutego.jaxb;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Dog {
  public String name;
  public Flea flea;
}

class Flea {
  public String name;
}

CDATAContentHandler:

package com.tutego.jaxb;

import com.sun.xml.txw2.output.CharacterEscapeHandler;
import com.sun.xml.txw2.output.DataWriter;
import org.xml.sax.SAXException;
import java.io.IOException;
import java.io.Writer;

public class CDATAContentHandler extends DataWriter {
  public CDATAContentHandler( Writer writer ) {
    super( writer, "UTF-8", MinimumEscapeHandler.theInstance );
  }

  @Override
  public void characters( char[] ch, int start, int length ) throws SAXException {
    boolean useCData = false;

    loop:
    for ( int i = start; i < start + length; i++ )
      switch ( ch[ i ] ) {
        case '<': case '>': case '&': useCData = true;
        break loop;
      }

    if ( useCData ) super.startCDATA();
    super.characters( ch, start, length );
    if ( useCData ) super.endCDATA();
  }
}

/**
 * Performs no character escaping. Usable only when the output encoding
 * is UTF, but this handler gives the maximum performance.
 *
 * @author Kohsuke Kawaguchi (kohsuke.kawaguchi@sun.com)
 */
class MinimumEscapeHandler implements CharacterEscapeHandler {

  private MinimumEscapeHandler() {
  }  // no instanciation please

  public static final CharacterEscapeHandler theInstance = new MinimumEscapeHandler();

  public void escape( char[] ch, int start, int length, boolean isAttVal, Writer out )
      throws IOException {
    // avoid calling the Writerwrite method too much by assuming
    // that the escaping occurs rarely.
    // profiling revealed that this is faster than the naive code.
    int limit = start + length;
    for ( int i = start; i < limit; i++ ) {
      char c = ch[ i ];
      if ( c == '&' || c == '<' || c == '>' || c == '\r' || (c == '\n' && isAttVal) || (c == '\"' && isAttVal) ) {
        if ( i != start )
          out.write( ch, start, i - start );
        start = i + 1;
        switch ( ch[ i ] ) {
          case '&':
            out.write( "&amp;" );
            break;
          case '<':
            out.write( "&lt;" );
            break;
          case '>':
            out.write( "&gt;" );
            break;
          case '\"':
            out.write( "&quot;" );
            break;
          case '\n':
          case '\r':
            out.write( "&#" );
            out.write( Integer.toString( c ) );
            out.write( ';' );
            break;
          default:
            throw new IllegalArgumentException( "Cannot escape: '" + c + "'" );
        }
      }
    }

    if ( start != limit )
      out.write( ch, start, limit - start );
  }
}

Retrieve Windows netstat data and observe new network connections

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

public class Netstat {

  public static class Protocol {

    public final String protocol;
    public final String localAddress;
    public final String remoteAddress;
    public final String status;

    public Protocol( String protocol, String localAddress, String remoteAddress, String status ) {
      this.protocol = protocol;
      this.localAddress = localAddress;
      this.remoteAddress = remoteAddress;
      this.status = status;
    }

    @Override
    public int hashCode() {
      return Objects.hash( localAddress, protocol, remoteAddress, status );
    }

    @Override
    public boolean equals( Object obj ) {
      if ( this == obj )
        return true;
      if ( obj == null )
        return false;
      if ( getClass() != obj.getClass() )
        return false;
      Protocol other = (Protocol) obj;
      if ( localAddress == null && other.localAddress != null )
        return false;
      else if ( !localAddress.equals( other.localAddress ) )
        return false;
      if ( protocol == null && other.protocol != null )
        return false;
      else if ( !protocol.equals( other.protocol ) )
        return false;
      if ( remoteAddress == null && other.remoteAddress != null )
        return false;
      else if ( !remoteAddress.equals( other.remoteAddress ) )
        return false;
      if ( status == null && other.status != null )
        return false;
      else if ( !status.equals( other.status ) )
        return false;
      return true;
    }

    @Override
    public String toString() {
      return String.format( "%-6s %-22s %-22s %s", protocol, localAddress, remoteAddress, status );
    }
  }

  private final static Pattern pattern = Pattern.compile( "(TCP|UDP)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)" );

  public static Collection<Protocol> netStat() throws IOException {
    Collection<Protocol> result = new ArrayList<>();
    Process p = new ProcessBuilder( "netstat", "-n" ).start();
    try ( Scanner scanner = new Scanner( p.getInputStream() ) ) {
      while ( scanner.findWithinHorizon( pattern, 0 ) != null )
        result.add( new Protocol( scanner.match().group( 1 ), scanner.match().group( 2 ),
                                   scanner.match().group( 3 ), scanner.match().group( 4 ) ) );
    }
    return result;
  }

  public static void main( String[] args ) throws IOException, InterruptedException {
    Set<Protocol> oldStat = new HashSet<>( netStat() );

    while ( true ) {
      TimeUnit.SECONDS.sleep( 10 );

      HashSet<Protocol> newStat = new HashSet<>( netStat() );

      Set<Protocol> differenceSet = new HashSet<>( newStat );
      differenceSet.removeAll( oldStat );

      for ( Protocol p : differenceSet )
        System.out.println( p );

      oldStat = newStat;
    }
  }
}

Snippet: NETSTAT in Java with command line call

import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;

public class Netstat
{
  public static class Protocoll
  {
    public String protocoll;
    public String localAddress;
    public String remoteAddress;
    public String status;

    public Protocoll( String protocoll, String localAddress, String remoteAddress, String status )
    {
      this.protocoll = protocoll;
      this.localAddress = localAddress;
      this.remoteAddress = remoteAddress;
      this.status = status;
    }

    @Override
    public String toString()
    {
      return String.format( "%-6s %-22s %-22s %s", protocoll, localAddress, remoteAddress, status );
    }
  }

  public static void main( String[] args ) throws IOException
  {
    for ( Protocoll p : netStat() )
      System.out.println( p );
  }

  public static Iterable<Protocoll> netStat() throws IOException
  {
    Collection<Protocoll> result = new ArrayList<>();
    ProcessBuilder builder = new ProcessBuilder( "netstat", "-n" );
    Process p = builder.start();
    try ( Scanner scanner = new Scanner( p.getInputStream() ) ) {
      Pattern pattern = Pattern.compile( "(TCP|UDP)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)" );
      while ( scanner.findWithinHorizon( pattern, 0 ) != null )
        result.add( new Protocoll( scanner.match().group( 1 ), scanner.match().group( 2 ), scanner.match().group( 3 ), scanner.match().group( 4 ) ) );
    }
    return result;
  }
}

This leads to something like

TCP    127.0.0.1:16709        127.0.0.1:49159        HERGESTELLT

TCP    127.0.0.1:19872        127.0.0.1:49176        HERGESTELLT

TCP    127.0.0.1:49159        127.0.0.1:16709        HERGESTELLT

TCP    127.0.0.1:49176        127.0.0.1:19872        HERGESTELLT

TCP    127.0.0.1:49189        127.0.0.1:49190        HERGESTELLT

TCP    127.0.0.1:49190        127.0.0.1:49189        HERGESTELLT

Snippet: List all MessageDigest provider

Pattern digestPattern = Pattern.compile( "^(Alg\\.Alias\\.)?MessageDigest\\.(?<alg>(\\w|-)+)" );
for ( Provider p : Security.getProviders() ) {
  for ( Object o : Collections.list( p.keys() ) ) {
    for ( Matcher m = digestPattern.matcher( o.toString() ); m.find(); )
      System.out.println( m.group("alg") );
  }
}

The result is:

SHA-1 SHA MD5 SHA-384 SHA-512 SHA1 SHA MD5 SHA-256 MD2

Also look at http://download.java.net/jdk8/docs/technotes/guides/security/StandardNames.html.

Snippet: Kalender ausdrucken, Teil 2: von-bis

Die erste Version meines Kalenderprogramms druckte ein Kalender für ein Jahr. In Anwendungen dürfte häufiger vorkommen, dass es ein Start- und Enddatum gibt, das auch über Jahresgrenzen liegt. Das macht dieses Programm:

public static class CalLine
{
  public int year;
  public int weekOfYear;
  public int month = -1;  // 0 <= month <= 11
  public int[] day = { -1, -1, -1, -1, -1, -1, -1 };
}

public static List<CalLine> calenderOfTheYear( Date start, Date end )
{
  Calendar startCal = new GregorianCalendar();
  startCal.setTime( start );
  Calendar endCal = new GregorianCalendar();
  endCal.setTime( end );
  return calenderOfTheYear( startCal, endCal );
}

public static List<CalLine> calenderOfTheYear( Calendar start, Calendar end )
{
  List<CalLine> lines = new ArrayList<>();

  // Calender instances are mutable, so copy them
  Calendar startCal = (Calendar) start.clone(); 
  Calendar endCal   = (Calendar) end.clone(); 

  // For start date: first go backwards to the beginning of the month
  // then find monday of this week
  while ( startCal.get( Calendar.DAY_OF_MONTH ) != 1 )
    startCal.add( Calendar.DAY_OF_YEAR, -1 );
  while ( startCal.get( Calendar.DAY_OF_WEEK ) != Calendar.MONDAY )
    startCal.add( Calendar.DAY_OF_YEAR, -1 );

  // For end date: go forwards and find end of month
  // then find sunday of this week
  while ( endCal.get( Calendar.DAY_OF_MONTH ) != startCal.getActualMaximum( Calendar.DAY_OF_MONTH ) )
    endCal.add( Calendar.DAY_OF_YEAR, 1 );
  while ( endCal.get( Calendar.DAY_OF_WEEK ) != Calendar.SUNDAY )
    endCal.add( Calendar.DAY_OF_YEAR, 1 );
  endCal.add( Calendar.DAY_OF_YEAR, 1 );  // add 1 to test with < not <=

  CalLine line = new CalLine();

  while ( startCal.before( endCal ) ) {
    if ( line.year == 0 )
      line.year = startCal.get( Calendar.YEAR );
    if ( line.weekOfYear == 0 )
      line.weekOfYear = startCal.get( Calendar.WEEK_OF_YEAR );

    int dayOfMonth = startCal.get( Calendar.DAY_OF_MONTH );
    int dayOfWeek  = startCal.get( Calendar.DAY_OF_WEEK );

    if ( dayOfMonth == 1 )
      line.month = startCal.get( Calendar.MONTH );

    line.day[dayOfWeek - 1] = dayOfMonth;

    if ( dayOfWeek == Calendar.SUNDAY ) {
      // Days are Sun, Mon, ..., Sat. Rearange to Mon, ..., Sun 
      int first = line.day[ 0 ]; // This is faster then System.arraycopy()
      line.day[ 0 ] = line.day[ 1 ]; line.day[ 1 ] = line.day[ 2 ]; line.day[ 2 ] = line.day[ 3 ];
      line.day[ 3 ] = line.day[ 4 ]; line.day[ 4 ] = line.day[ 5 ]; line.day[ 5 ] = line.day[ 6 ];
      line.day[ 6 ] = first;

      lines.add( line );
      line = new CalLine();   // it ends always with SUN, last line is not added
    }

    startCal.add( Calendar.DAY_OF_YEAR, 1 );
  }

  return lines;
}

Beispielaufruf:

List<CalLine> lines = DateUtils.calenderOfTheYear( new GregorianCalendar( 2011, Calendar.NOVEMBER, 12 ), new GregorianCalendar( 2012, Calendar.JANUARY, 22 ) );

String[] monthNames = { "Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez" };
System.out.println( "KW        Mo Do Mi Do Fr Sa So" ); // to lazy for DateFormatSymbols here...

for ( CalLine l : lines ) {
  String monthStr = (l.month == -1) ? "   " : monthNames[ l.month ];
  String s = String.format( "%2d  %s   %(2d %(2d %(2d %(2d %(2d %(2d %(2d",
                            l.weekOfYear, monthStr,
                            l.day[0], l.day[1], l.day[2], l.day[3], l.day[4], l.day[5], l.day[6] ).replace( "(1)", "  " );
  System.out.println( s );
}

Das führt zu

KW        Mo Do Mi Do Fr Sa So
44  Nov   31  1  2  3  4  5  6
45         7  8  9 10 11 12 13
46        14 15 16 17 18 19 20
47        21 22 23 24 25 26 27
48  Dez   28 29 30  1  2  3  4
49         5  6  7  8  9 10 11
50        12 13 14 15 16 17 18
51        19 20 21 22 23 24 25
52  Jan   26 27 28 29 30 31  1
 1         2  3  4  5  6  7  8
 2         9 10 11 12 13 14 15
 3        16 17 18 19 20 21 22
 4        23 24 25 26 27 28 29
 5  Feb   30 31  1  2  3  4  5

Snippet: Kalender des Jahres ausgeben

Angeregt durch den Compact Calendar (http://davidseah.com/compact-calendar/) wollte ich etwas ähnliches in meine Webanwendung einbauen, sodass das Ergebnis tabellenartig wie https://docs.google.com/spreadsheet/ccc?key=0AkyxK00VLnSidEl1SS1sZjZiVlpuRnJIY1JmUW9IRHc#gid=0 formatiert wird.

import java.text.DateFormatSymbols;
import java.util.*;

public class PrintCalender
{
  public static class CalLine
  {
    int weekOfYear; 
    int month = -1;  // 0 <= month <= 11 
    int[] day = { -1, -1, -1, -1, -1, -1, -1 }; 
  }

  public static List<CalLine> calenderOfTheYear( int year )
  {
    Calendar cal = new GregorianCalendar( year, 1, 1 );

    List<CalLine> lines = new ArrayList<>();
    CalLine line = new CalLine();

    for ( int dayOfYear = 1; dayOfYear <= cal.getActualMaximum( Calendar.DAY_OF_YEAR ); dayOfYear++ ) {
      cal.set( Calendar.DAY_OF_YEAR, dayOfYear );
      line.weekOfYear = cal.get( Calendar.WEEK_OF_YEAR ); // Set several times, thats ok

      int dayOfMonth = cal.get( Calendar.DAY_OF_MONTH );
      int dayOfWeek  = cal.get( Calendar.DAY_OF_WEEK );

      if ( dayOfMonth == 1 )
        line.month = cal.get( Calendar.MONTH );

      line.day[dayOfWeek - 1] = dayOfMonth;

      if ( dayOfWeek == Calendar.SUNDAY ) {
        lines.add( line );
        line = new CalLine();
      }
    }
    lines.add( line );
    return lines;
  }
  
  public static void main( String[] args )
  {
    List<CalLine> lines = calenderOfTheYear( 2012 );

    String[] monthNames = new DateFormatSymbols( Locale.GERMANY ).getMonths();
    System.out.println( "KW        Mo Do Mi Do Fr Sa So" ); // to lazy for DateFormatSymbols here...

    for ( CalLine l : lines ) {
      String monthStr = (l.month == -1) ? "   " : monthNames[ l.month ].substring( 0, 3 );
      // Days are Sun, Mon, ..., Sat. Rearange to Mon, ..., Sun
      String s = String.format( "%2d  %s   %(2d %(2d %(2d %(2d %(2d %(2d %(2d",
                                l.weekOfYear, monthStr,
                                l.day[1], l.day[2], l.day[3], l.day[4], l.day[5], l.day[6], l.day[0] ).replace( "(1)", "  " );
      System.out.println( s );
    }
  }
}

Zur Demo gibt eine Textausgabe (mit einem Hack). Das Ergebnis für dieses Jahr:

kw        mo do mi do fr sa so
52  jan                      1
 1         2  3  4  5  6  7  8
 2         9 10 11 12 13 14 15
 3        16 17 18 19 20 21 22
 4        23 24 25 26 27 28 29
 5  feb   30 31  1  2  3  4  5
 6         6  7  8  9 10 11 12
 7        13 14 15 16 17 18 19
 8        20 21 22 23 24 25 26
 9  mär   27 28 29  1  2  3  4
10         5  6  7  8  9 10 11
11        12 13 14 15 16 17 18
12        19 20 21 22 23 24 25
13  apr   26 27 28 29 30 31  1
14         2  3  4  5  6  7  8
15         9 10 11 12 13 14 15
16        16 17 18 19 20 21 22
17        23 24 25 26 27 28 29
18  mai   30  1  2  3  4  5  6
19         7  8  9 10 11 12 13
20        14 15 16 17 18 19 20
21        21 22 23 24 25 26 27
22  jun   28 29 30 31  1  2  3
23         4  5  6  7  8  9 10
24        11 12 13 14 15 16 17
25        18 19 20 21 22 23 24
26  jul   25 26 27 28 29 30  1
27         2  3  4  5  6  7  8
28         9 10 11 12 13 14 15
29        16 17 18 19 20 21 22
30        23 24 25 26 27 28 29
31  aug   30 31  1  2  3  4  5
32         6  7  8  9 10 11 12
33        13 14 15 16 17 18 19
34        20 21 22 23 24 25 26
35  sep   27 28 29 30 31  1  2
36         3  4  5  6  7  8  9
37        10 11 12 13 14 15 16
38        17 18 19 20 21 22 23
39        24 25 26 27 28 29 30
40  okt    1  2  3  4  5  6  7
41         8  9 10 11 12 13 14
42        15 16 17 18 19 20 21
43        22 23 24 25 26 27 28
44  nov   29 30 31  1  2  3  4
45         5  6  7  8  9 10 11
46        12 13 14 15 16 17 18
47        19 20 21 22 23 24 25
48  dez   26 27 28 29 30  1  2
49         3  4  5  6  7  8  9
50        10 11 12 13 14 15 16
51        17 18 19 20 21 22 23
52        24 25 26 27 28 29 30
 1        31                  

			

How to put files in a ZIP file with NIO.2

URI p = Paths.get( "c:/Users/Christian/Dropbox/jokes.zip" ).toUri();
URI uri = URI.create( "jar:" + p );

Map<String, String> env = new HashMap<>();
env.put( "create", "true" );
try ( FileSystem zipfs = FileSystems.newFileSystem( uri, env ) ) {
  Files.write( zipfs.getPath( "/j1.txt" ), "The truth is out there. Anybody got the URL?".getBytes() );
  Files.write( zipfs.getPath( "/j2.txt" ), "The more I C, the less I see.".getBytes() );
}