src.com.ibm.as400.util.CommandHelpRetriever Maven / Gradle / Ivy
///////////////////////////////////////////////////////////////////////////////
//
// JTOpen (IBM Toolbox for Java - OSS version)
//
// Filename: CommandHelpRetriever.java
//
// The source code contained herein is licensed under the IBM Public License
// Version 1.0, which has been approved by the Open Source Initiative.
// Copyright (C) 1997-2002 International Business Machines Corporation and
// others. All rights reserved.
//
///////////////////////////////////////////////////////////////////////////////
package com.ibm.as400.util;
// JDK classes.
import java.io.*;
import java.util.*;
// XSL classes.
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
// Toolbox classes.
import com.ibm.as400.access.*;
// WebSphere 4.0 ships only a stub XML4J.jar, and XML4J.jar goes away in the future. We need to
// use xerces.jar to be compatible with the version used by WebSphere.
//import org.apache.xerces.parsers.SAXParser;
//import javax.xml.parsers.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
//import org.xml.sax.helpers.*;
/**
* Generates IBM-formatted CL command help documentation.
* This class requires that valid XML and XSL processors (e.g. Xerces and Xalan) be in the CLASSPATH.
*
* CommandHelpRetriever can be run as a command line program, as follows:
*
* java com.ibm.as400.util.CommandHelpRetriever -library *
-
*
*
-help
*- Displays the help text. * The -help option may be abbreviated to -h or -?. *
* Parameters: *
*
-
*
*
-library
IBM i library.
* - Specifies the IBM i library.
* This parameter may be abbreviated
-l
or-lib
. *
*
* -command
IBM i command.
* - Specifies the IBM i command.
* This parameter may be abbreviated
-c
or-cmd
. *
*
* -system
IBM i system name
* - Specifies the IBM i system. If an IBM i system name is not provided, a signon dialog will be displayed.
* This optional parameter may be abbreviated
-s
or-sys
. *
*
* -userid
IBM i userID.
* - Specifies the IBM i userId. If an IBM i userID is not provided, a signon dialog will be displayed.
* This optional parameter may be abbreviated
-u
or-uid
. *
*
* -password
IBM i password.
* - Specifies the IBM i password. If an IBM i password is not provided, a signon dialog will be displayed.
* This optional parameter may be abbreviated
-p
or-pwd
. *
*
* -showChoicePgmValues
[true | false]
* - Specifies whether or not parameter choices returned from choice programs are shown in the Choices cells of the parameter summary table.
* The default is false.
* This optional parameter may be abbreviated
-scpv
. *
*
* -output
output location. *- Specifies the output location for the generated help. The default is the current directory. The output
* cannot be a file when the command (-c) parameter contains a wildcard (*).
* This optional parameter may be abbreviated
-o
. *
*
* -debug
[true | false] *- Specifies whether to output the source command help and xml files to the output location specified by the -output parameter. The default is false.
* This optional parameter may be abbreviated
-d
. *
*
*
Note: While the String being returned is a typical UTF-16 Java String, the contents * of the String is an HTML file with a META tag that defines the charset as UTF-8. * Applications that use the String returned by this method should then be sure to convert * the contents to UTF-8 bytes, or replace the charset tag inside the HTML with whichever * encoding the application chooses to convert to. See {@link #generateHTMLBytes generateHTMLBytes()}. * * @param command The command. * @param panelGroup The panel group used to generate the help text, instead of the Command's defined panel group. * @return An HTML string consisting of the help documentation for the command. * @see java.util.Locale * @see com.ibm.as400.access.AS400 * @see com.ibm.as400.access.Command * @see com.ibm.as400.access.PanelGroup **/ public synchronized String generateHTML(Command command, PanelGroup panelGroup) throws AS400Exception, AS400SecurityException, ErrorCompletingRequestException, IOException, InterruptedException, ObjectDoesNotExistException, SAXException, ParserConfigurationException, TransformerConfigurationException, TransformerException { if (command == null) throw new NullPointerException("command"); if (panelGroup == null) throw new NullPointerException("panelGroup"); return generate(command, panelGroup); } /** * Generates IBM-formatted command help documentation for the specified CL command. * Portions of the resulting HTML will contain strings that were translated using * the {@link java.util.Locale Locale} specified on the {@link com.ibm.as400.access.AS400 AS400} * object for the given {@link com.ibm.as400.access.Command Command}. * *
Note: The byte array returned by this method has already been encoded in UTF-8 in order to
* match the charset tag within the HTML document.
*
* @param command The command.
* @param panelGroup The panel group used to generate the help text. Specify null to use the Command's defined panel group.
* @return An HTML document encoded in UTF-8 bytes, consisting of the help documentation for the command.
* @see java.util.Locale
* @see com.ibm.as400.access.AS400
* @see com.ibm.as400.access.Command
* @see com.ibm.as400.access.PanelGroup
**/
public synchronized byte[] generateHTMLBytes(Command command, PanelGroup panelGroup) throws AS400Exception, AS400SecurityException,
ErrorCompletingRequestException, IOException,
InterruptedException, ObjectDoesNotExistException,
SAXException,
ParserConfigurationException,
TransformerConfigurationException, TransformerException
{
if (command == null)
throw new NullPointerException("command");
return generate(command, panelGroup).getBytes("UTF-8");
}
/**
* Generates IBM-formatted command help documentation for the specified CL command.
* Portions of the resulting HTML will contain strings that were translated using
* the {@link java.util.Locale Locale} specified on the {@link com.ibm.as400.access.AS400 AS400}
* object for the given {@link com.ibm.as400.access.Command Command}.
* @param command The command.
* @param panelGroup The panel group used to generate the help text, instead of the Command's defined panel group.
* @return An HTML string consisting of the help documentation for the command.
* @see java.util.Locale
* @see com.ibm.as400.access.AS400
* @see com.ibm.as400.access.Command
* @see com.ibm.as400.access.PanelGroup
**/
private synchronized String generate(Command command, PanelGroup panelGroup) throws AS400Exception, AS400SecurityException,
ErrorCompletingRequestException, IOException,
InterruptedException, ObjectDoesNotExistException,
SAXException,
ParserConfigurationException,
TransformerConfigurationException, TransformerException
{
if (Trace.isTraceOn())
Trace.log(Trace.DIAGNOSTIC, "Generating HTML documentation for '"+command+"' and panel group '"+panelGroup+"'.");
String xml = command.getXML();
if (debug_)
{
String path = command.getPath();
QSYSObjectPathName pn = new QSYSObjectPathName(path);
String lib = pn.getLibraryName();
String name = pn.getObjectName();
File outDir = new File(outputDirectory_);
boolean isDir = outDir.isDirectory();
File outFile = null;
if (isDir)
outFile = new File(outDir, lib + "_" + name + "_XML.xml");
else
outFile = new File(outputDirectory_ + "_XML.xml");
FileWriter fw = new FileWriter(outFile);
try { fw.write(xml); }
finally { if (fw != null) fw.close(); }
}
if (Trace.isTraceOn())
Trace.log(Trace.DIAGNOSTIC, "Retrieved command XML:\n"+xml+"\n");
String threadSafe = null;
String whereAllowedToRun = null;
try
{
switch (command.getThreadSafety())
{
case Command.THREADSAFE_NO:
threadSafe = "0";
break;
case Command.THREADSAFE_YES:
threadSafe = "1";
break;
case Command.THREADSAFE_CONDITIONAL:
threadSafe = "2";
break;
default:
break;
}
whereAllowedToRun = command.getWhereAllowedToRun();
}
catch (AS400Exception e)
{
AS400Message[] msgs = e.getAS400MessageList();
// CPF6250 - Can't retrieve info for command. Probably because it is a system command.
if (msgs.length != 1 || !msgs[0].getID().toUpperCase().trim().equals("CPF6250"))
throw new AS400Exception(msgs);
}
if (Trace.isTraceOn())
Trace.log(Trace.DIAGNOSTIC, "Using command threadsafety = "+threadSafe+" and where allowed to run = "+whereAllowedToRun+".");
String helpResults = null;
try
{
helpResults = (panelGroup == null ? command.getXMLHelpText() : command.getXMLHelpText(panelGroup));
}
catch (AS400Exception e)
{
AS400Message[] msgs = e.getAS400MessageList();
//
// Note: It is also possible to get a CPF6E3B when the user is not authorized to the help text.
// However, we do not see the underlying message that the user is not authorized.
// @C2A
// CPF6250 - Can't retrieve info for command. Probably because it is a system command.
if (msgs.length != 1 ||
( !msgs[0].getID().toUpperCase().trim().equals("CPF6250") &&
!msgs[0].getID().toUpperCase().trim().equals("CPF6E3B") ))
throw new AS400Exception(msgs);
}
if (debug_ && helpResults != null)
{
String path = command.getPath();
QSYSObjectPathName pn = new QSYSObjectPathName(path);
String lib = pn.getLibraryName();
String name = pn.getObjectName();
File outDir = new File(outputDirectory_);
boolean isDir = outDir.isDirectory();
File outFile = null;
if (isDir)
outFile = new File(outDir, lib + "_" + name + "_HTMLHelp.html");
else
outFile = new File(outputDirectory_ + "_HTMLHelp.html");
FileWriter fw = new FileWriter(outFile);
try { fw.write(helpResults); }
finally { if (fw != null) fw.close(); }
}
// Reset the transformer. We could re-use the same Transformer object,
// but the problem is that any document() calls in the XSL are resolved
// and cached by the transformer, so that the second time through, our
// help text would still be from the previous command.
// One way around this is to DOM parse the help text ourselves and pass
// that in to the transformer, instead of coding a document() call in
// the XSL; however, this is INCREDIBLY slow since the DOM tree can
// consist of a large number of objects, all of which the transformer
// has to marshal into its own internal format. It turns out that
// using a document() call in the XSL code is faster, especially since
// we don't get any re-use out of the help text's DOM tree.
setupHTMLTransformer(command.getSystem().getLocale());
htmlTransformer_.setParameter("CommandHelp", helpResults == null || helpResults.trim().length() == 0 ? "__NO_HELP" : "myCommandHelpResolver");
htmlTransformer_.setParameter("ShowChoicePgmValues", showChoices_ ? "1" : "0");
htmlTransformer_.setParameter("ThreadSafe", threadSafe == null ? "0" : threadSafe);
htmlTransformer_.setParameter("WhereAllowed", whereAllowedToRun == null ? "000000000000000" : whereAllowedToRun);
resolver_.helpResults_ = helpResults;
StreamSource sourceXML = new StreamSource(new StringReader(xml));
StringWriter buf = new StringWriter();
StreamResult output = new StreamResult(buf);
if (Trace.isTraceOn()) {
Trace.log(Trace.DIAGNOSTIC, "Performing XSL transform.");
Trace.log(Trace.DIAGNOSTIC, "Help Results is "+helpResults);
}
try {
htmlTransformer_.transform(sourceXML, output);
} catch (TransformerException e) {
if (Trace.isTraceOn()) {
Trace.log(Trace.DIAGNOSTIC, "Exception from transform.");
Trace.log(Trace.DIAGNOSTIC, e);
}
throw e;
}
if (Trace.isTraceOn())
Trace.log(Trace.DIAGNOSTIC, "Successfully generated help documentation.");
return buf.toString();
}
/**
* Generates an IBM-formatted UIM template for the specified CL command.
* Portions of the resulting UIM output will contain strings that were translated using
* the {@link java.util.Locale Locale} specified on the {@link com.ibm.as400.access.AS400 AS400}
* object for the given {@link com.ibm.as400.access.Command Command}.
* @param command The command.
* @return A UIM string consisting of the UIM template for the command.
* @see java.util.Locale
* @see com.ibm.as400.access.AS400
* @see com.ibm.as400.access.Command
**/
public synchronized String generateUIM(Command command) throws AS400Exception, AS400SecurityException,
ErrorCompletingRequestException, IOException,
InterruptedException, ObjectDoesNotExistException,
SAXException,
ParserConfigurationException,
TransformerConfigurationException, TransformerException
{
if (command == null)
throw new NullPointerException("command");
if (Trace.isTraceOn())
Trace.log(Trace.DIAGNOSTIC, "Generating UIM documentation for "+command+".");
String xml = null;
try
{
xml = command.getXMLExtended();
}
catch(AS400Exception ae)
{
AS400Message[] msgs = ae.getAS400MessageList();
if (msgs.length == 1 && msgs[0].getID().equalsIgnoreCase("CPF3C21"))
{
if (Trace.isTraceOn())
{
Trace.log(Trace.WARNING, "Extended command XML format not supported by this system. Using older version.");
}
xml = command.getXML();
}
else
{
throw ae;
}
}
if (debug_)
{
String path = command.getPath();
QSYSObjectPathName pn = new QSYSObjectPathName(path);
String lib = pn.getLibraryName();
String name = pn.getObjectName();
File outDir = new File(outputDirectory_);
boolean isDir = outDir.isDirectory();
File outFile = null;
if (isDir)
outFile = new File(outDir, lib + "_" + name + "_XML_X.xml");
else
outFile = new File(outputDirectory_ + "_XML_X.xml");
FileWriter fw = new FileWriter(outFile);
try { fw.write(xml); }
finally { if (fw != null) fw.close(); }
}
if (Trace.isTraceOn())
{
Trace.log(Trace.DIAGNOSTIC, "Retrieved extended command XML:\n"+xml+"\n");
}
// Reset the transformer. We could re-use the same Transformer object,
// but the problem is that any document() calls in the XSL are resolved
// and cached by the transformer, so that the second time through, our
// help text would still be from the previous command.
// One way around this is to DOM parse the help text ourselves and pass
// that in to the transformer, instead of coding a document() call in
// the XSL; however, this is INCREDIBLY slow since the DOM tree can
// consist of a large number of objects, all of which the transformer
// has to marshal into its own internal format. It turns out that
// using a document() call in the XSL code is faster, especially since
// we don't get any re-use out of the help text's DOM tree.
setupUIMTransformer(command.getSystem().getLocale());
StreamSource sourceXML = new StreamSource(new StringReader(xml));
StringWriter buf = new StringWriter();
StreamResult output = new StreamResult(buf);
if (Trace.isTraceOn())
{
Trace.log(Trace.DIAGNOSTIC, "Performing XSL transform of UIM.");
}
uimTransformer_.transform(sourceXML, output);
if (Trace.isTraceOn())
{
Trace.log(Trace.DIAGNOSTIC, "Successfully generated UIM documentation.");
}
return buf.toString();
}
/**
* Returns whether or not the source XML and source command HTML help, which are used in
* generating the resulting command help HTML documentation, are saved to the current output location.
*
* @return true if the source XML and source HTML files will be generated; false otherwise. The default is false.
* @see #setDebug
**/
public boolean getDebug()
{
return debug_;
}
/**
* Returns the output location for the source XML and source command HTML help when running programatically. The default is the current directory.
*
* @return The output location of the source files.
* @see #setOutputLocation
**/
public String getOutputLocation()
{
return outputDirectory_;
}
/**
* Returns whether or not the generated HTML documentation will contain parameter values
* returned by a "choices program".
* @return true if the extra parameters will be shown; false otherwise. The default is false.
* @see #setShowChoiceProgramValues
**/
public boolean getShowChoiceProgramValues()
{
return showChoices_;
}
/**
* Used to get the translated MRI for a given Locale.
**/
private static final String[][] getTransformedHTMLParms(Locale locale)
{
String[][] parms = new String[mriHTMLTags_.length+4][];
if (Trace.isTraceOn())
{
Trace.log(Trace.DIAGNOSTIC, "Transforming CommandHelpRetriever HTML MRI for locale: "+locale);
}
ResourceBundle bundle = ResourceBundle.getBundle("com.ibm.as400.access.MRI", locale);
ResourceBundle bundle2 = ResourceBundle.getBundle("com.ibm.as400.access.MRI2", locale);
int i=0;
for (; i