Skip to content

Commit

Permalink
[#225] 테스트 코드 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
km2535 committed Sep 5, 2024
1 parent 445f956 commit 55def15
Show file tree
Hide file tree
Showing 10 changed files with 171 additions and 89 deletions.
121 changes: 98 additions & 23 deletions src/main/java/com/speech/up/api/converter/WavToRaw.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.speech.up.api.converter;

import javax.sound.sampled.*;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.UnsupportedAudioFileException;

import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.constraints.NotNull;
Expand All @@ -20,36 +28,103 @@ public WavToRaw() {
super();
}

// WAV 파일을 읽어 PCM 데이터를 바이트 배열로 반환
public byte[] convertToRawPcm(MultipartFile multipartFile) throws UnsupportedAudioFileException, IOException {
File file = File.createTempFile("uploaded-", ".wav");
// MultipartFile 데이터를 임시 파일로 저장
multipartFile.transferTo(file);
try (AudioInputStream sourceStream = AudioSystem.getAudioInputStream(file)) {
AudioFormat sourceFormat = sourceStream.getFormat();
AudioFormat targetFormat = FORMAT;
// WAV 파일을 읽어 PCM 데이터를 Optional<byte[]>로 반환
public Optional<byte[]> convertToRawPcm(MultipartFile multipartFile) {
Optional<File> tempFile = createTempFile(multipartFile);
if (tempFile.isEmpty()) {
return Optional.empty(); // 파일 생성 실패 시 빈 Optional 반환
}

if (!AudioSystem.isConversionSupported(targetFormat, sourceFormat)) {
throw new UnsupportedAudioFileException("The source format is not supported.");
}
Optional<byte[]> pcmData = processAudioFile(tempFile.get());
deleteTempFile(tempFile.get());

try (AudioInputStream convertedStream = AudioSystem.getAudioInputStream(targetFormat, sourceStream);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
return pcmData;
}

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = convertedStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}
// MultipartFile을 임시 파일로 변환
private Optional<File> createTempFile(MultipartFile multipartFile) {
try {
File tempFile = File.createTempFile("uploaded-", ".wav");
multipartFile.transferTo(tempFile); // MultipartFile을 임시 파일로 저장
return Optional.of(tempFile);
} catch (IOException e) {
log.error("임시 파일 생성 실패: {}", e.getMessage());
return Optional.empty(); // 파일 생성 실패 시 빈 Optional 반환
}
}

byte[] rawPcmData = byteArrayOutputStream.toByteArray();
return formatWav2Raw(rawPcmData);
// 임시 파일 삭제
private void deleteTempFile(File tempFile) {
if (!fileExists(tempFile)) {
return; // 파일이 존재하지 않으면 조기 리턴
}

if (!tempFile.delete()) {
log.warn("임시 파일 삭제 실패: {}", tempFile.getPath());
}
}

// 파일 존재 여부 확인
private boolean fileExists(File file) {
return file != null && file.exists();
}

// 파일을 처리하여 PCM 데이터로 변환
private Optional<byte[]> processAudioFile(File file) {
Optional<AudioInputStream> sourceStream = getAudioInputStream(file);
if (sourceStream.isEmpty()) {
return Optional.empty(); // AudioInputStream 생성 실패 시 빈 Optional 반환
}

Optional<AudioInputStream> convertedStream = convertAudioStream(sourceStream.get());
if (convertedStream.isEmpty()) {
return Optional.empty(); // AudioStream 변환 실패 시 빈 Optional 반환
}

return readPcmData(convertedStream.get());
}

// 오디오 파일을 AudioInputStream으로 가져오기
private Optional<AudioInputStream> getAudioInputStream(File file) {
try {
return Optional.of(AudioSystem.getAudioInputStream(file));
} catch (UnsupportedAudioFileException | IOException e) {
log.error("오디오 스트림 생성 실패: {}", e.getMessage());
return Optional.empty(); // AudioInputStream 생성 실패 시 빈 Optional 반환
}
}

// 소스 포맷을 변환 가능 여부 확인 및 변환
private Optional<AudioInputStream> convertAudioStream(AudioInputStream sourceStream) {
AudioFormat sourceFormat = sourceStream.getFormat();

if (!AudioSystem.isConversionSupported(FORMAT, sourceFormat)) {
log.error("변환할 수 없는 오디오 포맷: {}", sourceFormat);
return Optional.empty(); // 변환 불가 시 빈 Optional 반환
}

return Optional.of(AudioSystem.getAudioInputStream(FORMAT, sourceStream));
}

// PCM 데이터를 읽고 반환
private Optional<byte[]> readPcmData(AudioInputStream convertedStream) {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = convertedStream.read(buffer)) != -1) {
byteArrayOutputStream.write(buffer, 0, bytesRead);
}

byte[] rawPcmData = byteArrayOutputStream.toByteArray();
return Optional.of(formatWav2Raw(rawPcmData)); // PCM 데이터로 변환
} catch (IOException e) {
log.error("PCM 데이터 읽기 실패: {}", e.getMessage());
return Optional.empty(); // PCM 데이터 읽기 실패 시 빈 Optional 반환
}
}

// WAV 헤더를 제거하고 PCM 데이터만 반환
private byte[] formatWav2Raw(@NotNull final byte[] audioFileContent) {
return Arrays.copyOfRange(audioFileContent, HEADER_SIZE, audioFileContent.length);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
Expand All @@ -22,10 +23,12 @@
import com.speech.up.api.etri.dto.ResponseRecognitionDto;
import com.speech.up.api.etri.type.ApiType;
import com.speech.up.api.etri.url.UrlCollector;
import com.speech.up.common.enums.StatusCode;
import com.speech.up.common.exception.custom.CustomIOException;
import com.speech.up.common.exception.http.BadRequestException;
import com.speech.up.report.service.ReportService;
import com.speech.up.record.entity.RecordEntity;
import com.speech.up.record.repository.RecordRepository;
import com.speech.up.report.service.ReportService;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -55,10 +58,13 @@ public void callRecognitionApi(String script, Long recordId) {
String audioContents = encodeAudioToBase64(recordEntity.getAudio());

RequestPronunciationDto pronunciationRequest = createPronunciationRequest(audioContents, script);
RequestRecognitionDto recognizedRequest = createRecognizedRequest(audioContents, recordEntity.getLanguageCode());
RequestRecognitionDto recognizedRequest = createRecognizedRequest(audioContents,
recordEntity.getLanguageCode());

ResponseEntity<ResponseRecognitionDto> recognizedResponse = sendPostRequest(ApiType.RECOGNITION, recognizedRequest, ResponseRecognitionDto.class);
ResponseEntity<ResponsePronunciationApiDto> pronunciationResponse = sendPostRequest(ApiType.PRONUNCIATION, pronunciationRequest, ResponsePronunciationApiDto.class);
ResponseEntity<ResponseRecognitionDto> recognizedResponse = sendPostRequest(ApiType.RECOGNITION,
recognizedRequest, ResponseRecognitionDto.class);
ResponseEntity<ResponsePronunciationApiDto> pronunciationResponse = sendPostRequest(ApiType.PRONUNCIATION,
pronunciationRequest, ResponsePronunciationApiDto.class);

handleApiResponses(recognizedResponse, pronunciationResponse);

Expand All @@ -67,7 +73,8 @@ public void callRecognitionApi(String script, Long recordId) {

saveReportIfValid(recognizedBody, pronunciationBody, recordEntity);
} catch (IOException e) {
throw new RuntimeException("Error during API request", e);
log.error(e.getMessage(), e);
throw new CustomIOException(StatusCode.IO_ERROR);
}
}

Expand All @@ -88,21 +95,17 @@ private RequestRecognitionDto createRecognizedRequest(String audioContents, Stri
return RequestRecognitionDto.createRecognition("reserved field", audioContents, languageCode);
}

private <T> ResponseEntity<T> sendPostRequest(ApiType apiType, Object requestDTO, Class<T> responseType) throws IOException {
private <T> ResponseEntity<T> sendPostRequest(ApiType apiType, Object requestDTO, Class<T> responseType) throws
IOException {
URL url = getUrl(apiType);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
HttpURLConnection con = (HttpURLConnection)url.openConnection();
configureConnection(con);

try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
String jsonRequest = gson.toJson(requestDTO);
log.info("Sending request to {} API: {}", apiType, jsonRequest);
wr.write(jsonRequest.getBytes(StandardCharsets.UTF_8));
wr.flush();
}
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String jsonRequest = gson.toJson(requestDTO);
wr.write(jsonRequest.getBytes(StandardCharsets.UTF_8));
wr.flush();

int responseCode = con.getResponseCode();
log.info("Response code from {} API: {}", apiType, responseCode);

if (responseCode != HttpURLConnection.HTTP_OK) {
String errorResponse = readErrorResponse(con);
log.error("Error response from {} API: {}", apiType, errorResponse);
Expand Down Expand Up @@ -130,12 +133,11 @@ private void configureConnection(HttpURLConnection con) throws ProtocolException
}

private String readErrorResponse(HttpURLConnection con) throws IOException {
try (InputStream errorStream = con.getErrorStream()) {
if (errorStream != null) {
return new String(errorStream.readAllBytes(), StandardCharsets.UTF_8);
} else {
return "No error stream available";
}
InputStream errorStream = con.getErrorStream();
if (Objects.nonNull(errorStream)) {
return new String(errorStream.readAllBytes(), StandardCharsets.UTF_8);
} else {
return "No error stream available";
}
}

Expand All @@ -153,7 +155,7 @@ private void handleApiResponses(ResponseEntity<ResponseRecognitionDto> recognize
private void saveReportIfValid(ResponseRecognitionDto recognizedBody,
ResponsePronunciationApiDto pronunciationBody,
RecordEntity recordEntity) {
if (recognizedBody != null && pronunciationBody != null) {
if (Objects.nonNull(recognizedBody) && Objects.nonNull(pronunciationBody)) {
String recognized = recognizedBody.getReturn_object().getRecognized();
Double score = pronunciationBody.getReturn_object().getScore();
reportService.saveReport(recordEntity, recognized, score);
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/com/speech/up/auth/entity/CustomOAuth2User.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package com.speech.up.auth.entity;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.core.user.OAuth2User;

import lombok.AllArgsConstructor;
Expand All @@ -14,19 +21,31 @@
public class CustomOAuth2User implements OAuth2User {

private String userId;
private String authorities; // 사용자 권한을 쉼표로 구분된 문자열로 저장

@Override
public Map<String, Object> getAttributes() {
return null;
Map<String, Object> attributes = new HashMap<>();
attributes.put("userId", userId);
return attributes;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
return Objects.isNull(authorities) ? parseAuthorities(authorities) : Set.of();
}

@Override
public String getName() {
return this.userId;
}

// 권한 문자열을 파싱하여 GrantedAuthority의 컬렉션으로 변환
private Collection<? extends GrantedAuthority> parseAuthorities(String authorities) {
return Arrays.stream(authorities.split(","))
.map(String::trim)
.filter(auth -> !auth.isEmpty())
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
}
}
10 changes: 7 additions & 3 deletions src/main/java/com/speech/up/auth/provider/JwtProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class JwtProvider {
@Value("${jwt.secret.key}")
Expand All @@ -40,17 +45,16 @@ public String validate(String jwt) {
.getBody()
.getSubject();
} catch (NullPointerException nullPointerException) {
log.error("Invalid JWT");
throw new IllegalArgumentException("JwtProvider 클래스에 문제 있으니 확인해라.");
} catch (Exception exception) {
throw new IllegalArgumentException(exception);
}
return subject;
}

public String getHeader(HttpServletRequest request) {
String authorization = request.getHeader("Authorization");

if (authorization != null && authorization.startsWith("Bearer ")) {
if (Objects.nonNull(authorization) && authorization.startsWith("Bearer ")) {
authorization = authorization.substring(7);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2Authenticatio
Provider provider = new Provider(oAuth2User);
UserEntity userEntity = provider.getUser(ProviderType.valueOf(oauthClientName.toUpperCase()));

assert userEntity != null;

if (!userRepository.existsBySocialId(userEntity.getSocialId())) {
userRepository.save(userEntity);
} else {
Expand All @@ -42,7 +40,7 @@ public OAuth2User loadUser(OAuth2UserRequest request) throws OAuth2Authenticatio
UserEntity updateUserAccess = UserEntity.updateUserAccess(user);
userRepository.save(updateUserAccess);
}
return new CustomOAuth2User(userEntity.getSocialId());
return new CustomOAuth2User(userEntity.getSocialId(), userEntity.getAuthorization());
}

}
1 change: 1 addition & 0 deletions src/main/java/com/speech/up/common/enums/StatusCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public enum StatusCode {
IO_ERROR(1, "IO Error"),
NO_SCRIPTS(1001, "No Scripts"),
NO_RECORDS(2002, "No Records"),
NO_AUTHORIZATION(403, "No Authorization"),
NO_FILES(2003, "No Files");

private final int code;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package com.speech.up.common.exception.custom;

import java.io.IOException;

import org.springframework.http.HttpStatus;

import com.speech.up.common.enums.StatusCode;

import lombok.Getter;

@Getter
public abstract class CustomIOException extends IOException {
public class CustomIOException extends RuntimeException {
private final StatusCode errorCode;

public CustomIOException(StatusCode errorCode) {
Expand Down
Loading

0 comments on commit 55def15

Please sign in to comment.