/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE
* or https://OpenDS.dev.java.net/OpenDS.LICENSE.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at
* trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
* add the following below this CDDL HEADER, with the fields enclosed
* by brackets "[]" replaced with your own identifying information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Portions Copyright 2009 Sun Microsystems, Inc.
*/
package com.ibm.staf.service.opends;
import com.ibm.staf.*;
import com.ibm.staf.wrapper.*;
import com.ibm.staf.service.*;
import com.ibm.staf.service.opends.tester.*;
import java.util.*;
import java.io.*;
import java.util.ArrayList;
/**
* DSML Staf service
* it allows :
* - to test one or multiple DSEE DSML suite testcases (TODO)
* - compare testcase result against expected result
*/
public class DSMLService implements STAFServiceInterfaceLevel30 {
private static final String OP_COMPARE = "COMPARE";
private static final String OP_CHECK_ERROR_STRINGS = "CHECK_ERROR_STRINGS";
private static final String OP_HELP = "HELP";
private static final String OP_FILE = "FILE";
private static final String OP_EXP_FILE = "EXP_FILE";
private static final String OP_ISSUE_FILE = "ISSUE_FILE";
private static final String OP_DIR = "DIR";
private static final String OP_EXP_DIR = "EXP_DIR";
private final String MATCH = " matches ";
private final String DIFFER = " differs from ";
private String fServiceName;
private STAFHandle fHandle;
private String fLocalMachineName = "";
private STAFLog logger = null;
// Define any error codes unique to this service
private static final int kDSMLInvalidSomething = 4001;
private static final int kErrorStringMatchOffset = 100000000;
// STAFCommandParsers for each request
private STAFCommandParser fParser;
private String fLineSep;
public STAFResult init(STAFServiceInterfaceLevel30.InitInfo info) {
try {
fServiceName = info.name;
fHandle = new STAFHandle("STAF/Service/" + info.name);
logger = new STAFLog(STAFLog.HANDLE, "dsmlLog", fHandle,
STAFLog.Fatal | STAFLog.Error | STAFLog.Warning);
} catch (STAFException e) {
return new STAFResult(STAFResult.STAFRegistrationError,
e.toString());
}
// COMPARE parser
fParser = new STAFCommandParser(0, false);
fParser.addOption(OP_COMPARE, 1, STAFCommandParser.VALUENOTALLOWED);
fParser.addOption(OP_FILE, 1, STAFCommandParser.VALUEREQUIRED);
fParser.addOption(OP_DIR, 1, STAFCommandParser.VALUEREQUIRED);
fParser.addOption(OP_EXP_FILE, 1, STAFCommandParser.VALUEREQUIRED);
fParser.addOption(OP_EXP_DIR, 1, STAFCommandParser.VALUEREQUIRED);
// if you specify COMPARE, RESULT_FILE is required
fParser.addOptionNeed(OP_EXP_FILE, OP_FILE);
fParser.addOptionNeed(OP_EXP_DIR, OP_DIR);
fParser.addOptionNeed(OP_COMPARE, OP_EXP_FILE + " " + OP_EXP_DIR);
fParser.addOptionNeed(OP_EXP_FILE + " " + OP_EXP_DIR, OP_COMPARE);
// CHECK_ERROR_STRINGS parser
fParser.addOption(OP_CHECK_ERROR_STRINGS, 1, STAFCommandParser.VALUENOTALLOWED);
fParser.addOptionNeed(OP_CHECK_ERROR_STRINGS, OP_FILE);
STAFResult res = new STAFResult();
// Resolve the line separator variable for the local machine
res = STAFUtil.resolveInitVar("{STAF/Config/Sep/Line}", fHandle);
if (res.rc != STAFResult.Ok) {
return res;
}
fLineSep = res.result;
// Resolve the machine name variable for the local machine
res = STAFUtil.resolveInitVar("{STAF/Config/Machine}", fHandle);
if (res.rc != STAFResult.Ok) {
return res;
}
fLocalMachineName = res.result;
// Register Help Data
registerHelpData(
kDSMLInvalidSomething + 1,
"Invalid input",
"missing or wrong input files for results or expected results");
return new STAFResult(STAFResult.Ok);
}
public STAFResult acceptRequest(STAFServiceInterfaceLevel30.RequestInfo info) {
//delegate the request handling
StringTokenizer requestTokenizer = new StringTokenizer(info.request);
String request = requestTokenizer.nextToken().toLowerCase();
// call the appropriate method to handle the command
if (request.equalsIgnoreCase(OP_COMPARE)) {
return handleCompare(info);
} else if (request.equalsIgnoreCase(OP_CHECK_ERROR_STRINGS)) {
return handleCheckErrorStrings(info);
} else if (request.equalsIgnoreCase(OP_HELP)) {
return handleHelp(info);
} else {
return handleInvalidRequest(info);
}
}
public STAFResult term() {
logger.log(STAFLog.Warning, "termination initiated");
try {
// Un-register Help Data
unregisterHelpData(kDSMLInvalidSomething + 2);
// Un-register the service handle
fHandle.unRegister();
} catch (STAFException ex) {
return new STAFResult(STAFResult.STAFRegistrationError,
ex.toString());
}
return new STAFResult(STAFResult.Ok);
}
private STAFResult handleCheckErrorStrings(STAFServiceInterfaceLevel30.RequestInfo info) {
// default return will be kDSMLInvalidSomething + 14 marking that
// no known error string match the erroneous expected file content.
STAFResult sr = new STAFResult(kDSMLInvalidSomething + 14);
STAFCommandParseResult parsedRequest = fParser.parse(info.request);
if (parsedRequest.rc != STAFResult.Ok) {
return new STAFResult(STAFResult.InvalidRequestString,
parsedRequest.errorBuffer);
}
String resultFile = parsedRequest.optionValue(OP_FILE);
Properties errProps = new Properties();
final String RE = ".r";
final String lblMarker = "_";
try {
ClassLoader cl = this.getClass().getClassLoader();
InputStream in = cl.getResourceAsStream("errorStrings.properties");
errProps.load(in);
in.close();
Enumeration errEnum = errProps.propertyNames();
while (errEnum.hasMoreElements()) {
String k = (String) errEnum.nextElement();
String issueID = null;
String lbl = null;
boolean re = k.endsWith(RE);
int lblNdx = k.indexOf(lblMarker);
if (lblNdx != -1) {
if (re) {
lbl = k.substring(lblNdx + 1, k.length() - RE.length());
} else {
lbl = k.substring(lblNdx + 1);
}
}
if (lblNdx != -1) {
issueID = k.substring(0, lblNdx);
} else if (re) {
issueID = k.substring(0, k.length() - RE.length());
} else {
issueID = k;
}
String v = errProps.getProperty(k);
BufferedReader rbr = new BufferedReader(new FileReader(resultFile));
String line = "";
while ((line = rbr.readLine()) != null) {
if (re) {
if (line.matches(v)) {
sr = new STAFResult(kErrorStringMatchOffset +
Integer.parseInt(issueID),""+lbl+line);
}
} else {
if (line.indexOf(v) != -1) {
sr = new STAFResult(kErrorStringMatchOffset +
Integer.parseInt(issueID),""+lbl+line);
break;
}
}
}
}
} catch (FileNotFoundException fnfe) {
sr.rc = kDSMLInvalidSomething + 11;
sr.result = fnfe.getMessage();
} catch (IOException ioe) {
sr.rc = kDSMLInvalidSomething + 12;
sr.result = ioe.getMessage();
} catch (Exception e) {
sr.rc = kDSMLInvalidSomething + 13;
sr.result = e.getMessage();
}
return sr;
}
private STAFResult handleCompare(STAFServiceInterfaceLevel30.RequestInfo info) {
STAFResult sr = new STAFResult(0);
//parse the input request
STAFCommandParseResult parsedRequest = fParser.parse(info.request);
if (parsedRequest.rc != STAFResult.Ok) {
return new STAFResult(STAFResult.InvalidRequestString,
parsedRequest.errorBuffer);
}
// Resolve any STAF variables in the DIR option's value
STAFResult res = new STAFResult();
String file = parsedRequest.optionValue(OP_FILE);
String exp_file = parsedRequest.optionValue(OP_EXP_FILE);
String dir = parsedRequest.optionValue(OP_DIR);
String exp_dir = parsedRequest.optionValue(OP_EXP_DIR);
if (dir != null && dir.trim().length() > 0) {
sr = handleCompareDir(exp_dir, dir);
}
if (file != null && file.trim().length() > 0) {
sr = handleCompareFile(exp_file, file);
}
return sr;
}
/*
* It's expected that the result and expected result file have the same
* file path up to the file extension.
* expected result having extension ".res"
* result to be compared to expected result ".run"
* The filePath should exclude the file extension
* for ex a file like /tmp/add000.res the filePath expected is /tmp/add000
*/
private STAFResult handleCompareFile(String exp_file, String file) {
STAFResult sr = new STAFResult(STAFResult.Ok);
logger.log(STAFLog.Warning,
"handle File compare for exp_file=[" + exp_file + "], file=[" + file + "]");
if (!(exp_file.endsWith(DSMLFileFilter.EXPECTED_FILE_EXTENSION) || exp_file.endsWith(DSMLFileFilter.ISSUE_FILE_EXTENSION))) {
sr.rc = STAFResult.FileReadError;
sr.result = "invalid input " + exp_file + " should end with " +
DSMLFileFilter.EXPECTED_FILE_EXTENSION + " or " +
DSMLFileFilter.ISSUE_FILE_EXTENSION;
} else if (!file.endsWith(DSMLFileFilter.RUN_FILE_EXTENSION)) {
sr.rc = STAFResult.FileReadError;
sr.result = "invalid input " + file + " should end with " + DSMLFileFilter.RUN_FILE_EXTENSION;
} else {
File expectedFile, resultFile;
// read the result and expected content files, and compare theme
try {
expectedFile = new File(exp_file);
resultFile = new File(file);
String line;
//reading result into ArrayList of POST results
BufferedReader resultBuffReader = new BufferedReader(new FileReader(resultFile));
ArrayList rl = new ArrayList();
StringBuffer resultContent = new StringBuffer();
int ln = 0;
while ((line = resultBuffReader.readLine()) != null) {
if (line.startsWith("HTTP") && ln > 0) {
rl.add(resultContent);
resultContent = new StringBuffer(line + "\n");
} else {
resultContent.append(line + "\n");
}
ln++;
}
rl.add(resultContent.toString());
resultBuffReader.close();
//reading expected result of POST results
BufferedReader expectedBufferReader = new BufferedReader(new FileReader(expectedFile));
ArrayList erl = new ArrayList();
StringBuffer expectedContent = new StringBuffer();
ln = 0;
while ((line = expectedBufferReader.readLine()) != null) {
if (line.startsWith("HTTP") && ln > 0) {
erl.add(expectedContent);
expectedContent = new StringBuffer(line + "\n");
} else {
expectedContent.append(line + "\n");
}
ln++;
}
erl.add(expectedContent.toString());
expectedBufferReader.close();
if (rl.size() != erl.size()) {
sr.rc = kDSMLInvalidSomething + 3;
sr.result = "number of results " +
resultFile + "[" + rl.size() + "]" +
expectedFile + "[" + erl.size() + "]";
} else {
boolean identical = true;
for (int i = 0; i < rl.size(); i++) {
//starting from 1, because the first is always empty
identical &= compareResults((String) erl.get(i), (String) rl.get(i));
logger.log(STAFLog.Warning, "comparing\n" + (String) erl.get(i) + "\nwith\n" + (String) rl.get(i));
if (identical) {
// success
sr.rc = STAFResult.Ok;
sr.result = resultFile + MATCH + expectedFile;
} else {
logger.log(STAFLog.Error, "exp_file=[" + exp_file + "] " +
"differ from file=[" + file + "]");
sr.rc = kDSMLInvalidSomething + 4;
sr.result = resultFile + DIFFER + expectedFile;
break;
}
}
}
} catch (FileNotFoundException fnfe) {
sr.rc = kDSMLInvalidSomething + 5;
sr.result = fnfe.getMessage();
} catch (IOException ioe) {
sr.rc = kDSMLInvalidSomething + 6;
sr.result = ioe.getMessage();
} catch (Exception e) {
sr.rc = kDSMLInvalidSomething + 7;
sr.result = e.getMessage();
}
}
return sr;
}
private STAFResult handleCompareDir(String exp_dir, String run_dir) {
logger.log(STAFLog.Warning,
"handle Directory comparaison exp_dir[" + exp_dir + "],dir[" + run_dir + "]");
File expDirFile;
File runDirFile;
STAFResult sr = new STAFResult(STAFResult.Ok);
try {
expDirFile = new File(exp_dir);
runDirFile = new File(run_dir);
ArrayList test_a = new ArrayList();
ArrayList missing_e = new ArrayList();
ArrayList missing_r = new ArrayList();
if (expDirFile.isDirectory() && runDirFile.isDirectory()) {
// find all the files with extension ".res"
File[] eFiles = expDirFile.listFiles(new DSMLFileFilter(DSMLFileFilter.EXPECTED_FILE_EXTENSION));
ArrayList ea = new ArrayList(eFiles.length);
String eName;
for (int ei = 0; ei < eFiles.length; ei++) {
eName = eFiles[ei].getName();
eName = eName.substring(0, eName.lastIndexOf(DSMLFileFilter.EXPECTED_FILE_EXTENSION));
ea.add(eName);
}
// find all the files with extension ".run"
File[] rFiles = runDirFile.listFiles(new DSMLFileFilter(DSMLFileFilter.RUN_FILE_EXTENSION));
ArrayList ra = new ArrayList(rFiles.length);
String rName;
for (int ri = 0; ri < rFiles.length; ri++) {
rName = rFiles[ri].getName();
rName = rName.substring(0, rName.lastIndexOf(DSMLFileFilter.RUN_FILE_EXTENSION));
ra.add(rName);
if (!ea.contains(rName)) {
// get a run file not matching expected result
missing_e.add(rName);
} else {
// expected and run file are both present
test_a.add(rName);
}
}
// find the missing result file and remove from test_a
for (int i = 0; i < ea.size(); i++) {
String e = (String) ea.get(i);
if (!ra.contains(e)) {
missing_r.add(e);
}
}
// loop through the test set test_a and compare the files
for (int i = 0; i < test_a.size(); i++) {
String tf = (String) test_a.get(i);
sr = handleCompareFile(
exp_dir + File.separator + tf + DSMLFileFilter.EXPECTED_FILE_EXTENSION,
run_dir + File.separator + tf + DSMLFileFilter.RUN_FILE_EXTENSION);
}
} else {
logger.log(STAFLog.Warning, "Directory comparaison with invalid input dir : " + exp_dir);
sr.rc = kDSMLInvalidSomething + 8;
sr.result = "Directory comparaison with invalid input dir : " + exp_dir;
}
} catch (Exception e) {
sr.rc = kDSMLInvalidSomething + 9;
sr.result = e.getMessage();
}
return sr;
}
private boolean compareResults(String expectedResult, String result) throws Exception {
ResponseChecker dsmlReponse = null;
ResponseChecker expectedReponse = null;
//System.out.println("result\n" + result);
try {
dsmlReponse = new ResponseChecker(result);
} catch (Exception e) {
if (e.getCause() != null) {
e.printStackTrace();
throw (new Exception("Response parsing error: " + e.getCause().getMessage()));
} else {
e.printStackTrace();
throw (new Exception("Response parsing error: " + e.getMessage()));
}
}
try {
expectedReponse = new ResponseChecker(expectedResult);
} catch (Exception e) {
if (e.getCause() != null) {
throw (new Exception("Parsing error for expected result : " + e.getCause().getMessage()));
} else {
throw (new Exception("Parsing error for expected result : " + e.getMessage()));
}
}
try {
return (dsmlReponse.equals(expectedReponse));
} catch (Exception e) {
logger.log(STAFLog.Warning, "failed comparing DSML responses exception " + e.getMessage());
return false;
}
}
private STAFResult handleInvalidRequest(STAFServiceInterfaceLevel30.RequestInfo info) {
logger.log(STAFLog.Error, "invalid request : [" + info.request + "]");
STAFResult sr = new STAFResult(kDSMLInvalidSomething + 10);
sr.result = info.request;
return sr;
}
private STAFResult handleHelp(STAFServiceInterfaceLevel30.RequestInfo info) {
// Verify the requester has at least trust level 1
STAFResult trustResult = STAFUtil.validateTrust(
1, fServiceName, "HELP", fLocalMachineName, info);
if (trustResult.rc != STAFResult.Ok) {
return trustResult;
}
// Return help text for the service
return new STAFResult(
STAFResult.Ok,
"DSML Service Help :" + fLineSep + fLineSep + OP_COMPARE + "(" +
OP_EXP_FILE + " filename " + OP_FILE + " filename " + " | " +
OP_EXP_DIR + " dirname " + OP_DIR + " dirname )" +
fLineSep + OP_CHECK_ERROR_STRINGS + " " + OP_FILE + " filename " +
fLineSep + OP_HELP);
}
// Register error codes for the STAX Service with the HELP service
private void registerHelpData(int errorNumber, String info,
String description) {
//TODO
}
// Un-register error codes for the STAX Service with the HELP service
private void unregisterHelpData(int errorNumber) {
//TODO
}
private class DSMLFileFilter implements FilenameFilter {
public static final String EXPECTED_FILE_EXTENSION = ".res";
public static final String ISSUE_FILE_EXTENSION = ".issue";
public static final String RUN_FILE_EXTENSION = ".run";
public static final String INPUT_FILE_EXTENSION = ".dat";
private ArrayList extList;
private String exclusiveExtension;
DSMLFileFilter() {
extList = new ArrayList();
exclusiveExtension = null;
extList.add(EXPECTED_FILE_EXTENSION);
extList.add(ISSUE_FILE_EXTENSION);
extList.add(RUN_FILE_EXTENSION);
extList.add(INPUT_FILE_EXTENSION);
}
DSMLFileFilter(String ext) {
exclusiveExtension = ext;
}
public boolean accept(File dir, String name) {
int li = name.lastIndexOf(".");
if (li > 0) {
if (exclusiveExtension != null) {
//comparing file name extension with exclusively one extension
if (name.substring(li).equals(exclusiveExtension)) {
return ((new File(dir + File.separator + name)).isFile());
} else {
return false;
}
} else {
// compare file name extension
if (extList.contains(name.substring(li))) {
return ((new File(dir + File.separator + name)).isFile());
} else {
return false;
}
}
} else {
return false;
}
}
}
}