package org.kevoree.library.javase.pipe;
import org.kevoree.annotation.ChannelTypeFragment;
import org.kevoree.annotation.Library;
import org.kevoree.annotation.Start;
import org.kevoree.annotation.Stop;
import org.kevoree.framework.AbstractChannelFragment;
import org.kevoree.framework.ChannelFragmentSender;
import org.kevoree.framework.KevoreeChannelFragment;
import org.kevoree.framework.KevoreePort;
import org.kevoree.framework.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* User: Erwan Daubert - erwan.daubert@gmail.com
* Date: 08/11/11
* Time: 11:49
*
* @author Erwan Daubert
* @version 1.0
*/
@Library(name = "JavaSE")
@ChannelTypeFragment
public class PipeChannel extends AbstractChannelFragment implements PipeInstance {
private Logger logger = LoggerFactory.getLogger(PipeChannel.class);
private Map<String, RandomAccessFile> outputStreams;
private PipeReader reader;
@Start
public void startPipeChannel () throws IOException, InterruptedException {
outputStreams = new HashMap<String, RandomAccessFile>(this.getOtherFragments().size());
if (isWindows()) {
initializeOnWindows();
} else {
initializeOnLinux();
}
reader = new PipeReader(this);
}
@Stop
public void stopPipeChannel () {
for (RandomAccessFile stream : outputStreams.values()) {
try {
stream.close();
} catch (IOException e) {
}
}
reader.stop();
}
@Override
public Object dispatch (Message msg) {
for (KevoreePort p : getBindedPorts()) {
forward(p, msg);
}
for (KevoreeChannelFragment cf : getOtherFragments()) {
forward(cf, msg);
}
return null;
}
@Override
public ChannelFragmentSender createSender (final String remoteNodeName, final String remoteChannelName) {
return new ChannelFragmentSender() {
@Override
public Object sendMessageToRemote (Message message) {
if (isWindows()) {
dispatchOnWindows(message);
} else {
try {
dispatchOnUnix(message, remoteNodeName);
} catch (IOException e) {
logger.warn(
"Unable to use the pipe for " + remoteChannelName + " from " + getNodeName() + " to "
+ remoteNodeName, e);
}
}
return null;
}
};
}
public void localForward (byte[] msg, int length) {
try {
Message message = (Message) new ObjectInputStream(new ByteArrayInputStream(msg, 0, length)).readObject();
for (KevoreePort p : getBindedPorts()) {
forward(p, message);
}
} catch (Exception e) {
logger.warn("Unable to convert data received as a message", e);
}
}
private void initializeOnWindows () {
// TODO
}
private void initializeOnLinux () throws IOException, InterruptedException {
final Process p = Runtime.getRuntime()
.exec("mkfifo -m 777 " + System.getProperty("java.io.tmpdir") + File.separator + this
.getName() + "_" + this.getNodeName());
new Thread() {
public void run () {
InputStream inStream = p.getInputStream();
InputStream errStream = p.getErrorStream();
byte[] bytes = new byte[1024];
try {
int length = inStream.read(bytes);
errStream.read(bytes);
while (length != -1) {
length = inStream.read(bytes);
// System.out.write(bytes, 0, length);
errStream.read(bytes);
}
} catch (IOException e) {
// e.printStackTrace();
}
}
}.start();
p.waitFor();
}
private void dispatchOnWindows (Message msg) {
// TODO
}
private void dispatchOnUnix (Message msg, String nodeName) throws IOException {
if (outputStreams.get(nodeName) == null) {
outputStreams.put(nodeName,
new RandomAccessFile(new File(System.getProperty("java.io.tmpdir") + File.separator + this
.getName() + "_" + nodeName), "rw"));
}
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ObjectOutputStream objectStream = new ObjectOutputStream(stream);
objectStream.writeObject(msg);
outputStreams.get(nodeName).writeInt(stream.size());
outputStreams.get(nodeName).write(stream.toByteArray());
}
public static boolean isWindows () {
String os = System.getProperty("os.name").toLowerCase();
return (os.contains("win"));
}
}