Categories
Java

Configuring logging in a Java web application

Here is a short HOWTO for making some initial configuring when using Commons logging or log4j. Additionally this post will describe how to set the default locale in a servlet environment.

First you will need to create a new class derived from HttpServlet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package mypackage;
 
import java.util.Locale;
 
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
 
/**
 * Initializes log4j so it reads its configuration from WEB-INF directory and sets default locale.
 * @author Ralph Schuster
 *
 */
public class LogConfiguratorServlet extends HttpServlet {
 
   /**
    * Serial ID.
    */
   private static final long serialVersionUID = -5756062055681369027L;
 
   private static final String DEFAULT_FILE = "WEB-INF/log4j.properties";
 
   private static final String DEFAULT_LOCALE = "en_US"; // You can use "en", too.
 
   /**
    * Initializes log4j and sets default locale.
    */
   public void init() {
      // Do the log4j configuration
      String prefix =  getServletContext().getRealPath("/");
      String file = getInitParameter("config-file");
      // if the config-file is not set, then no point in trying
      String s = null;
      if (file != null) {
         s = prefix+file;
      } else {
         s = prefix+DEFAULT_FILE;
      }
      PropertyConfigurator.configure(s);
      LogFactory.getLog(getClass()).debug("log4j configuration file: "+s);
 
      // Do the locale configuration
      s = getInitParameter("locale");
      if (s == null) s = DEFAULT_LOCALE;
      Locale available[] = Locale.getAvailableLocales();
      for (int i=0; i<available.length; i++) {
         if (available[i].toString().equals(s)) {
            Locale.setDefault(available[i]);
         }
      }
      LogFactory.getLog(getClass()).debug("Default locale set to: "+Locale.getDefault());
   }
 
   /**
    * Does nothing.
    */
   public void doGet(HttpServletRequest req, HttpServletResponse res) {
   }
 
}

You then need to deploy the class in your servlet container and adjust the web.xml file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   <servlet>
      </servlet-name>log4j-init</servlet-name>
      <servlet-class>mypackage.LogConfiguratorServlet</servlet-class>
 
      <init-param>
         <param-name>config-file</param-name>
         <param-value>WEB-INF/log4j.properties</param-value>
      </init-param>
      <init-param>
         <param-name>locale</param-name>
         <param-value>de_DE</param-value>
      </init-param>
 
      <load-on-startup>1</load-on-startup>
   </servlet>
Categories
Protocols

HTTP headers for binary file downloads

In case you need to send files from a webserver, use these HTTP headers:

Content-Type:application/octet-stream
Content-Disposition:attachment;filename=filename
Content-Length:100

Of course, you need to set your own content type, filename and file length. 🙂

Categories
WordPress

WordPress Bad Behaviour blocking wp-cron

I noticed that Bad Behaviour did block my WordPress’ wp-cron requests. There is a solution: Add your server’s IP address to the whitelist.inc.php variable $bb2_whitelist_ip_ranges:

$bb2_whitelist_ip_ranges = array(
                "10.0.0.0/8",
                "172.16.0.0/12",
                "192.168.0.0/16",
                "<your-ip-here>",
);
Categories
Perl

Scanning directories with Perl

I often come across a task to do specific processing for each file at a subdirectory tree. Here is a skeleton code for what you need to get it started.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/perl
 
my $ROOTDIR = shift;
processDir($ROOTDIR);
 
exit 0;
 
# This is the main routine. Do not change it unless you know what you do!
sub processDir {
   my $dir = shift;
   my (@FILES, $entry, $path);
 
   if (opendir(DIRIN, $dir)) {
      @FILES = readdir(DIRIN);
      closedir(DIRIN);
 
      # iterate over dir entries
      foreach $entry (@FILES) {
         next if $entry eq '..';
         next if $entry eq '.';
         $path = "$dir/$entry";
 
         if (-f $path) {
            if (fileCheck($path)) {
               processFile($path);
            }
         } elsif (-d $path) {
            if (dirCheck($path)) {
               # recurse into subdir
               processDir($path);
            }
         }
      }
   }
}
 
# Do your file processing in this function only
# $file will have the complete path
sub processFile {
   my $file = shift;
}
 
# This function decides whether a file should be processed or not
# Return 1 when you want a file to be processed
# $file will have the complete path
sub fileCheck {
   my $file = shift;
   return 1;
}
 
# This function decides whether a directory should be searched recursively.
# Return 1 when you want the algorithm to steep into the directory.
# $dir will have the complete path
sub dirCheck {
   my $dir = shift;
   return 1;
}

You only will need to override lines 39-41. In case you don’t want to handle all files and directories, just make appropriate implementations in functions checkFile() and checkDir() respectively. This code works on all platforms.

Categories
Miscellaneous

Prevent Spamming

I usually get annoyed by spam robots. They are able nowadays to even bypass captchas. So what helps? I recently read an article saying that scientists work on a new kind of spam filters that can identify spam by the way the actual text looks like. That raised an idea in my head. Why not just count the number of links that a new guestbook entry contains? Usually this is what they do at my guestbook. They leave dozens of links. So I added a simple count in my guestbook plugin. Whenever there are too many links, I just ignore the entry. 🙂

Categories
Java

SimpleCaptcha for Servers

Currently there is a bug in SimpleCaptcha library that prevents it running in non-graphics environments. It will throw a java.awt.HeadlessException. Although the code does not rely on various graphics classes, they were left causing this problem.

I fixed the code and recompiled it. You can download the fixed JAR file here. Do not forget to set the system property java.awt.headless to true, e.g. by specifying Djava.awt.headless=true at command line.

Categories
Java Typo3

TYPO3-like templating with Java

Here is a class I wrote to apply TYPO3-like templating mechanism within Java. I am quite familiar with that kind of templates, so I decided to use it within one of my projects, too. The implementation requires Java 5.

Java Templating class

You need to adopt the class’ package though 😉

Categories
Perl

Perl Message Logging

The following code is a quick and dirty, but nevertheless usefull snippet to add logging facility to any perl script. You might want to add additional severities at lines 2-6, change the timestamp format at line 14, or enable logging into a file at lines 42-54.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# Defines severities of messages to log
my %TYPES = (
   ERROR => 1,
   DEBUG => 1,
   INFO  => 1
);
 
# Creates the time string for log messages
# Usage: getTimestring($unixTimeValue)
sub getTimestring {
   my $t = shift;
   $t = time if !$t;
   my @T = localtime($t);
   my $time = sprintf("%02d/%02d/%04d %02d:%02d:%02d",
              $T[3], $T[4]+1, $T[5]+1900, $T[2], $T[1], $T[0]);
   return $time;
}
 
# logs an error message
# Usage: logError($message);
sub logError {
   my $s = shift;
   logEntry($s, 'ERROR');
}
 
# logs an information message
# Usage: logInfo($message);
sub logInfo {
   my $s = shift;
   logEntry($s, 'INFO');
}
 
# logs a debug message
# Usage: logDebug($message);
sub logDebug {
   my $s = shift;
   logEntry($s, 'DEBUG');
}
 
# logs a single entry with given message severity
# Usage: logEntry($message, $severity);
sub logEntry {
   my $s = shift;
   my $type = shift;
   return if !$TYPES{$type};
 
   # build timestamp and string
   $type = rpad($type, 5);
   my $time = getTimestring();
   $s =~ s/\n/\n$time $type - /g;
 
   # print to STDOUT if required
   print "$time $type - $s\n";
}
 
# Right pads a string
# Usage: rpad($string, $maxlen[, $padchar]);
sub rpad {
   my $s = shift;
   my $len = shift;
   my $char = shift;
 
   $char = ' ' if !$char;
   $s .= $char while (length($s) &lt; $len);
   return $s;
}
Categories
Java PHP Perl

URL Parameter Transforming

Need to transform URL parameters and decode values such as “Hello%20World!”? Here is how:

Perl:

$s =~ s/%([\da-f][\da-f])/chr( hex($1) )/egi;

Java:

s = java.net.URLEncoder.encode(s, "UTF-8");

PHP:

$s = urldecode($s);
Categories
Miscellaneous

Country Codes and Timezones

My current job often challenge me with various country codes and timezones. So I prepared two lists providing you with this information. country_codes.csv list all country codes (ICAO, ISO 2-letter, ISO 3-letter, ISO 3-digit), country names and continents. timezones.csv will list the ISO 2-letter code together with country name and Unix Timezone. Both lists might not be complete. So if you find errors or omissions, just let me know.

Country Code List (CSV)

Unix Timezones (CSV)