Sunny Son's Blog (손인선)

June 30, 2017

ICS(Integration Cloud Service)를 통한 HCM(Human Capital Management) 연계 (Integrate HCM and others via ICS)

Filed under: Cloud — sunnyson @ 1:23 pm
Tags: , , , ,

Oracle 의 기존 ERP제품의 클라우드 버젼이 많이 발표 되었습니다.
대표적인 제품 중의 하나가 HCM(Human Capital Management) 제품입니다.
한국에서도 모 회사에 판매가 되어 좋은 레퍼런스가 되고 있습니다.

이 서비스 POC 중에 경험 했던 내용을 정리하고자 합니다.

사용된 제품은 HCM과 이를 연계하기 위한 ICS (Integration Cloud Service) 입니다.

HCM을 사용하게 되면 볼 수 있는 화면은 다음과 같습니다.

HCM GUI

이번 시나리오는 Employee Information을 조회 / 업데이트 하는 것입니다.
HCM상에서 조회하는 화면은 다음과 같습니다.

HCM_Employee_Information

전체 시나리오 화면은 다음과 같습니다.

HCM_Integration_Scenario

클라이언트 단은 별도의 프로그램을 작성하지 않고 SOAP UI를 통하여 JSON 형태의 데이터를 전달하였습니다.

HCM_Integration_Scenario2

이제 그 절차에 대해서 화면으로 설명하겠습니다.

Slide6Slide7

이 부분은 HCM에서 확인하는 것입니다. Business Object 를 탐색하는 것입니다. 해당 Business Object를 찾는게 어렵기는 합니다.

Slide8

실제로 HCM Business Object는 웹서비스 형태입니다. 이렇게 WSDL형태로 외부에 노출이 됩니다.

새로운 Integration을 생성합니다.

Slide9

HCM과의 연계를 위하여 새로이 어댑터를 생성하고자 합니다. Oracle HCM Cloud를 선택합니다.

Slide10

신규 HCM 연결 어댑터를 만드는 겁니다. 이름 지정합니다.

Slide11

HCM_Invoke라는 것을 만들었습니다. 아래 보시면 WSDL URL이 있습니다.

Slide12

HCM을 연결하기 위한 ID / Password 등이 보입니다.

Slide13

신규 Integration을 작성하고자 합니다. 편의를 위해서 4가지의 기본 Style 혹은 Pattern을 제공합니다. 선택하셔서 실제 편집중에 수정하실 수 있습니다.

Slide14

Integration에 대한 이름등을 지정합니다.

Slide15

Trigger 부분에서 부터 시작합니다. 즉, 외부 Client가 호출하는 부분입니다. 여기서는 REST로 하겠습니다. 왼쪽의 Generic Rest Connector를 Drag & Drop해서 가운데 동그라미 부분에 넣습니다.

Slide16

이 REST Endpoint 부분에 대한 설정을 합니다. 이 부분은 HCM의 데이터를 갖고 오는 시나리오이므로, REST의 룰에 의해 GET 을 선택합니다.

Slide17

REST API는 Query Parameter 를 전달합니다. 이 Query Parameter에 HCM에서 데이터를 조회할 키 부분을 넣을 수 있습니다.

Slide18

조회한 데이터를 Client에 돌려 주는 JSON 데이터를 미리 작성한 샘플로 넣었습니다.

Slide19

종료되었습니다.

Slide20

이제 가장 앞 Trigger 부분이 생성되었습니다. 그리고 바로 아래 화살표 부분이 같이 생성됩니다. 이것은 데이터 매핑을 위해 자동으로 생성되는 것입니다.

Slide21

이제 HCM 부분을 호출해야 합니다. 이를 위해서 앞서 생성한 HCM Connector를 Drag & Drop 으로 생성합니다.

Slide22초기화 작업 중입니다.

Slide23

이 부분은 HCM을 호출하는 어댑터 이름을 지정합니다.

Slide24

앞서 Connector 생성시에는 연결 정보만 있습니다. 이제 실제 HCM에서 호출할 Business Object를 선택해야 합니다. 이 부분에 대해서는 HCM Consultant 에게 도움을 받아야할 것 같습니다.

Slide25

생성 되었습니다.

Slide26

Client에서 들어오는 데이터를 HCM을 호출하기 위하여 변경하여야 합니다.

Slide27

앞서 Query Parameter로 받은 값을 HCM에서 필요로 하는 값으로 매핑합니다.

Slide28

이제 Client에 반환하는 데이터를 매핑합니다.

Slide29

왼쪽이 HCM 데이터입니다. 이 부분에서 필요로 하는 부분을 오른쪽으로 매핑합니다.

Slide30

이제 다 됬습니다.

Slide31

개발자의 가장 중요한 부분의 하나는 모니터링입니다. 지나 다니는 데이터를 확인할 수 있습니다. 저는 Phone Number를 선택하였습니다.

Slide33

작업을 마친 Integration은 바로 작동하지 않습니다. 일단 Pending 상태이구요, 원하실때 Activation 하면 됩니다. 가운데 체크 표시는 앞서 지정한 모니터링 부분을 수행할 것인지를 묻는 것입니다.

Slide34

해당 Integration의 오른쪽에 느낌표가 있습니다. 이 부분에 마우스를 올리면 해당 Integration에 대한 정보를 확인할 수 있습니다.

Slide35

위의 URL (파란색 부분)을 클릭하면 해당 Integration 에 Endpoint에 접속합니다. 어떤 Method를 사용하는지, 어떤 형태의 데이터를 넣어야 하는지, 어떤 결과 값을 받는지를 참조하여 프로그래머에게 도움을 줄 수 있습니다.

Slide36

SOAP UI를 통해 간단하게 테스트 해봤습니다.

Slide37

테스트 도구는 다양합니다. POST MAN도 있구요, 저는 Firefox를 사용하는데 REST Client라는 Add-on 프로그램도 꽤 좋은 툴입니다.

이상이 Employee Information 을 조회하는 설정입니다.

다음은 Update를 하는 부분입니다. 참조하세요

Slide38Slide39

ICS는 기본적으로 Endpoint 라는, 이 시나리오에서는 SOAP UI라는 Client를 사용하는데요, 외부에 노출되는 부분을 생성합니다. 기본적으로 REST 형태를 지원하지만, 필요하다면 SOAP 등도 사용할 수 있습니다.

Slide40

이부분은 Update 이기 때문에, REST 사용시 기본적인 PUT option 을 선택합니다.

Slide41

잘 아시겠지만, REST는 Query Parameter를 지정해야 하죠. 이번에는 PUT 이기 때문에 Query Parameter는 지정하지 않겠습니다.

Slide42

이번 시나리오에서는 JSON  데이터를 사용하고자 합니다. 이때 XML, URL-encoded 데이터 형태도 사용할 수 있습니다.

Slide43

이미 생성된 JSON 데이터를 업로드하실 수도 있고, 아니면 간략하게 샘플 데이터를 직접 넣을 수도 있습니다.

Slide44Slide45Slide46

이 부분이 ICS 제품에서 실제 디자인을 담당하는 화면입니다. 가장 윗 부분에 보이는 UpdatePhone(trigger) 라는 부분이 외부에서 호출되는 부분입니다. 그리고 다음 UpdatePhone(화살표) 부분은 JSON data를 매핑하는 부분입니다.

Slide47

왼쪽에 보이는 Invokes 부분에서 이미 만들어진 HCM_Invoke Adapter 부분을 Drag & Drop 형태로 끼워 놓습니다.

Slide48

HCM 을 호출하는 커넥터 부분입니다. 어댑터라고도 하구요. 이 부분의 이름을 변경하실 수도 있습니다.

Slide49

앞서 Query 부분에서 보았듯이, HCM Connector기본적으로는 HCM에 연결하기 위한 기본적인 연결 정보만을 가지고 있습니다. 이제 HCM에서 실제 호출할 서비스 명을 지정합니다. 필요하다면 이 작업을 여러번 하여 여러개의 서비스를 호출할 수 있습니다.

Slide50Slide51

HCM Connector를 배치하면 다시 화살표 모양의 매핑할 수 있는 component가 생성됩니다.

Slide52

이제 매핑을 해보겠습니다. 일차로 client에서 들어온 데이터를 HCM을 호출 할때 사용하도록 데이터 매핑을 하겠습니다.

Slide53

왼쪽은 Client에서 들어온 데이터이고 오른쪽은 HCM의 mergePerson 이라는 서비스를 호출하는 메타 데이터입니다. 이 메타 데이터가 일반적으로 굉장히 복잡합니다. 정확한 데이터의 위치를 찾는 것이 상당히 어렵습니다. 저도 이 부분을 확인하느라고 HCM GUI와 계속 비교 해봤었습니다.

Slide54

다시 Client에게 돌려주는 부분의 매핑도 합니다. (생략)

Slide55

ICS상에서 실제 운영시 모니터링을 할 수 있습니다. 이 때 어떠한 데이터를 모니터링 할 것인가를 결정하는 부분입니다. 저는 전화번호를 수정할 꺼니까 이 부분을 모니터링 하기로 했습니다.

Slide56

ICS 에서 작업을 마쳤습니다. 작업은 마쳤지만, 실행이 되는 것은 아닙니다. Activation 이라는 부분을 마쳐야 하는 것이죠. 위의 그림에서 보듯이 오른쪽에 초록색 화살표로 되는 것이 실제 작동하는 것이고, Pending Activation 은 실제로 구동하지 않는 것입니다. 실제 운영시에도 언제든지 이 부분의 선택을 통하여 작동 / 정지를 선택할 수 있습니다.

Slide57Slide58

작성한 Integration 의 옆에 보면 느낌표가 있습니다. 이 느낌표 위에 마우스를 올리면 해당 Integration에 대한 정보를 알 수 있습니다. 특히 Endpoint URL이 있는데요(즉 Client에서 연결하는 부분) 이 부분은 다시 링크가 되어 있습니다. 이 부분을 클릭하면 다음의 데이터를 확인할 수 있습니다.

Slide59

앞서 URL를 선택하면 나오는 샘플 및 Method 등입니다. 앞서 Integration 작성시 넣었던 샘플이 사용되어 예를 들어주고 있습니다.

Slide60

SOAP UI를 통하여 역시 테스트를 마쳤습니다.

Slide61

실제 HCM UI를 통하여 특정인의 데이터를 변경한 화면입니다.

이상이 HCM의 데이터를 조회하고 업데이트 하는 방법입니다.

감사합니다.

June 15, 2016

Oracle MFT – callout to support sub-directory

Filed under: 써니,SOA — sunnyson @ 6:07 pm
Tags: , , , , ,

Till now (June 15th 2016), Oracle MFT product doesn’t support file transferring especially with sub-directory.
So thus, I made a Java Callout in order to resolve this matter for a customer who purchased and need it urgently.


  1. Source Pre-processing
    – Java Callout : com.oracle.callout.sample.SrcPre1
    -Xml file for Callout : SrcPre1.xml
  2. Target Pre-processing
    -Java Callout : com.oracle.callout.sample.InsertFolderForFTP
    -Xml file for Callout : InsertFolderForFTP.xml
  3. Compile
    – Core-12.1.1.0.jar, mdsrt.jar should be added into CLASSPATH
    – Org.apache.commons-net-1.4.1.jar( for FTP)
  4. Install
    -$ cp InsertFolderForFTP.jar $MW_HOME/user_projects/domains/base_domain/mft/callouts/
    -$ $MW_HOME/mft/common/bin/wlst.sh
    -connect(“weblogic”, “<PASSWORD>, “t3://localhost:7001”)
    -createCallouts(‘/home/oracle/InsertFolderForFTP.xml’)
    -createCallouts(‘/home/oracle/SrcPre1.xml’)
  5. Log : /tmp/mft/*.log
    – Hard coded at Java Callout source itself. It should be changed.

Java Source code –  SrcPre1.java

package com.oracle.callout.sample;

import java.io.File;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

import java.io.PrintWriter;

import java.util.Map;

import oracle.tip.mft.engine.processsor.plugin.PluginContext;
import oracle.tip.mft.engine.processsor.plugin.PluginOutput;
import oracle.tip.mft.engine.processsor.plugin.PreCalloutPlugin;
import oracle.tip.mft.bean.MFTMessage;
import oracle.tip.mft.bean.SourceMessage;
import oracle.tip.mft.bean.TargetMessage;

import java.sql.*;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Hashtable;

import java.util.Iterator;
import java.util.List;

import java.util.StringTokenizer;

import javax.naming.*;

import oracle.tip.mft.engine.mds.MdsManager;
import oracle.tip.mft.mds.model.source.SourceMO;
import oracle.tip.mft.system.MFTBeanFactory;
import oracle.tip.mft.system.MFTUtil;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import oracle.mds.core.*;

import oracle.tip.mft.common.transport.util.EngineTransportUtil;
import oracle.tip.mft.mds.model.binding.TechnologyBindingType;
import oracle.tip.mft.mds.model.category.SourceTargetCategoryType;

//import com.google.common.base.Splitter;

public class SrcPre1 implements PreCalloutPlugin {

@Override
public boolean isPayloadChangeRequired(PluginContext pluginContext, Map<String, String> map) {
return false;
}

@Override
// This function will be called only if the isPayloadChangesRequired returns false.
public PluginOutput process(PluginContext pluginContext, InputStream input, Map<String, String> calloutParams) {
PluginOutput res = new PluginOutput();

try {
PluginOutput out    = new PluginOutput();
String protocolType = “FTP”;
String FolderName   = null;

String SourceName = getSourceName(pluginContext.getMessage().toString());
MdsManager mdsMgr = (MdsManager) MFTBeanFactory.getBean(“mdsManager”);

List moList = mdsMgr.getAllSources();
SourceMO mo;

for (Iterator i$ = moList.iterator(); i$.hasNext();) {
mo = (SourceMO) i$.next();

//                logme(“\n getSourceID = [” + mo.getSource().getId() + “]”);
//                logme(“\n getSourceName = [” + mo.getSource().getName() + “]”);
//                logme(“\n getSourceID = [” + mo.getSource().toString() + “]”);
//                logme(“\n getSourceID = [” + mo.getMDSInstance().getMDSConfig().toString() + “]”);
//                logme(“\n getSourceID = [” + mo.getTypeName().toString() + “]”);
//                logme(“\n getSourceID = [” + mo.getReference().getMOName() + “]”);

SourceTargetCategoryType sourceTargetCategory =
mo.getSource().getSourceType().getSourceTargetCategory();
String _SourceName = mo.getSource().getName();
TechnologyBindingType protocal = EngineTransportUtil.getTechnologyBindingFromMO(sourceTargetCategory);
if (protocal != null && _SourceName.equals(SourceName)) {
protocolType = protocal.getType();
//                    logme(“protocolType = ” + protocolType + “,SourceName = ” + SourceName);
if (protocolType.equals(“FTP”)) {
TechnologyBindingType.FTPType ftptype = protocal.getFTP();
FolderName = ftptype.getFolder();
break;
} else if (protocolType.equals(“SSH-FTP”)) {
TechnologyBindingType.SSHFTPType sshftptype = protocal.getSSHFTP();
FolderName = sshftptype.getFolder();

break;
}
break;

}
}

logme(“++ Source [” + pluginContext.getCustomPropertyMap().get(“directory.path”) +
“/” + pluginContext.getTransformedInputFileName() +
“] with “+protocolType+”, SourceName = [” + SourceName + “]++”);
//Debug
//logme(“\n++ Source Context tostring = [” + pluginContext.getMessage().toString() + “]”);
//logme(“\n++ Source Context tostring = [” + pluginContext.getTransformedInputFileName()+ “]”);
// In order to pass root directory of source server.
pluginContext.getCustomPropertyMap().put(“FolderName”, FolderName);
return out;
} catch (Exception e) {
e.printStackTrace();
res.setException(new Exception(“Callout:RENAMEEXP- Exception in custom plugin class:\n” +
pluginContext.getMessage()));
}
return res;
}

@Override
// This function will be called only if the isPayloadChangesRequired returns true.
public PluginOutput process(PluginContext context, InputStream input, OutputStream out,
Map<String, String> calloutParams) {
return null;
}

public void logme(String text) {
try {
PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(“/tmp/mft/RenameRegexp.txt”, true)));
String timeStamp = new SimpleDateFormat(“yyyy.MM.dd.HH.mm.ss”).format(new java.util.Date());
output.write(timeStamp + “:”);
output.write(text);
output.write(“\n”);
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public String getSourceName(String _input) {
String _s2 = null, _s3 = null;

StringTokenizer st1 = new StringTokenizer(_input, “, “);
while (st1.hasMoreElements()) {
//System.out.println(st1.nextElement());
_s2 = (String) st1.nextElement();
if (_s2.contains(“sourceName=”)) {
_s3 = _s2.substring(_s2.lastIndexOf(“sourceName=”) + “sourceName=”.length());
break;
}
}
return _s3;
}

}

 


Java Source code –  InsertFolderForFTP.java

package com.oracle.callout.sample;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

import java.io.File;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;

import java.io.PrintWriter;

import java.util.Map;

import oracle.tip.mft.engine.processsor.plugin.PluginContext;
import oracle.tip.mft.engine.processsor.plugin.PluginOutput;
import oracle.tip.mft.engine.processsor.plugin.PreCalloutPlugin;
import oracle.tip.mft.bean.MFTMessage;
import oracle.tip.mft.bean.SourceMessage;
import oracle.tip.mft.bean.TargetMessage;

import java.sql.*;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Hashtable;

import java.util.Iterator;
import java.util.List;

import java.util.StringTokenizer;

import javax.naming.*;

import oracle.tip.mft.system.MFTUtil;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

import oracle.tip.mft.bean.*;
import oracle.tip.mft.common.transport.util.EngineTransportUtil;
import oracle.tip.mft.engine.mds.MdsManager;
import oracle.tip.mft.mds.model.binding.TechnologyBindingType;
import oracle.tip.mft.mds.model.category.SourceTargetCategoryType;
import oracle.tip.mft.mds.model.security.SSH;
import oracle.tip.mft.mds.model.source.SourceMO;
import oracle.tip.mft.mds.model.target.TargetMO;
import oracle.tip.mft.security.SecurityUtility;
import oracle.tip.mft.system.GlobalContext;
import oracle.tip.mft.system.MFTBeanFactory;
import oracle.tip.mft.transport.adapter.impl.ftp.FTPTransportReceiver;
import oracle.tip.mft.transport.adapter.impl.ftp.FTPTransportUtil;

public class InsertFolderForFTP implements PreCalloutPlugin {

@Override
public boolean isPayloadChangeRequired(PluginContext pluginContext, Map<String, String> map) {
return false;
}

@Override
// This function will be called only if the isPayloadChangesRequired returns false.
public PluginOutput process(PluginContext pluginContext, InputStream input, Map<String, String> calloutParams) {
PluginOutput res = new PluginOutput();
String newfname = “”;
String oldfname = “”;
String protocol = “FTP”;

try {
// Should be considered how to get rid of these parameters. It should be inherited from MFT framework
String TargetName     = getTargetName(pluginContext.getMessage().toString());
String TargetFolder   = null;
String TargetHostname = null;
String Targetusername = null;
String Targetpassword = null;
String protocolType   = null;
int TargetPort = 21;

// this code only works for Target Pre- processing
PluginOutput out = new PluginOutput();
oldfname         = pluginContext.getTransformedInputFileName();

// Query MDS to get all target list and compare with name from MFTConsole configuration
MdsManager mdsMgr = (MdsManager) MFTBeanFactory.getBean(“mdsManager”);
List moList = mdsMgr.getAllTargets();
TargetMO mo;

for (Iterator i$ = moList.iterator(); i$.hasNext();) {
mo = (TargetMO) i$.next();

SourceTargetCategoryType sourceTargetCategory =
mo.getTarget().getTargetType().getSourceTargetCategory();

TechnologyBindingType protocal = EngineTransportUtil.getTechnologyBindingFromMO(sourceTargetCategory);
String _TargetName = mo.getTarget().getName();
if (protocal != null && _TargetName.equals(TargetName)) {
protocolType = protocal.getType();
if (protocolType.equals(“FTP”)) {
TechnologyBindingType.FTPType ftptype = protocal.getFTP();
TargetFolder   = ftptype.getFolder();
TargetHostname = ftptype.getHost();
TargetPort     = ftptype.getControlPort();
Targetusername = ftptype.getUser();
//Targetusername = ftptype.
Targetpassword = SecurityUtility.getPasswordCredentialAsString(ftptype.getPassword());
break;
} else if (protocolType.equals(“SSH-FTP”)) {
protocol = “SSH-FTP”;
TechnologyBindingType.SSHFTPType sshftptype = protocal.getSSHFTP();
TargetFolder   = sshftptype.getFolder();
TargetHostname = sshftptype.getHost();
TargetPort     = sshftptype.getPort();
Targetusername = sshftptype.getUser();
Targetpassword = SecurityUtility.getPasswordCredentialAsString(sshftptype.getPassword());
break;
}

}
}

String SourceFolder     = pluginContext.getCustomPropertyMap().get(“FolderName”);
String SubDirectoryName = pluginContext.getCustomPropertyMap().get(“directory.path”);
SubDirectoryName =
SubDirectoryName.substring(SubDirectoryName.lastIndexOf(SourceFolder) + SourceFolder.length());

if (protocol.equals(“FTP”)) {
if(SubDirectoryName.length() > 0) SubDirectoryName = SubDirectoryName.substring(1);
if(SubDirectoryName.length() > 0)
newfname = TargetFolder + “/” + SubDirectoryName + “/” + oldfname; // worked relative path but not absolute path
else
newfname = TargetFolder + “/” + oldfname; // worked relative path but not absolute path
}
else if (protocol.equals(“SSH-FTP”))
newfname = SubDirectoryName+ “/” + oldfname;

destFileName = newfname;
logme(“with ” + protocolType + “, TargetName = [” + TargetName + “]++”);

if (newfname != null && newfname.length() > 0) {
// Check & Create subdirectories for each files.
// Should be modified to process exceptions later.
if (protocol.equals(“FTP”))
checkTargetDirectoryFTP(TargetHostname, TargetPort, Targetusername, Targetpassword,
TargetFolder + “/” + SubDirectoryName);
else if (protocol.equals(“SSH-FTP”))
checkTargetDirectorySFTP(TargetHostname, TargetPort, Targetusername, Targetpassword,
TargetFolder + SubDirectoryName);

// Set new filename with sub directory name
out.setNewFileName(newfname);
}
return out;
} catch (Exception e) {
e.printStackTrace();
res.setException(new Exception(“Callout:RENAMEEXP- Exception in custom plugin class:\n” +
pluginContext.getMessage()));
}
return res;
}

@Override
// This function will be called only if the isPayloadChangesRequired returns true.
public PluginOutput process(PluginContext context, InputStream input, OutputStream out,
Map<String, String> calloutParams) {
return null;
}

public void logme(String text) {
rawlog(“++ Target [” + destFileName + “] ” + text);
}

public void rawlog(String text) {
try {
PrintWriter output = new PrintWriter(new BufferedWriter(new FileWriter(“/tmp/mft/RenameRegexp.txt”, true)));
String timeStamp = new SimpleDateFormat(“yyyy.MM.dd.HH.mm.ss”).format(new java.util.Date());
output.write(timeStamp + “:”);
output.write(text);
output.write(“\n”);
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public int checkTargetDirectoryFTP(String TargetHostname, int TargetPort, String Targetusername,
String Targetpassword, final String directory) {

FTPClient client = new FTPClient();

try {
if (!client.isConnected()) {
client.connect(TargetHostname, TargetPort);
client.login(Targetusername, Targetpassword);
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
logme(“Negative reply form FTP server, aborting, id was {}:” + reply);
throw new IOException(“failed to connect to FTP server”);
}
}

String[] iterable = directory.split(“/”);
String dir = “”;
boolean dirExists1 = client.changeWorkingDirectory(directory);
if(!dirExists1) {
for (int i = 1; i < iterable.length; i++) {
dir = dir + “/” + iterable[i];
boolean dirExists = client.changeWorkingDirectory(dir);
if (!dirExists) {
// try to create directory:
logme(” try to create directory [” + dir + “]\n”);
client.makeDirectory(dir);
dirExists = client.changeWorkingDirectory(dir);
}
if (!dirExists) {
logme(“failed to change FTP directory (forms), not doing anything\n”);
return -1;
}
}
} else {
logme(“!! Target Directory [” + directory + “] existing already, skip!!\n”);
}

if (client.isConnected()) {
client.disconnect();
}
} catch (Exception s) {
return -1;
}
return 0;
}

public int checkTargetDirectorySFTP(String TargetHostname, int TargetPort, String Targetusername,
String Targetpassword, final String directory) {

try {
//            logme(“\nEstablishing Connection.0..”);
JSch jsch = new com.jcraft.jsch.JSch();
//JSch jsch = new JSch();
//            logme(“\nEstablishing Connection..1.”);
Session session = jsch.getSession(Targetusername, TargetHostname, TargetPort);
//            logme(“\nEstablishing Connection..2.”);
session.setPassword(Targetpassword);
session.setConfig(“StrictHostKeyChecking”, “no”);
//            logme(“\nEstablishing Connection…”);
session.connect();
//           logme(“\nConnection established.”);
//           logme(“\nCrating SFTP Channel.”);
ChannelSftp sftpChannel = (ChannelSftp) session.openChannel(“sftp”);
sftpChannel.connect();

//            logme(“\nDirectory:” + sftpChannel.pwd());
//            logme(“\n directory = ” + directory + “\n”);
String[] iterable = directory.split(“/”);
String dir = “”;

Boolean dirExist = false;

try {
sftpChannel.cd(directory);
} catch (SftpException s2) {
dirExist = false;
}

if(!dirExist) {
for (int i = 1; i < iterable.length; i++) {
dir = dir + “/” + iterable[i];
try {
sftpChannel.cd(dir);
} catch (SftpException s2) {
sftpChannel.mkdir(dir);
}
}
}else {
logme(” Target Directory existing already, skip!!”);
}

sftpChannel.disconnect();
session.disconnect();
} catch (Exception s) {
s.printStackTrace();
logme(s.toString());
return -1;
}

return 0;
}

public String getTargetName(String _input) {
String _s2 = null, _s3 = null;

StringTokenizer st1 = new StringTokenizer(_input, “, “);
while (st1.hasMoreElements()) {
_s2 = (String) st1.nextElement();
if (_s2.contains(“targetName=”)) {
_s3 = _s2.substring(_s2.lastIndexOf(“targetName=”) + “targetName=”.length());
break;
}
}
return _s3;
}

private String destFileName = null;

}


SrcPre1.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<mft:Callouts xmlns:mft=”http://xmlns.oracle.com/mft&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://xmlns.oracle.com/mft callout.xsd “>
<mft:Callout description=”Insert Folder For FTP”
helpText=”File Rename with Regular Expressions”
groupName=”Source-pre” timeout=”300″
implementationClass=”com.oracle.callout.sample.SrcPre1″
libraryName=”SrcPre1.jar” name=”SrcPre1″>
</mft:Callout>
</mft:Callouts>


InsertFolderForFTP.xml

<?xml version=”1.0″ encoding=”UTF-8″?>
<mft:Callouts xmlns:mft=”http://xmlns.oracle.com/mft&#8221;
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://xmlns.oracle.com/mft callout.xsd “>
<mft:Callout description=”Insert Folder For FTP”
helpText=”File Rename with Regular Expressions”
groupName=”Target-pre” timeout=”300″
implementationClass=”com.oracle.callout.sample.InsertFolderForFTP”
libraryName=”InsertFolderForFTP.jar” name=”InsertFolderForFTP”>
</mft:Callout>
</mft:Callouts>


MFT Console

mft1mft2mft3mft4

Blog at WordPress.com.