Michel Krämer http://www.michel-kraemer.de Michel Krämers Blog über Open Source und Software-Entwicklung mit Scala, Java und C++, sowie anderen hilfreichen Tipps und Tricks. Mon Apr 09 18:47:37 +0200 2012 de hourly 1 bson4jackson 2.0 wurde soeben veröffentlicht! http://www.michel-kraemer.de/bson4jackson-2.0-wurde-soeben-ver%F6ffentlicht http://www.michel-kraemer.de/bson4jackson-2.0-wurde-soeben-ver%F6ffentlicht#comments 2012-04-09T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/bson4jackson-2.0-wurde-soeben-ver%F6ffentlicht Die Version 2.0 von bson4jackson wurde soeben veröffentlicht. bson4jackson erweitert den Jackson JSON processor um das BSON-Format, eine binäre Repräsentation von JSON. Die neuste Version unterstützt nun auch Jackson 2.0.]]> Die Version 2.0 von bson4jackson wurde soeben veröffentlicht. bson4jackson erweitert den Jackson JSON processor um das BSON-Format, eine binäre Repräsentation von JSON. Die neuste Version unterstützt nun auch Jackson 2.0.

Enda O'Donohoe hat zwei Bugs im UTF-8-Dekoder behoben. Vielen Dank dafür!

Die Unterstützung für Jackson 2.0 wurde hauptsächlich von James Roper beigesteuert. Vielen Dank für deine Beiträge, James!

bson4jackson wird ab sofort keine älteren Version von Jackson mehr unterstützen. Falls Sie nach einer Version suchen, die mit Jackson 1.x läuft, dann laden Sie bitte bson4jackson 1.3.0 herunter.

Weitere Informationen

Eine vollständige Übersicht über bson4jackson (inkl. Hinweisen zum Download) findet man in meinem Tutorial.

]]>
Verbesserte MongoDB-Unterstützung für bson4jackson http://www.michel-kraemer.de/verbesserte-mongodb-unterstuetzung-fuer-bson4jackson http://www.michel-kraemer.de/verbesserte-mongodb-unterstuetzung-fuer-bson4jackson#comments 2011-12-17T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/verbesserte-mongodb-unterstuetzung-fuer-bson4jackson bson4jackson Version 1.2.0 wurde gerade veröffentlicht. bson4jackson erweitert den Jackson JSON processor um das BSON-Format, eine binäre Repräsentation von JSON. Dank zahlreicher Beiträge aus der Community bietet das neue Release von bson4jackson nun eine verbesserte Unterstützung für MongoDB.]]> bson4jackson Version 1.2.0 wurde gerade veröffentlicht. bson4jackson erweitert den Jackson JSON processor um das BSON-Format, eine binäre Repräsentation von JSON. Dank zahlreicher Beiträge aus der Community bietet das neue Release von bson4jackson nun eine verbesserte Unterstützung für MongoDB.

Gergő Ertli hat einen Fehler bei der Unterstützung des ObjectId-Typs behoben. Object IDs werden von MongoDB als primäre Schlüssel für Dokumente verwendet.

Die Unterstützung für den UUID-Typ wurde von Ed Anuff implementiert. Er hat ein Modul hinzugefügt, das bei Jacksons ObjectMapper registriert werden kann:

ObjectMapper om = new ObjectMapper(new BsonFactory());
om.registerModule(new BsonUuidModule());

Dank der Beteiligung von James Roper unterstützt die BsonParser-Klasse nun das Feature HONOR_DOCUMENT_LENGTH. Es bringt den Parser dazu, die ersten 4 Bytes, also die Größe eines Dokuments, auszuwerten und zu beachten. Natürlich funktioniert dies nur, wenn das Feature BsonGenerator.Feature.ENABLE_STREAMING nicht während der Erzeugung des Dokuments aktiviert war.

Das Feature ist besonders nützlich, um mehrere Dokumente aus einem Input-Stream von MongoDB zu lesen. Es kann wie folgt aktiviert werden:

BsonFactory fac = new BsonFactory();
fac.enable(BsonParser.Feature.HONOR_DOCUMENT_LENGTH);
BsonParser parser = (BsonParser)fac.createJsonParser(...);

Darüber hinaus wurden zahlreiche kleinere Fehler behoben. Die Bibliothek wurde mit Jackson 1.7 bis 1.9 getestet.

Weitere Informationen

Eine vollständige Übersicht über bson4jackson (inkl. Hinweisen zum Download) findet man in meinem Tutorial.

]]>
Build Scala projects with Eclipse Buckminster http://www.michel-kraemer.de/build-scala-projects-with-eclipse-buckminster http://www.michel-kraemer.de/build-scala-projects-with-eclipse-buckminster#comments 2011-06-26T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/build-scala-projects-with-eclipse-buckminster In one of my previous posts I talked about how to build Scala projects with PDE Build. However, PDE Build is rather old and has long been superseded by Buckminster. The great advantage of Buckminster is that it is actually a lightweight Eclipse SDK with all that you need to build an RCP application: a workspace of projects, a target platform, and so on. To build Scala projects in Eclipse you will most likely install the Scala IDE. Unfortunately, this plug-in cannot be installed in Buckminster right away. But there is a workaround...]]> In one of my previous posts I talked about how to build Scala projects with PDE Build. However, PDE Build is rather old and has long been superseded by Buckminster. The great advantage of Buckminster is that it is actually a lightweight Eclipse SDK with all that you need to build an RCP application: a workspace of projects, a target platform, and so on. To build Scala projects in Eclipse you will most likely install the Scala IDE. Unfortunately, this plug-in cannot be installed in Buckminster right away. But there is a workaround...

Short disclaimer: in this article I'm not going to describe how to actually build projects with Buckminster. This article is rather about how to install Buckminster, so it is able to handle Scala projects like any other project. If you need a more general description, please refer to the Buckminster website.

Why Buckminster?

Let's first talk about why I prefer Buckminster over other solutions. Compared to other build tools, Buckminster has one great advantage: it provides an environment very similar to the one you're developing in—the Eclipse SDK. You can see Buckminster as a lightweight Eclipse SDK without all this distracting UI stuff, but with a command line interface instead. However, Buckminster still has a workspace where you can import your projects into, and of course a target platform which defines the environment for your RCP application. Running a Buckminster-driven build with continuous integration systems like Hudson/Jenkins is also very easy, since all you have to do is to create some configuration files—a resource map and a CQuery—and then run a simple command on the shell like buckminster build. However, there there is also a plug-in available for Hudson/Jenkins, which automatically downloads and installs Buckminster if necessary. For more information on the usage please refer to the great book Buckminster, The definitive guide by Henrik Lindberg and Thomas Hallgren.

Buckminster is also one of the few tools that are able to build a full-featured Eclipse RCP application. There are extensions for other build tools like Ant or—since we're talking about building Scala projects here—sbt. For example, Bnd is one of them. It allows building OSGi bundles without the need for creating a MANIFEST.MF file manually. Besides, you can always package your OSGi bundles yourself using the jar tool, but that is really not enough for serious RCP development.

If you want to build your RCP application headlessly, you have to use a tool that is really aware of what it is building. It has to understand the complex dependencies between your projects and the OSGi bundles from the target platform you use. Apart from that, it has to be able to parse files like MANIFEST.MF, build.properties, plugin.xml as well as configurations stored in .product or feature.xml files.

As far as I know, there are only three products available which support all these features—or at least most of them: PDE Build, Maven Tycho and of course Buckminster. I mention PDE Build here since it was formerly the recommended way to build RCP applications, but has now been superseded by Buckminster. PDE Build is also only a set of Ant scripts and does not support all of the aforementioned features. Tycho, on the other hand, has recently become a mature solution. It integrates very tightly into the well-known Maven build tool. This makes it very easy for people who are using Tycho for the first time, but already know Maven. Apart from that, Tycho contains some cool features like archetypes which automatically create pom.xml files for the bundles to build.

Nevertheless, I found Tycho always being slower than Buckminster—at least for very large projects with a lot of bundles. I don't know if this has something to do with the support for incremental builds in multi-module projects (Is this still a problem with Maven 3 anyhow?) or with the way Tycho is resolving the target platform and how it calculates bundle dependencies. Apart from that, Tycho builds projects in a slightly different environment than they are developed in. This eliminates all of the aforementioned advantages of having a build environment that is very similar to the Eclipse SDK—as I said, this is in fact what you have when you use Buckminster. These disadvantages make it of course not impossible to build RCP applications, but they are the reason why I would prefer Buckminster over Tycho. Of course, this may change eventually, since Tycho is continuously developed.

How to install Buckminster and the Scala IDE normally

There is a Buckminster plug-in for the Eclipse SDK which adds a context menu with build tasks to all workspace projects. You simply install it using the p2 update manager. The current update site can be found at http://www.eclipse.org/buckminster/downloads.html.

Installing this plug-in and then installing the Scala IDE is very easy and lets you build Scala-featured OSGi bundles in a few minutes. Nevertheless, setting up Buckminster with the Scala IDE for headless operation is a little bit harder. If you follow the documentation very strictly, you will do the following things:

First you have to download the latest version of the p2 director application: director_latest.zip. You can then install the Buckminster RCP application with the following command:

$ director -r <url to headless repo> -d <buckminster install folder>
      -p Buckminster -i org.eclipse.buckminster.cmdline.product

This will download Buckminster from the supplied update site—which can be found on this site—and install it into the given folder. After that you will most likely want to install some additional features in order to enable headless builds. Change into the directory where you installed Buckminster and run the following commands, for example:

$ buckminster install <headless repo> org.eclipse.buckminster.core.headless.feature
$ buckminster install <headless repo> org.eclipse.buckminster.emma.headless.feature
$ buckminster install <headless repo> org.eclipse.buckminster.git.headless.feature
$ buckminster install <headless repo> org.eclipse.buckminster.pde.headless.feature

Additionally, you have to install the Scala IDE into Buckminster. Go to http://download.scala-ide.org and select the update site that fits your needs. Then run the following command:

$ buckminster install <scala ide repo> org.scala-ide.sdt.feature

Cannot complete the install because one or more required items could not be found.
[0]Software being installed: Scala IDE for Eclipse 2.0.0
     (org.scala-ide.sdt.feature.feature.group 2.0.0)
[0]Missing requirement: Scala IDE for Eclipse 2.0.0
     (org.scala-ide.sdt.feature.feature.group 2.0.0)
   requires 'org.eclipse.ui.navigator 0.0.0' but it could not be found

Oops! What happened? It seems like the Scala IDE requires user interface bundles, but my Buckminster runs on the command line!

Workaround

In order to work around this problem, you have to install Buckminster a little bit differently. First, you need the p2 director application again, but this time you will install the Eclipse SDK:

$ director -r <eclipse sdk repo url> -d <eclipse install folder>
      -profileProperties org.eclipse.update.install.features=true
      -p SDKProfile -i org.eclipse.sdk.ide

After that, change into the directory where you just installed Eclipse and run the following commands to install Buckminster:

$ eclipse -nosplash -application org.eclipse.equinox.p2.director
      -r <url to buckminster headless repo>
      -i org.eclipse.buckminster.core.headless.feature.feature.group
      -i org.eclipse.buckminster.emma.headless.feature.feature.group
      -i org.eclipse.buckminster.git.headless.feature.feature.group
      -i org.eclipse.buckminster.pde.headless.feature.feature.group

Please note the additional .feature.group at the end of each feature to install.

Finally, you can install the Scala IDE:

$ eclipse -nosplash -application org.eclipse.equinox.p2.director
      -r <scala ide repo>
      -i org.scala-ide.sdt.feature.feature.group
      -i org.scala-ide.sdt.weaving.feature.feature.group

This should succeed without errors.

From now on you can launch Buckminster with the following command:

$ eclipse -nosplash -application org.eclipse.buckminster.cmdline.headless

You may get the following exception when the Scala IDE bundles are started:

java.lang.IllegalStateException: Workbench has not been created yet

This is due to the fact that you don't have a UI and thus no workbench. Fortunately, there's an (undocumented?) system property you can set to avoid this exception. Simply add the following line at the end of your eclipse.ini:

-Dsdtcore.headless

This tells the Scala IDE that you're running it in headless mode and that it should avoid accessing the workbench.

Summary

In this article I described how to headlessly build Scala projects with Buckminster. I talked about why I prefer Buckminster over other build tools and presented a workaround for installing Buckminster and the Scala IDE with the command line.

After installing Buckminster this way, you will have a full fledged tool to build Eclipse RCP applications including Scala plug-ins. However, installing a complete SDK would not be necessary if the Scala IDE bundles did not depend on Eclipse's UI. It's probably possible to create a feature containing only the core plugins like it has been done for the Groovy plug-in, but that's something the Scala IDE team has to figure out in the future.

Nevertheless, a complete Eclipse SDK has also an advantage worth to mention: everything that works on your local machine will also work on your headless build server. Actually, you may even install your local Eclipse the same way as described above. Then you can absolutely be sure that your application is built in the same environment as it is developed in. This can make debugging a lot easier.

]]>
Binäres JSON mit bson4jackson http://www.michel-kraemer.de/binaeres-json-mit-bson4jackson http://www.michel-kraemer.de/binaeres-json-mit-bson4jackson#comments 2011-01-30T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/binaeres-json-mit-bson4jackson JSON hat sich inzwischen als hervorragende Alternative zu XML etabliert. Die meisten JSON-Parser in Java sind jedoch noch relativ langsam. Auf meiner Suche nach schnelleren Libraries bin ich auf zwei Dinge gestoßen: BSON und Jackson.]]> JSON hat sich inzwischen als hervorragende Alternative zu XML etabliert. Die meisten JSON-Parser in Java sind jedoch noch relativ langsam. Auf meiner Suche nach schnelleren Libraries bin ich auf zwei Dinge gestoßen: BSON und Jackson.

BSON ist binär kodiertes JSON. Das Format ist besonders darauf ausgelegt, schnell und einfach maschinell lesbar zu sein. BSON wurde bekannt durch seine Verwendung als primäres Austauschformat für das dokumentenorientierte Datenbankmanagementsystem MongoDB. Jackson ist laut dem JVM Serializers Benchmark einer der schnellsten JSON-Prozessoren, die es gibt. Außerdem bietet Jackson die Möglichkeit, eigene Erweiterungen hinzuzufügen und somit die Bibliothek um weitere Austauschformate zu ergänzen.

bson4jackson

Das ist der Punkt, an dem bson4jackson ins Spiel kommt. Die Bibliothek erweitert Jackson um die Möglichkeit, BSON-Dokumente zu lesen und zu schreiben. Dadurch, dass bson4jackson vollständig integriert ist, kann man die wirklich sehr gelungene API von Jackson nutzen. Somit lassen sich einfache POJOs sehr schnell serialisieren. Angenommen man möchte Objekte der folgende Klasse mittels BSON austauschen:

public class Person {
  private String _name;
 
  public void setName(String name) {
    _name = name;
  }
 
  public String getName() {
    return _name;
  }
}

Dann kann man den so genannten ObjectMapper benutzen, der das schnelle Serialisieren von POJOs erlaubt:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.undercouch.bson4jackson.BsonFactory;
 
public class ObjectMapperSample {
  public static void main(String[] args) throws Exception {
    //create dummy POJO
    Person bob = new Person();
    bob.setName("Bob");
 
    //serialize data
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectMapper mapper = new ObjectMapper(new BsonFactory());
    mapper.writeValue(baos, bob);
 
    //deserialize data
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    Person clone_of_bob = mapper.readValue(bais, Person.class);
 
    assert bob.getName().equals(clone_of_bob.getName());
  }
}

Oder man verwendet die Streaming API von Jackson und serialisiert das Objekt manuell:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import de.undercouch.bson4jackson.BsonFactory;
 
public class ManualSample {
  public static void main(String[] args) throws Exception {
    //create dummy POJO
    Person bob = new Person();
    bob.setName("Bob");
 
    //create factory
    BsonFactory factory = new BsonFactory();
 
    //serialize data
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    JsonGenerator gen = factory.createJsonGenerator(baos);
    gen.writeStartObject();
    gen.writeFieldName("name");
    gen.writeString(bob.getName());
    gen.close();
 
    //deserialize data
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    JsonParser parser = factory.createJsonParser(bais);
    Person clone_of_bob = new Person();
    parser.nextToken();
    while (parser.nextToken() != JsonToken.END_OBJECT) {
      String fieldname = parser.getCurrentName();
      parser.nextToken();
      if ("name".equals(fieldname)) {
        clone_of_bob.setName(parser.getText());
      }
    }
 
    assert bob.getName().equals(clone_of_bob.getName());
  }
}

Optimierung fürs Streaming

Eine Einschränkung des BSON-Formats ist, dass jedes Dokument mit einer Längenangabe beginnt. Beim Schreiben muss die Länge des gesamten Dokuments also im Voraus bekannt sein. bson4jackson ist gezwungen, das Dokument zu puffern bevor es in den OutputStream geschrieben werden kann. Der Parser von bson4jackson ignoriert die Längeangabe jedoch, sodass man sie auch weglassen kann. Dazu muss man die BsonFactory folgendermaßen erzeugen:

BsonFactory fac = new BsonFactory();
fac.enable(BsonGenerator.Feature.ENABLE_STREAMING);

Dies kann den Serialisierungsvorgang für große Dokumente sehr beschleunigen und den Speicherverbrauch stark reduzieren. Der offizielle MongoDB-Treiber für Java ignoriert die Längenangabe übrigens auch. Die Optimierung lässt sich also ebenfalls nutzen, wenn die von bson4jackson geschriebenen Dokumente mit dem MongoDB-Treiber gelesen werden sollen.

Performance

In der Version 1.1.0 von bson4jackson wurden neben der Unterstützung für Jackson 1.7 auch einige Verbesserungen hinsichtlich der Performance vorgenommen. Inzwischen ist bson4jackson deutlich schneller als der offizielle MongoDB-Treiber für Java (Stand: Januar 2011). Dies trifft beim Serialisieren jedoch nur zu, wenn die Streaming-API verwendet wird, da durch den ObjectMapper von Jackson noch ein kleiner Overhead dazu addiert werden muss (der MongoDB-Treiber arbeitet allerdings auch mit einer Art Streaming-API). Beim Deserialisieren ist bson4jackson immer schneller. Die aktuellen Ergebnisse des Benchmarks kann man unter folgender Seite nachschauen:

https://github.com/eishay/jvm-serializers/wiki

Kompatibilität mit MongoDB

In Version 1.2.0 wurde die Kompatibilität von bson4jackson zu MongoDB deutlich verbessert. Dank der Beteiligung von James Roper unterstützt die BsonParser-Klasse nun das Feature HONOR_DOCUMENT_LENGTH. Es bringt den Parser dazu, die ersten 4 Bytes, also die Größe eines Dokuments, auszuwerten und zu beachten. Natürlich funktioniert dies nur, wenn das Feature BsonGenerator.Feature.ENABLE_STREAMING nicht während der Erzeugung des Dokuments aktiviert war.

Das Feature ist besonders nützlich, um mehrere Dokumente aus einem Input-Stream von MongoDB zu lesen. Es kann wie folgt aktiviert werden:

BsonFactory fac = new BsonFactory();
fac.enable(BsonParser.Feature.HONOR_DOCUMENT_LENGTH);
BsonParser parser = (BsonParser)fac.createJsonParser(...);

Unterstützung für Jackson 2.0

Jackson 2.0 wird seit bson4jackson 2.0 unterstützt. Falls Sie nach einer Version suchen, die mit Jackson 1.x läuft, dann laden Sie bitte bson4jackson 1.3.0 herunter.

Download

Vorkompilierte Binaries

Vorkompilierte Binärdateien von bson4jackson kann man sich in meinem GitHub-Repository herunterladen. Zusätzlich benötigt man nur noch eine Kopie von Jackson und schon kann es losgehen.

Maven/sbt/buildr

Alternativ kann man auch Maven benutzen, um bson4jackson herunterzuladen:

<dependencies>
  <dependency>
    <groupId>de.undercouch</groupId>
    <artifactId>bson4jackson</artifactId>
    <version>2.0.0</version>
  </dependency>
</dependencies>

Für sbt muss man folgende Zeile zu seiner Projektbeschreibung hinzufügen:

val bson4jackson = "de.undercouch" % "bson4jackson" % "2.0.0"

Für buildr kann man folgenden Code nutzen:

compile.with 'de.undercouch:bson4jackson:jar:2.0.0'
]]>
Scala-Projekte mit Eclipse PDE Build bauen (2) http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen-2 http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen-2#comments 2010-11-20T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen-2 Vor einiger Zeit habe ich darüber berichtet, wie man Scala-Projekte automatisiert mit Eclipse PDE Build bauen kann. Dabei muss eine spezielles Ant-Skript (customBuildCallbacks.xml) im Projektverzeichnis angelegt werden, das den Scala-Compiler und die Library sucht, entpackt und dann auf die Quellcode-Dateien loslässt.]]> Vor einiger Zeit habe ich darüber berichtet, wie man Scala-Projekte automatisiert mit Eclipse PDE Build bauen kann. Dabei muss eine spezielles Ant-Skript (customBuildCallbacks.xml) im Projektverzeichnis angelegt werden, das den Scala-Compiler und die Library sucht, entpackt und dann auf die Quellcode-Dateien loslässt.

Dieses Verfahren funktioniert nach wie vor. Die OSGi-Bundles, die den Scala-Compiler und die Library enthalten, werden mit der Scala IDE für Eclipse geliefert. Dieses Projekt ist inzwischen jedoch nicht mehr so eng an die EPFL gekoppelt, sondern wird weitgehend unabhängig vom Scala-Release-Zyklus weiterentwickelt. Dadurch haben sich die Namen der OSGi-Bundles geändert. Ohne Anpassungen funktioniert das von mir zum Download bereitgestellte Skript deshalb nicht mehr.

Folgende Änderungen sind notwendig:

  • Der Symbolic Name des OSGi-Bundles, das die Scala-Library enthält, beginnt nun mit org.scala-ide.scala.library_
  • Der Compiler ist nun in einem Bundle, dessen Namen mit org.scala-ide.scala.compiler_ beginnt
  • Der Scala-Ant-Task befindet sich nun in der scala-compiler.jar im Compiler-Bundle

Ich habe ein neues Skript erstellt, das hier heruntergeladen werden kann:

customBuildCallbacks.xml (4.0 KiB)

]]>
Einfachere Benutzung von Git http://www.michel-kraemer.de/einfachere-benutzung-von-git http://www.michel-kraemer.de/einfachere-benutzung-von-git#comments 2010-06-04T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/einfachere-benutzung-von-git Seit einiger Zeit benutze ich Git zur Verwaltung meiner Projekte. Da die graphischen Benutzeroberflächen noch nicht besonders ausgereift sind und ich gerne die volle Kontrolle über alles habe, benutze ich Git auf der Kommandozeile (i.e. Bash). Damit ich dort nicht immer wieder die gleichen Kommandos eingeben muss, habe ich mir einige Bash-Aliasse und -Funktionen überlegt, die die Benutzung von Git vereinfachen.]]> Seit einiger Zeit benutze ich Git zur Verwaltung meiner Projekte. Da die graphischen Benutzeroberflächen noch nicht besonders ausgereift sind und ich gerne die volle Kontrolle über alles habe, benutze ich Git auf der Kommandozeile (i.e. Bash). Damit ich dort nicht immer wieder die gleichen Kommandos eingeben muss, habe ich mir einige Bash-Aliasse und -Funktionen überlegt, die die Benutzung von Git vereinfachen.

Die vereinfachten Kommandos kann man in meinem Github-Repository herunterladen. Eine Anleitung zur Installation und Benutzung findet sich in der README.

Hier nun eine kurzer Ausschnitt aus den definierten Kommandos:

add
Führt git add -v und danach git status aus. Alle Parameter werden an git add weitergeleitet.
Beispiel:
add -p foobar.txt
commit
Alias für git commit
gadd
Filtert die Ausgabe von git ls-files mit grep, damit nur die Dateien zum Index hinzugefügt werden, die einem bestimmten Muster entsprechen. Alle Parameter (einschließlich des Musters) werden an grep übergeben. Genauso wie bei add wird hier am Ende git status aufgerufen.
Beispiel:
gadd -i '\.java$'
log
Alias für git log
pull
Führt git pull --rebase aus und zeigt dann die Commits seit dem letzten Pull in einem komprimierten Format an.
push
Alias für git push
st
Alias für git status

Die Kommandos wurden unter msysgit, getestet, sollten aber auch auf anderen Plattformen funktionieren. Eine vollständige Liste findet man in der README.

In Zukunft wird die Liste der Kommandos vielleicht noch erweitert. Ich würde mich über Feedback freuen.

Abschließend möchte ich mich bei Simon Templer und Simon Thum für die Ideen bedanken!

]]>
Mehrsprachige Webseiten mit Lift und OSGi http://www.michel-kraemer.de/mehrsprachige-webseiten-mit-lift-und-osgi http://www.michel-kraemer.de/mehrsprachige-webseiten-mit-lift-und-osgi#comments 2010-04-05T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/mehrsprachige-webseiten-mit-lift-und-osgi Für die Internationalisierung von Webseiten bietet Lift bereits einige Mechanismen. Wird das Framework aber in einer OSGi-Umgebung verwendet, benötigt man einen kleinen Workaround, damit die Resource Bundles in Form von Property-Files gefunden werden können.]]> Für die Internationalisierung von Webseiten bietet Lift bereits einige Mechanismen. Wird das Framework aber in einer OSGi-Umgebung verwendet, benötigt man einen kleinen Workaround, damit die Resource Bundles in Form von Property-Files gefunden werden können.

Internationalisierung mit Lift

Zunächst eine kleine Zusammenfassung der Möglichkeiten zur Internationalisierung mit Lift: Die String-Ressourcen müssen in so genannten "Property-Bundles" abgelegt werden. Das sind ganz normale Java-Properties-Dateien in der folgenden Form:

title=Meine Website
yes=Ja
no=Nein
deletequestion=Möchten Sie alles löschen?

Der Name der Property-Bundles beginnt immer mit lift. Jedoch werden unterschiedliche Suffixe angehängt, die die entsprechende Sprache und optional das Land im ISO-Format angeben. Zum Beispiel enthält die Datei lift_en.properties englische String-Ressourcen während lift_de.properties deutsche und lift_de_CH.properties schweizerdeutsche enthält. Den Präfix lift kann man im Boot-Loader der Webapplikation spezifizieren:

LiftRules.resourceNames = "anotherPrefix" :: Nil

Die Variable resourceNames ist dabei eine Liste von Strings. Das heißt, man kann seine Resource-Bundles auch in mehrere Dateien mit unterschiedlichen Präfixen aufteilen, damit man z.B. in großen Projekten nicht den Überblick verliert.

Hat man die Resource-Bundles erstellt, kann man Strings in HTML-Templates mit <lift:loc locid="..." /> übersetzen. Verwendet man also die Properties-Datei aus obigem Beispiel, dann wird das folgende Template

<html>
<head>
<title><lift:loc locid="title" /></title>
</head>
<body>
<lift:loc locid="deletequestion" />
<button><lift:loc locid="yes" /></button>
<button><lift:loc locid="no" /></button>
</body>
</html>

in folgenden HTML-Code übersetzt:

<html>
<head>
<title>Meine Website</title>
</head>
<body>
Möchten Sie alles Löschen?
<button>Ja</button>
<button>Nein</button>
</body>
</html>

Im Scala-Quellcode kann man stattdessen das Stateful-Objekt net.liftweb.http.S verwenden. Es definiert die Methode ?, die einen String als Parameter annimmt und diesen im Resource-Bundle sucht:

def snippet(xhtml: NodeSeq): NodeSeq =
  <p>{ S ? "deletequestion" }</p>

Ein kleiner Tipp: Möchte man in den HTML-Templates Tag-Attribute übersetzen (z.B. das Attribut value eines input-Elements), dann sollte man den entsprechenden Teil in ein Snippet auslagern, sodass man das S-Objekt verwenden kann:

def inputButton(xhtml: NodeSeq): NodeSeq =
  <input type="button" value={ S ? "yes" } />

Resource-Bundles in der OSGi-Umgebung

Das Problem mit der oben beschriebenen Methode ist, dass die Resource-Bundles von Lift im Classpath mittels getClass.getClassLoader.getResourceAsStream() gesucht werden. In einer OSGi-Umgebung können Sie demnach nicht mehr gefunden werden, da der Classloader des Bundles net.liftweb.lift-webkit verwendet wird.

Wie eingangs erwähnt, kann man dies mit einem Workaround lösen. Dazu muss man im BootLoader eine Resource-Bundle-Factory definieren:

LiftRules.resourceBundleFactories prepend {
  case (basename, locale) => ResourceBundle.getBundle(basename, locale)
}

Dadurch werden die Resource-Bundles über den Classloader des Bundles, das den BootLoader enthält, geladen.

Zusammenfassung

Die Mechanismen zur Internationalisierung mit Lift sind ausreichend für die meisten Webseiten. Wenn man etwas mit dem Lift-Tag nicht übersetzen kann (z.B. Attribute) oder man mehr Kontrolle benötigt, muss man auf Snippets ausweichen. In OSGi-Umgebungen muss man eine Resource-Bundle-Factory erzeugen, die die Properties-Dateien über den korrekten Classloader lädt.

]]>
Scala-Projekte mit Eclipse PDE Build bauen http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen#comments 2010-03-30T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/scala-projekte-mit-eclipse-pde-build-bauen PDE Build ist das Standard-Build-System von Eclipse. Es wird verwendet, um OSGi Bundles, Plugins, Features oder Produkte zu exportieren. Im so genannten Headless Mode kann man es einsetzen, um automatisierte Builds ohne Eclipse UI durchzuführen. Die Scala IDE unterstützt PDE Build bisher noch nicht. Um Scala-Projekte zu kompilieren, muss man selbst etwas Hand anlegen.]]> PDE Build ist das Standard-Build-System von Eclipse. Es wird verwendet, um OSGi Bundles, Plugins, Features oder Produkte zu exportieren. Im so genannten Headless Mode kann man es einsetzen, um automatisierte Builds ohne Eclipse UI durchzuführen. Die Scala IDE unterstützt PDE Build bisher noch nicht. Um Scala-Projekte zu kompilieren, muss man selbst etwas Hand anlegen.

Dieser Artikel bezieht sich auf eine ältere Version der Scala IDE for Eclipse. Informationen über die aktuelle Version findet man in einem neueren Beitrag!

Zunächst benötigt man ein Ant-Skript, das man in den Build-Prozess einhängen kann. Das Skript sollte den Namen customBuildCallbacks.xml haben und im Wurzel-Verzeichnis des Bundles liegen, das den zu kompilierenden Scala-Quellcode enthält:

de.michel-kraemer.myplugin/
  |- bin
  |- META-INF
  |- src
  |- build.properties
  |- customBuildCallbacks.xml

Im gleichen Verzeichnis liegt die Datei build.properties des Plugins. (Nicht zu verwechseln mit der build.properties-Datei, die man für den Headless Build benötigt!) Damit das neue Ant-Skript während des PDE Builds auch ausgeführt wird, muss man dieser Datei folgendes hinzufügen:

customBuildCallbacks=customBuildCallbacks.xml
customBuildCallbacks.inheritall=true

Die zweite Zeile ermöglicht den Zugriff auf globale Properties wie zum Beispiel ${build.result.folder}.

Im Ant-Skript kann man spezielle Targets definieren, die zu bestimmten Zeitpunkten im Build-Prozess aufgerufen werden. Am besten kopiert man dazu die Vorlage aus dem Verzeichnis ${eclipse.home}/plugins/org.eclipse.pde.build_*/templates/plugins/.

Das Target post.compile.@dot eignet sich hervorragend, um den Scala-Compiler manuell aufzurufen. Dazu muss man zunächst die Ant-Tasks definieren, die bereits mit der Scala Library ausgeliefert werden. Eine automatische Suche nach der Scala Library, die durch die Scala IDE installiert wird, und den dazugehörigen Tools kann man in Ant zum Beispiel folgendermaßen realisieren:

<!-- find eclipse.home -->
<pathconvert property="eclipse.home">
    <path location="${eclipse.launcher}" />
    <mapper>
        <!-- map "${eclipse.home}/eclipse.exe" to "${eclipse.home}" -->
        <globmapper from="*/eclipse.exe" to="*" handledirsep="true" />
    </mapper>
</pathconvert>
 
<!-- find scala bundle -->
<pathconvert property="scala_bundle">
    <path>
        <fileset dir="${eclipse.home}/plugins">
            <include name="scala.library_*" />
        </fileset>
    </path>
</pathconvert>
 
<!-- find scala tools -->
<pathconvert property="scala_tools_jar">
    <path>
        <fileset dir="${eclipse.home}/plugins">
            <include name="scala.tools.nsc_*" />
        </fileset>
    </path>
</pathconvert>

Danach steht der Pfad zum Scala-OSGi-Bundle in der Variablen ${scala_bundle} zur Verfügung. Die Variable ${scala_tools_jar} zeigt außerdem auf die Jar-Datei, die die Scala-Tools und damit auch die Ant-Tasks enthält.

Das Library-Bundle muss als nächstes entpackt werden, damit die eigentliche Scala-Library scala-library.jar bei der Task-Definition und beim Kompilieren im Classpath verwendet werden kann. Dazu nutzt man am besten das temporäre Build-Verzeichnis, das in der Variablen ${build.result.folder} zu finden ist:

<unjar dest="${build.result.folder}/scala-library" src="${scala_bundle}" />
<property name="scala_library_jar"
    location="${build.result.folder}/scala-library/lib/scala-library.jar" />

Danach können die Scala-Ant-Tasks definiert werden:

<!-- define scalac task -->
<taskdef resource="scala/tools/ant/antlib.xml">
    <classpath>
        <pathelement location="${scala_tools_jar}" />
        <pathelement location="${scala_library_jar}" />
    </classpath>
</taskdef>

Vor dem Kompilieren der Klassen, muss zunächst noch der korrekte Classpath definiert werden. Dieser setzt sich aus den vom PDE Build vorgegebenen Classpath @dot.classpath und der Scala-Library zusammen:

<pathconvert property="my.classpath">
    <restrict>
        <path>
            <path refid="@dot.classpath" />
            <pathelement location="${scala_library_jar}" />
        </path>
        <!-- remove libraries from classpath that don't exist (optional) -->
        <rsel:exists />
    </restrict>
</pathconvert>

Das Filtern von nicht vorhandenen Bibliotheken aus dem Classpath über <rsel:exists /> ist hierbei optional. Damit dies funktioniert, muss man im Root-Knoten der XML-Datei den entsprechenden Namespace definieren:

<project name="Build specific targets and properties"
    xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
    ...

Schließlich wird der Quellcode kompiliert:

<!-- compile scala source files -->
<mkdir dir="${target.folder}" />
<scalac srcdir="${source.folder1}"
    destdir="${target.folder}"
    classpath="${my.classpath}">
    <include name="**/*.scala" />
</scalac>

Als letztes kann man noch die Scala-Quelldateien aus dem Zielordner entfernen, damit diese nicht mit dem Plugin ausgeliefert werden:

<!-- delete scala source files in output folder -->
<delete>
    <fileset dir="${target.folder}" includes="**/*.scala" />
</delete>

Zusammenfassung

Die hier vorgestellte Methode verwendet die Möglichkeit, eigene Ant-Kommandos in den PDE-Build-Prozess aufzunehmen. Dabei wird versucht, die Scala-Bibliothek und die -Tools zu verwenden, die zusammen mit der IDE ausgeliefert werden. Falls man dies nicht möchte, kann man auch die Dateien scala-library.jar sowie scala-compiler.jar (enthält den Ant-Task) aus der Standard-Scala-Distribution kopieren und diese stattdessen in den Classpath einbinden.

Den vollständigen Quellcode der generischen Datei customBuildCallbacks.xml kann man hier herunterladen:

customBuildCallbacks-old.xml (3.8 KiB)

Dieser Artikel bezieht sich auf eine ältere Version der Scala IDE for Eclipse. Ein aktualisiertes Ant-Skript findet man in einem neueren Beitrag!

Die Datei kann ohne Änderungen in jedes OSGi-Bundle kopiert werden, das mit PDE Build gebaut werden soll und Scala-Code enthält. Lediglich die Datei build.properties muss noch wie oben beschrieben angepasst werden.

]]>
Style Guide für Scala http://www.michel-kraemer.de/style-guide-fur-scala http://www.michel-kraemer.de/style-guide-fur-scala#comments 2010-03-22T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/style-guide-fur-scala Scala hat bisher noch keinen offiziellen Style Guide, weshalb Daniel Spiewak im November 2009 einen Vorschlag für ein solches Dokument auf der Scala-Mailingliste gepostet hat. Wie dort zu lesen ist, findet selbst Martin Odersky, der Schöpfer von Scala, den Vorschlag gut und kann sich vorstellen, das Dokument in absehbarer Zeit offiziell auf der Scala-website zu veröffentlichen.]]> Scala hat bisher noch keinen offiziellen Style Guide, weshalb Daniel Spiewak im November 2009 einen Vorschlag für ein solches Dokument auf der Scala-Mailingliste gepostet hat. Wie dort zu lesen ist, findet selbst Martin Odersky, der Schöpfer von Scala, den Vorschlag gut und kann sich vorstellen, das Dokument in absehbarer Zeit offiziell auf der Scala-website zu veröffentlichen.

Die PDF-Version kann man sich unter folgender Adresse herunterladen:
http://www.codecommit.com/scala-style-guide.pdf

Eine Online-Version ist unter folgender Adresse verfügbar:
http://davetron5000.github.com/scala-style/

Der Style Guide ist gut gegliedert. Zu jedem Vorschlag wird auch stets ein Grund angegeben, warum es sinnvoll ist, den Code auf diese Weise zu formatieren und nicht anders. Gegenbeispiele zeigen, wie unleserlich der Code wird, wenn man sich nicht an den Style Guide hält.

Da ich ein großer Verfechter strukturierten Codes bin, kann ich das Dokument nur jedem empfehlen, der sich mit Scala beschäftigt. Wenn man die Sprache gerade neu lernt, sollte man sich den Style Guide möglichst früh durchlesen, damit gar nicht erst "schlechte Gewohnheiten" aufkommen. Durch Einhalten des Styles kann die Lesbarkeit von Scala-Programmen erhöht werden, wodurch auch die Erweiterbarkeit und Wartbarkeit vereinfacht wird.

]]>
phpBB auf dem iPhone/iPod Touch http://www.michel-kraemer.de/phpbb-auf-dem-iphone-ipod-touch http://www.michel-kraemer.de/phpbb-auf-dem-iphone-ipod-touch#comments 2010-03-03T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/phpbb-auf-dem-iphone-ipod-touch Das iPhone eignet sich hervorragend für Foren-Moderatoren, die viel unterwegs sind und z.B. im Zug Beiträge beantworten möchten. Leider lässt sich das Standard-Theme von phpBB auf dem iPhone (oder dem iPod Touch). nur sehr schlecht bedienen. Die Schriftgröße ist außerdem in den meisten Foren so klein, dass man ständig zoomen muss.]]> Das iPhone eignet sich hervorragend für Foren-Moderatoren, die viel unterwegs sind und z.B. im Zug Beiträge beantworten möchten. Leider lässt sich das Standard-Theme von phpBB auf dem iPhone (oder dem iPod Touch). nur sehr schlecht bedienen. Die Schriftgröße ist außerdem in den meisten Foren so klein, dass man ständig zoomen muss.

Etwas komfortabler ist das speziell für das iPhone entwickelte, kostenlose Theme phpbb-iphone-style. Es reduziert die Anzeige auf die wichtigsten Elemente, vergrößert die Schrift und erleichtert die Bedienung mit dem Touchscreen.

Die Installation ist sehr einfach. Man muss lediglich den Quellcode aus dem Subversion-Repository des Projekts herunterladen und auf dem Webserver in das Unterverzeichnis styles kopieren. Wenn man möchte, kann man außerdem die beigelegten Anweisungen befolgen, sodass beim Öffnen des Forums mit einem mobilen Browser automatisch das neue Theme ausgewählt wird. Hat man das erledigt, kann man das Theme wahlweise im Administrationsbereich deaktivieren, sodass es in normalen Browsern nicht manuell ausgewählt werden kann.

Ich habe phpbb-iphone-style im Spamihilator-Forum installiert. Hier ein paar Screenshots:

Ich werde in den kommenden Tagen noch einige kleinere Änderungen am Aussehen vornehmen, sodass es besser zum Stil der Spamihilator-Website passt.

]]>
Neues Scala-Projekt mit OSGi http://www.michel-kraemer.de/neues-scala-projekt-mit-osgi http://www.michel-kraemer.de/neues-scala-projekt-mit-osgi#comments 2010-02-15T00:00:00+01:00 Michel Krämer http://www.michel-kraemer.de/neues-scala-projekt-mit-osgi Die Scala IDE für Eclipse erlaubt das Entwickeln von Scala-Applikationen in Eclipse. Sie hat aber noch einen weiteren Vorteil: Dank ihr kann man die Programmiersprache auch innerhalb einer OSGi-Umgebung nutzen. Die Sprackbibliothek wird nämlich als OSGi-Bundle zusammen mit der Scala IDE ausgeliefert.]]> Die Scala IDE für Eclipse erlaubt das Entwickeln von Scala-Applikationen in Eclipse. Sie hat aber noch einen weiteren Vorteil: Dank ihr kann man die Programmiersprache auch innerhalb einer OSGi-Umgebung nutzen. Die Sprackbibliothek wird nämlich als OSGi-Bundle zusammen mit der Scala IDE ausgeliefert.

Zunächst muss die Scala IDE installiert werden. Um ein OSGi-Bundle mit Scala-Nature zu erzeugen, muss man in Eclipse dann zuerst ein ganz normales Plugin-Projekt erzeugen. Danach muss man die Scala-Nature hinzufügen, damit der Scala-Quellcode kompiliert werden kann. Dazu klickt man mit der rechten Maustaste im Navigator oder Package Explorer auf das neue Projekt und wählt "Scala/Add Scala Nature". Dadurch werden folgende Einträge in die Datei .project eingefügt:

<buildCommand>
  <name>org.scala-ide.sdt.core.scalabuilder</name>
  <arguments>
  </arguments>
</buildCommand>
<nature>org.scala-ide.sdt.core.scalanature</nature>

Damit die Scala Library genutzt werden kann, muss man in der META-INF/MANIFEST.MF das Bundle org.scala-ide.scala.library als Required Bundle angeben:

Der Scala-Compiler erstellt sodann normalen Java-Bytecode sodass eine vollständige Integration mit Java und OSGi sichergestellt ist. Etwas störend ist die unvollständige Unterstützung von OSGi-Package-Imports der Scala IDE. Wenn man einmal ein Package aus einem Bundle per Import-Package importiert hat, kann man danach auch Klassen aus allen anderen Packages dieses Bundles im Scala-Quellcode importieren. Die IDE zeigt dabei keine Fehler an. Zur Laufzeit kommt es jedoch korrekterweise zu ClassNotFoundExceptions. Man hat somit zwei Möglichkeiten:

  • Auf Require-Bundle statt Import-Package umsteigen, was jedoch nicht empfohlen ist.
  • Nach dem Auftreten der Laufzeitfehler die Packages manuell importieren (erfahrende OSGi-Entwickler kennen diese Vorgehensweise sowieso) und auf eine neue Version der Scala IDE warten.
]]>
Windows Vista auf eine andere Partition verschieben http://www.michel-kraemer.de/vista-auf-andere-partition-verschieben http://www.michel-kraemer.de/vista-auf-andere-partition-verschieben#comments 2009-05-06T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/vista-auf-andere-partition-verschieben Der Kauf einer größeren Festplatte muss nicht unbedingt bedeuten, dass man das komplette Betriebssystem neu installieren muss. Dieser Artikel fasst die Schritte zusammen, die beim Verschieben einer Vista-Installation auf eine andere Partition nötig sind. Die Punkte lassen sich auch anwenden, wenn man eine Dual-Boot-Konfiguration auflösen und das Betriebssystem auf der Startpartition gegen das auf einer anderen ersetzen möchte.]]> Der Kauf einer größeren Festplatte muss nicht unbedingt bedeuten, dass man das komplette Betriebssystem neu installieren muss. Dieser Artikel fasst die Schritte zusammen, die beim Verschieben einer Vista-Installation auf eine andere Partition nötig sind. Die Punkte lassen sich auch anwenden, wenn man eine Dual-Boot-Konfiguration auflösen und das Betriebssystem auf der Startpartition gegen das auf einer anderen ersetzen möchte.

Der Artikel Howto: Duplicate any Windows installation to a new hard disk ... von Lorin Thwaits ist ein guter Ausgangspunkt. Die dort beschriebenen Schritte seien hier kurz zusammengefasst:

  1. Vorbereiten der Zielpartition (z.B. durch Formatierung oder Partitionierung)
  2. Einlegen der Windows Vista-Installations-DVD
  3. Rechner neu starten und von der Installations-DVD booten
  4. Installation starten, bis man zur Eingabe der Seriennummer gelangt
  5. Durch Drücken von Umschalt+F10 ein Eingabefenster öffnen
  6. Mit folgendem Kommando alle Dateien von der alten Partition (z.B. X:) auf die neue (z.B. C:) kopieren:
    ROBOCOPY X:\ C:\ /e /XJ /efsraw /copyall /dcopy:t /r:0
  7. Abwarten, bis alle Dateien kopiert wurden (dies kann je nach Größe der Partition mehrere Stunden dauern)
  8. Installation abbrechen und neu starten

Weitere Informationen findet man in oben genanntem Artikel. Allerdings bezieht dieser sich auf das Kopieren einer Windows XP-Installation. Erst in den Kommentaren liest man, dass der Schalter /XJ für das Kopieren einer Vista-Installation unbedingt nötig ist! Dadurch wird nämlich verhindert, dass so genannte "Abzweigunspunkte" (engl. Junction Points) verfolgt werden. Ein solcher Punkt ist in der Deutschen Vista-Version z.B. das virtuelle Verzeichnis "C:\Benutzer", das in Wirklichkeit auf "C:\Users" verweist. Lässt man den Schalter weg, kopiert ROBOCOPY beide Verzeichnisse, wodurch doppelter Speicherplatz belegt wird.

Probleme beim Booten

Nach dem Kopieren kann es passieren, dass Vista nicht mehr korrekt startet. Die folgenden Hinweise sollen bei der Problemlösung helfen:

Beim Start erscheint: NTLDR fehlt

Dieses Problem lässt sich einfach beheben, indem man von der Windows Vista-DVD bootet und die Reparaturoption auswählt. Die Installationsroutine sollte einen Fehler finden und beheben. Gegebenenfalls ist die Prozedur ein weiteres Mal zu wiederholen. Danach sollte Windows wieder starten.

Nach dem Starten von Windows, kann man sich anmelden, aber dann bleibt der Bildschirm leer

Dieser Fall tritt auf, wenn der Windows Explorer nicht gefunden werden kann. Vista speichert in der Registry zu jedem Laufwerksbuchstaben den physischen Identifzierer der jeweiligen Festplatte bzw. Partition. Da sich Vista nun auf einer anderen Partition befindet, entspricht der Laufwerksbuchstabe C: nicht mehr dem gleichen Identifizierer wie vorher. Dieses Problem kann man wie folgt lösen:

  1. Windows neu starten
  2. Bevor der Startbildschirm erscheint F8 drücken, um das Boot-Menü zu öffnen
  3. "Abgesicherter Modus" auswählen.
  4. Nach dem Start von Windows mit einem Benutzer anmelden, der Administratorrechte hat. Wurde das Administratorkonto nicht aktiviert, hat der Hauptbenutzer im abgesicherten Modus automatisch alle Rechte.
  5. Sollte der Explorer immer noch nicht starten, durch Drücken von Strg+Alt+Entf den Task-Manager öffnen
  6. Den Menüpunkt "Datei/Neuer Task (Ausführen...)" wählen.
  7. regedit eingeben und mit OK bestätigen.
  8. Der Registrierungs-Editor erscheint. Dort folgenden Pfad öffnen:
    HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices
  9. Auf der rechten Seite alle Einträge (außer "Standard") löschen
  10. Rechner neu starten

Nach diesen Schritten sollte das System wieder wie gewohnt laufen.

Ruhezustand funktioniert nicht mehr (das System fährt nicht mehr korrekt hoch)

Dies kann zwei Ursachen haben. Entweder ist die Datei für den Ruhezustand (C:\hiberfil.sys) defekt oder ein Eintrag in der Startkonfiguration stimmt nicht.

Im ersten Fall genügt es, folgende Schritte durchzuführen:

  1. Im Startmenü den Eintrag "Zubehör/Eingabeaufforderung" mit der rechten Maustaste anklicken und "Als Administrator ausführen" wählen.
  2. Folgende Kommandos ausführen:
    powercfg -h off
    powercfg -h on

Der Ruhezustand wird hiermit deaktiviert und danach wieder aktiviert, wodurch die hiberfil.sys neu erstellt wird.

Funktioniert der Ruhezustand danach immer noch nicht, ist die Startkonfiguration beschädigt. Dies kann man wie folgt beheben:

  1. Die Eingabeaufforderung wie oben als Administrator starten
  2. Überprüfen der Startkonfiguration durch folgendes Kommando:
    bcdedit -enum all
  3. Der Abschnitt "Resume from Hibernate" oder "Wiederaufnahme aus dem Ruhezustand" sollte vorhanden sein. (Falls nicht, bitte die oben beschriebenen Schritte ausführen). Allerdings enthält dieser folgenden fehlerhaften Eintrag:
    inherit {resumeloadersettings}
  4. Kopieren des Identifizierers des entsprechenden Abschnitts. Zum Beispiel:
    Bezeichner {xxxx-xxxx-xxxx-xxxx}
  5. Den fehlerhaften Eintrag durch folgendes Kommando löschen (wobei der Bezeichner durch den soeben kopierten ersetzt werden muss:
    bcdedit -deletevalue {xxxx-xxxx-xxxx-xxxx} inherit

Danach sollte der Ruhezustand wie gewohnt funktionieren. Falls der Startbildschirm nun in englischer Sprache erscheint, kann man ihn mit folgendem Kommando auf Deutsch umschalten:

bcdedit -set {xxxx-xxxx-xxxx-xxxx} locale de-DE

Der Identifizierer ist wieder durch den oben gefundenen zu ersetzen.

Weitere Informationen zur Startkonfiguration findet man in Martin Richters Artikel Vista SP1 und so manche Ruhezustand/Hibernate Probleme.

]]>
5 Anti-Spam-Maßnahmen für phpBB 3.0 http://www.michel-kraemer.de/anti-spam-phpbb3 http://www.michel-kraemer.de/anti-spam-phpbb3#comments 2009-04-08T00:00:00+02:00 Michel Krämer http://www.michel-kraemer.de/anti-spam-phpbb3 phpBB ist als Foren-Software mit offenem Quellcode sehr beliebt und weit verbreitet. Aus diesem Grund ist es aber auch häufig das Ziel von Spammern. In der Version 3.0 wurde deshalb unter anderem ein besseres Captcha eingeführt. Leider haben sich die Spammer inzwischen auf die neue Version eingestellt und Bots geschrieben, die das Captcha automatisch überwinden und Beiträge absetzen können. Im Folgenden werden deshalb fünf Anti-Spam-Maßnahmen beschrieben, die sich in jeder phpBB-3.0-Installation einsetzen lassen und sehr effektiv sind. Ziel ist es dabei, möglichst viele Spam-Beiträge zu blockieren ohne den normalen Betrieb des Forums zu beeinträchtigen.]]> phpBB ist als Foren-Software mit offenem Quellcode sehr beliebt und weit verbreitet. Aus diesem Grund ist es aber auch häufig das Ziel von Spammern. In der Version 3.0 wurde deshalb unter anderem ein besseres Captcha eingeführt. Leider haben sich die Spammer inzwischen auf die neue Version eingestellt und Bots geschrieben, die das Captcha automatisch überwinden und Beiträge absetzen können. Im Folgenden werden deshalb fünf Anti-Spam-Maßnahmen beschrieben, die sich in jeder phpBB-3.0-Installation einsetzen lassen und sehr effektiv sind. Ziel ist es dabei, möglichst viele Spam-Beiträge zu blockieren ohne den normalen Betrieb des Forums zu beeinträchtigen.

Maßnahme 1: Links

Spammer versuchen meist bestimmte Websites zu bewerben. Deshalb enthalten etwa 95% aller Spam-Beiträge Links bzw. URLs. Die effektivste Methode solche Beiträge zu verhindern, ist Links komplett zu sperren. Da die hier vorgestellten Maßnahmen normale Benutzer aber möglichst wenig beeinträchtigen sollen, kann ein kleiner Trick verwendet werden: Es wird davon ausgegangen, dass ein Spammer sich in einem Forum neu anmeldet und direkt damit beginnt, Werbebotschaften zu schreiben. Das heißt, Gäste und Benutzer mit weniger als einer bestimmten Zahl von Beiträgen werden als potenzielle Spammer behandelt. Ihre Beiträge werden genauer untersucht. Alle anderen Benutzer bleiben von den Maßnahmen unbetroffen.

Um Beiträge mit Links zu blockieren, kann die Funktion submit_post() in der Datei includes\functions_posting.php um folgende Zeilen ergänzt werden:

//Define the minimum number of posts for "good" users
//Users below this threshold are considered potential spammers
$user_posts_threshold = 3;
 
//strip whitespace characters in the post body
$msgwows = $data['message'];
$msgwows = str_replace(" ", "", $msgwows);
$msgwows = str_replace("\n", "", $msgwows);
$msgwows = str_replace("\r", "", $msgwows);
$msgwows = str_replace("\t", "", $msgwows);
 
if (!$user->data['is_registered'] ||
    $user->data['user_posts'] < $user_posts_threshold) {
  if (strpos($msgwows, 'http://') !== FALSE ||
      strpos($msgwows, 'ftp://') !== FALSE ||
      strpos($msgwows, 'www.') !== FALSE ||
      strpos($msgwows, '[url') !== FALSE) {
    trigger_error("You are not allowed to post URLs!");
  }
}

Dieser Code sollte selbstverständlich ganz am Anfang der Funktion stehen, damit die Beiträge vor dem Speichern gefiltert werden.

Maßnahme 2: Bilder

Spammer versuchen Filter oftmals durch den Einsatz von Bildern zu umgehen. Dazu schreiben sie ihre Werbebotschaften und Links in Bilddateien und hängen diese an Foren-Beiträge an. Mit dem gleicher Methode wie oben beschrieben, können in der Funktion submit_post() in der Datei functions/functions_posting.php Beiträge mit Bildern geblockt werden:

if (!$user->data['is_registered'] ||
    $user->data['user_posts'] < $user_posts_threshold) {
  if (strpos($msgwows, '[img') !== FALSE) {
    trigger_error("You are not allowed to post images!");
  }
}

Maßnahme 3: Russische und Chinesische Beiträge?

Einige Spam-Beiträge sind auf Russisch oder Chinesisch oder enthalten einfach nur eine Menge unleserlicher Sonderzeichen. Man kann sich zunutze machen, dass in deutsch- und englischsprachigen Foren in der Regel nur Deutsche bzw. Englische Beiträge erwünscht sind. Beiträge mit sehr vielen Sonderzeichen bzw. Zeichen aus fremdsprachigen Alphabeten können problemlos als Spam betrachtet werden.

Cory Mawhorter hat eine kleine PHP-Funktion veröffentlicht (is_english()), die auf einfache Weise Sonderzeichen erkennt. Diese kann verwendet werden, um Deutsche bzw. Englische Texte von fremdsprachigen zu unterscheiden:

if (!$user->data['is_registered'] ||
    $user->data['user_posts'] < $user_posts_threshold) {
  if (!is_english($msgwows, 0.75)) {
    trigger_error("Only German or English posts are allowed here!");
  }
}

Maßnahme 4: http:BL

Das Project Honey Pot bietet ein effektives System an, um Spammer und Adresssammler von Webseiten fern zu halten. http:BL gleicht die IP-Adresse eines Besuchers mit einer Datenbank ab. Ist die IP-Adresse bekannt und verbirgt sich dahinter ein Spammer, dann kann der Besucher schon gesperrt werden bevor er die Webseite sieht. Das System verwendet DNS, wodurch die Abfragen relativ schnell sind.

Um http:BL zu verwenden, muss man sich bei Project Honey Pot registrieren. Dadurch erhält man einen Schlüssel, der dem eigenen Benutzernamen eindeutig zugeordnet ist. Project Honey Pot will dadurch Missbrauch des Systems verhindern. Ein MOD für phpBB wird angeboten, allerdings nur für Version 2.0. Diesen kann man unter Umständen an phpBB 3.0 anpassen. Alternativ kann man folgenden Code an das Ende der Datei common.php kopieren:

//configure your http:BL Access Key here
$httpblkey = "xxxxxxxxxxx";
$httpblmaxdays = 21;
$httpblmaxthreat = 25;
 
//if you already configured a honey pot on your website use this line:
//$httpblhoneypot = "http://xxxxxxxxxxx";
 
function httpbl_check() {
  global $httpblkey, $httpblmaxdays, $httpblmaxthreat, $httpblhoneypot;
 
  $ip = $_SERVER["REMOTE_ADDR"];
 
  $result = explode(".", gethostbyname($httpblkey."."
    .implode(".", array_reverse(explode(".", $ip)))
    .".dnsbl.httpbl.org"));
 
  if ($result[0] != 127) {
    //something went wrong or the IP is not in the database.
    //ignore this one.
    return;
  }
 
  $days = $result[1];
  $threat = $result[2];
 
  if ($days < $httpblmaxdays && $threat > $httpblmaxthreat) {
    if ($httpblhoneypot) {
      header("HTTP/1.1 301 Moved Permanently");
      header("Location: ".$httpblhoneypot);
    }
    die();
  }
}
httpbl_check();

In der Variablen $httpblkey muss der http:BL Access Key angegeben werden.

Maßnahme 5: Akismet

Eine weitere Methode Spam zu blockieren, ist Akismet. Dieses System wird auch gerne in WordPress-Blogs eingesetzt. Wie für Project Honey Pot, benötigt man hierfür einen API-Key, den man durch eine Registrierung erhält.

In Foren kann Akismet zum Beispiel beim Absenden von Beiträgen verwendet werden. Das System kann zu Falschmeldungen führen, weshalb die Filterung auch hier wieder nur auf die ersten Beiträge eines Benutzers beschränkt wird. Der folgende Code verwendet die Datei Akismet.class.php, die man von Alex Potsides’ Blog herunterladen kann. Der Code kann in die Funktion submit_post() in der Datei includes/functions_posting.php eingefügt werden:

//configure your Akismet API key here
$akismet_key = 'xxxxxxxxxxx';
 
//the URL you entered when you registered for a Wordpress account
$akismet_url = 'xxxxxxxxxxx';
 
include('Akismet.class.php');
 
$akismet = new Akismet($akismet_url, $akismet_key);
if (!$user->data['is_registered'])
  $akismet->setCommentAuthor($username);
else
  $akismet->setCommentAuthor($user->data['username']);
$akismet->setCommentContent($data['message']);
$akismet->setUserIP($user->ip);
if ($user->data['is_registered'])
{
  $akismet->setCommentAuthorEmail(strtolower($user->data['user_email']));
  $akismet->setCommentAuthorURL(strtolower($user->data['user_website']));
}
 
if ((!$user->data['is_registered'] ||
    $user->data['user_posts'] < $user_posts_threshold) &&
    $akismet->isCommentSpam()) {
    trigger_error("Akismet says your post is spam");
}

Die Variable $akismet_key muss den Akismet API Key enthalten. Die URL, die man bei der Registrierung für einen WordPress-Account angegeben hat, muss in der Variablen $akismet_url stehen.

Akismet kann desweiteren sinnvoll bei der Registrierung von neuen Benutzern eingesetzt werden. Dazu ist folgender Code in die Funktion user_add() in der Datei includes/functions_user.php einzufügen:

//configure your Akismet API key here
$akismet_key = 'xxxxxxxxxxx';
 
//the URL you entered when you registered for a Wordpress account
$akismet_url = 'xxxxxxxxxxx';
 
include('Akismet.class.php');
 
$akismet = new Akismet($akismet_url, $akismet_key);
$akismet->setCommentAuthor($username_clean);
$akismet->setUserIP($user->ip);
$akismet->SetCommentAuthorEmail(strtolower($user_row['user_email']));
 
if($akismet->isCommentSpam()) {
  trigger_error("Akismet says you are a spammer");
}

Fazit

Die hier vorgestellten Maßnahmen helfen, das Spam-Aufkommen in phpBB-3.0-Foren drastisch zu reduzieren. Seit dem Aktivieren der verschiedenen Filter im Spamihilator-Forum konnte kein einziger Spammer einen Beitrag absetzen. Das Blockieren von Links und Bildern ist dabei die effektivste Methode. Durch das Filtern von Sonderzeichen werden alle anderen Spam-Beiträge verhindert. Der normale Betrieb wird kaum gestört, da die Maßnahmen nur neue Benutzer betreffen. Sobald ein Benutzer eine bestimmte Anzahl von "guten" Beiträgen geschrieben hat, werden die Filter deaktiviert. Bisher hat dies noch kein Spammer ausgenutzt. Falls dies jemals der Fall sein sollte, kann die Schwelle sehr leicht erhöht werden.

Trotz aller Filtermaßnahmen beim Schreiben von Beträgen, bleibt immer noch das Problem, dass Spammer sich nach wie vor registrieren und in ihrer Signatur auf eine Webseite verlinken können. Maßnahmen für dieses Problem sind noch zu entwickeln.

In vielen von Spam geplagten Foren sind Gäste nicht zugelassen. Man muss sich registrieren, um Beiträge schreiben zu können. Dies kann für einfache Support-Foren zu umständlich sein. Die Benutzer möchten gerne Beiträge schreiben können ohne lange und komplizierte Registrierungsverfahren zu durchlaufen. Mit den in diesem Artikel vorgestellten Maßnahmen können Gäste grundsätzlich wieder zugelassen werden, denn die Filterung ist für solche immer aktiv.

Abschließend bleibt zu erwähnen, dass der Einsatz von Akismet auf deutschen Webseiten zur Zeit noch umstritten ist. Weiteres darüber findet man unter anderem in folgendem Artikel: http://www.drweb.de/magazin/akismet-und-der-datenschutz/. Maßnahme 5 kann bei Bedarf ausgelassen werden.

]]>