From dd468badba90491ae5c681bbf87e9b07b934328d Mon Sep 17 00:00:00 2001 From: tanhe123 Date: Mon, 23 Oct 2017 14:39:19 +0800 Subject: [PATCH] add file encoding support --- src/main/java/net/coding/ide/dto/FileDTO.java | 22 +++++++++++----- .../java/net/coding/ide/model/Workspace.java | 22 ++++++++++++++-- .../net/coding/ide/service/GitManager.java | 2 ++ .../coding/ide/service/GitManagerImpl.java | 24 ++++++++++++------ .../coding/ide/service/WorkspaceManager.java | 4 +++ .../ide/service/WorkspaceManagerImpl.java | 15 +++++++++++ .../ide/web/controller/ExceptionAdvice.java | 7 ++++++ .../ide/web/controller/GitController.java | 7 +++++- .../web/controller/WorkspaceController.java | 25 +++++++++++-------- 9 files changed, 100 insertions(+), 28 deletions(-) diff --git a/src/main/java/net/coding/ide/dto/FileDTO.java b/src/main/java/net/coding/ide/dto/FileDTO.java index 7a15882..68f78ce 100644 --- a/src/main/java/net/coding/ide/dto/FileDTO.java +++ b/src/main/java/net/coding/ide/dto/FileDTO.java @@ -19,22 +19,32 @@ public class FileDTO { @NonNull private String path; - @NonNull private String content; - @NonNull private Boolean base64; - private long lastModified; + private Long lastModified; - private FileDTO(String path, String content, Boolean base64, long lastModified) { + private String encoding; + + private FileDTO(String path, String content, String encoding, Boolean base64, Long lastModified) { this.path = path; this.content = content; this.base64 = base64; this.lastModified = lastModified; + this.encoding = encoding; + } + + public static FileDTO of(String path, String content, String encoding, Boolean base64, Long lastModified) { + return new FileDTO(path, content, encoding, base64, lastModified); + } + + public static FileDTO of(String path, String content, Boolean base64) { + return new FileDTO(path, content, null, base64, null); } - public static FileDTO of(String path, String content, Boolean base64, long lastModified) { - return new FileDTO(path, content, base64, lastModified); + public static FileDTO of(String path, String content, String encoding, Boolean base64) { + return new FileDTO(path, content, encoding, base64, null); } + } diff --git a/src/main/java/net/coding/ide/model/Workspace.java b/src/main/java/net/coding/ide/model/Workspace.java index 5877b8d..6a725c8 100644 --- a/src/main/java/net/coding/ide/model/Workspace.java +++ b/src/main/java/net/coding/ide/model/Workspace.java @@ -30,6 +30,7 @@ import java.util.Map; import static com.google.common.io.Files.toByteArray; +import static org.apache.commons.lang.StringUtils.isNotBlank; /** * Created by vangie on 14/11/10. @@ -97,6 +98,13 @@ public static void purge(File baseDir) { } public String read(String path, boolean base64) throws IOException { + return read(path, getEncoding(), base64); + } + + /** + * read file by specific encoding or workspace default encoding + */ + public String read(String path, String encodingParam, boolean base64) throws IOException { Path p = this.getPath(path); if (Files.isSymbolicLink(p) && !linkTargetExist(p)) { @@ -110,7 +118,11 @@ public String read(String path, boolean base64) throws IOException { return BaseEncoding.base64().encode(content); } - return new String(content, getEncoding()); + if (isNotBlank(encodingParam)) { + return new String(content, encodingParam); + } else { + return new String(content, encoding); + } } catch (FileNotFoundException e) { throw new WorkspaceIOException(path + " not found", e); } @@ -233,7 +245,12 @@ public File getKeyDir() { return keyDir.toFile(); } + public void write(String path, String content, boolean base64, boolean override, boolean createParent) throws IOException { + write(path, content, encoding, base64, override, createParent); + } + + public void write(String path, String content, String encodingParam, boolean base64, boolean override, boolean createParent) throws IOException { Path p = this.getPath(path); if (Files.isSymbolicLink(p) && !linkTargetExist(p)) { @@ -254,7 +271,8 @@ public void write(String path, String content, boolean base64, boolean override, BufferedWriter bw = null; try { - bw = Files.newBufferedWriter(p, Charset.forName(getEncoding())); + final String finalEncoding = isNotBlank(encodingParam) ? encodingParam : getEncoding(); + bw = Files.newBufferedWriter(p, Charset.forName(finalEncoding)); if (override) { bw.write(decodeContent); diff --git a/src/main/java/net/coding/ide/service/GitManager.java b/src/main/java/net/coding/ide/service/GitManager.java index 2722fe9..07812bd 100644 --- a/src/main/java/net/coding/ide/service/GitManager.java +++ b/src/main/java/net/coding/ide/service/GitManager.java @@ -125,5 +125,7 @@ public interface GitManager { String readFileFromRef(Workspace ws, String ref, String path, boolean base64) throws IOException; + String readFileFromRef(Workspace ws, String ref, String path, String encoding, boolean base64) throws IOException; + void reset(Workspace ws, String ref, ResetType resetType) throws GitAPIException; } diff --git a/src/main/java/net/coding/ide/service/GitManagerImpl.java b/src/main/java/net/coding/ide/service/GitManagerImpl.java index 2f1d463..48a7087 100644 --- a/src/main/java/net/coding/ide/service/GitManagerImpl.java +++ b/src/main/java/net/coding/ide/service/GitManagerImpl.java @@ -698,15 +698,15 @@ private void generate_conflict_files(Workspace ws, ObjectId base, ObjectId local String content = readBlobContent(repository, base, ws.getEncoding()); - ws.write(path + CONFLIX_FILE_BASE_SUFFIX, content, false, true, false); + ws.write(path + CONFLIX_FILE_BASE_SUFFIX, content, ws.getEncoding(), false, true, false); content = readBlobContent(repository, local, ws.getEncoding()); - ws.write(path + CONFLIX_FILE_LOCAL_SUFFIX, content, false, true, false); + ws.write(path + CONFLIX_FILE_LOCAL_SUFFIX, content, ws.getEncoding(), false, true, false); content = readBlobContent(repository, remote, ws.getEncoding()); - ws.write(path + CONFLIX_FILE_REMOTE_SUFFIX, content, false, true, true); + ws.write(path + CONFLIX_FILE_REMOTE_SUFFIX, content, ws.getEncoding(), false, true, true); } @@ -727,11 +727,15 @@ private String readBlobContent(Repository repository, ObjectId objectId, String return content.toString(encoding); } + public String readFileFromRef(Workspace ws, String ref, String path, boolean base64) throws IOException { + return readFileFromRef(ws, ref, path, ws.getEncoding(), base64); + } + /** * 读取某次提交的的某个文件的内容 */ @Override - public String readFileFromRef(Workspace ws, String ref, String path, boolean base64) throws IOException { + public String readFileFromRef(Workspace ws, String ref, String path, String encoding, boolean base64) throws IOException { Repository repository = getRepository(ws.getSpaceKey()); ObjectId objectId = repository.resolve(ref); @@ -770,7 +774,11 @@ public String readFileFromRef(Workspace ws, String ref, String path, boolean bas if (base64) { return BaseEncoding.base64().encode(content); } else { - return new String(content, ws.getEncoding()); + if (StringUtils.isNotBlank(encoding)) { + return new String(content, encoding); + } else { + return new String(content, ws.getEncoding()); + } } } } @@ -810,9 +818,9 @@ public ConflictFile queryConflictFile(Workspace ws, String path, boolean base64) ConflictFile response = new ConflictFile(); - response.setBase(ws.read(basePath, base64)); - response.setLocal(ws.read(localPath, base64)); - response.setRemote(ws.read(remotePath, base64)); + response.setBase(ws.read(basePath, ws.getEncoding(), base64)); + response.setLocal(ws.read(localPath, ws.getEncoding(), base64)); + response.setRemote(ws.read(remotePath, ws.getEncoding(), base64)); return response; } diff --git a/src/main/java/net/coding/ide/service/WorkspaceManager.java b/src/main/java/net/coding/ide/service/WorkspaceManager.java index 319d842..ec401ca 100644 --- a/src/main/java/net/coding/ide/service/WorkspaceManager.java +++ b/src/main/java/net/coding/ide/service/WorkspaceManager.java @@ -4,11 +4,13 @@ package net.coding.ide.service; +import net.coding.ide.dto.FileDTO; import net.coding.ide.entity.WorkspaceEntity; import net.coding.ide.model.FileInfo; import net.coding.ide.model.FileSearchResultEntry; import net.coding.ide.model.Workspace; import net.coding.ide.model.exception.GitCloneAuthFailException; +import org.eclipse.jgit.api.errors.GitAPIException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -32,6 +34,8 @@ public interface WorkspaceManager { WorkspaceEntity getWorkspaceEntity(String spaceKey); + FileDTO readFile(Workspace ws, String path, String encoding, boolean base64) throws IOException, GitAPIException, Exception; + FileInfo getFileInfo(Workspace ws, String path) throws Exception; List listFiles(Workspace ws, String path, boolean order, boolean group) throws Exception; diff --git a/src/main/java/net/coding/ide/service/WorkspaceManagerImpl.java b/src/main/java/net/coding/ide/service/WorkspaceManagerImpl.java index 347b547..4383461 100644 --- a/src/main/java/net/coding/ide/service/WorkspaceManagerImpl.java +++ b/src/main/java/net/coding/ide/service/WorkspaceManagerImpl.java @@ -10,6 +10,7 @@ import com.google.common.collect.Maps; import com.jcraft.jsch.JSchException; import lombok.extern.slf4j.Slf4j; +import net.coding.ide.dto.FileDTO; import net.coding.ide.entity.ProjectEntity; import net.coding.ide.entity.WorkspaceEntity; import net.coding.ide.event.WorkspaceDeleteEvent; @@ -58,6 +59,7 @@ import static java.lang.String.format; import static net.coding.ide.entity.WorkspaceEntity.WsWorkingStatus.*; +import static org.apache.commons.lang3.StringUtils.isBlank; /** * Created by vangie on 14/11/11. @@ -479,6 +481,19 @@ private void updateReadableAndWritable(FileInfo fileInfo, Path p) { fileInfo.setWritable(file.canWrite()); } + @Override + public FileDTO readFile(Workspace ws, String path, String encodingParam, boolean base64) throws Exception { + FileInfo fileInfo = getFileInfo(ws, path); + + final String encoding = isBlank(encodingParam) ? ws.getEncoding() : encodingParam; + + return FileDTO.of(path, + ws.read(path, encoding, base64), + encoding, + base64, + fileInfo.getLastModified().getMillis()); + } + private void updateFileTime(FileInfo fileInfo, Path p) throws IOException { updateFileTime(fileInfo, p, null); } diff --git a/src/main/java/net/coding/ide/web/controller/ExceptionAdvice.java b/src/main/java/net/coding/ide/web/controller/ExceptionAdvice.java index 91bd855..0c686b8 100644 --- a/src/main/java/net/coding/ide/web/controller/ExceptionAdvice.java +++ b/src/main/java/net/coding/ide/web/controller/ExceptionAdvice.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.UnsupportedEncodingException; import static java.lang.String.format; import static org.springframework.http.HttpStatus.*; @@ -38,6 +39,12 @@ public class ExceptionAdvice { @Value("${UPLOAD_FILE_SIZE_LIMIT}") private int fileSizeLimit; + @ExceptionHandler(UnsupportedEncodingException.class) + @ResponseBody + public ResponseEntity unsupportedEncodingException(UnsupportedEncodingException e) { + return makeMsgWithHttpStatus(BAD_REQUEST.value(), "unsupported encoding: " + e.getMessage()); + } + @ExceptionHandler(WorkspaceIOException.class) @ResponseStatus(INTERNAL_SERVER_ERROR) @ResponseBody diff --git a/src/main/java/net/coding/ide/web/controller/GitController.java b/src/main/java/net/coding/ide/web/controller/GitController.java index 90e0571..6f50260 100644 --- a/src/main/java/net/coding/ide/web/controller/GitController.java +++ b/src/main/java/net/coding/ide/web/controller/GitController.java @@ -14,6 +14,7 @@ import net.coding.ide.model.exception.NotFoundException; import net.coding.ide.service.GitManager; import net.coding.ide.service.WorkspaceManager; +import org.apache.commons.lang3.StringUtils; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.filter.AuthorRevFilter; import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter; @@ -310,8 +311,12 @@ public ResponseEntity createStash(@PathVariable("spaceKey") Workspace ws, public FileDTO read(@PathVariable("spaceKey") Workspace ws, @RequestParam String ref, @RequestParam String path, + @RequestParam String encoding, @RequestParam(defaultValue = "false") boolean base64) throws IOException { - String content = gitMgr.readFileFromRef(ws, ref, path, base64); + + final String finalEncoding = StringUtils.isBlank(encoding) ? ws.getEncoding() : encoding; + + String content = gitMgr.readFileFromRef(ws, ref, path, finalEncoding, base64); return FileDTO.of(path, content, base64); } diff --git a/src/main/java/net/coding/ide/web/controller/WorkspaceController.java b/src/main/java/net/coding/ide/web/controller/WorkspaceController.java index b118f41..120f022 100644 --- a/src/main/java/net/coding/ide/web/controller/WorkspaceController.java +++ b/src/main/java/net/coding/ide/web/controller/WorkspaceController.java @@ -17,6 +17,7 @@ import net.coding.ide.model.exception.WorkspaceMissingException; import net.coding.ide.service.GitManager; import net.coding.ide.service.WorkspaceManager; +import org.apache.commons.lang3.StringUtils; import org.modelmapper.ModelMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,10 +27,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; @@ -49,6 +47,7 @@ import static java.net.URLEncoder.encode; import static java.util.Collections.synchronizedList; import static net.coding.ide.model.HttpSessions.OPENED_WORKSPACE_LIST; +import static org.apache.commons.lang3.StringUtils.isNotBlank; import static org.springframework.http.HttpHeaders.CONTENT_DISPOSITION; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; @@ -184,27 +183,31 @@ public List list(@PathVariable("spaceKey") Workspace ws, @RequestMapping(value = "/workspaces/{spaceKey}/file/read", method = GET) public FileDTO read(@PathVariable("spaceKey") Workspace ws, @RequestParam String path, + @RequestParam(required = false) String encoding, @RequestParam(defaultValue = "false") boolean base64) throws Exception { - FileInfo fileInfo = wsMgr.getFileInfo(ws, path); + final String finalEncoding = StringUtils.isBlank(encoding) ? ws.getEncoding() : encoding; - return FileDTO.of(path, - ws.read(path, base64), - base64, - fileInfo.getLastModified().getMillis()); + return wsMgr.readFile(ws, path, finalEncoding, base64); } @RequestMapping(value = "/workspaces/{spaceKey}/files", method = PUT) public FileDTO write(@PathVariable("spaceKey") Workspace ws, @RequestParam String path, @RequestParam String content, + @RequestParam(required = false) String encoding, @RequestParam(defaultValue = "false") boolean base64, @RequestParam(defaultValue = "true") boolean override, @RequestParam(defaultValue = "true") boolean createParent) throws Exception { - ws.write(path, content, base64, override, createParent); + + final String finalEncoding = isNotBlank(encoding) ? encoding : ws.getEncoding(); + + ws.write(path, content, finalEncoding, base64, override, createParent); + FileDTO fileDTO = FileDTO.of(path, - ws.read(path, base64), + ws.read(path, finalEncoding, base64), + finalEncoding, base64); if (ws.exists(path)) {