at.spardat.xma.pipes.WindowsPipe Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2003, 2007 s IT Solutions AT Spardat GmbH .
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* s IT Solutions AT Spardat GmbH - initial API and implementation
*******************************************************************************/
/*
* @(#) $Id: WindowsPipe.java 2089 2007-11-28 13:56:13Z s3460 $
*
*
*
*
*
*/
package at.spardat.xma.pipes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import at.spardat.xma.boot.natives.Pipes;
/**
* @author s3460
* @since version_number
*/
public class WindowsPipe extends XMAPipe {
//private static final String PIPE_PATH = "\\\\.\\pipe\\";
private static final int BUFFER_SIZE = 4096;
private int pipeHandle;
WindowsPipe(String pipeName) throws IOException {
//super(PIPE_PATH + pipeName);
super(pipeName);
createPipe(getPipeName());
}
private void createPipe(String pipeName) throws IOException {
pipeHandle = Pipes.CreateNamedPipe(pipeName, WIN32Constants.PIPE_ACCESS_DUPLEX, // read/write
// access
WIN32Constants.PIPE_TYPE_MESSAGE | // message type
// pipe
WIN32Constants.PIPE_READMODE_MESSAGE | // message-read
// mode
WIN32Constants.PIPE_WAIT, // blocking mode
1,//only one client valid //WIN32Constants.PIPE_UNLIMITED_INSTANCES, // max. instances
BUFFER_SIZE, // output buffer size
BUFFER_SIZE, // input buffer size
WIN32Constants.NMPWAIT_USE_DEFAULT_WAIT, // client time-out
WIN32Constants.NULL);
if (pipeHandle == WIN32Constants.INVALID_HANDLE_VALUE) {
throw new IOException(
"Pipe '"
+ pipeName
+ "' cannot be created. (WIN-API: CreateNamedPipe()). Windows Error: "
+ Pipes.FormatMessage(Pipes.GetLastError()));
}
}
/*
* (non-Javadoc)
*
* @see at.spardat.xma.pipes.XMAPipes#destroyPipe()
*/
public void destroyPipe() throws IOException {
if (!Pipes.CloseHandle(pipeHandle)) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' cannot be destroyed. (WIN-API: closeHandel()). Windows Error: "
+ Pipes.FormatMessage(Pipes.GetLastError()));
}
}
/*
* (non-Javadoc)
*
* @see at.spardat.xma.pipes.XMAPipes#open()
*/
public void open() throws IOException {
int error = 0;
if (!Pipes.ConnectNamedPipe(pipeHandle, WIN32Constants.NULL)
&& (error = Pipes.GetLastError()) != WIN32Constants.ERROR_PIPE_CONNECTED) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' cannot be opened. (WIN-API: ConnectNamedPipe()). Windows Error: "
+ Pipes.FormatMessage(error));
}
}
/*
* (non-Javadoc)
*
* @see at.spardat.xma.pipes.XMAPipes#close()
*/
public void close() throws IOException {
if (!Pipes.FlushFileBuffers(pipeHandle)) {
}
if (!Pipes.DisconnectNamedPipe(pipeHandle)) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' cannot be closed. (WIN-API: DisconnectNamedPipe()). Windows Error: "
+ Pipes.FormatMessage(Pipes.GetLastError()));
}
}
/*
* (non-Javadoc)
*
* @see at.spardat.xma.pipes.XMAPipes#write(byte[])
*/
public void write(byte[] out) throws IOException {
//Schreibt mehr als BUFFER_SIZE, call kann aber dann blokieren
//Kann auch durch write Schleife ersetzt werden ! siehe MSDN.
//Dann blockiert aber die write Funktion. Anforderungen noch unklar...
// if (out.length > BUFFER_SIZE) {
// throw new IOException("Pipe '" + getPipeName()
// + "' write Error. Byte Array to write lenght (" + out.length
// + ") is greater than max. Buffersize (" + BUFFER_SIZE + ")");
// }
int[] bytesWritten = new int[1];
if (!Pipes.WriteFile(
pipeHandle,
out,
out.length,
bytesWritten,
WIN32Constants.NULL)) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' write Error. (WIN-API: WriteFile()). Windows Error: "
+ Pipes.FormatMessage(Pipes.GetLastError()));
}
if (out.length != bytesWritten[0]) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' write Error. (WIN-API: WriteFile()). Byte Array to write lenght ("
+ out.length + ") actually written bytes (" + bytesWritten[0]
+ ")");
}
}
/*
* (non-Javadoc) reads ReadFile in a loop as there can be more data than
* BUFFER_SIZE
*
* @see at.spardat.xma.pipes.XMAPipes#read()
*/
public byte[] read() throws IOException {
ArrayList list = new ArrayList();
int size = 0;
//loop as long ReadFile() returns fals end GetLastError() ==
// ERROR_MORE_DATA
boolean ok = true;
int error = 0;
do {
byte[] bufferIn = new byte[BUFFER_SIZE];
int[] bytesRead = new int[1];
ok = Pipes.ReadFile(
pipeHandle,
bufferIn,
BUFFER_SIZE,
bytesRead,
WIN32Constants.NULL);
if (!ok && (error = Pipes.GetLastError()) != WIN32Constants.ERROR_MORE_DATA
&& error != WIN32Constants.ERROR_SUCCESS) {
throw new IOException(
"Pipe '"
+ getPipeName()
+ "' read Error. (WIN-API: ReadFile()). Windows Error: "
+ Pipes.FormatMessage(error));
}
byte[] result = new byte[bytesRead[0]];
System.arraycopy(bufferIn, 0, result, 0, bytesRead[0]);
size += bytesRead[0];
list.add(result);
} while (!ok);
//copy all results in one array
byte[] endresult = new byte[size];
int i = 0;
for (Iterator iter = list.iterator(); iter.hasNext();) {
byte[] element = (byte[]) iter.next();
System.arraycopy(element, 0, endresult, i, element.length);
i += element.length;
}
return endresult;
}
}