package org.bouncycastle.i18n;

import org.bouncycastle.i18n.filter.Filter;
import org.bouncycastle.i18n.filter.TrustedInput;
import org.bouncycastle.i18n.filter.UntrustedInput;
import org.bouncycastle.i18n.filter.UntrustedUrlInput;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.Format;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.TimeZone;

public class LocalizedMessage 
{

    protected final String id;
    protected final String resource;
    
    // ISO-8859-1 is the default encoding
    public static final String DEFAULT_ENCODING = "ISO-8859-1";
    protected String encoding = DEFAULT_ENCODING;
    
    protected FilteredArguments arguments;
    protected FilteredArguments extraArgs = null;
    
    protected Filter filter = null;
    
    protected ClassLoader loader = null;
    
    
Constructs a new LocalizedMessage using resource as the base name for the RessourceBundle and id as the message bundle id the resource file.
Params:
  • resource – base name of the resource file
  • id – the id of the corresponding bundle in the resource file
Throws:
/** * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the * RessourceBundle and <code>id</code> as the message bundle id the resource file. * @param resource base name of the resource file * @param id the id of the corresponding bundle in the resource file * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code> */
public LocalizedMessage(String resource,String id) throws NullPointerException { if (resource == null || id == null) { throw new NullPointerException(); } this.id = id; this.resource = resource; arguments = new FilteredArguments(); }
Constructs a new LocalizedMessage using resource as the base name for the RessourceBundle and id as the message bundle id the resource file.
Params:
  • resource – base name of the resource file
  • id – the id of the corresponding bundle in the resource file
  • encoding – the encoding of the resource file
Throws:
/** * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the * RessourceBundle and <code>id</code> as the message bundle id the resource file. * @param resource base name of the resource file * @param id the id of the corresponding bundle in the resource file * @param encoding the encoding of the resource file * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code> * @throws UnsupportedEncodingException if the encoding is not supported */
public LocalizedMessage(String resource,String id, String encoding) throws NullPointerException, UnsupportedEncodingException { if (resource == null || id == null) { throw new NullPointerException(); } this.id = id; this.resource = resource; arguments = new FilteredArguments(); if (!Charset.isSupported(encoding)) { throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported."); } this.encoding = encoding; }
Constructs a new LocalizedMessage using resource as the base name for the RessourceBundle and id as the message bundle id the resource file.
Params:
  • resource – base name of the resource file
  • id – the id of the corresponding bundle in the resource file
  • arguments – an array containing the arguments for the message
Throws:
/** * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the * RessourceBundle and <code>id</code> as the message bundle id the resource file. * @param resource base name of the resource file * @param id the id of the corresponding bundle in the resource file * @param arguments an array containing the arguments for the message * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code> */
public LocalizedMessage(String resource, String id, Object[] arguments) throws NullPointerException { if (resource == null || id == null || arguments == null) { throw new NullPointerException(); } this.id = id; this.resource = resource; this.arguments = new FilteredArguments(arguments); }
Constructs a new LocalizedMessage using resource as the base name for the RessourceBundle and id as the message bundle id the resource file.
Params:
  • resource – base name of the resource file
  • id – the id of the corresponding bundle in the resource file
  • encoding – the encoding of the resource file
  • arguments – an array containing the arguments for the message
Throws:
/** * Constructs a new LocalizedMessage using <code>resource</code> as the base name for the * RessourceBundle and <code>id</code> as the message bundle id the resource file. * @param resource base name of the resource file * @param id the id of the corresponding bundle in the resource file * @param encoding the encoding of the resource file * @param arguments an array containing the arguments for the message * @throws NullPointerException if <code>resource</code> or <code>id</code> is <code>null</code> * @throws UnsupportedEncodingException if the encoding is not supported */
public LocalizedMessage(String resource, String id, String encoding, Object[] arguments) throws NullPointerException, UnsupportedEncodingException { if (resource == null || id == null || arguments == null) { throw new NullPointerException(); } this.id = id; this.resource = resource; this.arguments = new FilteredArguments(arguments); if (!Charset.isSupported(encoding)) { throw new UnsupportedEncodingException("The encoding \"" + encoding + "\" is not supported."); } this.encoding = encoding; }
Reads the entry id + "." + key from the resource file and returns a formated message for the given Locale and TimeZone.
Params:
  • key – second part of the entry id
  • loc – the used Locale
  • timezone – the used TimeZone
Throws:
Returns:a Strng containing the localized message
/** * Reads the entry <code>id + "." + key</code> from the resource file and returns a * formated message for the given Locale and TimeZone. * @param key second part of the entry id * @param loc the used {@link Locale} * @param timezone the used {@link TimeZone} * @return a Strng containing the localized message * @throws MissingEntryException if the resource file is not available or the entry does not exist. */
public String getEntry(String key,Locale loc, TimeZone timezone) throws MissingEntryException { String entry = id; if (key != null) { entry += "." + key; } try { ResourceBundle bundle; if (loader == null) { bundle = ResourceBundle.getBundle(resource,loc); } else { bundle = ResourceBundle.getBundle(resource, loc, loader); } String result = bundle.getString(entry); if (!encoding.equals(DEFAULT_ENCODING)) { result = new String(result.getBytes(DEFAULT_ENCODING), encoding); } if (!arguments.isEmpty()) { result = formatWithTimeZone(result,arguments.getFilteredArgs(loc),loc,timezone); } result = addExtraArgs(result, loc); return result; } catch (MissingResourceException mre) { throw new MissingEntryException("Can't find entry " + entry + " in resource file " + resource + ".", resource, entry, loc, loader != null ? loader : this.getClassLoader()); } catch (UnsupportedEncodingException use) { // should never occur - cause we already test this in the constructor throw new RuntimeException(use); } } protected String formatWithTimeZone( String template, Object[] arguments, Locale locale, TimeZone timezone) { MessageFormat mf = new MessageFormat(" "); mf.setLocale(locale); mf.applyPattern(template); if (!timezone.equals(TimeZone.getDefault())) { Format[] formats = mf.getFormats(); for (int i = 0; i < formats.length; i++) { if (formats[i] instanceof DateFormat) { DateFormat temp = (DateFormat) formats[i]; temp.setTimeZone(timezone); mf.setFormat(i,temp); } } } return mf.format(arguments); } protected String addExtraArgs(String msg, Locale locale) { if (extraArgs != null) { StringBuffer sb = new StringBuffer(msg); Object[] filteredArgs = extraArgs.getFilteredArgs(locale); for (int i = 0; i < filteredArgs.length; i++) { sb.append(filteredArgs[i]); } msg = sb.toString(); } return msg; }
Sets the Filter that is used to filter the arguments of this message
Params:
  • filter – the Filter to use. null to disable filtering.
/** * Sets the {@link Filter} that is used to filter the arguments of this message * @param filter the {@link Filter} to use. <code>null</code> to disable filtering. */
public void setFilter(Filter filter) { arguments.setFilter(filter); if (extraArgs != null) { extraArgs.setFilter(filter); } this.filter = filter; }
Returns the current filter.
Returns:the current filter
/** * Returns the current filter. * @return the current filter */
public Filter getFilter() { return filter; }
Set the ClassLoader which loads the resource files. If it is set to null then the default ClassLoader is used.
Params:
  • loader – the ClassLoader which loads the resource files
/** * Set the {@link ClassLoader} which loads the resource files. If it is set to <code>null</code> * then the default {@link ClassLoader} is used. * @param loader the {@link ClassLoader} which loads the resource files */
public void setClassLoader(ClassLoader loader) { this.loader = loader; }
Returns the ClassLoader which loads the resource files or null if the default ClassLoader is used.
Returns:the ClassLoader which loads the resource files
/** * Returns the {@link ClassLoader} which loads the resource files or <code>null</code> * if the default ClassLoader is used. * @return the {@link ClassLoader} which loads the resource files */
public ClassLoader getClassLoader() { return loader; }
Returns the id of the message in the resource bundle.
Returns:the id of the message
/** * Returns the id of the message in the resource bundle. * @return the id of the message */
public String getId() { return id; }
Returns the name of the resource bundle for this message
Returns:name of the resource file
/** * Returns the name of the resource bundle for this message * @return name of the resource file */
public String getResource() { return resource; }
Returns an Object[] containing the message arguments.
Returns:the message arguments
/** * Returns an <code>Object[]</code> containing the message arguments. * @return the message arguments */
public Object[] getArguments() { return arguments.getArguments(); }
Params:
  • extraArg –
/** * * @param extraArg */
public void setExtraArgument(Object extraArg) { setExtraArguments(new Object[] {extraArg}); }
Params:
  • extraArgs –
/** * * @param extraArgs */
public void setExtraArguments(Object[] extraArgs) { if (extraArgs != null) { this.extraArgs = new FilteredArguments(extraArgs); this.extraArgs.setFilter(filter); } else { this.extraArgs = null; } }
Returns:
/** * * @return */
public Object[] getExtraArgs() { return (extraArgs == null) ? null : extraArgs.getArguments(); } protected class FilteredArguments { protected static final int NO_FILTER = 0; protected static final int FILTER = 1; protected static final int FILTER_URL = 2; protected Filter filter = null; protected boolean[] isLocaleSpecific; protected int[] argFilterType; protected Object[] arguments; protected Object[] unpackedArgs; protected Object[] filteredArgs; FilteredArguments() { this(new Object[0]); } FilteredArguments(Object[] args) { this.arguments = args; this.unpackedArgs = new Object[args.length]; this.filteredArgs = new Object[args.length]; this.isLocaleSpecific = new boolean[args.length]; this.argFilterType = new int[args.length]; for (int i = 0; i < args.length; i++) { if (args[i] instanceof TrustedInput) { this.unpackedArgs[i] = ((TrustedInput) args[i]).getInput(); argFilterType[i] = NO_FILTER; } else if (args[i] instanceof UntrustedInput) { this.unpackedArgs[i] = ((UntrustedInput) args[i]).getInput(); if (args[i] instanceof UntrustedUrlInput) { argFilterType[i] = FILTER_URL; } else { argFilterType[i] = FILTER; } } else { this.unpackedArgs[i] = args[i]; argFilterType[i] = FILTER; } // locale specific this.isLocaleSpecific[i] = (this.unpackedArgs[i] instanceof LocaleString); } } public boolean isEmpty() { return unpackedArgs.length == 0; } public Object[] getArguments() { return arguments; } public Object[] getFilteredArgs(Locale locale) { Object[] result = new Object[unpackedArgs.length]; for (int i = 0; i < unpackedArgs.length; i++) { Object arg; if (filteredArgs[i] != null) { arg = filteredArgs[i]; } else { arg = unpackedArgs[i]; if (isLocaleSpecific[i]) { // get locale arg = ((LocaleString) arg).getLocaleString(locale); arg = filter(argFilterType[i], arg); } else { arg = filter(argFilterType[i], arg); filteredArgs[i] = arg; } } result[i] = arg; } return result; } private Object filter(int type, Object obj) { if (filter != null) { Object o = (null == obj) ? "null" : obj; switch (type) { case NO_FILTER: return o; case FILTER: return filter.doFilter(o.toString()); case FILTER_URL: return filter.doFilterUrl(o.toString()); default: return null; } } else { return obj; } } public Filter getFilter() { return filter; } public void setFilter(Filter filter) { if (filter != this.filter) { for (int i = 0; i < unpackedArgs.length; i++) { filteredArgs[i] = null; } } this.filter = filter; } } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("Resource: \"").append(resource); sb.append("\" Id: \"").append(id).append("\""); sb.append(" Arguments: ").append(arguments.getArguments().length).append(" normal"); if (extraArgs != null && extraArgs.getArguments().length > 0) { sb.append(", ").append(extraArgs.getArguments().length).append(" extra"); } sb.append(" Encoding: ").append(encoding); sb.append(" ClassLoader: ").append(loader); return sb.toString(); } }