better logging than printf – using log4j – part II

However, Just like with computers, cars and women there is always a faster, bigger, or better model on the horizon.

Version 1.2 of log4j has reached its end of life on August 5th 2015 but there is a version 2 to take it place.  There is a lot of things to like about the new version of log4j with some of the benefits being.

  • Improved performance
  • Support for multiple API’s
  • Plugin architecture
  • Java 8 lambda support
  • Custom log levels

Some of the basics of log4j was explained in part I.

Log4j version 1.2

Using version 1.2 of log4j it is really easy to send our output to either the screen or to a file.

Property file

log4j.rootLogger=INFO, stdout, pgmlogfile

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d; %-5p; (%F:%L); %m%n

log4j.appender.pgmlogfile=org.apache.log4j.FileAppender
log4j.appender.pgmlogfile.file=${LOGDIR}/${LOGFILE}
log4j.appender.pgmlogfile.Append=true
log4j.appender.pgmlogfile.layout=org.apache.log4j.PatternLayout
log4j.appender.pgmlogfile.layout.ConversionPattern=%d %-5p; (%F:%L); %m%n

This log4j property file will display the output to both the console and save it to a log file.  In this example the output file is determined at runtime by evaluating the LOGDIR and the LOGFILE environment variables.

The configuration format of log4j2 can still support the old properties file style format, however, the contents of that file would be slightly different for version 2.

Rather than trying to keep these two incompatible configuration files separate it is just as easy to switch over to the xml format that is supported by version 2.0 of log4j2.

Note: XML isn’t really new as it was possible to have xml configuration files with version 1.2 of log4j.

Log4j version 2

Log4j2 will load its configuration from a file, but now it supports so many possible formats there is a specific order that it will go through in an attempt to find the configuration file when one isn’t presented to it.  The first place it looks is if the log4j.configurationFile property is set in your virtual machine. When this is defined it will be used regardless how the file is named.

When this property is not defined, then log4j will look for the config file in the classpath.  The default configuration file to use will be searched for using the following names in this order.

log4j2-test.properties
log4j2-test.yaml or log4j2-test.yml
log4j2-test.json or log4j2-test.jsn
log4j2-test.xml
log4j2.properties
log4j2.yaml or log4j2.yml
log4j2.json or log4j2.jsn
log4j2.xml

If no configuration file could be located the DefaultConfiguration will be used. This will cause logging output to go to the console.  The default configuration is not bad but by default it will only display errors or higher and only to the screen.

log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config">
	<Properties>
		<Property name="LOG_NAME">logfile.log</Property>
		<Property name="LOG_DIR">${sys:LOGDIRECTORY}</Property>
		<Property name="LOG_ARCHIVE">${sys:LOGARCHIVE}</Property>
		<Property name="ROLL_NAME">logfile-%d-%i.log</Property>
		<Property name="FILEPATTERN">%-5p | %d{yyyy-MM-dd HH:mm:ss} | [%t] %C (%F:%L) - %m%n</Property>
		<Property name="PATTERN">%-5p | %C{2} (%F:%L) - %m%n</Property>
	</Properties>
	<Appenders>
		<RollingFile name="ROLLINGFILE" fileName="${LOG_DIR}/${LOG_NAME}" filePattern="${LOG_ARCHIVE}/${ROLL_NAME}" append="true">
		<PatternLayout pattern="${FILEPATTERN}"/>
		<Policies>
			<SizeBasedTriggeringPolicy size="1 KB" />
		</Policies>
		<DefaultRolloverStrategy max="4"/>
	</RollingFile>
	<Console name="STDOUT" target="SYSTEM_OUT">
		<PatternLayout pattern="${PATTERN}"/>
	</Console>
	</Appenders>

	<Loggers>
		<!-- add this line to get debug output for this particular class -->
		<Logger name="de.companyname.utility.Mymath" level="debug"/>

		<Root level="info">
			<AppenderRef ref="STDOUT"/>
			<AppenderRef ref="ROLLINGFILE"/>
		</Root>
	</Loggers>
</Configuration>

This configuration file is similar to the old log4j property file listed above. The output from level info or above will be output to both the screen and saved to a file. The format of the two different types of output can either use the same or a different format.  In this case, the log file contains an extra date and time stamp per line.

One other slight difference is that the log file will contain the full package and class name (%C) while the console output will only display a portion (%C{2}) of the package name. When the log file reaches 1 kilobyte, it will be renamed keeping up to four log files. Beyond that the oldest will be deleted.  This can obviously be changed to more realistic sizes in the megabytes.

It might not be be obvious at the first glance but there is a neat little trick you can do as part of the rolling appender setup.  If we use a different directory as part of the filepattern then we are actually not only renaming the old files but moving them to a different directory when the file size reaches the maximum size.

The only thing not fully explained is the following line.

<!-- add this line to get debug 
output for this particular class -->
<Logger name="de.companyname.utility.Mymath" level="debug"/>

The comment does rather give it away. Adding this line to our log4j2 properties actually will allow us to easily see the debug output for that particular class without turning on debugging for the entire program.

One final difference between the old and new version of log4j is how properties inside of the configuration file are treated.  To access the JVM values it is necessary to prefix them with “sys:”.

It is not necessary to define everything as a property as is done in this example.  However, doing so does show the contrast between the JVM values and standard properties.

Sample program

Program.java

package de.companyname.utility;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Program {

	static Logger logfile = LogManager.getLogger(Program.class.getName());
	
	public static void main(String[] args) 
	{
		logfile.info("Program starting at " + "");
		logfile.trace("add a trace to log output");
		
		for (int index = 1; index <= 5; index++)
		{
			try {
				int square = 
de.companyname.utility.Mymath.square(index);
				logfile.info(index + " x " + index + " = " + 
square);
			}
			catch (Exception ex)
			{
				logfile.fatal(" while processing value " + 
index);
				logfile.fatal(ex.getMessage());
			}
		}
		
		logfile.debug("add some additional debug to output");
		logfile.info("Program finishing at " + "");
	}
}

 

Mymath.java

package de.companyname.utility;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Mymath {

	/*
	 * will return the square of the value input.
	 * this method will only be for the range of positive numbers.
	 */
	static public int square (int value) throws Exception
	{
		Logger logfile = LogManager.getLogger(Mymath.class.getName());
		
		logfile.debug("entering square");
		logfile.debug("parameter is " + value);
		int retval = 0;
		
		if (value > 0)
			retval = value * value;
		else
		{
			logfile.debug("invalid value of " + value + " given");
		}
		
		logfile.debug("leaving square");
		return retval;
	}
}

 

runProgram.sh

#!/bin/bash

VMARGS="-DLOGDIRECTORY=log -DLOGARCHIVE=archive -Dlog4j.configurationFile=resources/log4j2.xml -DLOGARCHIVE=archive -DLOGDIRECTORY=log"
CP=lib/log4j-api-2.6.2.jar:lib/log4j-core-2.6.2.jar:.
PGM=de.companyname.utility.Program

mkdir log
mkdir archive

CMD="java -cp $CP $VMARGS $PGM"

echo $CMD
$CMD

 

Output

With no debugging enabled, the program simply outputs the information messages from the main program.

2016-08-25 17:23:58 | INFO | utility.Program (Program.java:13) – Program starting at
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:20) – 1 x 1 = 1
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:20) – 2 x 2 = 4
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:20) – 3 x 3 = 9
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:20) – 4 x 4 = 16
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:20) – 5 x 5 = 25
2016-08-25 17:23:58 | INFO | utility.Program (Program.java:30) – Program finishing at

It is possible to see the debug output from square method in the Mymath class by adding this to the log4j2 xml file.

<Logger name="de.companyname.utility.Mymath" level="debug"/>

2016-08-25 17:10:38 | INFO | utility.Program (Program.java:13) – Program starting at
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:16) – entering square
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:17) – parameter is 1
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:27) – leaving square
2016-08-25 17:10:38 | INFO | utility.Program (Program.java:20) – 1 x 1 = 1

2016-08-25 17:10:38 | INFO | utility.Program (Program.java:20) – 4 x 4 = 16
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:16) – entering square
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:17) – parameter is 5
2016-08-25 17:10:38 | DEBUG | utility.Mymath (Mymath.java:27) – leaving square
2016-08-25 17:10:38 | INFO | utility.Program (Program.java:20) – 5 x 5 = 25
2016-08-25 17:10:38 | INFO | utility.Program (Program.java:30) – Program finishing at

If the goal was to see either all debug output in the entire program or to reduce the output to only errors and above then simply change the root level (ie. debug or error).

	<Root level="info">
		<AppenderRef ref="STDOUT"/>
		<AppenderRef ref="ROLLINGFILE"/>
	</Root>

All of this is standard log4j2 which is both easy to use and easy to understand.  It is also possible to create new log levels and filter using them as well.  That will be covered in part III on log4j2.

Apache Log4j2 documentation
logging.apache.org/log4j/2.0/log4j-users-guide.pdf

Note: The example was compiled with java 1.8 and uses log4j-api-2.6.2.jar and log4j-core-2.6.2.jar.

Posted in programming | Tagged , , | Comments Off on better logging than printf – using log4j – part II

better logging than printf – using log4j – part I

The old way

Log files or debugging can be done using print statements.  It is a very rudimentary way to see some of your internal variables or to have a log of how the program run went.

This printf sample can turn off the debugging with a single variable.  It is not too difficult to set this value as a parameter to the program but it is really just too much effort for such simple control.  It is a all or nothing that is not so satisfying.

It is however, much better than not having any ability to log or debug the program in question.

public class Program  {

	boolean debug = true;
	public Program()
	{
	}
	public void performWork()
	{
		int index = 0;
		System.out.println("Interface 'Program' starting");

		for (index = 1; index <= 10; index++)
		{
			int square = index * index;
			if (debug == true)
				System.out.println(index + " x " + index + " = " + square);
			System.out.println("square is " + square);
		}
		System.out.println("Interface 'Program' finished");
	}
	public static void main(String args[])
	{
		Program helper = new Program();
		helper.performWork();
	}
}

“Printf” logfile output

Interface 'Program' starting
1 x 1 = 1
square is 1
2 x 2 = 4
square is 4
3 x 3 = 9
square is 9
4 x 4 = 16
square is 16
5 x 5 = 25
square is 25
6 x 6 = 36
square is 36
7 x 7 = 49
square is 49
8 x 8 = 64
square is 64
9 x 9 = 81
square is 81
10 x 10 = 100
square is 100
Interface 'Program' finished

This output may have been acceptable back in computer class but it really doesn’t measure up in a production environment.  True, we see the output, both the standard and debug output, however, this output could have been from version 1 of our program six months ago or version 3 yesterday.

Fortunately, better logging and debug output has been solved quite elegantly by the Log4j project at Apache.

The really clever thing about their solution is that all of the logging/debugging is controlled via a tiny configuration file.  Write your program to read in the configuration file and then use the log4j output methods.  Changing the configuration file changes the nature of the log output.

The object is “Logger” has a few methods each of which can be used in lieu of printf.

  • debug
  • info
  • warn
  • error
  • fatal

Each of these are actually treated as a different level with each all inclusive of all levels before it.  The real beauty is Log4j allows you to filter which level of output you wish to see. Log4j supports date, displays debug level, class file and line number if you really need it.

This alone is more than enough reason to use log4j to help control logging but there is more.  It is possible to route the output to a file, the console or both.

# Root logger option
log4j.rootLogger=debug, terminal

# Redirect log messages 
log4j.appender.terminal=org.apache.log4j.ConsoleAppender
log4j.appender.terminal.Target=System.out
log4j.appender.terminal.layout=org.apache.log4j.PatternLayout
log4j.appender.terminal.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

The highlighted lines set the output to the screen.  The last two lines allow for some customization how the output looks.   The rootLogger sets what level to filter at.  Simply edit the property file to the level of logging that you wish to see.  The filter is set to “debug” so all logging output (debug,info,warn, error and fatal) will be displayed.

The new way with log4j and property files

The next sample program is virtually no different than the printf version for outputting log details.

In the constructor, in this example, the PropertyConfigurator object is used to load the log4j.properties file from the current directory.  Log4j will be clever enough to do all the setup in the background after reading the property file.

ConfigFileLog4j.java

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

public class ConfigFileLog4j {

	Logger logfile = null;
	
	public ConfigFileLog4j()
	{
		// get a handle to "logger"
		PropertyConfigurator.configure("log4j.properties");
		logfile = Logger.getLogger(ConfigFileLog4j.class);
	}
	public void performWork()
	{
		int index = 0;
		logfile.info("Interface 'ConfigFileLog4j' starting");

		for (index = 1; index <= 10; index++)
		{
			int square = index * index;
			logfile.debug(index + " x " + index + " = " + square);
			logfile.info("square is " + square);
		}
		logfile.info("Interface 'ConfigFileLog4j' finished");
	}
	public static void main(String args[])
	{
		ConfigFileLog4j helper = new ConfigFileLog4j();
		helper.performWork();
	}
}

 

Log4j logfile output

This sample output is done with the filter set to “info” thus giving us the output that we probably want to see from a normal run.

2016-07-10 23:08:38 INFO ConfigFileLog4j:22 - Interface 'ConfigFileLog4j' starting
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 1
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 4
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 9
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 16
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 25
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 36
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 49
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 64
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 81
2016-07-10 23:08:38 INFO ConfigFileLog4j:28 - square is 100
2016-07-10 23:08:38 INFO ConfigFileLog4j:30 - Interface 'ConfigFileLog4j' finished

This is probably the easiest way to use log4j.  Simply include the property file with the program, change the property file as necessary during development.

This is good because if an unruly client or IT department needs a different format or wishes to reduce the logging this can be achieved by simply modifying the configuration file not changing and recompiling the program itself.

It is possible to display the output purely to the console when running.

log4j.rootLogger=debug, terminal

# console setup
log4j.appender.terminal=org.apache.log4j.ConsoleAppender
log4j.appender.terminal.Target=System.out
log4j.appender.terminal.layout=org.apache.log4j.PatternLayout
log4j.appender.terminal.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

However, once the program is fully bug free, you can ignore the console and simply write all output to the log file.

log4j.rootLogger=debug, file

# Redirect log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.file=${LOGDIR}/${LOGFILE}
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.MaxBackupIndex=3 
log4j.appender.file.Append=true 
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

There are actually a couple of nifty things that you can do when writing the output to log files.  The first is that you can decide on the maximum log file size as well as how many old copies of the logs to keep.  Once the logfile reaches this size it automatically moves the current logfile to logfile.1 – if necessary renaming all of the log files to a newer version until all the logs are renamed and then resumes writing the output to the log file.

In the above property file the output is set to Append.  This will simply append future program output to the end of the log file.  This is really handy to easily see the history of a given program at a glance.

In my opinion one of the more interesting things that you can do with log files is you can use values from the java virtual machine, in this case LOGDIR and LOGFILE, to determine some of the functionality.

This may not be necessary in most cases but perhaps for a situation where multiple related program s utilizes a single property file this might come in handy.

It is even possible to have a single log4j property file that is designed to output to both the screen and save to the log file.

log4j.rootLogger=debug, file, terminal

# console setup
log4j.appender.terminal=org.apache.log4j.ConsoleAppender
log4j.appender.terminal.Target=System.out
log4j.appender.terminal.layout=org.apache.log4j.PatternLayout
log4j.appender.terminal.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

# file setup
log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.file=${LOGDIR}/${LOGFILE}
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.MaxBackupIndex=3 
log4j.appender.file.Append=true 
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c:%L - %m%n

 

runProgram.sh

#!/bin/bash

CP=lib/log4j-1.2.17.jar:.
PGM=ConfigFileLog4j

mkdir log

CMD="java -DLOGFILE=custom.log -DLOGDIR=log -cp $CP $PGM"

echo $CMD
$CMD

Unfortunately this shouldn’t really be called the new way of doing things.  Just recently, in 2013, a newer better version of Log4j came out.  This will be the subject of part II of this article.

Note: This example was compiled with java 1.7 and uses log4j-1.2.17.jar

Note: This example was also compiled with java 1.8 and uses log4j-1.2.17.jar

Posted in programming | Tagged , , | Comments Off on better logging than printf – using log4j – part I

she said … he heard an office tale.

I want to give 50 euros a year to Microsoft until I die.

I after taking a few minutes to parse the sentence I believe that it actually sounded more like.

All of my friends are using Microsoft 360 and I use it at work.  It seems pretty good, I would like to use for my personal computer.

I am guessing that this is exactly the kind of thing that Microsoft has been dreaming of.  A nice stable income from people who are tired of getting software installed and keeping it constantly patched on their computer.

I didn’t really need to think much to come up with my personal answer on this topic.  Purchase the software … or at least a software license and install it on the computer.  The upfront costs are a bit more but it amortizes nicely over time.  This is probably more true now than when windows was still fighting with OS/2 for desktop supremacy.

The desktops and laptops today are considerably more powerful now than back in the day, yet for most business tasks the business case for getting a new computer each year would be a pretty difficult sell.  My machine has a quad core with eight threads (thanks hyper-threading), just like the prior few years.

This isn’t to say that the new CPU’s don’t bring a lot to the table but what it brings may be more useful for visualization or energy consumption.

The same is true for some of the software sold today.  Each version has more features than the previous but unless you are doing a lot collaboration you might only see that the menus or ribbons have changed.

Costs

The table actually doesn’t fully encompass all of the options.  Microsoft actually has a number of different plans for consumers and business.  They also have a number of large business and enterprise pricing plans as well.

Sofware / Plan Cost online storage
Google Apps
For work
40 Euro per year 30 GB storage
Google Apps
Unlimited
120 Euro per year 1 TB storage
Office 365
Home
99.99 Euro per year 1 TB storage
Office 365
Personal
69.99 Euro per year 1 TB storage

This may be cheaper than to purchase the software outright – almost.  The good news of having a software service like this is that you don’t need to deal with the hardware (disk storage) getting full or breaking down.  The software should always be patched to the most current level.  Both Microsoft and Google are providing this intangible but very important benefit.

My wife actually doesn’t have any of those worries. She has outsourced them to  me (along with installing windows patches and taking out the garbage).

Purchasing the software outright isn’t necessarily much cheaper, it really depends on your time horizon.  If you really have to use the most cutting edge version of the software you will getting approximately every two years.

Sofware Cost online storage
Office 2013 129.99 Euro  N/A

If you can live with the functionality for perhaps the life of your personal computer then the timeline might be four or five years.  This would have a cost of approximately 25 Euros per year.  If you are like one person I heard of, you would have just upgraded from Office 97 which yields the staggeringly tiny number of eight Euros per year.

The back of the envelope numbers seem to suggest purchasing the software would be the most cost effective way to proceed.  I did consider another metric for pricing.  Her original question was not “how can I subsidize my company by purchasing my own software” but what software should she purchase for her home computer.

Well, she doesn’t write novels and presumably her work reports and presentations would be done at work.  Sending letters through the post is almost unheard of, so that means she is probably looking to do the occasional report or presentation at home.  Perhaps, depending on which statistics you believe, she will also be using this to update her resume.

What this might mean is that she would be working at home on perhaps  perhaps five reports a year and a resume every three years.  It might be even cheaper to use either Google Apps or Office 365 but sign up for a single month when you really needed it.

There is one more solution that beats all the others hands down.

Sofware Cost online storage
Apache
OpenOffice
Free N/A
LibreOffice Free N/A

LibreOffice is a fork from the original OpenOffice that was previously owned by Oracle. The Apache is now the maintainer of the OpenOffice suite.  Oracle decided that the OpenOffice product would be better managed by another organization with a non-commercial focus and so set OpenOffice free.

“Given the breadth of interest in free personal productivity applications and the rapid evolution of personal computing technologies, we believe the OpenOffice.org project would be best managed by an organization focused on serving that broad constituency on a non-commercial basis,” said Oracle Chief Architect Edward Screven in a statement.

Both of these open source office package really provide value other than costing anything.  They are full office suites that can do word processing, spreadsheet and presentations.  They are not only just as powerful as the market leader, well almost, but it is possible to give a copy to your friend or coworker without going to jail.

They are more traditional software packages, that are installed on your personal computer but can be used with other popular solutions such as dropbox, onedrive or google drive if you need access from anywhere.

Conclusion

Get the solution that you are most comfortable with.  Open source office software is more than adequate for a lot of situations, however, don’t overlook simply purchasing Microsoft office.  Buying and using  Microsoft office for 3 or more years gives 100% compatibility without succumbing to the upgrade treadmill.

Once you are ready to move on you might* be able to offer the still working software to someone who might want it.

*Depending on the license that came with the software.

Posted in Soapbox | Tagged | Comments Off on she said … he heard an office tale.

blindsided by timezones

I recently got back from a holiday from another timezone.  It was a yearly pilgrimage to visit my parents in the Midwest.  The food was great, the weather was great, family was great but technology was on par with last millennium.  My children didn’t have the bandwidth to download any new games but they were still able to play minecraft together.

Imagine my surprise when the children’s kindles no longer connected to my network at home.  It didn’t seem to be a wlan problem as other devices could connect to the network but more importantly the Kindle’s could see my neighbors networks.

While checking into this I saw that some patch was installed during my holidays.  Was this patch responsible for the problem?  Was the device dropped?  Too many xray’s at the airport.  Is there a problem with my wlan?

Troubleshooting checklist

  • turn off and on the wlan
  • restart the device
  • drop and recreate the wlan entry

Google was full of similar situations and I was busy scratching my head but it was my wife who had a fresh idea.  Enable a hotspot from her tablet and try to connect.  It worked, the kindle connected to the hotspot and pointed out the difference in the timezone.

The timezone wasn’t the biggest problem but it was wrong as well.  Simply changing the timezone made the difference.  All of a sudden my wlan showed up in the list networks – and worked shortly after that.

I wonder what strange behaviors exist in some of the other muli-million line code bases …

Posted in Soapbox | Tagged | 1 Comment

safe computing – strengthening passwords

A password is simply a method of verifying who you are.  When a good password is selected it is both easy to remember but not easy to guess.  It should contain both upper and lower case letters, numbers and if possible a couple of symbols and should be suitably long.

Yet, even a well chosen password won’t help you if the system you are connecting to is, well, stupidly written.  I suspect that there are a lot of methods to prevent a brute force attack – that is to test every possible character combination in an attempt to guess the correct password.

If no special precautions are taken, how quickly could we force a hypothetical password.  If our password is six characters long and is uppercase letters, lowercase letters and numbers how many combinations can we have?

26 upper case
26 lower case
10 digits

62 * 62 * 62 * 62 * 62 * 62 = 56,800,235,584

If we can try ten thousand passwords a second, it would take 94,667 minutes or approximately sixty six days to crack the password.  This would make it impractical to attempt to sneak into the boss’s office and hack his computer, but if the system doesn’t have any safeguards it is within the realm of possibility, especially if the system you are attempting to connect to is on the Internet.

combinations 56800235584 56800235584
guesses per second 1 10000
seconds 56800235584 5680024
 
min 946670593 94667
hours 15777843 1578
days 657410 66
years 1801 0
centuries 18 0

If we can try ten thousand passwords a second, it would take 94,667 minutes or approximately sixty six days to crack the password.  This would make it impractical to attempt to sneak into the boss’s office and hack his computer, but if the system doesn’t have any safeguards it is within the realm of possibility, especially if the system you are attempting to connect to is on the Internet.

Two months is a long time but perhaps the naughty person gets lucky or uses a more clever method for guessing the passwords this could be shorted considerably.

This could be defeated by adding any one of a few different methods to defeat this.

  • only accept one password per second
  • have a second password
  • lock the account after a limited amount of time
  • temporarily suspend account after a number of incorrect attempts
  • increase the delay between password login with each incorrect attempt

If the first choice were implemented the amount of time to go through the entire list of passwords would increase from sixty six days to 1800 years.  Yet, it is possible that the user would pick a poor password that is easy to guess.

Adding a strong second password, would help to secure the system but we cannot guarantee that the user will select a strong password.  It is actually just as likely that the second password they select is identical to the first.

A better solution is to give the user a strong second password, and to ensure that this password is changed often we should generate it ourselves.  This both easy and possible by using a security token.

tokenA token is a small hard ware device to generate a random six digit password.  This device is registered with the company server and the random password is only valid for two minutes.

This type of security is pretty commonly used by companies to their employees to provide secure access to their networks over insecure networks such as the Internet.  Private companies and their employees are not the only ones to use such devices.  These devices can be used as a part of creating secure vpn connections or to provide solid proof of the identity of the user.

Quite a few companies make these types of arrangements with their customers, especially where either money or identity is at stake.  A few organizations that provide two factor authentication are as follows.

Amazon
Paypal
Facebook
Dropbox
Twitter

Yet, with the magic that is the smart phone it is possible to actually replace this security device with a small application that runs on the phone.  Thus the phone itself can be used to create the six digit security code for the two factor authentication.

Generating the code using either a security token or on your phone is one method for two factor authentication but there is another slight variant.  This second method involves also entering a six digit code but rather than generating the code, it is received via sms to the cell phone.

You cannot guarantee what level of quality the security for all the systems that you connect to but if you do have a chance to increase your personal level of security you should take it.

I hope to write up more information about two factor authentication in the near future.

Posted in security | Comments Off on safe computing – strengthening passwords

When all you have is a hammer …

I was speaking with a friend the other day and he was telling about this crazy thing that was being done in his department.  There was a task that needed to be done usually once a day and it was important that it was not only performed but that it was also documented

Considering the types of follow up questions they were constantly doing the entire solution would have been quite appropriate as a small database application.

My friend is neither an IT person nor is there anyone in his group with those types skills. The task is too small for IT to allocate a project but too much work to actually do it in spare time.  Thus the users were using a spreadsheet to track this information.  Each day they added a new tab, and on each tab was information about the task or tasks that were done.

The whole thing seemed rather foreign to me.  It seems all of my tasks usually end up in the shape of a program at some point.

Just this morning one of my users wanted some test data to be uploaded into the application.  Almost like my friends situation, it was too unimportant to do right and received almost no attention – until today.

I decided to write up a small shell script to automatically create a few pdf files and configuration files to go with them.  All I need to do is to add the internal entity id when running the script.  The script creates a random number and picks some random static data.  The overall affect is quite similar to what production looks like.

%% Subject=Test for entity id PRO7:1019999:IR-LOAN-SHORT:PRO7
%% FaxNumber=john.johnson@bigcompany.com;max.mustermann@bigcompany.com
%% Message=special message goes here
%% Attachments=special.pdf
%% Entity=PRO7

The configuration contains enough information for the processing system to send out files.

The script just loops through the internal id’s provided on the command line.  Special kudos to the ability to have arrays and generate random numbers in a shell script.

#!/usr/bin/ksh 
clear

if [ $# -eq 0 ]
then
  echo add the entity ids to command line
  exit
fi

EMAILTO="john.johnson@bigcompany.com;max.mustermann@bigcompany.com"
MSG="special message goes here"
ATTACH="special.pdf"

INSTRUMENTS[0]="FX-SPOT"
INSTRUMENTS[1]="FIXING"
INSTRUMENTS[2]="FX-FWD"
INSTRUMENTS[3]="IR-LOAN-LONG"
INSTRUMENTS[4]="IR-LOAN-SHORT"
INSTRUMENTS[5]="COMMODITY"
INSTRUMENTS[6]="IR-DEPOSIT-SHORT"
INSTRUMENTS[7]="IR-BOND"

while [ $# -gt 0 ]
do
  TXN=$RANDOM
  IDX=$(($RANDOM % 8))
  INSTRUMENT=${INSTRUMENTS[$IDX]}
  BASENAME=$1-$TXN
  SEND=true

  TEX=${BASENAME}.tex
  PDF=${BASENAME}.pdf
  XSL=form.xsl
  XML=${BASENAME}.xml

  ENTITY=$1
  echo " Test for entity id '$ENTITY'  " > $XML

  echo %% Subject=Test for entity id $ENTITY:10$TXN:$INSTRUMENT:$ENTITY > $TEX
  echo"%% FaxNumber=$EMAILTO" >> $TEX
  echo %% Message=$MSG >> $TEX
  echo %% Attachments=$ATTACH >> $TEX
  echo %% Entity=$ENTITY >> $TEX

  cat $TEX
  fop -xml ${XML} -xsl form.xsl -pdf ${PDF}
  shift
  echo " "
  echo " "
  echo " "
done

The magic is not in the shell script, that is pretty much just the glue, the magic is in the ability to create PDF files.

I must admit that in the past I did not do an extensive study on what different solutions are available for creating PDF files.

Apache™ FOP (Formatting Objects Processor) is a print formatter driven by XSL formatting objects (XSL-FO) and an output independent formatter. It is a Java application that reads a formatting object (FO) tree and renders the resulting pages to a specified output. Output formats currently supported include PDF, PS, PCL, AFP, XML (area tree representation), Print, AWT and PNG, and to a lesser extent, RTF and TXT. The primary output target is PDF.

Somehow I gravitated towards using Apache Fop to create the files. I find this technology so useful because it is easy enough to create a well formatted form that can be generated into many different types of output of which PDF is only one.

You decide what the format of the output should be and create a form to parse that output.  Once all of this has been decided it is easy enough to create a program (if necessary) to then create that format of xml file.

Form is simply some xslt code.  The most important part of the form is the description of what the output dimensions will look like.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fo="http://www.w3.org/1999/XSL/Format" exclude-result-prefixes="fo">
<xsl:template match="test">
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="simpleA4" page-height="29.7cm" page-width="21cm" margin-top="2cm" margin-bottom="2cm" margin-left="2cm" margin-right="2cm">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="simpleA4">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-size="16pt" font-weight="bold" space-after="5mm">Test: <xsl:value-of select="desc"/> </fo:block>

        </fo:flow>
      </fo:page-sequence>
     </fo:root>
</xsl:template>

</xsl:stylesheet>

The form is then merged with the xml data file to create the output.

This particular example is actually very poor as there is almost no real connection between the xslt form and the data file.  The only common element is that the beginning block is called test.

<test> 
<desc>Test for entity id 'ZDF' </desc> 
</test>

Unless other templates are added, the text for any xml tags that are encountered are simply output without any real additional formatting into the output file.

I don’t have time for a full set of examples so I simply refer you to the Apache examples.  I will however be revisiting this topic in the future will more examples and a fuller explanation.

Posted in Command line, programming | Tagged , | Comments Off on When all you have is a hammer …

Punishment for laziness – root password recovery

I had a new idea for adding one more computer to my life.  The task was to actually provide some fun new functionality to my family and I attacked the task.

At the beginning, I needed to log in as root fairly often to get Apache setup and configured as well as some of my own customization’s.  Because of this, all the passwords were at the tip of my fingers.  My customization’s got better and better so eventually I rarely logged into the computer at all, not as root, nor even as a normal user.

One day I actually did need to log in as the root user only to discover that I couldn’t remember the password.  There was no fear, as I normally have all my passwords in a password safe.

Well, I must have been distracted when setting up that computer because I failed to write down any of the information.  This pretty much left me with a few options

  1. the application is fine, just use it and never change it
  2. copy my configuration and scripts and re-setup the computer
  3. find a way to reset the root password

I had to do this once before for a Linux Mint computer that I setup.  I was hoping that these instructions would do the trick.  This time it was a Debian (8.2) system.  The method to do this is really easy.

Attempt #1

  1. change kernal parameters from grub to boot to a shell
  2. change the password

For some reason, when I did this with this machine the prompt would come up and then the machine would hang.  I wanted to do a quick update to ensure that everything was up to date but didn’t have the root password.

Attempt #2

  1. change kernel parameters for group to boot to single user mode
  2. use passwd to change the password

I was experiencing the same difficulties with this option as experienced with the first attempt.  The machine would boot to single user mode and hang.

Attempt #3

  1. boot with a live disk
  2. mount root partition
  3. change shadow file

Despite the supposed difficulty of this option, there really is nothing to it.  The only problems that this computer system was sitting in the corner headless.  This doesn’t really increase the difficulty of the task other than the additional effort of moving the computer and connecting up the accessories.

This computer is actually just a tiny one with no CD/DVD rom drive.  Thus the task was slightly changed to the following.

  1. download a live image
  2. create bootable USB stick
  3. boot computer from USB stick
  4. mount root partition
  5. change shadow file

The description of how to actually reset the root password via the shadow file is really well described in a lot of places, but the site that I used was

http://www.linuxforums.org/forum/linux-tutorials-howtos-reference-material/54418-howto-recover-reset-root-password.html

You only need to change the line for the root user in the shadow file and don’t need to do anything with the password file.  In the tutorial the password is reset to nothing, so you do need to make sure that this server is not reachable by anyone else during this critical time.

I did find one more interesting method that could be used to reset the password.

Runner up

  1. boot a live disk
  2. mount the root partition
  3. chroot to disk
  4. use passwd to change password of root user

This also would have been a pretty simple option but I was a bit concerned that the distribution that was being booted didn’t match the one that was installed.

 

It was a very interesting evening but actually it should be considered more of a punishment for failing to keep better track of a system that I setup.

This should also serve as a object lesson that security.  If someone else has unlimited access to the physical computer it is no longer secure.

Posted in Command line | Tagged , | Comments Off on Punishment for laziness – root password recovery

command line fun – spaces and arguments

I normally get to control most aspects of the program.  The most important yet trivial is the parameters that are being passed to the program.  Because I know what I want it is usually possible to coerce the calling script into giving me what I need.

Unfortunately there are always exceptions.  The most common problem is with dealing with normal users from the Windows world.  There are a lot of characters that they have no compunction about putting into a filename with the most common being the space.

If I am expecting a lot of files (and no spaces) then this extra space or six really can create some havoc. I would normally have a simple loop to iterate through my list.

#!/bin/bash

PARMS=$*

for item in $PARMS
do
  echo $item
  echo "(some processing goes here)"
  echo " "
done

Works great with commands that looks like any of the following

  • filename=receivables.txt
  • receivables.txt
  • -name=receivables.txt

When the space is introduced into the parameter value then the value gets split up with this type of processing.

> ./parser.sh filename=receivables.txt receivables.txt -name=receivables.txt "account receivables.txt"
filename=receivables.txt
(some processing goes here)
 
receivables.txt
(some processing goes here)
 
-name=receivables.txt
(some processing goes here)
 
account
(some processing goes here)
 
receivables.txt
(some processing goes here)

The bash shell actually does know that there are only four parameters that were passed, the problem is with this rather simplistic method of parsing.  Simply accessing the parameters directly will actually return the exact parameter including any spaces or special characters.

#!/bin/bash

filename1=$1
filename2=$2
filename3=$3
filename4=$4
filename11=$11

echo filename1 $filename1
echo filename2 $filename2
echo filename3 $filename3
echo filename4 $filename4
echo filename11 $filename11

It does work yet in a inflexible manner, besides this will work for the parameters up to 9 but not beyond that.  The easiest way would be to take the first parameter from the command line, process the file and then move to the next file.  The bash shell allows us to do that using the shift command.

#!/bin/bash

PARMS=$*

while [ $# -gt 0 ]
do
  filename=$1
  shift
  echo filename is "'$filename'"
  echo "(some processing goes here)"
  echo " "
done

In this way we simply continue taking arguments until there are no arguments left to take.

#!/bin/bash

DEBUG=0

idx=0
president=false

while [ $# -gt 0 ]
do
   item=$1
   if [ $DEBUG -ne 0 ]
   then
      echo ${idx}. $item
   fi

   VARIABLE=`echo $item | nawk -F=  '{print ($1)}'`
   VALUE=`echo $item | nawk -F=  '{print ($2)}'`

   case $VARIABLE in

      -president) president=true;;
      first) firstname=$VALUE;;
      last)  lastname=$VALUE;;
      addr)  address=$VALUE;;
      city)  city=$VALUE;;
      state)  state=$VALUE;;
      zip)  zipcode=$VALUE;;

      *) echo "unknown parm set ($VARIABLE/$VALUE)";;

   esac
   idx=$((idx + 1))
   shift
done

echo User Info
if [ $president == "true" ]
then
  echo President of the United States
fi
echo $firstname $lastname
echo $address
echo $city $state $zipcode

This method of parsing out the parameters supports both parameter=value as well as the more classic parameter preceded with a dash followed by a value.

> ./parser.sh first=bob last=johnson addr="123 main street" -president city=smallville state=IL zip=12321
User Info
President of the United States
bob johnson
123 main street
smallville IL 12321
>

To support the more classic method of parameter passing would require a few small changes, but that is left as an example to the reader.

Posted in Command line | Tagged , | Comments Off on command line fun – spaces and arguments

Big brother is watching (you buy underwear)

Edward Snowden raised the stakes of privacy in June 2013 when he released the scope of the internet and phone surveillance by American intelligence agencies.  We learned quite a bit about what types of data collections were being done.

  1. Phone records gathered
  2. Britain collecting fiber optic data
  3. NSA spying on other world leaders
  4. NSA efforts to crack encryption and undermine Internet security
  5. NSA cracks google and yahoo data center links
  6. NSA collects text messages

All of this is pretty scary stuff but as long as you are as innocent as a newborn baby and have no links to any other people.  No links to other people is hard to pull off as it has already been proven that everyone on earth are separated by six degrees.

Yet as scary as all of that is this is not about the government tracing your every move – it actually much worse than that.  It is about private industry using technology to track their customers.

You can lie about your name when meeting someone in a bar and you can give the wrong telephone number to someone you just met but it is much harder to lie about one of your most fundamental features – your face.

As recently as even a few years ago it would not be affordable for most firms to have facial recognition systems in place but with each year the hardware is both cheaper and more powerful.  The hardware and software are both important pieces to the equation but the missing ingredient is the actual faces.  In some cases the faces are being supplied by the police of people with shoplifting histories which then allows the stores to decide which what action to take against these people.

If you are worried about higher prices at your local store due to shop lifting then this particular intrusion is not so worrying.  Yet, even if you are worried there is really nothing much you can do about it in the US.  There are only two US states, Texas and Illinois, that have laws that deal with privacy concerns and no federal laws.

According to the an article at retailwire.com, 75% of shoppers would not shop at a store that does facial recognition for marketing purposes.  I guess this does resonate with me as I don’t even give out my zip code when asked for it during my check out.

Whether or not we like facial recognition for loss prevention is pretty much a moot point.  If the stores don’t tell the consumers it is in place they won’t be complaining or boycotting stores that use it.  In addition, if facial recognition is good for the bottom line then it will become standard at most stores.

The things that I am worried about is some form of mission creep.  Once the software is in place and doing a great job, it is possible that the thieves will know this to be the case and will go elsewhere.  This leaves a facial recognition system in place looking for a job.

What I foresee is that the cameras that are near the checkout will eventually linked up with the checkout software.  This will allow the store to create more perfect profiles than simply looking at the cookies on your laptop.  The store will have a picture of Mr. Jones, linked to all of the items that he has ever purchased.  Depending on how responsible the establishment is it may even keep track of every method of payments. If Mr. Jones at any point in his “consumer relationship”  filled out a survey or was a member of a rewards club program then the company has his address and perhaps birth date.

This is not so speculative as almost this very thing was being done at Target to profile their customers to create pregnancy scores.  This is an example of how big data can be used to find patterns and then use those patterns to try and sell some merchandise.

If the stores you frequent have this types of personal information, you will be receiving birthday congratulations perhaps with coupons. If your particular interests are not so obscure (extreme ironing, soap carving, collecting sick bags) it is quite possible that you will be receiving personalized advertising sent directly to your home or email.

People are not innately lazy but there are limits to how much they can do in order to prevent being caught up in that web.  One way would be to have a large number of credit cards or use cash.  Neither is particular convenient, the former is not free and the latter means you either go to the ATM often or have piles of cash with you or at home. Besides, using extreme methods of payment might be enough to create anonymity when every transaction is now being tied together by your face.

Just how prevalent is facial recognition software?    Well a couple of google searches will return a number of companies that are in the market with their own solutions.  It is difficult to say exactly what the solutions are that they provide other than they do facial recognition.

FaceFirst (www.facefirst.com)
Safran (safran.com)
Cognitec (www.cognitec.com)
Sightcorp  (http://sightcorp.com)

Of the list of companies that provide solutions the one that might be more interesting than the rest would be the last, Kairos.  According to their site they do emotion analysis.  It is difficult to say if this would threaten the people in the marketing department but as a solution it would provide a method to prevent individual bias when evaluating people during their research.

In addition to the list of private companies with their solution, there are some public companies with their private uses for facial recognition.

You know that facial recognition has finally hit the mainstream when you can even find open source projects that deal with that particular problem.

How Serious is this really?

Well, as there really are very few laws for governing the behavior of companies tracking people by their faces then I guess the industry will be responsible for self regulating their own behavior.  How bad could it really get?

Companies or trade groups seem to have a rather spotty record when it comes to self regulating their own behavior.  This is not so much my personal observations as what you can find in the news.

Apparently there were negotiations on the topic of facial recognition privacy and they didn’t go well. You can hardly expect that organizations whose main goal is to make a good return for their investors to want to limit their future actions. The issue is two mutually exclusive groups, one who would feel uncomfortable to be personally tracked by their clothing shop, electronics store, and church while the other wants to build profiles that they can use to make money.

It seems that the two groups were not very close to an agreement when the meeting broke up.

So we asked a narrower hypothetical: Suppose you’re walking down a public street—not private property—and a company you’ve never heard of would like to use facial recognition to identify you by name. We asked whether there were any trade groups or companies in the room that would agree that in this case, consent was necessary. The answer was unanimous: silence.

I am not going to invest all of my money into facial recognition software companies, but perhaps I will invest it in facial camouflage companies or other tools to allow people the ability to regain some of their anonymity.

references

http://www.slate.com/blogs/moneybox/2015/11/24/stores_are_using_face_recognition_to_catch_shoplifters.html

http://szeliski.org/Book/

http://www.slate.com/articles/technology/future_tense/2015/06/facial_recognition_privacy_talks_why_i_walked_out.html

Posted in Soapbox | Tagged , , | Comments Off on Big brother is watching (you buy underwear)

IBM Websphere MQ manipulations – part III

The curse of technology

The cool thing about technology demos is how everything just works, well unless you are demoing it to the boss.  The equipment is usually quite new, the scope is simple enough and there are never any complications.  The real world has a tendency to be more complicated.

Once a system goes live, the environment tends to be more static.  The hardware which was so good on day one doesn’t get any faster as the system utilization gets higher as the system is used by more users or departments.  To improve performance there may be some minor upgrades of larger disks or more memory, but even these tend offset by other software upgrades.

Depending on the size of the organization, this will continue like this until performance is unacceptable.  Then either the computer will be replaced or the entire system will be upgraded with new hardware and software.

Yet in a complicated environment it can be difficult to upgrade everything at once.  This might be because of lack of time or other resources to do the job but it could also be be due to incompatibilities between systems.

Vendors validate that their software works with certain versions of middleware, databases, operating systems just to name a few.  It simply not feasible for them to ensure that every version of their software can work with every version of every other software package including those not yet released.

Which brings me to the problem that I encountered.  The system we were dealing with was pretty old and was only validated to work with MQ 6, yet most of the rest of the organization was using MQ 7.  This wasn’t a problem at the beginning when the only goal was sending simple messages from place to place.

When accounting wanted us to send some additional meta data along with our messages was when our problems began.  The real problem was not because our system couldn’t support MQ 7 but because we were limited to Java 6 and the new MQ libraries were dependent on Java 7.  This meant that we couldn’t use the classes IBM wrote to help out.

Old School

Back in the olden days when editors didn’t have syntax coloring and object oriented programming was an idea new developers simply wrote out streams of bytes, manipulated memory or cast void pointers to get around type checking. It gets the job done but is less understandable by those who follow.

To do this task we were stuck between a rock and a hard place, most of the organization had upgraded to MQ version 7.5 but our department was stuck with an application that could only use version 6 of Java which could not use the 7.5 libraries (which were for java 7).

The solution we had to implement was to write out the data in the same structure as IBM would have.  This would allow us to write out the data into a MQ version 6 using its standard libraries and read it out and the other end with version 7 libraries.

The good news is that we don’t really need to work very hard to provide this solution.

I am not going to describe the format of the header as the source code actually does a fairly good job of that.  I have commented the code showing which bytes it is actually outputting.

MQ Version 6

Putting a message with a RFH2 header

import java.io.IOException;

import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

public class OldSchool {

    String mqHostName;
    String mqQueueManagerName;
    String mqQueueChannel;
    String mqQueueName;
    int mqQueuePort;

    String filenametoput;
    String inputpath;

    String userdefdata = "pink";

    private final int encoding = MQC.MQENC_NATIVE;
    private final int codedCharSetId = 0xfffffffe; // MQC.MQCCSI_DEFAULT;
    private final static String RFH2_FORMAT = "MQHRF2  ";
    private final int STRUC_LENGTH = 36;

    private MQQueueManager mqQueueManager; // for QMGR object
    private MQQueue queue; // for Queue object

    public OldSchool() {
    }
    private void displayException(MQException mex, String action)
    {
        System.out.println("Error while " + action);
        System.out.println("QMGR Name : " + mqQueueManagerName);
        System.out.println("Queue Name : " + mqQueueName);
        System.out.println("CC   : " + mex.completionCode);
        System.out.println("RC   : " + mex.reasonCode);
    }

	public void init(String host, String managername, String channel, String queuename, int queueport)
	{
		mqHostName 		= host;
		mqQueueManagerName 	= managername;
		mqQueueChannel  	= channel;
		mqQueueName    		= queuename;
		mqQueuePort     	= queueport;

		// validity checking left off.
	}

    public void connect()  
    { 
        try {
            MQEnvironment.hostname = mqHostName;
            MQEnvironment.channel = mqQueueChannel;
            MQEnvironment.port = mqQueuePort;

            mqQueueManager = new MQQueueManager(mqQueueManagerName);
        } 
        catch (MQException mqExp) 
        {
            displayException(mqExp,"doing queue manager connect");
            System.exit(1);
        }
    }
    public void disconnect()  
    { 
        try {
            mqQueueManager.disconnect();
        } 
        catch (MQException mqExp) 
        {
            displayException(mqExp,"doing queue manager disconnect");
            System.exit(1);
        }
    }
    public void open()
    {
        int openOption = MQC.MQOO_OUTPUT;

        try {
            queue = mqQueueManager.accessQueue(mqQueueName, openOption, null, null, null);
        } 
        catch (MQException e)         
        {
            displayException(e,"doing queue open");
            System.exit(1);
        }
    }
    public void close()  
    {
        try {
            queue.close();
        } 
        catch (MQException mqExp) 
        {
            displayException(mqExp,"closing queue");
            System.exit(1);
        }
    }

    private void putMessageWithHeader(String messageTextToSend)  
    {
        try {
            // create message
            MQMessage mqm = new MQMessage();
            mqm.format = MQC.MQFMT_STRING;
                        
            // setup our rfh2 header, one byte a at a time

            // our properties will be sent out in xml format 
            // oldschool
            String areas = userdefdata;

            while (areas.length() % 4 != 0)
            {
                areas = areas + " ";
            }
            int  areasLen = areas.getBytes("UTF-8").length;
            System.out.println("folder areas lengths = " + (areasLen));

            int structuralLen = areasLen + STRUC_LENGTH + 4;
            System.out.println("complete length = " + structuralLen);

            // prepare a header
            mqm.seek(0);
            mqm.format = RFH2_FORMAT;                
            mqm.writeString("RFH ");                // 52 46 48 20                - header name    
            mqm.writeInt(2);                        // 00 00 00 02                - version
            mqm.writeInt(structuralLen);            // 00 00 00 54                - length
            mqm.writeInt(encoding);                 // 00 00 01 11                - encoding
            mqm.writeInt(codedCharSetId);           // FF FF FF FE                - codedcharsetid
            mqm.writeString("        ");            // 20 20 20 20 20 20 20 20    - format
            mqm.writeInt(0);                        // 00 00 00 00                - flags

            // CCSID 1208 -- UTF-8
            mqm.writeInt(1208);                     // 00 00 04 B8                - nameValueCodedCharSetId

            // actually write out 
            // our folder stuff.    
            mqm.writeInt(areasLen);                 // 00 00 00 2C                - how big is properties area (usr,jms,...)

            // properties section here
            mqm.write(areas.getBytes("UTF-8"));     
                                                    // 3C 75 73 72 3E 3C 63 6F   o
                                                    // 6C 64 73 63 68 6F 6F 6C   ldschool
                                                    // 3C 2F 63 6F 64 65 62 61   ...I.ta
                                                    // 74 20 49 20 74 61 77 20   t.I.taw.
                                                    // 61 20 70 75 64 64 79 20   a.puddy.
                                                    // 74 61 74                  tat             

            // now process our actual message

            // the byte array could be contents of a file, but we 
            // will keep this simple.
            byte[] bytearray;
            bytearray = messageTextToSend.getBytes();
            mqm.write(bytearray);                  

            // then finish the job.
            // send it out.
            //dumpMessage(mqm);
            queue.put(mqm);

            System.out.println("Message sent");
        } 
        catch (MQException mqExp) 
        {
            displayException(mqExp,"sending message");
            System.exit(1);        
        } 
        catch (IOException e) 
        {
            System.out.println("sending message, write byte array error");
            System.exit(1);        
        }
    }

    public void putHeaderMessage(String args[])
    {
    	init(args[0],args[1],args[2],args[3],Integer.parseInt(args[4]));
		connect();
        open();
        putMessageWithHeader("I tat I taw a puddy tat");
        close();
        disconnect();
    }

    public static void main(String[] args) 
    {
        OldSchool myputter;
        myputter = new OldSchool();
        myputter.putHeaderMessage(args);
    }
}

Dumping message

Sure, I could have looked around on the Internet to find a solution but as long as I can produce a message using the new libraries we can dump it to ensure we can create the same structure by hand with the old libraries.

	dump message
				  
	 1. 52 46 48 20 00 00 00 02   RFH.....
	 2. 00 00 00 54 00 00 01 11   ...T....
	 3. FF FF FF FE 20 20 20 20   ........
	 4. 20 20 20 20 00 00 00 00   ........
	 5. 00 00 04 B8 00 00 00 2C   .......,
	 6. 3C 75 73 72 3E 3C 63 6F   o
	 8. 6C 64 73 63 68 6F 6F 6C   ldschool
	 9. 3C 2F 63 6F 64 65 62 61   ...I.ta
	12. 74 20 49 20 74 61 77 20   t.I.taw.
	13. 61 20 70 75 64 64 79 20   a.puddy.
	14. 74 61 74                  tat 

It is possible that the entire solution could have been done easier.  It would have been much easier if we had access to the standard MQ tools but that is a story for another time.

The key piece of code for this task was to dump out the two different messages before putting them into the queue.  This is the code I used.

public void dumpMessage(MQMessage msg)
{
	int mLen;
	System.out.println("dump message");

	try {
		msg.seek(0);
		mLen = msg.getTotalMessageLength();
		byte binMessage[] = new byte[mLen];
		msg.readFully(binMessage);

		StringBuilder sb = new StringBuilder();
		StringBuilder sbascii = new StringBuilder();
		int lineno = 0;

		int idx = 0;
		for (idx = 0; idx < mLen; idx++)
		{
			if (idx % 8 == 0 )
			{
				sb.append("  " + sbascii.toString());
				System.out.println(sb.toString());
				sb = new StringBuilder();
				sbascii = new StringBuilder();

				lineno++;
				if (lineno < 10) { sb.append(" " + lineno + ". "); } else { sb.append(lineno + ". "); } } sb.append(String.format("%02X ", binMessage[idx])); if (binMessage[idx] > 32 && binMessage[idx] < 127)
				sbascii.append(String.format("%c", binMessage[idx]));
			else
				sbascii.append(".");
		}

		sb.append("  " + sbascii.toString() + " \n");

		System.out.println(sb.toString());            

	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}

Plenty -o- reference materials

https://www-01.ibm.com/support/knowledgecenter/SSFKSJ_7.1.0/com.ibm.mq.javadoc.doc/WMQJavaClasses/com/ibm/mq/MQMessage.html

http://www.ibm.com/developerworks/websphere/library/techarticles/1001_xiao/1001_xiao.html

Posted in programming, Setup From Scratch | Tagged , | Comments Off on IBM Websphere MQ manipulations – part III