Results for category "Publikationen"

20 Articles

h2benchw2csv released / Benutzerfreundlichkeit Teil 2

Wie gestern angekündigt, wurde noch heute Nacht das Projekt freigeschaltet. So eben habe ich die Build-Scripte angepasst und die Version 1.0 auf Sourceforge hochgeladen. h2benchw2csv ist nun unter http://h2benchw2csv.sourceforge.net verfügbar.

Während der Projekteinrichtung musste ich feststellen, dass die Entwickler hinter der GUI von sf.net mittlerweile einiges getan haben. Die Zuweisung der Projektkategorien läuft nun per AJAX. Allerdings konnte ich feststellen, dass man einem Projekt unter Umständen leere Kategorien zuweisen kann.

Weiterhin funktioniert nun die Aktivierung / Deaktivierung von Projekt-Features (Mailing List, Tracker u.s.w.) ebenfalls per AJAX.

Twicker 1.0 veröffentlicht

Nachdem ich in den letzten Tagen zig andere Sachen zu tun hatte, bin ich heute endlich dazu gekommen, Twicker zu veröffentlichen. Twicker ist eine kleine JavaScript-Applikation, die aus vordefinierten Twitter-Tweets eine Statistik über gespielte Kicker-Spiele führt. Twicker inkl. Live-Demo ist unter http://twicker.sourceforge.net zu finden.

ADUaCET released

A few minutes ago I released ADUaCET (Active Directory User and Computer Employee Tab) on sourceforge.net.
With ADUaCET the Microsoft Active Directory User and Computer MMC will be extended so that you are able store the image and employee number of users in Active Directory.

ServiceConsoleControl

Gestern habe ich ein alt-bekanntes Problem gelöst. Des öfteren muss ich über die Konsole Windows-Dienste neu starten. Da “net restart” nicht existiert, muss man auf

net stop $SERVICE && net start $SERVICE

zurückgreifen.
Außerdem haben wir in unseren Backup-Scripts einige Dienste, die Abhängigkeiten zu anderen Diensten haben (z.B. McAffe EPO, das von MSSQL abhängt). Hier wäre der pragmatische Lösungsansatz

net stop "McAfee Alert Manager" >> %log%
net stop "McAfee ePolicy Orchestrator 3.6.1 Application Server" >> %log%
net stop "McAfee ePolicy Orchestrator 3.6.1 Server" >> %log%
net stop "McAfee ePolicy Orchestrator 3.6.1 Event Parser" >> %log%
net stop "McAfee Outbreak Manager" >> %log%
net stop "McAfee Log Service" >> %log%
net stop "McAfee SpamKiller" >> %log%
net stop "SQLAgent$EPOSERVER" >> %log%
net stop "MSSQL$EPOSERVER" >> %log%

REM Am Ende alles wieder starten

Viel einfacher wäre ein einfaches

net stop MSSQL$EPOSERVER

wodurch alle von diesem Dienst abhängigen Dienste ebenfalls beendet werden.

Soweit so gut, ich habe mich gestern also hingesetzt und das ganze in C# heruntergetippert. scc (angelehnt an sc) unterstützt die Befehle “start, stop und restart”. Der Code dafür lautet:

using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;
using System.Threading;

namespace ServiceConsoleControl
{
    /// <summary>
    /// Main entry class
    /// </summary>
    class Program
    {
        private static String NAME = "scc";

        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                ShowUsageAndExit(null);
            }

            try
            {
                Command cmd = Command.Factory(args[0]);
                cmd.SetServiceName(args[1]);
                cmd.Execute();
            }
            catch (Exception e)
            {
                ShowUsageAndExit("Error: " + e.Message);
            }
        }
        /// <summary>
        /// Shows the usage of this program and exits with code 0
        /// </summary>
        /// <param name="_line">additional line to print before usage is shown</param>
        public static void ShowUsageAndExit(String _line)
        {
            if (_line != null)
            {
                Program.LogLine(_line);
            }

            Program.LogLine(Program.NAME + " starts, stops and restarts services with all dependencies to other services");
            Program.LogLine("Usage: " + Program.NAME + " [" + Command.CMD_START + ", " + Command.CMD_STOP + ", " + Command.CMD_RESTART + "] [Service]");
            Environment.Exit(0);
        }

        /// <summary>
        /// Write string to console
        /// </summary>
        /// <param name="_msg">string to write</param>
        public static void LogLine(String _msg)
        {
            Console.WriteLine(_msg);
        }
    }

    /// <summary>
    /// Interface for executable service commands
    /// </summary>
    interface IServiceCommand
    {
        /// <summary>
        /// Execute the command
        /// </summary>
        void Execute();

        /// <summary>
        /// Sets name of service
        /// </summary>
        /// <param name="_name">name of service</param>
        void SetServiceName(String _name);

        /// <summary>
        /// Retrieves name of service
        /// </summary>
        /// <returns>name of service</returns>
        string GetServiceName();
    }

    /// <summary>
    /// Abstract class for commands, implements IServiceCommand
    /// </summary>
    abstract class Command : IServiceCommand
    {
        private String _name;

        protected ServiceController sc = new ServiceController();

        public static String CMD_STOP = "stop";

        public static String CMD_START = "start";

        public static String CMD_RESTART = "restart";

        /// <summary>
        /// Factory method for command.
        /// Given command will be lowered.
        /// If the command is not supported, an exception will be thrown
        /// </summary>
        /// <param name="_cmd">Command to execute - this can be one of this.CMD_*</param>
        /// <returns>Instance of Command</returns>
        public static Command Factory(String _cmd)
        {
            _cmd = _cmd.ToLower();

            if (_cmd.Equals(CMD_RESTART))
            {
                return new RestartCommand();
            }
            else if (_cmd.Equals(CMD_START))
            {
                return new StartCommand();
            }
            else if (_cmd.Equals(CMD_STOP))
            {
                return new StopCommand();
            }

            throw new Exception("Unsupported command: " + _cmd);
        }

        /// <summary>
        /// Sets service name, required by IServiceCommand
        /// </summary>
        /// <param name="_serviceName">Service name to set</param>
        public void SetServiceName(String _serviceName)
        {
            _name = _serviceName;
            sc.ServiceName = _serviceName;
        }

        /// <summary>
        /// Gets service name, required by IServiceCommand
        /// </summary>
        /// <returns>Service name</returns>
        public String GetServiceName()
        {
            return _name;
        }

        /// <summary>
        /// Abstract execute command which is required by IServiceCommand
        /// </summary>
        abstract public void Execute();
    }

    /// <summary>
    /// Abstract class for recursive commands, can be used for solving dependencies between services
    /// </summary>
    abstract class RecursiveCommand : Command
    {
        /// <summary>
        /// Depth of dependency
        /// </summary>
        private int _depth = 0;

        /// <summary>
        /// Stringbuilder with prefixing spaces
        /// </summary>
        private StringBuilder sb;

        /// <summary>
        /// Timespan to wait for service
        /// </summary>
        protected TimeSpan tsWait = new System.TimeSpan(10000000000000);

        /// <summary>
        /// Abstract method which retrieves the recursive command
        /// </summary>
        /// <returns>RecursiveCommand</returns>
        abstract protected RecursiveCommand GetCommand();

        /// <summary>
        /// Depth value
        /// </summary>
        public int Depth
        {
            set { _depth = value; }
            get { return _depth; }
        }

        /// <summary>
        /// Return depth as spaces
        /// </summary>
        /// <returns>String with depth as spaces</returns>
        protected String GetSpaces()
        {
            if (sb == null)
            {
                sb = new StringBuilder();

                for (int i = 0; i < _depth; i++)
                {
                    sb.Append("  ");
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// Executes GetCommand() on all given ServiceController[]
        /// </summary>
        /// <param name="scs">Array of ServiceController on which the GetCommand() will be executed</param>
        protected void ExecuteCommandOnServiceControllers(ServiceController[] _scs)
        {
            Program.LogLine(GetSpaces() + "Service dependencies: " + _scs.Length);

            for (int i = 0, m = _scs.Length; i < m; i++)
            {
                RecursiveCommand rc = this.GetCommand();
                rc.Depth = this.Depth + 1;
                rc.SetServiceName(_scs[i].ServiceName);
                rc.Execute();
            }
        }

        /// <summary>
        /// Returns true if service is of ServiceType Win32ShareProcess or Win32OwnProcess. Other types cannot be killed
        /// </summary>
        protected bool IsKillable
        {
            get
            {
                if (sc.ServiceType.Equals(ServiceType.Win32ShareProcess) || sc.ServiceType.Equals(ServiceType.Win32OwnProcess))
                {
                    return true;
                }

                Program.LogLine(GetSpaces() + this.DisplayName + " is of type " + sc.ServiceType.ToString() + ". These services can not be processed.");
                return false;
            }
        }

        /// <summary>
        /// Returns display name
        /// </summary>
        public String DisplayName
        {
            get
            {
                return "Service " + sc.DisplayName + " (" + sc.ServiceName + ")";
            }

        }
    }

    /// <summary>
    /// Command for restarting a service
    /// </summary>
    class RestartCommand : Command
    {
        /// <summary>
        /// Stops the service and then restarts
        /// </summary>
        public override void Execute()
        {
            IServiceCommand stopCmd = new StopCommand();
            IServiceCommand startCmd = new StartCommand();
            stopCmd.SetServiceName(this.GetServiceName());
            startCmd.SetServiceName(this.GetServiceName());

            stopCmd.Execute();
            startCmd.Execute();
        }

        public override String ToString()
        {
            return CMD_RESTART;
        }
    }

    /// <summary>
    /// Command for starting a service with all its dependencies
    /// </summary>
    class StartCommand : RecursiveCommand
    {
        public override String ToString()
        {
            return CMD_START;
        }

        /// <summary>
        /// Retrieve a new instance of myself
        /// </summary>
        /// <returns></returns>
        protected override RecursiveCommand GetCommand()
        {
            return new StartCommand();
        }

        /// <summary>
        /// Starts a service. The service could only be started if it is Win32[Own|Share]Process. KernelDriver or other types of services are not allowed.
        /// At first all services will be started which this service depends on. At second the service itself will be started.
        /// After that all services are started which depends on this service.
        /// </summary>
        public override void Execute()
        {
            if (this.IsKillable)
            {
                if (sc.Status.Equals(ServiceControllerStatus.Stopped))
                {
                    Program.LogLine(GetSpaces() + "Starting " + this.DisplayName);
                    Program.LogLine(GetSpaces() + "Starting all services that " + this.DisplayName + " depends on ...");
                    ExecuteCommandOnServiceControllers(sc.ServicesDependedOn);
                    sc.Start();
                    sc.WaitForStatus(ServiceControllerStatus.Running, tsWait);
                    Program.LogLine(GetSpaces() + "Service is now in status " + sc.Status.ToString());
                    Program.LogLine(GetSpaces() + "Starting all services that depends on " + this.DisplayName + " ... ");
                    ExecuteCommandOnServiceControllers(sc.DependentServices);
                }
                else
                {
                    Program.LogLine(GetSpaces() + this.DisplayName + " has status " + sc.Status.ToString() + " - nothing to do");
                }
            }
        }
    }

    /// <summary>
    /// Command for stopping a service with all its dependencies
    /// </summary>
    class StopCommand : RecursiveCommand
    {
        public override String ToString()
        {
            return CMD_STOP;
        }

        /// <summary>
        /// Returns an instance of myself
        /// </summary>
        /// <returns>New instance of StopCommand</returns>
        protected override RecursiveCommand GetCommand()
        {
            return new StopCommand();
        }

        /// <summary>
        /// Executes the command. The service could only be stopped if it is Win32[Own|Share]Process. KernelDriver or other types of services are not allowed.
        /// At first all services will be stopped that depends on this service. Then this service is stopped.
        /// </summary>
        public override void Execute()
        {
            if (this.IsKillable)
            {
                if (sc.Status.Equals(ServiceControllerStatus.Running))
                {
                    Program.LogLine(GetSpaces() + "Stopping " + this.DisplayName);
                    Program.LogLine(GetSpaces() + "Stopping all services that depends on " + this.DisplayName + " ...");
                    ExecuteCommandOnServiceControllers(sc.DependentServices);
                    sc.Stop();
                    sc.WaitForStatus(ServiceControllerStatus.Stopped, tsWait);
                    Program.LogLine(GetSpaces() + "Service is now in status " + sc.Status.ToString());
                }
                else
                {
                    Program.LogLine(GetSpaces() + this.DisplayName + " has status " + sc.Status.ToString() + " - nothing to do");
                }
            }
        }
    }
}

Patched mod_auth_sspi compiled against Apache 2.0.61

The last Apache module i published was linked against Apache 2.0.54 and compiled with Visual Studio 2005. Yesterdy evening I noticed, that the module does not work with Apache 2.0.61.
So i compiled it with Visual C++ 6 and used the includes from Apache 2.0.61.

Patch for mod_auth_sspi

I finished my patch for mod_auth_sspi. With this patch you get the additional directive SSPIUseActiveDirectoryStyle. You must set SSPIOmitDomain to ‘off’ for using it:

# ... httpd.conf
SSPIOmitDomain Off
SSPIUseActiveDirectoryStyle On

If enabled, the REMOTE_USER-variable will store the domain-username combination as $USER@$DOMAIN and not $DOMAIN$USER.
I made this patch, because I am currently working on a seamleas authentication integration for Mediawiki and the extension Auth_remoteuser.
The developers of mod_auth_sspi are contacted and I hope the patch will be accepted.

Using BIRT with PHP and php/Java bridge

As I promised some days before, here you get the tutorial of how to use BIRT, PHP, Zend Framework (ZF) and php/Java bridge (pJb).

Software requirements
I have tested the environment with:
* Zend Framework 1.0.1
* php/Java bridge 4.3.0
* BIRT 2.2.0
* PHP 5.2.1
* Ecw_Java_* classes version 1.0 (EcwJ)

Installation
I presume, you have already unpacked ZF. Unpack the EcwJ into the ZF library path (/library).
Unpack the directory ReportEngine from the BIRT package to a directory of your choice.
Create a directory called pJb. Extract the directory java from the JavaBridge.war (it is in the pJb package) into it. Extract /WEB-INF/lib/JavaBridge.jar into the /pjb directory.
Create the directories /pjb/lib and /pjb/srv

In the end you should have the following directory structure:


/birt/
/birt/ReportEngine
/pjb/
/pjb/java
/pjb/lib
/pjb/srv
//library/Ecw
//library/Ecw/Java
//library/Ecw/Java/Bridge
//library/Ecw/Java/Reporting
//library/Ecw/Java/Reporting/Birt

Create a batch or bash file /pjb/start-bridge.[bat|sh]. Use this content.

Windows:

java.exe -Duser.home=$DIR_PJBsrv;php.java.bridge.base=$DIR_PJB JavaBridge.jar SERVLET:8080 5 php-java-brige.log

Windows:

#!/bin/bash
java -Duser.home=$DIR_PJB/srv;php.java.bridge.base=$DIR_PJB JavaBridge.jar SERVLET:8080 5 php-java-brige.log

Replace $DIR_PJB with your installation directory of pJb. The argument -Duser.home fixes a security hole version 4.3.0 of pJb contains.

You can now start the pJb with executing start-bridge.[bat|sh].
php-java-bridge.log should contain something like this:

Sep 23 19:57:40 JavaBridge INFO : VM                  : 1.6.0_02@http://java.sun.com/
Sep 23 19:57:40 JavaBridge INFO : JavaBridge version             : 4.2.2
Sep 23 19:57:40 JavaBridge INFO : logFile             : php-java-brige.log
Sep 23 19:57:40 JavaBridge INFO : default logLevel    : 5
Sep 23 19:57:40 JavaBridge INFO : socket              : SERVLET:8080
Sep 23 19:57:40 JavaBridge INFO : java.ext.dirs       : C:ckldevlangjavadistjre1.6.0_02libext;C:WINDOWSSunJavalibext
Sep 23 19:57:40 JavaBridge INFO : php.java.bridge.base: C:ckldevprojectsweb200_VwpilotPRtrunkbinphp-java-bridgesrv;php.java.bridge.base=C:ckldevprojectsweb200_VwpilotPRtrunkbinphp-java-bridge
Sep 23 19:57:40 JavaBridge INFO : extra library dir   : C:ckldevprojectsweb200_VwpilotPRtrunkbinphp-java-bridgesrv;php.java.bridge.base=C:ckldevprojectsweb200_VwpilotPRtrunkbinphp-java-bridgelib
Sep 23 19:57:40 JavaBridge INFO : thread pool size    : 20
Sep 23 19:57:40 JavaBridge INFO : JavaBridgeRunner started on port INET:8080
...

Set the environment variable BIRT_HOME to the direcoty of your ReportEngine.

Windows:

set BIRT_HOME=$DIR_BIRT/ReportEngine

Linux

export BIRT_HOME=$DIR_BIRT/ReportEngine

Replace $DIR_BIRT with your installation path of BIRT.

First steps in PHP
Copy the following content to a ZF controller of your choice:

Ecw_Java_Bridge_Instance::setServerUrl("$SERVER_URL");
            Ecw_Java_Bridge_Instance::getInstance();
java_set_file_encoding("UTF-8");
Ecw_Java_Bridge_Instance::java_require_dir("$DIR_RE/lib");

$report = new Ecw_Java_Reporting_Birt_Pdf("$DIR_RE");
$report->setReportPath("$DIR_RE/samples/hello_world.rptdesign");
$report->setOutputFileName("$DIR_RE/samples/hello_world.pdf");
            $report->run();

Replace $SERVER_URL with the address of pJb instance. This should be http://localhost:8080/JavaBridge/java/Java.inc.
Replace $DIR_RE with the BIRT ReportEngine directory.

Execute the controller in your browser and you should see a hello_world.pdf in $DIR_BIRT/samples directory.

Using BIRT and PHP without Zend Plaform

Oh well… my first blog entry in English, because I think this article is interesting for all the PHP developers out there – including non-German people 😉

Every developer will reach the point generating reports for the running project. Making reports with Java oder .NET is relatively easy. Products like Crystal Reports (commercial) or BIRT (open source) support developers in designing and creating pleasant reports.

PHP can be extended with the function of BIRT with buying the Zend Platform. But in most cases the minority of people is able to buy this product. Zend Platform costs around 1000$ – 1500$ for a one year license.

Our development team had the problem of generating reports with PHP more than one time. In our last project we used FOP + XSL/XSLT from the Apache Foundation and triggered the report building by using exec() and command line.
The problem with FOP is that it is highly memory intensive and the building of XSLT templates is time consuming – if you do not have nice tools for that.
Last week I investigated and evaluated BIRT for using it in a J2EE/GWT-based application we are programming. The BIRT Designer is a nice tool for creating reports in HTML and/or PDF and we will (hopeley) include it in our project.
I demonstrated the results Christoph who was really amazed of it. Christoph said “Well… it would be so nice using BIRT with PHP for ZABOS (ZABOS is our SMS Alert System). But Zend Platform is sooo expensive.” (mimimi)
It was friday afternoon and nothing more was to do so I decided to look for reporting mechanisms in PHP. The results were… let’s say: poor 😉

The next idea was triggering BIRT from command line via PHP exec()’s method. I wrote a wrapper class in Java, which could be used to start BIRT from command line (using java -jar de.ecw.birt.BIRTRunner –help).
After some minutes of coding and testing this class worked like a charme. I was happy, but I thought “Woah… It would be nice using Java directly from PHP”. I remembered that there was a PHP module called php_java which could access Java through the JNI (Java Native Interface). But all the comments on php.net said the old php_java module is more than deprecated and does not work. The newer commentator said that the php/Java-Bridge was a worth checking at. Hm… I read the documentation of the php/Java-Bridge and was enthusiastic: This was exactly what I needed.

I downloaded the latest release and was a little bit confused about the different files and JARs.
The solution is easy: Unpack the JavaBridge.war archive. The folder /java is needed in your PHP project path and includes all classes for connecting to the JavaBridge-server.
The file /WEB-INF/lib/JavaBridge.jar must be extracted to a directory of your choice (= $path-to-java-bridge). Please create inside this directory another directory called ‘lib’.
Your folder must look like this:

/java-bridge
JavaBridge.jar
/lib

Afterwards I started the server:

cd $path-to-java-bridge
java.exe -Dphp.java.bridge.base=$path-to-java-bridge -jar JavaBridge.jar SERVLET:8080 6 php-java-brige.log

The log file did not show any error so I tried a simple “Hello world” in Java and PHP:

<?php
  // index.php
  require_once("java/Java.inc");
  $aString = new Java("java.lang.String", "Hello world");
  print $aString;
?>

Really nice: PHP connected to the local JavaBridge server. The JavaBridge instantiates a new String-object an called the toString() method. This was exactly what I needed for using php/Java-bridge with BIRT.

I refactored my own BIRTRunner class so that I just needed to call 4 methods and I got the desired result.
The appended .jar file must be extracted to the $path-to-java-bridge/lib, and you must restart the JavaBridge AND Apache. There seems to be an issue with UTF-8/JavaBridge/Apache.

My index.php had to be refactored too:

<?php
  // index.php
  // require JavaBridge interface
  require_once("java/Java.inc");
  // set encoding to UTF-8
  java_set_file_encoding("UTF-8");

  // remove try-/catch-block if not using PHP5
  try
  {
    // where our reports are stored
    $targetFile = "d:/result.html";
    // ConcreteTask encapsulate the logic
    $birtTask = new Java("de.ecw.birt.task.ConcreteTask");
    // the home of your BIRT-runtime directory
    $birtTask->setEngineHome('D:DevelopmentBIRT_RuntimeReportEngine');
    // the path of your BIRT report design
    $birtTask->setReportPath('D:DevelopmentBIRTworkspaceCAPlanuser.rptdesign');
    // create new render options
    $htmlRenderOptions = new Java("org.eclipse.birt.report.engine.api.HTMLRenderOption");
    $htmlRenderOptions->setOutputFileName($targetFile);
    $birtTask->setRenderOption($htmlRenderOptions);
    // run the BIRT task
    $birtTask->run();

    // get file content and print to browser
    $content = file_get_contents($targetFile);
    echo $content;
  }
  catch (JavaException $e)
  {
    print $e->getMessage();
  }
?>

To my surprise it worked. I had not really expected it – but I was really able to use PHP and BIRT without buying Zend Platform.

There are so many possibilities and TODOs I want to mention:
* You can create the .rptdesign on-the-fly using Smarty
* You cold write a wrapper class on PHP side so it is much easier to create reports
* … to be continued