001: package ru.emdev.EmForge.wiki.providers.svnprovider;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.UnsupportedEncodingException;
006: import java.text.ParseException;
007: import java.text.SimpleDateFormat;
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.Date;
011: import java.util.HashMap;
012: import java.util.Iterator;
013: import java.util.List;
014: import java.util.Map;
015:
016: import org.apache.commons.logging.Log;
017: import org.apache.commons.logging.LogFactory;
018: import org.tmatesoft.svn.core.SVNDirEntry;
019: import org.tmatesoft.svn.core.SVNException;
020: import org.tmatesoft.svn.core.SVNLogEntry;
021: import org.tmatesoft.svn.core.SVNNodeKind;
022: import org.tmatesoft.svn.core.SVNProperty;
023: import org.tmatesoft.svn.core.io.ISVNEditor;
024: import org.tmatesoft.svn.core.io.SVNRepository;
025: import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
026:
027: import com.ecyrd.jspwiki.QueryItem;
028: import com.ecyrd.jspwiki.WikiPage;
029: import com.ecyrd.jspwiki.providers.ProviderException;
030: import com.ecyrd.jspwiki.providers.VersioningProvider;
031: import com.ecyrd.jspwiki.providers.WikiPageProvider;
032:
033: public class SVNPageProvider extends SvnBaseProvider implements
034: WikiPageProvider, VersioningProvider {
035: protected final Log logger = LogFactory.getLog(getClass());
036:
037: public void putPageText(WikiPage i_page, String i_text)
038: throws ProviderException {
039: try {
040: SVNRepository repository = getRepository();
041:
042: String filePath = getPagePath(i_page.getName());
043: logger.debug("path for wiki page is: " + filePath);
044:
045: // check - is file already exists
046: SVNNodeKind nodeKind = repository.checkPath(filePath, -1);
047: if (nodeKind == SVNNodeKind.NONE) {
048: // create page
049:
050: // creates editor
051: ISVNEditor editor = repository.getCommitEditor(
052: "SVNPageProvider::putPageText", null);
053:
054: // create new file with this contenst
055: editor.openRoot(-1);
056: editor.openDir(m_wikiPath, -1);
057:
058: // file does not exists - add it
059:
060: editor.addFile(filePath, null, -1);
061: editor.applyTextDelta(filePath, null);
062:
063: SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
064: String checksum = deltaGenerator.sendDelta(filePath,
065: new ByteArrayInputStream(i_text
066: .getBytes("UTF-8")), editor, true);
067:
068: /*
069: * Closes the new added file.
070: */
071: editor.closeFile(filePath, checksum);
072:
073: /*
074: * Closes the root directory.
075: */
076: editor.closeDir();
077:
078: /*
079: * This is the final point in all editor handling. Only now all that new
080: * information previously described with the editor's methods is sent to
081: * the server for committing. As a result the server sends the new
082: * commit information.
083: */
084: editor.closeEdit();
085: logger.debug("wiki page was added:" + i_page.getName());
086: } else {
087: // modify page
088: // creates editor
089: ISVNEditor editor = repository.getCommitEditor(
090: "SVNPageProvider::putPageText", null);
091:
092: // create new file with this contenst
093: editor.openRoot(-1);
094: editor.openDir(m_wikiPath, -1);
095:
096: editor.openFile(filePath, -1);
097:
098: editor.applyTextDelta(filePath, null);
099:
100: SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
101: String checksum = deltaGenerator.sendDelta(filePath,
102: new ByteArrayInputStream(i_text
103: .getBytes("UTF-8")), editor, true);
104:
105: editor.closeFile(filePath, checksum);
106: editor.closeDir();
107: editor.closeDir();
108:
109: editor.closeEdit();
110:
111: logger.debug("wiki page was modified:"
112: + i_page.getName());
113: }
114:
115: } catch (SVNException ex) {
116: logger.error("Cannot put page text:", ex);
117: throw new ProviderException(
118: "SVNPageProvider::putPageText error");
119: } catch (UnsupportedEncodingException ex2) {
120: logger.error("Cannot put page text:", ex2);
121: throw new ProviderException(
122: "SVNPageProvider::putPageText error");
123: }
124: }
125:
126: public boolean pageExists(String i_page) {
127: return pageExists(i_page, -1);
128: }
129:
130: public boolean pageExists(String i_page, int i_version) {
131: //first - try to get value from cache
132: String filePath = getPagePath(i_page);
133:
134: SVNNodeKind nodeKind = SVNNodeKind.NONE;
135: try {
136: SVNRepository repository = getRepository();
137:
138: logger.debug("Check is page exists " + i_page + " version "
139: + i_version);
140: // check - is file already exists
141: nodeKind = repository.checkPath(filePath, i_version);
142: } catch (SVNException ex) {
143: logger.error("Cannot get pageExists info:", ex);
144: }
145:
146: return nodeKind == SVNNodeKind.FILE;
147: }
148:
149: public Collection findPages(QueryItem[] query) {
150: // returns empty collection
151: logger.error("Find Pages is not implemented!");
152: return null;
153: }
154:
155: /** Gets Page Info
156: *
157: * @todo Impement getting size of page
158: */
159: public WikiPage getPageInfo(String i_page, int i_version)
160: throws ProviderException {
161: if (!pageExists(i_page)) {
162: return null;
163: }
164:
165: String filePath = getPagePath(i_page);
166:
167: Map fileProperties = new HashMap();
168: WikiPage page = new WikiPage(m_wikiEngine, i_page);
169:
170: // fix for Blog Plugin:
171: if (i_version == 1)
172: i_version = -1;
173:
174: try {
175: logger.debug("Get information about page " + i_page
176: + " version " + i_version);
177:
178: SVNRepository repository = getRepository();
179:
180: // get file information
181: repository.getFile(filePath, i_version, fileProperties,
182: null);
183:
184: // set version as revision
185: Integer version = new Integer(fileProperties.get(
186: SVNProperty.COMMITTED_REVISION).toString());
187: page.setVersion(version);
188:
189: // set author as LAST_AUTHOR
190: page.setAuthor(fileProperties.get(SVNProperty.LAST_AUTHOR)
191: .toString());
192: page.setSize(-1);
193:
194: // set date
195: SimpleDateFormat dateFormat = new SimpleDateFormat(
196: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
197: Date lastModified = dateFormat.parse(fileProperties.get(
198: SVNProperty.COMMITTED_DATE).toString());
199: page.setLastModified(lastModified);
200:
201: } catch (SVNException ex) {
202: logger.error("Cannot get page info:", ex);
203: throw new ProviderException(
204: "SVNPageProvider::putPageText error");
205: } catch (ParseException pex) {
206: logger.error("Cannot get page info:", pex);
207: throw new ProviderException(
208: "SVNPageProvider::putPageText error");
209: }
210:
211: return page;
212: }
213:
214: @SuppressWarnings("unchecked")
215: public Collection getAllPages() throws ProviderException {
216: List result = new ArrayList();
217:
218: try {
219: SVNRepository repository = getRepository();
220:
221: Collection entries = repository.getDir(m_wikiPath, -1,
222: null, (Collection) null);
223:
224: Iterator iterator = entries.iterator();
225: while (iterator.hasNext()) {
226: SVNDirEntry entry = (SVNDirEntry) iterator.next();
227:
228: if (entry.getKind() == SVNNodeKind.FILE) {
229: String name = unmangleName(entry.getName());
230:
231: // get WikiName from the file name
232: WikiPage page = new WikiPage(m_wikiEngine, name);
233: page.setAuthor(entry.getAuthor());
234: page.setLastModified(entry.getDate());
235: page.setVersion((int) entry.getRevision());
236: page.setSize(entry.getSize());
237:
238: result.add(page);
239: }
240: }
241:
242: } catch (SVNException ex) {
243: logger.error("Cannot get all pages:", ex);
244: throw new ProviderException(
245: "SVNPageProvider::getAllPages error "
246: + ex.getMessage());
247: }
248:
249: return result;
250: }
251:
252: /**
253: * @todo Not implemented yet, returns empty collection for now
254: */
255: public Collection getAllChangedSince(Date date) {
256: // returns empty collection
257: return new ArrayList();
258: }
259:
260: public int getPageCount() throws ProviderException {
261: int count = 0;
262: try {
263: SVNRepository repository = getRepository();
264: Collection entries = repository.getDir(m_wikiPath, -1,
265: null, (Collection) null);
266:
267: count = entries.size();
268: } catch (SVNException ex) {
269: logger.error("Cannot put page text:", ex);
270: //throw new ProviderException("SVNPageProvider::putPageText error");
271: return 0;
272: }
273:
274: return count;
275: }
276:
277: @SuppressWarnings("unchecked")
278: public List getVersionHistory(String i_page)
279: throws ProviderException {
280: if (!pageExists(i_page)) {
281: return null;
282: }
283:
284: String filePath = getPagePath(i_page);
285: List result = new ArrayList();
286:
287: try {
288: SVNRepository repository = getRepository();
289:
290: long endRevision = repository.getLatestRevision();
291:
292: Collection logEntries = repository.log(
293: new String[] { filePath }, null, 0, endRevision,
294: false, false);
295:
296: for (Iterator entries = logEntries.iterator(); entries
297: .hasNext();) {
298: SVNLogEntry logEntry = (SVNLogEntry) entries.next();
299:
300: WikiPage page = new WikiPage(m_wikiEngine, i_page);
301: page.setAuthor(logEntry.getAuthor());
302: page.setLastModified(logEntry.getDate());
303: page.setVersion((int) logEntry.getRevision());
304:
305: result.add(page);
306: }
307: } catch (SVNException ex) {
308: logger.error("Cannot version history:", ex);
309: //throw new ProviderException("SVNPageProvider::putPageText error");
310: return null;
311: }
312:
313: return result;
314: }
315:
316: public String getPageText(String i_page, int i_version)
317: throws ProviderException {
318: if (!pageExists(i_page)) {
319: return null;
320: }
321:
322: String filePath = m_wikiPath + "/" + mangleName(i_page)
323: + ".txt";
324: Map fileProperties = new HashMap();
325: ByteArrayOutputStream baos = new ByteArrayOutputStream();
326:
327: try {
328: logger.debug("Get page text " + i_page + " version "
329: + i_version);
330:
331: SVNRepository repository = getRepository();
332:
333: // get file contents
334: repository.getFile(filePath, i_version, fileProperties,
335: baos);
336:
337: } catch (SVNException ex) {
338: logger.error("Cannot put page text:", ex);
339: return null;
340: }
341:
342: String result = null;
343:
344: try {
345: result = baos.toString("UTF-8");
346: } catch (UnsupportedEncodingException ex2) {
347: logger.error("Cannot get page text:", ex2);
348: throw new ProviderException(
349: "SVNPageProvider::getPageText error");
350: }
351:
352: return result;
353: }
354:
355: /** Delete Version
356: * @todo Deleting Version is not supported by Subversion Page Provider
357: */
358: public void deleteVersion(String i_pageName, int i_version)
359: throws ProviderException {
360: if (!pageExists(i_pageName)) {
361: return;
362: }
363:
364: String filePath = getPagePath(i_pageName);
365:
366: try {
367: deleteVersion(filePath, i_version,
368: "SVNPageProvider::deleteVersion");
369: } catch (SVNException ex) {
370: logger.error("Cannot delete version:", ex);
371: throw new ProviderException(
372: "SVNPageProvider::deletePage error");
373: }
374: }
375:
376: /** Delete Wiki Page
377: *
378: */
379: public void deletePage(String i_pageName) throws ProviderException {
380: if (!pageExists(i_pageName)) {
381: return;
382: }
383:
384: String filePath = getPagePath(i_pageName);
385:
386: try {
387: deleteFile(filePath, "SVNPageProvider::deletePage");
388: } catch (SVNException ex) {
389: logger.error("Cannot delete page", ex);
390: throw new ProviderException(
391: "SVNPageProvider::deletePage error");
392: }
393: }
394:
395: /** Move Wiki Page
396: *
397: * @note it is not tested - probably it is not work
398: */
399: public void movePage(String i_from, String i_to)
400: throws ProviderException {
401: if (!pageExists(i_from)) {
402: return;
403: }
404: if (pageExists(i_to)) {
405: return;
406: }
407:
408: String filePath = getPagePath(i_from);
409: String newPath = getPagePath(i_to);
410:
411: try {
412: SVNRepository repository = getRepository();
413:
414: // creates editor
415: ISVNEditor editor = repository.getCommitEditor(
416: "SVNPageProvider::putPageText", null);
417:
418: // create new file with this contenst
419: editor.openRoot(-1);
420: editor.openDir(m_wikiPath, -1);
421:
422: editor.addFile(newPath, filePath, -1);
423: editor.deleteEntry(filePath, -1);
424:
425: editor.closeDir();
426: editor.closeDir();
427:
428: editor.closeEdit();
429: } catch (SVNException ex) {
430: logger.error("Cannot move page:", ex);
431: throw new ProviderException(
432: "SVNPageProvider::movePage error");
433: }
434:
435: }
436:
437: public String getProviderInfo() {
438: // TODO Auto-generated method stub
439: return "Subversion Page Provider";
440: }
441:
442: }
|