001: package ru.emdev.EmForge.wiki.providers.svnprovider;
002:
003: import java.io.ByteArrayInputStream;
004: import java.io.ByteArrayOutputStream;
005: import java.io.IOException;
006: import java.io.InputStream;
007: import java.text.ParseException;
008: import java.text.SimpleDateFormat;
009: import java.util.ArrayList;
010: import java.util.Collection;
011: import java.util.Date;
012: import java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.List;
015: import java.util.Map;
016:
017: import org.apache.commons.logging.Log;
018: import org.apache.commons.logging.LogFactory;
019: import org.tmatesoft.svn.core.SVNDirEntry;
020: import org.tmatesoft.svn.core.SVNException;
021: import org.tmatesoft.svn.core.SVNLogEntry;
022: import org.tmatesoft.svn.core.SVNNodeKind;
023: import org.tmatesoft.svn.core.SVNProperty;
024: import org.tmatesoft.svn.core.io.ISVNEditor;
025: import org.tmatesoft.svn.core.io.SVNRepository;
026: import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
027:
028: import com.ecyrd.jspwiki.QueryItem;
029: import com.ecyrd.jspwiki.WikiPage;
030: import com.ecyrd.jspwiki.attachment.Attachment;
031: import com.ecyrd.jspwiki.providers.ProviderException;
032: import com.ecyrd.jspwiki.providers.WikiAttachmentProvider;
033:
034: /** Subversion attachment provider
035: *
036: */
037: public class SVNAttachmentProvider extends SvnBaseProvider implements
038: WikiAttachmentProvider {
039: protected final Log logger = LogFactory.getLog(getClass());
040:
041: public void putAttachmentData(Attachment i_att, InputStream i_data)
042: throws ProviderException, IOException {
043: String attachmentDir = getAttachmentDir(i_att.getParentName());
044: String filePath = getAttachmentPath(i_att.getParentName(),
045: i_att.getFileName());
046:
047: try {
048: SVNRepository repository = getRepository();
049:
050: SVNNodeKind nodeKind = repository.checkPath(attachmentDir,
051: -1);
052: boolean attFolderExists = false;
053: boolean attExists = false;
054:
055: if (nodeKind == SVNNodeKind.DIR) {
056: attFolderExists = true;
057: }
058:
059: nodeKind = repository.checkPath(filePath, -1);
060: if (nodeKind == SVNNodeKind.FILE) {
061: attExists = true;
062: }
063:
064: // creates editor
065: ISVNEditor editor = repository.getCommitEditor(
066: "SVNPageProvider::putPageText", null);
067:
068: editor.openRoot(-1);
069: editor.openDir(m_wikiPath, -1);
070:
071: // create attachment folder if it is required
072: if (attFolderExists) {
073: editor.openDir(attachmentDir, -1);
074: } else {
075: editor.addDir(attachmentDir, null, -1);
076: }
077:
078: // add file - or modify if attachment already exist
079: String checksum = null;
080:
081: if (attExists) {
082: editor.openFile(filePath, -1);
083:
084: editor.applyTextDelta(filePath, null);
085:
086: SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
087: checksum = deltaGenerator.sendDelta(filePath, i_data,
088: editor, true);
089: } else {
090: editor.addFile(filePath, null, -1);
091:
092: editor.applyTextDelta(filePath, null);
093:
094: SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
095: checksum = deltaGenerator.sendDelta(filePath, i_data,
096: editor, true);
097: }
098:
099: editor.closeFile(filePath, checksum);
100: editor.closeDir();
101: editor.closeDir();
102: editor.closeEdit();
103:
104: logger.debug("path for wiki page is: " + filePath);
105: } catch (SVNException ex) {
106: logger.error("Cannot put page text:", ex);
107: throw new ProviderException(
108: "SVNPageProvider::putPageText error");
109: }
110: }
111:
112: public InputStream getAttachmentData(Attachment i_att)
113: throws ProviderException, IOException {
114: String filePath = getAttachmentPath(i_att.getParentName(),
115: i_att.getFileName());
116:
117: ByteArrayOutputStream baos = new ByteArrayOutputStream();
118: Map fileProperties = new HashMap();
119:
120: try {
121: SVNRepository repository = getRepository();
122:
123: // get file contents
124: repository.getFile(filePath, i_att.getVersion(),
125: fileProperties, baos);
126:
127: } catch (SVNException ex) {
128: logger.error("Cannot put page text:", ex);
129: return null;
130: }
131:
132: return new ByteArrayInputStream(baos.toByteArray());
133: }
134:
135: @SuppressWarnings("unchecked")
136: public Collection listAttachments(WikiPage i_page)
137: throws ProviderException {
138: List result = new ArrayList();
139:
140: try {
141: SVNRepository repository = getRepository();
142:
143: String attachmentDir = getAttachmentDir(i_page.getName());
144:
145: SVNNodeKind nodeKind = repository.checkPath(attachmentDir,
146: -1);
147: if (nodeKind == SVNNodeKind.NONE) {
148: return result;
149: }
150:
151: Collection entries = repository.getDir(attachmentDir, -1,
152: null, (Collection) null);
153:
154: Iterator iterator = entries.iterator();
155: while (iterator.hasNext()) {
156: SVNDirEntry entry = (SVNDirEntry) iterator.next();
157:
158: if (entry.getKind() == SVNNodeKind.FILE) {
159:
160: // get WikiName from the file name
161: result.add(getAttachment(i_page.getName(), entry));
162: }
163: }
164:
165: } catch (SVNException ex) {
166: logger.error("Cannot get all pages:", ex);
167: throw new ProviderException(
168: "SVNPageProvider::putPageText error");
169: }
170:
171: return result;
172: }
173:
174: /** Create Attachement
175: * @param i_parentName - page name
176: * @param i_element - Repository element
177: * @return Attachment object from Repository
178: * @author spopov
179: */
180: protected Attachment getAttachment(String i_parentName,
181: SVNDirEntry i_element) {
182:
183: Attachment att = new Attachment(m_wikiEngine, i_parentName,
184: i_element.getName());
185: att.setVersion((int) i_element.getRevision());
186: att.setAuthor(i_element.getAuthor());
187: att.setLastModified(i_element.getDate());
188: att.setSize(i_element.getSize());
189:
190: return att;
191: }
192:
193: public Collection findAttachments(QueryItem[] query) {
194: // TODO Auto-generated method stub
195: return null;
196: }
197:
198: public List listAllChanged(Date timestamp) throws ProviderException {
199: // TODO Auto-generated method stub
200: return new ArrayList();
201: }
202:
203: public Attachment getAttachmentInfo(WikiPage i_page, String i_name,
204: int i_version) throws ProviderException {
205: String filePath = getAttachmentPath(i_page.getName(), i_name);
206:
207: Map fileProperties = new HashMap();
208: Attachment attachment = new Attachment(m_wikiEngine, i_page
209: .getName(), i_name);
210:
211: // fix for Blog Plugin:
212: if (i_version == 1)
213: i_version = -1;
214:
215: try {
216: logger.debug("Get information about attachment " + i_page
217: + "/" + i_name + " version " + i_version);
218:
219: SVNRepository repository = getRepository();
220:
221: // get file information
222: repository.getFile(filePath, i_version, fileProperties,
223: null);
224:
225: // set version as revision
226: Integer version = new Integer(fileProperties.get(
227: SVNProperty.COMMITTED_REVISION).toString());
228: attachment.setVersion(version);
229:
230: // set author as LAST_AUTHOR
231: attachment.setAuthor(fileProperties.get(
232: SVNProperty.LAST_AUTHOR).toString());
233: attachment.setSize(-1);
234:
235: // set date
236: SimpleDateFormat dateFormat = new SimpleDateFormat(
237: "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
238: Date lastModified = dateFormat.parse(fileProperties.get(
239: SVNProperty.COMMITTED_DATE).toString());
240: attachment.setLastModified(lastModified);
241:
242: } catch (SVNException ex) {
243: logger.error("Cannot get attachment info:", ex);
244: throw new ProviderException(
245: "SVNAttachmentProvider::getAttachmentInfo error");
246: } catch (ParseException pex) {
247: logger.error("Cannot get attachment info:", pex);
248: throw new ProviderException(
249: "SVNAttachmentProvider::getAttachmentInfo error");
250: }
251:
252: return attachment;
253: }
254:
255: public List getVersionHistory(Attachment i_att) {
256: String filePath = getAttachmentPath(i_att.getParentName(),
257: i_att.getFileName());
258: List<Attachment> result = new ArrayList<Attachment>();
259:
260: try {
261: SVNRepository repository = getRepository();
262:
263: long endRevision = repository.getLatestRevision();
264:
265: Collection logEntries = repository.log(
266: new String[] { filePath }, null, 0, endRevision,
267: false, false);
268:
269: for (Iterator entries = logEntries.iterator(); entries
270: .hasNext();) {
271: SVNLogEntry logEntry = (SVNLogEntry) entries.next();
272:
273: Attachment attachment = new Attachment(m_wikiEngine,
274: i_att.getParentName(), i_att.getFileName());
275: attachment.setAuthor(logEntry.getAuthor());
276: attachment.setLastModified(logEntry.getDate());
277: attachment.setVersion((int) logEntry.getRevision());
278:
279: result.add(attachment);
280: }
281: } catch (SVNException ex) {
282: logger.error("Cannot version history:", ex);
283: //throw new ProviderException("SVNAttachmentProvider::getVersionHistory error");
284: }
285:
286: return result;
287: }
288:
289: public void deleteVersion(Attachment i_att)
290: throws ProviderException {
291: String filePath = getAttachmentPath(i_att.getParentName(),
292: i_att.getFileName());
293:
294: try {
295: deleteVersion(filePath, i_att.getVersion(),
296: "SVNAttachmentProvider::deleteVersion");
297: } catch (SVNException ex) {
298: logger.error("Cannot delete version of the attachment: ",
299: ex);
300: throw new ProviderException(
301: "Cannot delete version of the attachment: "
302: + ex.getMessage());
303: }
304: }
305:
306: public void deleteAttachment(Attachment i_att)
307: throws ProviderException {
308:
309: String filePath = getAttachmentPath(i_att.getParentName(),
310: i_att.getFileName());
311: try {
312: // delete an attachment with all version(the 2nd param : -1)
313: deleteFile(filePath,
314: "SVNAttachmentProvider::deleteAttachment");
315: } catch (SVNException ex) {
316: logger.error("Cannot delete the attachment: ", ex);
317: throw new ProviderException("Cannot delete attachment: "
318: + ex.getMessage());
319: }
320: }
321:
322: public void moveAttachmentsForPage(String oldParent,
323: String newParent) throws ProviderException {
324: // TODO Auto-generated method stub
325:
326: }
327:
328: public String getProviderInfo() {
329: return "Subversion Attchment Provider";
330: }
331: }
|