16
16
17
17
package org .jivesoftware .openfire .archive ;
18
18
19
- import java .awt .Color ;
20
- import java .io .ByteArrayOutputStream ;
21
- import java .net .URL ;
22
- import java .util .Arrays ;
23
- import java .util .Collection ;
24
- import java .util .Enumeration ;
25
- import java .util .HashMap ;
26
- import java .util .Iterator ;
27
- import java .util .List ;
28
- import java .util .Map ;
29
- import java .util .concurrent .Future ;
30
-
31
- import org .dom4j .DocumentHelper ;
19
+ import com .itextpdf .io .font .constants .StandardFonts ;
20
+ import com .itextpdf .io .image .ImageData ;
21
+ import com .itextpdf .io .image .ImageDataFactory ;
22
+ import com .itextpdf .kernel .colors .Color ;
23
+ import com .itextpdf .kernel .colors .ColorConstants ;
24
+ import com .itextpdf .kernel .colors .DeviceRgb ;
25
+ import com .itextpdf .kernel .events .Event ;
26
+ import com .itextpdf .kernel .events .IEventHandler ;
27
+ import com .itextpdf .kernel .events .PdfDocumentEvent ;
28
+ import com .itextpdf .kernel .font .PdfFontFactory ;
29
+ import com .itextpdf .kernel .geom .PageSize ;
30
+ import com .itextpdf .kernel .geom .Rectangle ;
31
+ import com .itextpdf .kernel .pdf .PdfDocument ;
32
+ import com .itextpdf .kernel .pdf .PdfPage ;
33
+ import com .itextpdf .kernel .pdf .PdfWriter ;
34
+ import com .itextpdf .kernel .pdf .canvas .PdfCanvas ;
35
+ import com .itextpdf .kernel .pdf .canvas .draw .SolidLine ;
36
+ import com .itextpdf .kernel .pdf .xobject .PdfImageXObject ;
37
+ import com .itextpdf .layout .Document ;
38
+ import com .itextpdf .layout .element .Paragraph ;
39
+ import com .itextpdf .layout .element .Text ;
40
+ import com .itextpdf .layout .property .Leading ;
41
+ import com .itextpdf .layout .property .Property ;
32
42
import org .jivesoftware .openfire .XMPPServer ;
33
43
import org .jivesoftware .openfire .plugin .MonitoringPlugin ;
34
44
import org .jivesoftware .openfire .user .UserManager ;
40
50
import org .slf4j .LoggerFactory ;
41
51
import org .xmpp .packet .JID ;
42
52
43
- import com .lowagie .text .Chunk ;
44
- import com .lowagie .text .Document ;
45
- import com .lowagie .text .DocumentException ;
46
- import com .lowagie .text .Font ;
47
- import com .lowagie .text .FontFactory ;
48
- import com .lowagie .text .Image ;
49
- import com .lowagie .text .PageSize ;
50
- import com .lowagie .text .Paragraph ;
51
- import com .lowagie .text .pdf .PdfContentByte ;
52
- import com .lowagie .text .pdf .PdfPageEventHelper ;
53
- import com .lowagie .text .pdf .PdfWriter ;
54
- import org .xmpp .packet .Message ;
53
+ import java .io .ByteArrayOutputStream ;
54
+ import java .io .IOException ;
55
+ import java .net .URL ;
56
+ import java .util .*;
57
+ import java .util .concurrent .Future ;
55
58
56
59
/**
57
60
* Utility class for asynchronous web calls for archiving tasks.
@@ -135,29 +138,23 @@ public Map<String, ConversationInfo> getConversations(boolean formatParticipants
135
138
return cons ;
136
139
}
137
140
138
- public ByteArrayOutputStream getConversationPDF (Conversation conversation ) {
139
- Font red = FontFactory
140
- .getFont (FontFactory .HELVETICA , 12f , Font .BOLD , new Color (0xFF , 0x00 , 0x00 ));
141
- Font blue = FontFactory
142
- .getFont (FontFactory .HELVETICA , 12f , Font .ITALIC , new Color (0x00 , 0x00 , 0xFF ));
143
- Font black = FontFactory .getFont (FontFactory .HELVETICA , 12f , Font .BOLD , Color .BLACK );
144
-
145
- Map <String , Font > colorMap = new HashMap <String , Font >();
141
+ public ByteArrayOutputStream getConversationPDF (Conversation conversation ) throws IOException {
142
+ Map <JID , Color > colorMap = new HashMap <>();
146
143
if (conversation != null ) {
147
144
Collection <JID > set = conversation .getParticipants ();
148
145
int count = 0 ;
149
146
for (JID jid : set ) {
150
147
if (conversation .getRoom () == null ) {
151
148
if (count == 0 ) {
152
- colorMap .put (jid . toString (), blue );
149
+ colorMap .put (jid , ColorConstants . BLUE );
153
150
}
154
151
else {
155
- colorMap .put (jid . toString (), red );
152
+ colorMap .put (jid , ColorConstants . RED );
156
153
}
157
154
count ++;
158
155
}
159
156
else {
160
- colorMap .put (jid . toString (), black );
157
+ colorMap .put (jid , ColorConstants . BLACK );
161
158
}
162
159
}
163
160
}
@@ -166,28 +163,28 @@ public ByteArrayOutputStream getConversationPDF(Conversation conversation) {
166
163
return buildPDFContent (conversation , colorMap );
167
164
}
168
165
169
- private ByteArrayOutputStream buildPDFContent (Conversation conversation ,
170
- Map <String , Font > colorMap ) {
171
- Font roomEvent = FontFactory
172
- .getFont (FontFactory .HELVETICA , 12f , Font .ITALIC , new Color (0xFF , 0x00 , 0xFF ));
166
+ private ByteArrayOutputStream buildPDFContent (Conversation conversation , Map <JID , Color > colorMap ) throws IOException {
173
167
174
- try {
175
- Document document = new Document (PageSize .A4 , 50 , 50 , 50 , 50 );
176
- ByteArrayOutputStream baos = new ByteArrayOutputStream ();
177
- PdfWriter writer = PdfWriter .getInstance (document , baos );
178
- writer .setPageEvent (new PDFEventListener ());
179
- document .open ();
168
+ try ( final ByteArrayOutputStream baos = new ByteArrayOutputStream ();
169
+ final PdfWriter writer = new PdfWriter (baos );
170
+ final PdfDocument pdfDocument = new PdfDocument (writer )
171
+ )
172
+ {
173
+ pdfDocument .setDefaultPageSize ( PageSize .A4 );
174
+ final Document document = new Document (pdfDocument );
180
175
176
+ pdfDocument .addEventHandler (PdfDocumentEvent .END_PAGE , new PDFEventListener (document ));
177
+ document .setProperty (Property .LEADING , new Leading (Leading .MULTIPLIED , 1.0f ));
181
178
182
- Paragraph p = new Paragraph (
183
- LocaleUtils .getLocalizedString ("archive.search.pdf.title" , MonitoringConstants .NAME ),
184
- FontFactory .getFont (FontFactory .HELVETICA ,
185
- 18 , Font .BOLD ));
186
- document .add (p );
187
- document .add (Chunk .NEWLINE );
179
+ document .add ( new Paragraph () );
180
+ document .add (
181
+ new Paragraph ( LocaleUtils .getLocalizedString ("archive.search.pdf.title" , MonitoringConstants .NAME ) )
182
+ .setFont (PdfFontFactory .createFont (StandardFonts .HELVETICA_BOLD ))
183
+ .setFontSize ( 18 )
184
+ );
185
+ document .add ( new Paragraph ().add (new Text ("\n " )) );
188
186
189
- ConversationInfo coninfo = new ConversationUtils ()
190
- .getConversationInfo (conversation .getConversationID (), false );
187
+ final ConversationInfo coninfo = new ConversationUtils ().getConversationInfo (conversation .getConversationID (), false );
191
188
192
189
String participantsDetail ;
193
190
if (coninfo .getAllParticipants () == null ) {
@@ -197,48 +194,20 @@ private ByteArrayOutputStream buildPDFContent(Conversation conversation,
197
194
participantsDetail = String .valueOf (coninfo .getAllParticipants ().length );
198
195
}
199
196
200
- Paragraph chapterTitle = new Paragraph (
201
- LocaleUtils
202
- .getLocalizedString ("archive.search.pdf.participants" , MonitoringConstants .NAME ) +
203
- " " + participantsDetail ,
204
- FontFactory .getFont (FontFactory .HELVETICA , 12 ,
205
- Font .BOLD ));
206
-
207
- document .add (chapterTitle );
208
-
209
-
210
- Paragraph startDate = new Paragraph (
211
- LocaleUtils .getLocalizedString ("archive.search.pdf.startdate" , MonitoringConstants .NAME ) +
212
- " " +
213
- coninfo .getDate (),
214
- FontFactory .getFont (FontFactory .HELVETICA , 12 ,
215
- Font .BOLD ));
216
- document .add (startDate );
217
-
218
-
219
- Paragraph duration = new Paragraph (
220
- LocaleUtils .getLocalizedString ("archive.search.pdf.duration" , MonitoringConstants .NAME ) +
221
- " " +
222
- coninfo .getDuration (),
223
- FontFactory .getFont (FontFactory .HELVETICA , 12 ,
224
- Font .BOLD ));
225
- document .add (duration );
226
-
227
-
228
- Paragraph messageCount = new Paragraph (
229
- LocaleUtils
230
- .getLocalizedString ("archive.search.pdf.messagecount" , MonitoringConstants .NAME ) +
231
- " " +
232
- conversation .getMessageCount (),
233
- FontFactory .getFont (FontFactory .HELVETICA , 12 ,
234
- Font .BOLD ));
235
- document .add (messageCount );
236
- document .add (Chunk .NEWLINE );
237
-
197
+ document .add (
198
+ new Paragraph ( LocaleUtils .getLocalizedString ("archive.search.pdf.participants" , MonitoringConstants .NAME ) + " " + participantsDetail + '\n' )
199
+ .add ( LocaleUtils .getLocalizedString ("archive.search.pdf.startdate" , MonitoringConstants .NAME ) + " " + coninfo .getDate () + '\n' )
200
+ .add ( LocaleUtils .getLocalizedString ("archive.search.pdf.duration" , MonitoringConstants .NAME ) + " " + coninfo .getDuration () + '\n' )
201
+ .add ( LocaleUtils .getLocalizedString ("archive.search.pdf.messagecount" , MonitoringConstants .NAME ) + " " + conversation .getMessageCount () + '\n' )
202
+ .setFont (PdfFontFactory .createFont (StandardFonts .HELVETICA_BOLD ))
203
+ .setFontSize (12 )
204
+ );
238
205
239
- Paragraph messageParagraph ;
206
+ document . add ( new Paragraph (). add ( new Text ( " \n " ))) ;
240
207
241
- for (ArchivedMessage message : conversation .getMessages ()) {
208
+ final Paragraph messageParagraph = new Paragraph ();
209
+ for (ArchivedMessage message : conversation .getMessages ())
210
+ {
242
211
String time = JiveGlobals .formatTime (message .getSentDate ());
243
212
String from = message .getFromJID ().getNode ();
244
213
String to = message .getIsPMforNickname (); // Only non-null when this is a Private Message sent in a MUC.
@@ -247,34 +216,38 @@ private ByteArrayOutputStream buildPDFContent(Conversation conversation,
247
216
}
248
217
String body = message .getBody ();
249
218
String prefix ;
219
+
250
220
if (!message .isRoomEvent ()) {
251
221
if (to == null ) {
252
222
prefix = "[" + time + "] " + from + ": " ;
253
223
} else {
254
224
prefix = "[" + time + "] " + from + " -> " + to + ": " ;
255
225
}
256
- Font font = colorMap .get (message .getFromJID (). toString ());
257
- if (font == null ) {
258
- font = colorMap .get (message .getFromJID ().toBareJID ());
226
+ Color color = colorMap .get (message .getFromJID ());
227
+ if (color == null ) {
228
+ color = colorMap .get (message .getFromJID ().asBareJID ());
259
229
}
260
- if (font == null ) {
261
- font = FontFactory . getFont ( FontFactory . HELVETICA , 12f , Font . BOLD , Color . BLACK ) ;
230
+ if (color == null ) {
231
+ color = ColorConstants . BLACK ;
262
232
}
263
- messageParagraph = new Paragraph (new Chunk (prefix , font ));
233
+
234
+ messageParagraph .add (new Text (prefix ).setFont (PdfFontFactory .createFont (StandardFonts .HELVETICA_BOLD )).setFontColor (color ));
235
+ messageParagraph .add (new Text (body ).setFontColor (ColorConstants .BLACK ));
264
236
}
265
237
else {
266
238
prefix = "[" + time + "] " ;
267
- messageParagraph = new Paragraph (new Chunk (prefix , roomEvent ));
239
+ messageParagraph .add ( new Text (prefix )).setFont (PdfFontFactory .createFont (StandardFonts .HELVETICA_OBLIQUE )).setFontColor (ColorConstants .MAGENTA );
240
+ messageParagraph .add ( new Text (body ).setFont (PdfFontFactory .createFont (StandardFonts .HELVETICA_OBLIQUE )).setFontColor (ColorConstants .MAGENTA ));
268
241
}
269
- messageParagraph .add (body );
270
- messageParagraph .add (" " );
271
- document .add (messageParagraph );
242
+ messageParagraph .add (new Text ("\n " ));
272
243
}
273
244
245
+ document .add (messageParagraph );
246
+
274
247
document .close ();
275
248
return baos ;
276
249
}
277
- catch (DocumentException e ) {
250
+ catch (Exception e ) {
278
251
Log .error ("error creating PDF document: " + e .getMessage (), e );
279
252
return null ;
280
253
}
@@ -393,34 +366,42 @@ private String formatJID(boolean html, JID jid) {
393
366
return formattedJID ;
394
367
}
395
368
396
- class PDFEventListener extends PdfPageEventHelper {
369
+ /**
370
+ * Writes a footer.
371
+ */
372
+ public static class PDFEventListener implements IEventHandler {
373
+ private final Document document ;
374
+
375
+ public PDFEventListener (Document document ) {
376
+ this .document = document ;
377
+ }
397
378
398
379
@ Override
399
- public void onEndPage (PdfWriter writer , Document document ) {
400
- PdfContentByte cb = writer .getDirectContent ();
401
-
380
+ public void handleEvent (Event event ) {
402
381
try {
403
- cb .setColorStroke (new Color (156 , 156 , 156 ));
404
- cb .setLineWidth (2 );
405
- cb .moveTo (document .leftMargin (), document .bottomMargin () - 5 );
406
- cb .lineTo (document .getPageSize ().width () - document .rightMargin (),
407
- document .bottomMargin () - 5 );
408
- cb .stroke ();
409
-
410
- ClassLoader classLoader = ConversationUtils .class .getClassLoader ();
411
- Enumeration <URL > providerEnum = classLoader .getResources ("images/pdf_generatedbyof.gif" );
412
- while (providerEnum .hasMoreElements ()) {
413
- Image gif = Image .getInstance (providerEnum .nextElement ());
414
- cb .addImage (gif , 221 , 0 , 0 , 28 , (int )document .leftMargin (),
415
- (int )document .bottomMargin () - 35 );
416
- }
382
+ final URL resource = ConversationUtils .class .getClassLoader ().getResource ("images/pdf_generatedbyof.gif" );
383
+ if (resource != null ) {
384
+ final ImageData imageData = ImageDataFactory .create (resource );
417
385
418
- }
419
- catch (Exception e ) {
420
- Log .error ("error drawing PDF footer: " + e .getMessage ());
421
- }
422
- cb .saveState ();
386
+ final PdfDocumentEvent docEvent = (PdfDocumentEvent ) event ;
387
+ final PdfDocument pdf = docEvent .getDocument ();
388
+ final PdfPage page = docEvent .getPage ();
389
+ final Rectangle pageSize = page .getPageSize ();
390
+ final PdfCanvas pdfCanvas = new PdfCanvas (page .getLastContentStream (), page .getResources (), pdf );
391
+ float x = document .getLeftMargin ();
392
+ float y = 4 ; // Counts from the bottom of the page.
423
393
394
+ pdfCanvas .addXObjectAt (new PdfImageXObject (imageData ), x , y );
395
+
396
+ final SolidLine line = new SolidLine (2 );
397
+ line .setColor (new DeviceRgb (156 , 156 , 156 ));
398
+ line .draw (pdfCanvas , new Rectangle (document .getLeftMargin (), document .getBottomMargin () - 2 , pageSize .getWidth () - document .getRightMargin () - document .getLeftMargin (), 2 ));
399
+
400
+ pdfCanvas .release ();
401
+ }
402
+ } catch (Exception e ) {
403
+ Log .error ("error drawing PDF footer." , e );
404
+ }
424
405
}
425
406
}
426
407
}
0 commit comments