Aufbau eines Hackintosh

Ich bin ja schon lange kein Apple-Nutzer mehr, aber in den letzten Tagen hat mich ein kleines Projekt gepackt:

Kann ich auf meinem aktuellen Desktop mit Hardware von Mitte 2012 ein Mac OS installieren?

Grundsätzlich ist Mac OS für mich interessant: Ein Unix-basiertes System mit anständiger GUI. Normalerweise
läuft auf meinen Rechnern ja ein Linux mit i3wm, in der letzten Zeit wieder vermehrt Windows 10 auf Desktop und Laptop.
Wer aber mal versucht hat, Linux auf einem HiDPI Display und auf Laptop-Hardware anständig zum Laufen zu bringen,
der wird meine Schmerzen verstehen.

Daher also der Grundgedanke: Kann ich ein Mac OS bekommen, ohne die Apple-typische Gängelei bei der Hardware? Zugegeben,
die Apple-Hardware funktioniert gut zusammen, allerdings ist der letzte anständige Desktop Rechner uralt und es ist weit und
breit keine neue Hardware zu sehen. Ausserdem bin ich zu sehr Gamer, um auf Windows zu verzichten und möchte bei der
Auswahl von Grafikkarte, Soundkarte und RAM nicht auf die Zwangszuweisung von Apple angewiesen sein.

Ich habe also angefangen, mich in diverse Foren einzulesen, Anleitungen zur Erstellung eines Installationsmediums zu lesen und
schlussendlich habe ich mir aus meiner uralten, aus meiner Macbook-Zeit übriggebliebenen Installations CD einen USB Stick
erstellt, mit dem ich mich an die Installation auf meiner Hardware gewagt habe. Es ging nicht ohne die tatkräftige Hilfe aus
einem Forum, wo meine ersten Installationsversuche noch einmal begutachtet und korrigiert wurden. Unter anderem braucht man

  • das Installationsmedium (aus dem Apple Store oder aus einem Karton mit uralten CDs)
  • den Clover Installer
  • zusätzliche Kernel Extensions wie FakeSMC

Die Hardware muss auch in etwa passen, z.B. braucht man ein UEFI Board. Empfohlen werden im Moment Boards von Gigabyte, da die
dort verbauten Chipsätze gut mit Mac OS zusammenspielen. Ich habe aber ein etwas älteres Board von ASRock, das auch funktioniert.

Mittlerweile bin ich also so weit, das sich ein funktionierendes Mac OS High Sierra auf meinem Desktop habe. Ich muss zwar
noch vom USB Stick booten und dann erst das Mac OS auf der internen SSD starten, aber das bekomme ich auch noch in den Griff.

Meine Nvidia GTX 970 macht auch schon ein Bild, aber die offiziellen Treiber laufen noch nicht. Audio habe ich noch nicht
probiert, aber da ich eine externe USB Soundkarte von Xonar habe, sollte das auch kein Problem sein.

Edit Die Grafikkarte läuft auch.

Screenshot von Mac OS High Sierra

Einziger Bug: beim Start öffnet sich eins meiner Bluray Laufwerke. Aber damit kann ich erstmal leben.

Enable request logging in Jetty 9.1

Today I wanted to have a more detailed look into the requests coming into one of my applications using
Eclipse Jetty. While it is easy enough to see incoming requests by enabling logging for
class org.eclipse.jetty.server.Server (via the standard java logging API or SLF4J), adding a method to log incoming
request headers is on a different level.

After digging around in the documentation and the sourcecode for a while, this is what I came up with:

// Create a server, but do not start it. This would prevent adding
// handlers later
Server server = JettyHttpContainerFactory.createServer(baseUri, null, null, false);

HandlerCollection handlers = new HandlerCollection();
// request log handler
RequestLogHandler requestLogHandler = new RequestLogHandler();
RequestLog requestLog = new Slf4jRequestLog();
requestLogHandler.setRequestLog(requestLog);
RequestLog traceLog = new Slf4jRequestLog() {
  @Override
  public void log(Request request, Response response) {
	  LOG.info("*************************************");
	  try {
	    Enumeration<String> headerNames = request.getHeaderNames();
	    while(headerNames.hasMoreElements()) {
		    String headerName = headerNames.nextElement();
		    String headerValue = request.getHeader(headerName);
		    LOG.info("{}: {}", headerName, headerValue);
	    }
	    // only dump the request body if we can reset the inputstream
	    if(request.getInputStream().markSupported()) {
		    request.getInputStream().mark(Integer.MAX_VALUE);
		    LOG.info(IOUtils.toString(request.getInputStream()));
		    request.getInputStream().reset();
	    } else {
		    LOG.info("Can not dump request body, because it can not be reset");
	    }
	  } catch (IOException e) {
	    LOG.warn(e);
	  }
	  LOG.info("*************************************");
  }
};
requestLogHandler.setRequestLog(traceLog);
// handler for real requests
final JettyHttpContainer containerHandler = ContainerFactory.createContainer(JettyHttpContainer.class,
	new RestResourceConfigWithSpringSupport("application-context.xml", MyServiceClass.class));
// add all handlers
handlers.setHandlers(new Handler[]{requestLogHandler, containerHandler});
server.setHandler(handlers);

server.start();

Note that I’m using a RestResourceConfigWithSpringSupport, but that doesn’t have to be the case. The main point for me
was to create the JettyHttpContainer myself and not use the one created by a different call to
JettyHttpContainerFactory.createServer(...). This way I can see at least the HTTP headers coming into my application. I’d
prefer to see the body too, but I didn’t want to spent the time for it right now.

If anyone knows a way to wrap the request InputStream into a re-readable option, please let me know.