Monday, August 23, 2010

Internationalization and Localization

Internationalization (i18n) is the concept of architecting a software to make it locale sensitive. During this process, the software is broken into localizable modules and these modules are then used in the code. Translating the localizable module for a specific locale is called localization (l10n).

More specifically, during internationalization, the software is decomposed into code and resources and then during localization, for each locale, a version of the resource is created. The user chooses the locale in which he is using the software and the software automatically uses the resources specific for the locale.

A locale represents a region or country and is typically represented by (1) language (2) country (3) further variations. For example, "en" represents english and "en_US" represents US english. Language and country specifications are standardized by ISO and are specified at the following URLs - http://www.ics.uci.edu/pub/ietf/http/related/iso639.tx and http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html. Variations on the other hand are quite proprietary to the computing environment.

Depending on the type of the software, user can set the locale on the OS, browser or on the software itself. For thick applications like Microsoft Word etc, the locale information is read from the operating system. For web based application, typically, the locale information is read from the user's browser setting using ACCEPT-LANGUAGE HTTP header. Other applications (thick or web based) may give locale setting as probably preference settings on the application for the user.

In the Java world, locale is abstracted using the class java.util.Locale and a resource (actually collection of resource) using java.util.ResourceBundle. Resource itself is accessed as a name-value pair from the ResourceBundle.

Resource bundles are organized in families in a tree structure with the resource bundle with the base name forming the root.

For example consider a resource bundle family MyResource. Consider that it has bundles for english, US english and UK english, french, French french and Canadian french. So, the names of the resource bundles would be MyResource, MyResource_en, MyResource_en_US, MyResource_en_US, MyResource_fr, MyResource_fr_FR, MyResource_fr_CA.

This forms a hierarchy of bundles as below -
MyResource
-- MyResource_en
-- -- MyResource_en_US
-- -- MyResource_en_UK
-- MyResource_fr
-- -- MyResource_fr_FR
-- -- MyResource_fr_CA

A resource bundle family also has a default locale setting. For example "en" could be the default locale.

When a resource is looked up in a bundle family, if the locale is specified, then the bundle matching the exact locale in the hierarchy is looked up. If an exact bundle corresponding to the locale is not found, then the nearest bundle for the locale is used. If the locale is not specified, then, the bundle corresponding to the default locale is looked up.

For example, if we look up a resource by specifying as below

String baseName = "MyResources";
Locale locale = new Locale("en", "US");
String resourceName = "Name";
ResourceBundle bundle = ResourceBundle.getBundle(baseName, locale);
String resource = bundle.getString(resourceName);

If the input locale is null, the default locale which is en is chosen. In this case, the resource is looked up in MyResource_en and then MyResource.

If the input locale is fr, then the resource is looked up in MyResource_fr and if not found, in MyResource.

If the input locale is en_US (as in the snippet above), then the resource is looked up in MyResource_en_US, if not found, then in MyResource_en and if not found again, in MyResource.

When looking for the bundles with the above names, it searches for classes with the above names and if such classes exist in the classpath, it is used. Otherwise, it looks for property files by appending ".properties" to the names and loads them up as resources.

Coming to JEE world, JSF specifications have the faces-config/application/message-bundle and faces-config/application/resource-bundle tags which can be used in the faces-config.xml configuration for specifying the known resource and message bundles.

faces-config/application/locale-config/default-locale can be used to specify the default locale and faces-config/application/locale-config/supported-locale to specify the supported locales.

Typically, following is done to configure -
  1. Resource bundle family property files are created
  2. Using faces-config/application/resource-bundle, the bundle family is declared specifying the base name and a variable name which can then be used later to refer the bundle using Expression Language statements in JSF/JSPX files
  3. Specify the faces-config/application/locale-config/default-locale and set of faces-config/application/locale-config/supported-locale for all the supported locales in the family
  4. In JSF/JSPX, the bundle is directly used using expression language and the resource referenced using the subscript operator
For example,

Create the following files
org.myapp.MyResources
org.myapp.MyResources_en_US

Enter the resource Colour=Colour in org.myapp.MyResources and then translate to US english in org.myapp.MyResources_en_US as Colour=Color

Edit faces.config.xml and add the following XML tags -

[application]
-- [faces-config]
---- [application]
------ [resource-bundle]
-------- [base-name] org.myapp.MyResources [/base-name]
-------- [var] bundle [/var]
------ [/resource-bundle]
---- [locale-config]
------ [default-locale]en[/default-locale]
------ [supported-locale]en_US[/supported-locale]
------ [supported-locale]it[/supported-locale]
---- [/locale-config]
-- [/application]
[/faces-config]

Then in the JSF/JSPX, it can be used as below

[af:inputText label="#{bundle.Colour}" id="it1"/]

Please note that JSF 1.2 onwards, loadBundle tag is not necessary.

JSF also has internal messages which are used by JSF components. For example, messages which are shown on built in validators etc. If it is desired to override these messages, then the message-bundle tag can be used.

At runtime, depending on the user's browser settings, HTTP message will have the ACCEPT-LANGUAGES header, which the JSF runtime will use to set the locale appropriately, thereby loading the correct resource bundles.

Thursday, August 19, 2010

Security Auditing in WebLogic

Weblogic provides an extensible mechanism to audit the activities of weblogic security framework. Weblogic security framework is the framework which takes care of all security related features in a weblogic server including authentication and authorization. Auditing is turned off by default.

The security framework comes out of the box with a DefaultAuditProvider which can be installed and configured into the security framework. When installed and configured in, it starts logging audit information into a file named DefaultAuditRecorder.log in the server log directory. If the default audit provider is not sufficient, users can write custom audit providers and have it installed and perform custom activities such as storing in database etc. The security framework is designed in a pluggable fashion and there can be multiple audit providers if desired.

All the components of the security framework such as authentication providers, authorization providers etc. emit audit events. If an audit provider is installed, then it receives these audit events and it can do whatever it wants with it. Obviously, the DefaultAuditProvider simply logs these events.

A generic audit event has the following information – (1) event type (2) severity level (information, warning, error, success and failure). The severity levels also have ranks associated with them, with “information” having the least rank and “failure” the maximum and (3) optional “context info” about the event (things like ejb method name and parameters in an authorization audit event).

The DefaultAuditProvider has configuration to choose the severity and context information to be filtered or propagated. This configuration is of course specific to the DefaultAuditProvider. A custom audit provider can have any other configuration as desired. Once the audit provider is installed, its settings can be changed at runtime without having to bounce WLS instance. All the settings and configurations are done through WLS console.

The security framework components also add extra data to the event by inheriting from the generic audit event. For example, events generated by the authentication provider have sub type which specifies the action being performed – such as authentication, identity assertion, user being locked etc. An authorization provider adds information regarding the resource being accessed and the subject accessing the resource. The interfaces for the sub events are well defined and a custom auditor can be more intelligent when dealing with the events. The DefaultAuditProvider does not bother much and just logs it using the “toString” semantics.