1 /*
   2  * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * Licensed Materials - Property of IBM
  27  * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997,1998
  28  * RMI-IIOP v1.0
  29  *
  30  *  Defect History
  31  *
  32  *  #26964 LKR 11/25/96 \u0020 at end-of-message not handled properly by Java.
  33  *  #31840 LKR 06/05/97 Replace \n in templates with Java's line separator.
  34  *
  35  */
  36 
  37 package com.sun.tools.corba.se.idl.som.cff;
  38 
  39 import java.io.IOException;
  40 import java.util.Enumeration;
  41 import java.util.Properties;
  42 import java.lang.String;
  43 import java.lang.System;
  44 
  45 /**
  46  * This class provides messaging services for accessing, and merging
  47  * parameters into, translatable message text.  The text is presumed
  48  * to reside in a .properties file.  A "cff.properties" file that
  49  * contains all of the message text needed for the CFF framework itself
  50  * is loaded during class initialization.  All of the messages in the
  51  * cff.properties file that are needed by the CFF framework contain keys
  52  * that begin with the string "cff.".
  53  * <p>
  54  * The static method Messages.msgLoad may be used to merge additional
  55  * message text .properties files needed by other frameworks or user
  56  * programs.
  57  *
  58  * @see com.sun.tools.corba.se.idl.som.cff.Messages#msgLoad
  59  *
  60  * @author      Larry K. Raper
  61  */
  62 
  63 public abstract class Messages {
  64 
  65     /* Class variables */
  66 
  67 
  68     /* Metasymbol for leading or trailing blank */
  69     private static final String LTB = "%B";
  70     /* Metasymbol for line separator */
  71     private static final char NL  = '\n';
  72 
  73     private static final String lineSeparator =
  74         System.getProperty ("line.separator");
  75 
  76     private static final Properties m = new Properties ();
  77     private static boolean loadNeeded = true;
  78 
  79     /* Class methods for message loading and formatting */
  80 
  81     private static final synchronized void loadDefaultProperties () {
  82 
  83         if (!loadNeeded)
  84             return;
  85         try {
  86             m.load (FileLocator.locateLocaleSpecificFileInClassPath (
  87                 "com/sun/tools/corba/se/idl/som/cff/cff.properties"));
  88         } catch (IOException ioe) { }
  89         fixMessages (m);  /* #26964 Replace any metasymbols */
  90         loadNeeded = false;
  91 
  92     }
  93 
  94     /**
  95      * This method was introduced to fix defect #26964.  For Java 1.0.2
  96      * on Win NT, the escape sequence \u0020 was not being handled
  97      * correctly by the Java Properties class when it was the final
  98      * character of a line.  Instead the trailing blank was dropped
  99      * and the next line was swallowed as a continuation.  To work
 100      * around the problem, we introduced our own metasymbol to represent
 101      * a trailing blank.  Hence:
 102      *
 103      * Performs substitution for any metasymbols in the message
 104      * templates.  So far only %B is needed.  This was introduced
 105      * to make it more convenient for .properties files to
 106      * contain message templates with leading or trailing blanks
 107      * (although %B may actually occur anywhere in a template).
 108      * Subsequently, checking for '\n' has also been added.  Now,
 109      * wherever '\n' occurs in a message template, it is replaced
 110      * with the value of System.getProperty ("line.separator").
 111      */
 112     private static final void fixMessages (Properties p) {
 113 
 114         Enumeration keys = p.keys ();
 115         Enumeration elems = p.elements ();
 116         while (keys.hasMoreElements ()) {
 117             String key = (String) keys.nextElement ();
 118             String elem = (String) elems.nextElement ();
 119             int i = elem.indexOf (LTB);
 120             boolean changed = false;
 121             while (i != -1) {
 122                 if (i == 0)
 123                     elem = " " + elem.substring (2);
 124                 else
 125                     elem = elem.substring (0, i) + " " + elem.substring (i+2);
 126                 changed = true;
 127                 i = elem.indexOf (LTB);
 128             }
 129             int lsIncr = lineSeparator.length () - 1;
 130             for (i=0; i<elem.length (); i++) {
 131                 if (elem.charAt (i) == NL) {
 132                     elem = elem.substring (0, i) +
 133                         lineSeparator + elem.substring (i+1);
 134                     i += lsIncr;
 135                     changed = true;
 136                 }
 137             }
 138             if (changed)
 139                 p.put (key, elem);
 140         }
 141 
 142     }
 143 
 144     /**
 145      * Loads additional message keys and text found in the passed
 146      * properties file.  The specified properties file is assumed to
 147      * reside in the CLASSPATH. An IOException is thrown if the loading fails.
 148      */
 149     public static final synchronized void msgLoad (String propertyFileName)
 150         throws IOException {
 151 
 152         m.load (FileLocator.locateLocaleSpecificFileInClassPath (
 153             propertyFileName));
 154         fixMessages (m);   /* #26964 Replace any metasymbols */
 155         loadNeeded = false;
 156 
 157     }
 158 
 159     /**
 160      * Returns the message text corresponding to the passed msgkey
 161      * string.  If the msgkey cannot be found, its value is returned
 162      * as the output message text.
 163      */
 164     public static final String msg (String msgkey) {
 165 
 166         if (loadNeeded)
 167             loadDefaultProperties ();
 168         String msgtext = m.getProperty (msgkey, msgkey);
 169         return msgtext;
 170 
 171     }
 172 
 173     /**
 174      * Returns the message text corresponding to the passed msgkey
 175      * string.  The message text is assumed to require the insertion
 176      * of a single argument, supplied by the "parm" parameter.
 177      * If the message text does not contain the meta characters "%1"
 178      * that indicate where to place the argument, the passed argument
 179      * is appended at the end of the message text.
 180      * <p>
 181      * If the msgkey cannot be found, its value is used as the
 182      * message text.
 183      */
 184     public static final String msg (String msgkey, String parm) {
 185 
 186         if (loadNeeded)
 187             loadDefaultProperties ();
 188         String msgtext = m.getProperty (msgkey, msgkey);
 189         int i = msgtext.indexOf ("%1");
 190         if (i >= 0) {
 191             String ending = "";
 192             if ((i+2) < msgtext.length ())
 193                 ending = msgtext.substring (i+2);
 194             return msgtext.substring (0, i) + parm + ending;
 195         } else
 196             msgtext += " " + parm;
 197         return msgtext;
 198 
 199     }
 200 
 201     /**
 202      * Returns the message text corresponding to the passed msgkey
 203      * string.  The message text is assumed to require the insertion
 204      * of a single argument, supplied by the "parm" parameter.
 205      * If the message text does not contain the meta characters "%1"
 206      * that indicate where to place the argument, the passed argument
 207      * is appended at the end of the message text.
 208      * <p>
 209      * If the msgkey cannot be found, its value is used as the
 210      * message text.
 211      */
 212     public static final String msg (String msgkey, int parm) {
 213 
 214         return msg (msgkey, String.valueOf (parm));
 215 
 216     }
 217 
 218     /**
 219      * Returns the message text corresponding to the passed msgkey
 220      * string.  The message text is assumed to require the insertion
 221      * of two arguments, supplied by the "parm1" and "parm2" parameters.
 222      * If the message text does not contain the meta characters "%1" and
 223      * "%2" that indicate where to place the arguments, the passed arguments
 224      * are appended at the end of the message text.
 225      * <p>
 226      * If the msgkey cannot be found, its value is used as the
 227      * message text.
 228      */
 229     public static final String msg (String msgkey, String parm1, String parm2) {
 230 
 231         if (loadNeeded)
 232             loadDefaultProperties ();
 233         String result = m.getProperty (msgkey, msgkey);
 234         String ending = "";
 235         int i = result.indexOf ("%1");
 236         if (i >= 0) {
 237             if ((i+2) < result.length ())
 238                 ending = result.substring (i+2);
 239             result = result.substring (0, i) + parm1 + ending;
 240         } else
 241             result += " " + parm1;
 242         i = result.indexOf ("%2");
 243         if (i >= 0) {
 244             ending = "";
 245             if ((i+2) < result.length ())
 246                 ending = result.substring (i+2);
 247             result = result.substring (0, i) + parm2 + ending;
 248         } else
 249             result += " " + parm2;
 250         return result;
 251 
 252     }
 253 
 254     /**
 255      * Returns the message text corresponding to the passed msgkey
 256      * string.  The message text is assumed to require the insertion
 257      * of two arguments, supplied by the "parm1" and "parm2" parameters.
 258      * If the message text does not contain the meta characters "%1" and
 259      * "%2" that indicate where to place the arguments, the passed arguments
 260      * are appended at the end of the message text.
 261      * <p>
 262      * If the msgkey cannot be found, its value is used as the
 263      * message text.
 264      */
 265     public static final String msg (String msgkey, int parm1, String parm2) {
 266 
 267         return msg (msgkey, String.valueOf (parm1), parm2);
 268 
 269     }
 270 
 271     /**
 272      * Returns the message text corresponding to the passed msgkey
 273      * string.  The message text is assumed to require the insertion
 274      * of two arguments, supplied by the "parm1" and "parm2" parameters.
 275      * If the message text does not contain the meta characters "%1" and
 276      * "%2" that indicate where to place the arguments, the passed arguments
 277      * are appended at the end of the message text.
 278      * <p>
 279      * If the msgkey cannot be found, its value is used as the
 280      * message text.
 281      */
 282     public static final String msg (String msgkey, String parm1, int parm2) {
 283 
 284         return msg (msgkey, parm1, String.valueOf (parm2));
 285 
 286     }
 287 
 288     /**
 289      * Returns the message text corresponding to the passed msgkey
 290      * string.  The message text is assumed to require the insertion
 291      * of two arguments, supplied by the "parm1" and "parm2" parameters.
 292      * If the message text does not contain the meta characters "%1" and
 293      * "%2" that indicate where to place the arguments, the passed arguments
 294      * are appended at the end of the message text.
 295      * <p>
 296      * If the msgkey cannot be found, its value is used as the
 297      * message text.
 298      */
 299     public static final String msg (String msgkey, int parm1, int parm2) {
 300 
 301         return msg (msgkey, String.valueOf (parm1), String.valueOf (parm2));
 302 
 303     }
 304 
 305 
 306     /**
 307      * Returns the message text corresponding to the passed msgkey
 308      * string.  The message text is assumed to require the insertion
 309      * of three arguments, supplied by the "parm1", "parm2" and "parm3"
 310      *  parameters.
 311      * If the message text does not contain the meta characters "%1" and
 312      * "%2" that indicate where to place the arguments, the passed arguments
 313      * are appended at the end of the message text.
 314      * <p>
 315      * If the msgkey cannot be found, its value is used as the
 316      * message text.
 317      */
 318     public static final String msg (String msgkey, String parm1,
 319                             String parm2, String parm3) {
 320         if (loadNeeded)
 321             loadDefaultProperties ();
 322         String result = m.getProperty (msgkey, msgkey);
 323         result = substituteString(result, 1, parm1);
 324         result = substituteString(result, 2, parm2);
 325         result = substituteString(result, 3, parm3);
 326 
 327         return result;
 328     }
 329 
 330     /* helper function for string substition.
 331      @return the substituted string, it substitution is possible.
 332        Otherwise, return a new string with subst at the end.
 333      @orig: original string
 334      @paramNum the parameter number to search. For example,
 335          paramNam == 1 means search for "%1".
 336      @subst: string for the substitution.
 337     */
 338     private static String substituteString(String orig, int paramNum,
 339                      String subst){
 340         String result = orig;
 341         String paramSubst = "%"+ paramNum;
 342         int len = paramSubst.length();
 343         int index = result.indexOf (paramSubst);
 344         String ending = "";
 345         if (index >= 0) {
 346             if ((index+len) < result.length ())
 347                 ending = result.substring (index+len);
 348             result = result.substring (0, index) + subst + ending;
 349         }
 350         else result += " " + subst;
 351 
 352          return result;
 353     }
 354 
 355 
 356 }