initialize

This commit is contained in:
Pruefer
2025-06-06 09:15:13 +02:00
commit fa7c2730f1
5817 changed files with 1339670 additions and 0 deletions

View File

@@ -0,0 +1,205 @@
using com.itac.mes.commonsmt;
using com.itac.mes.commonsmt.data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
namespace com.itac.mes.commonsmt
{
class FailoverHostList
{
// this list is cyclically updated as long as a mesService Endpoint is active and not closed
private List<FailoverHost> failoverHosts;
// this is the host all current calls are going to
private FailoverHost activeHost;
public event MyEventHandler OnLog;
public FailoverHostList(MyEventHandler log)
{
this.OnLog = log;
}
public void log(TraceEventType traceEventType, string message)
{
if (OnLog == null) { return; }
MyEventArgs myEventArgs = new MyEventArgs();
myEventArgs.message = "iTAC.MES.Suite SMT-Plugin:" + message;
myEventArgs.traceEventType = traceEventType;
OnLog(this, myEventArgs);
}
public void setFailover(FailoverHost[] newFailoverHosts)
{
// protocol all changes
Boolean newHosts = false;
if (newFailoverHosts == null)
{
activeHost = null;
this.failoverHosts = null;
return;
}
if (this.failoverHosts == null)
{
// initial setting
log(TraceEventType.Information, "setting initial failover hosts :");
foreach (FailoverHost item in newFailoverHosts)
{
log(TraceEventType.Information, ": " + item.getHostname());
}
}
else
{
// whats new, whats removed...
Dictionary<String, FailoverHost> currentHosts = new Dictionary<String, FailoverHost>();
foreach (FailoverHost item in this.failoverHosts)
{
currentHosts.Add(item.getHostname(), item);
}
foreach (FailoverHost item in newFailoverHosts)
{
if (currentHosts.ContainsKey(item.getHostname()))
{
// enthalten, also aus dieser Liste lösche
currentHosts.Remove(item.getHostname());
}
else
{
// bisher nicht enthalten, also neu
Console.Write("new failover host " + item.getHostname());
newHosts = true;
}
}
if (currentHosts.Count > 0)
{
log(TraceEventType.Information, "some failover host removed ");
foreach (FailoverHost removedHost in currentHosts.Values)
{
log(TraceEventType.Information, " - " + removedHost.getHostname());
}
}
else
{
if (!newHosts)
{
log(TraceEventType.Information, "failover host list remains unchanged ");
foreach (FailoverHost item in newFailoverHosts)
{
log(TraceEventType.Information, ":" + item.getHostname());
}
}
}
}
this.failoverHosts = newFailoverHosts.ToList();
// der erste Host in der Liste ist auch der Host, zu dem die aufrufe ohne Failover gehen!!!
if (activeHost == null)
{
if (newFailoverHosts.Length > 0)
{
activeHost = newFailoverHosts[0];
}
else
{
// clean default host
activeHost = null;
}
}
}
/**
* Removes a host from the failover list.
*
* If the host is the currently active host {@link #getActiveHost()} then the current host is set to null<br>
* If the host is not in the host list then nothing happens
*
* @param host
* the host to be removed; do nothing if host is null
*/
public void remove(FailoverHost host)
{
if (host == null)
{
return;
}
log(TraceEventType.Information, "remove host " + host.getHostname() + " from failover list");
for (int i = 0; i < getList().Count; i++)
{
FailoverHost item = getList()[i];
if (item.getHostname().Equals(host.getHostname()))
{
getList().Remove(item);
log(TraceEventType.Information, "host " + item.getHostname() + " removed from failover list");
}
}
if (activeHost != null && activeHost.getHostname().Equals(host.getHostname()))
{
setActiveHost(null);
}
}
/**
* @return the number of hosts in the failover list
*/
public int size()
{
return failoverHosts == null ? 0 : failoverHosts.Count;
}
/**
* @return the list of currently known host to fail over
*/
public List<FailoverHost> getList()
{
return failoverHosts == null ? new List<FailoverHost>() : failoverHosts;
}
public FailoverHost getActiveHost()
{
return activeHost;
}
public void setActiveHost(FailoverHost host)
{
if (host == null)
{
log(TraceEventType.Information, "clear active failover hosts");
}
else
{
log(TraceEventType.Information, "set " + host.getHostname() + " as active failover hosts");
}
this.activeHost = host;
}
public FailoverHost getNextFailoverHost()
{
FailoverHost failoverHost = null;
log(TraceEventType.Information, "scanning for other failover hosts. list contains a total of " + size() + " hosts");
foreach (FailoverHost host in getList())
{
if (host.Equals(getActiveHost()))
{
continue;
}
failoverHost = host;
log(TraceEventType.Information, "next failover hosts is " + host.getHostname());
break;
}
// den nächsten aus der Liste ohne den defaultHost
if (size() == 0)
{
log(TraceEventType.Information, "No more failover host available!");
}
return failoverHost;
}
}
}

View File

@@ -0,0 +1,338 @@
using com.itac.mes.commonsmt;
using com.itac.mes.commonsmt.data;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Text;
namespace com.itac.mes.commonsmt
{
class FailoverInvocationHandler : FailoverHostList
{
// Zugriff auf die folgenden Maps muss synchronisiert erfolgen
static readonly object _locker = new object();
// In dieser Map sind alle offenen Verbindungen zum DataInterface enthalten
private Dictionary<String, IhapEventChannel> openClientChannels = new Dictionary<String, IhapEventChannel>();
// pro Verbindung wird gezaehlt wie viele Connections es schon gab...
private Dictionary<String, Int32> channelNameCounter = new Dictionary<String, Int32>();
public FailoverInvocationHandler(MyEventHandler OnLog)
: base(OnLog)
{
}
/**
* gets a new communication channel with specified name
*
* @param channelName
* the name for the channel
* @param connectionListener
* when a connection listener is set (!= null) a thread is established to cyclically check wether the channel is still
* active or not. If a connection is shutdown by a server (the remote function host) an event at the listener is fired
* @return the communication channel where mesFunctions are exceuted (remote calls via IHap)
* @throws IOException
* when no connection could be established
*/
private IMesServicesChannel getConnection(string channelName, Object s)
{
if (getActiveHost() == null)
{
log(TraceEventType.Error, "cannot get new connection " + channelName + " because active host is unset");
return null;
}
// for every channel a new connection Every connection has it's own counter
string channelNameWithNumber = getChannelName(channelName);
// Neue Verbindung zum DataInterface aufmachen
var tcpClient = new TcpClient(getActiveHost().getHostname(), getActiveHost().getPort());
// eine neue TCp-Client-Verbindung
var iHapEventChannel = new IhapEventChannel(tcpClient, channelNameWithNumber);
if (iHapEventChannel == null)
{
log(TraceEventType.Error, "iHapEventChannel not created");
throw new Exception("iHapEventChannel not created");
}
log(TraceEventType.Information, "before adding " + channelNameWithNumber);
lock (_locker)
{
if (openClientChannels.ContainsKey(channelNameWithNumber))
{
openClientChannels.Remove(channelNameWithNumber);
}
openClientChannels.Add(channelNameWithNumber, iHapEventChannel);
}
log(TraceEventType.Information, "" + channelNameWithNumber + " added");
iHapEventChannel.channelName = channelNameWithNumber;
// Listener installieren, um zu reagieren, wenn das Data-Interface die Verbindung abgebrochen hat
// iHapEventChannel.connectionStateChangeListener += new PropertyChangeListener(iHapEventChannel_connectionStateChangeListener);
var remoteMesService = (IMesServicesChannel)iHapEventChannel.GetTransparentProxy();
if (remoteMesService == null)
{
log(TraceEventType.Error, "iHapEventChannel.transparentProxy not created");
throw new Exception("iHapEventChannel.transparentProxy not created");
}
remoteMesService.setChannelName(channelNameWithNumber);
remoteMesService.startup();
return remoteMesService;
}
private string getChannelName(string channelName)
{
// gab es fuer diesen channelName bereits eine Connection
string channelNameWithNumber = channelName;
var counter = 0;
lock (_locker)
{
if (channelNameCounter.ContainsKey(channelName))
{
counter = channelNameCounter[channelName];
counter++;
if (counter > 100000) { counter = 1; }
channelNameCounter.Remove(channelName);
channelNameCounter.Add(channelName, counter);
}
else
{
channelNameCounter.Add(channelName, counter);
}
channelNameWithNumber = channelName + "#" + counter;
}
return channelNameWithNumber;
}
private void handleThrowable(Object response, Exception throwable)
{
if (!(response is MesResponse))
{
return;
}
MesResponse mesResponse = (MesResponse)response;
mesResponse.setTotalResult(MesServices.MES_RESULT_NOT_OK);
if (throwable is PluginException)
{
setResponseValues(mesResponse, ((PluginException)throwable).getResponseDetail());
}
else if (throwable is IOException)
{
addError(mesResponse.getErrorDetails(),
getErrorDetail(throwable.Message, ResponseDetail.COMMUNICATION_FAILURE));
}
else
{
addError(mesResponse.getErrorDetails(),
getErrorDetail(throwable.Message, ResponseDetail.PROCESSED_WITH_EXCEPTION));
}
}
private ErrorDetail[] addError(ErrorDetail[] errorDetails, ErrorDetail errorDetail)
{
List<ErrorDetail> list = new List<ErrorDetail>();
foreach (ErrorDetail item in errorDetails)
{
list.Add(item);
}
list.Add(errorDetail);
return list.ToArray();
}
// convenient method
private ErrorDetail getErrorDetail(String detail, int code)
{
ErrorDetail errorDetail = new ErrorDetail();
errorDetail.setCode(code);
errorDetail.setDetail(detail);
return errorDetail;
}
/**
* finalizing means closing communication channel and loggin response Object
*
* @param connection
* the used connection
*/
private void finalizeRequest(IMesServicesChannel connection)
{
if (connection != null)
{
string connectionName = connection.getChannelName();
if (connectionName != null)
{
openClientChannels.Remove(connectionName);
}
connection.shutdown();
}
}
private IMesServicesChannel getConnection(string channelName)
{
return getConnection(channelName, null);
}
protected void setResponseValues(MesResponse response, ResponseDetail responseDetail)
{
if (responseDetail.getCode() == ResponseDetail.OK)
{
response.setTotalResult(MesServices.MES_RESULT_OK);
return;
}
response.setTotalResult(MesServices.MES_RESULT_NOT_OK);
addError(response.getErrorDetails(), getErrorDetail(responseDetail.getText(), responseDetail.getCode()));
}
public IMessage Invoke(IMessage msg)
{
IMethodCallMessage methodMsg = (IMethodCallMessage)msg;
MethodInfo methodInfo = typeof(IMesServices).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
if (methodInfo == null)
{
// TODO: check if this is longer required
// object ret = failoverInvocationHandler.invoke(this, methodInfo, methodMsg.InArgs);
}
// special handling for a couple of function (mesStart, mesStop, getFailoverHosts..FailoverInvocationHandler.)
Object response = Activator.CreateInstance(methodInfo.ReturnType);
// if no failoverhost available return error
if (getActiveHost() == null && size() == 0)
{
// no host set, no failover available --> fail
return null;
}
// do a failover for all methods startswith "mes" (operational methods)
if (methodInfo.Name.StartsWith("mes"))
{
IMesServices connection = null;
try
{
bool callFailed = false;
do
{
try
{
callFailed = false;
log(TraceEventType.Information, "call " + methodInfo.Name + "@" + getActiveHost().getHostname());
connection = getConnection(methodInfo.Name);
if (connection == null)
{
callFailed = true;
}
else
{
response = methodInfo.Invoke(connection, methodMsg.InArgs);
if (response == null)
{
callFailed = true;
}
else
{
if ((response is MesResponse))
{
MesResponse responseObject = (MesResponse)response;
if (responseObject.getTotalResult() == MesServices.MES_RESULT_NOT_OK)
{
// set DetailResult to COMMUNICATION_FAILURE
// repeat this call to another host
callFailed = hasCommunicationFailure(responseObject.getErrorDetails());
}
}
}
}
}
catch (SocketException)
{
callFailed = true;
}
if (callFailed)
{
if (connection != null)
{
// explicit finalize this connection
connection = null;
}
remove(getActiveHost());
setActiveHost(getNextFailoverHost());
}
} while (callFailed && getActiveHost() != null);
// if failover did not find any available host return communication error
if (getActiveHost() == null)
{
if ((response is MesResponse))
{
MesResponse responseObject = (MesResponse)response;
addError(responseObject.getErrorDetails(),
getErrorDetail("no failover host active", ResponseDetail.COMMUNICATION_FAILURE));
responseObject.setTotalResult(MesServices.MES_RESULT_NOT_OK);
}
}
}
catch (Exception throwable)
{
handleThrowable(response, throwable);
}
finally
{
if (response is MesFailoverResponse)
{
// internally update the list
setFailover(((MesFailoverResponse)response).getFailoverHosts());
}
finalizeRequest((IMesServicesChannel)connection);
}
}
else
{
// simply call the method, no failover for them
response = methodInfo.Invoke(this, methodMsg.InArgs);
}
return new ReturnMessage(response, methodMsg.Args, 0, methodMsg.LogicalCallContext, methodMsg);
}
private Boolean hasCommunicationFailure(ErrorDetail[] errorDetails)
{
if (errorDetails == null)
{
return false;
}
foreach (ErrorDetail errDetail in errorDetails)
{
if (errDetail.getCode() == ResponseDetail.COMMUNICATION_FAILURE)
{
log(TraceEventType.Error, "communication failure on this connection");
throw new SocketException();
}
if (errDetail.getCode() == -10005)
{
log(TraceEventType.Error, "communication failure on this connection");
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
namespace com.itac.mes.commonsmt
{
class FailoverProxy : RealProxy
{
private FailoverInvocationHandler failoverInvocationHandler;
public FailoverProxy(Type type, FailoverInvocationHandler failoverInvocationHandler)
: base(type)
{
this.failoverInvocationHandler = failoverInvocationHandler;
}
public override IMessage Invoke(IMessage msg)
{
return failoverInvocationHandler.Invoke(msg);
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
namespace com.itac.mes.commonsmt
{
/// <summary>
/// Interface IMesServicesChannel
/// </summary>
public interface IMesServicesChannel : IMesServices
{
/// <summary>
/// returns true when this channel is currently shutting down. While shutting down this channel could not be used for communication.
/// </summary>
/// <returns></returns>
Boolean isShutdown();
/// <summary>
/// starting up this channel. While starting up this channel could not be used for communication.
/// </summary>
void startup();
/// <summary>
/// initiate the shutdown of the channel.
/// </summary>
void shutdown();
/// <summary>
/// setting a name for this channel. Name could be used by java client as well.
/// </summary>
/// <param name="channelName"></param>
void setChannelName(String channelName);
/// <summary>
/// returning the name of this channel.
/// </summary>
/// <returns></returns>
String getChannelName();
}
}

View File

@@ -0,0 +1,319 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
using System.IO;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Threading;
using com.itac.artes.ihap;
using com.itac.util.logging;
namespace com.itac.mes.commonsmt
{
/// <summary>
///
/// </summary>
public class MyChannelEventArgs : EventArgs
{
public MyChannelEventArgs(string channelName, string message)
{
this.channelName = channelName;
this.message = message;
}
public string channelName; public string message;
}
/// <summary>
///
/// </summary>
public delegate void PropertyChangeListener(Object sender, MyChannelEventArgs e);
/// <summary>
///
/// </summary>
public class IhapEventChannel : RealProxy
{
public static Object classLock = new Object();
private static int CONNECTION_CHECK_MILLIES = 500;
private TcpClient _client;
private IhapOutputStream _ios;
private IhapInputStream _iis;
private bool _isShutdown;
/// <summary>
///
/// </summary>
public string channelName { get; set; }
private long lastCall = DateTime.Now.Ticks;
private Object lockObject = new Object();
private Thread aliveThread;
/// <summary>
///
/// </summary>
public event PropertyChangeListener connectionStateChangeListener;
/// <summary>
///
/// </summary>
public IhapEventChannel(TcpClient client, String channelName)
: base(typeof(IMesServicesChannel))
{
// diesen Constructor nur einmal betreten
lock (classLock)
{
}
this.channelName = channelName;
this._client = client;
_ios = new IhapOutputStream(_client.GetStream());
_iis = new IhapInputStream(_client.GetStream());
aliveThread = new Thread(new ThreadStart(aliveThreadRun));
aliveThread.Name = channelName;
}
/// <summary>
///
/// </summary>
public void shutdown()
{
LogHandler.log("LOGGER", LogLevel.INFO, "closing channel" + channelName);
_isShutdown = true;
try
{
_client.Close();
}
catch (Exception)
{
LogHandler.log("LOGGER", LogLevel.WARN, "closing channel" + channelName + " failed");
}
}
/// <summary>
///
/// </summary>
public long getLastCall()
{
return lastCall;
}
/// <summary>
///
/// </summary>
public bool isConnected()
{
return _client.Client.Connected;
}
/// <summary>
///
/// </summary>
public bool isShutdownInProgress()
{
return _isShutdown;
}
/// <summary>
///
/// </summary>
public override IMessage Invoke(IMessage message)
{
lastCall = new DateTime().Ticks;
IMethodCallMessage methodMsg = (IMethodCallMessage)message;
try
{
MethodInfo methodInfo = typeof(IMesServices).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
// der Reihe nach alle Interface durchgehen, die als Callback implementiert sind
if (methodInfo == null)
{
methodInfo = typeof(IMesServicesChannel).GetMethod(methodMsg.MethodName, (Type[])methodMsg.MethodSignature);
}
if (methodInfo == null)
{
throw new Exception("IHapHandler.cs: methode '" + methodMsg.MethodName + "' nicht in den Interfacen gefunden");
}
object[] args = methodMsg.Args;
if (methodMsg.MethodName.Equals("Equals"))
{
return new ReturnMessage(args[0].Equals(this), args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("getChannelName"))
{
return new ReturnMessage(channelName, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("GetHashCode"))
{
return new ReturnMessage(this.GetHashCode(), args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("shutdown"))
{
shutdown();
stopAliveThread();
connectionClosed();
return new ReturnMessage(null, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
else if (methodMsg.MethodName.Equals("startup"))
{
aliveThread.Start();
return new ReturnMessage(null, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
Object retValue = sendCall(methodInfo, args);
return new ReturnMessage(retValue, args, 0, methodMsg.LogicalCallContext, methodMsg);
}
catch (TargetInvocationException ite)
{
return new ReturnMessage(ite.GetBaseException(), methodMsg);
}
catch (Exception ite)
{
return new ReturnMessage(ite.GetBaseException(), methodMsg);
}
}
private Object sendCall(MethodInfo method, Object[] args)
{
lock (lockObject)
{
LogHandler.log("LOGGER", LogLevel.DEBUG, "Send event '" + method.Name + "' to socket " + _client.Client.RemoteEndPoint + " on " + channelName);
Object result = null;
try
{
_ios.writeBoolean(false);
_ios.call(method, args);
_ios.Flush();
IhapReply reply = _iis.readReply();
if (reply is IhapSuccessReply)
{
result = ((IhapSuccessReply)reply).getReturnValue();
}
else
{
IhapFaultReply fault = (IhapFaultReply)reply;
switch (fault.getFaultCode())
{
case FaultCode.NoSuchMethodException:
throw new NotImplementedException(fault.getMessage());
case FaultCode.ProtocolException:
throw new IhapProtocolException(fault.getMessage(), null);
default:
throw new IhapProtocolException(fault.getMessage(), null);
//(Exception)fault.getException();
}
}
}
catch (Exception e)
{
LogHandler.log("LOGGER", LogLevel.ERROR, "Error while sending event call on " + channelName + ":" + e.Message + "\n" + e.StackTrace);
shutdown();
}
return result;
}
}
/// <summary>
///
/// </summary>
protected void connectionClosed()
{
// Hier wird überprüft, ob ein Eintrag in der Aufruf-Liste vorhanden ist.
if (this.connectionStateChangeListener != null)
{
// Hier wird jeder Delegat, der sich für den Event registriert hat, aufgerufen.
this.connectionStateChangeListener(this, new MyChannelEventArgs(channelName, "connectionClosed"));
}
}
private void stopAliveThread()
{
if (aliveThread.IsAlive && (aliveThread.ThreadState != System.Threading.ThreadState.Running))
{
aliveThread.Interrupt();
}
}
/// <summary>
///
/// </summary>
public void aliveThreadRun()
{
while (!_isShutdown && aliveThread.ThreadState == System.Threading.ThreadState.Running)
{
// wenn der letzte Call laenger als .. her ist...
try
{
Thread.Sleep(50);
}
catch (Exception)
{
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
LogHandler.log("LOGGER", LogLevel.INFO, "interrupted for " + channelName);
}
if (DateTime.Now.Ticks - lastCall > CONNECTION_CHECK_MILLIES)
{
try
{
// versuchen den Server zu pingen
// wenn das fehlschlägt ist die Verbindung kaputt
lock (lockObject)
{ // das erfolgreiche Schreiben eines booleschen Wertes ist aus Kommunikationssicht zu sehen wie der
// erfolgreiche Aufruf einer Methode
if (!_isShutdown && (aliveThread.ThreadState == System.Threading.ThreadState.Running))
{
// nur wenn die Verbindung nicht bereits gestoppt wurde...
_ios.writeBoolean(true);
_ios.Flush();
lastCall = DateTime.Now.Ticks;
}
}
}
catch (Exception)
{
try
{
_isShutdown = true;
_client.Close();
}
catch (IOException e)
{
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
LogHandler.log("LOGGER", LogLevel.INFO, "shutdown connection problem for " + channelName, e);
}
finally
{
// die Schreibverbindung ist kaputt, also diese Connection töten...
LogHandler.log("LOGGER", LogLevel.DEBUG, "detected broken connection for " + channelName
+ " because Server closed port");
connectionClosed();
}
}
}
else
{
LogHandler.log("LOGGER", LogLevel.DEBUG, "Channel too old, stop channel now");
}
}
// wenn beim schliessen der Verbindung noch was passiert ist das nicht schlimm
stopAliveThread();
LogHandler.log("LOGGER", LogLevel.INFO, "channel shut down finished for " + channelName);
}
}
}

View File

@@ -0,0 +1,837 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using com.itac.mes.tools;
using System;
using System.Diagnostics;
using System.IO;
using com.itac.mes.commonsmt.data;
using System.Runtime.CompilerServices;
using System.Threading;
namespace com.itac.mes.commonsmt
{
/// <summary>
/// documentation for the namespace
/// </summary>
[System.Runtime.CompilerServices.CompilerGenerated]
class NamespaceDoc
{
}
public class MyEventArgs : EventArgs
{
public TraceEventType traceEventType;
public String message;
}
/// <summary>
///
/// </summary>
public delegate void MyEventHandler(Object sender, MyEventArgs e);
/// <summary>
/// Class level summary documentation goes here.</summary>
/// <remarks>
/// Longer comments can be associated with a type or member through
/// the remarks tag.</remarks>
public class MesServices : IMesServices
{
/// <summary>
///
/// </summary>
public event MyEventHandler OnLog;
/// <summary>
/// return this value in {@link MesResponse#setTotalResult(int)}
/// {@link MesResponse#getTotalResult()} for any request
/// which was processed successfully.
/// All returned values are be valid.</summary>
public static int MES_RESULT_OK = 0;
/// <summary>
/// return this value in {@link MesResponse#setTotalResult(int)}/{@link MesResponse#getTotalResult()} for any request
/// which was NOT processed successfully. Not all returned values must be valid, depends on the request.
///
/// @see separate calls in {@link IMesServices#} for detailled information.
/// </summary>
public static int MES_RESULT_NOT_OK = 1;
// allowed port range
private static int MIN_PORT = 1023;
private static int MAX_PORT = 49150;
// 10 minutes default
private static int DEFAULT_REFRESH_INTERVAL = 600000;
// some bool flags for operation
private Boolean configured;
private Boolean active;
// every call to a mes host needs an own id; the id does not change when a call is completed on a failover host
private RequestIdGenerator idGenerator = new RequestIdGenerator();
// the invocation handler accepts all calls from the failoverProxy
private FailoverInvocationHandler failoverInvocationHandler;
// this proxy delegates the calls to all known failover hosts
private IMesServices failoverProxy;
// update Thread counter
private int runCounter;
/// <summary>
/// do not marshal objects but print as xml
/// </summary>
private ItacXmlSerializer serializer = new ItacXmlSerializer();
//// failover detection
private static int updateThreadCount;
private Thread failoverUpdateThread;
private int refreshFailoverhostsInterval;
/// <summary>
///
/// </summary>
public MesServices(String hostname, int port, int refreshFailoverhostsInterval)
{
setConfigured(false);
setActive(false);
//// create and initialize the failover proxy
failoverInvocationHandler = new FailoverInvocationHandler(OnLog);
// create the proxy and set the delegate
failoverProxy = (IMesServices)new FailoverProxy(typeof(IMesServices), failoverInvocationHandler).GetTransparentProxy();
// check hostname
if (!isHostNameValid(hostname))
{
log(TraceEventType.Error, "hostname must not be null or empty");
return;
}
// check port range
if (!isPortValid(port))
{
log(TraceEventType.Error, String.Format("value {0} is out of range {1}..{2}", port, MIN_PORT, MAX_PORT));
return;
}
// check refresh interval
if (!isRefreshIntervalValid(refreshFailoverhostsInterval))
{
log(TraceEventType.Error, "value {0} is out of valid values [-1], [0], [>60000]");
return;
}
setRefreshFailoverhostsInterval(refreshFailoverhostsInterval);
setConfigured(true);
FailoverHost failoverHost = new FailoverHost();
failoverHost.setHostname(hostname);
failoverHost.setPort(port);
failoverInvocationHandler.setFailover(new FailoverHost[] { failoverHost });
}
protected void setRefreshFailoverhostsInterval(int refreshFailoverhostsInterval)
{
this.refreshFailoverhostsInterval = refreshFailoverhostsInterval;
}
protected Boolean isPortValid(int newPort)
{
Boolean result = newPort >= MIN_PORT && newPort <= MAX_PORT;
return result;
}
protected Boolean isHostNameValid(String hostname)
{
return hostname != null && hostname.Length != 0;
}
protected Boolean isRefreshIntervalValid(long refreshFailoverhostsInterval)
{
return refreshFailoverhostsInterval == -1 || refreshFailoverhostsInterval == 0 || refreshFailoverhostsInterval > 60000;
}
protected void setActive(Boolean active)
{
if (!this.active && active)
{
log(TraceEventType.Information, "setting MesServices active");
}
else if (this.active && !active)
{
log(TraceEventType.Information, "setting MesServices inactive");
}
this.active = active;
}
protected Boolean isActive()
{
return active;
}
protected Boolean isConfigured()
{
return configured;
}
protected void setConfigured(Boolean configured)
{
if (!this.configured && configured)
{
log(TraceEventType.Information, "setting MesServices configured");
}
else if (this.configured && !configured)
{
log(TraceEventType.Information, "setting MesServices unconfigured");
}
this.configured = configured;
}
/// <summary>
/// Vorbedingungen sind dass der Request gesetzt ist, sowie die Konfiguration und die aktivierung des Plugin
/// </summary>
/// <param name="mesResponse"> Parameter description for s goes here.</param>
/// <param name="mesRequest"> Parameter description for s goes here.</param>
/// <seealso cref="System.String">
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists. </seealso>
private void checkPreconditions(MesResponse mesResponse, MesRequest mesRequest) /* throws CogiscanException */{
checkRequestPreconditons(mesRequest);
if (mesResponse == null)
{
throw new PluginException(ResponseDetail.RESPONSE_IS_NULL, "response is null");
}
// requestId aus Request in den Response uebernehmen
mesResponse.setRequestId(mesRequest.getRequestId());
// Konfigurationsprobleme checken
if (!isConfigured())
{
throw new PluginException(ResponseDetail.PLUGIN_NOT_CONFIGURED, "plugin is not yet configured");
}
if (!isActive())
{
throw new PluginException(ResponseDetail.PLUGIN_NOT_ACTIVE, "plugin is not yet active");
}
setResponseValues(mesResponse, new ResponseDetail("", ResponseDetail.OK));
}
private void checkRequestPreconditons(MesRequest mesRequest)
{
if (mesRequest == null)
{
throw new PluginException(ResponseDetail.REQUEST_IS_NULL, "the request is null");
}
if (mesRequest.getRequestId() <= 0)
{
mesRequest.setRequestId(idGenerator.getNextId());
}
if (mesRequest.getEventDate() == null || mesRequest.getEventDate().Ticks == 0)
{
mesRequest.setEventDate(DateTime.Now);
}
// Request ausgeben
logRequest(mesRequest);
}
/**
* finalizing means closing communication channel and loggin response Object
*
* @param connection
* the used connection
* @param responseObject
* the responseObject
*/
private void finalizeRequest(MesResponse responseObject)
{
logResponse(responseObject);
}
// * gets a new communication cahnnel with specified name
// *
// * @param channelName
// * the name for the channel
// * @param connectionListener
// * @return
// * @throws IOException
// eine neue socket zum DataInterface als Client aufmachen. ?ber diese Verbindung werden alle Events zum
// Datainterface ?bertragen
// Returned nie einen Null-Wert
/// <summary>
/// Description for SomeMethod.</summary>
/// You can use the cref attribute on any tag to reference a type or member
/// and the compiler will check that the reference exists.
private void log(TraceEventType traceEventType, string message)
{
if (OnLog == null) { return; }
MyEventArgs myEventArgs = new MyEventArgs();
myEventArgs.message = "iTAC.MES.Suite SMT-Plugin:" + message;
myEventArgs.traceEventType = traceEventType;
OnLog(this, myEventArgs);
}
// convenient method
private ErrorDetail getErrorDetail(String detail, int code)
{
ErrorDetail errorDetail = new ErrorDetail();
errorDetail.setCode(code);
errorDetail.setDetail(detail);
return errorDetail;
}
private void handleThrowable(MesResponse response, Exception throwable)
{
response.setTotalResult(MesServices.MES_RESULT_NOT_OK);
if (throwable is PluginException)
{
setResponseValues(response, ((PluginException)throwable).getResponseDetail());
}
else if (throwable is IOException)
{
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(throwable.Message, ResponseDetail.COMMUNICATION_FAILURE));
response.setErrorDetails(details);
}
else
{
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(throwable.Message, ResponseDetail.PROCESSED_WITH_EXCEPTION));
response.setErrorDetails(details);
}
}
private void logResponse(MesResponse mesResponse)
{
if (mesResponse == null)
{
log(TraceEventType.Information, "finish empty response");
return;
}
try
{
String v = serializer.serialize(mesResponse).ToString();
log(TraceEventType.Verbose, "finish response " + mesResponse.getRequestId() + " (" + mesResponse.GetType().Name + ")"
+ " with code " + mesResponse.getTotalResult() + "\n" + v);
}
catch (Exception)
{
log(TraceEventType.Verbose, "finish request " + mesResponse.getRequestId() + " with code " + mesResponse.getTotalResult() + "\ncannot log response message");
}
}
private void logRequest(MesRequest mesRequest)
{
if (mesRequest == null)
{
log(TraceEventType.Information, "finish empty request");
return;
}
try
{
String v = serializer.serialize(mesRequest).ToString();
log(TraceEventType.Verbose, "finish request " + mesRequest.getRequestId() + " (" + mesRequest.GetType().Name + ")" + "\n" + v);
}
catch (Exception)
{
log(TraceEventType.Verbose, "finish request " + mesRequest.getRequestId() + "\ncannot log request message");
}
}
private void setResponseValues(MesResponse response, ResponseDetail responseDetail)
{
if (responseDetail.getCode() == ResponseDetail.OK)
{
response.setTotalResult(MesServices.MES_RESULT_OK);
return;
}
response.setTotalResult(MesServices.MES_RESULT_NOT_OK);
ErrorDetail[] details = response.getErrorDetails();
addError(ref details, getErrorDetail(responseDetail.getText(), responseDetail.getCode()));
response.setErrorDetails(details);
}
protected IMesServices getFailoverProxy()
{
return failoverProxy;
}
#region IMesServices_Member
/// <summary>
///
/// </summary>
/// <param name="createContainerRequest"></param>
/// <returns></returns>
public CreateContainerResponse mesCreateContainer(CreateContainerRequest createContainerRequest)
{
CreateContainerResponse responseObject = new CreateContainerResponse();
try
{
checkPreconditions(responseObject, createContainerRequest);
responseObject = getFailoverProxy().mesCreateContainer(createContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
public CreateMslContainerResponse mesCreateMslContainer(CreateMslContainerRequest createMslContainerRequest)
{
CreateMslContainerResponse responseObject = new CreateMslContainerResponse();
try
{
checkPreconditions(responseObject, createMslContainerRequest);
responseObject = getFailoverProxy().mesCreateMslContainer(createMslContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public CheckContainerResponse mesCheckContainer(CheckContainerRequest checkContainerRequest)
{
CheckContainerResponse responseObject = new CheckContainerResponse();
try
{
checkPreconditions(responseObject, checkContainerRequest);
responseObject = getFailoverProxy().mesCheckContainer(checkContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
public CheckMslContainerResponse mesCheckMslContainer(CheckMslContainerRequest checkMslContainerRequest)
{
CheckMslContainerResponse responseObject = new CheckMslContainerResponse();
try
{
checkPreconditions(responseObject, checkMslContainerRequest);
responseObject = getFailoverProxy().mesCheckMslContainer(checkMslContainerRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public PlacementRecipeCheckResponse mesCheckPlacementRecipe(PlacementRecipeCheckRequest placementRecipeCheckRequest)
{
PlacementRecipeCheckResponse responseObject = new PlacementRecipeCheckResponse();
try
{
checkPreconditions(responseObject, placementRecipeCheckRequest);
responseObject = getFailoverProxy().mesCheckPlacementRecipe(placementRecipeCheckRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public InterlockingResponse mesInterlocking(InterlockingRequest interlockingRequest)
{
InterlockingResponse responseObject = new InterlockingResponse();
try
{
checkPreconditions(responseObject, interlockingRequest);
responseObject = getFailoverProxy().mesInterlocking(interlockingRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// <param name="name">description</param>
/// <returns>description</returns>
/// <seealso cref="MesRequest"/>
/// </summary>
public PanelInfoResponse mesPanelInformation(PanelInfoRequest infoRequest)
{
PanelInfoResponse responseObject = new PanelInfoResponse();
try
{
checkPreconditions(responseObject, infoRequest);
responseObject = getFailoverProxy().mesPanelInformation(infoRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesItemProduced(ItemProducedRequest itemProducedRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, itemProducedRequest);
responseObject = getFailoverProxy().mesItemProduced(itemProducedRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMachineState(MachineStatusRequest machineStatus)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, machineStatus);
responseObject = getFailoverProxy().mesMachineState(machineStatus);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMachineMessage(MachineMessageRequest machineMessage)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, machineMessage);
responseObject = getFailoverProxy().mesMachineMessage(machineMessage);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesFailoverResponse mesGetFailoverList(MesRequest mesRequest)
{
MesFailoverResponse responseObject = new MesFailoverResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetFailoverList(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesMaterialConsumed(MaterialConsumedRequest materialConsumedRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, materialConsumedRequest);
responseObject = getFailoverProxy().mesMaterialConsumed(materialConsumedRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesConfigurationResponse mesGetConfiguration(MesRequest mesRequest)
{
MesConfigurationResponse responseObject = new MesConfigurationResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetConfiguration(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
finalizeRequest(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesStart(MesStartRequest mesRequest)
{
checkRequestPreconditons(mesRequest);
MesResponse responseObject = new MesResponse();
responseObject.setRequestId(mesRequest.getRequestId());
try
{
if (!isConfigured())
{
throw new PluginException(ResponseDetail.MES_NOT_CONFIGURED_PROPERLY, "");
}
if (isActive())
{
setResponseValues(responseObject, new ResponseDetail("", ResponseDetail.OK));
return responseObject;
}
// append own assembly vresion to mesStart message
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
responseObject = getFailoverProxy().mesStart(mesRequest);
stopWatch.Stop();
long millies = stopWatch.ElapsedMilliseconds;
log(TraceEventType.Information, "roundtrip = " + (millies) + " milliseconds");
if (responseObject.getTotalResult() == MES_RESULT_OK)
{
setActive(true);
startUpdateThread();
}
}
catch (PluginException cse)
{
handleThrowable(responseObject, cse);
}
finally
{
logResponse(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesGetStatus(MesRequest mesRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesGetStatus(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
logResponse(responseObject);
}
return responseObject;
}
/// <summary>
///
/// </summary>
public MesResponse mesStop(MesRequest mesRequest)
{
MesResponse responseObject = new MesResponse();
try
{
checkPreconditions(responseObject, mesRequest);
responseObject = getFailoverProxy().mesStop(mesRequest);
}
catch (Exception throwable)
{
handleThrowable(responseObject, throwable);
}
finally
{
logResponse(responseObject);
}
setActive(false);
stopUpdateThread();
return responseObject;
}
#endregion IMesServices_Member
#region UpdateThread
public void failoverThreadProc()
{
log(TraceEventType.Information, Thread.CurrentThread.Name + "renew failoverHost list thread started, call #" + (++runCounter));
while (true)
{
try
{
mesGetFailoverList(new MesRequest());
log(TraceEventType.Information, Thread.CurrentThread.Name + "renew failoverHost list finished");
int millies = refreshFailoverhostsInterval;
if (millies == -1)
{
millies = DEFAULT_REFRESH_INTERVAL;
}
TimeSpan ts = TimeSpan.FromMilliseconds(millies);
log(TraceEventType.Information, Thread.CurrentThread.Name + "next failover resolving in " + ts.ToString());
Thread.Sleep(millies);
}
catch (ThreadAbortException)
{
log(TraceEventType.Error, Thread.CurrentThread.Name + "interrupted or failed");
break;
}
catch (ThreadInterruptedException)
{
log(TraceEventType.Error, Thread.CurrentThread.Name + "interrupted");
break;
}
}
log(TraceEventType.Information, Thread.CurrentThread.Name + "closed");
}
[MethodImpl(MethodImplOptions.Synchronized)]
protected Thread getUpdateThread()
{
String threadName = "failoverUpdateThread#" + (updateThreadCount++);
Thread failoverUpdateThread = new Thread(new ThreadStart(failoverThreadProc));
// threadName) {
//};
log(TraceEventType.Error, Thread.CurrentThread.Name + "created");
return failoverUpdateThread;
}
protected void startUpdateThread()
{
// if connection is established and OK start observation thread
if (failoverUpdateThread == null)
{
failoverUpdateThread = getUpdateThread();
failoverUpdateThread.Start();
}
}
/**
* the current active channel was closed (port closed on DataInterface)
*
* @param channelName
*/
protected void stopUpdateThread()
{
log(TraceEventType.Information, " was closed by iTAC.MES.Suite DataInterface");
// den Ueberwachungsthread stoppen
if (failoverUpdateThread != null)
{
log(TraceEventType.Information, " stop " + failoverUpdateThread.Name + " now");
failoverUpdateThread.Interrupt();
failoverUpdateThread = null;
}
}
private void addError(ref ErrorDetail[] errorDetail1, ErrorDetail errorDetail2)
{
if (errorDetail1 == null)
{
errorDetail1 = new ErrorDetail[0];
}
int newArrSize = errorDetail1.Length + 1;
Array.Resize<ErrorDetail>(ref errorDetail1, newArrSize);
errorDetail1[newArrSize - 1] = errorDetail2;
}
#endregion UpdateThread
}
}

View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C3D8FC7C-22B2-46F9-842F-19165F078217}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>CommonSmtPlugin</RootNamespace>
<AssemblyName>CommonSmtPlugin</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>
</DocumentationFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>
</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>0</WarningLevel>
<DocumentationFile>bin\Release\CommonSmtPlugin.XML</DocumentationFile>
<RunCodeAnalysis>true</RunCodeAnalysis>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="artes-dotnet">
<HintPath>lib\artes-dotnet.dll</HintPath>
</Reference>
<Reference Include="CommonSmtApi, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\CommonSmtApi.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FailoverHostList.cs" />
<Compile Include="FailoverInvocationHandler.cs" />
<Compile Include="FailoverProxy.cs" />
<Compile Include="IhapEventChannel.cs" />
<Compile Include="IMesServicesChannel.cs" />
<Compile Include="RequestIdGenerator.cs" />
<Compile Include="tool\ItacXmlSerializer.cs" />
<Compile Include="ResponseDetail.cs" />
<Compile Include="PluginException.cs" />
<Compile Include="MesServices.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
using System.Runtime.Serialization;
using System.Security.Permissions;
namespace com.itac.mes.commonsmt
{
/// <summary>
/// This Exception contains some details about the reason
/// </summary>
[Serializable]
public class PluginException : Exception
{
private ResponseDetail responseDetail;
private int p;
/// <summary>
///
/// </summary>
public PluginException(ResponseDetail responseDetail)
{
this.responseDetail = responseDetail;
}
/// <summary>
///
/// </summary>
public PluginException(int p, String message)
{
this.responseDetail = new ResponseDetail(message, p);
this.p = p;
}
/// <summary>
///
/// </summary>
public ResponseDetail getResponseDetail()
{
return responseDetail;
}
}
}

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("Common SMT Plugin: ${mes.interface.version}/${timestamp}")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("iTAC Software AG")]
[assembly: AssemblyProduct("CommonSmtPlugin")]
[assembly: AssemblyCopyright("Copyright © iTAC Software AG 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("fd38d098-5efd-432e-86b9-451f5c47cf00")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2016 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace com.itac.mes.commonsmt
{
class RequestIdGenerator
{
protected static int MIN_REQUEST_ID = 0;
protected static int MAX_REQUEST_ID = 1000000;
private int requestId;
static object lockObject = new object();
// creates an almost unique id
public int getNextId()
{
lock (lockObject)
{
requestId += 1;
if (requestId >= MAX_REQUEST_ID)
{
requestId = MIN_REQUEST_ID;
}
}
return requestId;
}
}
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
namespace com.itac.mes.commonsmt
{
/// <summary>
///
/// </summary>
public class ResponseDetail
{
/// <summary>
/// WARNINGS, HINTS: positive values
/// </summary>
public static int OK = 0;
/// <summary>
/// Plugin-ERRORS: negative values
/// </summary>
public static int REQUEST_IS_NULL = -10001; //
/// <summary>
/// any call to MES before mesConfigure was called properly
/// </summary>
public static int PLUGIN_NOT_CONFIGURED = -10002; //
/// <summary>
///
/// </summary>
public static int PLUGIN_NOT_ACTIVE = -10003; //
/// <summary>
///
/// </summary>
public static int PLUGIN_NOT_CONNECTED = -10004; //
/// <summary>
///
/// </summary>
public static int COMMUNICATION_FAILURE = -10005; //
/// <summary>
///
/// </summary>
public static int WRONG_COMMUNICATION_PROPERTIES = -10006; //
/// <summary>
/// the version from the mes does not fit the version of the interface
/// </summary>
public static int PLUGIN_VERSION_MISMATCH = -10007; //
/// <summary>
/// The response was not set before
/// </summary>
public static int RESPONSE_IS_NULL = -10008; //
/// <summary>
/// Errors from Data Interface negative values
/// </summary>
public static int MES_NOT_CONNECTED = -20000; //
/// <summary>
///
/// </summary>
public static int MES_NOT_CONFIGURED_PROPERLY = -20001; //
/// <summary>
///
/// </summary>
public static int MES_NOT_INITIALIZED = -20002; //
/// <summary>
///
/// </summary>
public static int PARSED_WITH_EXCEPTION = -20003; //
/// <summary>
///
/// </summary>
public static int PROCESSED_WITH_EXCEPTION = -20004; //
/// <summary>
///
/// </summary>
public static int SERIALNUMBER_NOT_ALLOWED = -20005; //
/// <summary>
///
/// </summary>
public static int PARSE_PROBLEM = -20006; //
/// <summary>
///
/// </summary>
public static int NOT_SENT = -20007; //
/// <summary>
///
/// </summary>
public static int MES_SERVICE_NOT_REACHABLE = -20008; //
private int code;
private String text;
/// <summary>
///
/// </summary>
public ResponseDetail(String text, int code)
{
this.text = text;
this.code = code;
}
/// <summary>
///
/// </summary>
public int getCode()
{
return code;
}
/// <summary>
///
/// </summary>
public String getText()
{
return text;
}
}
}

View File

@@ -0,0 +1,154 @@
#region Namespace
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using com.itac.mes.proxy.business;
using com.itac.oib;
#endregion
namespace com.itac.mes.proxy.sockets
{
public class SocketAdapter
{
private readonly IList<IhapHandler> _channels = new List<IhapHandler>();
private readonly TcpListener _listener;
private readonly IAdapterControl _adapterControl;
private readonly OIBServiceImpl _serviceImpl;
private bool _isShutdown = false;
private int listeningPort;
// Wenn ein IHapHandler ein Disconnect feststellt wird eine Verbindung entfernt...
public void ClientDisconnected(IhapHandler iHapHandler)
{
// remove handler with disconnected sockets
for (int i = _channels.Count - 1; i >= 0; i--)
{
IhapHandler element = _channels[i];
if (element == iHapHandler)
{
_channels[i].shutdown();
_channels.RemoveAt(i);
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Remove socket connection.");
}
}
LogHandler.log(Constants.LOGGER, TraceEventType.Verbose, "Nr of active connections: " + _channels.Count);
}
public SocketAdapter(int listeningPort, IAdapterControl adapterControl, OIBServiceImpl serviceImpl)
{
_listener = new TcpListener(IPAddress.Any, listeningPort);
_listener.Start();
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Listen on port " + listeningPort);
_adapterControl = adapterControl;
_serviceImpl = serviceImpl;
var thread = new Thread(Run);
thread.Start();
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Startup " + Constants.SERVICE_NAME + " finished.");
//
// neuen Thread aufmachen, der immer wieder nachguckt, wie oft die IHapHandler benutzt werden. und unbenutzte Verbindungen entfernt
var checkAliveThread = new Thread(RunCheckAlive);
checkAliveThread.Start();
}
public void Run()
{
Thread.CurrentThread.Name = "SocketAdapter";
while (!_isShutdown)
{
TcpClient client;
try
{
client = _listener.AcceptTcpClient();
}
catch (SocketException se)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Critical, "Accepting new socket connection failed", se);
continue;
}
var handler = new IhapHandler(client, _serviceImpl);
handler.setAdapterControl(_adapterControl);
handler.ClientDisconnected += ClientDisconnected;
_channels.Add(handler);
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Incoming socket connection from " + client.Client.RemoteEndPoint);
}
}
public void RunCheckAlive()
{
Thread.CurrentThread.Name = "CheckAliveThread";
while (!_isShutdown)
{
bool removed = false;
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "registered incoming socket connections: " + _channels.Count);
try
{
for (int i = _channels.Count - 1; i >= 0; i--)
{
var channel = _channels[i];
if (!channel.isConnected())
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "remove disconnected incoming socket connection for " + channel.getName());
_channels.Remove(channel);
removed = true;
continue;
}
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "" + channel.getName() + " channel last used: " + new DateTime(channel.getLastCall()));
if ((channel.getLastCall() + 36001000L) < DateTime.Now.Ticks) // eine Stunde...
{
// Verbindung schliessen, wenn Sie länger als ... nicht benutzt wurde
// channel.shutdown();
}
}
if (removed)
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "remaining open incoming socket connections after cleanup: " + _channels.Count);
}
}
catch (Exception )
{
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "service channel listing interrupted");
}
// LG: Why this??
Thread.Sleep(60000);
}
}
public void Shutdown()
{
_isShutdown = true;
try
{
_listener.Stop();
foreach (var channel in _channels)
{
if (channel.isConnected())
{
channel.shutdown();
}
}
_channels.Clear();
}
catch
{
}
LogHandler.log(Constants.LOGGER, TraceEventType.Information, "Listen port closed.");
}
}
}

View File

@@ -0,0 +1,7 @@
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\bin\Debug\CommonSmtPlugin.dll
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\bin\Debug\CommonSmtPlugin.pdb
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\bin\Debug\artes-dotnet.dll
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\bin\Debug\CommonSmtApi.dll
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\obj\Debug\Plugin.csprojResolveAssemblyReference.cache
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\obj\Debug\CommonSmtPlugin.dll
C:\projects_jee\imsinterface\mainline\interface\commonsmt\dotnetplugin\Plugin\obj\Debug\CommonSmtPlugin.pdb

View File

@@ -0,0 +1,340 @@
/*
* Copyright (c) 2015 iTAC Software AG, Germany. All Rights Reserved.
*
* This software is protected by copyright. Under no circumstances may any part of this file in any form be copied,
* printed, edited or otherwise distributed, be stored in a retrieval system, or be translated into another language
* without the written permission of iTAC Software AG.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace com.itac.mes.tools
{
/// <summary>
/// This Class is able to serialize all objects to a xml string.
/// </summary>
public class ItacXmlSerializer
{
private static int MAX_INDENT_LEVEL = 15;
private static int indentationWidth = 2;
private int indentationLevel = 0;
private bool formatting = true;
private StringBuilder writer;
private static String[] indentStrings;
private bool logXmlFormat = true;// Eine Möglichkeit auch nicht-XML zu loggen
static ItacXmlSerializer()
{
indentStrings = new String[MAX_INDENT_LEVEL];
for (int level = 0; level < MAX_INDENT_LEVEL; level++)
{
StringBuilder indentBuffer = new StringBuilder();
int count = level * indentationWidth;
for (int i = 0; i < count; i++)
{
indentBuffer.Append(' ');
}
indentStrings[level] = indentBuffer.ToString();
}
}
// [MethodImpl(MethodImplOptions.Synchronized)]
/// <summary>
///
/// </summary>
public StringBuilder serialize(Object source)
{
if (source == null) { return new StringBuilder("null"); }
writer = new StringBuilder();
if (source.GetType().IsArray)
{
writeArray("", source);
}
else
{
writeStart(source.GetType().Name, true);
writeStructure(source);
writeEnd(source.GetType().Name, true, true);
}
return writer;
}
private void indent()
{
if (formatting)
{
indentationLevel += 1;
}
}
private void unindent()
{
if (formatting && indentationLevel > 0)
{
indentationLevel -= 1;
}
}
private void writeArray(String fieldName, Object fieldvalue)
{
Object[] array = (Object[])fieldvalue;
// do not print empty arrays
if (array != null && array.Length > 0)
{
if (!fieldName.Equals(""))
{
writeStart(fieldName, true);
}
String simpleClassName = fieldvalue.GetType().Name.Substring(0, fieldvalue.GetType().Name.Length - 2);
for (int i = 0; i < array.Length; i++)
{
writeStart(simpleClassName, true);
writeObject("", array[i]);
writeEnd(simpleClassName, true, false);
}
if (!fieldName.Equals(""))
{
writeEnd(fieldName, true, false);
}
}
}
private void writeList(String fieldName, Object fieldvalue)
{
IList array = (IList)fieldvalue;
// do not print empty arrays
if (array != null && array.Count > 0)
{
if (!fieldName.Equals(""))
{
writeStart(fieldName, true);
}
String simpleClassName = fieldvalue.GetType().Name.Substring(0, fieldvalue.GetType().Name.Length - 2);
for (int i = 0; i < array.Count; i++)
{
// writeStart(simpleClassName, true);
writeStructure(array[i]);
// writeEnd(simpleClassName, true, false);
}
if (!fieldName.Equals(""))
{
writeEnd(fieldName, true, false);
}
}
}
private void allClassProperties(List<PropertyInfo> fieldList, Type clazz)
{
// über alle Felder aller parent Interfaces, solange das Interface nicht Object ist.
if (clazz == null || clazz == typeof(Object))
{
return;
}
// fields: all public fields
PropertyInfo[] fields = clazz.GetProperties();
foreach (PropertyInfo field in fields)
{
fieldList.Add(field);
}
allClassProperties(fieldList, clazz.BaseType);
}
private void allClassFields(List<FieldInfo> fieldList, Type clazz)
{
// über alle Felder aller parent Interfaces, solange das Interface nicht Object ist.
if (clazz == null || clazz == typeof(Object))
{
return;
}
// fields: all public fields
FieldInfo[] fields = clazz.GetFields(BindingFlags.Instance| BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
fieldList.Add(field);
}
// allClassFields(fieldList, clazz.BaseType);
}
private void writeStructure(Object source)
{
List<PropertyInfo> propertyList = new List<PropertyInfo>();
allClassProperties(propertyList, source.GetType());
List<FieldInfo> fieldList = new List<FieldInfo>();
allClassFields(fieldList, source.GetType());
foreach (PropertyInfo field2 in propertyList)
{
try
{
Object fieldvalue = field2.GetValue(source, null);
writeObject(field2.Name, fieldvalue);
}
catch (Exception)
{
writeObject(field2.Name, "property write failed");
}
}
foreach (FieldInfo field2 in fieldList)
{
try
{
Object fieldvalue = field2.GetValue(source);
writeObject(field2.Name, fieldvalue);
}
catch (Exception)
{
writeObject(field2.Name, "field write failed");
}
}
}
private void writeObject(String fieldName, object fieldvalue)
{
if (fieldvalue == null)
{
return;
}
if (fieldvalue.GetType() == typeof(String))
{
writeString(fieldName, (String)fieldvalue);
}
else if (fieldvalue.GetType() == typeof(DateTime))
{
writeDate(fieldName, (DateTime)fieldvalue);
}
else if (fieldvalue.GetType() == typeof(bool) || fieldvalue.GetType() == typeof(Boolean))
{
if (((bool)fieldvalue)) { writeString(fieldName, "true"); } else { writeString(fieldName, "false"); }
}
else if (fieldvalue.GetType() == typeof(byte) || fieldvalue.GetType() == typeof(int) || fieldvalue.GetType() == typeof(Int16) || fieldvalue.GetType() == typeof(Int32)
|| fieldvalue.GetType() == typeof(Int64))
{
writeIntNumber(fieldName, (Object)fieldvalue);
}
else if (fieldvalue.GetType() == typeof(double) || fieldvalue.GetType() == typeof(float))
{
writeNumber(fieldName, (Object)fieldvalue);
}
else if (fieldvalue.GetType() == typeof(Double))
{
writeNumber(fieldName, (Object)fieldvalue);
}
else if (fieldvalue.GetType().IsGenericType)
{
writeList(fieldName, fieldvalue);
}
else if (fieldvalue.GetType().IsArray)
{
writeArray(fieldName, fieldvalue);
}
else
{
// Strukturierten Wert schreiben
writeStart(fieldName, true);
writeStructure(fieldvalue);
writeEnd(fieldName, true, false);
}
}
private void writeDate(String fieldName, DateTime fieldvalue)
{
writeStart(fieldName, false);
writer.Append(fieldvalue.ToString("o"));
writeEnd(fieldName, false, false);
}
private void writeStart(string fieldName, bool endLineAndIndent)
{
startLine();
if (logXmlFormat)
{
writer.Append("<");
writer.Append(fieldName);
writer.Append(">");
}
else
{
writer.Append(fieldName);
writer.Append(": ");
}
if (endLineAndIndent)
{
endLine();
indent();
}
}
private void writeEnd(string fieldName, bool indenting, bool newLine)
{
if (logXmlFormat)
{
if (indenting)
{
unindent();
startLine();
}
writer.Append("</");
writer.Append(fieldName);
writer.Append(">");
endLine();
}
else
{
if (indenting)
{
unindent();
}
if (newLine)
{
endLine();
}
}
}
private void writeNumber(String fieldName, Object fieldvalue)
{
writeStart(fieldName, false);
writer.Append(fieldvalue.ToString());
writeEnd(fieldName, false, true);
}
private void writeIntNumber(String fieldName, Object fieldvalue)
{
writeStart(fieldName, false);
writer.Append(fieldvalue.ToString());
writeEnd(fieldName, false, true);
}
private void writeString(String fieldName, String value)
{
writeStart(fieldName, false);
writer.Append(value);
writeEnd(fieldName, false, true);
}
private void endLine()
{
if (formatting)
{
writer.Append("\n");
}
}
private void startLine()
{
if (formatting)
{
writer.Append(indentStrings[Math.Min(indentationLevel, MAX_INDENT_LEVEL)]);
}
}
}
}