| /* |
| * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package com.sun.tools.corba.se.logutil; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| |
| import java.util.Arrays; |
| import java.util.Date; |
| import java.util.Formatter; |
| import java.util.List; |
| import java.util.Queue; |
| |
| public class MC { |
| |
| private static final String VERSION = "1.0"; |
| |
| private static final List<String> SUN_EXCEPTION_GROUPS = Arrays.asList(new String[] |
| { "SUNBASE", "ORBUTIL", "ACTIVATION", "NAMING", "INTERCEPTORS", "POA", "IOR", "UTIL" }); |
| |
| private static final List<String> EXCEPTIONS = Arrays.asList(new String[] |
| { "UNKNOWN", "BAD_PARAM", "NO_MEMORY", "IMP_LIMIT", "COMM_FAILURE", "INV_OBJREF", "NO_PERMISSION", |
| "INTERNAL", "MARSHAL", "INITIALIZE", "NO_IMPLEMENT", "BAD_TYPECODE", "BAD_OPERATION", "NO_RESOURCES", |
| "NO_RESPONSE", "PERSIST_STORE", "BAD_INV_ORDER", "TRANSIENT", "FREE_MEM", "INV_IDENT", "INV_FLAG", |
| "INTF_REPOS", "BAD_CONTEXT", "OBJ_ADAPTER", "DATA_CONVERSION", "OBJECT_NOT_EXIST", "TRANSACTION_REQUIRED", |
| "TRANSACTION_ROLLEDBACK", "INVALID_TRANSACTION", "INV_POLICY", "CODESET_INCOMPATIBLE", "REBIND", |
| "TIMEOUT", "TRANSACTION_UNAVAILABLE", "BAD_QOS", "INVALID_ACTIVITY", "ACTIVITY_COMPLETED", |
| "ACTIVITY_REQUIRED" }); |
| |
| /** |
| * Read the minor codes from the input file and |
| * write out a resource file. |
| * |
| * @param inFile the file to read the codes from. |
| * @param outDir the directory to write the resource file to. |
| * @throws FileNotFoundException if the input file can not be found. |
| * @throws IOException if an I/O error occurs. |
| */ |
| private void makeResource(String inFile, String outDir) |
| throws FileNotFoundException, IOException { |
| writeResource(outDir, new Input(inFile)); |
| } |
| |
| /** |
| * Create a new Java source file using the specified Scheme input file, |
| * and writing the result to the given output directory. |
| * |
| * @param inFile the file to read the data from. |
| * @param outDir the directory to write the Java class to. |
| * @throws FileNotFoundException if the input file can not be found. |
| * @throws IOException if an I/O error occurs. |
| */ |
| private void makeClass(String inFile, String outDir) |
| throws FileNotFoundException, IOException { |
| writeClass(inFile, outDir, new Input(inFile)); |
| } |
| |
| /** |
| * Writes out a Java source file using the data from the given |
| * {@link Input} object. The result is written to {@code outDir}. |
| * The name of the input file is just used in the header of the |
| * resulting source file. |
| * |
| * @param inFile the name of the file the data was read from. |
| * @param outDir the directory to write the Java class to. |
| * @param input the parsed input data. |
| * @throws FileNotFoundException if the output file can't be written. |
| */ |
| private void writeClass(String inFile, String outDir, Input input) |
| throws FileNotFoundException { |
| String packageName = input.getPackageName(); |
| String className = input.getClassName(); |
| String groupName = input.getGroupName(); |
| Queue<InputException> exceptions = input.getExceptions(); |
| FileOutputStream file = new FileOutputStream(outDir + File.separator + className + ".java"); |
| IndentingPrintWriter pw = new IndentingPrintWriter(file); |
| |
| writeClassHeader(inFile, groupName, pw); |
| pw.printMsg("package @ ;", packageName); |
| pw.println(); |
| pw.println("import java.util.logging.Logger ;"); |
| pw.println("import java.util.logging.Level ;"); |
| pw.println(); |
| pw.println("import org.omg.CORBA.OMGVMCID ;"); |
| pw.println( "import com.sun.corba.se.impl.util.SUNVMCID ;"); |
| pw.println( "import org.omg.CORBA.CompletionStatus ;"); |
| pw.println( "import org.omg.CORBA.SystemException ;"); |
| pw.println(); |
| pw.println( "import com.sun.corba.se.spi.orb.ORB ;"); |
| pw.println(); |
| pw.println( "import com.sun.corba.se.spi.logging.LogWrapperFactory;"); |
| pw.println(); |
| pw.println( "import com.sun.corba.se.spi.logging.LogWrapperBase;"); |
| pw.println(); |
| writeImports(exceptions, pw); |
| pw.println(); |
| pw.indent(); |
| pw.printMsg("public class @ extends LogWrapperBase {", className); |
| pw.println(); |
| pw.printMsg("public @( Logger logger )", className); |
| pw.indent(); |
| pw.println( "{"); |
| pw.undent(); |
| pw.println( "super( logger ) ;"); |
| pw.println( "}"); |
| pw.println(); |
| pw.flush(); |
| writeFactoryMethod(className, groupName, pw); |
| writeExceptions(groupName, exceptions, className, pw); |
| pw.undent(); |
| pw.println( ); |
| pw.println( "}"); |
| pw.flush(); |
| pw.close(); |
| } |
| |
| /** |
| * Writes out the header of a Java source file. |
| * |
| * @param inFile the input file the file was generated from. |
| * @param groupName the group of exceptions the Java source file is for. |
| * @param pw the print writer used to write the output. |
| */ |
| private void writeClassHeader(String inFile, String groupName, |
| IndentingPrintWriter pw) { |
| if (groupName.equals("OMG")) |
| pw.println("// Log wrapper class for standard exceptions"); |
| else |
| pw.printMsg("// Log wrapper class for Sun private system exceptions in group @", |
| groupName); |
| pw.println("//"); |
| pw.printMsg("// Generated by MC.java version @, DO NOT EDIT BY HAND!", VERSION); |
| pw.printMsg("// Generated from input file @ on @", inFile, new Date()); |
| pw.println(); |
| } |
| |
| /** |
| * Write out the import list for the exceptions. |
| * |
| * @param groups the exceptions that were parsed. |
| * @param pw the {@link IndentingPrintWriter} for writing to the file. |
| */ |
| private void writeImports(Queue<InputException> exceptions, |
| IndentingPrintWriter pw) { |
| if (exceptions == null) |
| return; |
| for (InputException e : exceptions) |
| pw.println("import org.omg.CORBA." + e.getName() + " ;"); |
| } |
| |
| /** |
| * Write out the factory method for this group of exceptions. |
| * |
| * @param className the name of the generated class. |
| * @param groupName the name of this group of exceptions. |
| * @param pw the {@link IndentingPrintWriter} for writing to the file. |
| */ |
| private void writeFactoryMethod(String className, String groupName, |
| IndentingPrintWriter pw) { |
| pw.indent(); |
| pw.println( "private static LogWrapperFactory factory = new LogWrapperFactory() {"); |
| pw.println( "public LogWrapperBase create( Logger logger )" ); |
| pw.indent(); |
| pw.println( "{"); |
| pw.undent(); |
| pw.printMsg("return new @( logger ) ;", className); |
| pw.undent(); |
| pw.println( "}" ); |
| pw.println( "} ;" ); |
| pw.println(); |
| pw.printMsg("public static @ get( ORB orb, String logDomain )", className); |
| pw.indent(); |
| pw.println( "{"); |
| pw.indent(); |
| pw.printMsg( "@ wrapper = ", className); |
| pw.indent(); |
| pw.printMsg( "(@) orb.getLogWrapper( logDomain, ", className); |
| pw.undent(); |
| pw.undent(); |
| pw.printMsg( "\"@\", factory ) ;", groupName); |
| pw.undent(); |
| pw.println( "return wrapper ;" ); |
| pw.println( "} " ); |
| pw.println(); |
| pw.printMsg( "public static @ get( String logDomain )", className); |
| pw.indent(); |
| pw.println( "{"); |
| pw.indent(); |
| pw.printMsg( "@ wrapper = ", className); |
| pw.indent(); |
| pw.printMsg( "(@) ORB.staticGetLogWrapper( logDomain, ", className); |
| pw.undent(); |
| pw.undent(); |
| pw.printMsg( "\"@\", factory ) ;", groupName); |
| pw.undent(); |
| pw.println( "return wrapper ;" ); |
| pw.println( "} " ); |
| pw.println(); |
| } |
| |
| /** |
| * Writes out the exceptions themselves. |
| * |
| * @param groupName the name of this group of exceptions. |
| * @param exceptions the exceptions to write out. |
| * @param className the name of the generated class. |
| * @param pw the {@link IndentingPrintWriter} for writing to the file. |
| */ |
| private void writeExceptions(String groupName, Queue<InputException> exceptions, |
| String className, IndentingPrintWriter pw) { |
| for (InputException e : exceptions) { |
| pw.println("///////////////////////////////////////////////////////////"); |
| pw.printMsg("// @", e.getName()); |
| pw.println("///////////////////////////////////////////////////////////"); |
| pw.println(); |
| for (InputCode c : e.getCodes()) |
| writeMethods(groupName, e.getName(), c.getName(), c.getCode(), |
| c.getLogLevel(), className, StringUtil.countArgs(c.getMessage()), pw); |
| pw.flush(); |
| } |
| } |
| |
| /** |
| * Writes out the methods for a particular error. |
| * |
| * @param groupName the name of this group of exceptions. |
| * @param exceptionName the name of this particular exception. |
| * @param errorName the name of this particular error. |
| * @param code the minor code for this particular error. |
| * @param ident the name of the error in mixed-case identifier form. |
| * @param level the level at which to place log messages. |
| * @param className the name of the class for this group of exceptions. |
| * @param numParams the number of parameters the detail message takes. |
| * @param pw the print writer for writing to the file. |
| */ |
| private void writeMethods(String groupName, String exceptionName, String errorName, |
| int code, String level, String className, int numParams, |
| IndentingPrintWriter pw) { |
| String ident = StringUtil.toMixedCase(errorName); |
| pw.printMsg("public static final int @ = @ ;", errorName, getBase(groupName, code)); |
| pw.println(); |
| pw.flush(); |
| writeMethodStatusCause(groupName, exceptionName, errorName, ident, level, |
| numParams, className, pw); |
| pw.println(); |
| pw.flush(); |
| writeMethodStatus(exceptionName, ident, numParams, pw); |
| pw.println(); |
| pw.flush(); |
| writeMethodCause(exceptionName, ident, numParams, pw); |
| pw.println(); |
| pw.flush(); |
| writeMethodNoArgs(exceptionName, ident, numParams, pw); |
| pw.println(); |
| pw.flush(); |
| } |
| |
| /** |
| * Writes out a method for an error that takes a |
| * {@link org.omg.CORBA.CompletionStatus} and a cause. |
| * |
| * @param groupName the name of this group of exceptions. |
| * @param exceptionName the name of this particular exception. |
| * @param errorName the name of this particular error. |
| * @param ident the name of the error in mixed-case identifier form. |
| * @param logLevel the level at which to place log messages. |
| * @param numParams the number of parameters the detail message takes. |
| * @param className the name of the class for this group of exceptions. |
| * @param pw the print writer for writing to the file. |
| */ |
| private void writeMethodStatusCause(String groupName, String exceptionName, |
| String errorName, String ident, |
| String logLevel, int numParams, |
| String className, IndentingPrintWriter pw) { |
| pw.indent(); |
| pw.printMsg( "public @ @( CompletionStatus cs, Throwable t@) {", exceptionName, |
| ident, makeDeclArgs(true, numParams)); |
| pw.printMsg( "@ exc = new @( @, cs ) ;", exceptionName, exceptionName, errorName); |
| pw.indent(); |
| pw.println( "if (t != null)" ); |
| pw.undent(); |
| pw.println( "exc.initCause( t ) ;" ); |
| pw.println(); |
| pw.indent(); |
| pw.printMsg( "if (logger.isLoggable( Level.@ )) {", logLevel); |
| if (numParams > 0) { |
| pw.printMsg( "Object[] parameters = new Object[@] ;", numParams); |
| for (int a = 0; a < numParams; ++a) |
| pw.printMsg("parameters[@] = arg@ ;", a, a); |
| } else |
| pw.println( "Object[] parameters = null ;"); |
| pw.indent(); |
| pw.printMsg( "doLog( Level.@, \"@.@\",", logLevel, groupName, ident); |
| pw.undent(); |
| pw.undent(); |
| pw.printMsg( "parameters, @.class, exc ) ;", className); |
| pw.println( "}"); |
| pw.println(); |
| |
| pw.undent(); |
| pw.println( "return exc ;"); |
| pw.println( "}"); |
| } |
| |
| /** |
| * Writes out a method for an error that takes a |
| * {@link org.omg.CORBA.CompletionStatus}. |
| * |
| * @param exceptionName the name of this particular exception. |
| * @param ident the name of the error in mixed-case identifier form. |
| * @param numParams the number of parameters the detail message takes. |
| * @param pw the print writer for writing to the file. |
| */ |
| private void writeMethodStatus(String exceptionName, String ident, |
| int numParams, IndentingPrintWriter pw) { |
| pw.indent(); |
| pw.printMsg("public @ @( CompletionStatus cs@) {", exceptionName, |
| ident, makeDeclArgs(true, numParams)); |
| pw.undent(); |
| pw.printMsg("return @( cs, null@ ) ;", ident, makeCallArgs(true, numParams)); |
| pw.println("}"); |
| } |
| |
| /** |
| * Writes out a method for an error that takes a cause. |
| * |
| * @param exceptionName the name of this particular exception. |
| * @param ident the name of the error in mixed-case identifier form. |
| * @param numParams the number of parameters the detail message takes. |
| * @param pw the print writer for writing to the file. |
| */ |
| private void writeMethodCause(String exceptionName, String ident, |
| int numParams, IndentingPrintWriter pw) { |
| pw.indent(); |
| pw.printMsg("public @ @( Throwable t@) {", exceptionName, ident, |
| makeDeclArgs(true, numParams)); |
| pw.undent(); |
| pw.printMsg("return @( CompletionStatus.COMPLETED_NO, t@ ) ;", ident, |
| makeCallArgs(true, numParams)); |
| pw.println("}"); |
| } |
| |
| /** |
| * Writes out a method for an error that takes no arguments. |
| * |
| * @param exceptionName the name of this particular exception. |
| * @param ident the name of the error in mixed-case identifier form. |
| * @param numParams the number of parameters the detail message takes. |
| * @param pw the print writer for writing to the file. |
| */ |
| private void writeMethodNoArgs(String exceptionName, String ident, |
| int numParams, IndentingPrintWriter pw) { |
| |
| pw.indent(); |
| pw.printMsg("public @ @( @) {", exceptionName, ident, |
| makeDeclArgs(false, numParams)); |
| pw.undent(); |
| pw.printMsg("return @( CompletionStatus.COMPLETED_NO, null@ ) ;", |
| ident, makeCallArgs(true, numParams)); |
| pw.println("}"); |
| } |
| |
| /** |
| * Returns a list of comma-separated arguments with type declarations. |
| * |
| * @param leadingComma true if the list should start with a comma. |
| * @param numArgs the number of arguments to generate. |
| * @return the generated string. |
| */ |
| private String makeDeclArgs(boolean leadingComma, int numArgs) { |
| return makeArgString("Object arg", leadingComma, numArgs); |
| } |
| |
| /** |
| * Returns a list of comma-separated arguments without type declarations. |
| * |
| * @param leadingComma true if the list should start with a comma. |
| * @param numArgs the number of arguments to generate. |
| * @return the generated string. |
| */ |
| private String makeCallArgs(boolean leadingComma, int numArgs) { |
| return makeArgString("arg", leadingComma, numArgs); |
| } |
| |
| /** |
| * Returns a list of comma-separated arguments. |
| * |
| * @param prefixString the string with which to prefix each argument. |
| * @param leadingComma true if the list should start with a comma. |
| * @param numArgs the number of arguments to generate. |
| * @return the generated string. |
| */ |
| private String makeArgString(String prefixString, boolean leadingComma, |
| int numArgs) { |
| if (numArgs == 0) |
| return " "; |
| if (numArgs == 1) { |
| if (leadingComma) |
| return ", " + prefixString + (numArgs - 1); |
| else |
| return " " + prefixString + (numArgs - 1); |
| } |
| return makeArgString(prefixString, leadingComma, numArgs - 1) + |
| ", " + prefixString + (numArgs - 1); |
| } |
| |
| /** |
| * Returns the {@link String} containing the calculation of the |
| * error code. |
| * |
| * @param groupName the group of exception to which the code belongs. |
| * @param code the minor code number representing the exception within the group. |
| * @return the unique error code. |
| */ |
| private String getBase(String groupName, int code) { |
| if (groupName.equals("OMG")) |
| return "OMGVMCID.value + " + code; |
| else |
| return "SUNVMCID.value + " + (code + getSunBaseNumber(groupName)); |
| } |
| |
| /** |
| * Returns the base number for Sun-specific exceptions. |
| * |
| * @return the base number. |
| */ |
| private int getSunBaseNumber(String groupName) { |
| return 200 * SUN_EXCEPTION_GROUPS.indexOf(groupName); |
| } |
| |
| /** |
| * Writes out a resource file using the data from the given |
| * {@link Input} object. The result is written to {@code outDir}. |
| * |
| * @param outDir the directory to write the Java class to. |
| * @param input the parsed input data. |
| * @throws FileNotFoundException if the output file can't be written. |
| */ |
| private void writeResource(String outDir, Input input) |
| throws FileNotFoundException { |
| FileOutputStream file = new FileOutputStream(outDir + File.separator + |
| input.getClassName() + ".resource"); |
| IndentingPrintWriter pw = new IndentingPrintWriter(file); |
| String groupName = input.getGroupName(); |
| for (InputException e : input.getExceptions()) { |
| String exName = e.getName(); |
| for (InputCode c : e.getCodes()) { |
| String ident = StringUtil.toMixedCase(c.getName()); |
| pw.printMsg("@.@=\"@: (@) @\"", groupName, ident, |
| getMessageID(groupName, exName, c.getCode()), exName, c.getMessage()); |
| } |
| pw.flush(); |
| } |
| pw.close(); |
| } |
| |
| /** |
| * Returns the message ID corresponding to the given group name, |
| * exception name and error code. |
| * |
| * @param groupName the name of the group of exceptions. |
| * @param exception the name of the particular exception. |
| * @param code an error code from the given exception. |
| * @return the message ID. |
| */ |
| private String getMessageID(String groupName, String exceptionName, int code) { |
| if (groupName.equals("OMG")) |
| return getStandardMessageID(exceptionName, code); |
| else |
| return getSunMessageID(groupName, exceptionName, code); |
| } |
| |
| /** |
| * Returns the standard (OMG) message ID corresponding to the given |
| * exception name and error code. |
| * |
| * @param exceptionName the name of the particular exception. |
| * @param code an error code from the given exception. |
| * @return the message ID. |
| */ |
| private String getStandardMessageID(String exceptionName, int code) { |
| return new Formatter().format("IOP%s0%04d", getExceptionID(exceptionName), |
| code).toString(); |
| } |
| |
| /** |
| * Returns the Sun message ID corresponding to the given group name, |
| * exception name and error code. |
| * |
| * @param groupName the name of the group of exceptions. |
| * @param exceptionName the name of the particular exception. |
| * @param code an error code from the given exception. |
| * @return the message ID. |
| */ |
| private String getSunMessageID(String groupName, String exceptionName, int code) { |
| return new Formatter().format("IOP%s1%04d", getExceptionID(exceptionName), |
| getSunBaseNumber(groupName) + code).toString(); |
| } |
| |
| /** |
| * Returns the exception ID corresponding to the given exception name. |
| * |
| * @param exceptionName the name of the particular exception. |
| * @return the message ID. |
| */ |
| private String getExceptionID(String exceptionName) { |
| return new Formatter().format("%03d", EXCEPTIONS.indexOf(exceptionName)).toString(); |
| } |
| |
| /** |
| * Entry point for running the generator from the command |
| * line. Users can specify either "make-class" or "make-resource" |
| * as the first argument to generate the specified type of file. |
| * |
| * @param args the command-line arguments. |
| * @throws FileNotFoundException if the input file can not be found. |
| * @throws IOException if an I/O error occurs. |
| */ |
| public static void main(String[] args) |
| throws FileNotFoundException, IOException |
| { |
| if (args.length < 3) |
| { |
| System.err.println("(make-class|make-resource) <input file> <output dir>"); |
| System.exit(-1); |
| } |
| if (args[0].equals("make-class")) |
| new MC().makeClass(args[1], args[2]); |
| else if (args[0].equals("make-resource")) |
| new MC().makeResource(args[1], args[2]); |
| else |
| System.err.println("Invalid command: " + args[0]); |
| } |
| |
| } |