Java tutorial
/** * Yobi, Project Hosting SW * * Copyright 2012 NAVER Corp. * http://yobi.io * * @Author Ahn Hyeok Jun * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package playRepository; import controllers.UserApp; import controllers.routes; import models.Project; import models.User; import models.enumeration.ResourceType; import models.resource.Resource; import org.apache.commons.io.FileUtils; import org.apache.tika.Tika; import org.codehaus.jackson.node.ObjectNode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.diff.RawText; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.tigris.subversion.javahl.ClientException; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNDiffClient; import org.tmatesoft.svn.core.wc.SVNRevision; import play.libs.Json; import utils.FileUtil; import utils.GravatarUtil; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class SVNRepository implements PlayRepository { private static String repoPrefix = "repo/svn/"; public static String getRepoPrefix() { return repoPrefix; } public static void setRepoPrefix(String repoPrefix) { SVNRepository.repoPrefix = repoPrefix; } private final String projectName; private final String ownerName; public SVNRepository(final String userName, String projectName) { this.ownerName = userName; this.projectName = projectName; } @Override public byte[] getRawFile(String revision, String path) throws SVNException { Long revId = (revision.equals("HEAD") ? -1l : Long.parseLong(revision)); org.tmatesoft.svn.core.io.SVNRepository repository = getSVNRepository(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); repository.getFile(path, revId, null, baos); // revId=-1l return baos.toByteArray(); } @Override public ObjectNode getMetaDataFromPath(String path) throws SVNException, IOException { org.tmatesoft.svn.core.io.SVNRepository repository = getSVNRepository(); SVNNodeKind nodeKind = repository.checkPath(path, -1); if (nodeKind == SVNNodeKind.DIR) { ObjectNode result = Json.newObject(); ObjectNode listData = Json.newObject(); SVNProperties prop = new SVNProperties(); Collection<SVNDirEntry> entries = repository.getDir(path, -1, prop, SVNDirEntry.DIRENT_ALL, (Collection) null); result.put("type", "folder"); for (SVNDirEntry entry : entries) { ObjectNode data = Json.newObject(); String author = entry.getAuthor(); User user = User.findByLoginId(author); Long commitTime = entry.getDate().getTime(); data.put("type", entry.getKind() == SVNNodeKind.DIR ? "folder" : "file"); data.put("msg", entry.getCommitMessage()); data.put("author", author); data.put("avatar", getAvatar(user)); data.put("userName", user.name); data.put("userLoginId", user.loginId); data.put("createdDate", commitTime); data.put("commitMessage", entry.getCommitMessage()); data.put("commiter", author); data.put("commitDate", commitTime); data.put("commitId", entry.getRevision()); data.put("size", entry.getSize()); listData.put(entry.getName(), data); } result.put("data", listData); return result; } else if (nodeKind == SVNNodeKind.FILE) { return fileAsJson(path, repository); } else { return null; } } private static String getAvatar(User user) { if (user.isAnonymous() || user.avatarUrl().equals(UserApp.DEFAULT_AVATAR_URL)) { String defaultImageUrl = "http://ko.gravatar.com/userimage/53495145/0eaeeb47c620542ad089f17377298af6.png"; return GravatarUtil.getAvatar(user.email, 34, defaultImageUrl); } else { return user.avatarUrl(); } } @Override public ObjectNode getMetaDataFromPath(String branch, String path) throws IOException, SVNException { List<String> branches = getBranchNames(); if (!branches.contains(branch)) { return null; } org.tmatesoft.svn.core.io.SVNRepository repository = getSVNRepository(); SVNNodeKind nodeKind = repository.checkPath(path, -1); if (nodeKind == SVNNodeKind.DIR) { ObjectNode result = Json.newObject(); ObjectNode listData = Json.newObject(); SVNProperties prop = new SVNProperties(); Collection<SVNDirEntry> entries = repository.getDir(path, -1, prop, SVNDirEntry.DIRENT_ALL, (Collection) null); result.put("type", "folder"); for (SVNDirEntry entry : entries) { ObjectNode data = Json.newObject(); String author = entry.getAuthor(); User user = User.findByLoginId(author); Long commitTime = entry.getDate().getTime(); data.put("type", entry.getKind() == SVNNodeKind.DIR ? "folder" : "file"); data.put("msg", entry.getCommitMessage()); data.put("author", author); data.put("avatar", getAvatar(user)); data.put("userName", user.name); data.put("userLoginId", user.loginId); data.put("createdDate", commitTime); data.put("commitMessage", entry.getCommitMessage()); data.put("commiter", author); data.put("commitDate", commitTime); data.put("commitId", entry.getRevision()); data.put("commitUrl", routes.CodeHistoryApp .show(ownerName, projectName, String.valueOf(entry.getRevision())).url()); data.put("size", entry.getSize()); listData.put(entry.getName(), data); } result.put("data", listData); return result; } else if (nodeKind == SVNNodeKind.FILE) { return fileAsJson(path, repository); } else { return null; } } private ObjectNode fileAsJson(String path, org.tmatesoft.svn.core.io.SVNRepository repository) throws SVNException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); SVNProperties prop = new SVNProperties(); repository.getFile(path, -1l, prop, baos); SVNDirEntry entry = repository.info(path, -1l); long size = entry.getSize(); boolean isBinary; String mimeType; String data = null; if (size > MAX_FILE_SIZE_CAN_BE_VIEWED) { isBinary = true; mimeType = "application/octet-stream"; } else { byte[] bytes = baos.toByteArray(); isBinary = RawText.isBinary(bytes); if (!isBinary) { data = new String(bytes, FileUtil.detectCharset(bytes)); } mimeType = new Tika().detect(bytes, path); } String author = prop.getStringValue(SVNProperty.LAST_AUTHOR); User user = User.findByLoginId(author); String commitDate = prop.getStringValue(SVNProperty.COMMITTED_DATE); DateTimeFormatter dateFormatter = ISODateTimeFormat.dateTime(); Long commitTime = dateFormatter.parseMillis(commitDate); ObjectNode result = Json.newObject(); result.put("type", "file"); result.put("revisionNo", prop.getStringValue(SVNProperty.COMMITTED_REVISION)); result.put("author", author); result.put("avatar", getAvatar(user)); result.put("userName", user.name); result.put("userLoginId", user.loginId); result.put("createdDate", commitTime); result.put("commitMessage", entry.getCommitMessage()); result.put("commiter", author); result.put("size", size); result.put("isBinary", isBinary); result.put("mimeType", mimeType); result.put("data", data); return result; } @Override public void create() throws ClientException { String svnPath = new File(SVNRepository.getRepoPrefix() + ownerName + "/" + projectName).getAbsolutePath(); new org.tigris.subversion.javahl.SVNAdmin().create(svnPath, false, false, null, "fsfs"); } @Override public void delete() { FileUtil.rm_rf(new File(getRepoPrefix() + ownerName + "/" + projectName)); } @Override public String getPatch(String commitId) throws SVNException { long rev = Integer.parseInt(commitId); return getPatch(rev - 1, rev); } @Override public String getPatch(String revA, String revB) throws SVNException { return getPatch(Long.parseLong(revA), Long.parseLong(revB)); } private String getPatch(long revA, long revB) throws SVNException { // Prepare required arguments. SVNURL svnURL = SVNURL.fromFile(new File(getRepoPrefix() + ownerName + "/" + projectName)); // Get diffClient. SVNClientManager clientManager = SVNClientManager.newInstance(); SVNDiffClient diffClient = clientManager.getDiffClient(); // Using diffClient, write the changes by commitId into // byteArrayOutputStream, as unified format. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); diffClient.doDiff(svnURL, null, SVNRevision.create(revA), SVNRevision.create(revB), SVNDepth.INFINITY, true, byteArrayOutputStream); return byteArrayOutputStream.toString(); } @Override public List<FileDiff> getDiff(String commitId) throws IOException { throw new UnsupportedOperationException(); } @Override public List<FileDiff> getDiff(String revA, String revB) throws IOException { throw new UnsupportedOperationException(); } @Override public List<Commit> getHistory(int page, int limit, String until, String path) throws IOException, GitAPIException, SVNException { // Get the repository SVNURL svnURL = SVNURL.fromFile(new File(repoPrefix + ownerName + "/" + projectName)); org.tmatesoft.svn.core.io.SVNRepository repository = SVNRepositoryFactory.create(svnURL); // path to get log String[] paths = { "/" }; if (path != null) { paths[0] = "/" + path; } // Determine revisions long startRevision = repository.getLatestRevision() - page * limit; long endRevision = startRevision - limit; if (endRevision < 1) { endRevision = 1; } // No log to return. if (startRevision < endRevision) { return new ArrayList<>(); } // Get the logs List<Commit> result = new ArrayList<>(); for (Object entry : repository.log(paths, null, startRevision, endRevision, false, false)) { result.add(new SvnCommit((SVNLogEntry) entry)); } return result; } @Override public Commit getCommit(String revNumber) throws IOException, SVNException { long rev = Integer.parseInt(revNumber); String[] paths = { "/" }; SVNURL svnURL = SVNURL.fromFile(new File(getRepoPrefix() + ownerName + "/" + projectName)); org.tmatesoft.svn.core.io.SVNRepository repository = SVNRepositoryFactory.create(svnURL); for (Object entry : repository.log(paths, null, rev, rev, false, false)) { return new SvnCommit((SVNLogEntry) entry); } return null; } @Override public List<String> getBranchNames() { ArrayList<String> branches = new ArrayList<>(); branches.add(SVNRevision.HEAD.getName()); return branches; } @Override public Resource asResource() { return new Resource() { @Override public String getId() { return null; } @Override public Project getProject() { return Project.findByOwnerAndProjectName(ownerName, projectName); } @Override public ResourceType getType() { return ResourceType.CODE; } }; } private org.tmatesoft.svn.core.io.SVNRepository getSVNRepository() throws SVNException { SVNURL svnURL = SVNURL.fromFile(new File(getRepoPrefix() + ownerName + "/" + projectName)); return SVNRepositoryFactory.create(svnURL); } public boolean isFile(String path, long rev) throws SVNException { return getSVNRepository().checkPath(path, rev) == SVNNodeKind.FILE; } @Override public boolean isFile(String path) throws SVNException, IOException { return isFile(path, getSVNRepository().getLatestRevision()); } @Override public boolean isFile(String path, String revStr) throws SVNException { return isFile(path, Long.valueOf(revStr)); } @Override public boolean renameTo(String projectName) { return move(this.ownerName, this.projectName, this.ownerName, projectName); } @Override public String getDefaultBranch() throws IOException { return "HEAD"; } @Override public void setDefaultBranch(String target) throws IOException { } @Override public Commit getParentCommitOf(String revNumber) { Long rev = Long.parseLong(revNumber) - 1; try { return getCommit(rev.toString()); } catch (Exception e) { throw new RuntimeException(e); } } @Override public boolean isEmpty() { SVNURL svnURL; org.tmatesoft.svn.core.io.SVNRepository repository = null; try { svnURL = SVNURL.fromFile(new File(repoPrefix + ownerName + "/" + projectName)); repository = SVNRepositoryFactory.create(svnURL); return repository.getLatestRevision() == 0; } catch (SVNException e) { throw new RuntimeException(e); } finally { if (repository != null) { repository.closeSession(); } } } public boolean move(String srcProjectOwner, String srcProjectName, String desrProjectOwner, String destProjectName) { File src = new File(getRepoPrefix() + srcProjectOwner + "/" + srcProjectName); File dest = new File(getRepoPrefix() + desrProjectOwner + "/" + destProjectName); src.setWritable(true); try { if (src.exists()) { FileUtils.moveDirectory(src, dest); } return true; } catch (IOException e) { play.Logger.error("Move Failed", e); return false; } } @Override public File getDirectory() { return new File(getRepoPrefix() + ownerName + "/" + projectName); } }