Skip to content

Commit 5bfab44

Browse files
committed
Add version info to document on creation
This is done to preserve document info in case of license unloading. DITO-465
1 parent 7553a86 commit 5bfab44

File tree

4 files changed

+183
-45
lines changed

4 files changed

+183
-45
lines changed

kernel/src/main/java/com/itextpdf/kernel/Version.java

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,28 @@ public final class Version {
8585
* iText Group requests that you retain the iText producer line
8686
* in every PDF that is created or manipulated using iText.
8787
*/
88-
private String producerLine = iTextProductName + " " + release + " \u00a92000-2018 iText Group NV";
88+
private static final String producerLine = iTextProductName + " " + release + " \u00a92000-2018 iText Group NV";
8989

9090
/**
91-
* The license key.
91+
* The version info;
9292
*/
93-
private String key = null;
93+
private final VersionInfo info;
9494

9595
private boolean expired;
9696

97+
/**
98+
* @depricated Use {@link Version#getInstance()} instead. Will be removed in next major release.
99+
*/
100+
@Deprecated
101+
public Version() {
102+
this.info = new VersionInfo(iTextProductName, release, producerLine, null);
103+
}
104+
105+
private Version(VersionInfo info, boolean expired) {
106+
this.info = info;
107+
this.expired = expired;
108+
}
109+
97110
/**
98111
* Gets an instance of the iText version that is currently used.
99112
* Note that iText Group requests that you retain the iText producer line
@@ -105,19 +118,20 @@ public static Version getInstance() {
105118
return version;
106119
}
107120
}
108-
Version localVersion = new Version();
121+
Version localVersion;
122+
String key = null;
109123
try {
110124
String coreVersion = release;
111125
String[] info = getLicenseeInfoFromLicenseKey(coreVersion);
112126
if(info != null){
113127
if (info[3] != null && info[3].trim().length() > 0) {
114-
localVersion.key = info[3];
128+
key = info[3];
115129
} else {
116-
localVersion.key = "Trial version ";
130+
key = "Trial version ";
117131
if (info[5] == null) {
118-
localVersion.key += "unauthorised";
132+
key += "unauthorised";
119133
} else {
120-
localVersion.key += info[5];
134+
key += info[5];
121135
}
122136
}
123137

@@ -129,35 +143,35 @@ public static Version getInstance() {
129143
}
130144

131145
if (info[4] != null && info[4].trim().length() > 0) {
132-
localVersion.producerLine = info[4];
146+
localVersion = initVersion(info[4], key, false);
133147
} else if (info[2] != null && info[2].trim().length() > 0) {
134-
localVersion.addLicensedPostfix(info[2]);
148+
localVersion = initDefaultLicensedVersion(info[2], key);
135149
} else if (info[0] != null && info[0].trim().length() > 0) {
136150
// fall back to contact name, if company name is unavailable.
137151
// we shouldn't have a licensed version without company name,
138152
// but let's account for it anyway
139-
localVersion.addLicensedPostfix(info[0]);
153+
localVersion = initDefaultLicensedVersion(info[0], key);
140154
} else {
141-
localVersion.addAGPLPostfix(null);
155+
localVersion = initAGPLVersion(null, key);
142156
}
143157
} else {
144-
localVersion.addAGPLPostfix(null);
158+
localVersion = initAGPLVersion(null, key);
145159
}
146160
//Catch the exception
147161
} catch(LicenseVersionException lve) {
148162
//Rethrow license version exceptions
149163
throw lve;
150164
}catch(ClassNotFoundException cnfe){
151165
//License key library not on classpath, switch to AGPL
152-
localVersion.addAGPLPostfix(null);
166+
localVersion = initAGPLVersion(null, key);
153167
} catch (Exception e) {
154168
//Check if an iText5 license is loaded
155169
if(e.getCause() != null && e.getCause().getMessage().equals(LicenseVersionException.LICENSE_FILE_NOT_LOADED)) {
156170
if (isiText5licenseLoaded()) {
157171
throw new LicenseVersionException(LicenseVersionException.NO_I_TEXT7_LICENSE_IS_LOADED_BUT_AN_I_TEXT5_LICENSE_IS_LOADED);
158172
}
159173
}
160-
localVersion.addAGPLPostfix(e.getCause());
174+
localVersion = initAGPLVersion(e.getCause(), key);
161175
}
162176
return atomicSetVersion(localVersion);
163177
}
@@ -186,7 +200,7 @@ public static boolean isExpired() {
186200
* @return the product name
187201
*/
188202
public String getProduct() {
189-
return iTextProductName;
203+
return info.getProduct();
190204
}
191205

192206
/**
@@ -197,7 +211,7 @@ public String getProduct() {
197211
* @return the release number
198212
*/
199213
public String getRelease() {
200-
return release;
214+
return info.getRelease();
201215
}
202216

203217
/**
@@ -209,7 +223,7 @@ public String getRelease() {
209223
* @return iText version
210224
*/
211225
public String getVersion() {
212-
return producerLine;
226+
return info.getVersion();
213227
}
214228

215229
/**
@@ -218,24 +232,38 @@ public String getVersion() {
218232
* @return a license key.
219233
*/
220234
public String getKey() {
221-
return key;
235+
return info.getKey();
222236
}
223237

224-
private void addLicensedPostfix(String ownerName) {
225-
producerLine += " (" + ownerName;
238+
/**
239+
* Returns a version info in one class
240+
*
241+
* @return a version info.
242+
*/
243+
public VersionInfo getInfo() {
244+
return info;
245+
}
246+
247+
private static Version initDefaultLicensedVersion(String ownerName, String key) {
248+
String producer = producerLine + " (" + ownerName;
226249
if (! key.toLowerCase().startsWith("trial")) {
227-
producerLine += "; licensed version)";
250+
producer += "; licensed version)";
228251
} else {
229-
producerLine += "; " + key + ")";
252+
producer += "; " + key + ")";
230253
}
254+
return initVersion(producer, key, false);
231255
}
232256

233-
private void addAGPLPostfix(Throwable cause) {
234-
producerLine += AGPL;
257+
private static Version initAGPLVersion(Throwable cause, String key) {
258+
String producer = producerLine + AGPL;
235259

236-
if (cause != null && cause.getMessage() != null && cause.getMessage().contains("expired")) {
237-
expired = true;
238-
}
260+
boolean expired = cause != null && cause.getMessage() != null && cause.getMessage().contains("expired");
261+
262+
return initVersion(producer, key, expired);
263+
}
264+
265+
private static Version initVersion(String producer, String key, boolean expired) {
266+
return new Version(new VersionInfo(iTextProductName, release, producer, key), expired);
239267
}
240268

241269
private static Class<?> getLicenseKeyClass() throws ClassNotFoundException {
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
3+
This file is part of the iText (R) project.
4+
Copyright (c) 1998-2018 iText Group NV
5+
Authors: Bruno Lowagie, Paulo Soares, et al.
6+
7+
This program is free software; you can redistribute it and/or modify
8+
it under the terms of the GNU Affero General Public License version 3
9+
as published by the Free Software Foundation with the addition of the
10+
following permission added to Section 15 as permitted in Section 7(a):
11+
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
12+
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
13+
OF THIRD PARTY RIGHTS
14+
15+
This program is distributed in the hope that it will be useful, but
16+
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17+
or FITNESS FOR A PARTICULAR PURPOSE.
18+
See the GNU Affero General Public License for more details.
19+
You should have received a copy of the GNU Affero General Public License
20+
along with this program; if not, see http://www.gnu.org/licenses or write to
21+
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22+
Boston, MA, 02110-1301 USA, or download the license from the following URL:
23+
http://itextpdf.com/terms-of-use/
24+
25+
The interactive user interfaces in modified source and object code versions
26+
of this program must display Appropriate Legal Notices, as required under
27+
Section 5 of the GNU Affero General Public License.
28+
29+
In accordance with Section 7(b) of the GNU Affero General Public License,
30+
a covered work must retain the producer line in every PDF that is created
31+
or manipulated using iText.
32+
33+
You can be released from the requirements of the license by purchasing
34+
a commercial license. Buying such a license is mandatory as soon as you
35+
develop commercial activities involving the iText software without
36+
disclosing the source code of your own applications.
37+
These activities include: offering paid services to customers as an ASP,
38+
serving PDFs on the fly in a web application, shipping iText with a closed
39+
source product.
40+
41+
For more information, please contact iText Software Corp. at this
42+
43+
*/
44+
package com.itextpdf.kernel;
45+
46+
import java.io.Serializable;
47+
48+
public class VersionInfo implements Serializable {
49+
50+
private static final long serialVersionUID = 1514128839876564529L;
51+
52+
private final String productName;
53+
private final String releaseNumber;
54+
private final String producerLine;
55+
private final String licenseKey;
56+
57+
public VersionInfo(String productName, String releaseNumber, String producerLine, String licenseKey) {
58+
this.productName = productName;
59+
this.releaseNumber = releaseNumber;
60+
this.producerLine = producerLine;
61+
this.licenseKey = licenseKey;
62+
}
63+
64+
/**
65+
* Gets the product name.
66+
* iText Group NV requests that you retain the iText producer line
67+
* in every PDF that is created or manipulated using iText.
68+
*
69+
* @return the product name
70+
*/
71+
public String getProduct() {
72+
return productName;
73+
}
74+
75+
/**
76+
* Gets the release number.
77+
* iText Group NV requests that you retain the iText producer line
78+
* in every PDF that is created or manipulated using iText.
79+
*
80+
* @return the release number
81+
*/
82+
public String getRelease() {
83+
return releaseNumber;
84+
}
85+
86+
/**
87+
* Returns the iText version as shown in the producer line.
88+
* iText is a product developed by iText Group NV.
89+
* iText Group requests that you retain the iText producer line
90+
* in every PDF that is created or manipulated using iText.
91+
*
92+
* @return iText version
93+
*/
94+
public String getVersion() {
95+
return producerLine;
96+
}
97+
98+
/**
99+
* Returns a license key if one was provided, or null if not.
100+
*
101+
* @return a license key.
102+
*/
103+
public String getKey() {
104+
return licenseKey;
105+
}
106+
}

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfDocument.java

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ This file is part of the iText (R) project.
5151
import com.itextpdf.kernel.PdfException;
5252
import com.itextpdf.kernel.ProductInfo;
5353
import com.itextpdf.kernel.Version;
54+
import com.itextpdf.kernel.VersionInfo;
5455
import com.itextpdf.kernel.counter.EventCounterHandler;
5556
import com.itextpdf.kernel.counter.event.CoreEvent;
5657
import com.itextpdf.kernel.crypto.BadPasswordException;
@@ -197,6 +198,7 @@ public class PdfDocument implements IEventDispatcher, Closeable, Serializable {
197198
private static final AtomicLong lastDocumentId = new AtomicLong();
198199

199200
private long documentId;
201+
private VersionInfo versionInfo = Version.getInstance().getInfo();
200202

201203
/**
202204
* Yet not copied link annotations from the other documents.
@@ -324,7 +326,7 @@ public byte[] getXmpMetadata(boolean createNew) {
324326
addCustomMetadataExtensions(xmpMeta);
325327
try {
326328
xmpMeta.setProperty(XMPConst.NS_DC, PdfConst.Format, "application/pdf");
327-
xmpMeta.setProperty(XMPConst.NS_PDF, PdfConst.Producer, Version.getInstance().getVersion());
329+
xmpMeta.setProperty(XMPConst.NS_PDF, PdfConst.Producer, versionInfo.getVersion());
328330
setXmpMetadata(xmpMeta);
329331
} catch (XMPException ignored) {
330332
}
@@ -1813,19 +1815,12 @@ protected void open(PdfVersion newPdfVersion) {
18131815
writer.crypto = reader.decrypt;
18141816
}
18151817
writer.document = this;
1816-
String producer = null;
18171818
if (reader == null) {
18181819
catalog = new PdfCatalog(this);
18191820
info = new PdfDocumentInfo(this).addCreationDate();
1820-
producer = Version.getInstance().getVersion();
1821-
} else {
1822-
if (info.getPdfObject().containsKey(PdfName.Producer)) {
1823-
producer = info.getPdfObject().getAsString(PdfName.Producer).toUnicodeString();
1824-
}
1825-
producer = addModifiedPostfix(producer);
18261821
}
1822+
updateProducerInInfoDictionary();
18271823
info.addModDate();
1828-
info.getPdfObject().put(PdfName.Producer, new PdfString(producer));
18291824
trailer = new PdfDictionary();
18301825
trailer.put(PdfName.Root, catalog.getPdfObject().getIndirectReference());
18311826
trailer.put(PdfName.Info, info.getPdfObject().getIndirectReference());
@@ -2003,10 +1998,19 @@ protected List<ICounter> getCounters() {
20031998
return CounterManager.getInstance().getCounters(PdfDocument.class);
20041999
}
20052000

2001+
/**
2002+
* Gets iText version info.
2003+
*
2004+
* @return iText version info.
2005+
*/
2006+
final VersionInfo getVersionInfo() {
2007+
return versionInfo;
2008+
}
2009+
20062010
private void updateProducerInInfoDictionary() {
20072011
String producer = null;
20082012
if (reader == null) {
2009-
producer = Version.getInstance().getVersion();
2013+
producer = versionInfo.getVersion();
20102014
} else {
20112015
if (info.getPdfObject().containsKey(PdfName.Producer)) {
20122016
producer = info.getPdfObject().getAsString(PdfName.Producer).toUnicodeString();
@@ -2290,9 +2294,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
22902294
}
22912295

22922296
private String addModifiedPostfix(String producer) {
2293-
Version version = Version.getInstance();
2294-
if (producer == null || !version.getVersion().contains(version.getProduct())) {
2295-
return version.getVersion();
2297+
if (producer == null || !versionInfo.getVersion().contains(versionInfo.getProduct())) {
2298+
return versionInfo.getVersion();
22962299
} else {
22972300
int idx = producer.indexOf("; modified using");
22982301
StringBuilder buf;
@@ -2302,7 +2305,7 @@ private String addModifiedPostfix(String producer) {
23022305
buf = new StringBuilder(producer.substring(0, idx));
23032306
}
23042307
buf.append("; modified using ");
2305-
buf.append(version.getVersion());
2308+
buf.append(versionInfo.getVersion());
23062309
return buf.toString();
23072310
}
23082311
}

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfXrefTable.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ This file is part of the iText (R) project.
4848
import com.itextpdf.io.util.MessageFormatUtil;
4949
import com.itextpdf.kernel.ProductInfo;
5050
import com.itextpdf.kernel.Version;
51+
import com.itextpdf.kernel.VersionInfo;
5152
import org.slf4j.Logger;
5253
import org.slf4j.LoggerFactory;
5354

@@ -404,12 +405,12 @@ protected static void writeKeyInfo(PdfDocument document) {
404405
FingerPrint fingerPrint = document.getFingerPrint();
405406

406407
String platform = "";
407-
Version version = Version.getInstance();
408-
String k = version.getKey();
408+
VersionInfo versionInfo = document.getVersionInfo();
409+
String k = versionInfo.getKey();
409410
if (k == null) {
410411
k = "iText";
411412
}
412-
writer.writeString(MessageFormatUtil.format("%{0}-{1}{2}\n", k, version.getRelease(), platform));
413+
writer.writeString(MessageFormatUtil.format("%{0}-{1}{2}\n", k, versionInfo.getRelease(), platform));
413414

414415
for (ProductInfo productInfo : fingerPrint.getProducts() ) {
415416
writer.writeString(MessageFormatUtil.format("%{0}\n", productInfo));

0 commit comments

Comments
 (0)