use of com.ibm.as400.access.SpooledFile in project IBMiProgTool by vzupka.
the class WrkSplF method selectSpooledFiles.
/**
* Select spooled files according to path string from the node selected from the right tree and to criteria given in
* parameters;
* The path string is a file of type .OUTQ or library QSYS.LIB; Information from the spooled files is written to array lists.
*
* @param namePar
* @param numberPar
* @param pagesPar
* @param jobPar
* @param userPar
* @param jobNumberPar
* @param datePar
* @param timePar
* @return
*/
protected SpooledFile selectSpooledFiles(String namePar, String numberPar, String pagesPar, String jobPar, String userPar, String jobNumberPar, String datePar, String timePar) {
this.namePar = namePar;
this.numberPar = numberPar;
this.pagesPar = pagesPar;
this.jobPar = jobPar;
this.userPar = userPar;
this.jobNumberPar = jobNumberPar;
this.datePar = datePar;
this.timePar = timePar;
nbrOfRows = 0;
// Check connection to PRINT service before creating a spooled file list.
// ======================================================================
pingObject = new AS400JPing(properties.getProperty("HOST"));
// pingObject.setTimeout(1000);
ping_PRINT = pingObject.ping(AS400.PRINT);
boolean isPingOk = ping_PRINT;
while (!isPingOk) {
row = "Error: Ping to server " + properties.getProperty("HOST") + " failed. Reconnecting PRINT service.";
mainWindow.msgVector.add(row);
mainWindow.showMessages(noNodes);
try {
ping_PRINT = pingObject.ping(AS400.PRINT);
isPingOk = ping_PRINT;
System.out.println("pingOk: " + isPingOk);
Thread.sleep(2000);
} catch (Exception exc) {
row = "Error: Ping: " + exc.toString();
System.out.println("Error: Ping: " + exc.toString());
mainWindow.msgVector.add(row);
mainWindow.showMessages(noNodes);
exc.printStackTrace();
}
}
try {
remoteServer.connectService(AS400.PRINT);
} catch (Exception exc) {
row = "Error: Getting connection to PRINT service: " + exc.toString();
mainWindow.msgVector.add(row);
mainWindow.showMessages(noNodes);
exc.printStackTrace();
}
// Create object representing spooled files
SpooledFileList splfList = new SpooledFileList(remoteServer);
try {
// Parameter for selection all users for the first time or a specific user if not empty
if (rightPathString.equals("/QSYS.LIB")) {
row = "Wait: Retrieving list of all spooled files . . .";
mainWindow.msgVector.add(row);
mainWindow.showMessages(noNodes);
mainWindow.scrollMessagePane.getVerticalScrollBar().removeAdjustmentListener(mainWindow.messageScrollPaneAdjustmentListenerMax);
splfList.setUserFilter("*ALL");
splfList.setQueueFilter("/QSYS.LIB/%ALL%.LIB/%ALL%.OUTQ");
// Remove message scroll listener (cancel scrolling to the last message)
mainWindow.scrollMessagePane.getVerticalScrollBar().removeAdjustmentListener(mainWindow.messageScrollPaneAdjustmentListenerMax);
} else if (currentUser) {
// Spooled files for current user will be selected
splfList.setUserFilter("*CURRENT");
} else {
// Spooled files will be selected only from the output queue /QSYS.LIB/xxx.LIB/yyy.OUTQ
// (right path string from the right file tree)
splfList.setUserFilter("*ALL");
splfList.setQueueFilter(rightPathString);
}
// Selection of spooled files is asynchronous
splfList.openAsynchronously();
// Wait for completion
splfList.waitForListToComplete();
// Get list of all spooled files
Enumeration<SpooledFile> spooledFiles = splfList.getObjects();
// Clear array lists containing characteristics of spooled files
// that will be placed in table columns
nameArrList = new ArrayList<>();
numberArrList = new ArrayList<>();
pagesArrList = new ArrayList<>();
jobArrList = new ArrayList<>();
userArrList = new ArrayList<>();
spoolUsers = new ArrayList<>();
jobNumberArrList = new ArrayList<>();
dateArrList = new ArrayList<>();
timeArrList = new ArrayList<>();
queueArrList = new ArrayList<>();
splfArrList = new ArrayList<>();
// Select spooled files according to selection parameters
while (spooledFiles.hasMoreElements()) {
// Get next spooled file
splf = (SpooledFile) spooledFiles.nextElement();
if (splf != null) {
String splfFileNumberChar = String.valueOf(splf.getNumber());
String splfFilePagesChar = String.valueOf(splf.getIntegerAttribute(SpooledFile.ATTR_PAGES));
// to the array lists for the table
if (splf.getName().contains(namePar) && splfFileNumberChar.contains(numberPar) && splfFilePagesChar.contains(pagesPar) && splf.getJobName().contains(jobPar) && splf.getJobUser().contains(userPar) && splf.getJobNumber().contains(jobNumberPar) && splf.getCreateDate().contains(datePar) && splf.getCreateTime().contains(timePar)) {
// System.out.println("namePar 2: " + namePar);
// System.out.println("splf.getName() 2: " + splf.getName());
// System.out.print("File name selectSpoolFiles2: " + splf.getName());
// System.out.print(" \tFile number: " + splfFileNumberChar);
// System.out.print(" \tJob name: " + splf.getJobName());
// System.out.print(" \tUser name: " + splf.getJobUser());
// System.out.print(" \tJob number: " + splf.getJobNumber());
// System.out.print(" \tDate: " + splf.getCreateDate());
// System.out.print(" \tTime: " + splf.getCreateTime());
// System.out.println();
nameArrList.add(splf.getName());
numberArrList.add(splfFileNumberChar);
pagesArrList.add(splfFilePagesChar);
jobArrList.add(splf.getJobName());
userArrList.add(splf.getJobUser());
spoolUsers.add(splf.getJobUser());
jobNumberArrList.add(splf.getJobNumber());
dateArrList.add(splf.getCreateDate());
timeArrList.add(splf.getCreateTime());
// Qualified name of output queue, e.g. QGPL/QPRINT
queueArrList.add(getQualifiedQueueNameFromIfsPath(splf.getStringAttribute(SpooledFile.ATTR_OUTPUT_QUEUE)));
splfArrList.add(splf);
nameArrListWork.add(splf.getName());
numberArrListWork.add(splfFileNumberChar);
pagesArrListWork.add(splfFilePagesChar);
jobArrListWork.add(splf.getJobName());
userArrListWork.add(splf.getJobUser());
jobNumberArrListWork.add(splf.getJobNumber());
dateArrListWork.add(splf.getCreateDate());
timeArrListWork.add(splf.getCreateTime());
// Qualified name of output queue, e.g. QGPL/QPRINT
queueArrListWork.add(getQualifiedQueueNameFromIfsPath(splf.getStringAttribute(SpooledFile.ATTR_OUTPUT_QUEUE)));
splfArrListWork.add(splf);
nbrOfRows++;
}
}
}
// Ensure uniqueness of user names in array list (over linked hash set)
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.addAll(spoolUsers);
spoolUsers.clear();
spoolUsers.addAll(linkedHashSet);
// Last spooled file selected
return splf;
} catch (Exception exc) {
System.out.println("Error: " + exc.toString());
exc.printStackTrace();
return null;
}
}
use of com.ibm.as400.access.SpooledFile in project IBMiProgTool by vzupka.
the class WrkSplF method convertSpooledFile.
/**
* Read input stream and convert byte array buffers to text file (SpooledFile.txt) and to text area (spoolTextArea).
*
* @param splf
* @return
*/
@SuppressWarnings("ConvertToTryWithResources")
protected String convertSpooledFile(SpooledFile splf) {
/* String splfFileNumberChar = String.valueOf(splf.getNumber()); System.out.print("File name convertSpooledfile: "
* + splf.getName()); System.out.print(" \tFile number: " + splfFileNumberChar); System.out.print(" \tJob name: "
* + splf.getJobName()); System.out.print(" \tUser name: " + splf.getJobUser());
* System.out.print(" \tJob number: " + splf.getJobNumber()); System.out.print(" \tDate: " +
* splf.getCreateDate()); System.out.print(" \tTime: " + splf.getCreateTime()); System.out.println(); */
try {
Integer numberParInt = splf.getNumber();
PrintParameterList printParameterList = new PrintParameterList();
printParameterList.setParameter(SpooledFile.ATTR_SPOOLFILE, namePar);
printParameterList.setParameter(SpooledFile.ATTR_SPLFNUM, numberParInt);
printParameterList.setParameter(SpooledFile.ATTR_JOBNAME, jobPar);
printParameterList.setParameter(SpooledFile.ATTR_JOBUSER, userPar);
printParameterList.setParameter(SpooledFile.ATTR_JOBNUMBER, jobNumberPar);
printParameterList.setParameter(SpooledFile.ATTR_DATE, datePar);
printParameterList.setParameter(SpooledFile.ATTR_TIME, timePar);
InputStream inputStream = splf.getInputStream(printParameterList);
// Open output text file
BufferedWriter outfileText = Files.newBufferedWriter(spoolTextPath, Charset.forName(pcCharset), StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
// Create empty text area for converted lines
spoolTextArea = new JTextArea();
byte[] workBuffer = new byte[2000000];
byte[] inputBuffer = new byte[20000];
final int SINGLE_CHARACTERS = 10;
final int CLASS = 15;
final int COMMAND_CLASSES = 20;
final int PRESENTATION_POSITION = 30;
final int TRANSPARENT = 40;
final int VERTICAL_CHANNEL_SELECT = 50;
final int RVPP = 80;
final int AHPP = 90;
final int AVPP = 100;
final int RHPP = 110;
final int NBR_TRANSP_BYTES = 120;
final int VERTICAL_CHANNEL = 130;
final int CLASS_COUNTDOWN = 180;
int endPointer = 0;
int classCount = 0;
int machineState = SINGLE_CHARACTERS;
int bytesRead = inputStream.read(inputBuffer);
int currentPosInLine = 0;
// End position in line for continuation when replacing mode ends
int resumePosInLine = 0;
boolean isReplacingPrecedingBytes = false;
while (bytesRead != -1) {
for (int idx = 0; idx < bytesRead; idx++) {
byte byteRead = inputBuffer[idx];
// --------------------------------------------------------------------------------------
switch(machineState) {
case SINGLE_CHARACTERS:
{
// Skipped control characters
if (// Null
byteRead == 0x00 || // ASCII Transparency (ATRN)
byteRead == 0x01 || // ?
byteRead == 0x02 || // ?
byteRead == 0x03 || // Superscript (SPS)
byteRead == 0x09 || // Repeat (RPT)
byteRead == 0x0A || // Carriage Return (CR)
byteRead == 0x0D || // Backspace (BS)
byteRead == 0x16 || // Unit Backspace (UBS)
byteRead == 0x1A || // Word Underscore (WUS)
byteRead == 0x23 || // Switch (SW)
byteRead == 0x2A || // Bell/Stop (BEL/STP)
byteRead == 0x2F || // Numeric Backspace (NBS)
byteRead == 0x36 || // Subscript (SBS)
byteRead == 0x38) {
// System.out.print(byteToHex(byteRead));
break;
}
// ===================
if (// Required New Line (RNL)
byteRead == 0x06 || // Vertical Tab (VT)
byteRead == 0x0B || // Form Feed (FF)
byteRead == 0x0C || // New Line (NL)
byteRead == 0x15 || // Interchange Record Separator (IRE)
byteRead == 0x1E || // Line Feed/Index (LF/INX)
byteRead == 0x25 || // Index Return (IRT)
byteRead == 0x33 || // Required Form Feed/Required Page End (RFF/RFE)
byteRead == 0x3A) {
// - set pointer to the resume position.
if (isReplacingPrecedingBytes) {
// Set pointer to resume position in line
endPointer = endPointer + resumePosInLine - currentPosInLine;
// End replacing mode
isReplacingPrecedingBytes = false;
}
// Interpreted by CR and LF - Carriage Return and Line Feed
// CR
workBuffer[endPointer] = 0x0d;
endPointer++;
// LF
workBuffer[endPointer] = 0x25;
endPointer++;
currentPosInLine = 0;
break;
}
// Presentation position (34)
if (byteRead == 0x34) {
// System.out.println("Presentation Position command: " + byteToHex(byteRead));
machineState = PRESENTATION_POSITION;
break;
}
// Command classes introduced by 2B
if (byteRead == 0x2B) {
// System.out.println("B2 command classes: " + byteToHex(byteRead));
machineState = COMMAND_CLASSES;
break;
}
// --------------------
if (byteRead >= 0x40 || byteRead < 0xf9 || // Substitute (SUB)
byteRead == 0x3f) {
// System.out.print(byteToHex(byteRead));
if (byteRead == 0x3f) {
workBuffer[endPointer] = 0x40;
} else {
workBuffer[endPointer] = byteRead;
}
endPointer++;
currentPosInLine++;
break;
}
// Horizontal tab (HT)
if (// Horizontal Tab (HT)
byteRead == 0x05) {
// This command is not used by Twinax
break;
}
// Indent tab (IT)
if (// Indent tab (IT)
byteRead == 0x39) {
// This command is not used by Twinax
break;
}
// Transparent (TRN)
if (byteRead == 0x35) {
// System.out.print("TRN Transparent tab: " + byteToHex(byteRead));
// System.out.print(byteToHex(byteRead));
machineState = TRANSPARENT;
break;
}
// Vertical Channel Select (VCS)
if (byteRead == 0x04) {
// System.out.print("VCS Vertical Channel Select: " + byteToHex(byteRead));
// System.out.print(byteToHex(byteRead));
// Interpreted by CR and LF - Carriage Return and Line Feed
// CR
workBuffer[endPointer] = 0x0d;
endPointer++;
// LF
workBuffer[endPointer] = 0x25;
endPointer++;
machineState = VERTICAL_CHANNEL_SELECT;
break;
}
break;
}
case PRESENTATION_POSITION:
{
// Cast to *byte* is important because some types are negative numbers!
if (// Relative Vertical Presentation Position (RVPP)
byteRead == (byte) 0x4c) {
machineState = RVPP;
break;
} else if (// Absolute Horizontal Presentation Position (AHPP)
byteRead == (byte) 0xc0) {
machineState = AHPP;
break;
} else if (// Absolute Vertical Presentation Position (AVPP)
byteRead == (byte) 0xc4) {
machineState = AVPP;
break;
} else if (// Relative Horizontal Presentation Position (RHPP)
byteRead == (byte) 0xc8) {
machineState = RHPP;
break;
} else {
// System.out.println("Invalid Presentation position type: " + byteToHex(byteRead));
}
break;
}
case RVPP:
{
// Insert (count - 1) new lines
for (int cnt = 0; cnt < byteRead - 1; cnt++) {
// Interpreted by CR and LF - Carriage Return and Line Feed
// CR
workBuffer[endPointer] = 0x0d;
endPointer++;
// LF
workBuffer[endPointer] = 0x25;
endPointer++;
}
machineState = SINGLE_CHARACTERS;
break;
}
case AHPP:
{
// - insert new line and reset the last position in line to zero (start of line)
if (unsignedByteToInt(byteRead) < currentPosInLine) {
// Begin replacing mode in which already written bytes in the work buffer
// are being replaced by new bytes read from input.
isReplacingPrecedingBytes = true;
// Remember the current position in the line as a new beginning for adding bytes
// after the replacing mode ends.
resumePosInLine = currentPosInLine;
// Set pointer back to the work buffer where already written text in the line began
endPointer = endPointer - currentPosInLine + byteRead - 1;
// Set new last posiion in line to the first presentation position in the line
currentPosInLine = byteRead;
} else {
// Add RELATIVE number of spaces (absolute presentation position - currentPosInLine)
int numberOfSpaces = unsignedByteToInt(byteRead) - currentPosInLine - 1;
for (int cnt = 0; cnt < numberOfSpaces; cnt++) {
// Insert a space
workBuffer[endPointer] = 0x40;
endPointer++;
}
// Increment current position in line by the number of added spaces
currentPosInLine += numberOfSpaces;
}
machineState = SINGLE_CHARACTERS;
break;
}
case AVPP:
{
// because the count is usually 01
for (int cnt = 0; cnt < byteRead + 2; cnt++) {
// Interpreted by CR and LF - Carriage Return and Line Feed
// CR
workBuffer[endPointer] = 0x0d;
endPointer++;
// LF
workBuffer[endPointer] = 0x25;
endPointer++;
}
machineState = SINGLE_CHARACTERS;
break;
}
case RHPP:
{
// Insert (count -1) spaces (assume that RHPP is a positive number)
for (int cnt = 0; cnt < byteRead - 1; cnt++) {
// Interpret by inserting a space
workBuffer[endPointer] = 0x40;
endPointer++;
}
machineState = SINGLE_CHARACTERS;
break;
}
case TRANSPARENT:
{
// System.out.print(byteToHex(byteRead));
// Next byte will be skipped - number of bytes following this command
// not to be checked for printed datastream commands
machineState = NBR_TRANSP_BYTES;
break;
}
case NBR_TRANSP_BYTES:
{
// System.out.print(byteToHex(byteRead));
// No operation will be done (but machineState changed)
machineState = SINGLE_CHARACTERS;
break;
}
case VERTICAL_CHANNEL_SELECT:
{
// System.out.print(byteToHex(byteRead));
machineState = VERTICAL_CHANNEL;
break;
}
case VERTICAL_CHANNEL:
{
// System.out.print(byteToHex(byteRead));
// Vertical channel ID
// X'7A' = 10
// X'7B' = 11
// X'7C' = 12
// X'81' = 1
// X'82' = 2
// X'83' = 3
// X'84' = 4
// X'85' = 5
// X'86' = 6
// X'87' = 7
// X'88' = 8
// X'89' = 9
// Interpreted by CR and LF - Carriage Return and Line Feed
// CR
workBuffer[endPointer] = 0x0d;
endPointer++;
// LF
workBuffer[endPointer] = 0x25;
endPointer++;
machineState = SINGLE_CHARACTERS;
break;
}
case COMMAND_CLASSES:
{
// System.out.println("Class: " + byteToHex(byteRead));
// hexLine += byteToHex(byteRead);
machineState = CLASS;
break;
}
case CLASS:
{
// System.out.print(byteToHex(byteRead));
// This byte is the number (count) of this and following bytes.
// Save the count for later comparison.
classCount = byteRead;
// System.out.println("Class count = " + classCount);
machineState = CLASS_COUNTDOWN;
break;
}
case CLASS_COUNTDOWN:
{
// System.out.print(byteToHex(byteRead));
// Decrement class count and compare if greater than zero
classCount--;
if (classCount > 0) {
// System.out.println("Class count = " + classCount);
machineState = CLASS_COUNTDOWN;
} else {
// System.out.println("Class Countdown 0");
machineState = SINGLE_CHARACTERS;
}
break;
}
default:
{
// System.out.println("\nUNKNOWN CONTROL CHARACTER! " + byteToHex(byteRead));
}
}
// end switch
// This is the end of the state machine
}
// end for
// System.out.println("\n FIRST BYTE: " + byteToHex(inputBuffer[0]));
// Copy the printable part of the work array (up to *endPointer* position)
// to a new buffer that will be written out.
byte[] bufferToWrite = new byte[endPointer];
// Copy bytes from the work buffer to the new buffer
for (int indx = 0; indx < endPointer; indx++) {
bufferToWrite[indx] = workBuffer[indx];
}
// Create object for conversion from bytes to characters
AS400Text textConverter = new AS400Text(endPointer, ibmCcsidInt, remoteServer);
// int CCSID = textConverter.getCcsid();
// System.out.println(" CCSID: " + CCSID);
// Convert byte array buffer to text line
String textLine = (String) textConverter.toObject(bufferToWrite);
// System.out.println(textLine);
// Write text line to the text file
outfileText.write(textLine);
// Write text line to text area
spoolTextArea.append(textLine);
// Read next input buffer
bytesRead = inputStream.read(inputBuffer);
// Reset pointer in work buffer so it points to the beginning
endPointer = 0;
}
// Close files
inputStream.close();
outfileText.close();
row = "Info: Spooled file characters were converted using CCSID " + ibmCcsid + ".";
mainWindow.msgVector.add(row);
// do not add child nodes
mainWindow.showMessages(noNodes);
mainWindow.scrollMessagePane.getVerticalScrollBar().removeAdjustmentListener(mainWindow.messageScrollPaneAdjustmentListenerMax);
return spoolTextArea.getText();
} catch (Exception exc) {
System.out.println("Error: " + exc.toString());
exc.printStackTrace();
row = "Error: Spooled file CCSID '" + ibmCcsid + "' or text file character set '" + pcCharset + "' is not correct. - " + exc.toString();
mainWindow.msgVector.add(row);
row = "Set \"IBM i CCSID\" to 65535 and press button \"Spooled file\" to display the spooled file again.";
mainWindow.msgVector.add(row);
// do not add child nodes
mainWindow.showMessages(noNodes);
mainWindow.scrollMessagePane.getVerticalScrollBar().removeAdjustmentListener(mainWindow.messageScrollPaneAdjustmentListenerMax);
return "ERROR";
}
}
use of com.ibm.as400.access.SpooledFile in project IBMiProgTool by vzupka.
the class WrkSplFCall method displayLastSpooledFile.
/**
* Get the last from the list of all spooled files.
*/
protected void displayLastSpooledFile() {
// Change cursor to wait cursor
mainWindow.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
// Resulting splf is the last from the list of all spooled files belonging to the current user.
SpooledFile splf = wrkSplf.selectSpooledFiles("", "", "", userPar, "", "", "", "");
String spoolTextAreaString = wrkSplf.convertSpooledFile(splf);
JTextArea textArea = new JTextArea();
DisplayFile dspf = new DisplayFile(textArea, mainWindow);
dspf.displayTextArea(spoolTextAreaString, ibmCcsid);
// Change cursor to default
mainWindow.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
// Remove message scroll listener (cancel scrolling to the last message)
mainWindow.scrollMessagePane.getVerticalScrollBar().removeAdjustmentListener(mainWindow.messageScrollPaneAdjustmentListenerMax);
}
use of com.ibm.as400.access.SpooledFile in project IBMiProgTool by vzupka.
the class WrkSplF method convertSpooledFile2.
/**
* Read and transform spooled file data using automatic conversion;
*
* This method is not used because it does not give satisfying results:
* - Does not render non-ASCII characteres, they are replaced by a substitute character
* - Headings are sometimes incorrectly formatted (not on the next line)
*
* @param splf
* @return
*/
protected String convertSpooledFile2(SpooledFile splf) {
try {
Integer numberParInt = new Integer(numberPar);
PrintParameterList printParameterList = new PrintParameterList();
printParameterList.setParameter(SpooledFile.ATTR_SPOOLFILE, namePar);
printParameterList.setParameter(SpooledFile.ATTR_SPLFNUM, numberParInt);
printParameterList.setParameter(SpooledFile.ATTR_JOBNAME, jobPar);
printParameterList.setParameter(SpooledFile.ATTR_JOBUSER, userPar);
printParameterList.setParameter(SpooledFile.ATTR_JOBNUMBER, jobNumberPar);
printParameterList.setParameter(SpooledFile.ATTR_DATE, datePar);
printParameterList.setParameter(SpooledFile.ATTR_TIME, timePar);
printParameterList.setParameter(PrintObject.ATTR_MFGTYPE, "*WSCST");
printParameterList.setParameter(PrintObject.ATTR_WORKSTATION_CUST_OBJECT, "/QSYS.LIB/QWPDEFAULT.WSCST");
// Read the spooled file attributes for determining if it is AFPDS or SCS type spool file
String stringAttribute = splf.getStringAttribute(PrintObject.ATTR_PRTDEVTYPE);
if ((stringAttribute != null) && (stringAttribute.equals("*AFPDS"))) {
// Not applicable
} else if ((stringAttribute != null) && (stringAttribute.equals("*SCS"))) {
PrintObjectTransformedInputStream inputStream = splf.getTransformedInputStream(printParameterList);
System.out.println(splf.getStringAttribute(PrintObject.ATTR_CODEPAGE));
// Read the input stream buffer and create a string buffer
byte[] bytes = new byte[32767];
StringBuilder buffer = new StringBuilder();
// int bytesRead = 0;
int bytesRead = inputStream.read(bytes);
while (bytesRead >= 0) {
bytesRead = inputStream.read(bytes);
// System.out.println(bytesRead);
if (bytesRead > 0) {
buffer.append(new String(bytes, 0, bytesRead));
}
}
// System.out.println(buffer);
spoolTextArea = new JTextArea(buffer.toString());
}
} catch (Exception exc) {
exc.printStackTrace();
return "ERROR";
}
return "";
}
Aggregations