Skip to content

Commit ebc37a4

Browse files
committed
fixes #152: Update itext to 7.1.13
No functional changes, other than that the PDFs that are generated might look slightly different.
1 parent d20378e commit ebc37a4

File tree

4 files changed

+212
-227
lines changed

4 files changed

+212
-227
lines changed

changelog.html

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ <h1>
5858
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/146'>Issue #146</a>] - Allow database used for MUC MAM to be configurable</li>
5959
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/147'>Issue #147</a>] - Allow how MUC PMs are stored to be configurable</li>
6060
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/148'>Issue #148</a>] - Database errors should cause an XMPP error</li>
61+
<li>[<a href='https://github.com/igniterealtime/openfire-monitoring-plugin/issues/152'>Issue #152</a>] - Update iText library to 7.1.13</li>
6162
</ul>
6263

6364
<p><b>2.1.0</b> -- September 10, 2020</p>

pom.xml

+9-4
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,15 @@
7979
<version>8.4.0</version>
8080
</dependency>
8181
<dependency>
82-
<groupId>com.lowagie</groupId>
83-
<artifactId>itext</artifactId>
84-
<!-- NB. Later versions are available at com.itextpdf:itextpdf but require code changes -->
85-
<version>2.0.8</version>
82+
<groupId>com.itextpdf</groupId>
83+
<artifactId>itext7-core</artifactId>
84+
<version>7.1.13</version>
85+
<type>pom</type>
86+
</dependency>
87+
<dependency>
88+
<groupId>com.orsonpdf</groupId>
89+
<artifactId>orsonpdf</artifactId>
90+
<version>1.7</version>
8691
</dependency>
8792
<dependency>
8893
<groupId>org.picocontainer</groupId>

src/java/org/jivesoftware/openfire/archive/ConversationUtils.java

+109-128
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,29 @@
1616

1717
package org.jivesoftware.openfire.archive;
1818

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;
3242
import org.jivesoftware.openfire.XMPPServer;
3343
import org.jivesoftware.openfire.plugin.MonitoringPlugin;
3444
import org.jivesoftware.openfire.user.UserManager;
@@ -40,18 +50,11 @@
4050
import org.slf4j.LoggerFactory;
4151
import org.xmpp.packet.JID;
4252

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;
5558

5659
/**
5760
* Utility class for asynchronous web calls for archiving tasks.
@@ -135,29 +138,23 @@ public Map<String, ConversationInfo> getConversations(boolean formatParticipants
135138
return cons;
136139
}
137140

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<>();
146143
if (conversation != null) {
147144
Collection<JID> set = conversation.getParticipants();
148145
int count = 0;
149146
for (JID jid : set) {
150147
if (conversation.getRoom() == null) {
151148
if (count == 0) {
152-
colorMap.put(jid.toString(), blue);
149+
colorMap.put(jid, ColorConstants.BLUE);
153150
}
154151
else {
155-
colorMap.put(jid.toString(), red);
152+
colorMap.put(jid, ColorConstants.RED);
156153
}
157154
count++;
158155
}
159156
else {
160-
colorMap.put(jid.toString(), black);
157+
colorMap.put(jid, ColorConstants.BLACK);
161158
}
162159
}
163160
}
@@ -166,28 +163,28 @@ public ByteArrayOutputStream getConversationPDF(Conversation conversation) {
166163
return buildPDFContent(conversation, colorMap);
167164
}
168165

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 {
173167

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);
180175

176+
pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new PDFEventListener(document));
177+
document.setProperty(Property.LEADING, new Leading(Leading.MULTIPLIED, 1.0f));
181178

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")) );
188186

189-
ConversationInfo coninfo = new ConversationUtils()
190-
.getConversationInfo(conversation.getConversationID(), false);
187+
final ConversationInfo coninfo = new ConversationUtils().getConversationInfo(conversation.getConversationID(), false);
191188

192189
String participantsDetail;
193190
if (coninfo.getAllParticipants() == null) {
@@ -197,48 +194,20 @@ private ByteArrayOutputStream buildPDFContent(Conversation conversation,
197194
participantsDetail = String.valueOf(coninfo.getAllParticipants().length);
198195
}
199196

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+
);
238205

239-
Paragraph messageParagraph;
206+
document.add( new Paragraph().add(new Text("\n")));
240207

241-
for (ArchivedMessage message : conversation.getMessages()) {
208+
final Paragraph messageParagraph = new Paragraph();
209+
for (ArchivedMessage message : conversation.getMessages())
210+
{
242211
String time = JiveGlobals.formatTime(message.getSentDate());
243212
String from = message.getFromJID().getNode();
244213
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,
247216
}
248217
String body = message.getBody();
249218
String prefix;
219+
250220
if (!message.isRoomEvent()) {
251221
if (to == null) {
252222
prefix = "[" + time + "] " + from + ": ";
253223
} else {
254224
prefix = "[" + time + "] " + from + " -> " + to + ": ";
255225
}
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());
259229
}
260-
if (font == null) {
261-
font = FontFactory.getFont(FontFactory.HELVETICA, 12f, Font.BOLD, Color.BLACK);
230+
if (color == null) {
231+
color = ColorConstants.BLACK;
262232
}
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));
264236
}
265237
else {
266238
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));
268241
}
269-
messageParagraph.add(body);
270-
messageParagraph.add(" ");
271-
document.add(messageParagraph);
242+
messageParagraph.add(new Text("\n"));
272243
}
273244

245+
document.add(messageParagraph);
246+
274247
document.close();
275248
return baos;
276249
}
277-
catch (DocumentException e) {
250+
catch (Exception e) {
278251
Log.error("error creating PDF document: " + e.getMessage(), e);
279252
return null;
280253
}
@@ -393,34 +366,42 @@ private String formatJID(boolean html, JID jid) {
393366
return formattedJID;
394367
}
395368

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+
}
397378

398379
@Override
399-
public void onEndPage(PdfWriter writer, Document document) {
400-
PdfContentByte cb = writer.getDirectContent();
401-
380+
public void handleEvent(Event event) {
402381
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);
417385

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.
423393

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+
}
424405
}
425406
}
426407
}

0 commit comments

Comments
 (0)