001: package ru.emdev.EmForge.svn.web;
002:
003: import java.text.DecimalFormat;
004: import java.util.Calendar;
005: import java.util.Collection;
006: import java.util.Iterator;
007: import java.util.TimeZone;
008:
009: import org.apache.commons.lang.StringUtils;
010: import org.tmatesoft.svn.core.SVNDirEntry;
011: import org.tmatesoft.svn.core.SVNException;
012: import org.tmatesoft.svn.core.SVNLogEntry;
013: import org.tmatesoft.svn.core.SVNNodeKind;
014: import org.tmatesoft.svn.core.io.SVNRepository;
015:
016: /**
017: * Helper class to the svn browser
018: *
019: * @author Walter Mourao
020: *
021: */
022: public class Helper {
023:
024: /**
025: * Extracts the file name from the file path
026: *
027: * @param filePath
028: * the fully qualified file path
029: * @return the fille name extracted from the path
030: */
031: static public String fileNameFromFilePath(String filePath) {
032: final int slashPos = filePath.lastIndexOf('/');
033: final String fileName;
034: if (slashPos < 0)
035: fileName = filePath;
036: else
037: fileName = filePath.substring(slashPos + 1);
038:
039: return fileName;
040: }
041:
042: /**
043: * Extract the path from the fully qualified file path
044: *
045: * @param filePath
046: * the fully qualified file path
047: * @return the path without the file name
048: */
049: static public String dirPathFromFilePath(String filePath) {
050: final int slashPos = filePath.lastIndexOf('/');
051: final String dirPath;
052: if (slashPos < 0)
053: dirPath = "/";
054: else if (filePath.startsWith("/"))
055: dirPath = filePath.substring(1, slashPos + 1);
056: else
057: dirPath = filePath.substring(0, slashPos + 1);
058:
059: return dirPath;
060: }
061:
062: /**
063: * Transforms the url parameter "revision" into subversion revision
064: *
065: * @param revision
066: * the revision as Long (can be null)
067: * @return the subversion revision, -1 if the parameter revision was null
068: */
069: static public long getCurrentRevision(Long revision) {
070: if (revision == null)
071: return -1;
072: else
073: return revision.longValue();
074: }
075:
076: /**
077: * Rounds a double to only one decimal digit
078: *
079: * @param value
080: * the original value
081: * @return the rounded value
082: */
083: static private double round1Digit(double value) {
084: return new Double((long) Math.round(value * 10)).doubleValue() / 10;
085: }
086:
087: /**
088: * Formats the size to the text format
089: *
090: * @param sz
091: * the size
092: * @return a string in the form "xxx bytes", "yyy kbytes" and so on
093: */
094: static public String formatSize(final long sz) {
095: DecimalFormat fmt = new DecimalFormat("#,###,###.#");
096: fmt.setMaximumFractionDigits(1);
097: fmt.setMinimumFractionDigits(0);
098: fmt.setMinimumIntegerDigits(1);
099:
100: double dsz = sz;
101:
102: if (sz > 1024000000) {
103: return fmt.format(round1Digit(dsz / 1024000000)) + " gB";
104: } else if (sz > 1024000) {
105: return fmt.format(round1Digit(dsz / 1024000)) + " mB";
106: } else if (sz > 1024)
107: return fmt.format(round1Digit(dsz / 1024)) + " kB";
108: else
109: return fmt.format(sz) + " bytes";
110: }
111:
112: /**
113: * Formats a date to a text format
114: *
115: * @param entryDate
116: * the date to be formatted
117: * @return a text in the format "xx days ago", "yy months ago" and so on
118: */
119: static public String formatAge(final java.util.Date entryDate) {
120:
121: final String age;
122:
123: final java.util.Calendar now = java.util.Calendar.getInstance();
124:
125: final java.util.GregorianCalendar entryCal = new java.util.GregorianCalendar();
126: entryCal.setTime(entryDate);
127:
128: final java.util.Calendar diff = new java.util.GregorianCalendar();
129: TimeZone zeroZone = TimeZone.getDefault();
130: zeroZone.setRawOffset(0);
131: diff.setTimeZone(zeroZone);
132: diff.setTimeInMillis(now.getTimeInMillis()
133: - entryCal.getTimeInMillis());
134:
135: final int years = diff.get(Calendar.YEAR) - 1970;
136: if (years > 0)
137: age = String.valueOf(years) + " year"
138: + (years > 1 ? "s" : "");
139: else {
140: final int months = diff.get(Calendar.MONTH);// -ref.get(Calendar.MONTH);
141: if (months > 0)
142: age = String.valueOf(months) + " month"
143: + (months > 1 ? "s" : "");
144: else {
145: final int days = diff.get(Calendar.DAY_OF_MONTH);// -ref.get(Calendar.DAY_OF_MONTH);
146: if (days > 0)
147: age = String.valueOf(days) + " day"
148: + (days > 1 ? "s" : "");
149: else {
150: final int hours = diff.get(Calendar.HOUR_OF_DAY);// -ref.get(Calendar.HOUR_OF_DAY);
151: if (hours > 0)
152: age = String.valueOf(hours) + " hour"
153: + (hours > 1 ? "s" : "");
154: else {
155: final int minutes = diff.get(Calendar.MINUTE);// -ref.get(Calendar.MINUTE);
156: if (minutes > 0)
157: age = String.valueOf(minutes) + " minute"
158: + (minutes > 1 ? "s" : "");
159: else {
160: final int seconds = diff
161: .get(Calendar.SECOND);// -ref.get(Calendar.SECOND);
162: if (seconds > 0)
163: age = String.valueOf(seconds)
164: + " second"
165: + (seconds > 1 ? "s" : "");
166: else
167: age = "0 seconds";
168: }
169: }
170: }
171: }
172: }
173:
174: return age;
175: }
176:
177: /**
178: * Read a repository directory
179: *
180: * @param repository
181: * the subversion repository
182: * @param path
183: * the directory path
184: * @param revision
185: * the revision to be used
186: * @return a list of file/directories entries
187: * @throws SVNException
188: */
189: static public SvnDataVO[] listEntries(SVNRepository repository,
190: String path, long revision) throws SVNException {
191:
192: final Collection entries = new java.util.ArrayList();
193:
194: repository.getDir(path, revision, true, entries);
195:
196: final int numEntries = entries.size();
197:
198: final SvnDataVO[] ret = new SvnDataVO[numEntries];
199:
200: int i = 0;
201: final Iterator iterator = entries.iterator();
202: while (iterator.hasNext()) {
203: final SVNDirEntry entry = (SVNDirEntry) iterator.next();
204:
205: final SvnDataVO svnData = new SvnDataVO();
206: svnData.setKind(entry.getKind().toString());
207:
208: svnData.setAge(formatAge(entry.getDate()));
209: svnData.setDate(entry.getDate());
210:
211: StringBuffer comment = new StringBuffer(entry.getAuthor()
212: + ": " + entry.getCommitMessage());
213: svnData.setLastChange(comment.toString());
214:
215: svnData.setAuthor(entry.getAuthor());
216: svnData.setCommitMessage(entry.getCommitMessage());
217:
218: svnData.setName(entry.getName());
219: svnData.setRevision(String.valueOf(entry.getRevision()));
220:
221: // directories doesn't have size
222: if (entry.getKind() == SVNNodeKind.FILE) {
223: svnData.setStrSize(formatSize(entry.getSize()));
224: svnData.setSize(entry.getSize());
225: }
226:
227: if (StringUtils.isEmpty(path) || path.equals("/"))
228: svnData.setPath(entry.getRelativePath());
229: else
230: svnData.setPath(path + entry.getRelativePath());
231:
232: ret[i++] = svnData;
233: }
234:
235: return ret;
236: }
237:
238: /**
239: * Filters the user properties from the internal subversion properties
240: *
241: * @param key
242: * the property key
243: * @return true if the property is a user property, false if not
244: */
245: static public boolean isUserProperty(String key) {
246: return key.startsWith("svn:")
247: && key.substring(4).indexOf(':') == -1;
248: }
249:
250: /**
251: * Reads log entries from a subversion file or directory
252: *
253: * @param repository
254: * the subversion repository
255: * @param path
256: * the directory/file path
257: * @param startRevision
258: * the starting log entry revision
259: * @param endRevision
260: * the ending log entry revision
261: * @param changedPath
262: * true if the list of changed files must be retrieved
263: * @return the desired log entries
264: * @throws SVNException
265: */
266: @SuppressWarnings("unchecked")
267: static public Collection<SVNLogEntry> getLogEntries(
268: final SVNRepository repository, final String path,
269: final long startRevision, final long endRevision,
270: final boolean changedPath) throws SVNException {
271:
272: return (Collection<SVNLogEntry>) repository.log(
273: new String[] { path }, null, startRevision,
274: endRevision, changedPath, false);
275: }
276:
277: /** Checks, is specified path directory or file
278: *
279: */
280: static public Boolean isDirectory(SVNRepository repository,
281: String path, long revision) throws SVNException {
282: SVNDirEntry info = repository.info(path, revision);
283:
284: if (info != null && info.getKind() == SVNNodeKind.DIR) {
285: return true;
286: } else {
287: return false;
288: }
289: }
290: }
|