diff --git a/java/src/main/java/com/genexus/sap/DestinationProvider.java b/java/src/main/java/com/genexus/sap/DestinationProvider.java index 7fd6e6fd2..22d3e0d66 100644 --- a/java/src/main/java/com/genexus/sap/DestinationProvider.java +++ b/java/src/main/java/com/genexus/sap/DestinationProvider.java @@ -6,9 +6,11 @@ import com.genexus.diagnostics.Log; import com.sap.conn.jco.ext.DestinationDataEventListener; import com.sap.conn.jco.ext.DestinationDataProvider; +import com.sap.conn.jco.ext.ServerDataEventListener; +import com.sap.conn.jco.ext.ServerDataProvider; import com.sap.conn.jco.ext.Environment; -public class DestinationProvider implements DestinationDataProvider +public class DestinationProvider implements DestinationDataProvider, ServerDataProvider { private static DestinationProvider _instance; @@ -19,10 +21,10 @@ public static DestinationProvider Instance() _instance = new DestinationProvider(); } return _instance; - } private String SAP_SERVER = "SAP_SERVER"; + private String SAP_DOC_SERVER = "DMS_SERVER"; private Properties connectionProperties; private Hashtable connectionList = new Hashtable(); private DestinationDataEventListener eventListener; @@ -52,7 +54,6 @@ public Properties getDestinationProperties(String sessionName) public boolean supportsEvents() { return true; - } /*@Override*/ @@ -61,6 +62,73 @@ public void setDestinationDataEventListener(DestinationDataEventListener eventLi this.eventListener = eventListener; } + @Override + public Properties getServerProperties(String serverName) { + if (serverName != null) + { + Properties val = connectionList.get(serverName); + if (val != null) + { + return val; + } + else + { + return null; + } + } + else + { + return null; + } + } + + @Override + public void setServerDataEventListener(ServerDataEventListener arg0) { + // Our logon parameters don't change dynamically, so we don't need to fire events. See above comment on DestinationDataEventListener. + } + + public void removeServerProperties(String serverName) + { + if (eventListener != null) + { + eventListener.deleted(serverName); + } + connectionProperties = null; + connectionList.remove(serverName); + } + + public void setServerProperties( String serverName, Properties properties) + { + if ( serverName == null || serverName.equals("")) + { + serverName = SAP_DOC_SERVER; + } + if (!Environment.isServerDataProviderRegistered()) + { + Environment.registerServerDataProvider(this); + } + if (properties == null) + { + if (eventListener != null) + { + eventListener.deleted( serverName); + } + connectionProperties = null; + connectionList.remove( serverName); + } + else + { + Log.info("GX SAP Doc Server - Setting Properties : " + serverName + " total : " + Integer.toString(connectionList.size())); + connectionProperties = properties; + connectionList.put( serverName, connectionProperties); + if (eventListener != null) + { + eventListener.updated(serverName); + } + } + } + + public void removeConnectionProperties(String sessionName) { if (eventListener != null) @@ -76,7 +144,6 @@ public void setConnectionProperties( String sessionName, Properties properties) if ( sessionName == null || sessionName.equals("")) { sessionName = SAP_SERVER; - } if (!Environment.isDestinationDataProviderRegistered()) { diff --git a/java/src/main/java/com/genexus/sap/DocumentClient.java b/java/src/main/java/com/genexus/sap/DocumentClient.java new file mode 100644 index 000000000..e996cdbe9 --- /dev/null +++ b/java/src/main/java/com/genexus/sap/DocumentClient.java @@ -0,0 +1,130 @@ +package com.genexus.sap; + +import java.io.*; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import com.sap.conn.jco.AbapClassException; +import com.sap.conn.jco.AbapException; + +import com.sap.conn.jco.JCoFunction; +import com.sap.conn.jco.JCoParameterList; +import com.sap.conn.jco.JCoTable; +import com.sap.conn.jco.server.JCoServer; +import com.sap.conn.jco.server.JCoServerContext; +import com.sap.conn.jco.server.JCoServerContextInfo; +import com.sap.conn.jco.server.JCoServerErrorListener; +import com.sap.conn.jco.server.JCoServerExceptionListener; + +import com.sap.conn.jco.server.JCoServerFunctionHandler; + +public class DocumentClient { + private static final int BLOB_LENGTH = 1022; + + static class ErrorHandler implements JCoServerErrorListener, JCoServerExceptionListener { + + @Override + public void serverExceptionOccurred(JCoServer server, String connectionID, JCoServerContextInfo serverCtx, Exception error) { + // Technical problem in server connection (network, logon data, etc.) + error.printStackTrace(); + } + + @Override + public void serverErrorOccurred(JCoServer server, String connectionID, JCoServerContextInfo serverCtx, Error error) { + // Technical problem in server connection (out-of-memory, etc.) + error.printStackTrace(); + } + + } + + // BAPI_DOCUMENT_CHECKOUTVIEW2 will send the file data via this function module. + static class FTP_R3_TO_CLIENTHandler implements JCoServerFunctionHandler { + + @Override + public void handleRequest(JCoServerContext serverCtx, JCoFunction function) throws AbapException, AbapClassException { + String fname; + int length; + JCoTable blob; + + // In the case of BAPI_DOCUMENT_CHECKOUTVIEW2, MODE is always binary, so the MODE and TEXT parameters of FTP_R3_TO_CLIENT can be ignored. + JCoParameterList imports = function.getImportParameterList(); + fname = imports.getString("FNAME"); + length = imports.getInt("LENGTH"); + blob = function.getTableParameterList().getTable("BLOB"); + FileOutputStream out = null; + try { + out = new FileOutputStream(fname); + boolean hasNextRow = false; + if (!blob.isEmpty()){ + hasNextRow = true; + blob.firstRow(); + } + while (length > BLOB_LENGTH){ + if (hasNextRow){ + out.write(blob.getByteArray(0), 0, BLOB_LENGTH); + length -= BLOB_LENGTH; + hasNextRow = blob.nextRow(); + } + else throw new IOException("Not enough data in table BLOB ("+String.valueOf(BLOB_LENGTH * blob.getNumRows())+") for requested file size (" + String.valueOf(length) + ")"); + } + if (length > 0){ + if (hasNextRow) out.write(blob.getByteArray(0), 0, length); + else throw new IOException("Not enough data in table BLOB ("+String.valueOf(BLOB_LENGTH * blob.getNumRows())+") for requested file size (" + String.valueOf(length) + ")"); + } + } + catch (IOException e) { + e.printStackTrace(); + function.getExportParameterList().setValue("ERROR", 3); + } + finally{ + if (out != null){ + try{ + out.close(); + } + catch (IOException ioe){} + } + } + } + + } + + static class FTP_CLIENT_TO_R3Handler implements JCoServerFunctionHandler { + @Override + public void handleRequest(JCoServerContext serverCtx, JCoFunction function) throws AbapException, AbapClassException { + String fname; + + fname = function.getImportParameterList().getString("FNAME"); + fname = fname.replace("#",""); + + try (InputStream source = Files.newInputStream(Paths.get(fname));) { + + byte[] file2 = new byte[BLOB_LENGTH]; + int bytesread; + int totallenght =0; + + InputStream source2 = Files.newInputStream(Paths.get(fname)); + + JCoTable blobtable = function.getTableParameterList().getTable("BLOB"); + while((bytesread = source2.read(file2,0,file2.length)) >0 ) + { + + blobtable.appendRow(); + blobtable.setValue("LINE", file2); + totallenght += bytesread; + } + + JCoParameterList exports = function.getExportParameterList(); + exports.setValue("LENGTH", totallenght); + } + catch (IOException e) { + e.printStackTrace(); + function.getExportParameterList().setValue("ERROR", 3); + } + } + } + + + +} \ No newline at end of file diff --git a/java/src/main/java/com/genexus/sap/SessionManager.java b/java/src/main/java/com/genexus/sap/SessionManager.java index 3d741b8e9..efccadb15 100644 --- a/java/src/main/java/com/genexus/sap/SessionManager.java +++ b/java/src/main/java/com/genexus/sap/SessionManager.java @@ -1,8 +1,6 @@ package com.genexus.sap; - import java.util.Properties; - import com.genexus.ModelContext; import com.genexus.diagnostics.Log; import com.sap.conn.jco.AbapException; @@ -11,11 +9,22 @@ import com.sap.conn.jco.JCoDestinationManager; import com.sap.conn.jco.JCoException; import com.sap.conn.jco.JCoFunction; +import com.sap.conn.jco.JCoMetaData; +import com.sap.conn.jco.JCoRecordMetaData; +import com.sap.conn.jco.server.JCoServer; +import com.sap.conn.jco.server.DefaultServerHandlerFactory; + import com.sap.conn.jco.ext.DestinationDataProvider; +import com.sap.conn.jco.ext.ServerDataProvider; +import com.sap.conn.jco.server.JCoServerFactory; +import com.sap.conn.jco.JCoCustomRepository; +import com.sap.conn.jco.JCoFunctionTemplate; +import com.sap.conn.jco.JCoListMetaData; +import com.sap.conn.jco.JCo; public class SessionManager { - + private static final int BLOB_LENGTH = 1022; private String msHost = ""; private String msServ = ""; private String group = ""; @@ -41,12 +50,15 @@ public class SessionManager private String registrationCount = "3"; private String programID = ""; private String serverName = ""; + private String repositoryName = ""; private ModelContext _context = null; DestinationProvider destinationProvider = null; Properties connectionProperties=null; - + JCoServer receiver = null; + JCoServer sender = null; + public SessionManager(ModelContext context) { _context = context; @@ -87,14 +99,20 @@ public void Connect() { connectionProperties.setProperty(DestinationDataProvider.JCO_MSSERV, msServ + ":" + port); } - } - connectionProperties.setProperty(DestinationDataProvider.JCO_GWHOST, gatewayHost); - connectionProperties.setProperty(DestinationDataProvider.JCO_GWSERV, gatewayService); - connectionProperties.setProperty(DestinationDataProvider.JCO_R3NAME, systemId); - connectionProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, sapRouter); - connectionProperties.setProperty(DestinationDataProvider.JCO_GROUP, group); - + } } + // Document Transfer server + //connectionProperties.setProperty(DestinationDataProvider.JCO_GWHOST, gatewayHost); + //connectionProperties.setProperty(DestinationDataProvider.JCO_GWSERV, gatewayService); + connectionProperties.setProperty(DestinationDataProvider.JCO_R3NAME, systemId); + connectionProperties.setProperty(DestinationDataProvider.JCO_SAPROUTER, sapRouter); + connectionProperties.setProperty(DestinationDataProvider.JCO_GROUP, group); + + connectionProperties.setProperty(ServerDataProvider.JCO_GWHOST,gatewayHost); + connectionProperties.setProperty(ServerDataProvider.JCO_GWSERV, gatewayService); + connectionProperties.setProperty(ServerDataProvider.JCO_PROGID, programID); + connectionProperties.setProperty(ServerDataProvider.JCO_CONNECTION_COUNT, registrationCount); + // connectionProperties.setProperty(DestinationDataProvider.JCO_SYSNR, instanceNumber); connectionProperties.setProperty(DestinationDataProvider.JCO_CLIENT, clientNumber); connectionProperties.setProperty(DestinationDataProvider.JCO_USER, userName); @@ -113,13 +131,20 @@ public void Connect() Log.info("GX SAP - Connecting " + sessionName); destinationProvider.setConnectionProperties( hashedSession, connectionProperties); + destinationProvider.setServerProperties(serverName, connectionProperties); _context.setContextProperty("SAPSessionName", hashedSession); + + _context.setContextProperty("SAPReceiverServerName", serverName); + _context.setContextProperty("SAPReceiverRepositoryName", repositoryName); + _context.setContextProperty("SAPSenderServerName", serverName); + _context.setContextProperty("SAPSenderRepositoryName", repositoryName); + + try { JCoDestination destination = JCoDestinationManager.getDestination(hashedSession); destination.ping(); - } catch (AbapException ex) { @@ -146,20 +171,182 @@ public void Connect() } } - public void DocumentReceiverStart() + + public JCoServer setupServerDownload(String serverName, String repositoryName) throws JCoException { + JCoServer server = JCoServerFactory.getServer(serverName); + JCoCustomRepository repo = JCo.createCustomRepository(repositoryName); + JCoListMetaData imports, exports, tables; + JCoFunctionTemplate FTP_R3_TO_CLIENT; + + + imports = JCo.createListMetaData("IMPORTING"); + imports.add("FNAME", JCoMetaData.TYPE_CHAR, 256, 512, JCoListMetaData.IMPORT_PARAMETER); + imports.add("LENGTH", JCoMetaData.TYPE_INT, 4, 4, JCoListMetaData.IMPORT_PARAMETER); + imports.add("MODE", JCoMetaData.TYPE_CHAR, 1, 2, JCoListMetaData.IMPORT_PARAMETER | JCoListMetaData.OPTIONAL_PARAMETER); + imports.lock(); + + exports = JCo.createListMetaData("EXPORTING"); + exports.add("ERROR", JCoMetaData.TYPE_INT, 4, 4, JCoListMetaData.EXPORT_PARAMETER); + exports.add("LENGTH", JCoMetaData.TYPE_INT, 4, 4, JCoListMetaData.EXPORT_PARAMETER); + exports.lock(); + + JCoRecordMetaData tabLine = JCo.createRecordMetaData("BLOB"); + tabLine.add("LINE", JCoMetaData.TYPE_BYTE, BLOB_LENGTH, 0, BLOB_LENGTH, 0); + tabLine.lock(); + tables = JCo.createListMetaData("TABLES"); + tables.add("BLOB", JCoMetaData.TYPE_TABLE, tabLine, 0); + tables.lock(); + + FTP_R3_TO_CLIENT = JCo.createFunctionTemplate("FTP_R3_TO_CLIENT", imports, exports, null, tables, null); + repo.addFunctionTemplateToCache(FTP_R3_TO_CLIENT); + server.setRepository(repo); + + DefaultServerHandlerFactory.FunctionHandlerFactory handlerFactory = new DefaultServerHandlerFactory.FunctionHandlerFactory(); + handlerFactory.registerHandler("FTP_R3_TO_CLIENT", new DocumentClient.FTP_R3_TO_CLIENTHandler()); + server.setCallHandlerFactory(handlerFactory); + + DocumentClient.ErrorHandler hdl = new DocumentClient.ErrorHandler(); + server.addServerErrorListener(hdl); + server.addServerExceptionListener(hdl); + + return server; } - public void DocumentSenderStart() - { + + public JCoServer setupServerUpload(String serverName, String repositoryName) throws JCoException + { + JCoServer server = JCoServerFactory.getServer(serverName); + + JCoCustomRepository repo = JCo.createCustomRepository(repositoryName); + JCoListMetaData imports, exports, tables; + JCoFunctionTemplate FTP_CLIENT_TO_R3; + + imports = JCo.createListMetaData("IMPORTING"); + imports.add("FNAME", JCoMetaData.TYPE_CHAR, 256, 512, JCoListMetaData.IMPORT_PARAMETER); + imports.add("MODE", JCoMetaData.TYPE_CHAR, 1, 2, JCoListMetaData.IMPORT_PARAMETER | JCoListMetaData.OPTIONAL_PARAMETER); + imports.lock(); + + exports = JCo.createListMetaData("EXPORTING"); + exports.add("ERROR", JCoMetaData.TYPE_INT, 4, 4, JCoListMetaData.EXPORT_PARAMETER); + exports.add("LENGTH", JCoMetaData.TYPE_INT, 4, 4, JCoListMetaData.EXPORT_PARAMETER); + exports.lock(); + + JCoRecordMetaData tabLine = JCo.createRecordMetaData("BLOB"); + tabLine.add("LINE", JCoMetaData.TYPE_BYTE, BLOB_LENGTH, 0, BLOB_LENGTH, 0); + tabLine.lock(); + + tables = JCo.createListMetaData("TABLES"); + tables.add("BLOB", JCoMetaData.TYPE_TABLE, tabLine, 0); + tables.lock(); + + FTP_CLIENT_TO_R3 = JCo.createFunctionTemplate("FTP_CLIENT_TO_R3", imports, exports, null, tables, null); + repo.addFunctionTemplateToCache(FTP_CLIENT_TO_R3); + server.setRepository(repo); + + DefaultServerHandlerFactory.FunctionHandlerFactory handlerFactory = new DefaultServerHandlerFactory.FunctionHandlerFactory(); + handlerFactory.registerHandler("FTP_CLIENT_TO_R3", new DocumentClient.FTP_CLIENT_TO_R3Handler()); + server.setCallHandlerFactory(handlerFactory); + + DocumentClient.ErrorHandler hdl = new DocumentClient.ErrorHandler(); + server.addServerErrorListener(hdl); + server.addServerExceptionListener(hdl); + + return server; } - public void DocumentSenderStop() + public void DocumentReceiverStart() + { + Log.info("GX SAP - DMS Receiver Start " + serverName + " " + repositoryName); + try { + receiver = setupServerDownload(serverName, repositoryName); + receiver.start(); + } + catch (JCoException ex) + { + Log.error("GX SAP - Error Starting " + ex.toString()) ; + } + } + + public void DocumentReceiverStop() { + String receiverName = ""; + if (serverName == null || serverName.equals("")) + { + Object receiverObj = _context.getContextProperty("SAPReceiverServerName"); + if (receiverObj != null) + { + receiverName = (String)receiverObj; + } + } + else + { + receiverName = serverName; + } + + try { + if (!receiverName.equals("")) + { + receiver = JCoServerFactory.getServer(receiverName); + if (receiver != null) receiver.stop(); + Log.info("GX SAP - DMS Receiver stop " + receiverName ); + } + else + { + Log.error("GX SAP - Error Stopping receiver." ); + } + } + catch (JCoException ex) + { + Log.error("GX SAP - Error Stopping " + ex.toString()) ; + } } - public void DocumentReceiverStop() + public void DocumentSenderStart() + { + Log.info("GX SAP - DMS Sender Start " + serverName + " " + repositoryName); + + try { + sender = setupServerUpload(serverName, repositoryName); + sender.start(); + } + catch (JCoException ex) + { + Log.error("GX SAP - Error Starting " + ex.toString()) ; + } + } + + public void DocumentSenderStop() { + String senderName = ""; + if (serverName == null || serverName.equals("")) + { + Object senderObj = _context.getContextProperty("SAPSenderServerName"); + if (senderObj != null) + { + senderName = (String)senderObj; + } + } + else + { + senderName = serverName; + } + try { + if (!senderName.equals("")) + { + sender = JCoServerFactory.getServer(senderName); + if (sender != null) sender.stop(); + Log.info("GX SAP - DMS Sender stop " + senderName ); + } + else + { + Log.error("GX SAP - Error Stopping sender" ); + } + } + catch (JCoException ex) + { + Log.error("GX SAP - Error Stopping " + ex.toString()) ; + } } public void TransactionBegin() @@ -332,6 +519,12 @@ public String getServerName() } + public String getRepositoryName() + { + return repositoryName; + } + + /* Setters */ public void setPort( String value ) @@ -374,34 +567,34 @@ public void setUserName( String value ) } public void setPassword( String value ) - { + { password = value; - } + } public void setInstanceNumber( String value ) - { + { instanceNumber = value; - } + } public void setAppServer( String value ) - { + { appServer = value; - } + } public void setRouterString( String value ) - { + { routerString = value; } public void setClientNumber( String value ) - { + { clientNumber = value; - } + } public void setSystemId( String value ) - { + { systemId = value; - } + } public void setSessionName( String value ) { @@ -429,14 +622,14 @@ public void setLanguage(String value) } public void setErrorCode( Integer value ) - { + { errorCode = value; - } + } public void setErrorMessage( String value ) - { + { errorMessage = value; - } + } public void setRegistrationCount(String value) { @@ -452,5 +645,10 @@ public void setServerName(String value) { serverName = value; } + + public void setRepositoryName(String value) + { + repositoryName = value; + } } \ No newline at end of file