├── src ├── com │ └── pspace │ │ └── ifsmover │ │ └── rest │ │ ├── script │ │ ├── ifsmoverRest.sh │ │ ├── ifsmoverRest.conf │ │ └── ifsmoverRestLog.xml │ │ ├── PrintStack.java │ │ ├── repository │ │ ├── RepositoryFactory.java │ │ ├── Repository.java │ │ ├── IfsFile.java │ │ └── IfsS3.java │ │ ├── Utils.java │ │ ├── DeleteConfigFile.java │ │ ├── data │ │ ├── DataCheck.java │ │ ├── DataRequest.java │ │ ├── DataRerun.java │ │ ├── DataStart.java │ │ ├── DataStatus.java │ │ └── format │ │ │ ├── JsonRerun.java │ │ │ ├── JsonCheck.java │ │ │ └── JsonStart.java │ │ ├── exception │ │ ├── RestException.java │ │ └── ErrCode.java │ │ ├── api │ │ ├── MoverRequest.java │ │ ├── Stop.java │ │ ├── Check.java │ │ ├── Remove.java │ │ ├── Rerun.java │ │ ├── Start.java │ │ └── Status.java │ │ ├── handler │ │ ├── GWHandlerJetty.java │ │ ├── GW.java │ │ └── GWHandler.java │ │ ├── Main.java │ │ ├── S3Config.java │ │ ├── db │ │ ├── DBManager.java │ │ ├── MariaDB.java │ │ └── Sqlite.java │ │ └── RestConfig.java └── jar-with-dependencies.xml ├── pom.xml └── README.md /src/com/pspace/ifsmover/rest/script/ifsmoverRest.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | java -jar -Dconfigure=/usr/local/pspace/etc/moverrest/ifsmoverRest.conf -Dlogback.configurationFile=/usr/local/pspace/etc/moverrest/ifsmoverRestLog.xml /usr/local/pspace/bin/ifsmoverRest.jar & -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/script/ifsmoverRest.conf: -------------------------------------------------------------------------------- 1 | endpoint=http://0.0.0.0:7070 2 | secure-endpoint=https://0.0.0.0:7443 3 | keystore-path= 4 | keystore-password= 5 | ifsmover-path=/usr/local/pspace/bin/mover 6 | db_repository=mariadb 7 | db_host= 8 | db_name= 9 | db_port= 10 | db_user= 11 | db_password= 12 | db_pool_size=5 -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/PrintStack.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest; 12 | 13 | import org.slf4j.Logger; 14 | 15 | public class PrintStack { 16 | public static void logging(Logger log, Exception e) { 17 | log.error(e.getMessage()); 18 | for ( StackTraceElement k : e.getStackTrace() ) { 19 | log.error(k.toString()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/jar-with-dependencies.xml: -------------------------------------------------------------------------------- 1 | 4 | jar-with-dependencies 5 | 6 | jar 7 | 8 | false 9 | 10 | 11 | metaInf-services 12 | 13 | 14 | 15 | 16 | / 17 | true 18 | true 19 | runtime 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/repository/RepositoryFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.repository; 12 | 13 | public class RepositoryFactory { 14 | public Repository getSourceRepository(String type) { 15 | if (type.equalsIgnoreCase(Repository.IFS_FILE)) { 16 | return new IfsFile(); 17 | } else if (type.equalsIgnoreCase(Repository.S3)) { 18 | return new IfsS3(); 19 | } 20 | 21 | return null; 22 | } 23 | 24 | public IfsS3 getTargetRepository(String jobId) { 25 | return new IfsS3(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/script/ifsmoverRestLog.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 11 | 12 | 13 | 14 | 15 | ${IFSMOVER_REST_LOGS_PATH}/ifsmoverRest.log 16 | 17 | ${IFSMOVER_REST_LOGS_PATH}/ifsmoverRest.log.%d{yyyy-MM-dd}.%i.log.gz 18 | 30 19 | 500MB 20 | 20GB 21 | 22 | 23 | %-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread{5}][%logger{10}.%method:%line] : %msg%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/Utils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest; 12 | 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import com.pspace.ifsmover.rest.db.DBManager; 17 | import com.pspace.ifsmover.rest.db.MariaDB; 18 | import com.pspace.ifsmover.rest.db.Sqlite; 19 | 20 | public class Utils { 21 | private static final Logger logger = LoggerFactory.getLogger(Utils.class); 22 | private static DBManager dbManager; 23 | 24 | public static DBManager getDBInstance() { 25 | if (dbManager == null) { 26 | if (RestConfig.getInstance().getDBRepository().equalsIgnoreCase(RestConfig.MARIADB)) { 27 | dbManager = MariaDB.getInstance(); 28 | } else if (RestConfig.getInstance().getDBRepository().equalsIgnoreCase(RestConfig.SQLITEDB)) { 29 | dbManager = Sqlite.getInstance(); 30 | } else { 31 | logger.error("undefined db repository."); 32 | dbManager = null; 33 | } 34 | } 35 | 36 | return dbManager; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/DeleteConfigFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | 12 | package com.pspace.ifsmover.rest; 13 | 14 | import java.io.File; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | public class DeleteConfigFile implements Runnable { 19 | private static final Logger logger = LoggerFactory.getLogger(DeleteConfigFile.class); 20 | 21 | @Override 22 | public void run() { 23 | // TODO Auto-generated method stub 24 | String path = RestConfig.getInstance().getPath(); 25 | File dir = new File(path); 26 | File[] files = dir.listFiles(); 27 | 28 | for (int i = 0; i < files.length; i++) { 29 | if (files[i].getName().startsWith("source-")) { 30 | logger.info("delete config file : {}", files[i].getAbsolutePath()); 31 | files[i].delete(); 32 | } else if (files[i].getName().startsWith("target-")) { 33 | logger.info("delete config file : {}", files[i].getAbsolutePath()); 34 | files[i].delete(); 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/DataCheck.java: -------------------------------------------------------------------------------- 1 | package com.pspace.ifsmover.rest.data; 2 | 3 | import java.io.InputStream; 4 | 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.JsonMappingException; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.pspace.ifsmover.rest.PrintStack; 9 | import com.pspace.ifsmover.rest.data.format.JsonCheck; 10 | import com.pspace.ifsmover.rest.exception.ErrCode; 11 | import com.pspace.ifsmover.rest.exception.RestException; 12 | 13 | import org.slf4j.LoggerFactory; 14 | 15 | public class DataCheck extends DataRequest { 16 | private String jsonData; 17 | private JsonCheck jsonCheck = null; 18 | 19 | public DataCheck(InputStream inputStream) { 20 | super(inputStream); 21 | logger = LoggerFactory.getLogger(DataCheck.class); 22 | } 23 | 24 | @Override 25 | public void extract() throws RestException { 26 | // TODO Auto-generated method stub 27 | jsonData = readJson(); 28 | ObjectMapper jsonMapper = new ObjectMapper(); 29 | try { 30 | jsonCheck = jsonMapper.readValue(jsonData, JsonCheck.class); 31 | } catch (JsonMappingException e) { 32 | PrintStack.logging(logger, e); 33 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 34 | } catch (JsonProcessingException e) { 35 | PrintStack.logging(logger, e); 36 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 37 | } 38 | } 39 | 40 | public JsonCheck getJsonCheck() { 41 | return jsonCheck; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/DataRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | 16 | import com.google.common.base.Strings; 17 | import com.pspace.ifsmover.rest.PrintStack; 18 | import com.pspace.ifsmover.rest.exception.ErrCode; 19 | import com.pspace.ifsmover.rest.exception.RestException; 20 | 21 | import org.slf4j.Logger; 22 | 23 | public abstract class DataRequest { 24 | protected InputStream inputStream; 25 | protected Logger logger; 26 | 27 | public DataRequest(InputStream inputStream) { 28 | this.inputStream = inputStream; 29 | } 30 | 31 | protected String readJson() throws RestException { 32 | String ret = null; 33 | 34 | try { 35 | byte[] json = inputStream.readAllBytes(); 36 | ret = new String(json); 37 | } catch (IOException e) { 38 | PrintStack.logging(logger, e); 39 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 40 | } 41 | 42 | logger.info(ret); 43 | 44 | if (Strings.isNullOrEmpty(ret)) { 45 | logger.warn(ErrCode.INVALID_ARGUMENT.getMessage()); 46 | throw new RestException(ErrCode.INVALID_ARGUMENT); 47 | } 48 | 49 | return ret; 50 | } 51 | 52 | public abstract void extract() throws RestException; 53 | } 54 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/exception/RestException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.exception; 12 | 13 | import static java.util.Objects.requireNonNull; 14 | 15 | import java.util.Map; 16 | 17 | import com.google.common.collect.ImmutableMap; 18 | 19 | @SuppressWarnings("serial") 20 | 21 | public class RestException extends Exception { 22 | private final ErrCode error; 23 | private final Map elements; 24 | 25 | public RestException(ErrCode error) { 26 | this(error, error.getMessage(), (Throwable) null, 27 | ImmutableMap.of()); 28 | } 29 | 30 | public RestException(ErrCode error, String message, Throwable cause, Map elements) { 31 | super(requireNonNull(message), cause); 32 | this.error = requireNonNull(error); 33 | this.elements = ImmutableMap.copyOf(elements); 34 | } 35 | 36 | public RestException(ErrCode error, Throwable cause) { 37 | this(error, error.getMessage(), cause, 38 | ImmutableMap.of()); 39 | } 40 | 41 | public RestException(ErrCode error, String message) { 42 | this(error, message, (Throwable) null, 43 | ImmutableMap.of()); 44 | } 45 | 46 | public ErrCode getError() { 47 | return error; 48 | } 49 | 50 | public Map getElements() { 51 | return elements; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/repository/Repository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.repository; 12 | 13 | import com.pspace.ifsmover.rest.S3Config; 14 | 15 | public interface Repository { 16 | public final String IFS_FILE = "file"; 17 | public final String S3 = "s3"; 18 | public final String SWIFT = "swift"; 19 | 20 | public final int NO_ERROR = 0; 21 | public final int FILE_PATH_NOT_EXIST = -1000; 22 | public final int FILE_PATH_NOT_DIR = -1001; 23 | 24 | public final int ENDPOINT_IS_NULL = -2000; 25 | public final int BUCKET_IS_NULL = -2001; 26 | public final int UNABLE_FIND_REGION = -2002; 27 | public final int INVALID_ENDPOINT = -2003; 28 | public final int INVALID_ACCESS_KEY = -2004; 29 | public final int INVALID_SECRET_KEY = -2005; 30 | public final int AMAZON_CLIENT_EXCEPTION = -2006; 31 | public final int AMAZON_SERVICE_EXCEPTION = -2007; 32 | public final int BUCKET_NO_EXIST = -2008; 33 | public final int FAILED_CREATE_BUCKET = -2009; 34 | public final int INVALID_BUCKET = -2010; 35 | 36 | public final int SWIFT_DOMAIN_VALUE_EMPTY = -3000; 37 | public final int SWIFT_PROJECT_VALUE_EMPTY = -3001; 38 | public final int SWIFT_AUTH_ERROR = -3002; 39 | public final int SWIFT_RESPONSE_ERROR = -3003; 40 | public final int SWIFT_INVALID_BUCKET_NAME = -3004; 41 | 42 | String getErrCode(); 43 | String getErrMessage(); 44 | void setConfig(S3Config config, boolean isSource); 45 | int check(); 46 | } 47 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/MoverRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.IOException; 14 | 15 | import com.pspace.ifsmover.rest.exception.RestException; 16 | 17 | import jakarta.servlet.http.HttpServletRequest; 18 | import jakarta.servlet.http.HttpServletResponse; 19 | 20 | public abstract class MoverRequest { 21 | protected HttpServletRequest request; 22 | protected HttpServletResponse response; 23 | protected String userId; 24 | protected String jobId; 25 | 26 | public MoverRequest(HttpServletRequest request, HttpServletResponse response) { 27 | this.request = request; 28 | this.response = response; 29 | } 30 | 31 | protected void setReturnJaonError(String errMsg, boolean isStart) throws IOException { 32 | String returnJson = null; 33 | if (isStart) { 34 | returnJson = "{\"Result\":\"failed\", \"Message\":\"" + errMsg + "\", \"JobId\":0}"; 35 | } else { 36 | returnJson = "{\"Result\":\"failed\", \"Message\":\"" + errMsg + "\"}"; 37 | } 38 | response.getOutputStream().write(returnJson.getBytes()); 39 | response.setStatus(HttpServletResponse.SC_OK); 40 | } 41 | 42 | public abstract void process() throws RestException; 43 | 44 | protected String getUserId() { 45 | return userId; 46 | } 47 | protected void setUserId(String userId) { 48 | this.userId = userId; 49 | } 50 | protected String getJobId() { 51 | return jobId; 52 | } 53 | protected void setJobId(String jobId) { 54 | this.jobId = jobId; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/DataRerun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data; 12 | 13 | import java.io.InputStream; 14 | 15 | import com.fasterxml.jackson.core.JsonProcessingException; 16 | import com.fasterxml.jackson.databind.JsonMappingException; 17 | import com.fasterxml.jackson.databind.ObjectMapper; 18 | import com.pspace.ifsmover.rest.PrintStack; 19 | import com.pspace.ifsmover.rest.data.format.JsonRerun; 20 | import com.pspace.ifsmover.rest.exception.ErrCode; 21 | import com.pspace.ifsmover.rest.exception.RestException; 22 | 23 | import org.slf4j.LoggerFactory; 24 | 25 | public class DataRerun extends DataRequest { 26 | private String jsonData; 27 | private JsonRerun jsonRerun = null; 28 | 29 | public DataRerun(InputStream inputStream) { 30 | super(inputStream); 31 | logger = LoggerFactory.getLogger(DataRerun.class); 32 | } 33 | 34 | @Override 35 | public void extract() throws RestException { 36 | // TODO Auto-generated method stub 37 | jsonData = readJson(); 38 | ObjectMapper jsonMapper = new ObjectMapper(); 39 | try { 40 | jsonRerun = jsonMapper.readValue(jsonData, JsonRerun.class); 41 | } catch (JsonMappingException e) { 42 | PrintStack.logging(logger, e); 43 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 44 | } catch (JsonProcessingException e) { 45 | PrintStack.logging(logger, e); 46 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 47 | } 48 | } 49 | 50 | public JsonRerun getJsonRerun() { 51 | return jsonRerun; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/DataStart.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data; 12 | 13 | import java.io.InputStream; 14 | 15 | import com.fasterxml.jackson.core.JsonProcessingException; 16 | import com.fasterxml.jackson.databind.JsonMappingException; 17 | import com.fasterxml.jackson.databind.ObjectMapper; 18 | import com.pspace.ifsmover.rest.PrintStack; 19 | import com.pspace.ifsmover.rest.data.format.JsonStart; 20 | import com.pspace.ifsmover.rest.exception.ErrCode; 21 | import com.pspace.ifsmover.rest.exception.RestException; 22 | 23 | import org.slf4j.LoggerFactory; 24 | 25 | public class DataStart extends DataRequest { 26 | private String jsonData; 27 | private JsonStart jsonStart = null; 28 | 29 | public DataStart(InputStream inputStream) { 30 | super(inputStream); 31 | logger = LoggerFactory.getLogger(DataStart.class); 32 | } 33 | 34 | @Override 35 | public void extract() throws RestException { 36 | // TODO Auto-generated method stub 37 | jsonData = readJson(); 38 | ObjectMapper jsonMapper = new ObjectMapper(); 39 | try { 40 | jsonStart = jsonMapper.readValue(jsonData, JsonStart.class); 41 | } catch (JsonMappingException e) { 42 | PrintStack.logging(logger, e); 43 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 44 | } catch (JsonProcessingException e) { 45 | PrintStack.logging(logger, e); 46 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 47 | } 48 | } 49 | 50 | public JsonStart getJsonStart() { 51 | return jsonStart; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/exception/ErrCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.exception; 12 | 13 | import static java.util.Objects.requireNonNull; 14 | import com.google.common.base.CaseFormat; 15 | import jakarta.servlet.http.HttpServletResponse; 16 | 17 | public enum ErrCode { 18 | SERVER_ERROR(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"), 19 | BAD_REQUEST(HttpServletResponse.SC_BAD_REQUEST, "Bad Request"), 20 | INVALID_ARGUMENT(HttpServletResponse.SC_BAD_REQUEST, "Bad Request"), 21 | NOT_IMPLEMENTED(HttpServletResponse.SC_NOT_IMPLEMENTED, 22 | "A header you provided implies functionality that is not" + 23 | " implemented."), 24 | INTERNAL_SERVER_DB_ERROR(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "database error has occurred"), 25 | INTERNAL_SERVER_ERROR(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "internal server error has occurred"); 26 | 27 | private final String errorCode; 28 | private final int httpStatusCode; 29 | private final String message; 30 | 31 | ErrCode(int httpStatusCode, String message) { 32 | this.errorCode = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name()); 33 | this.httpStatusCode = httpStatusCode; 34 | this.message = requireNonNull(message); 35 | } 36 | 37 | public String getErrorCode() { 38 | return errorCode; 39 | } 40 | 41 | public int getHttpStatusCode() { 42 | return httpStatusCode; 43 | } 44 | 45 | public String getMessage() { 46 | return message; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return getHttpStatusCode() + " " + getErrorCode() + " " + getMessage(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/repository/IfsFile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.repository; 12 | 13 | import java.io.File; 14 | 15 | import com.google.common.base.Strings; 16 | import com.pspace.ifsmover.rest.S3Config; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | public class IfsFile implements Repository { 22 | private static final Logger logger = LoggerFactory.getLogger(IfsFile.class); 23 | private S3Config config; 24 | private boolean isSource; 25 | private String errCode; 26 | private String errMessage; 27 | private String path; 28 | 29 | @Override 30 | public String getErrCode() { 31 | return errCode; 32 | } 33 | 34 | @Override 35 | public String getErrMessage() { 36 | return errMessage; 37 | } 38 | 39 | @Override 40 | public void setConfig(S3Config config, boolean isSource) { 41 | this.config = config; 42 | this.isSource = isSource; 43 | } 44 | 45 | @Override 46 | public int check() { 47 | if (Strings.isNullOrEmpty(config.getPrefix())) { 48 | path = config.getMountPoint(); 49 | } else { 50 | path = config.getMountPoint() + config.getPrefix(); 51 | } 52 | 53 | 54 | File dir = new File(path); 55 | if (dir.exists()) { 56 | if (!dir.isDirectory()) { 57 | errCode = ""; 58 | errMessage = "mountpoint(" + path + ") is not directory."; 59 | return FILE_PATH_NOT_DIR; 60 | } 61 | } else { 62 | errCode = ""; 63 | errMessage = "mountpoint is not exist. - " + path; 64 | return FILE_PATH_NOT_EXIST; 65 | } 66 | return NO_ERROR; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/handler/GWHandlerJetty.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.handler; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.nio.charset.Charset; 16 | import java.util.List; 17 | 18 | import com.pspace.ifsmover.rest.exception.RestException; 19 | 20 | import org.apache.http.client.utils.URLEncodedUtils; 21 | import org.eclipse.jetty.server.Request; 22 | import org.eclipse.jetty.server.handler.AbstractHandler; 23 | import org.eclipse.jetty.util.MultiMap; 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.apache.http.NameValuePair; 27 | 28 | import jakarta.servlet.ServletException; 29 | import jakarta.servlet.http.HttpServletRequest; 30 | import jakarta.servlet.http.HttpServletResponse; 31 | 32 | public class GWHandlerJetty extends AbstractHandler { 33 | private static final Logger logger = LoggerFactory.getLogger(GWHandlerJetty.class); 34 | private final GWHandler handler; 35 | 36 | public GWHandlerJetty() { 37 | handler = new GWHandler(); 38 | } 39 | 40 | private void sendS3Exception(HttpServletRequest request, HttpServletResponse response, RestException e) 41 | throws IOException { 42 | handler.sendSimpleErrorResponse(request, response, e.getError(), e.getMessage(), e.getElements()); 43 | } 44 | 45 | @Override 46 | public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) 47 | throws IOException, ServletException { 48 | // TODO Auto-generated method stub 49 | try (InputStream is = request.getInputStream()) { 50 | handler.doHandle(baseRequest, request, response, is); 51 | baseRequest.setHandled(true); 52 | } catch (RestException e) { 53 | sendS3Exception(request, response, e); 54 | baseRequest.setHandled(true); 55 | } 56 | } 57 | 58 | public GWHandler getHandler() { 59 | return this.handler; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/Main.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | 12 | package com.pspace.ifsmover.rest; 13 | 14 | import java.io.File; 15 | import java.util.concurrent.Executors; 16 | import java.util.concurrent.ScheduledExecutorService; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | import com.pspace.ifsmover.rest.handler.GW; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | public class Main { 25 | private final static String VERSION = "0.1.6"; 26 | 27 | private static ScheduledExecutorService serviceEmptyTrash = null; 28 | private static final Logger logger = LoggerFactory.getLogger(Main.class); 29 | public static void main(String[] args) throws Exception { 30 | if (args.length == 1) { 31 | if (args[0].equals("-v")) { 32 | System.out.println("ifsmoverRest version : " + VERSION); 33 | System.exit(0); 34 | } 35 | } 36 | 37 | findIfsMover(); 38 | // serviceEmptyTrash = Executors.newSingleThreadScheduledExecutor(); 39 | // serviceEmptyTrash.scheduleAtFixedRate(new DeleteConfigFile(), 0, 1, TimeUnit.DAYS); 40 | 41 | logger.info("ifsmoverRest Start ..."); 42 | GW gw = new GW(); 43 | try { 44 | gw.init(); 45 | gw.start(); 46 | gw.join(); 47 | } catch (IllegalStateException e) { 48 | PrintStack.logging(logger, e); 49 | } catch (Exception e) { 50 | PrintStack.logging(logger, e); 51 | } finally { 52 | gw.stop(); 53 | } 54 | } 55 | 56 | private static void findIfsMover() { 57 | File file = new File(RestConfig.getInstance().getPath() + "/ifs_mover"); 58 | if (!file.exists()) { 59 | System.out.println(); 60 | System.out.println("Can't find ifs_mover"); 61 | System.out.println("ifsmover path : " + RestConfig.getInstance().getPath()); 62 | System.out.println("Check /usr/local/pspace/etc/moverrest/ifsmoverRest.conf - ifsmover_path"); 63 | System.exit(-1); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/DataStatus.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.util.Collections; 16 | 17 | import com.google.common.base.Strings; 18 | import com.pspace.ifsmover.rest.exception.RestException; 19 | 20 | import jakarta.servlet.http.HttpServletRequest; 21 | 22 | import org.slf4j.LoggerFactory; 23 | 24 | public class DataStatus extends DataRequest { 25 | HttpServletRequest request; 26 | private String jobId; 27 | private String srcBucket; 28 | private String dstBucket; 29 | public static final String JOBID = "jobid"; 30 | public static final String SRC_BUCKET = "srcbucket"; 31 | public static final String DST_BUCKET = "dstbucket"; 32 | 33 | public DataStatus(InputStream inputStream) { 34 | super(inputStream); 35 | logger = LoggerFactory.getLogger(DataStatus.class); 36 | } 37 | 38 | public DataStatus(HttpServletRequest request) throws IOException { 39 | super(request.getInputStream()); 40 | this.request = request; 41 | logger = LoggerFactory.getLogger(DataStatus.class); 42 | jobId = ""; 43 | srcBucket = ""; 44 | dstBucket = ""; 45 | } 46 | 47 | @Override 48 | public void extract() throws RestException { 49 | for (String parameter : Collections.list(request.getParameterNames())) { 50 | logger.debug("parameter : {}", parameter); 51 | String param = parameter.toLowerCase(); 52 | if (param.equals(JOBID)) { 53 | jobId = request.getParameter(parameter); 54 | } else if (param.equals(SRC_BUCKET)) { 55 | srcBucket = request.getParameter(parameter); 56 | } else if (param.equals(DST_BUCKET)) { 57 | dstBucket = request.getParameter(parameter); 58 | } 59 | } 60 | } 61 | 62 | public String getJobId() { 63 | return jobId; 64 | } 65 | 66 | public String getSrcBucket() { 67 | return srcBucket; 68 | } 69 | 70 | public String getDstBucket() { 71 | return dstBucket; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/S3Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest; 12 | 13 | import java.net.MalformedURLException; 14 | import java.net.URL; 15 | 16 | import com.google.common.base.Strings; 17 | 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | public class S3Config { 22 | private static final Logger logger = LoggerFactory.getLogger(S3Config.class); 23 | private URL url; 24 | private String mountPoint; 25 | private String endPoint; 26 | private String accessKey; 27 | private String secretKey; 28 | private String bucket; 29 | private String prefix; 30 | private boolean isAWS; 31 | 32 | public S3Config(String mountPoint, String endPoint, String accessKey, String secretKey, String bucket, String prefix) { 33 | this.mountPoint = mountPoint; 34 | this.endPoint = endPoint; 35 | this.accessKey = accessKey; 36 | this.secretKey = secretKey; 37 | this.bucket = bucket; 38 | this.prefix = prefix; 39 | 40 | if (!Strings.isNullOrEmpty(endPoint)) { 41 | endPoint = endPoint.toLowerCase(); 42 | if (endPoint.startsWith("http")) { 43 | isAWS = false; 44 | try { 45 | url = new URL(endPoint); 46 | } catch (MalformedURLException e) { 47 | logger.error(e.getMessage()); 48 | } 49 | } else { 50 | isAWS = true; 51 | } 52 | } else { 53 | isAWS = false; 54 | } 55 | } 56 | 57 | public boolean isAWS() { 58 | return isAWS; 59 | } 60 | 61 | public String getMountPoint() { 62 | return mountPoint; 63 | } 64 | 65 | public String getEndPointProtocol() { 66 | if (url == null) { 67 | return null; 68 | } 69 | return url.getProtocol(); 70 | } 71 | 72 | public String getEndPoint() { 73 | if (isAWS) { 74 | return endPoint; 75 | } else { 76 | if (url == null) { 77 | return null; 78 | } 79 | return url.getHost() + ":" + url.getPort(); 80 | } 81 | } 82 | 83 | public String getAccessKey() { 84 | return accessKey; 85 | } 86 | 87 | public String getSecretKey() { 88 | return secretKey; 89 | } 90 | 91 | public String getBucket() { 92 | return bucket; 93 | } 94 | 95 | public String getPrefix() { 96 | return prefix; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Stop.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.File; 15 | import java.io.InputStreamReader; 16 | 17 | import com.google.common.base.Strings; 18 | import com.pspace.ifsmover.rest.RestConfig; 19 | import com.pspace.ifsmover.rest.Utils; 20 | import com.pspace.ifsmover.rest.db.Sqlite; 21 | import com.pspace.ifsmover.rest.PrintStack; 22 | import com.pspace.ifsmover.rest.exception.ErrCode; 23 | import com.pspace.ifsmover.rest.exception.RestException; 24 | 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | import jakarta.servlet.http.HttpServletRequest; 29 | import jakarta.servlet.http.HttpServletResponse; 30 | 31 | public class Stop extends MoverRequest { 32 | private static final Logger logger = LoggerFactory.getLogger(Status.class); 33 | private String userId; 34 | private String jobId; 35 | 36 | public Stop(HttpServletRequest request, HttpServletResponse response, String userId, String jobId) { 37 | super(request, response); 38 | this.userId = userId; 39 | this.jobId = jobId; 40 | } 41 | 42 | @Override 43 | public void process() throws RestException { 44 | // TODO Auto-generated method stub 45 | logger.info("Stop ..."); 46 | logger.info("userId : {}, jobId : {}", userId, jobId); 47 | 48 | try { 49 | long matchId = Utils.getDBInstance().getUserMatchJob(userId, jobId); 50 | if (matchId == -1) { 51 | String returnJson = null; 52 | returnJson = "{\"Result\":\"failed\", \"Message\":\"Not exist userId and jobId\"}"; 53 | response.getOutputStream().write(returnJson.getBytes()); 54 | response.setStatus(HttpServletResponse.SC_OK); 55 | return; 56 | } 57 | 58 | String command = null; 59 | String osName = System.getProperty("os.name").toLowerCase(); 60 | if (osName.contains("win")) { 61 | command = "python ifs_mover -jobstop=" + jobId; 62 | } else { 63 | command = "./ifs_mover -jobstop=" + jobId; 64 | } 65 | 66 | File file = new File(RestConfig.getInstance().getPath()); 67 | Process process = Runtime.getRuntime().exec(command, null, file); 68 | process.waitFor(); 69 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 70 | String result = reader.readLine(); 71 | logger.info("result : {}", result); 72 | 73 | String returnJson = null; 74 | if (Strings.isNullOrEmpty(result)) { 75 | returnJson = "{\"Result\":\"success\", \"Message\":\"Stop success\"}"; 76 | } else { 77 | returnJson = "{\"Result\":\"failed\", \"Message\":\"" + result + "\"}"; 78 | } 79 | 80 | response.getOutputStream().write(returnJson.getBytes()); 81 | response.setStatus(HttpServletResponse.SC_OK); 82 | } catch (Exception e) { 83 | PrintStack.logging(logger, e); 84 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/db/DBManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.db; 12 | 13 | import java.util.HashMap; 14 | import java.util.List; 15 | import java.util.Map; 16 | 17 | public interface DBManager { 18 | public static final String SQL_SELECT_JOB_STATUS = "SELECT A.job_id, A.job_state, A.job_type, A.source_point, A.target_point, A.objects_count, A.objects_size, A.moved_objects_count, A.moved_objects_size, A.failed_count, A.failed_size, A.skip_objects_count, A.skip_objects_size, A.delete_objects_count, A.delete_objects_size, A.start, A.end, A.error_desc FROM JOB A INNER JOIN UserMatchJob B ON A.job_id = B.job_id WHERE B.user_id = '"; 19 | public static final String JOB_TABLE_COLUMN_JOB_ID = "job_id"; 20 | public static final String JOB_TABLE_COLUMN_JOB_STATE = "job_state"; 21 | public static final String JOB_TABLE_COLUMN_PID = "pid"; 22 | public static final String JOB_TABLE_COLUMN_JOB_TYPE = "job_type"; 23 | public static final String JOB_TABLE_COLUMN_SOURCE_POINT = "source_point"; 24 | public static final String JOB_TABLE_COLUMN_TARGET_POINT = "target_point"; 25 | public static final String JOB_TABLE_COLUMN_OBJECTS_COUNT = "objects_count"; 26 | public static final String JOB_TABLE_COLUMN_OBJECTS_SIZE = "objects_size"; 27 | public static final String JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT = "moved_objects_count"; 28 | public static final String JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE = "moved_objects_size"; 29 | public static final String JOB_TABLE_COLUMN_FAILED_COUNT = "failed_count"; 30 | public static final String JOB_TABLE_COLUMN_FAILED_SIZE = "failed_size"; 31 | public static final String JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT = "skip_objects_count"; 32 | public static final String JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE = "skip_objects_size"; 33 | public static final String JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT = "delete_objects_count"; 34 | public static final String JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE = "delete_objects_size"; 35 | public static final String JOB_TABLE_COLUMN_START = "start"; 36 | public static final String JOB_TABLE_COLUMN_END = "end"; 37 | public static final String JOB_TABLE_COLUMN_ERROR_DESC = "error_desc"; 38 | public static final String MATCH_TABLE_COLUMN_MATCH_ID = "match_id"; 39 | 40 | public static final String SQL_GET_JOB_INFO = "SELECT job_state, job_type, error_desc FROM JOB WHERE job_id = "; 41 | public static final String SQL_INSERT_USERMATCHJOB = "INSERT INTO UserMatchJob(user_id, job_id) VALUES(?, ?)"; 42 | public static final String SQL_GET_USERMATCHJOB = "SELECT match_id FROM UserMatchJob WHERE user_id='"; 43 | public static final String SQL_GET_USERMATCHJOB_JOBID = "' and job_id='"; 44 | 45 | public static final String SQL_DELETE_USERMATCHJOB = "DELETE FROM UserMatchJob WHERE match_id = "; 46 | 47 | public static final int JOB_STATE_INIT = 0; 48 | public static final int JOB_STATE_MOVE = 1; 49 | public static final int JOB_STATE_COMPLETE = 4; 50 | public static final int JOB_STATE_STOP = 5; 51 | public static final int JOB_STATE_REMOVE = 6; 52 | public static final int JOB_STATE_RERUN_INIT = 7; 53 | public static final int JOB_STATE_RERUN_MOVE = 8; 54 | public static final int JOB_STATE_ERROR = 10; 55 | 56 | public void init(String dbUrl, String dbPort, String dbName, String userName, String passwd, int poolSize) throws Exception; 57 | public Map getJobInfo(String jobId); 58 | public void insertUserMatchJob(String userId, String jobId); 59 | public int getUserMatchJob(String userId, String jobId); 60 | public void deleteUserMatchJob(long matchId); 61 | public List> status(String userId); 62 | public List> status(String userId, String jobId); 63 | public List> status(String userId, String srcBucket, String dstBucket); 64 | public List> statusSrcBucket(String userId, String srcBucket); 65 | public List> statusDstBucket(String userId, String dstBucket); 66 | } 67 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Check.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.File; 15 | import java.io.FileWriter; 16 | import java.io.IOException; 17 | import java.io.InputStreamReader; 18 | 19 | import com.pspace.ifsmover.rest.RestConfig; 20 | import com.pspace.ifsmover.rest.S3Config; 21 | import com.pspace.ifsmover.rest.PrintStack; 22 | import com.pspace.ifsmover.rest.data.DataCheck; 23 | import com.pspace.ifsmover.rest.data.format.JsonCheck; 24 | import com.pspace.ifsmover.rest.exception.ErrCode; 25 | import com.pspace.ifsmover.rest.exception.RestException; 26 | import com.pspace.ifsmover.rest.repository.IfsS3; 27 | import com.pspace.ifsmover.rest.repository.Repository; 28 | import com.pspace.ifsmover.rest.repository.RepositoryFactory; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | import jakarta.servlet.http.HttpServletRequest; 34 | import jakarta.servlet.http.HttpServletResponse; 35 | 36 | public class Check extends MoverRequest { 37 | private static final Logger logger = LoggerFactory.getLogger(Start.class); 38 | private JsonCheck jsonCheck = null; 39 | 40 | public Check(HttpServletRequest request, HttpServletResponse response) { 41 | super(request, response); 42 | } 43 | 44 | @Override 45 | public void process() throws RestException { 46 | // TODO Auto-generated method stub 47 | logger.info("Check ..."); 48 | try { 49 | DataCheck dataCheck = new DataCheck(request.getInputStream()); 50 | 51 | try { 52 | dataCheck.extract(); 53 | } catch (Exception e) { 54 | throw new RestException(ErrCode.BAD_REQUEST); 55 | } 56 | 57 | jsonCheck = dataCheck.getJsonCheck(); 58 | 59 | if (jsonCheck.getType().equalsIgnoreCase(Repository.SWIFT)) { 60 | throw new RestException(ErrCode.NOT_IMPLEMENTED); 61 | } 62 | 63 | // Check 64 | S3Config config = null; 65 | config = new S3Config(jsonCheck.getSource().getMountPoint(), 66 | jsonCheck.getSource().getEndPoint(), 67 | jsonCheck.getSource().getAccess(), 68 | jsonCheck.getSource().getSecret(), 69 | jsonCheck.getSource().getBucket(), 70 | jsonCheck.getSource().getPrefix()); 71 | 72 | RepositoryFactory factory = new RepositoryFactory(); 73 | Repository sourceRepository = factory.getSourceRepository(jsonCheck.getType()); 74 | sourceRepository.setConfig(config, true); 75 | int result = sourceRepository.check(); 76 | if (result != 0) { 77 | setReturnJaonError(sourceRepository.getErrMessage(), false); 78 | return; 79 | } 80 | 81 | config = new S3Config(null, 82 | jsonCheck.getTarget().getEndPoint(), 83 | jsonCheck.getTarget().getAccess(), 84 | jsonCheck.getTarget().getSecret(), 85 | jsonCheck.getTarget().getBucket(), 86 | jsonCheck.getTarget().getPrefix()); 87 | IfsS3 ifsS3 = new IfsS3(); 88 | ifsS3.setConfig(config, false); 89 | result = ifsS3.check(); 90 | if (result != 0) { 91 | setReturnJaonError(ifsS3.getErrMessage(), false); 92 | return; 93 | } 94 | 95 | String returnJson = "{\"Result\":\"success\", \"Message\":\"Check success.\"}"; 96 | response.getOutputStream().write(returnJson.getBytes()); 97 | response.setStatus(HttpServletResponse.SC_OK); 98 | } catch (IOException e) { 99 | PrintStack.logging(logger, e); 100 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/format/JsonRerun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data.format; 12 | 13 | import com.fasterxml.jackson.annotation.JsonProperty; 14 | 15 | public class JsonRerun { 16 | @JsonProperty("Source") 17 | private Source source; 18 | 19 | public static final class Source { 20 | @JsonProperty("Mountpoint") 21 | private String mountPoint; 22 | 23 | @JsonProperty("Endpoint") 24 | private String endPoint; 25 | 26 | @JsonProperty("Access") 27 | private String access; 28 | 29 | @JsonProperty("Secret") 30 | private String secret; 31 | 32 | @JsonProperty("Bucket") 33 | private String bucket; 34 | 35 | @JsonProperty("Prefix") 36 | private String prefix; 37 | 38 | @JsonProperty("Move_size") 39 | private String moveSize; 40 | 41 | public String getMountPoint() { 42 | return mountPoint; 43 | } 44 | 45 | public void setMountPoint(String mountPoint) { 46 | this.mountPoint = mountPoint; 47 | } 48 | 49 | public String getEndPoint() { 50 | return endPoint; 51 | } 52 | 53 | public void setEndPoint(String endPoint) { 54 | this.endPoint = endPoint; 55 | } 56 | 57 | public String getAccess() { 58 | return access; 59 | } 60 | 61 | public void setAccess(String access) { 62 | this.access = access; 63 | } 64 | 65 | public String getSecret() { 66 | return secret; 67 | } 68 | 69 | public void setSecret(String secret) { 70 | this.secret = secret; 71 | } 72 | 73 | public String getBucket() { 74 | return bucket; 75 | } 76 | 77 | public void setBucket(String bucket) { 78 | this.bucket = bucket; 79 | } 80 | 81 | public String getPrefix() { 82 | return prefix; 83 | } 84 | 85 | public void setPrefix(String prefix) { 86 | this.prefix = prefix; 87 | } 88 | 89 | public String getMoveSize() { 90 | return moveSize; 91 | } 92 | 93 | public void setMoveSize(String moveSize) { 94 | this.moveSize = moveSize; 95 | } 96 | } 97 | 98 | @JsonProperty("Target") 99 | public Target target; 100 | 101 | public static final class Target { 102 | @JsonProperty("Endpoint") 103 | private String endPoint; 104 | 105 | @JsonProperty("Access") 106 | private String access; 107 | 108 | @JsonProperty("Secret") 109 | private String secret; 110 | 111 | @JsonProperty("Bucket") 112 | private String bucket; 113 | 114 | @JsonProperty("Prefix") 115 | private String prefix; 116 | 117 | public String getEndPoint() { 118 | return endPoint; 119 | } 120 | 121 | public void setEndPoint(String endPoint) { 122 | this.endPoint = endPoint; 123 | } 124 | 125 | public String getAccess() { 126 | return access; 127 | } 128 | 129 | public void setAccess(String access) { 130 | this.access = access; 131 | } 132 | 133 | public String getSecret() { 134 | return secret; 135 | } 136 | 137 | public void setSecret(String secret) { 138 | this.secret = secret; 139 | } 140 | 141 | public String getBucket() { 142 | return bucket; 143 | } 144 | 145 | public void setBucket(String bucket) { 146 | this.bucket = bucket; 147 | } 148 | 149 | public String getPrefix() { 150 | return prefix; 151 | } 152 | 153 | public void setPrefix(String prefix) { 154 | this.prefix = prefix; 155 | } 156 | } 157 | 158 | public Source getSource() { 159 | return source; 160 | } 161 | 162 | public void setSource(Source source) { 163 | this.source = source; 164 | } 165 | 166 | public Target getTarget() { 167 | return target; 168 | } 169 | 170 | public void setTarget(Target target) { 171 | this.target = target; 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/format/JsonCheck.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data.format; 12 | 13 | import com.fasterxml.jackson.annotation.JsonProperty; 14 | 15 | public class JsonCheck { 16 | @JsonProperty("Type") 17 | private String type; 18 | 19 | @JsonProperty("Source") 20 | private Source source; 21 | 22 | public static final class Source { 23 | @JsonProperty("Mountpoint") 24 | private String mountPoint; 25 | 26 | @JsonProperty("Endpoint") 27 | private String endPoint; 28 | 29 | @JsonProperty("Access") 30 | private String access; 31 | 32 | @JsonProperty("Secret") 33 | private String secret; 34 | 35 | @JsonProperty("Bucket") 36 | private String bucket; 37 | 38 | @JsonProperty("Prefix") 39 | private String prefix; 40 | 41 | @JsonProperty("Move_size") 42 | private String moveSize; 43 | 44 | public String getMountPoint() { 45 | return mountPoint; 46 | } 47 | 48 | public void setMountPoint(String mountPoint) { 49 | this.mountPoint = mountPoint; 50 | } 51 | 52 | public String getEndPoint() { 53 | return endPoint; 54 | } 55 | 56 | public void setEndPoint(String endPoint) { 57 | this.endPoint = endPoint; 58 | } 59 | 60 | public String getAccess() { 61 | return access; 62 | } 63 | 64 | public void setAccess(String access) { 65 | this.access = access; 66 | } 67 | 68 | public String getSecret() { 69 | return secret; 70 | } 71 | 72 | public void setSecret(String secret) { 73 | this.secret = secret; 74 | } 75 | 76 | public String getBucket() { 77 | return bucket; 78 | } 79 | 80 | public void setBucket(String bucket) { 81 | this.bucket = bucket; 82 | } 83 | 84 | public String getPrefix() { 85 | return prefix; 86 | } 87 | 88 | public void setPrefix(String prefix) { 89 | this.prefix = prefix; 90 | } 91 | 92 | public String getMoveSize() { 93 | return moveSize; 94 | } 95 | 96 | public void setMoveSize(String moveSize) { 97 | this.moveSize = moveSize; 98 | } 99 | } 100 | 101 | @JsonProperty("Target") 102 | public Target target; 103 | 104 | public static final class Target { 105 | @JsonProperty("Endpoint") 106 | private String endPoint; 107 | 108 | @JsonProperty("Access") 109 | private String access; 110 | 111 | @JsonProperty("Secret") 112 | private String secret; 113 | 114 | @JsonProperty("Bucket") 115 | private String bucket; 116 | 117 | @JsonProperty("Prefix") 118 | private String prefix; 119 | 120 | public String getEndPoint() { 121 | return endPoint; 122 | } 123 | 124 | public void setEndPoint(String endPoint) { 125 | this.endPoint = endPoint; 126 | } 127 | 128 | public String getAccess() { 129 | return access; 130 | } 131 | 132 | public void setAccess(String access) { 133 | this.access = access; 134 | } 135 | 136 | public String getSecret() { 137 | return secret; 138 | } 139 | 140 | public void setSecret(String secret) { 141 | this.secret = secret; 142 | } 143 | 144 | public String getBucket() { 145 | return bucket; 146 | } 147 | 148 | public void setBucket(String bucket) { 149 | this.bucket = bucket; 150 | } 151 | 152 | public String getPrefix() { 153 | return prefix; 154 | } 155 | 156 | public void setPrefix(String prefix) { 157 | this.prefix = prefix; 158 | } 159 | 160 | 161 | } 162 | 163 | public String getType() { 164 | return type; 165 | } 166 | 167 | public void setType(String type) { 168 | this.type = type; 169 | } 170 | 171 | public Source getSource() { 172 | return source; 173 | } 174 | 175 | public void setSource(Source source) { 176 | this.source = source; 177 | } 178 | 179 | public Target getTarget() { 180 | return target; 181 | } 182 | 183 | public void setTarget(Target target) { 184 | this.target = target; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Remove.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.File; 15 | import java.io.InputStreamReader; 16 | import java.util.Map; 17 | 18 | import com.google.common.base.Strings; 19 | import com.pspace.ifsmover.rest.RestConfig; 20 | import com.pspace.ifsmover.rest.Utils; 21 | import com.pspace.ifsmover.rest.db.DBManager; 22 | import com.pspace.ifsmover.rest.PrintStack; 23 | import com.pspace.ifsmover.rest.exception.ErrCode; 24 | import com.pspace.ifsmover.rest.exception.RestException; 25 | 26 | import org.slf4j.Logger; 27 | import org.slf4j.LoggerFactory; 28 | 29 | import jakarta.servlet.http.HttpServletRequest; 30 | import jakarta.servlet.http.HttpServletResponse; 31 | 32 | public class Remove extends MoverRequest { 33 | private static final Logger logger = LoggerFactory.getLogger(Remove.class); 34 | private String userId; 35 | private String jobId; 36 | 37 | public Remove(HttpServletRequest request, HttpServletResponse response, String userId, String jobId) { 38 | super(request, response); 39 | this.userId = userId; 40 | this.jobId = jobId; 41 | } 42 | 43 | @Override 44 | public void process() throws RestException { 45 | // TODO Auto-generated method stub 46 | logger.info("Remove ..."); 47 | logger.info("userId : {}, jobId : {}", userId, jobId); 48 | 49 | try { 50 | long matchId = Utils.getDBInstance().getUserMatchJob(userId, jobId); 51 | if (matchId == -1) { 52 | String returnJson = null; 53 | returnJson = "{\"Result\":\"failed\", \"Message\":\"Not exist userId and jobId\"}"; 54 | response.getOutputStream().write(returnJson.getBytes()); 55 | response.setStatus(HttpServletResponse.SC_OK); 56 | return; 57 | } 58 | 59 | Map info = null; 60 | info = Utils.getDBInstance().getJobInfo(jobId); 61 | int jobState = (int) info.get(DBManager.JOB_TABLE_COLUMN_JOB_STATE); 62 | if (jobState == DBManager.JOB_STATE_INIT) { 63 | logger.warn("Job status is INIT. Stop first, and then Remove."); 64 | setReturnJaonError("Job status is INIT. Stop first, and then Remove.", false); 65 | return; 66 | } else if (jobState == DBManager.JOB_STATE_MOVE) { 67 | logger.warn("Job status is MOVE. Stop first, and then Remove."); 68 | setReturnJaonError("Job status is MOVE. Stop first, and then Remove.", false); 69 | return; 70 | } else if (jobState == DBManager.JOB_STATE_RERUN_INIT) { 71 | logger.warn("Job status is RERUN-INIT. Stop first, and then Remove.", false); 72 | setReturnJaonError("Job status is RERUN-INIT. Stop first, and then Remove.", false); 73 | return; 74 | } else if (jobState == DBManager.JOB_STATE_RERUN_MOVE) { 75 | logger.warn("Job status is RERUN-MOVE. Stop first, and then Remove."); 76 | setReturnJaonError("Job status is RERUN-MOVE. Stop first, and then Remove.", false); 77 | return; 78 | } 79 | 80 | String command = null; 81 | String osName = System.getProperty("os.name").toLowerCase(); 82 | if (osName.contains("win")) { 83 | command = "python ifs_mover -jobremove=" + jobId; 84 | } else { 85 | command = "./ifs_mover -jobremove=" + jobId; 86 | } 87 | 88 | File file = new File(RestConfig.getInstance().getPath()); 89 | Process process = Runtime.getRuntime().exec(command, null, file); 90 | process.waitFor(); 91 | BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); 92 | String result = reader.readLine(); 93 | logger.info("result : {}", result); 94 | 95 | String returnJson = null; 96 | if (Strings.isNullOrEmpty(result)) { 97 | returnJson = "{\"Result\":\"success\", \"Message\":\"Remove success\"}"; 98 | Utils.getDBInstance().deleteUserMatchJob(matchId); 99 | } else { 100 | returnJson = "{\"Result\":\"failed\", \"Message\":\"" + result + "\"}"; 101 | } 102 | 103 | response.getOutputStream().write(returnJson.getBytes()); 104 | response.setStatus(HttpServletResponse.SC_OK); 105 | } catch (Exception e) { 106 | PrintStack.logging(logger, e); 107 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/data/format/JsonStart.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.data.format; 12 | 13 | import com.fasterxml.jackson.annotation.JsonProperty; 14 | 15 | import jnr.ffi.Struct.pid_t; 16 | 17 | public class JsonStart { 18 | @JsonProperty("UserId") 19 | private String userId; 20 | 21 | @JsonProperty("Type") 22 | private String type; 23 | 24 | @JsonProperty("Source") 25 | private Source source; 26 | 27 | public static final class Source { 28 | @JsonProperty("Mountpoint") 29 | private String mountPoint; 30 | 31 | @JsonProperty("Endpoint") 32 | private String endPoint; 33 | 34 | @JsonProperty("Access") 35 | private String access; 36 | 37 | @JsonProperty("Secret") 38 | private String secret; 39 | 40 | @JsonProperty("Bucket") 41 | private String bucket; 42 | 43 | @JsonProperty("Prefix") 44 | private String prefix; 45 | 46 | @JsonProperty("Move_size") 47 | private String moveSize; 48 | 49 | public String getMountPoint() { 50 | return mountPoint; 51 | } 52 | 53 | public void setMountPoint(String mountPoint) { 54 | this.mountPoint = mountPoint; 55 | } 56 | 57 | public String getEndPoint() { 58 | return endPoint; 59 | } 60 | 61 | public void setEndPoint(String endPoint) { 62 | this.endPoint = endPoint; 63 | } 64 | 65 | public String getAccess() { 66 | return access; 67 | } 68 | 69 | public void setAccess(String access) { 70 | this.access = access; 71 | } 72 | 73 | public String getSecret() { 74 | return secret; 75 | } 76 | 77 | public void setSecret(String secret) { 78 | this.secret = secret; 79 | } 80 | 81 | public String getBucket() { 82 | return bucket; 83 | } 84 | 85 | public void setBucket(String bucket) { 86 | this.bucket = bucket; 87 | } 88 | 89 | public String getPrefix() { 90 | return prefix; 91 | } 92 | 93 | public void setPrefix(String prefix) { 94 | this.prefix = prefix; 95 | } 96 | 97 | public String getMoveSize() { 98 | return moveSize; 99 | } 100 | 101 | public void setMoveSize(String moveSize) { 102 | this.moveSize = moveSize; 103 | } 104 | } 105 | 106 | @JsonProperty("Target") 107 | public Target target; 108 | 109 | public static final class Target { 110 | @JsonProperty("Endpoint") 111 | private String endPoint; 112 | 113 | @JsonProperty("Access") 114 | private String access; 115 | 116 | @JsonProperty("Secret") 117 | private String secret; 118 | 119 | @JsonProperty("Bucket") 120 | private String bucket; 121 | 122 | @JsonProperty("Prefix") 123 | private String prefix; 124 | 125 | public String getEndPoint() { 126 | return endPoint; 127 | } 128 | 129 | public void setEndPoint(String endPoint) { 130 | this.endPoint = endPoint; 131 | } 132 | 133 | public String getAccess() { 134 | return access; 135 | } 136 | 137 | public void setAccess(String access) { 138 | this.access = access; 139 | } 140 | 141 | public String getSecret() { 142 | return secret; 143 | } 144 | 145 | public void setSecret(String secret) { 146 | this.secret = secret; 147 | } 148 | 149 | public String getBucket() { 150 | return bucket; 151 | } 152 | 153 | public void setBucket(String bucket) { 154 | this.bucket = bucket; 155 | } 156 | 157 | public String getPrefix() { 158 | return prefix; 159 | } 160 | 161 | public void setPrefix(String prefix) { 162 | this.prefix = prefix; 163 | } 164 | } 165 | 166 | public String getUserId() { 167 | return userId; 168 | } 169 | 170 | public void setUserId(String userId) { 171 | this.userId = userId; 172 | } 173 | 174 | public String getType() { 175 | return type; 176 | } 177 | 178 | public void setType(String type) { 179 | this.type = type; 180 | } 181 | 182 | public Source getSource() { 183 | return source; 184 | } 185 | 186 | public void setSource(Source source) { 187 | this.source = source; 188 | } 189 | 190 | public Target getTarget() { 191 | return target; 192 | } 193 | 194 | public void setTarget(Target target) { 195 | this.target = target; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | com.pspace.ifsmover.rest 4 | ifsmover-rest 5 | 1.0.0 6 | jar 7 | ifsmover-rest 8 | 9 | 10 | 1.7.32 11 | UTF-8 12 | 11 13 | 14 | 15 | 16 | 17 | org.eclipse.jetty 18 | jetty-servlet 19 | 11.0.4 20 | 21 | 22 | com.fasterxml.jackson.dataformat 23 | jackson-dataformat-xml 24 | 2.12.5 25 | 26 | 27 | com.amazonaws 28 | aws-java-sdk-s3 29 | 1.12.262 30 | compile 31 | 32 | 33 | com.googlecode.json-simple 34 | json-simple 35 | 1.1 36 | 37 | 38 | com.google.guava 39 | guava 40 | 30.1-jre 41 | 42 | 43 | com.google.code.findbugs 44 | annotations 45 | 3.0.1 46 | 47 | 48 | org.apache.httpcomponents 49 | httpclient 50 | 4.5.13 51 | 52 | 53 | org.apache.httpcomponents 54 | httpcore 55 | 4.4.14 56 | 57 | 58 | commons-io 59 | commons-io 60 | 2.11.0 61 | 62 | 63 | org.xerial 64 | sqlite-jdbc 65 | 3.34.0 66 | 67 | 68 | org.slf4j 69 | slf4j-api 70 | ${slf4j.version} 71 | 72 | 73 | ch.qos.logback 74 | logback-classic 75 | 1.2.3 76 | 77 | 78 | args4j 79 | args4j 80 | 2.33 81 | 82 | 83 | com.github.jnr 84 | jnr-posix 85 | 3.1.10 86 | compile 87 | 88 | 89 | org.apache.commons 90 | commons-crypto 91 | 1.1.0 92 | 93 | 94 | org.mariadb.jdbc 95 | mariadb-java-client 96 | 3.0.4 97 | 98 | 99 | com.zaxxer 100 | HikariCP 101 | 3.4.5 102 | 103 | 104 | 105 | 106 | src 107 | 108 | 109 | src 110 | 111 | **/*.java 112 | 113 | 114 | 115 | 116 | 117 | maven-compiler-plugin 118 | 3.8.1 119 | 120 | ${java.version} 121 | ${java.version} 122 | UTF-8 123 | 124 | 125 | 126 | org.apache.maven.plugins 127 | maven-jar-plugin 128 | 3.2.0 129 | 130 | 131 | 132 | true 133 | true 134 | 135 | 136 | 137 | 138 | 139 | org.apache.maven.plugins 140 | maven-assembly-plugin 141 | 3.3.0 142 | 143 | 144 | src/jar-with-dependencies.xml 145 | 146 | 147 | 148 | com.pspace.ifsmover.rest.Main 149 | true 150 | 151 | 152 | 153 | 154 | 155 | make-assembly 156 | package 157 | 158 | single 159 | 160 | 161 | 162 | 163 | 164 | org.skife.maven 165 | really-executable-jar-maven-plugin 166 | 1.5.0 167 | 168 | ifsmoverRest.jar 169 | 170 | 171 | 172 | package 173 | 174 | really-executable-jar 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/handler/GW.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.handler; 12 | 13 | import static com.google.common.base.Preconditions.checkArgument; 14 | import static java.util.Objects.requireNonNull; 15 | 16 | import com.pspace.ifsmover.rest.RestConfig; 17 | import com.pspace.ifsmover.rest.Utils; 18 | 19 | import org.eclipse.jetty.http.HttpCompliance; 20 | import org.eclipse.jetty.http.UriCompliance; 21 | import org.eclipse.jetty.server.HttpConfiguration; 22 | import org.eclipse.jetty.server.HttpConnectionFactory; 23 | import org.eclipse.jetty.server.ProxyConnectionFactory; 24 | import org.eclipse.jetty.server.Server; 25 | import org.eclipse.jetty.server.ServerConnector; 26 | import org.eclipse.jetty.util.ssl.SslContextFactory; 27 | import org.eclipse.jetty.util.thread.ExecutorThreadPool; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | public class GW { 32 | private Server server; 33 | private GWHandlerJetty handler; 34 | private static final Logger logger = LoggerFactory.getLogger(GW.class); 35 | 36 | public void init() { 37 | checkArgument(RestConfig.getInstance().getEndpoint() != null || RestConfig.getInstance().getSecureEndpoint() != null, 38 | "Must provide endpoint or secure-endpoint"); 39 | 40 | if (RestConfig.getInstance().getEndpoint() != null) { 41 | checkArgument(RestConfig.getInstance().getEndpoint().getPath().isEmpty(), 42 | "endpoint path must be empty, was: %s", RestConfig.getInstance().getEndpoint().getPath()); 43 | } 44 | 45 | if (RestConfig.getInstance().getSecureEndpoint() != null) { 46 | checkArgument(RestConfig.getInstance().getSecureEndpoint().getPath().isEmpty(), 47 | "secure-endpoint path must be empty, was: %s", 48 | RestConfig.getInstance().getSecureEndpoint().getPath()); 49 | requireNonNull(RestConfig.getInstance().getKeystorePath(), "Must provide keyStorePath with HTTPS endpoint"); 50 | requireNonNull(RestConfig.getInstance().getKeystorePassword(), "Must provide keyStorePassword with HTTPS endpoint"); 51 | logger.info("keystorePath: {}", RestConfig.getInstance().getKeystorePath()); 52 | logger.info("keystorePassword: {}", RestConfig.getInstance().getKeystorePassword()); 53 | if (RestConfig.getInstance().getKeystorePassword() == null) { 54 | logger.info("null"); 55 | } 56 | } 57 | 58 | ExecutorThreadPool pool = new ExecutorThreadPool((int)10); 59 | pool.setName("ifsmoverREST"); 60 | server = new Server(pool); 61 | 62 | HttpConfiguration httpConfig = new HttpConfiguration(); 63 | httpConfig.setSendServerVersion(false); 64 | 65 | HttpConnectionFactory httpConnectionFactory = new HttpConnectionFactory(httpConfig); 66 | HttpCompliance customHttpCompliance = HttpCompliance.from("RFC7230,MULTIPLE_CONTENT_LENGTHS"); 67 | httpConnectionFactory.getHttpConfiguration().setHttpCompliance(customHttpCompliance); 68 | UriCompliance customUriCompliance = UriCompliance.from("RFC3986,-AMBIGUOUS_PATH_SEPARATOR"); 69 | httpConnectionFactory.getHttpConfiguration().setUriCompliance(customUriCompliance); 70 | 71 | ServerConnector connector; 72 | if (RestConfig.getInstance().getEndpoint() != null) { 73 | ProxyConnectionFactory httpProxyConnectionFactory = new ProxyConnectionFactory(httpConnectionFactory.getProtocol()); 74 | connector = new ServerConnector(server, httpProxyConnectionFactory, httpConnectionFactory); 75 | connector.setHost(RestConfig.getInstance().getEndpoint().getHost()); 76 | connector.setPort(RestConfig.getInstance().getEndpoint().getPort()); 77 | connector.setIdleTimeout(RestConfig.getInstance().getJettyMaxIdleTimeout()); 78 | connector.setReuseAddress(true); 79 | server.addConnector(connector); 80 | } 81 | 82 | if (RestConfig.getInstance().getSecureEndpoint() != null) { 83 | SslContextFactory.Server sslContextFactory = new SslContextFactory.Server(); 84 | sslContextFactory.setKeyStorePath(RestConfig.getInstance().getKeystorePath()); 85 | sslContextFactory.setKeyStorePassword(RestConfig.getInstance().getKeystorePassword()); 86 | connector = new ServerConnector(server, sslContextFactory, httpConnectionFactory); 87 | connector.setHost(RestConfig.getInstance().getSecureEndpoint().getHost()); 88 | connector.setPort(RestConfig.getInstance().getSecureEndpoint().getPort()); 89 | connector.setIdleTimeout(RestConfig.getInstance().getJettyMaxIdleTimeout()); 90 | connector.setReuseAddress(true); 91 | server.addConnector(connector); 92 | } 93 | 94 | handler = new GWHandlerJetty(); 95 | server.setHandler(handler); 96 | 97 | try { 98 | Utils.getDBInstance().init(RestConfig.getInstance().getDbHost(), 99 | RestConfig.getInstance().getDbPort(), 100 | RestConfig.getInstance().getDatabase(), 101 | RestConfig.getInstance().getDbUser(), 102 | RestConfig.getInstance().getDbPass(), 103 | RestConfig.getInstance().getDbPoolSize()); 104 | } catch (Exception e) { 105 | logger.error(e.getMessage()); 106 | System.exit(-1); 107 | } 108 | } 109 | 110 | public void start() throws Exception { 111 | server.start(); 112 | } 113 | 114 | public void join() throws Exception { 115 | server.join(); 116 | } 117 | 118 | public void stop() throws Exception { 119 | server.stop(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/handler/GWHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.handler; 12 | 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.io.UnsupportedEncodingException; 16 | import java.io.Writer; 17 | import java.net.URLDecoder; 18 | import java.util.Collections; 19 | import java.util.Map; 20 | 21 | import javax.xml.stream.XMLOutputFactory; 22 | import javax.xml.stream.XMLStreamException; 23 | import javax.xml.stream.XMLStreamWriter; 24 | 25 | import com.google.common.base.Strings; 26 | import com.pspace.ifsmover.rest.api.Check; 27 | import com.pspace.ifsmover.rest.api.MoverRequest; 28 | import com.pspace.ifsmover.rest.api.Remove; 29 | import com.pspace.ifsmover.rest.api.Rerun; 30 | import com.pspace.ifsmover.rest.api.Start; 31 | import com.pspace.ifsmover.rest.api.Status; 32 | import com.pspace.ifsmover.rest.api.Stop; 33 | import com.pspace.ifsmover.rest.exception.ErrCode; 34 | import com.pspace.ifsmover.rest.exception.RestException; 35 | 36 | import org.eclipse.jetty.server.Request; 37 | import org.slf4j.Logger; 38 | import org.slf4j.LoggerFactory; 39 | 40 | import jakarta.servlet.http.HttpServletRequest; 41 | import jakarta.servlet.http.HttpServletResponse; 42 | 43 | public class GWHandler { 44 | private static final Logger logger = LoggerFactory.getLogger(GWHandler.class); 45 | private String moverPath; 46 | private final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); 47 | 48 | public final void doHandle(Request baseRequest, HttpServletRequest request, HttpServletResponse response, InputStream is) throws RestException { 49 | String method = request.getMethod(); 50 | long startTime = System.currentTimeMillis(); 51 | 52 | String uri = request.getRequestURI(); 53 | 54 | logger.info("request url : {}", request.getRequestURL()); 55 | logger.info("PREURI - {}", uri); 56 | logger.info("client address - {}", request.getRemoteAddr()); 57 | logger.info("client host - {}", request.getRemoteHost()); 58 | logger.info("method - {}", method); 59 | 60 | for (String parameter : Collections.list(request.getParameterNames())) { 61 | logger.info("parameter {} - {}", parameter, Strings.nullToEmpty(request.getParameter(parameter))); 62 | } 63 | for (String headerName : Collections.list(request.getHeaderNames())) { 64 | for (String headerValue : Collections.list(request.getHeaders(headerName))) { 65 | logger.info("header {} - {}", headerName, Strings.nullToEmpty(headerValue)); 66 | } 67 | } 68 | 69 | String[] path = uri.split("/"); 70 | try { 71 | for (int i = 0; i < path.length; i++) { 72 | path[i] = URLDecoder.decode(path[i], "UTF-8"); 73 | logger.info("path[{}] : {}", i, path[i]); 74 | } 75 | } catch (UnsupportedEncodingException e) { 76 | throw new RestException(ErrCode.BAD_REQUEST); 77 | } 78 | 79 | MoverRequest moverRequest = null; 80 | 81 | if (!path[1].equalsIgnoreCase("api")) { 82 | throw new RestException(ErrCode.BAD_REQUEST); 83 | } else { 84 | if (path[2].equalsIgnoreCase("Check")) { 85 | moverRequest = new Check(request, response); 86 | } else if (path[2].equalsIgnoreCase("Start")) { 87 | moverRequest = new Start(request, response); 88 | } else if (path[2].equalsIgnoreCase("Stop")) { 89 | if (path.length == 5) { 90 | String userId = path[3]; 91 | String jobId = path[4]; 92 | moverRequest = new Stop(request, response, userId, jobId); 93 | } else { 94 | throw new RestException(ErrCode.BAD_REQUEST); 95 | } 96 | } else if (path[2].equalsIgnoreCase("Rerun")) { 97 | if (path.length == 5) { 98 | String userId = path[3]; 99 | String jobId = path[4]; 100 | moverRequest = new Rerun(request, response, userId, jobId); 101 | } else { 102 | throw new RestException(ErrCode.BAD_REQUEST); 103 | } 104 | } else if (path[2].equalsIgnoreCase("Status")) { 105 | if (path.length == 4) { 106 | String userId = path[3]; 107 | moverRequest = new Status(request, response, userId); 108 | } else { 109 | throw new RestException(ErrCode.BAD_REQUEST); 110 | } 111 | } else if (path[2].equalsIgnoreCase("Remove")) { 112 | if (path.length == 5) { 113 | String userId = path[3]; 114 | String jobId = path[4]; 115 | moverRequest = new Remove(request, response, userId, jobId); 116 | } else { 117 | throw new RestException(ErrCode.BAD_REQUEST); 118 | } 119 | } else { 120 | throw new RestException(ErrCode.BAD_REQUEST); 121 | } 122 | } 123 | 124 | moverRequest.process(); 125 | } 126 | 127 | protected final void sendSimpleErrorResponse( 128 | HttpServletRequest request, HttpServletResponse response, 129 | ErrCode code, String message, 130 | Map elements) throws IOException { 131 | 132 | response.setStatus(code.getHttpStatusCode()); 133 | 134 | if (request.getMethod().equals("HEAD")) { 135 | // The HEAD method is identical to GET except that the server MUST 136 | // NOT return a message-body in the response. 137 | return; 138 | } 139 | 140 | try (Writer writer = response.getWriter()) { 141 | response.setContentType("application/xml"); 142 | XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(writer); 143 | xml.writeStartDocument(); 144 | xml.writeStartElement("Error"); 145 | 146 | writeSimpleElement(xml, "Code", code.getErrorCode()); 147 | writeSimpleElement(xml, "Message", message); 148 | 149 | for (Map.Entry entry : elements.entrySet()) { 150 | writeSimpleElement(xml, entry.getKey(), entry.getValue()); 151 | } 152 | 153 | writeSimpleElement(xml, "RequestId", "4442587FB7D0A2F9"); 154 | 155 | xml.writeEndElement(); 156 | xml.flush(); 157 | } catch (XMLStreamException xse) { 158 | throw new IOException(xse); 159 | } 160 | } 161 | 162 | private void writeSimpleElement(XMLStreamWriter xml, String elementName, String characters) throws XMLStreamException { 163 | xml.writeStartElement(elementName); 164 | xml.writeCharacters(characters); 165 | xml.writeEndElement(); 166 | } 167 | 168 | public void setMoverPath(String moverPath) { 169 | this.moverPath = moverPath; 170 | } 171 | 172 | public String getMoverPath() { 173 | return moverPath; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IfsMoverRest 2 | 3 | ## 개요 4 | 5 | ### 용도 6 | * [IfsMover](https://github.com/infinistor/ifsmover)를 구동하기 위한 REST Server. 7 | 8 | ### 전제 조건 9 | * [IfsMover-0.2.6+](https://github.com/infinistor/ifsmover/releases) 설치되어 있어야 합니다. 10 | 11 | 12 | ### API 13 | * UserId는 임의의 문자열입니다. 14 | * ifsmoverRest의 모든 동작은 UserId로 구분됩니다. 15 | * UserId는 사용자가 관리합니다. 16 | 17 | #### Check 18 | type, source, target 정보에 대한 검사 결과를 리턴합니다. 19 | 20 | * URL : /api/Check 21 | * Request 22 | 23 | ``` bash 24 | { 25 | "Type":"string", // file, s3, swift 26 | "Source":{ 27 | "Mountpoint":"string", 28 | "Endpoint":"string", 29 | "Access":"string", 30 | "Secret":"string", 31 | "Bucket":"string", 32 | "Prefix":"string", 33 | "Move_size":"string" 34 | }, 35 | "Target":{ 36 | "Endpoint":"string", 37 | "Access":"string", 38 | "Secret":"string", 39 | "Bucket":"string", 40 | "Prefix":"string" 41 | } 42 | } 43 | ``` 44 | 45 | * Return 46 | 47 | ``` bash 48 | { 49 | "Result":"string",// success, failed 50 | "Message":"string" 51 | } 52 | ``` 53 | 54 | * Test 55 | ``` bash 56 | curl -H "Content-Type:application/json" "http://localhost:7123/api/Check" -d "{\"Type\":\"s3\", \"Source\":{\"Mountpoint\":null, \"Endpoint\":\"http://localhost:8080\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-source\", \"Prefix\":null, \"Move_size\":null}, \"Target\":{\"Endpoint\":\"http://localhost:8080\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-target-01\", \"Prefix\":\"05-18-001\"}}" 57 | ``` 58 | 59 | #### Start 60 | ifsmover를 실행합니다. -check 옵션으로 먼저 수행한 후에 에러가 없으면 job을 수행하고 그렇지 않으면 failed를 리턴합니다. 61 | 62 | * URL : /api/Start 63 | * Request 64 | 65 | ``` bash 66 | { 67 | "UserId":"string", 68 | "Type":"string", // file, s3 69 | "Source":{ 70 | "Mountpoint":"string", 71 | "Endpoint":"string", 72 | "Access":"string", 73 | "Secret":"string", 74 | "Bucket":"string", 75 | "Prefix":"string", 76 | "Move_size":"string" 77 | }, 78 | "Target":{ 79 | "Endpoint":"string", 80 | "Access":"string", 81 | "Secret":"string", 82 | "Bucket":"string", 83 | "Prefix":"string" 84 | } 85 | } 86 | ``` 87 | 88 | * Return 89 | 90 | ``` bash 91 | { 92 | "Result":"string", // success, failed 93 | "Message":"string", 94 | "JobId":0 95 | } 96 | ``` 97 | 98 | * Test 99 | ``` bash 100 | curl -H "Content-Type:application/json" "http://localhost:7123/api/Start" -d "{\"UserId\":\"1234\", \"Type\":\"s3\", \"Source\":{\"Mountpoint\":null, \"Endpoint\":\"http://localhost:8080\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-source\", \"Prefix\":null, \"Move_size\":null}, \"Target\":{\"Endpoint\":\"http://localhost:8080\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-target-01\", \"Prefix\":\"05-18-001\"}}" 101 | ``` 102 | 103 | 104 | #### Stop 105 | UserId와 JobId에 해당하는 작업을 중지 시킵니다. 106 | 107 | * URL : /api/Stop/{UserId}/{JobId} 108 | * Return 109 | 110 | ``` bash 111 | { 112 | "Result":"string",// success, failed 113 | "Message":"string" 114 | } 115 | ``` 116 | 117 | * test 118 | ``` bash 119 | curl http://localhost:7123/api/Stop/1234/1 120 | ``` 121 | 122 | 123 | #### Rerun 124 | UserId와 JobId에 해당하는 작업을 다시 수행합니다. JobId에 해당하는 작업이 진행 중이면 강제로 종료하고 다시 시작합니다. 125 | 126 | * URL : /api/Rerun/{UserId}/{JobId} 127 | * Request 128 | 129 | ``` bash 130 | { 131 | "Source":{ 132 | "Mountpoint":"string", 133 | "Endpoint":"string", 134 | "Access":"string", 135 | "Secret":"string", 136 | "Bucket":"string", 137 | "Prefix":"string", 138 | "Move_size":"string" 139 | }, 140 | "Target":{ 141 | "Endpoint":"string", 142 | "Access":"string", 143 | "Secret":"string", 144 | "Bucket":"string", 145 | "Prefix":"string" 146 | } 147 | } 148 | ``` 149 | 150 | * Return 151 | 152 | ``` bash 153 | { 154 | "Result":"string",// success, failed 155 | "Message":"string" 156 | } 157 | ``` 158 | 159 | * Test 160 | ``` bash 161 | curl -H "Content-Type:application/json" "http://localhost:7123/api/Rerun/1234/1" -d "{\"Source\":{\"Mountpoint\":null, \"Endpoint\":\"http://localhost:8080\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-source\", \"Prefix\":null, \"Move_size\":null}, \"Target\":{\"Endpoint\":\"http://192.168.13.13:9090\", \"Access\":\"your_access_key\", \"Secret\":\"your_secret_key\", \"Bucket\":\"mover-test-target-01\", \"Prefix\":\"05-18-001\"}}" 162 | ``` 163 | 164 | 165 | #### Remove 166 | UserId와 JobId에 해당하는 작업을 삭제합니다. 진행 중인 작업은 삭제할 수 없습니다. 먼저 Stop을 한 후에 Remove를 해야 합니다. 167 | 168 | * URL : /api/Remove/{UserId}/{JobId} 169 | * Return 170 | 171 | ``` bash 172 | { 173 | "Result":"string",// success, failed 174 | "Message":"string" 175 | } 176 | ``` 177 | 178 | * Test 179 | ``` bash 180 | curl "http://localhost:7123/api/Remove/1234/1" 181 | ``` 182 | 183 | 184 | #### Status 185 | UserId에 해당하는 모든 Job에 대한 진행 정보를 가져옵니다. 186 | 187 | * URL : /api/Status/{UserId} -> 해당 UserId에 대한 모든 Job Status 188 | * URL : /api/Status/{UserId}?JobId=1&SrcBucket=bucket1&DstBucket=bucket2 189 | 190 | * Request 191 | 192 | * Return 193 | 194 | ``` bash 195 | { 196 | "Result":"string", // success, failed 197 | "Message":null, 198 | "Items":[ 199 | { 200 | "JobId":0, 201 | "Status":"string", 202 | "Source":"string", 203 | "Target":"string", 204 | "StartTime":"string", 205 | "EndTime":"string", 206 | "ErrorDesc":"string", 207 | "TotalCount":0, 208 | "TotalSize":"string", 209 | "MovedCount":0, 210 | "MovedSize":"string", 211 | "SkippedCount":0, 212 | "SkippedSize":"string", 213 | "FailedCount":0, 214 | "FailedSize":"string", 215 | "Progress":"string" 216 | }, 217 | ] 218 | } 219 | // Status 220 | INIT 221 | MOVE 222 | COMPLETE 223 | STOP 224 | RERUN INIT 225 | RERUN MOVE 226 | ERROR 227 | ``` 228 | 229 | * Test 230 | ``` bash // 1234 유저에 대한 모든 Job Status 231 | curl "http://localhost:7123/api/Status/1234" 232 | ``` 233 | ``` bash // 1234 유저에 대한 JobId=4인 Job Status 234 | curl "http://localhost:7123/api/Status/1234?JobId=4" 235 | ``` 236 | ``` bash // 1234 유저에 대한 SrcBucket=bucket인 Job Status 237 | curl "http://localhost:7123/api/Status/1234?SrcBucket=bucket" 238 | ``` 239 | ``` bash // 1234 유저에 대한 DstBucket=bucket인 Job Status 240 | curl "http://localhost:7123/api/Status/1234?DstBucket=bucket" 241 | ``` 242 | ``` bash // 1234 유저에 대한 SrcBucket=bucket1, DstBucket=bucket2인 Job Status 243 | curl "http://localhost:7123/api/Status/1234?SrcBucket=bucket1&DstBucket=bucket2" 244 | ``` 245 | 246 | ### 구동 환경 247 | * JDK 11+ 248 | 249 | 250 | ## How to Get Started 251 | git clone https://github.com/infinistor/ifsmoverrest.git 252 | 253 | ## How to Build 254 | 255 | ### Maven 설치 256 | * Maven이 설치되어 있는지 확인해야 합니다. 257 | 258 | * mvn -v 로 설치되어 있는지 확인하세요. 259 | 260 | * 설치가 되어 있지 않으면 다음 명령어로 설치를 해야 합니다.
261 | sudo apt install maven 262 | 263 | ### Build 264 | 265 | * pom.xml 파일이 있는 위치에서 mvn package 명령어를 입력하시면 빌드가 되고, 빌드가 완료되면 target이라는 폴더에 ifsmoverRest.jar가 생성됩니다. 266 | 267 | 268 | ## How to Use (빌드한 경우) 269 | 270 | * ifsmoverRest를 실행시키기 위하여 필요한 파일은 4개입니다. 271 | * target/ifsmoverRest.jar - 소스 빌드 후, 생성된 실행 파일 272 | * script/ifsmoverRest.sh - ifsmoverRest.jar를 실행시켜 주는 스크립트 273 | * script/ifsmoverRest.conf - ifsmoverRest.jar의 config 파일 274 | * script/ifsmoverRestLog.xml - log 관련 설정 275 | 276 | * 4개의 파일을 실행시킬 위치에 복사합니다. 277 | * target/ifsmoverRest.jar -> 실행시킬 위치/lib/ifsmoverRest.jar 278 | * script/ifsmoverRest.sh -> 실행시킬 위치/lib/ifsmoverRest.sh 279 | * script/ifsmoverRest.conf -> 실행시킬 위치/etc/ifsmoverRest.conf 280 | * script/ifsmoverRestLog.xml -> 실행시킬 위치/etc/ifsmoverRestLog.xml 281 | 282 | * ifsmoverRest.sh의 실행 권한을 확인합니다. 283 | * ifsmoverRest.sh의 실행 권한이 없는 경우 실행권한을 부여합니다.
284 | chmod +x ifsmoverRest.sh 285 | 286 | * 실행시킬 위치/etc/ifsmoverRest.conf에 ifsmoverRest 설정 정보를 입력합니다. 287 | 288 | ```bash 289 | endpoint=http://0.0.0.0:7123 // ifsmoverRest Server가 사용할 http port number 290 | secure-endpoint=https://0.0.0.0:7333 // ifsmverRest Server가 사용할 https port number 291 | keystore-path= // 인증서 위치, ** 인증서는 .jks만 지원합니다. 292 | keystore-passwords= // 인증서 암호 293 | ifsmover_path=/usr/local/pspace/bin/ifsmover-0.2.6 // ifsmover가 설지된 디렉토리 294 | db_repository=mariadb // [sqlite, mariadb] *주의 ifsmover와 설정이 같아야 합니다. 295 | db_host= // mariadb 시, host ip 296 | db_name= // mariadb 시, database name 297 | db_port= // mariadb 시, port 298 | db_user= // mariadb 시, user name 299 | db_password= // mariadb 시, user passwords 300 | db_pool_size=5 // mariadb 시, connection pool size 301 | ``` 302 | 303 | * ifsmoverRest.sh를 실행합니다.
304 | ./ifsmoverRest.sh 305 | 306 | 307 | ## How to Use (배포판의 경우) 308 | 309 | * 아래 배포판 페이지의 "Asset" 항목을 펼쳐서 ifsmoverRest-x.x.x.tar.gz 파일 링크를 미리 복사하세요. 310 | * 배포판 페이지 : https://github.com/infinistor/ifsmoverrest/releases 311 | 312 | * 배포판을 다운로드하고 압축을 풀어 설치합니다. 313 | 314 | ```bash 315 | # mkdir /usr/local/pspace 316 | # mkdir /usr/local/pspace/bin 317 | # cd /usr/local/pspace/bin 318 | # wget "https://github.com/infinistor/ifsmover/releases/download/v0.x.x/ifsmoverRest-0.x.x.tar.gz" 319 | # tar -xvf ifsmoverRest-0.x.x.tar.gz 320 | # mv ifsmoverRest-0.x.x ifsmoverRest 321 | ``` 322 | 323 | * 설치 경로로 이동합니다.
324 | cd /usr/local/pspace/bin/ifsmoverRest 325 | 326 | * /usr/local/pspace/bin/ifsmoverRest/etc/ifsmoverRest.conf에 ifsmoverRest 설정 정보를 입력합니다. 327 | 328 | ```bash 329 | endpoint=http://0.0.0.0:7123 // ifsmoverRest Server가 사용할 http port number 330 | secure-endpoint=https://0.0.0.0:7333 // ifsmverRest Server가 사용할 https port number 331 | keystore-path= // 인증서 위치, ** 인증서는 .jks만 지원합니다. 332 | keystore-passwords= // 인증서 암호 333 | ifsmover_path=/usr/local/pspace/bin/ifsmover-0.2.6 // ifsmover가 설지된 디렉토리 334 | ``` 335 | 336 | * ifsmoverRest.sh를 실행합니다.
337 | ./ifsmoverRest.sh 338 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/RestConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest; 12 | 13 | import static java.util.Objects.requireNonNull; 14 | 15 | import java.io.FileInputStream; 16 | import java.io.FileNotFoundException; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.net.URI; 20 | import java.net.URISyntaxException; 21 | import java.util.Properties; 22 | 23 | import com.google.common.base.Strings; 24 | 25 | import org.slf4j.Logger; 26 | import org.slf4j.LoggerFactory; 27 | 28 | public class RestConfig { 29 | private static final String SYSTEM_CONFIG_KEY = "configure"; 30 | private static final String CONFIG_FILE = "/usr/local/pspace/etc/moverrest/ifsmoverRest.conf"; 31 | private static final String ENDPOINT = "endpoint"; 32 | private static final String SECURE_ENDPOINT = "secure-endpoint"; 33 | private static final String KEYSTORE_PATH = "keystore-path"; 34 | private static final String KEYSTORE_PASSWORD = "keystore-password"; 35 | private static final String JETTY_MAX_IDLE_TIMEOUT = "jettyMaxIdleTimeout"; 36 | private static final String IFSMOVER_PATH = "ifsmover-path"; 37 | private static final String DB_REPOSITORY = "db_repository"; 38 | private static final String DB_HOST = "db_host"; 39 | private static final String DB_NAME = "db_name"; 40 | private static final String DB_PORT = "db_port"; 41 | private static final String DB_USER = "db_user"; 42 | private static final String DB_PASSWORD = "db_password"; 43 | private static final String DB_POOL_SIZE = "db_pool_size"; 44 | public static final String MARIADB = "mariadb"; 45 | public static final String SQLITEDB = "sqlite"; 46 | 47 | private static final String LOG_CONFIG_MUST_CONTAIN = "config file must contain: "; 48 | 49 | private Properties properties; 50 | private static final Logger logger = LoggerFactory.getLogger(RestConfig.class); 51 | private URI endpoint; 52 | private URI secureEndpoint; 53 | private String keystorePath; 54 | private String keystorePassword; 55 | private long jettyMaxIdleTimeout; 56 | private String ifsmoverPath; 57 | private static String dbRepository; 58 | private String dbHost; 59 | private String database; 60 | private String dbPort; 61 | private String dbUser; 62 | private String dbPass; 63 | private int dbPoolSize; 64 | 65 | public static RestConfig getInstance() { 66 | return LazyHolder.INSTANCE; 67 | } 68 | 69 | private static class LazyHolder { 70 | private static RestConfig INSTANCE = new RestConfig(); 71 | } 72 | 73 | private RestConfig() { 74 | String path = System.getProperty(SYSTEM_CONFIG_KEY); 75 | if (path == null) { 76 | path = CONFIG_FILE; 77 | } 78 | 79 | properties = new Properties(); 80 | try (InputStream myis = new FileInputStream(path)) { 81 | properties.load(myis); 82 | } catch (FileNotFoundException e) { 83 | throw new IllegalArgumentException("Properties file is not exist."); 84 | } catch (IOException e) { 85 | throw new IllegalArgumentException("Properties file load is failed."); 86 | } 87 | 88 | try { 89 | configure(); 90 | } catch (URISyntaxException e) { 91 | PrintStack.logging(logger, e); 92 | throw new IllegalArgumentException("Properties file load is fail"); 93 | } 94 | } 95 | 96 | public void configure() throws URISyntaxException { 97 | String endpoint = properties.getProperty(ENDPOINT); 98 | String secureEndpoint = properties.getProperty(SECURE_ENDPOINT); 99 | if (Strings.isNullOrEmpty(endpoint) && Strings.isNullOrEmpty(secureEndpoint)) { 100 | throw new IllegalArgumentException( 101 | "Properties file must contain: " + 102 | ENDPOINT + " or " + 103 | SECURE_ENDPOINT); 104 | } 105 | 106 | if (!Strings.isNullOrEmpty(endpoint)) { 107 | this.endpoint = requireNonNull(new URI(endpoint)); 108 | } 109 | 110 | if (!Strings.isNullOrEmpty(secureEndpoint)) { 111 | this.secureEndpoint = requireNonNull(new URI(secureEndpoint)); 112 | } 113 | 114 | this.keystorePath = properties.getProperty(KEYSTORE_PATH); 115 | this.keystorePassword = properties.getProperty(KEYSTORE_PASSWORD); 116 | 117 | String strJettyMaxIdleTimeout = properties.getProperty(JETTY_MAX_IDLE_TIMEOUT); 118 | if (strJettyMaxIdleTimeout == null) { 119 | jettyMaxIdleTimeout = 30000; 120 | } else { 121 | jettyMaxIdleTimeout = Long.parseLong(strJettyMaxIdleTimeout); 122 | } 123 | 124 | ifsmoverPath = properties.getProperty(IFSMOVER_PATH); 125 | if (Strings.isNullOrEmpty(ifsmoverPath)) { 126 | throw new IllegalArgumentException("Configuration file ifsmover-path is not exist."); 127 | } 128 | 129 | dbRepository = properties.getProperty(DB_REPOSITORY); 130 | dbHost = properties.getProperty(DB_HOST); 131 | if (dbRepository == null) { 132 | if (dbHost == null) { 133 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_HOST); 134 | } 135 | } else { 136 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 137 | if (dbHost == null) { 138 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_HOST); 139 | } 140 | } 141 | } 142 | 143 | database = properties.getProperty(DB_NAME); 144 | if (dbRepository == null) { 145 | if (database == null) { 146 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_NAME); 147 | } 148 | } else { 149 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 150 | if (database == null) { 151 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_NAME); 152 | } 153 | } 154 | } 155 | 156 | dbPort = properties.getProperty(DB_PORT); 157 | if (dbRepository == null) { 158 | if (dbPort == null) { 159 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_PORT); 160 | } 161 | } else { 162 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 163 | if (dbPort == null) { 164 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_PORT); 165 | } 166 | } 167 | } 168 | 169 | dbUser = properties.getProperty(DB_USER); 170 | if (dbRepository == null) { 171 | if (dbUser == null) { 172 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_USER); 173 | } 174 | } else { 175 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 176 | if (dbUser == null) { 177 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_USER); 178 | } 179 | } 180 | } 181 | 182 | dbPass = properties.getProperty(DB_PASSWORD); 183 | if (dbRepository == null) { 184 | if (dbPass == null) { 185 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_PASSWORD); 186 | } 187 | } else { 188 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 189 | if (dbPass == null) { 190 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_PASSWORD); 191 | } 192 | } 193 | } 194 | 195 | String dbPoolSize = properties.getProperty(DB_POOL_SIZE); 196 | if (dbRepository == null) { 197 | if (dbPoolSize == null) { 198 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_POOL_SIZE); 199 | } else { 200 | this.dbPoolSize = Integer.parseInt(dbPoolSize); 201 | } 202 | } else { 203 | if (dbRepository.equalsIgnoreCase(MARIADB)) { 204 | if (dbPoolSize == null) { 205 | throw new IllegalArgumentException(LOG_CONFIG_MUST_CONTAIN + DB_POOL_SIZE); 206 | } else { 207 | this.dbPoolSize = Integer.parseInt(dbPoolSize); 208 | } 209 | } 210 | } 211 | 212 | if (dbRepository == null) { 213 | dbRepository = MARIADB; 214 | } 215 | } 216 | 217 | public URI getEndpoint() { 218 | return this.endpoint; 219 | } 220 | 221 | public URI getSecureEndpoint() { 222 | return this.secureEndpoint; 223 | } 224 | 225 | public String getKeystorePath() { 226 | if (Strings.isNullOrEmpty(keystorePath)) { 227 | return null; 228 | } 229 | return this.keystorePath; 230 | } 231 | 232 | public String getKeystorePassword() { 233 | if (Strings.isNullOrEmpty(keystorePassword)) { 234 | return null; 235 | } 236 | return this.keystorePassword; 237 | } 238 | 239 | public long getJettyMaxIdleTimeout() { 240 | return jettyMaxIdleTimeout; 241 | } 242 | 243 | public String getPath() { 244 | return ifsmoverPath; 245 | } 246 | 247 | public static String getDBRepository() { 248 | return dbRepository; 249 | } 250 | 251 | public String getDbHost() { 252 | return dbHost; 253 | } 254 | 255 | public String getDatabase() { 256 | return database; 257 | } 258 | 259 | public String getDbPort() { 260 | return dbPort; 261 | } 262 | 263 | public String getDbUser() { 264 | return dbUser; 265 | } 266 | 267 | public String getDbPass() { 268 | return dbPass; 269 | } 270 | 271 | public int getDbPoolSize() { 272 | return dbPoolSize; 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/db/MariaDB.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.db; 12 | 13 | import java.sql.Connection; 14 | import java.sql.PreparedStatement; 15 | import java.sql.ResultSet; 16 | import java.sql.ResultSetMetaData; 17 | import java.sql.SQLException; 18 | import java.util.ArrayList; 19 | import java.util.HashMap; 20 | import java.util.List; 21 | import java.util.Map; 22 | 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | import com.zaxxer.hikari.HikariConfig; 27 | import com.zaxxer.hikari.HikariDataSource; 28 | 29 | public class MariaDB implements DBManager { 30 | protected Logger logger; 31 | private static HikariConfig config = new HikariConfig(); 32 | private static HikariDataSource ds; 33 | 34 | private static final String CREATE_DATABASE = "CREATE DATABASE IF NOT EXISTS "; 35 | private static final String CREATE_USER_MATCH_JOB_TABLE = 36 | "CREATE TABLE IF NOT EXISTS `UserMatchJob` (\n" 37 | + "`match_id` INT NOT NULL AUTO_INCREMENT,\n" 38 | + "`user_id` TEXT,\n" 39 | + "`job_id` INT NOT NULL,\n" 40 | + "PRIMARY KEY(`match_id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;"; 41 | 42 | private MariaDB() { 43 | logger = LoggerFactory.getLogger(MariaDB.class); 44 | } 45 | 46 | public static MariaDB getInstance() { 47 | return LazyHolder.INSTANCE; 48 | } 49 | 50 | private static class LazyHolder { 51 | private static final MariaDB INSTANCE = new MariaDB(); 52 | } 53 | 54 | public List> select(String query, List params) throws Exception { 55 | List> rmap = null; 56 | 57 | Connection conn = null; 58 | PreparedStatement pstmt = null; 59 | ResultSet rset = null; 60 | try { 61 | conn = ds.getConnection(); 62 | pstmt = conn.prepareStatement(query); 63 | 64 | int index = 1; 65 | if(params != null) { 66 | for(Object p : params) { 67 | pstmt.setObject(index, p); 68 | index++; 69 | } 70 | } 71 | 72 | // logger.debug(pstmt.toString()); 73 | rset = pstmt.executeQuery(); 74 | 75 | ResultSetMetaData md = rset.getMetaData(); 76 | int columns = md.getColumnCount(); 77 | int init = 0; 78 | while (rset.next()) { 79 | if(init == 0) { 80 | rmap = new ArrayList>(); 81 | init++; 82 | } 83 | 84 | HashMap map = null; 85 | map = new HashMap(columns); 86 | for(int i=1; i<=columns; ++i) { 87 | map.put(md.getColumnName(i), rset.getObject(i)); 88 | } 89 | rmap.add(map); 90 | } 91 | } catch (SQLException e) { 92 | logger.error(e.getMessage()); 93 | throw new Exception("Error"); 94 | } catch (Exception e) { 95 | logger.error(e.getMessage()); 96 | throw new Exception("Error"); 97 | } finally { 98 | if ( rset != null ) try { rset.close(); } catch (Exception e) {logger.error(e.getMessage()); throw new Exception("Error");} 99 | if ( pstmt != null ) try { pstmt.close(); } catch (Exception e) {logger.error(e.getMessage()); throw new Exception("Error");} 100 | if ( conn != null ) try { conn.close(); } catch (Exception e) {logger.error(e.getMessage()); throw new Exception("Error");} 101 | } 102 | 103 | return rmap; 104 | } 105 | 106 | private void execute(String query, List params) throws Exception { 107 | try (Connection conn = ds.getConnection(); 108 | PreparedStatement pstmt = conn.prepareStatement(query); 109 | ) { 110 | 111 | int index = 1; 112 | if(params != null) { 113 | for(Object p : params) { 114 | pstmt.setObject(index, p); 115 | index++; 116 | } 117 | } 118 | 119 | // logger.debug(pstmt.toString()); 120 | pstmt.execute(); 121 | } catch (SQLException e) { 122 | logger.error(e.getMessage()); 123 | throw new Exception("Error"); 124 | } catch (Exception e) { 125 | logger.error(e.getMessage()); 126 | throw new Exception("Error"); 127 | } 128 | } 129 | 130 | @Override 131 | public void init(String dbUrl, String dbPort, String dbName, String userName, String passwd, int poolSize) 132 | throws Exception { 133 | // TODO Auto-generated method stub 134 | String jdbcUrl = "jdbc:mariadb://" + dbUrl + ":" + dbPort + "/" + dbName + "?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8"; 135 | 136 | config.setJdbcUrl(jdbcUrl); 137 | config.setUsername(userName); 138 | config.setPassword(passwd); 139 | config.setDriverClassName("org.mariadb.jdbc.Driver"); 140 | config.setConnectionTestQuery("select 1"); 141 | config.addDataSourceProperty("maxPoolSize" , poolSize ); 142 | config.addDataSourceProperty("minPoolSize" , poolSize ); 143 | config.setPoolName("ifsmover"); 144 | config.setMaximumPoolSize(poolSize); 145 | config.setMinimumIdle(poolSize); 146 | 147 | ds = new HikariDataSource(config); 148 | 149 | createDB(dbName, userName, passwd); 150 | 151 | createTable(); 152 | } 153 | 154 | private void createDB(String dbname, String userName, String userPasswd) throws Exception { 155 | String query = CREATE_DATABASE + dbname + ";"; 156 | execute(query, null); 157 | } 158 | 159 | private void createTable() throws Exception { 160 | String query = CREATE_USER_MATCH_JOB_TABLE; 161 | execute(query, null); 162 | } 163 | 164 | @Override 165 | public Map getJobInfo(String jobId) { 166 | // TODO Auto-generated method stub 167 | Map info = new HashMap(); 168 | 169 | String sql = SQL_GET_JOB_INFO + jobId; 170 | 171 | List> resultList = null; 172 | try { 173 | resultList = select(sql, null); 174 | if (resultList != null) { 175 | info.put(JOB_TABLE_COLUMN_JOB_STATE, (int)resultList.get(0).get(JOB_TABLE_COLUMN_JOB_STATE)); 176 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, (String)resultList.get(0).get(JOB_TABLE_COLUMN_JOB_TYPE)); 177 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, (String) resultList.get(0).get(JOB_TABLE_COLUMN_ERROR_DESC)); 178 | } 179 | } catch (Exception e) { 180 | logger.error(e.getMessage()); 181 | } 182 | 183 | return info; 184 | } 185 | 186 | @Override 187 | public void insertUserMatchJob(String userId, String jobId) { 188 | // TODO Auto-generated method stub 189 | String sql = SQL_INSERT_USERMATCHJOB; 190 | List params = new ArrayList(); 191 | params.add(userId); 192 | params.add(jobId); 193 | 194 | try { 195 | execute(sql, params); 196 | } catch (Exception e) { 197 | logger.error(e.getMessage()); 198 | } 199 | } 200 | 201 | @Override 202 | public int getUserMatchJob(String userId, String jobId) { 203 | // TODO Auto-generated method stub 204 | int matchId = 0; 205 | String sql = SQL_GET_USERMATCHJOB + userId + SQL_GET_USERMATCHJOB_JOBID + jobId + "'"; 206 | List> resultList = null; 207 | try { 208 | resultList = select(sql, null); 209 | if (resultList != null) { 210 | if (resultList.get(0).get(MATCH_TABLE_COLUMN_MATCH_ID) != null) { 211 | matchId = (int) resultList.get(0).get(MATCH_TABLE_COLUMN_MATCH_ID); 212 | } 213 | } 214 | } catch (Exception e) { 215 | logger.error(e.getMessage()); 216 | } 217 | 218 | return matchId; 219 | } 220 | 221 | @Override 222 | public void deleteUserMatchJob(long matchId) { 223 | // TODO Auto-generated method stub 224 | String sql = SQL_DELETE_USERMATCHJOB + matchId; 225 | try { 226 | execute(sql, null); 227 | } catch (Exception e) { 228 | logger.error(e.getMessage()); 229 | } 230 | } 231 | 232 | @Override 233 | public List> status(String userId) { 234 | // TODO Auto-generated method stub 235 | try { 236 | return select(SQL_SELECT_JOB_STATUS + userId + "' ORDER BY A.job_id", null); 237 | } catch (Exception e) { 238 | logger.error(e.getMessage()); 239 | } 240 | 241 | return null; 242 | } 243 | 244 | @Override 245 | public List> status(String userId, String jobId) { 246 | // TODO Auto-generated method stub 247 | try { 248 | List params = new ArrayList(); 249 | params.add(jobId); 250 | return select(SQL_SELECT_JOB_STATUS + userId + "' and A.job_id = ?", params); 251 | } catch (Exception e) { 252 | logger.error(e.getMessage()); 253 | } 254 | return null; 255 | } 256 | 257 | @Override 258 | public List> status(String userId, String srcBucket, String dstBucket) { 259 | // TODO Auto-generated method stub 260 | try { 261 | List params = new ArrayList(); 262 | params.add("%" + srcBucket + "%"); 263 | params.add("%" + dstBucket + "%"); 264 | return select(SQL_SELECT_JOB_STATUS + userId + "' and A.source_point LIKE ? and A.target_point LIKE ?", params); 265 | } catch (Exception e) { 266 | logger.error(e.getMessage()); 267 | } 268 | return null; 269 | } 270 | 271 | @Override 272 | public List> statusSrcBucket(String userId, String srcBucket) { 273 | // TODO Auto-generated method stub 274 | try { 275 | List params = new ArrayList(); 276 | params.add("%" + srcBucket + "%"); 277 | return select(SQL_SELECT_JOB_STATUS + userId + "' and A.source_point LIKE ?", params); 278 | } catch (Exception e) { 279 | logger.error(e.getMessage()); 280 | } 281 | return null; 282 | } 283 | 284 | @Override 285 | public List> statusDstBucket(String userId, String dstBucket) { 286 | // TODO Auto-generated method stub 287 | try { 288 | List params = new ArrayList(); 289 | params.add("%" + dstBucket + "%"); 290 | return select(SQL_SELECT_JOB_STATUS + userId + "' and A.target_point LIKE ?", params); 291 | } catch (Exception e) { 292 | logger.error(e.getMessage()); 293 | } 294 | return null; 295 | } 296 | 297 | } 298 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Rerun.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.File; 14 | import java.io.FileWriter; 15 | import java.io.IOException; 16 | import java.util.Map; 17 | import java.util.UUID; 18 | 19 | import com.pspace.ifsmover.rest.RestConfig; 20 | import com.pspace.ifsmover.rest.S3Config; 21 | import com.pspace.ifsmover.rest.Utils; 22 | import com.pspace.ifsmover.rest.PrintStack; 23 | import com.pspace.ifsmover.rest.data.DataRerun; 24 | import com.pspace.ifsmover.rest.data.format.JsonRerun; 25 | import com.pspace.ifsmover.rest.db.DBManager; 26 | import com.pspace.ifsmover.rest.exception.ErrCode; 27 | import com.pspace.ifsmover.rest.exception.RestException; 28 | import com.pspace.ifsmover.rest.repository.IfsS3; 29 | import com.pspace.ifsmover.rest.repository.Repository; 30 | import com.pspace.ifsmover.rest.repository.RepositoryFactory; 31 | 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | 35 | import jakarta.servlet.http.HttpServletRequest; 36 | import jakarta.servlet.http.HttpServletResponse; 37 | 38 | public class Rerun extends MoverRequest { 39 | private static final Logger logger = LoggerFactory.getLogger(Rerun.class); 40 | private String userId = null; 41 | private String jobId = null; 42 | private JsonRerun jsonRerun = null; 43 | private String command = null; 44 | 45 | public Rerun(HttpServletRequest request, HttpServletResponse response, String userId, String jobId) { 46 | super(request, response); 47 | this.userId = userId; 48 | this.jobId = jobId; 49 | } 50 | 51 | @Override 52 | public void process() throws RestException { 53 | // TODO Auto-generated method stub 54 | logger.info("Rerun ..."); 55 | logger.info("userId : {}, jobId : {}", userId, jobId); 56 | 57 | try { 58 | DataRerun dataRerun = new DataRerun(request.getInputStream()); 59 | 60 | try { 61 | dataRerun.extract(); 62 | } catch (Exception e) { 63 | throw new RestException(ErrCode.BAD_REQUEST); 64 | } 65 | 66 | jsonRerun = dataRerun.getJsonRerun(); 67 | 68 | long matchId = Utils.getDBInstance().getUserMatchJob(userId, jobId); 69 | if (matchId == -1) { 70 | logger.error("Not exist userId and jobId"); 71 | setReturnJaonError("Not exist userId and jobId", false); 72 | return; 73 | } 74 | 75 | Map info = null; 76 | info = Utils.getDBInstance().getJobInfo(jobId); 77 | 78 | if (info == null) { 79 | logger.error("Can't find job({})", jobId); 80 | throw new RestException(ErrCode.BAD_REQUEST); 81 | } 82 | 83 | // Check 84 | S3Config config = null; 85 | config = new S3Config(jsonRerun.getSource().getMountPoint(), 86 | jsonRerun.getSource().getEndPoint(), 87 | jsonRerun.getSource().getAccess(), 88 | jsonRerun.getSource().getSecret(), 89 | jsonRerun.getSource().getBucket(), 90 | jsonRerun.getSource().getPrefix()); 91 | 92 | RepositoryFactory factory = new RepositoryFactory(); 93 | Repository sourceRepository = factory.getSourceRepository((String)info.get(DBManager.JOB_TABLE_COLUMN_JOB_TYPE)); 94 | sourceRepository.setConfig(config, true); 95 | int result = sourceRepository.check(); 96 | if (result != 0) { 97 | setReturnJaonError(sourceRepository.getErrMessage(), false); 98 | return; 99 | } 100 | 101 | config = new S3Config(null, 102 | jsonRerun.getTarget().getEndPoint(), 103 | jsonRerun.getTarget().getAccess(), 104 | jsonRerun.getTarget().getSecret(), 105 | jsonRerun.getTarget().getBucket(), 106 | jsonRerun.getTarget().getPrefix()); 107 | IfsS3 ifsS3 = new IfsS3(); 108 | ifsS3.setConfig(config, false); 109 | result = ifsS3.check(); 110 | if (result != 0) { 111 | setReturnJaonError(ifsS3.getErrMessage(), false); 112 | return; 113 | } 114 | 115 | String uuid = UUID.randomUUID().toString(); 116 | String sourceFileName = "source-" + uuid; 117 | String targetFileName = "target-" + uuid; 118 | 119 | printJsonRerun(); 120 | saveSourceConfFile(sourceFileName); 121 | saveTargetConfFile(targetFileName); 122 | 123 | String osName = System.getProperty("os.name").toLowerCase(); 124 | if (osName.contains("win")) { 125 | command = "python ifs_mover -rerun=" + jobId + " -source=" + sourceFileName + " -target=" + targetFileName; 126 | } else { 127 | command = "./ifs_mover -rerun=" + jobId + " -source=" + sourceFileName + " -target=" + targetFileName; 128 | } 129 | 130 | File file = new File(RestConfig.getInstance().getPath()); 131 | Process process = Runtime.getRuntime().exec(command, null, file); 132 | process.waitFor(); 133 | 134 | info = Utils.getDBInstance().getJobInfo(jobId); 135 | if (info == null) { 136 | logger.warn("Not exist userId and jobId"); 137 | setReturnJaonError("Not exist userId and jobId", false); 138 | return; 139 | } 140 | 141 | String returnJson = null; 142 | returnJson = "{\"Result\":\"success\", \"Message\":null}"; 143 | response.getOutputStream().write(returnJson.getBytes()); 144 | response.setStatus(HttpServletResponse.SC_OK); 145 | } catch (IOException | InterruptedException e) { 146 | PrintStack.logging(logger, e); 147 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 148 | } 149 | } 150 | 151 | public void printJsonRerun() { 152 | logger.info("Source.mountpoint : {}", jsonRerun.getSource().getMountPoint()); 153 | logger.info("Source.endpoint : {}", jsonRerun.getSource().getEndPoint()); 154 | logger.info("Source.access : {}", jsonRerun.getSource().getAccess()); 155 | logger.info("Source.secret : {}", jsonRerun.getSource().getSecret()); 156 | logger.info("Source.bucket : {}", jsonRerun.getSource().getBucket()); 157 | logger.info("Source.prefix : {}", jsonRerun.getSource().getPrefix()); 158 | logger.info("Source.move_size : {}", jsonRerun.getSource().getMoveSize()); 159 | logger.info("target.endpoint : {}", jsonRerun.getTarget().getEndPoint()); 160 | logger.info("target.access : {}", jsonRerun.getTarget().getAccess()); 161 | logger.info("target.secret : {}", jsonRerun.getTarget().getSecret()); 162 | logger.info("target.bucket : {}", jsonRerun.getTarget().getBucket()); 163 | logger.info("target.prefix : {}", jsonRerun.getTarget().getPrefix()); 164 | } 165 | 166 | public void saveSourceConfFile(String fileName) throws IOException { 167 | try { 168 | String fullPath = null; 169 | String path = RestConfig.getInstance().getPath(); 170 | if (path.charAt(path.length() - 1) == '/') { 171 | fullPath = path + fileName; 172 | } else { 173 | fullPath = path + "/" + fileName; 174 | } 175 | FileWriter fileWriter = new FileWriter(fullPath, false); 176 | if (jsonRerun.getSource().getMountPoint() == null) { 177 | fileWriter.write("mountpoint=\n"); 178 | } else { 179 | fileWriter.write("mountpoint=" + jsonRerun.getSource().getMountPoint() + "\n"); 180 | } 181 | if (jsonRerun.getSource().getEndPoint() == null) { 182 | fileWriter.write("endpoint=\n"); 183 | } else { 184 | fileWriter.write("endpoint=" + jsonRerun.getSource().getEndPoint() + "\n"); 185 | } 186 | if (jsonRerun.getSource().getAccess() == null) { 187 | fileWriter.write("access=\n"); 188 | } else { 189 | fileWriter.write("access=" + jsonRerun.getSource().getAccess() + "\n"); 190 | } 191 | if (jsonRerun.getSource().getSecret() == null) { 192 | fileWriter.write("secret=\n"); 193 | } else { 194 | fileWriter.write("secret=" + jsonRerun.getSource().getSecret() + "\n"); 195 | } 196 | if (jsonRerun.getSource().getBucket() == null) { 197 | fileWriter.write("bucket=\n"); 198 | } else { 199 | fileWriter.write("bucket=" + jsonRerun.getSource().getBucket() + "\n"); 200 | } 201 | if (jsonRerun.getSource().getPrefix() == null) { 202 | fileWriter.write("prefix=\n"); 203 | } else { 204 | fileWriter.write("prefix=" + jsonRerun.getSource().getPrefix() + "\n"); 205 | } 206 | if (jsonRerun.getSource().getMoveSize() == null) { 207 | fileWriter.write("move_size=\n"); 208 | } else { 209 | fileWriter.write("move_size=" + jsonRerun.getSource().getMoveSize() + "\n"); 210 | } 211 | 212 | fileWriter.close(); 213 | } catch (IOException e) { 214 | throw new IOException(e); 215 | } 216 | } 217 | 218 | public void saveTargetConfFile(String fileName) throws IOException { 219 | try { 220 | String fullPath = null; 221 | String path = RestConfig.getInstance().getPath(); 222 | if (path.charAt(path.length() - 1) == '/') { 223 | fullPath = path + fileName; 224 | } else { 225 | fullPath = path + "/" + fileName; 226 | } 227 | FileWriter fileWriter = new FileWriter(fullPath, false); 228 | if (jsonRerun.getTarget().getEndPoint() == null) { 229 | fileWriter.write("endpoint=\n"); 230 | } else { 231 | fileWriter.write("endpoint=" + jsonRerun.getTarget().getEndPoint() + "\n"); 232 | } 233 | if (jsonRerun.getTarget().getAccess() == null) { 234 | fileWriter.write("access=\n"); 235 | } else { 236 | fileWriter.write("access=" + jsonRerun.getTarget().getAccess() + "\n"); 237 | } 238 | if (jsonRerun.getTarget().getSecret() == null) { 239 | fileWriter.write("secret=\n"); 240 | } else { 241 | fileWriter.write("secret=" + jsonRerun.getTarget().getSecret() + "\n"); 242 | } 243 | if (jsonRerun.getTarget().getBucket() == null) { 244 | fileWriter.write("bucket=\n"); 245 | } else { 246 | fileWriter.write("bucket=" + jsonRerun.getTarget().getBucket() + "\n"); 247 | } 248 | if (jsonRerun.getTarget().getPrefix() == null) { 249 | fileWriter.write("prefix=\n"); 250 | } else { 251 | fileWriter.write("prefix=" + jsonRerun.getTarget().getPrefix() + "\n"); 252 | } 253 | 254 | fileWriter.close(); 255 | } catch (IOException e) { 256 | throw new IOException(e); 257 | } 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Start.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.BufferedReader; 14 | import java.io.File; 15 | import java.io.FileReader; 16 | import java.io.FileWriter; 17 | import java.io.IOException; 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | import com.pspace.ifsmover.rest.RestConfig; 22 | import com.pspace.ifsmover.rest.S3Config; 23 | import com.pspace.ifsmover.rest.Utils; 24 | import com.google.common.base.Strings; 25 | import com.pspace.ifsmover.rest.PrintStack; 26 | import com.pspace.ifsmover.rest.data.DataStart; 27 | import com.pspace.ifsmover.rest.data.format.JsonStart; 28 | import com.pspace.ifsmover.rest.db.DBManager; 29 | import com.pspace.ifsmover.rest.exception.ErrCode; 30 | import com.pspace.ifsmover.rest.exception.RestException; 31 | import com.pspace.ifsmover.rest.repository.IfsS3; 32 | import com.pspace.ifsmover.rest.repository.Repository; 33 | import com.pspace.ifsmover.rest.repository.RepositoryFactory; 34 | 35 | import org.slf4j.Logger; 36 | import org.slf4j.LoggerFactory; 37 | 38 | import jakarta.servlet.http.HttpServletRequest; 39 | import jakarta.servlet.http.HttpServletResponse; 40 | 41 | public class Start extends MoverRequest { 42 | private static final Logger logger = LoggerFactory.getLogger(Start.class); 43 | private JsonStart jsonStart = null; 44 | private String command = null; 45 | 46 | public Start(HttpServletRequest request, HttpServletResponse response) { 47 | super(request, response); 48 | } 49 | 50 | @Override 51 | public void process() throws RestException { 52 | // TODO Auto-generated method stub 53 | logger.info("Start ..."); 54 | 55 | try { 56 | DataStart dataStart = new DataStart(request.getInputStream()); 57 | try { 58 | dataStart.extract(); 59 | } catch (Exception e) { 60 | throw new RestException(ErrCode.BAD_REQUEST); 61 | } 62 | 63 | jsonStart = dataStart.getJsonStart(); 64 | 65 | if (jsonStart.getType().equalsIgnoreCase(Repository.SWIFT)) { 66 | throw new RestException(ErrCode.NOT_IMPLEMENTED); 67 | } else if (jsonStart.getType().equalsIgnoreCase(Repository.IFS_FILE)) { 68 | if (Strings.isNullOrEmpty(jsonStart.getSource().getMountPoint())) { 69 | logger.error("type : file - but source config mountpoint is null or empty"); 70 | throw new RestException(ErrCode.BAD_REQUEST); 71 | } 72 | } 73 | 74 | if (Strings.isNullOrEmpty(jsonStart.getUserId())) { 75 | logger.error("UserId is null or empty"); 76 | setReturnJaonError("UserId is null or empty", true); 77 | return; 78 | } 79 | 80 | // Check 81 | S3Config config = null; 82 | config = new S3Config(jsonStart.getSource().getMountPoint(), 83 | jsonStart.getSource().getEndPoint(), 84 | jsonStart.getSource().getAccess(), 85 | jsonStart.getSource().getSecret(), 86 | jsonStart.getSource().getBucket(), 87 | jsonStart.getSource().getPrefix()); 88 | 89 | RepositoryFactory factory = new RepositoryFactory(); 90 | Repository sourceRepository = factory.getSourceRepository(jsonStart.getType()); 91 | sourceRepository.setConfig(config, true); 92 | int result = sourceRepository.check(); 93 | if (result != 0) { 94 | setReturnJaonError(sourceRepository.getErrMessage(), true); 95 | return; 96 | } 97 | 98 | config = new S3Config(null, 99 | jsonStart.getTarget().getEndPoint(), 100 | jsonStart.getTarget().getAccess(), 101 | jsonStart.getTarget().getSecret(), 102 | jsonStart.getTarget().getBucket(), 103 | jsonStart.getTarget().getPrefix()); 104 | IfsS3 ifsS3 = new IfsS3(); 105 | ifsS3.setConfig(config, false); 106 | result = ifsS3.check(); 107 | if (result != 0) { 108 | setReturnJaonError(ifsS3.getErrMessage(), true); 109 | return; 110 | } 111 | 112 | String uuid = UUID.randomUUID().toString(); 113 | String sourceFileName = "source-" + uuid; 114 | String targetFileName = "target-" + uuid; 115 | 116 | printJsonStart(); 117 | saveSourceConfFile(sourceFileName); 118 | saveTargetConfFile(targetFileName); 119 | 120 | String osName = System.getProperty("os.name").toLowerCase(); 121 | if (osName.contains("win")) { 122 | command = "python ifs_mover -t=" + jsonStart.getType() + " -source=" + sourceFileName + " -target=" + targetFileName; 123 | } else { 124 | command = "./ifs_mover -t=" + jsonStart.getType() + " -source=" + sourceFileName + " -target=" + targetFileName; 125 | } 126 | 127 | logger.info("command : {}", command); 128 | File file = new File(RestConfig.getInstance().getPath()); 129 | Process process = Runtime.getRuntime().exec(command, null, file); 130 | 131 | // deleteJobIdFile(); 132 | String jobId = getJobIdFromFile(uuid); 133 | logger.info("JobId : {}", jobId); 134 | 135 | Map info = null; 136 | info = Utils.getDBInstance().getJobInfo(jobId); 137 | 138 | if (info == null) { 139 | logger.error("Can't find job({})", jobId); 140 | throw new RestException(ErrCode.BAD_REQUEST); 141 | } 142 | int jobState = (int) info.get(DBManager.JOB_TABLE_COLUMN_JOB_STATE); 143 | logger.info("job state : {}", info.get(DBManager.JOB_TABLE_COLUMN_JOB_STATE)); 144 | logger.info("job error desc : {}", info.get(DBManager.JOB_TABLE_COLUMN_ERROR_DESC)); 145 | Utils.getDBInstance().insertUserMatchJob(jsonStart.getUserId(), jobId); 146 | 147 | String returnJson = null; 148 | if (jobState == DBManager.JOB_STATE_ERROR) { 149 | returnJson = "{\"Result\":\"failed\", \"Message\":\"" + info.get(DBManager.JOB_TABLE_COLUMN_ERROR_DESC) + "\", \"JobId\":0}"; 150 | } else { 151 | returnJson = "{\"Result\":\"success\", \"Message\":null, \"JobId\":" + jobId + "}"; 152 | } 153 | response.getOutputStream().write(returnJson.getBytes()); 154 | response.setStatus(HttpServletResponse.SC_OK); 155 | } catch (IOException e) { 156 | PrintStack.logging(logger, e); 157 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 158 | } 159 | } 160 | 161 | public void printJsonStart() { 162 | logger.info("UserId : {}", jsonStart.getUserId()); 163 | logger.info("Type : {}", jsonStart.getType()); 164 | logger.info("Source.mountpoint : {}", jsonStart.getSource().getMountPoint()); 165 | logger.info("Source.endpoint : {}", jsonStart.getSource().getEndPoint()); 166 | logger.info("Source.access : {}", jsonStart.getSource().getAccess()); 167 | logger.info("Source.secret : {}", jsonStart.getSource().getSecret()); 168 | logger.info("Source.bucket : {}", jsonStart.getSource().getBucket()); 169 | logger.info("Source.prefix : {}", jsonStart.getSource().getPrefix()); 170 | logger.info("Source.move_size : {}", jsonStart.getSource().getMoveSize()); 171 | logger.info("Target.endpoint : {}", jsonStart.getTarget().getEndPoint()); 172 | logger.info("Target.access : {}", jsonStart.getTarget().getAccess()); 173 | logger.info("Target.secret : {}", jsonStart.getTarget().getSecret()); 174 | logger.info("Target.bucket : {}", jsonStart.getTarget().getBucket()); 175 | logger.info("Target.prefix : {}", jsonStart.getTarget().getPrefix()); 176 | } 177 | 178 | public void saveSourceConfFile(String fileName) throws IOException { 179 | try { 180 | String fullPath = null; 181 | String path = RestConfig.getInstance().getPath(); 182 | if (path.charAt(path.length() - 1) == '/') { 183 | fullPath = path + fileName; 184 | } else { 185 | fullPath = path + "/" + fileName; 186 | } 187 | 188 | FileWriter fileWriter = new FileWriter(fullPath, false); 189 | if (jsonStart.getSource().getMountPoint() == null) { 190 | fileWriter.write("mountpoint=\n"); 191 | } else { 192 | fileWriter.write("mountpoint=" + jsonStart.getSource().getMountPoint() + "\n"); 193 | } 194 | if (jsonStart.getSource().getEndPoint() == null) { 195 | fileWriter.write("endpoint=\n"); 196 | } else { 197 | fileWriter.write("endpoint=" + jsonStart.getSource().getEndPoint() + "\n"); 198 | } 199 | if (jsonStart.getSource().getAccess() == null) { 200 | fileWriter.write("access=\n"); 201 | } else { 202 | fileWriter.write("access=" + jsonStart.getSource().getAccess() + "\n"); 203 | } 204 | if (jsonStart.getSource().getSecret() == null) { 205 | fileWriter.write("secret=\n"); 206 | } else { 207 | fileWriter.write("secret=" + jsonStart.getSource().getSecret() + "\n"); 208 | } 209 | if (jsonStart.getSource().getBucket() == null) { 210 | fileWriter.write("bucket=\n"); 211 | } else { 212 | fileWriter.write("bucket=" + jsonStart.getSource().getBucket() + "\n"); 213 | } 214 | if (jsonStart.getSource().getPrefix() == null) { 215 | fileWriter.write("prefix=\n"); 216 | } else { 217 | fileWriter.write("prefix=" + jsonStart.getSource().getPrefix() + "\n"); 218 | } 219 | if (jsonStart.getSource().getMoveSize() == null) { 220 | fileWriter.write("part_size=\n"); 221 | } else { 222 | fileWriter.write("part_size=" + jsonStart.getSource().getMoveSize() + "\n"); 223 | } 224 | 225 | fileWriter.close(); 226 | } catch (IOException e) { 227 | throw new IOException(e); 228 | } 229 | } 230 | 231 | public void saveTargetConfFile(String fileName) throws IOException { 232 | try { 233 | String fullPath = null; 234 | String path = RestConfig.getInstance().getPath(); 235 | if (path.charAt(path.length() - 1) == '/') { 236 | fullPath = path + fileName; 237 | } else { 238 | fullPath = path + "/" + fileName; 239 | } 240 | 241 | FileWriter fileWriter = new FileWriter(fullPath, false); 242 | if (jsonStart.getTarget().getEndPoint() == null) { 243 | fileWriter.write("endpoint=\n"); 244 | } else { 245 | fileWriter.write("endpoint=" + jsonStart.getTarget().getEndPoint() + "\n"); 246 | } 247 | if (jsonStart.getTarget().getAccess() == null) { 248 | fileWriter.write("access=\n"); 249 | } else { 250 | fileWriter.write("access=" + jsonStart.getTarget().getAccess() + "\n"); 251 | } 252 | if (jsonStart.getTarget().getSecret() == null) { 253 | fileWriter.write("secret=\n"); 254 | } else { 255 | fileWriter.write("secret=" + jsonStart.getTarget().getSecret() + "\n"); 256 | } 257 | if (jsonStart.getTarget().getBucket() == null) { 258 | fileWriter.write("bucket=\n"); 259 | } else { 260 | fileWriter.write("bucket=" + jsonStart.getTarget().getBucket() + "\n"); 261 | } 262 | if (jsonStart.getTarget().getPrefix() == null) { 263 | fileWriter.write("prefix=\n"); 264 | } else { 265 | fileWriter.write("prefix=" + jsonStart.getTarget().getPrefix() + "\n"); 266 | } 267 | 268 | fileWriter.close(); 269 | } catch (IOException e) { 270 | throw new IOException(e); 271 | } 272 | } 273 | 274 | // private void deleteJobIdFile() { 275 | // File file = new File(RestConfig.getInstance().getPath() + "/.jobId"); 276 | // if (file.exists()) { 277 | // file.delete(); 278 | // } 279 | // } 280 | 281 | private String getJobIdFromFile(String uuid) throws IOException { 282 | File file = new File(RestConfig.getInstance().getPath() + "/.jobId" + uuid); 283 | while (!file.exists()) { 284 | try { 285 | Thread.sleep(100); 286 | } catch (InterruptedException e) { 287 | throw new IOException(e); 288 | } 289 | } 290 | BufferedReader br = new BufferedReader(new FileReader(file)); 291 | String jobId = br.readLine(); 292 | file.delete(); 293 | return jobId; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/repository/IfsS3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2NO_ERROR21 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * ifsmover is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.repository; 12 | 13 | import java.util.List; 14 | 15 | import com.amazonaws.AmazonClientException; 16 | import com.amazonaws.AmazonServiceException; 17 | import com.amazonaws.ClientConfiguration; 18 | import com.amazonaws.Protocol; 19 | import com.amazonaws.SdkClientException; 20 | import com.amazonaws.auth.AWSStaticCredentialsProvider; 21 | import com.amazonaws.auth.BasicAWSCredentials; 22 | import com.amazonaws.client.builder.AwsClientBuilder; 23 | import com.amazonaws.services.s3.AmazonS3; 24 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 25 | import com.google.common.base.CharMatcher; 26 | import com.google.common.base.Splitter; 27 | import com.pspace.ifsmover.rest.S3Config; 28 | 29 | import org.slf4j.Logger; 30 | import org.slf4j.LoggerFactory; 31 | 32 | public class IfsS3 implements Repository { 33 | private static final Logger logger = LoggerFactory.getLogger(IfsS3.class); 34 | private boolean isSource; 35 | private S3Config config; 36 | private boolean isAWS; 37 | private boolean isSecure; 38 | private AmazonS3 client; 39 | private String errCode; 40 | private String errMessage; 41 | 42 | private final String HTTPS = "https"; 43 | private final String AWS_S3_V4_SIGNER_TYPE = "AWSS3V4SignerType"; 44 | private final String BUCKET_ALREADY_OWNED_BY_YOU = "BucketAlreadyOwnedByYou"; 45 | private final String BUCKET_ALREADY_EXISTS = "BucketAlreadyExists"; 46 | private final String INVALID_ACCESS_KEY_ID = "InvalidAccessKeyId"; 47 | private final String SIGNATURE_DOES_NOT_MATCH = "SignatureDoesNotMatch"; 48 | 49 | private final int MILLISECONDS = 1000; 50 | private final int TIMEOUT = 300; 51 | private final int RETRY_COUNT = 2; 52 | 53 | private final String LOG_SOURCE_INVALID_ACCESS = "source - The access key is invalid."; 54 | private final String LOG_SOURCE_INVALID_SECRET = "source - The secret key is invalid."; 55 | private final String LOG_TARGET_INVALID_ACCESS = "target - The access key is invalid."; 56 | private final String LOG_TARGET_INVALID_SECRET = "target - The secret key is invalid."; 57 | private final String LOG_SOURCE_ENDPOINT_NULL = "source - endpoint is null"; 58 | private final String LOG_TARGET_ENDPOINT_NULL = "target - endpoint is null"; 59 | private final String LOG_SOURCE_BUCKET_NULL = "source - bucket is null"; 60 | private final String LOG_TARGET_BUCKET_NULL = "target - bucket is null"; 61 | private final String LOG_SOURCE_BUCKET_NOT_EXIST = "source - bucket is not exist"; 62 | private final String LOG_SOURCE_NOT_REGION = "source - unable to find region."; 63 | private final String LOG_TARGET_NOT_REGION = "target - unable to find region."; 64 | private final String LOG_SOURCE_INVALID_ENDPOINT = "source - endpoint is invalid."; 65 | private final String LOG_TARGET_INVALID_ENDPOINT = "target - endpoint is invalid."; 66 | 67 | public IfsS3() {} 68 | 69 | public void setConfig(S3Config config, boolean isSource) { 70 | this.config = config; 71 | this.isSource = isSource; 72 | isAWS = config.isAWS(); 73 | isSecure = isAWS; 74 | } 75 | 76 | @Override 77 | public int check() { 78 | if (config.getEndPoint() == null || config.getEndPoint().isEmpty()) { 79 | if (isSource) { 80 | logger.error(LOG_SOURCE_ENDPOINT_NULL); 81 | errMessage = LOG_SOURCE_ENDPOINT_NULL; 82 | } else { 83 | logger.error(LOG_TARGET_ENDPOINT_NULL); 84 | errMessage = LOG_TARGET_ENDPOINT_NULL; 85 | } 86 | return ENDPOINT_IS_NULL; 87 | } 88 | 89 | if (config.getBucket() == null || config.getBucket().isEmpty()) { 90 | if (isSource) { 91 | logger.error(LOG_SOURCE_BUCKET_NULL); 92 | errMessage = LOG_SOURCE_BUCKET_NULL; 93 | } else { 94 | logger.error(LOG_TARGET_BUCKET_NULL); 95 | errMessage = LOG_TARGET_BUCKET_NULL; 96 | } 97 | return BUCKET_IS_NULL; 98 | } 99 | 100 | if (isAWS) { 101 | isSecure = true; 102 | } else { 103 | if (config.getEndPointProtocol().compareToIgnoreCase(HTTPS) == 0) { 104 | isSecure = true; 105 | } else { 106 | isSecure = false; 107 | } 108 | } 109 | 110 | int result = getClient(); 111 | if (result != NO_ERROR) { 112 | return result; 113 | } 114 | 115 | if(!isValidBucketName(config.getBucket())) { 116 | if (isSource) { 117 | errMessage = "source - bucket name is invalid : " + config.getBucket(); 118 | } else { 119 | errMessage = "target - bucket name is invalid : " + config.getBucket(); 120 | } 121 | return 122 | INVALID_BUCKET; 123 | } 124 | result = existBucket(true, config.getBucket()); 125 | if (result == BUCKET_NO_EXIST) { 126 | if (isSource) { 127 | logger.error(LOG_SOURCE_BUCKET_NOT_EXIST); 128 | errMessage = LOG_SOURCE_BUCKET_NOT_EXIST; 129 | return BUCKET_NO_EXIST; 130 | } else { 131 | result = createBucket(true); 132 | if (result != NO_ERROR) { 133 | return result; 134 | } 135 | } 136 | } else if (result != NO_ERROR) { 137 | return result; 138 | } 139 | 140 | return NO_ERROR; 141 | } 142 | 143 | public int getClient() { 144 | try { 145 | client = createClient(isAWS, isSecure, config.getEndPoint(), config.getAccessKey(), config.getSecretKey()); 146 | } catch (SdkClientException e) { 147 | if (isSource) { 148 | logger.error(LOG_SOURCE_NOT_REGION); 149 | errMessage = LOG_SOURCE_NOT_REGION; 150 | } else { 151 | logger.error(LOG_TARGET_NOT_REGION); 152 | errMessage = LOG_TARGET_NOT_REGION; 153 | } 154 | 155 | return UNABLE_FIND_REGION; 156 | } catch (IllegalArgumentException e) { 157 | if (isSource) { 158 | logger.error(LOG_SOURCE_INVALID_ENDPOINT); 159 | errMessage = LOG_SOURCE_INVALID_ENDPOINT; 160 | } else { 161 | logger.error(LOG_TARGET_INVALID_ENDPOINT); 162 | errMessage = LOG_TARGET_INVALID_ENDPOINT; 163 | } 164 | return INVALID_ENDPOINT; 165 | } 166 | 167 | return NO_ERROR; 168 | } 169 | 170 | private AmazonS3 createClient(boolean isAWS, boolean isSecure, String URL, String AccessKey, String SecretKey) throws SdkClientException, IllegalArgumentException{ 171 | ClientConfiguration config; 172 | 173 | if (isSecure) { 174 | config = new ClientConfiguration().withProtocol(Protocol.HTTPS); 175 | } else { 176 | config = new ClientConfiguration().withProtocol(Protocol.HTTP); 177 | } 178 | 179 | config.setSignerOverride(AWS_S3_V4_SIGNER_TYPE); 180 | config.setMaxErrorRetry(RETRY_COUNT); 181 | config.setConnectionTimeout(TIMEOUT * MILLISECONDS); 182 | config.setSocketTimeout(TIMEOUT * MILLISECONDS); 183 | AmazonS3ClientBuilder clientBuilder = AmazonS3ClientBuilder.standard(); 184 | 185 | clientBuilder.setCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(AccessKey, SecretKey))); 186 | 187 | if (isAWS) { 188 | clientBuilder.setRegion(URL); 189 | } else { 190 | clientBuilder.setEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(URL, "")); 191 | } 192 | 193 | clientBuilder.setClientConfiguration(config); 194 | clientBuilder.setPathStyleAccessEnabled(true); 195 | 196 | return clientBuilder.build(); 197 | } 198 | 199 | private static final CharMatcher VALID_BUCKET_CHAR = 200 | CharMatcher.inRange('a', 'z') 201 | .or(CharMatcher.inRange('0', '9')) 202 | .or(CharMatcher.is('-')) 203 | .or(CharMatcher.is('.')); 204 | 205 | private boolean validateIpAddress(String string) { 206 | List parts = Splitter.on('.').splitToList(string); 207 | if (parts.size() != 4) { 208 | return false; 209 | } 210 | for (String part : parts) { 211 | try { 212 | int num = Integer.parseInt(part); 213 | if (num < 0 || num > 255) { 214 | return false; 215 | } 216 | } catch (NumberFormatException nfe) { 217 | return false; 218 | } 219 | } 220 | return true; 221 | } 222 | 223 | private boolean isValidBucketName(String bucketName) { 224 | if (bucketName == null || 225 | bucketName.length() < 3 || bucketName.length() > 255 || 226 | bucketName.startsWith(".") || bucketName.startsWith("-") || 227 | bucketName.endsWith(".") || bucketName.endsWith("-") || validateIpAddress(bucketName) || 228 | !VALID_BUCKET_CHAR.matchesAllOf(bucketName) || 229 | bucketName.startsWith("xn--") || bucketName.contains("..") || 230 | bucketName.contains(".-") || bucketName.contains("-.")) { 231 | 232 | return false; 233 | } 234 | 235 | return true; 236 | } 237 | 238 | private int existBucket(boolean isCheck, String bucket) { 239 | int result = NO_ERROR; 240 | logger.info("check exists bucket : {}", bucket); 241 | try { 242 | if (client.doesBucketExistV2(bucket)) { 243 | result = NO_ERROR; 244 | } else { 245 | result = BUCKET_NO_EXIST; 246 | } 247 | } catch (AmazonServiceException ase) { 248 | errCode = ase.getErrorCode(); 249 | switch (errCode) { 250 | case INVALID_ACCESS_KEY_ID: 251 | if (isCheck) { 252 | if (isSource) { 253 | logger.error(LOG_SOURCE_INVALID_ACCESS); 254 | errMessage = LOG_SOURCE_INVALID_ACCESS; 255 | } else { 256 | logger.error(LOG_TARGET_INVALID_ACCESS); 257 | errMessage = LOG_TARGET_INVALID_ACCESS; 258 | } 259 | } else { 260 | if (isSource) { 261 | logger.error(LOG_SOURCE_INVALID_ACCESS); 262 | errMessage = LOG_SOURCE_INVALID_ACCESS; 263 | } else { 264 | logger.error(LOG_TARGET_INVALID_ACCESS); 265 | errMessage = LOG_TARGET_INVALID_ACCESS; 266 | } 267 | } 268 | result = INVALID_ACCESS_KEY; 269 | break; 270 | 271 | case SIGNATURE_DOES_NOT_MATCH: 272 | if (isCheck) { 273 | if (isSource) { 274 | logger.error(LOG_SOURCE_INVALID_SECRET); 275 | errMessage = LOG_SOURCE_INVALID_SECRET; 276 | } else { 277 | logger.error(LOG_TARGET_INVALID_SECRET); 278 | errMessage = LOG_TARGET_INVALID_SECRET; 279 | } 280 | } else { 281 | if (isSource) { 282 | logger.error(LOG_SOURCE_INVALID_SECRET); 283 | errMessage = LOG_SOURCE_INVALID_SECRET; 284 | } else { 285 | logger.error(LOG_TARGET_INVALID_SECRET); 286 | errMessage = LOG_TARGET_INVALID_SECRET; 287 | } 288 | } 289 | result = INVALID_SECRET_KEY; 290 | break; 291 | } 292 | } catch (AmazonClientException ace) { 293 | if (isCheck) { 294 | if (isSource) { 295 | logger.error("source - {}", ace.getMessage()); 296 | errMessage = "source - " + ace.getMessage(); 297 | } else { 298 | logger.error("target - {}", ace.getMessage()); 299 | errMessage = "target - " + ace.getMessage(); 300 | } 301 | } 302 | result = AMAZON_CLIENT_EXCEPTION; 303 | } 304 | 305 | return result; 306 | } 307 | 308 | private int createBucket(boolean isCheck) { 309 | logger.info("check create bucket : {}", config.getBucket()); 310 | try { 311 | client.createBucket(config.getBucket()); 312 | if (isCheck) { 313 | client.deleteBucket(config.getBucket()); 314 | } 315 | return NO_ERROR; 316 | } catch (AmazonServiceException ase) { 317 | if (ase.getErrorCode().compareToIgnoreCase(BUCKET_ALREADY_OWNED_BY_YOU) == NO_ERROR) { 318 | return NO_ERROR; 319 | } else if (ase.getErrorCode().compareToIgnoreCase(BUCKET_ALREADY_EXISTS) == NO_ERROR) { 320 | return NO_ERROR; 321 | } 322 | 323 | errCode = ase.getErrorCode(); 324 | switch (errCode) { 325 | case INVALID_ACCESS_KEY_ID: 326 | if (isCheck) { 327 | if (isSource) { 328 | logger.error(LOG_SOURCE_INVALID_ACCESS); 329 | errMessage = LOG_SOURCE_INVALID_ACCESS; 330 | } else { 331 | logger.error(LOG_TARGET_INVALID_ACCESS); 332 | errMessage = LOG_TARGET_INVALID_ACCESS; 333 | } 334 | } else { 335 | if (isSource) { 336 | logger.error(LOG_SOURCE_INVALID_ACCESS); 337 | errMessage = LOG_SOURCE_INVALID_ACCESS; 338 | } else { 339 | logger.error(LOG_TARGET_INVALID_ACCESS); 340 | errMessage = LOG_TARGET_INVALID_ACCESS; 341 | } 342 | } 343 | return INVALID_ACCESS_KEY; 344 | 345 | case SIGNATURE_DOES_NOT_MATCH: 346 | if (isCheck) { 347 | if (isSource) { 348 | logger.error(LOG_SOURCE_INVALID_SECRET); 349 | errMessage = LOG_SOURCE_INVALID_SECRET; 350 | } else { 351 | logger.error(LOG_TARGET_INVALID_SECRET); 352 | errMessage = LOG_TARGET_INVALID_SECRET; 353 | } 354 | } else { 355 | if (isSource) { 356 | logger.error(LOG_SOURCE_INVALID_SECRET); 357 | errMessage = LOG_SOURCE_INVALID_SECRET; 358 | } else { 359 | logger.error(LOG_TARGET_INVALID_SECRET); 360 | errMessage = LOG_TARGET_INVALID_SECRET; 361 | } 362 | } 363 | return INVALID_SECRET_KEY; 364 | } 365 | 366 | logger.error("{}", ase.getMessage()); 367 | errMessage = ase.getMessage(); 368 | return FAILED_CREATE_BUCKET; 369 | } catch (IllegalArgumentException e) { 370 | logger.error(e.getMessage()); 371 | errMessage = e.getMessage(); 372 | return FAILED_CREATE_BUCKET; 373 | } 374 | } 375 | 376 | private boolean createBucket(String bucket) { 377 | try { 378 | client.createBucket(bucket); 379 | return true; 380 | } catch (AmazonServiceException ase) { 381 | if (ase.getErrorCode().compareToIgnoreCase(BUCKET_ALREADY_OWNED_BY_YOU) == NO_ERROR) { 382 | return true; 383 | } else if (ase.getErrorCode().compareToIgnoreCase(BUCKET_ALREADY_EXISTS) == NO_ERROR) { 384 | return true; 385 | } 386 | 387 | logger.error("{} - {}", ase.getErrorCode(), ase.getMessage()); 388 | errMessage = ase.getErrorCode() + " - " + ase.getMessage(); 389 | return false; 390 | } 391 | } 392 | 393 | @Override 394 | public String getErrMessage() { 395 | return errMessage; 396 | } 397 | 398 | @Override 399 | public String getErrCode() { 400 | return errCode; 401 | } 402 | } 403 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/db/Sqlite.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.db; 12 | 13 | import java.sql.Connection; 14 | import java.sql.DriverManager; 15 | import java.sql.PreparedStatement; 16 | import java.sql.ResultSet; 17 | import java.sql.SQLException; 18 | import java.sql.Statement; 19 | import java.util.ArrayList; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import org.slf4j.Logger; 25 | import org.slf4j.LoggerFactory; 26 | import org.sqlite.SQLiteConfig; 27 | 28 | import com.pspace.ifsmover.rest.RestConfig; 29 | 30 | public class Sqlite implements DBManager { 31 | private static final Logger logger = LoggerFactory.getLogger(Sqlite.class); 32 | 33 | private static Connection con; 34 | private static final String JDBC = "org.sqlite.JDBC"; 35 | private static final String DB_FILE_URL = "jdbc:sqlite:"; 36 | private static final String DB_FILE_NAME = "/ifs-mover.db"; 37 | 38 | private static final int CACHE_SIZE = 10000; 39 | private static final int WAIT_TIMEOUT = 20000; 40 | 41 | private static final String CREATE_USER_MATCH_JOB_TABLE = 42 | "CREATE TABLE IF NOT EXISTS 'UserMatchJob' (\n" 43 | + "'match_id' INTEGER NOT NULL,\n" 44 | + "'user_id' TEXT,\n" 45 | + "'job_id' INTEGER NOT NULL,\n" 46 | + "PRIMARY KEY('match_id' AUTOINCREMENT));"; 47 | 48 | private Sqlite() { 49 | } 50 | 51 | public static Sqlite getInstance() { 52 | return LazyHolder.INSTANCE; 53 | } 54 | 55 | private static class LazyHolder { 56 | private static final Sqlite INSTANCE = new Sqlite(); 57 | } 58 | 59 | @Override 60 | public void init(String dbUrl, String dbPort, String dbName, String userName, String passwd, int poolSize) 61 | throws Exception { 62 | // TODO Auto-generated method stub 63 | init(); 64 | createUserMatchJobTable(); 65 | } 66 | 67 | private static void init() { 68 | try { 69 | Class.forName(JDBC); 70 | SQLiteConfig config = new SQLiteConfig(); 71 | config.setCacheSize(CACHE_SIZE); 72 | config.setBusyTimeout(WAIT_TIMEOUT); 73 | config.setTransactionMode(SQLiteConfig.TransactionMode.DEFERRED); 74 | config.setLockingMode(SQLiteConfig.LockingMode.NORMAL); 75 | config.setSynchronous(SQLiteConfig.SynchronousMode.FULL); 76 | config.setJournalMode(SQLiteConfig.JournalMode.WAL); 77 | config.setEncoding(SQLiteConfig.Encoding.UTF_8); 78 | Sqlite.con = DriverManager.getConnection(getDBURL(), config.toProperties()); 79 | } catch (SQLException | ClassNotFoundException e) { 80 | logger.error(e.getMessage()); 81 | } 82 | } 83 | 84 | private static String getDBURL() { 85 | return DB_FILE_URL + RestConfig.getInstance().getPath() + DB_FILE_NAME; 86 | } 87 | 88 | private static Connection getReadConnection() { 89 | Connection con = null; 90 | try { 91 | Class.forName(JDBC); 92 | SQLiteConfig config = new SQLiteConfig(); 93 | config.setReadOnly(true); 94 | con = DriverManager.getConnection(getDBURL(), config.toProperties()); 95 | } catch (SQLException | ClassNotFoundException e) { 96 | logger.error(e.getMessage()); 97 | } 98 | 99 | return con; 100 | } 101 | 102 | public static void open() { 103 | if (Sqlite.con == null) { 104 | try { 105 | Class.forName(JDBC); 106 | Sqlite.con = DriverManager.getConnection(getDBURL()); 107 | init(); 108 | } catch (SQLException | ClassNotFoundException e) { 109 | logger.error(e.getMessage()); 110 | } 111 | } 112 | } 113 | 114 | public static void close() { 115 | if (Sqlite.con != null) { 116 | try { 117 | Sqlite.con.close(); 118 | } catch (SQLException e) { 119 | logger.error(e.getMessage()); 120 | } 121 | Sqlite.con = null; 122 | } 123 | } 124 | 125 | public static Connection getConnection() { 126 | open(); 127 | return Sqlite.con; 128 | } 129 | 130 | public static void createUserMatchJobTable() { 131 | open(); 132 | 133 | try (Statement stmt = con.createStatement()) { 134 | stmt.execute(CREATE_USER_MATCH_JOB_TABLE); 135 | } catch (SQLException e) { 136 | logger.error(e.getMessage()); 137 | } 138 | } 139 | 140 | @Override 141 | public Map getJobInfo(String jobId) { 142 | Connection con = null; 143 | con = getReadConnection(); 144 | 145 | String sql = SQL_GET_JOB_INFO + jobId; 146 | Map info = null; 147 | try (Statement stmt = con.createStatement(); 148 | ResultSet rs = stmt.executeQuery(sql);) { 149 | if (rs.next()) { 150 | info = new HashMap(); 151 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(1)); 152 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(2)); 153 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(3)); 154 | } 155 | } catch (SQLException e) { 156 | logger.error(e.getMessage()); 157 | } 158 | 159 | close(); 160 | 161 | return info; 162 | } 163 | 164 | @Override 165 | public void insertUserMatchJob(String userId, String jobId) { 166 | Connection con = null; 167 | con = getConnection(); 168 | 169 | try (PreparedStatement pstmt = con.prepareStatement(SQL_INSERT_USERMATCHJOB);) { 170 | pstmt.setString(1, userId); 171 | pstmt.setInt(2, Integer.parseInt(jobId)); 172 | pstmt.executeUpdate(); 173 | } catch (SQLException e) { 174 | logger.error(e.getMessage()); 175 | } 176 | 177 | close(); 178 | } 179 | 180 | @Override 181 | public int getUserMatchJob(String userId, String jobId) { 182 | Connection con = null; 183 | con = getReadConnection(); 184 | 185 | int matchId = 0; 186 | final String sql = SQL_GET_USERMATCHJOB + userId + SQL_GET_USERMATCHJOB_JOBID + jobId + "'"; 187 | try (Statement stmt = con.createStatement(); 188 | ResultSet rs = stmt.executeQuery(sql);) { 189 | if (rs.next()) { 190 | matchId = rs.getInt(1); 191 | } 192 | } catch (SQLException e) { 193 | logger.error(e.getMessage()); 194 | } 195 | 196 | close(); 197 | 198 | return matchId; 199 | } 200 | 201 | @Override 202 | public void deleteUserMatchJob(long matchId) { 203 | Connection con = null; 204 | con = getConnection(); 205 | 206 | String sql = SQL_DELETE_USERMATCHJOB + matchId; 207 | try (Statement stmt = con.createStatement()) { 208 | stmt.executeUpdate(sql); 209 | } catch (SQLException e) { 210 | logger.error(e.getMessage()); 211 | } 212 | 213 | close(); 214 | } 215 | 216 | @Override 217 | public List> status(String userId) { 218 | Connection con = null; 219 | con = getReadConnection(); 220 | 221 | List> list = new ArrayList>(); 222 | HashMap info = null; 223 | 224 | if (con == null) { 225 | return list; 226 | } 227 | 228 | try (Statement stmt = con.createStatement(); 229 | ResultSet rs = stmt.executeQuery(SQL_SELECT_JOB_STATUS + userId + "' ORDER BY A.job_id");) { 230 | while (rs.next()) { 231 | info = new HashMap(); 232 | 233 | info.put(JOB_TABLE_COLUMN_JOB_ID, rs.getInt(1)); 234 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(2)); 235 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(3)); 236 | info.put(JOB_TABLE_COLUMN_SOURCE_POINT, rs.getString(4)); 237 | info.put(JOB_TABLE_COLUMN_TARGET_POINT, rs.getString(5)); 238 | info.put(JOB_TABLE_COLUMN_OBJECTS_COUNT, rs.getLong(6)); 239 | info.put(JOB_TABLE_COLUMN_OBJECTS_SIZE, rs.getLong(7)); 240 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT, rs.getLong(8)); 241 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE, rs.getLong(9)); 242 | info.put(JOB_TABLE_COLUMN_FAILED_COUNT, rs.getLong(10)); 243 | info.put(JOB_TABLE_COLUMN_FAILED_SIZE, rs.getLong(11)); 244 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT, rs.getLong(12)); 245 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE, rs.getLong(13)); 246 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT, rs.getLong(14)); 247 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE, rs.getLong(15)); 248 | info.put(JOB_TABLE_COLUMN_START, rs.getString(16)); 249 | info.put(JOB_TABLE_COLUMN_END, rs.getString(17)); 250 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(18)); 251 | 252 | list.add(info); 253 | } 254 | } catch (SQLException e) { 255 | logger.error(e.getMessage()); 256 | } 257 | 258 | close(); 259 | 260 | return list; 261 | } 262 | 263 | @Override 264 | public List> status(String userId, String jobId) { 265 | Connection con = null; 266 | con = getReadConnection(); 267 | 268 | List> list = new ArrayList>(); 269 | HashMap info = null; 270 | 271 | if (con == null) { 272 | return list; 273 | } 274 | 275 | String sql = SQL_SELECT_JOB_STATUS + userId + "' and A.job_id = ?"; 276 | try (PreparedStatement pstmt = con.prepareStatement(sql)) { 277 | pstmt.setString(1, jobId); 278 | ResultSet rs = pstmt.executeQuery(); 279 | while (rs.next()) { 280 | info = new HashMap(); 281 | 282 | info.put(JOB_TABLE_COLUMN_JOB_ID, rs.getInt(1)); 283 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(2)); 284 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(3)); 285 | info.put(JOB_TABLE_COLUMN_SOURCE_POINT, rs.getString(4)); 286 | info.put(JOB_TABLE_COLUMN_TARGET_POINT, rs.getString(5)); 287 | info.put(JOB_TABLE_COLUMN_OBJECTS_COUNT, rs.getLong(6)); 288 | info.put(JOB_TABLE_COLUMN_OBJECTS_SIZE, rs.getLong(7)); 289 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT, rs.getLong(8)); 290 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE, rs.getLong(9)); 291 | info.put(JOB_TABLE_COLUMN_FAILED_COUNT, rs.getLong(10)); 292 | info.put(JOB_TABLE_COLUMN_FAILED_SIZE, rs.getLong(11)); 293 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT, rs.getLong(12)); 294 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE, rs.getLong(13)); 295 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT, rs.getLong(14)); 296 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE, rs.getLong(15)); 297 | info.put(JOB_TABLE_COLUMN_START, rs.getString(16)); 298 | info.put(JOB_TABLE_COLUMN_END, rs.getString(17)); 299 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(18)); 300 | 301 | list.add(info); 302 | } 303 | } catch (SQLException e) { 304 | logger.error(e.getMessage()); 305 | } 306 | 307 | close(); 308 | 309 | return list; 310 | } 311 | 312 | @Override 313 | public List> status(String userId, String srcBucket, String dstBucket) { 314 | Connection con = null; 315 | con = getReadConnection(); 316 | 317 | List> list = new ArrayList>(); 318 | HashMap info = null; 319 | 320 | if (con == null) { 321 | return list; 322 | } 323 | 324 | String sql = SQL_SELECT_JOB_STATUS + userId + "' and A.source_point LIKE ? and A.target_point LIKE ?"; 325 | try (PreparedStatement pstmt = con.prepareStatement(sql)) { 326 | pstmt.setString(1, srcBucket); 327 | pstmt.setString(2, dstBucket); 328 | ResultSet rs = pstmt.executeQuery(); 329 | while (rs.next()) { 330 | info = new HashMap(); 331 | 332 | info.put(JOB_TABLE_COLUMN_JOB_ID, rs.getInt(1)); 333 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(2)); 334 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(3)); 335 | info.put(JOB_TABLE_COLUMN_SOURCE_POINT, rs.getString(4)); 336 | info.put(JOB_TABLE_COLUMN_TARGET_POINT, rs.getString(5)); 337 | info.put(JOB_TABLE_COLUMN_OBJECTS_COUNT, rs.getLong(6)); 338 | info.put(JOB_TABLE_COLUMN_OBJECTS_SIZE, rs.getLong(7)); 339 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT, rs.getLong(8)); 340 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE, rs.getLong(9)); 341 | info.put(JOB_TABLE_COLUMN_FAILED_COUNT, rs.getLong(10)); 342 | info.put(JOB_TABLE_COLUMN_FAILED_SIZE, rs.getLong(11)); 343 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT, rs.getLong(12)); 344 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE, rs.getLong(13)); 345 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT, rs.getLong(14)); 346 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE, rs.getLong(15)); 347 | info.put(JOB_TABLE_COLUMN_START, rs.getString(16)); 348 | info.put(JOB_TABLE_COLUMN_END, rs.getString(17)); 349 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(18)); 350 | 351 | list.add(info); 352 | } 353 | } catch (SQLException e) { 354 | logger.error(e.getMessage()); 355 | } 356 | 357 | close(); 358 | 359 | return list; 360 | } 361 | 362 | @Override 363 | public List> statusSrcBucket(String userId, String srcBucket) { 364 | Connection con = null; 365 | con = getReadConnection(); 366 | 367 | List> list = new ArrayList>(); 368 | HashMap info = null; 369 | 370 | if (con == null) { 371 | return list; 372 | } 373 | 374 | String sql = SQL_SELECT_JOB_STATUS + userId + "' and A.source_point LIKE ?"; 375 | try (PreparedStatement pstmt = con.prepareStatement(sql)) { 376 | pstmt.setString(1, srcBucket); 377 | ResultSet rs = pstmt.executeQuery(); 378 | while (rs.next()) { 379 | info = new HashMap(); 380 | 381 | info.put(JOB_TABLE_COLUMN_JOB_ID, rs.getInt(1)); 382 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(2)); 383 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(3)); 384 | info.put(JOB_TABLE_COLUMN_SOURCE_POINT, rs.getString(4)); 385 | info.put(JOB_TABLE_COLUMN_TARGET_POINT, rs.getString(5)); 386 | info.put(JOB_TABLE_COLUMN_OBJECTS_COUNT, rs.getLong(6)); 387 | info.put(JOB_TABLE_COLUMN_OBJECTS_SIZE, rs.getLong(7)); 388 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT, rs.getLong(8)); 389 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE, rs.getLong(9)); 390 | info.put(JOB_TABLE_COLUMN_FAILED_COUNT, rs.getLong(10)); 391 | info.put(JOB_TABLE_COLUMN_FAILED_SIZE, rs.getLong(11)); 392 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT, rs.getLong(12)); 393 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE, rs.getLong(13)); 394 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT, rs.getLong(14)); 395 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE, rs.getLong(15)); 396 | info.put(JOB_TABLE_COLUMN_START, rs.getString(16)); 397 | info.put(JOB_TABLE_COLUMN_END, rs.getString(17)); 398 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(18)); 399 | 400 | list.add(info); 401 | } 402 | } catch (SQLException e) { 403 | logger.error(e.getMessage()); 404 | } 405 | 406 | close(); 407 | 408 | return list; 409 | } 410 | 411 | @Override 412 | public List> statusDstBucket(String userId, String dstBucket) { 413 | Connection con = null; 414 | con = getReadConnection(); 415 | 416 | List> list = new ArrayList>(); 417 | HashMap info = null; 418 | 419 | if (con == null) { 420 | return list; 421 | } 422 | 423 | String sql = SQL_SELECT_JOB_STATUS + userId + "' and A.target_point LIKE ?"; 424 | try (PreparedStatement pstmt = con.prepareStatement(sql)) { 425 | pstmt.setString(1, dstBucket); 426 | ResultSet rs = pstmt.executeQuery(); 427 | while (rs.next()) { 428 | info = new HashMap(); 429 | 430 | info.put(JOB_TABLE_COLUMN_JOB_ID, rs.getInt(1)); 431 | info.put(JOB_TABLE_COLUMN_JOB_STATE, rs.getInt(2)); 432 | info.put(JOB_TABLE_COLUMN_JOB_TYPE, rs.getString(3)); 433 | info.put(JOB_TABLE_COLUMN_SOURCE_POINT, rs.getString(4)); 434 | info.put(JOB_TABLE_COLUMN_TARGET_POINT, rs.getString(5)); 435 | info.put(JOB_TABLE_COLUMN_OBJECTS_COUNT, rs.getLong(6)); 436 | info.put(JOB_TABLE_COLUMN_OBJECTS_SIZE, rs.getLong(7)); 437 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT, rs.getLong(8)); 438 | info.put(JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE, rs.getLong(9)); 439 | info.put(JOB_TABLE_COLUMN_FAILED_COUNT, rs.getLong(10)); 440 | info.put(JOB_TABLE_COLUMN_FAILED_SIZE, rs.getLong(11)); 441 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT, rs.getLong(12)); 442 | info.put(JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE, rs.getLong(13)); 443 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT, rs.getLong(14)); 444 | info.put(JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE, rs.getLong(15)); 445 | info.put(JOB_TABLE_COLUMN_START, rs.getString(16)); 446 | info.put(JOB_TABLE_COLUMN_END, rs.getString(17)); 447 | info.put(JOB_TABLE_COLUMN_ERROR_DESC, rs.getString(18)); 448 | 449 | list.add(info); 450 | } 451 | } catch (SQLException e) { 452 | logger.error(e.getMessage()); 453 | } 454 | 455 | close(); 456 | 457 | return list; 458 | } 459 | 460 | 461 | } 462 | -------------------------------------------------------------------------------- /src/com/pspace/ifsmover/rest/api/Status.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021 PSPACE, inc. KSAN Development Team ksan@pspace.co.kr 3 | * KSAN is a suite of free software: you can redistribute it and/or modify it under the terms of 4 | * the GNU General Public License as published by the Free Software Foundation, either version 5 | * 3 of the License. See LICENSE for details 6 | * 7 | * 본 프로그램 및 관련 소스코드, 문서 등 모든 자료는 있는 그대로 제공이 됩니다. 8 | * KSAN 프로젝트의 개발자 및 개발사는 이 프로그램을 사용한 결과에 따른 어떠한 책임도 지지 않습니다. 9 | * KSAN 개발팀은 사전 공지, 허락, 동의 없이 KSAN 개발에 관련된 모든 결과물에 대한 LICENSE 방식을 변경 할 권리가 있습니다. 10 | */ 11 | package com.pspace.ifsmover.rest.api; 12 | 13 | import java.io.IOException; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | import com.google.common.base.Strings; 19 | import com.pspace.ifsmover.rest.PrintStack; 20 | import com.pspace.ifsmover.rest.Utils; 21 | import com.pspace.ifsmover.rest.data.DataStatus; 22 | import com.pspace.ifsmover.rest.db.DBManager; 23 | import com.pspace.ifsmover.rest.db.Sqlite; 24 | import com.pspace.ifsmover.rest.exception.ErrCode; 25 | import com.pspace.ifsmover.rest.exception.RestException; 26 | 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | import jakarta.servlet.http.HttpServletRequest; 31 | import jakarta.servlet.http.HttpServletResponse; 32 | 33 | public class Status extends MoverRequest { 34 | private static final Logger logger = LoggerFactory.getLogger(Status.class); 35 | private String userId = null; 36 | private String returnJson = null; 37 | 38 | private static final long UNIT_G = (1024 * 1024 * 1024); 39 | private static final long UNIT_M = (1024 * 1024); 40 | private static final long UNIT_K = 1024; 41 | 42 | public Status(HttpServletRequest request, HttpServletResponse response, String userId) { 43 | super(request, response); 44 | this.userId = userId; 45 | } 46 | 47 | @Override 48 | public void process() throws RestException { 49 | // TODO Auto-generated method stub 50 | logger.info("Status ..."); 51 | logger.info("userId : {}", userId); 52 | 53 | DataStatus dataStatus; 54 | try { 55 | dataStatus = new DataStatus(request); 56 | dataStatus.extract(); 57 | } catch (Exception e) { 58 | throw new RestException(ErrCode.BAD_REQUEST); 59 | } 60 | 61 | String jobId = dataStatus.getJobId(); 62 | String srcBucket = dataStatus.getSrcBucket(); 63 | String dstBucket = dataStatus.getDstBucket(); 64 | logger.info("jobId : {}, srcBucket : {}, dstBucket : {}", jobId, srcBucket, dstBucket); 65 | status(userId, jobId, srcBucket, dstBucket); 66 | 67 | try { 68 | response.getOutputStream().write(returnJson.getBytes()); 69 | } catch (IOException e) { 70 | PrintStack.logging(logger, e); 71 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 72 | } 73 | response.setStatus(HttpServletResponse.SC_OK); 74 | } 75 | 76 | private void status(String userId, String markedJobId, String srcBucket, String dstBucket) throws RestException { 77 | String jobId; 78 | int jobState; 79 | String jobType; 80 | String sourcePoint; 81 | String targetPoint; 82 | long objectsCount; 83 | long objectsSize; 84 | long movedObjectsCount; 85 | long movedObjectsSize; 86 | long failedCount; 87 | long failedSize; 88 | long skipObjectsCount; 89 | long skipObjectsSize; 90 | long deleteObjectCount; 91 | long deleteObjectSize; 92 | String startTime; 93 | String endTime; 94 | String errorDesc; 95 | 96 | double unitSize = 0.0; 97 | double unitMove = 0.0; 98 | double unitFailed = 0.0; 99 | double unitSkip = 0.0; 100 | double unitDelete = 0.0; 101 | double percent = 0.0; 102 | 103 | int jobCount = 0; 104 | try { 105 | List> list; 106 | if (!Strings.isNullOrEmpty(markedJobId)) { 107 | list = Utils.getDBInstance().status(userId, markedJobId); 108 | } else if (!Strings.isNullOrEmpty(srcBucket) && !Strings.isNullOrEmpty(dstBucket)) { 109 | list = Utils.getDBInstance().status(userId, srcBucket, dstBucket); 110 | } else if (!Strings.isNullOrEmpty(srcBucket)) { 111 | list = Utils.getDBInstance().statusSrcBucket(userId, srcBucket); 112 | } else if (!Strings.isNullOrEmpty(dstBucket)) { 113 | list = Utils.getDBInstance().statusDstBucket(userId, dstBucket); 114 | } else { 115 | list = Utils.getDBInstance().status(userId); 116 | } 117 | 118 | if (list == null || list.size() == 0) { 119 | logger.info("No Jobs were created."); 120 | returnJson = "{\"Result\":\"failed\", \"Message\":\"No Jobs were created.\", \"Items\":[]}"; 121 | } else { 122 | returnJson = "{\"Result\":\"success\", \"Message\":null, \"Items\":["; 123 | logger.info("status list size : {}", list.size()); 124 | for (Map info : list) { 125 | 126 | jobId = String.valueOf((int)info.get(DBManager.JOB_TABLE_COLUMN_JOB_ID)); 127 | jobState = (int) info.get(DBManager.JOB_TABLE_COLUMN_JOB_STATE); 128 | jobType = (String) info.get(DBManager.JOB_TABLE_COLUMN_JOB_TYPE); 129 | sourcePoint = (String) info.get(DBManager.JOB_TABLE_COLUMN_SOURCE_POINT); 130 | targetPoint = (String) info.get(DBManager.JOB_TABLE_COLUMN_TARGET_POINT); 131 | objectsCount = (long) info.get(DBManager.JOB_TABLE_COLUMN_OBJECTS_COUNT); 132 | objectsSize = (long) info.get(DBManager.JOB_TABLE_COLUMN_OBJECTS_SIZE); 133 | movedObjectsCount = (long) info.get(DBManager.JOB_TABLE_COLUMN_MOVED_OBJECTS_COUNT); 134 | movedObjectsSize = (long) info.get(DBManager.JOB_TABLE_COLUMN_MOVED_OBJECTS_SIZE); 135 | failedCount = (long) info.get(DBManager.JOB_TABLE_COLUMN_FAILED_COUNT); 136 | failedSize = (long) info.get(DBManager.JOB_TABLE_COLUMN_FAILED_SIZE); 137 | skipObjectsCount = (long) info.get(DBManager.JOB_TABLE_COLUMN_SKIP_OBJECTS_COUNT); 138 | skipObjectsSize = (long) info.get(DBManager.JOB_TABLE_COLUMN_SKIP_OBJECTS_SIZE); 139 | deleteObjectCount = (long) info.get(DBManager.JOB_TABLE_COLUMN_DELETE_OBJECT_COUNT); 140 | deleteObjectSize = (long) info.get(DBManager.JOB_TABLE_COLUMN_DELETE_OBJECT_SIZE); 141 | startTime = (String) info.get(DBManager.JOB_TABLE_COLUMN_START); 142 | endTime = (String) info.get(DBManager.JOB_TABLE_COLUMN_END); 143 | errorDesc = (String) info.get(DBManager.JOB_TABLE_COLUMN_ERROR_DESC); 144 | 145 | if (jobState == DBManager.JOB_STATE_REMOVE) { 146 | logger.info("JobId : {} -- removed job."); 147 | continue; 148 | } 149 | 150 | jobCount++; 151 | 152 | returnJson += "{\"JobId\":" + info.get(DBManager.JOB_TABLE_COLUMN_JOB_ID) + ","; 153 | 154 | switch (jobState) { 155 | case DBManager.JOB_STATE_INIT: 156 | returnJson += "\"Status\":\"INIT\","; 157 | break; 158 | 159 | case DBManager.JOB_STATE_MOVE: 160 | returnJson += "\"Status\":\"MOVE\","; 161 | break; 162 | 163 | case DBManager.JOB_STATE_COMPLETE: 164 | returnJson += "\"Status\":\"COMPLETE\","; 165 | break; 166 | 167 | case DBManager.JOB_STATE_STOP: 168 | returnJson += "\"Status\":\"STOP\","; 169 | break; 170 | 171 | case DBManager.JOB_STATE_RERUN_INIT: 172 | returnJson += "\"Status\":\"RERUN INIT\","; 173 | break; 174 | 175 | case DBManager.JOB_STATE_RERUN_MOVE: 176 | returnJson += "\"Status\":\"RERUN MOVE\","; 177 | break; 178 | 179 | case DBManager.JOB_STATE_ERROR: 180 | returnJson += "\"Status\":\"ERROR\","; 181 | break; 182 | 183 | default: 184 | logger.error("Undefined state : {}", jobState); 185 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 186 | } 187 | 188 | if (jobState == DBManager.JOB_STATE_ERROR) { 189 | setRerunJson(sourcePoint, targetPoint, startTime, endTime, errorDesc, 0, null, 0, null, 0, null, 0, null, 0, null, null); 190 | logger.info("jobId = {}", jobId); 191 | logger.info("job state = {}", jobState); 192 | logger.info("error desc = {}", errorDesc); 193 | continue; 194 | } 195 | 196 | if (jobState == DBManager.JOB_STATE_INIT) { 197 | String strObjectSize = null; 198 | unitSize = (double)objectsSize / UNIT_G; 199 | 200 | if (unitSize > 1.0) { 201 | strObjectSize = String.format("%,.2fG", unitSize); 202 | } else { 203 | unitSize = (double)objectsSize / UNIT_M; 204 | if (unitSize > 1.0) { 205 | strObjectSize = String.format("%,.2fM", unitSize); 206 | } else { 207 | unitSize = (double)objectsSize / UNIT_K; 208 | if (unitSize > 1.0) { 209 | strObjectSize = String.format("%,.2fK", unitSize); 210 | } else { 211 | strObjectSize = String.format("%,d", objectsSize); 212 | } 213 | } 214 | } 215 | setRerunJson(sourcePoint, targetPoint, startTime, endTime, errorDesc, objectsCount, strObjectSize, 0, null, 0, null, 0, null, 0, null, null); 216 | } else if (jobState == DBManager.JOB_STATE_RERUN_INIT) { 217 | String strObjectSize = null; 218 | String strSkipSize = null; 219 | String strFailSize = null; 220 | unitSize = (double)objectsSize / UNIT_G; 221 | 222 | if (unitSize > 1.0) { 223 | strObjectSize = String.format("%,.2fG", unitSize); 224 | } else { 225 | unitSize = (double)objectsSize / UNIT_M; 226 | if (unitSize > 1.0) { 227 | strObjectSize = String.format("%,.2fM", unitSize); 228 | } else { 229 | unitSize = (double)objectsSize / UNIT_K; 230 | if (unitSize > 1.0) { 231 | strObjectSize = String.format("%,.2fK", unitSize); 232 | } else { 233 | strObjectSize = String.format("%,d", objectsSize); 234 | } 235 | } 236 | } 237 | 238 | if (skipObjectsCount > 0) { 239 | unitSkip = (double)skipObjectsSize / UNIT_G; 240 | 241 | if (unitSkip > 1.0) { 242 | strSkipSize = String.format("%,.2fG", unitSkip); 243 | } else { 244 | unitSkip = (double)skipObjectsSize / UNIT_M; 245 | if (unitSkip > 1.0) { 246 | strSkipSize = String.format("%,.2fM", unitSkip); 247 | } else { 248 | unitSkip = (double)skipObjectsSize / UNIT_K; 249 | if (unitSkip > 1.0) { 250 | strSkipSize = String.format("%,.2fK", unitSkip); 251 | } else { 252 | strSkipSize = String.format("%,d", skipObjectsSize); 253 | } 254 | } 255 | } 256 | } 257 | 258 | if (failedCount > 0) { 259 | unitFailed = (double)failedSize / UNIT_G; 260 | if (unitFailed > 1.0) { 261 | strFailSize = String.format("%,.2fG", unitFailed); 262 | } else { 263 | unitFailed = (double)failedSize / UNIT_M; 264 | if (unitFailed > 1.0) { 265 | strFailSize = String.format("%,.2fM", unitFailed); 266 | } else { 267 | unitFailed = (double)failedSize / UNIT_K; 268 | if (unitFailed > 1.0) { 269 | strFailSize = String.format("%,.2fK", unitFailed); 270 | } else { 271 | strSkipSize = String.format("%,d", failedSize); 272 | } 273 | } 274 | } 275 | } 276 | setRerunJson(sourcePoint, targetPoint, startTime, endTime, errorDesc, objectsCount, strObjectSize, 0, null, skipObjectsCount, strSkipSize, failedCount, strFailSize, 0, null, null); 277 | } else { 278 | String strObjectSize = null; 279 | String strMoveSize = null; 280 | String strSkipSize = null; 281 | String strFailSize = null; 282 | String strDeleteSize = null; 283 | String strPercent = null; 284 | 285 | if (objectsCount == 0) { 286 | percent = 0.0; 287 | } else { 288 | percent = (((double)skipObjectsSize + (double)movedObjectsSize + (double)failedSize) / (double) objectsSize) * 100; 289 | strPercent = String.format("%.2f", percent); 290 | } 291 | 292 | unitSize = (double)objectsSize / UNIT_G; 293 | 294 | if (unitSize > 1.0) { 295 | strObjectSize = String.format("%,.2fG", unitSize); 296 | unitMove = (double)movedObjectsSize / UNIT_G; 297 | if (unitMove > 1.0) { 298 | strMoveSize = String.format("%,.2fG", unitMove); 299 | } else { 300 | unitMove = (double) movedObjectsSize / UNIT_M; 301 | if (unitMove > 1.0) { 302 | strMoveSize = String.format("%,.2fM", unitMove); 303 | } else { 304 | unitMove = (double) movedObjectsSize / UNIT_K; 305 | if (unitMove > 1.0) { 306 | strMoveSize = String.format("%,.2fK", unitMove); 307 | } else { 308 | strMoveSize = String.format("%,d", movedObjectsSize); 309 | } 310 | } 311 | } 312 | } else { 313 | unitSize = (double)objectsSize / UNIT_M; 314 | if (unitSize > 1.0) { 315 | strObjectSize = String.format("%,.2fM", unitSize); 316 | unitMove = (double)movedObjectsSize / UNIT_M; 317 | if (unitMove > 1.0) { 318 | strMoveSize = String.format("%,.2fM", unitMove); 319 | } else { 320 | unitMove = (double)movedObjectsSize / UNIT_K; 321 | if (unitMove > 1.0) { 322 | strMoveSize = String.format("%,.2fK", unitMove); 323 | } else { 324 | strMoveSize = String.format("%,d", movedObjectsSize); 325 | } 326 | } 327 | } else { 328 | unitSize = (double)objectsSize / UNIT_K; 329 | if (unitSize > 1.0) { 330 | strObjectSize = String.format("%,.2fK", unitSize); 331 | unitMove = (double)movedObjectsSize / UNIT_K; 332 | if (unitMove > 1.0) { 333 | strMoveSize = String.format("%,.2fK", unitMove); 334 | } else { 335 | strMoveSize = String.format("%,d", movedObjectsSize); 336 | } 337 | } else { 338 | strObjectSize = String.format("%,d", objectsSize); 339 | strMoveSize = String.format("%,d", movedObjectsSize); 340 | } 341 | } 342 | } 343 | 344 | if (skipObjectsCount > 0) { 345 | unitSkip = (double)skipObjectsSize / UNIT_G; 346 | if (unitSkip > 1.0) { 347 | strSkipSize = String.format("%,.2fG", unitSkip); 348 | } else { 349 | unitSkip = (double)skipObjectsSize / UNIT_M; 350 | if (unitSkip > 1.0) { 351 | strSkipSize = String.format("%,.2fM", unitSkip); 352 | } else { 353 | unitSkip = (double)skipObjectsSize / UNIT_K; 354 | if (unitSkip > 1.0) { 355 | strSkipSize = String.format("%,.2fK", unitSkip); 356 | } else { 357 | strSkipSize = String.format("%,d", skipObjectsSize); 358 | } 359 | } 360 | } 361 | } 362 | 363 | if (failedCount > 0) { 364 | unitFailed = (double)failedSize / UNIT_G; 365 | if (unitFailed > 1.0) { 366 | strFailSize = String.format("%,.2fG", unitFailed); 367 | } else { 368 | unitFailed = (double)failedSize / UNIT_M; 369 | if (unitFailed > 1.0) { 370 | strFailSize = String.format("%,.2fM", unitFailed); 371 | } else { 372 | unitFailed = (double)failedSize / UNIT_K; 373 | if (unitFailed > 1.0) { 374 | strFailSize = String.format("%,.2fK", unitFailed); 375 | } else { 376 | strFailSize = String.format("%,d", failedSize); 377 | } 378 | } 379 | } 380 | } 381 | 382 | if (deleteObjectCount > 0) { 383 | unitDelete = (double)deleteObjectSize / UNIT_G; 384 | if (unitDelete > 1.0) { 385 | strDeleteSize = String.format("%,.2fG", unitDelete); 386 | } else { 387 | unitDelete = (double)deleteObjectSize / UNIT_M; 388 | if (unitDelete > 1.0) { 389 | strDeleteSize = String.format("%,.2fM", unitDelete); 390 | } else { 391 | unitDelete = (double)deleteObjectSize / UNIT_K; 392 | if (unitDelete > 1.0) { 393 | strDeleteSize = String.format("%,.2fK", unitDelete); 394 | } else { 395 | strDeleteSize = String.format("%,d", deleteObjectSize); 396 | } 397 | } 398 | } 399 | } 400 | setRerunJson(sourcePoint, targetPoint, startTime, endTime, errorDesc, objectsCount, strObjectSize, movedObjectsCount, strMoveSize, skipObjectsCount, strSkipSize, failedCount, strFailSize, deleteObjectCount, strDeleteSize, strPercent); 401 | } 402 | 403 | logger.info("jobId = {}", jobId); 404 | 405 | if (jobState == DBManager.JOB_STATE_INIT) { 406 | logger.info("job state = INIT"); 407 | } else if (jobState == DBManager.JOB_STATE_MOVE) { 408 | logger.info("job state = MOVE"); 409 | } else if (jobState == DBManager.JOB_STATE_COMPLETE) { 410 | logger.info("job state = COMPLETE"); 411 | } else if (jobState == DBManager.JOB_STATE_STOP) { 412 | logger.info("job state = STOP"); 413 | } else if (jobState == DBManager.JOB_STATE_RERUN_INIT) { 414 | logger.info("job state = RERUN INIT"); 415 | } else if (jobState == DBManager.JOB_STATE_RERUN_MOVE) { 416 | logger.info("job state = RERUN MOVE"); 417 | } 418 | logger.info("job type = {}", jobType); 419 | logger.info("source = {}", sourcePoint); 420 | logger.info("target = {}", targetPoint); 421 | logger.info("objects count = {}", objectsCount); 422 | logger.info("objects size = {}", objectsSize); 423 | logger.info("moved objects count = {}", movedObjectsCount); 424 | logger.info("moved objects size = {}", movedObjectsSize); 425 | logger.info("failed count = {}", failedCount); 426 | logger.info("failed size = {}", failedSize); 427 | logger.info("skip objects count = {}", skipObjectsCount); 428 | logger.info("skip objects size = {}", skipObjectsSize); 429 | logger.info("start time = {}", startTime); 430 | logger.info("end time = {}", endTime); 431 | logger.info("error desc = {}", errorDesc); 432 | } 433 | returnJson += "]}"; 434 | 435 | if (jobCount == 0) { 436 | logger.info("No Jobs were created."); 437 | returnJson = "{\"Result\":\"failed\", \"Message\":\"No Jobs were created.\", \"Items\":[]}"; 438 | } 439 | } 440 | } catch (Exception e) { 441 | PrintStack.logging(logger, e); 442 | throw new RestException(ErrCode.INTERNAL_SERVER_ERROR); 443 | } 444 | } 445 | 446 | private void setRerunJson(String sourcePoint, 447 | String targetPoint, 448 | String startTime, 449 | String endTime, 450 | String errorDesc, 451 | long objectCount, 452 | String objectSize, 453 | long movedCount, 454 | String movedSize, 455 | long skippedCount, 456 | String skippedSize, 457 | long failedCount, 458 | String failedSize, 459 | long deleteObjectCount, 460 | String deleteSize, 461 | String progress) { 462 | returnJson += "\"Source\":\"" + sourcePoint + "\", \"Target\":\"" + targetPoint + "\","; 463 | if (!Strings.isNullOrEmpty(startTime)) { 464 | returnJson += "\"StartTime\":\"" + startTime + "\","; 465 | } else { 466 | returnJson += "\"StartTime\":null,"; 467 | } 468 | if (!Strings.isNullOrEmpty(endTime)) { 469 | returnJson += "\"EndTime\":\"" + endTime + "\","; 470 | } else { 471 | returnJson += "\"EndTime\":null,"; 472 | } 473 | if (!Strings.isNullOrEmpty(errorDesc)) { 474 | returnJson += "\"ErrorDesc\":\"" + errorDesc + "\","; 475 | } else { 476 | returnJson += "\"ErrorDesc\":null,"; 477 | } 478 | if (objectCount > 0) { 479 | returnJson += "\"TotalCount\":" + objectCount + ", \"TotalSize\":\"" + objectSize + "\","; 480 | } else { 481 | returnJson += "\"TotalCount\":0, \"TotalSize\":null,"; 482 | } 483 | if (movedCount > 0) { 484 | returnJson += "\"MovedCount\":" + movedCount + ", \"MovedSize\":\"" + movedSize + "\","; 485 | } else { 486 | returnJson += "\"MovedCount\":0, \"MovedSize\":null,"; 487 | } 488 | if (skippedCount > 0) { 489 | returnJson += "\"SkippedCount\":" + skippedCount + ", \"SkippedSize\":\"" + skippedSize + "\","; 490 | } else { 491 | returnJson += "\"SkippedCount\":0, \"SkippedSize\":null,"; 492 | } 493 | if (failedCount > 0) { 494 | returnJson += "\"FailedCount\":" + failedCount + ", \"FailedSize\":\"" + failedSize + "\","; 495 | } else { 496 | returnJson += "\"FailedCount\":0, \"FailedSize\":null,"; 497 | } 498 | if (deleteObjectCount > 0) { 499 | returnJson += "\"DeletedCount\":" + deleteObjectCount + ", \"DeletedSize\":\"" + deleteSize + "\","; 500 | } else { 501 | returnJson += "\"DeletedCount\":0, \"DeletedSize\":null,"; 502 | } 503 | if (!Strings.isNullOrEmpty(progress)) { 504 | returnJson += "\"Progress\":\"" + progress + "\"},"; 505 | } else { 506 | returnJson += "\"Progress\":null},"; 507 | } 508 | } 509 | } 510 | --------------------------------------------------------------------------------