Source code: com/xpn/xwiki/doc/XWikiAttachment.java
1 /**
2 * ===================================================================
3 *
4 * Copyright (c) 2003 Ludovic Dubost, All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details, published at
15 * http://www.gnu.org/copyleft/gpl.html or in gpl.txt in the
16 * root folder of this distribution.
17
18 * Created by
19 * User: Ludovic Dubost
20 * Date: 28 janv. 2004
21 * Time: 22:43:54
22 */
23 package com.xpn.xwiki.doc;
24
25 import com.xpn.xwiki.XWikiContext;
26 import com.xpn.xwiki.XWikiException;
27 import org.hibernate.ObjectNotFoundException;
28 import org.apache.commons.codec.binary.Base64;
29 import org.apache.commons.jrcs.rcs.Archive;
30 import org.apache.commons.jrcs.rcs.Node;
31 import org.apache.commons.jrcs.rcs.Version;
32 import org.dom4j.DocumentException;
33 import org.dom4j.Element;
34 import org.dom4j.dom.DOMElement;
35
36 import java.util.ArrayList;
37 import java.util.Date;
38 import java.util.List;
39
40 public class XWikiAttachment {
41 private XWikiDocument doc;
42
43 private int filesize;
44 private String filename;
45 private String author;
46 private Version version;
47 private String comment;
48 private Date date;
49 // Meta Data Archive
50 private Archive metaArchive;
51
52 private XWikiAttachmentContent attachment_content;
53 private XWikiAttachmentArchive attachment_archive;
54 private boolean isMetaDataDirty = false;
55
56 public XWikiAttachment(XWikiDocument doc, String filename) {
57 this();
58 setDoc(doc);
59 setFilename(filename);
60 }
61
62 public XWikiAttachment() {
63 filesize = 0;
64 filename = "";
65 author = "";
66 comment = "";
67 date = new Date();
68 }
69
70 public long getId() {
71 if (doc==null)
72 return filename.hashCode();
73 else
74 return (doc.getFullName() + "/" + filename).hashCode();
75 }
76
77 public void setDocId(long id) {
78 }
79
80 public long getDocId() {
81 return doc.getId();
82 }
83
84 public void setId(long id) {
85 }
86
87 public Object clone() {
88 XWikiAttachment attachment = null;
89 try {
90 attachment = (XWikiAttachment) getClass().newInstance();
91 } catch (Exception e) {
92 // This should not happen
93 }
94
95 attachment.setAuthor(getAuthor());
96 attachment.setComment(getComment());
97 attachment.setDate(getDate());
98 attachment.setDoc(getDoc());
99 attachment.setFilename(getFilename());
100 attachment.setFilesize(getFilesize());
101 attachment.setRCSVersion(getRCSVersion());
102 if (getAttachment_content()!=null) {
103 attachment.setAttachment_content((XWikiAttachmentContent)getAttachment_content().clone());
104 attachment.getAttachment_content().setAttachment(attachment);
105 }
106 if (getAttachment_archive()!=null) {
107 attachment.setAttachment_archive((XWikiAttachmentArchive)getAttachment_archive().clone());
108 attachment.getAttachment_archive().setAttachment(attachment);
109 }
110 return attachment;
111 }
112
113 public int getFilesize() {
114 return filesize;
115 }
116
117 public void setFilesize(int filesize) {
118 if (filesize != this.filesize) {
119 setMetaDataDirty(true);
120 }
121 this.filesize = filesize;
122 }
123
124 public String getFilename() {
125 return filename;
126 }
127
128 public void setFilename(String filename) {
129 filename = filename.replace('+',' ');
130 if (!filename.equals(this.filename)) {
131 setMetaDataDirty(true);
132 this.filename = filename;
133 }
134 }
135
136 public String getAuthor() {
137 return author;
138 }
139
140 public void setAuthor(String author) {
141 if (!author.equals(this.author)) {
142 setMetaDataDirty(true);
143 }
144 this.author = author;
145 }
146
147 public String getVersion() {
148 return getRCSVersion().toString();
149 }
150
151 public void setVersion(String version) {
152 this.version = new Version(version);
153 }
154
155 public Version getRCSVersion() {
156 if (version == null) {
157 version = new Version("1.1");
158 }
159 return version;
160 }
161
162 public void setRCSVersion(Version version) {
163 this.version = version;
164 }
165
166 public String getComment() {
167 if (!comment.equals(this.comment)) {
168 setMetaDataDirty(true);
169 }
170 return comment;
171 }
172
173 public void setComment(String comment) {
174 this.comment = comment;
175 }
176
177 public XWikiDocument getDoc() {
178 return doc;
179 }
180
181 public void setDoc(XWikiDocument doc) {
182 this.doc = doc;
183 }
184
185 public Date getDate() {
186 return date;
187 }
188
189 public void setDate(Date date) {
190 this.date = date;
191 }
192
193
194 public boolean isContentDirty() {
195 if (attachment_content==null)
196 return false;
197 else
198 return attachment_content.isContentDirty();
199 }
200
201 public void incrementVersion() {
202 if (version==null)
203 version = new Version("1.1");
204 else {
205 version = version.next();
206 }
207 }
208
209 public boolean isMetaDataDirty() {
210 return isMetaDataDirty;
211 }
212
213 public void setMetaDataDirty(boolean metaDataDirty) {
214 isMetaDataDirty = metaDataDirty;
215 }
216
217 /*
218 // This code should not be needed..
219 // Meta Data archiving is done
220 // in the main document..
221 public Archive getRCSMetaArchive() {
222 return metaArchive;
223 }
224
225 public void setRCSMetaArchive(Archive metaArchive) {
226 this.metaArchive = metaArchive;
227 }
228
229
230 public String getMetaArchive() throws XWikiException {
231 if (metaArchive==null)
232 updateMetaArchive(toXML());
233 if (metaArchive==null)
234 return "";
235 else {
236 StringBuffer buffer = new StringBuffer();
237 metaArchive.toString(buffer);
238 return buffer.toString();
239 }
240 }
241
242 public void setMetaArchive(String text) throws XWikiException {
243 try {
244 StringInputStream is = new StringInputStream(text);
245 metaArchive = new Archive(getFilename(), is);
246 }
247 catch (Exception e) {
248 Object[] args = { getFilename() };
249 throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_STORE_ATTACHMENT_ARCHIVEFORMAT,
250 "Exception while manipulating the archive for file {0}", e, args);
251 }
252 }
253
254 public void updateMetaArchive(String text) throws XWikiException {
255 try {
256 Lines lines = new Lines(text);
257 if (metaArchive!=null)
258 metaArchive.addRevision(lines.toArray(),"");
259 else
260 metaArchive = new Archive(lines.toArray(),getFilename(),getVersion());
261 }
262 catch (Exception e) {
263 Object[] args = { getFilename() };
264 throw new XWikiException( XWikiException.MODULE_XWIKI_STORE, XWikiException.ERROR_XWIKI_STORE_ARCHIVEFORMAT,
265 "Exception while manipulating the archive for file {0}", e, args);
266 }
267 }
268 */
269
270 public Element toXML() {
271 return toXML(false, false);
272 }
273
274 public Element toXML(boolean bWithAttachmentContent, boolean bWithVersions) {
275 Element docel = new DOMElement("attachment");
276 Element el = new DOMElement("filename");
277 el.addText(getFilename());
278 docel.add(el);
279
280 el = new DOMElement("filesize");
281 el.addText("" + getFilesize());
282 docel.add(el);
283
284 el = new DOMElement("author");
285 el.addText(getAuthor());
286 docel.add(el);
287
288 long d = getDate().getTime();
289 el = new DOMElement("date");
290 el.addText("" + d);
291 docel.add(el);
292
293 el = new DOMElement("version");
294 el.addText(getVersion());
295 docel.add(el);
296
297 el = new DOMElement("comment");
298 el.addText(getComment());
299 docel.add(el);
300
301 if (bWithAttachmentContent) {
302 el = new DOMElement("content");
303 XWikiAttachmentContent acontent = getAttachment_content();
304 if (acontent!=null) {
305 byte[] bcontent = getAttachment_content().getContent();
306 String content = new String(Base64.encodeBase64(bcontent));
307 el.addText(content);
308 } else {
309 el.addText("");
310 }
311 docel.add(el);
312 }
313
314 if (bWithVersions) {
315 XWikiAttachmentArchive aarchive = getAttachment_archive();
316 if (aarchive!=null) {
317 el = new DOMElement("versions");
318 try {
319 el.addText(aarchive.getArchive().toString());
320 } catch (XWikiException e) {
321 return null;
322 }
323 docel.add(el);
324 }
325 }
326
327 return docel;
328 }
329
330 public void fromXML(Element docel) throws DocumentException, java.text.ParseException, IllegalAccessException, InstantiationException, ClassNotFoundException {
331 setFilename(docel.element("filename").getText());
332 setFilesize(Integer.parseInt(docel.element("filesize").getText()));
333 setAuthor(docel.element("author").getText());
334 setVersion(docel.element("version").getText());
335 setComment(docel.element("comment").getText());
336
337 String sdate = docel.element("date").getText();
338 Date date = new Date(Long.parseLong(sdate));
339 setDate(date);
340 }
341
342 public XWikiAttachmentContent getAttachment_content() {
343 return attachment_content;
344 }
345
346 public void setAttachment_content(XWikiAttachmentContent attachment_content) {
347 this.attachment_content = attachment_content;
348 }
349
350 public XWikiAttachmentArchive getAttachment_archive() {
351 return attachment_archive;
352 }
353
354 public void setAttachment_archive(XWikiAttachmentArchive attachment_archive) {
355 this.attachment_archive = attachment_archive;
356 }
357
358 public byte[] getContent(XWikiContext context) throws XWikiException {
359 if (attachment_content==null) {
360 doc.loadAttachmentContent(this, context);
361 }
362
363 return attachment_content.getContent();
364 }
365
366 public Archive getArchive() {
367 if (attachment_archive==null)
368 return null;
369 else
370 return attachment_archive.getRCSArchive();
371 }
372
373 public void setArchive(Archive archive) {
374 if (attachment_archive==null) {
375 attachment_archive = new XWikiAttachmentArchive();
376 attachment_archive.setAttachment(this);
377 }
378 attachment_archive.setRCSArchive(archive);
379 }
380
381 public Version[] getVersions() {
382 Node[] nodes = getArchive().changeLog();
383 Version[] versions = new Version[nodes.length];
384 for (int i=0;i<nodes.length;i++) {
385 versions[i] = nodes[i].getVersion();
386 }
387 return versions;
388 }
389
390 // We assume versions go from 1.1 to the current one
391 // This allows not to read the full archive file
392 public List getVersionList() throws XWikiException {
393 List list = new ArrayList();
394 Version v = new Version("1.1");
395 while (true) {
396 list.add(v);
397 if (v.toString().equals(version.toString()))
398 break;
399 v.next();
400 }
401 return list;
402 }
403
404 public void setContent(byte[] data) {
405 if (attachment_content==null) {
406 attachment_content = new XWikiAttachmentContent();
407 attachment_content.setAttachment(this);
408 }
409 attachment_content.setContent(data);
410 }
411
412 public void updateContentArchive(XWikiContext context) throws XWikiException {
413 if (attachment_content == null)
414 return;
415
416 if (attachment_archive==null) {
417 try {
418 getDoc().getStore().loadAttachmentArchive(this, context, true);
419 } catch (XWikiException e) {
420 if (!(e.getException() instanceof ObjectNotFoundException))
421 throw e;
422 }
423 }
424
425 if (attachment_archive==null) {
426 attachment_archive = new XWikiAttachmentArchive();
427 attachment_archive.setAttachment(this);
428 }
429
430 attachment_archive.updateArchive(getContent(context));
431 }
432
433 public String getMimeType(XWikiContext context) {
434 // Choose the right content type
435 String mimetype = context.getEngineContext().getMimeType(getFilename().toLowerCase());
436 if (mimetype!=null)
437 return mimetype;
438 else
439 return "application/octet-stream";
440 }
441
442 public boolean isImage(XWikiContext context) {
443 String contenttype = getMimeType(context);
444 if (contenttype.startsWith("image/"))
445 return true;
446 else
447 return false;
448 }
449
450 }
451