diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 4580c18..3bd4a52 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -13,4 +13,9 @@
+ * Description: Aliyun OSS file operation helper + *
+ * Revision log: + * 2017-05-10: created by strawmanbobi + */ +public class OSSHelper { + + public static String BUCKET_NAME = "irext-debug"; + + private OSSClient mOSSClient; + + public OSSHelper() { + String END_POINT = "oss-cn-hangzhou.aliyuncs.com"; + String ACCESS_KEY = "T82nbipHSESmHzd8"; + String ACCESS_SECRET = "SOweQ8UVwCwPr2NC8EC89EOeKJc5Um"; + + mOSSClient = new OSSClient(END_POINT, ACCESS_KEY, ACCESS_SECRET); + } + + public boolean createBucket(String bucketName) { + Bucket bucket = mOSSClient.createBucket(bucketName); + return bucketName.equals(bucket.getName()); + } + + public final void deleteBucket(String bucketName) { + mOSSClient.deleteBucket(bucketName); + } + + public final String uploadObject2OSS(File file, String bucketName, String diskName) { + String resultStr = null; + try { + InputStream is = new FileInputStream(file); + String fileName = file.getName(); + Long fileSize = file.length(); + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentLength(is.available()); + metadata.setCacheControl("no-cache"); + metadata.setHeader("Pragma", "no-cache"); + metadata.setContentEncoding("utf-8"); + metadata.setContentType(getContentType(fileName)); + metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte."); + PutObjectResult putResult = mOSSClient.putObject(bucketName, diskName + fileName, is, metadata); + resultStr = putResult.getETag(); + } catch (Exception e) { + e.printStackTrace(); + } + return resultStr; + } + + public InputStream getOSS2InputStream(String bucketName, String diskName, String key) { + OSSObject ossObj = mOSSClient.getObject(bucketName, diskName + key); + return ossObj.getObjectContent(); + } + + public void deleteFile(String bucketName, String diskName, String key) { + mOSSClient.deleteObject(bucketName, diskName + key); + } + + private String getContentType(String fileName) { + String fileExtension = fileName.substring(fileName.lastIndexOf(".")); + if ("bmp".equalsIgnoreCase(fileExtension)) return "image/bmp"; + if ("gif".equalsIgnoreCase(fileExtension)) return "image/gif"; + if ("jpeg".equalsIgnoreCase(fileExtension) || + "jpg".equalsIgnoreCase(fileExtension) || + "png".equalsIgnoreCase(fileExtension)) + return "image/jpeg"; + if ("html".equalsIgnoreCase(fileExtension)) return "text/html"; + if ("txt".equalsIgnoreCase(fileExtension)) return "text/plain"; + if ("vsd".equalsIgnoreCase(fileExtension)) return "application/vnd.visio"; + if ("ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) + return "application/vnd.ms-powerpoint"; + if ("doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) + return "application/msword"; + if ("xml".equalsIgnoreCase(fileExtension)) return "text/xml"; + return "text/html"; + } +} diff --git a/src/main/java/net/irext/decoder/businesslogic/DecodeLogic.java b/src/main/java/net/irext/decoder/businesslogic/DecodeLogic.java index 56c9c63..7918e1b 100644 --- a/src/main/java/net/irext/decoder/businesslogic/DecodeLogic.java +++ b/src/main/java/net/irext/decoder/businesslogic/DecodeLogic.java @@ -1,7 +1,23 @@ package net.irext.decoder.businesslogic; +import net.irext.decoder.alioss.OSSHelper; +import net.irext.decoder.model.IRBinary; +import net.irext.decoder.model.RemoteIndex; +import net.irext.decoder.redisrepo.IIRBinaryRepository; +import net.irext.decoder.utils.FileUtils; +import net.irext.decoder.utils.MD5Util; +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import javax.servlet.ServletContext; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + /** * Filename: CollectCodeLogic * Revised: Date: 2018-12-08 @@ -15,8 +31,14 @@ import org.springframework.stereotype.Controller; @Controller public class DecodeLogic { + private static final String IR_BIN_FILE_PREFIX = "irda_"; + private static final String IR_BIN_FILE_SUFFIX = ".bin"; + private static DecodeLogic decodeLogic; + @Autowired + private ServletContext context; + public static DecodeLogic getInstance() { if (null == decodeLogic) { decodeLogic = new DecodeLogic(); @@ -28,7 +50,86 @@ public class DecodeLogic { } + public byte[] openIRBinary(IIRBinaryRepository irBinaryRepository, RemoteIndex remoteIndex) { + if (null == remoteIndex) { + return null; + } + try { + String checksum = remoteIndex.getBinaryMd5().toUpperCase(); + String remoteMap = remoteIndex.getRemoteMap(); + + IRBinary irBinary = irBinaryRepository.find(remoteIndex.getId()); + if (null != irBinary) { + byte[] binaries = irBinary.getBinary(); + if (null != binaries) { + System.out.println("binary content fetched from redis : " + binaries.length); + // validate binary content + String cachedChecksum = + MD5Util.byteArrayToHexString(MessageDigest.getInstance("MD5").digest(binaries)).toUpperCase(); + if (cachedChecksum.equals(checksum)) { + return binaries; + } + } + } + + // otherwise, read from file or OSS + String downloadPath = context.getRealPath("") + "bin_cache" + File.separator; + String fileName = IR_BIN_FILE_PREFIX + remoteMap + IR_BIN_FILE_SUFFIX; + String localFilePath = downloadPath + fileName; + + File binFile = new File(localFilePath); + FileInputStream fin = getFile(binFile, downloadPath, fileName, checksum); + if (null != fin) { + byte[] binaries = IOUtils.toByteArray(fin); + System.out.println("binary content get, save it to redis"); + irBinaryRepository.add(new IRBinary(remoteIndex.getId(), binaries)); + return binaries; + } + } catch (Exception ex) { + ex.printStackTrace(); + return null; + } + return null; + } + public int[] decode() { return null; } + + // helper methods + private FileInputStream getFile(File binFile, String downloadPath, String fileName, String checksum) { + try { + if (binFile.exists()) { + FileInputStream fileInputStream = new FileInputStream(binFile); + // validate binary content + byte []binaries = IOUtils.toByteArray(fileInputStream); + String fileChecksum = + MD5Util.byteArrayToHexString(MessageDigest.getInstance("MD5").digest(binaries)).toUpperCase(); + + if (fileChecksum.equals(checksum)) { + return new FileInputStream(binFile); + } + } + OSSHelper ossHelper = new OSSHelper(); + InputStream inputStream = ossHelper.getOSS2InputStream(OSSHelper.BUCKET_NAME, "", fileName); + // validate binary content + byte []binaries = IOUtils.toByteArray(inputStream); + String ossChecksum = + MD5Util.byteArrayToHexString(MessageDigest.getInstance("MD5").digest(binaries)).toUpperCase(); + if (ossChecksum.equals(checksum)) { + FileUtils.createDirs(downloadPath); + if (FileUtils.write(binFile, binaries)) { + return new FileInputStream(binFile); + } else { + System.out.println("fatal : write file to local path failed"); + } + } else { + System.out.println("fatal : checksum does not match even downloaded from OSS," + + " please contact the admin"); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } } diff --git a/src/main/java/net/irext/decoder/service/IRDecodeService.java b/src/main/java/net/irext/decoder/service/IRDecodeService.java index a79e687..2baf9a6 100644 --- a/src/main/java/net/irext/decoder/service/IRDecodeService.java +++ b/src/main/java/net/irext/decoder/service/IRDecodeService.java @@ -4,6 +4,8 @@ import net.irext.decoder.businesslogic.DecodeLogic; import net.irext.decoder.businesslogic.IndexLogic; import net.irext.decoder.mapper.RemoteIndexMapper; import net.irext.decoder.model.RemoteIndex; +import net.irext.decoder.redisrepo.IDecodeSessionRepository; +import net.irext.decoder.redisrepo.IIRBinaryRepository; import net.irext.decoder.request.CloseRequest; import net.irext.decoder.request.DecodeRequest; import net.irext.decoder.request.OpenRequest; @@ -13,6 +15,7 @@ import net.irext.decoder.response.Status; import net.irext.decoder.service.base.AbstractBaseService; import net.irext.decodesdk.bean.ACStatus; import net.irext.decodesdk.utils.Constants; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; /** @@ -31,6 +34,12 @@ public class IRDecodeService extends AbstractBaseService { private RemoteIndexMapper remoteIndexMapper; + @Autowired + private IIRBinaryRepository irBinaryRepository; + + @Autowired + private IDecodeSessionRepository decodeSessionRepository; + public IRDecodeService(RemoteIndexMapper remoteIndexMapper) { this.remoteIndexMapper = remoteIndexMapper; } @@ -41,11 +50,13 @@ public class IRDecodeService extends AbstractBaseService { int indexId = openRequest.getIndexId(); ServiceResponse response = new ServiceResponse(); - RemoteIndex index = IndexLogic.getInstance(remoteIndexMapper).getRemoteIndex(indexId); - if (null == index) { + RemoteIndex remoteIndex = IndexLogic.getInstance(remoteIndexMapper).getRemoteIndex(indexId); + if (null == remoteIndex) { response.setStatus(new Status(Constants.ERROR_CODE_NETWORK_ERROR, "")); return response; } + byte []binaryContent = DecodeLogic.getInstance().openIRBinary(irBinaryRepository, remoteIndex); + System.out.println("binary content fetched : " + binaryContent.length); return response; } catch (Exception e) { diff --git a/src/main/java/net/irext/decoder/utils/FileUtils.java b/src/main/java/net/irext/decoder/utils/FileUtils.java new file mode 100644 index 0000000..e0e792e --- /dev/null +++ b/src/main/java/net/irext/decoder/utils/FileUtils.java @@ -0,0 +1,114 @@ +package net.irext.decoder.utils; + +import java.io.*; + +/** + * Filename: FileUtils.java + * Revised: Date: 2017-04-14 + * Revision: Revision: 1.0 + *
+ * Description: File operations + *
+ * Revision log: + * 2017-04-14: created by strawmanbobi + */ +public class FileUtils { + + public static boolean write(File file, byte[] binaries) { + if (null == file) { + return false; + } + + if (null == binaries) { + System.out.println("fatal : content to write is null"); + return false; + } + FileOutputStream outputStream = null; + try { + outputStream = new FileOutputStream(file); + outputStream.write(binaries, 0, binaries.length); + outputStream.flush(); + return true; + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (outputStream != null) { + try { + outputStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return false; + } + + public static boolean createDirs(String path) { + File file = new File(path); + return file.exists() || file.mkdir(); + } + + public static byte[] getByteArrayFromFile(String fileName) { + File file; + try { + file = new File(fileName); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + + if (!file.exists() || !file.isFile() || !file.canRead()) { + return null; + } + + byte[] byteArray = null; + + try { + FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + int count; + byte buffer[] = new byte[512]; + while ((count = fis.read(buffer)) > 0) { + baos.write(buffer, 0, count); + } + byteArray = baos.toByteArray(); + fis.close(); + baos.flush(); + baos.close(); + } catch (Exception e) { + e.printStackTrace(); + } + + return byteArray; + } + + private static void deleteAllFiles(File root) { + File files[] = root.listFiles(); + if (files != null) { + for (File f : files) { + if (f.isDirectory()) { + deleteAllFiles(f); + try { + if(!f.delete()) { + System.out.println("failed to delete file"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } else { + if (f.exists()) { + deleteAllFiles(f); + try { + if(!f.delete()) { + System.out.println("failed to delete file"); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/net/irext/decoder/utils/MD5Util.java b/src/main/java/net/irext/decoder/utils/MD5Util.java new file mode 100644 index 0000000..c79acf0 --- /dev/null +++ b/src/main/java/net/irext/decoder/utils/MD5Util.java @@ -0,0 +1,53 @@ +package net.irext.decoder.utils; + +import java.security.MessageDigest; + +/** + * Filename: MD5Util.java + * Revised: Date: 2017-04-30 + * Revision: Revision: 1.0 + *
+ * Description: Crypto MD5 utility + *
+ * Revision log: + * 2017-04-30: created by strawmanbobi + */ +public class MD5Util { + + public static String byteArrayToHexString(byte b[]) { + StringBuffer resultSb = new StringBuffer(); + for (int i = 0; i < b.length; i++) + resultSb.append(byteToHexString(b[i])); + + return resultSb.toString(); + } + + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) + n += 256; + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + public static String MD5Encode(String origin, String charsetname) { + String resultString = null; + try { + resultString = new String(origin); + MessageDigest md = MessageDigest.getInstance("MD5"); + if (charsetname == null || "".equals(charsetname)) + resultString = byteArrayToHexString(md.digest(resultString + .getBytes())); + else + resultString = byteArrayToHexString(md.digest(resultString + .getBytes(charsetname))); + } catch (Exception exception) { + } + return resultString; + } + + private static final String hexDigits[] = {"0", "1", "2", "3", "4", "5", + "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"}; + +}