1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package de.bea.domingo.http;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.Calendar;
29 import java.util.Iterator;
30 import java.util.List;
31
32 import javax.xml.parsers.ParserConfigurationException;
33 import javax.xml.parsers.SAXParser;
34
35 import org.apache.commons.httpclient.HttpStatus;
36 import org.xml.sax.Attributes;
37 import org.xml.sax.SAXException;
38
39 import de.bea.domingo.DBase;
40 import de.bea.domingo.DBaseItem;
41 import de.bea.domingo.DDatabase;
42 import de.bea.domingo.DDocument;
43 import de.bea.domingo.DItem;
44 import de.bea.domingo.DNotesMonitor;
45 import de.bea.domingo.DNotesRuntimeException;
46 import de.bea.domingo.DView;
47
48 /***
49 * Http implementation of a Domingo document.
50 *
51 * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
52 */
53 public final class DocumentHttp extends BaseDocumentHttp implements DDocument {
54
55 /*** Value for item <tt>tmpSendOptions</tt>: Indicates to only send when sending a document. */
56 private static final String SEND = "1";
57
58 /*** Value for item <tt>tmpSendOptions</tt>: Indicates to also save when sending a document. */
59 private static final String SEND_AND_SAVE = "2";
60
61 /*** Value for item <tt>tmpSendOptions</tt>: Indicates to also only save as draft save when sending a document. */
62 private static final String SEND_SAVE_AS_DRAFT = "3";
63
64 /*** serial version ID for serialization. */
65 private static final long serialVersionUID = 1484836582323425207L;
66
67 private String fUniversalId;
68
69 private boolean fResponse;
70
71 private boolean fEncryptOnSend;
72
73 private boolean fSaveOnSend;
74
75 private boolean fSignOnSend;
76
77 private String fParentDocumentUNID;
78
79 private boolean fNewNote;
80
81 private boolean fSignOnSave;
82
83 /***
84 * Private Constructor for this class.
85 *
86 * @param factory the controlling factory
87 * @param parent the parent object
88 * @param unid the universal ID of the document
89 * @param monitor the monitor that handles logging
90 * @see lotus.domino.Database
91 */
92 protected DocumentHttp(final NotesHttpFactory factory, final DBase parent, final String unid, final DNotesMonitor monitor) {
93 super(factory, parent, unid, monitor);
94 this.fUniversalId = unid;
95 if (unid != null && unid.length() > 0) {
96 readDocument();
97 }
98 fResponse = hasItem("$Ref");
99 fParentDocumentUNID = getItemValueString("$Ref");
100 fEncryptOnSend = "1".equals(getItemValueString("Encrypt"));
101 fSaveOnSend = "1".equals(getItemValueString("SaveOptions"));
102 fSignOnSend = "1".equals(getItemValueString("Sign"));
103 fNewNote = false;
104 }
105
106 /***
107 * Private Constructor for this class.
108 *
109 * @param factory the controlling factory
110 * @param parent the parent object
111 * @param monitor the monitor that handles logging
112 * @see lotus.domino.Database
113 */
114 protected DocumentHttp(final NotesHttpFactory factory, final DBase parent, final DNotesMonitor monitor) {
115 super(factory, parent, monitor);
116 this.fUniversalId = "";
117 fNewNote = true;
118 }
119
120 /***
121 * Factory method for instances of this class.
122 *
123 * @param theFactory the controlling factory
124 * @param theParent the session that produced the database
125 * @param unid the universal id of a Notes document
126 * @param monitor the monitor that handles logging
127 *
128 * @return Returns a DDatabase instance of type DatabaseProxy
129 */
130 static DDocument getInstance(final NotesHttpFactory theFactory, final DBase theParent, final String unid,
131 final DNotesMonitor monitor) {
132 return new DocumentHttp(theFactory, theParent, unid, monitor);
133 }
134
135 /***
136 * Factory method for instances of this class.
137 *
138 * @param factory the controlling factory
139 * @param parent the session that produced the database
140 * @param monitor the monitor that handles logging
141 *
142 * @return Returns a DDatabase instance of type DatabaseProxy
143 */
144 static DDocument getInstance(final NotesHttpFactory factory, final DBase parent,
145 final DNotesMonitor monitor) {
146 return new DocumentHttp(factory, parent, monitor);
147 }
148
149 private void readDocument() {
150 if (getDSession().isDomingoAvailable()) {
151 readDocumentByXML();
152 } else {
153 readDocumentByHtml();
154 }
155 }
156
157 /***
158 * Reads a document in HTML format directly from the Http server.
159 */
160 private void readDocumentByHtml() {
161 BaseHttp parent = getParent();
162 String viewName;
163 if (parent instanceof DView) {
164 viewName = ((DView) parent).getName();
165 parent = parent.getParent();
166 } else {
167 viewName = "0";
168 }
169 if (!(parent instanceof DDatabase)) {
170 throw new NotesHttpRuntimeException("Unsupported parent: " + parent.getClass().getName());
171 }
172 String databaseName = ((DDatabase) parent).getFileName();
173 String url = databaseName + "/" + viewName + "/" + this.fUniversalId + "?EditDocument" + "?OpenDocument";
174 try {
175 final String bs = executeUrl(url);
176 } catch (IOException e) {
177 throw new NotesHttpRuntimeException(e);
178 }
179 }
180
181 /***
182 * Reads a document in XML format from the Domingo database.
183 */
184 private void readDocumentByXML() {
185 try {
186 final String bs = execute("cmd=ReadDocument&unid=" + fUniversalId);
187 final SAXParser parser = getDSession().getFactory().getSAXParserFactory().newSAXParser();
188 final DocumentParser documentParser = new DocumentParser();
189 parser.parse(new ByteArrayInputStream(bs.getBytes()), documentParser);
190 } catch (IOException e) {
191 throw new NotesHttpRuntimeException(e);
192 } catch (ParserConfigurationException e) {
193 throw new NotesHttpRuntimeException(e);
194 } catch (SAXException e) {
195 throw new NotesHttpRuntimeException(e);
196 }
197 }
198
199 /***
200 * {@inheritDoc}
201 *
202 * @see de.bea.domingo.DDocument#isNewNote()
203 */
204 public boolean isNewNote() {
205 return fNewNote;
206 }
207
208 /***
209 * {@inheritDoc}
210 *
211 * @see de.bea.domingo.DDocument#getUniversalID()
212 */
213 public String getUniversalID() {
214 return fUniversalId;
215 }
216
217 /***
218 * {@inheritDoc}
219 *
220 * @see de.bea.domingo.DDocument#getNoteID()
221 */
222 public String getNoteID() {
223 throw new UnsupportedOperationException("getNoteID()");
224 }
225
226 /***
227 * {@inheritDoc}
228 * @throws IOException
229 *
230 * @see de.bea.domingo.DBaseDocument#save(boolean, boolean)
231 */
232 public boolean save(final boolean force, final boolean makeresponse) throws DNotesRuntimeException {
233 final String path = getParentDatabase().getFilePath();
234 final String args = "&sign=" + fSignOnSave;
235 final String object = isNewNote() ? ((DItem) getFirstItem("Form")).getValueString() : getUniversalID();
236 final String command = isNewNote() ? "CreateDocument" : "SaveDocument";
237 final String pathInfo = path + "/" + object + "?" + command + args;
238 final DominoPostMethod method = getDSession().createPostMethod(pathInfo);
239 final Iterator itemIterator = getItems();
240 while (itemIterator.hasNext()) {
241 final DBaseItem item = (DBaseItem) itemIterator.next();
242 if (item instanceof DItem) {
243 final Iterator valueIterator = ((DItem) item).getValues().iterator();
244 while (valueIterator.hasNext()) {
245 addParameter(method, item.getName(), valueIterator.next());
246 }
247 }
248 }
249 try {
250 final int statusCode = getDSession().executeMethod(method);
251 if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_MOVED_TEMPORARILY) {
252 getMonitor().error("Http request failed: " + method.getStatusLine());
253 }
254
255 return statusCode == HttpStatus.SC_OK;
256 } catch (IOException e) {
257 getMonitor().error(e.getLocalizedMessage(), e);
258 throw new NotesHttpRuntimeException(e.getLocalizedMessage(), e);
259 } finally {
260 method.releaseConnection();
261 }
262 }
263
264 private void addParameter(final DominoPostMethod method, final String name, final Object value) {
265 if (value instanceof Calendar) {
266 method.addParameter(name, value.toString());
267 } else if (value instanceof Number) {
268 method.addParameter(name, value.toString());
269 } else if (value instanceof String) {
270 method.addParameter(name, value.toString());
271 }
272 }
273
274 /***
275 * {@inheritDoc}
276 *
277 * @see de.bea.domingo.DDocument#send(java.lang.String)
278 */
279 public void send(final String recipient) {
280 final List list = new ArrayList();
281 list.add(recipient);
282 send(list);
283 }
284
285 /***
286 * {@inheritDoc}
287 *
288 * @see de.bea.domingo.DDocument#send(java.util.List)
289 */
290 public void send(final List recipients) {
291
292 replaceItemValue("WebSubject", getItemValue("Subject"));
293 replaceItemValue("tmpSendOptions", fSaveOnSend ? SEND_AND_SAVE : SEND);
294 replaceItemValue("__Click", getItemValue("0"));
295
296
297 final String path = getParentDatabase().getFilePath();
298 final String args = "&encrypt=" + fEncryptOnSend + "&save=" + fSaveOnSend + "&sign=" + fSignOnSend;
299 try {
300
301 String result = execute(path, args);
302
303
304 getMonitor().debug(result);
305
306
307 } catch (IOException e) {
308 throw new NotesHttpRuntimeException("Cannot save document: " + e.getMessage(), e);
309 }
310 }
311
312 /***
313 * {@inheritDoc}
314 *
315 * @see de.bea.domingo.DDocument#copyToDatabase(de.bea.domingo.DDatabase)
316 */
317 public DDocument copyToDatabase(final DDatabase database) {
318 throw new UnsupportedOperationException("copyToDatabase()");
319 }
320
321 /***
322 * {@inheritDoc}
323 *
324 * @see de.bea.domingo.DDocument#isResponse()
325 */
326 public boolean isResponse() {
327 return fResponse;
328 }
329
330 /***
331 * {@inheritDoc}
332 *
333 * @see de.bea.domingo.DDocument#getParentDocumentUNID()
334 */
335 public String getParentDocumentUNID() {
336 return fParentDocumentUNID;
337 }
338
339 /***
340 * {@inheritDoc}
341 *
342 * @see de.bea.domingo.DDocument#getParentDocument()
343 */
344 public DDocument getParentDocument() {
345 return getInstance(getFactory(), getParent(), getParentDocumentUNID(), getMonitor());
346 }
347
348 /***
349 * {@inheritDoc}
350 *
351 * @see de.bea.domingo.DDocument#makeResponse(de.bea.domingo.DDocument)
352 */
353 public void makeResponse(final DDocument doc) {
354 throw new UnsupportedOperationException("makeResponse()");
355 }
356
357 /***
358 * {@inheritDoc}
359 *
360 * @see de.bea.domingo.DDocument#getResponses()
361 */
362 public Iterator getResponses() {
363 throw new UnsupportedOperationException("getResponses()");
364 }
365
366 /***
367 * {@inheritDoc}
368 *
369 * @see de.bea.domingo.DDocument#setSaveMessageOnSend(boolean)
370 */
371 public void setSaveMessageOnSend(final boolean flag) {
372 fSaveOnSend = flag;
373 }
374
375 /***
376 * {@inheritDoc}
377 *
378 * @see de.bea.domingo.DDocument#setEncryptOnSend(boolean)
379 */
380 public void setEncryptOnSend(final boolean flag) {
381 fEncryptOnSend = flag;
382 }
383
384 /***
385 * {@inheritDoc}
386 *
387 * @see de.bea.domingo.DDocument#setSignOnSend(boolean)
388 */
389 public void setSignOnSend(final boolean flag) {
390 fSignOnSend = flag;
391 }
392
393 /***
394 * {@inheritDoc}
395 *
396 * @see de.bea.domingo.DDocument#sign()
397 */
398 public void sign() {
399 fSignOnSave = true;
400 }
401
402 /***
403 * {@inheritDoc}
404 *
405 * @see de.bea.domingo.DDocument#replaceHTML(java.lang.String,
406 * java.lang.String)
407 */
408 public void replaceHTML(final String name, final String value) {
409 throw new UnsupportedOperationException("replaceHTML()");
410 }
411
412 /***
413 * {@inheritDoc}
414 *
415 * @see de.bea.domingo.DDocument#getFTSearchScore()
416 */
417 public int getFTSearchScore() {
418 throw new UnsupportedOperationException("getFTSearchScope()");
419 }
420
421 /***
422 * SAX parser for documents.
423 */
424 private class DocumentParser extends BaseHandler {
425
426 private String fName;
427
428 private boolean fNames;
429
430 private boolean fReaders;
431
432 private boolean fAuthors;
433
434 public void startElement(final String namespaceURI, final String localName, final String qName, final Attributes atts)
435 throws SAXException {
436 if ("item".equals(qName)) {
437 fName = atts.getValue("name");
438 String n = atts.getValue("names");
439 fNames = n != null && n.equals("true");
440 String r = atts.getValue("readers");
441 fReaders = r != null && r.equals("true");
442 String a = atts.getValue("authors");
443 fAuthors = a != null && a.equals("true");
444 reset();
445 } else {
446 super.startElement(namespaceURI, localName, qName, atts);
447 }
448 }
449
450 public void endElement(final String uri, final String localName, final String qName) throws SAXException {
451 if ("item".equals(qName)) {
452 final DItem item = replaceItemValue(fName, getValues());
453 item.setNames(fNames);
454 item.setReaders(fReaders);
455 item.setAuthors(fAuthors);
456 } else {
457 super.endElement(uri, localName, qName);
458 }
459 }
460 }
461
462 /***
463 * {@inheritDoc}
464 *
465 * @see de.bea.domingo.DDocument#getParentView()
466 */
467 public DView getParentView() {
468 throw new UnsupportedOperationException("not supported in Http Document");
469 }
470
471 /***
472 * {@inheritDoc}
473 *
474 * @see de.bea.domingo.DDocument#getFolderReferences()
475 */
476 public List getFolderReferences() {
477 throw new UnsupportedOperationException("not supported in Http Document");
478 }
479
480 /***
481 * {@inheritDoc}
482 *
483 * @see de.bea.domingo.DDocument#putInFolder(java.lang.String)
484 */
485 public void putInFolder(final String s) {
486 throw new UnsupportedOperationException("not supported in Http Document");
487 }
488
489 /***
490 * {@inheritDoc}
491 *
492 * @see de.bea.domingo.DDocument#putInFolder(java.lang.String, boolean)
493 */
494 public void putInFolder(final String s, final boolean flag) {
495 throw new UnsupportedOperationException("not supported in Http Document");
496 }
497
498 /***
499 * {@inheritDoc}
500 *
501 * @see de.bea.domingo.DDocument#removeFromFolder(java.lang.String)
502 */
503 public void removeFromFolder(final String s) {
504 throw new UnsupportedOperationException("not supported in Http Document");
505 }
506
507 /***
508 * {@inheritDoc}
509 *
510 * @see de.bea.domingo.DDocument#getURL()
511 */
512 public String getURL() {
513 throw new UnsupportedOperationException("not supported in Http Document");
514 }
515
516 /***
517 * {@inheritDoc}
518 *
519 * @see de.bea.domingo.DDocument#getNotesURL()
520 */
521 public String getNotesURL() {
522 throw new UnsupportedOperationException("not supported in Http Document");
523 }
524
525 /***
526 * {@inheritDoc}
527 *
528 * @see de.bea.domingo.DDocument#getHttpURL()
529 */
530 public String getHttpURL() {
531 throw new UnsupportedOperationException("not supported in Http Document");
532 }
533 }