public class SOAPClient implements Runnable {
/*
* endpoint url, the address where soap xml will be sent. It is hard coded
* now, later on to be made configurable
*/
private String endpointUrl = "";
/*
* This is for debugging purposes Message and response are written to the
* fileName
*/
static String fileName = "";
/*
* serverResponse This is a string representation of the response received
* from server
*/
private String serverResponse = null;
public String tempTestStringForDirectory = "";
/*
* A single file or a folder maybe provided
*/
private File fileOrFolder;
public SOAPClient(String endpointURL, File fileOrFolder) {
this.endpointUrl = endpointURL;
this.fileOrFolder = fileOrFolder;
serverResponse = null;
}
/*
* Creats a SOAPMessage out of a file that is passed
*
* @param fileAddress - Contents of this file are read and a SOAPMessage is
* created that will get sent to the server. This is a helper method. Is
* this step (method, conversion) necessary? set tempSoapText = XML String,
* currently getting from file, but it can be a simple string
*/
private SOAPMessage xmlStringToSOAPMessage(String fileAddress) {
System.out.println("xmlStringToSoap()");
// Picking up this string from file right now
// This can come from anywhere
String tempSoapText = readFileToString(fileAddress);
SOAPMessage soapMessage = null;
try {
// Create SoapMessage
MessageFactory msgFactory = MessageFactory.newInstance();
SOAPMessage message = msgFactory.createMessage();
SOAPPart soapPart = message.getSOAPPart();
// Load the SOAP text into a stream source
byte[] buffer = tempSoapText.getBytes();
ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
StreamSource source = new StreamSource(stream);
ByteArrayOutputStream out = new ByteArrayOutputStream();
// Set contents of message
soapPart.setContent(source);
message.writeTo(out);
soapMessage = message;
} catch (SOAPException e) {
System.out.println("soapException xmlStringToSoap()");
System.out.println("SOAPException : " + e);
} catch (IOException e) {
System.out.println("IOException xmlStringToSoap()");
System.out.println("IOException : " + e);
}
return soapMessage;
}
/*
* Reads the file passed and creates a string. fileAddress - Contents of
* this file are read into a String
*/
private String readFileToString(String fileAddress) {
FileInputStream stream = null;
MappedByteBuffer bb = null;
String stringFromFile = "";
try {
stream = new FileInputStream(new File(fileAddress));
FileChannel fc = stream.getChannel();
bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
stringFromFile = Charset.defaultCharset().decode(bb).toString();
} catch (IOException e) {
System.out.println("readFileToString IOException");
e.printStackTrace();
} finally {
try {
stream.close();
} catch (IOException e) {
System.out.println("readFileToString IOException");
e.printStackTrace();
}
}
return stringFromFile;
}
/*
* soapXMLtoEndpoint sends the soapXMLFileLocation to the endpointURL
*/
public void soapXMLtoEndpoint(String endpointURL, String soapXMLFileLocation) throws SOAPException {
SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
SOAPMessage response = connection.call(xmlStringToSOAPMessage(soapXMLFileLocation), endpointURL);
connection.close();
SOAPBody responseBody = response.getSOAPBody();
SOAPBodyElement responseElement = (SOAPBodyElement) responseBody.getChildElements().next();
SOAPElement returnElement = (SOAPElement) responseElement.getChildElements().next();
if (responseBody.getFault() != null) {
System.out.println("fault != null");
System.out.println(returnElement.getValue() + " " + responseBody.getFault().getFaultString());
} else {
serverResponse = returnElement.getValue();
System.out.println(serverResponse);
System.out.println("\nfault == null, got the response properly.\n");
}
}
/*
* This is for debugging purposes. Writes string to a file.
*
* @param message Contents to be written to file
*
* @param fileName the name of the
*/
private static void toFile(String message, String fileName) {
try {
FileWriter fstream = new FileWriter(fileName);
System.out.println("printing to file: ".concat(fileName));
BufferedWriter out = new BufferedWriter(fstream);
out.write(message);
out.close();
} catch (Exception e) {
System.out.println("toFile() Exception");
System.err.println("Error: " + e.getMessage());
}
}
/*
* Using dom to parse the xml. Getting both orderID and the description.
*
* @param xmlToParse XML in String format to parse. Gets the orderID and
* description Is the error handling required? What if orderID or
* description isn't found in the xmlToParse? Use setters and getters?
*
* @param fileName only for debuggining, it can be safely removed any time.
*/
private void domParsing(String xmlToParse, String fileName) {
if (serverResponse == null) {
return;
} else {
try {
System.out.println("in domParsing()");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
System.out.println("serverResponse contains fault");
Document doc = dBuilder.parse(new InputSource(new StringReader(serverResponse)));
doc.getDocumentElement().normalize();
NodeList orderNodeList = doc.getElementsByTagName("Order");
if (orderNodeList.getLength() > 0) {
tempTestStringForDirectory = tempTestStringForDirectory + "\n Got order\n" + "\n" + fileName + "\n" + "got order\n";
for (int x = 0; x < orderNodeList.getLength(); x++) {
System.out.println(orderNodeList.item(x).getAttributes().getNamedItem("orderId").getNodeValue());
}
}
NodeList descriptionNodeList = doc.getElementsByTagName("Description");
if (descriptionNodeList.getLength() > 0) {
System.out.println("getting description");
String tempDescriptionString = descriptionNodeList.item(0).getTextContent();
System.out.println(tempDescriptionString);
tempTestStringForDirectory = tempTestStringForDirectory + "\n Got description" + "\n" + fileName + "\n" + tempDescriptionString + "\n";
}
} catch (Exception e) {
System.out.println("domParsing() Exception");
e.printStackTrace();
}
}
}
/*
* Reads a single file or a whole directory structure
*/
private void listFilesForFolder(final File fileOrFolder) {
String temp = "";
if (fileOrFolder.isDirectory()) {
for (final File fileEntry : fileOrFolder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
if (fileEntry.isFile()) {
temp = fileEntry.getName();
try {
soapXMLtoEndpoint(endpointUrl, fileOrFolder.getAbsolutePath() + "\\" + fileEntry.getName());
domParsing(serverResponse, fileEntry.getName());
} catch (SOAPException e) {
e.printStackTrace();
}
}
}
}
}
if (fileOrFolder.isFile()) {
temp = fileOrFolder.getName();
System.out.println("this is a file");
System.out.println(temp);
try {
soapXMLtoEndpoint(endpointUrl, fileOrFolder.getAbsolutePath());
} catch (SOAPException e) {
e.printStackTrace();
}
domParsing(serverResponse, temp);
}
}
@Override
public void run() {
listFilesForFolder(fileOrFolder);
toFile(tempTestStringForDirectory, "test.txt");
}
public static void main(String[] args) {
String tempURLString = ".../OrderingService";
String tempFileLocation = "C:/Workspace2/Test5/";
SOAPClient soapClient = new SOAPClient(tempURLString, new File(tempFileLocation));
Thread thread = new Thread(soapClient);
thread.start();
System.out.println("program ended");
}
}
我认为 n 个文件的 n 个线程会很糟糕?那不会使系统崩溃,或者给太多线程错误吗?我正在尝试使我的程序多线程。我不知道我错过了什么。我的程序有一个逻辑可以知道是传递了单个文件还是传递了目录。如果传递一个文件,一个线程就可以了。但是如果一个目录通过了怎么办?我需要在我的 listFilesForFolder 方法中创建线程吗?线程总是从 main 方法启动,还是可以从其他方法启动?另外,这个程序会被其他人使用,所以正确处理线程应该是我的工作。他们所要做的就是使用我的程序。所以我觉得线程逻辑不应该属于main方法,而应该属于listFilesForFolder,这是我程序的起点。