Skip to content

Commit 091dabd

Browse files
Eugene BochiloiText-CI
authored andcommitted
Introduce way to pass MetaInfo to forms module
DEVSIX-6328 Autoported commit. Original commit hash: [c715df234]
1 parent 5a87609 commit 091dabd

File tree

7 files changed

+190
-7
lines changed

7 files changed

+190
-7
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
using System;
2+
using System.Threading;
3+
using iText.Commons.Actions.Contexts;
4+
using iText.Layout.Renderer;
5+
using iText.Test;
6+
7+
namespace iText.Forms.Fields {
8+
public class FormsMetaInfoStaticContainerTest : ExtendedITextTest {
9+
[NUnit.Framework.Test]
10+
public virtual void UseMetaInfoDuringTheActionOneThreadTest() {
11+
MetaInfoContainer metaInfo1 = new MetaInfoContainer(new _IMetaInfo_16());
12+
MetaInfoContainer metaInfo2 = new MetaInfoContainer(new _IMetaInfo_17());
13+
FormsMetaInfoStaticContainer.UseMetaInfoDuringTheAction(metaInfo1, () => {
14+
NUnit.Framework.Assert.AreSame(metaInfo1, FormsMetaInfoStaticContainer.GetMetaInfoForLayout());
15+
FormsMetaInfoStaticContainer.UseMetaInfoDuringTheAction(metaInfo2, () => NUnit.Framework.Assert.AreSame(metaInfo2
16+
, FormsMetaInfoStaticContainer.GetMetaInfoForLayout()));
17+
NUnit.Framework.Assert.IsNull(FormsMetaInfoStaticContainer.GetMetaInfoForLayout());
18+
}
19+
);
20+
NUnit.Framework.Assert.IsNull(FormsMetaInfoStaticContainer.GetMetaInfoForLayout());
21+
}
22+
23+
private sealed class _IMetaInfo_16 : IMetaInfo {
24+
public _IMetaInfo_16() {
25+
}
26+
}
27+
28+
private sealed class _IMetaInfo_17 : IMetaInfo {
29+
public _IMetaInfo_17() {
30+
}
31+
}
32+
33+
[NUnit.Framework.Test]
34+
public virtual void UseMetaInfoDuringTheActionSeveralThreadsTest() {
35+
FormsMetaInfoStaticContainerTest.MetaInfoCheckClass metaInfoCheckClass1 = new FormsMetaInfoStaticContainerTest.MetaInfoCheckClass
36+
(null);
37+
FormsMetaInfoStaticContainerTest.MetaInfoCheckClass metaInfoCheckClass2 = new FormsMetaInfoStaticContainerTest.MetaInfoCheckClass
38+
(metaInfoCheckClass1);
39+
FormsMetaInfoStaticContainerTest.MetaInfoCheckClass metaInfoCheckClass3 = new FormsMetaInfoStaticContainerTest.MetaInfoCheckClass
40+
(metaInfoCheckClass2);
41+
Thread thread = new Thread(() => metaInfoCheckClass3.CheckMetaInfo());
42+
thread.Start();
43+
thread.Join();
44+
NUnit.Framework.Assert.IsFalse(metaInfoCheckClass1.IsCheckFailed());
45+
NUnit.Framework.Assert.IsFalse(metaInfoCheckClass2.IsCheckFailed());
46+
NUnit.Framework.Assert.IsFalse(metaInfoCheckClass3.IsCheckFailed());
47+
}
48+
49+
private class MetaInfoCheckClass {
50+
private FormsMetaInfoStaticContainerTest.MetaInfoCheckClass metaInfoCheckClass = null;
51+
52+
private bool checkFailed = false;
53+
54+
public MetaInfoCheckClass(FormsMetaInfoStaticContainerTest.MetaInfoCheckClass metaInfoCheckClass) {
55+
this.metaInfoCheckClass = metaInfoCheckClass;
56+
}
57+
58+
public virtual void CheckMetaInfo() {
59+
MetaInfoContainer metaInfo = new MetaInfoContainer(new _IMetaInfo_56());
60+
FormsMetaInfoStaticContainer.UseMetaInfoDuringTheAction(metaInfo, () => {
61+
if (metaInfoCheckClass != null) {
62+
Thread thread = new Thread(() => metaInfoCheckClass.CheckMetaInfo());
63+
thread.Start();
64+
try {
65+
thread.Join();
66+
}
67+
catch (Exception) {
68+
checkFailed = true;
69+
}
70+
}
71+
checkFailed |= metaInfo != FormsMetaInfoStaticContainer.GetMetaInfoForLayout();
72+
}
73+
);
74+
checkFailed |= FormsMetaInfoStaticContainer.GetMetaInfoForLayout() != null;
75+
}
76+
77+
private sealed class _IMetaInfo_56 : IMetaInfo {
78+
public _IMetaInfo_56() {
79+
}
80+
}
81+
82+
public virtual bool IsCheckFailed() {
83+
return checkFailed;
84+
}
85+
}
86+
}
87+
}

itext.tests/itext.forms.tests/itext/forms/fields/PdfFormFieldUnitTest.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@ You should have received a copy of the GNU Affero General Public License
2121
along with this program. If not, see <https://www.gnu.org/licenses/>.
2222
*/
2323
using System;
24+
using iText.Commons.Actions.Contexts;
2425
using iText.Forms.Exceptions;
2526
using iText.IO.Source;
2627
using iText.Kernel.Exceptions;
28+
using iText.Kernel.Geom;
2729
using iText.Kernel.Pdf;
30+
using iText.Kernel.Pdf.Canvas;
31+
using iText.Layout;
32+
using iText.Layout.Properties;
33+
using iText.Layout.Renderer;
2834
using iText.Test;
2935

3036
namespace iText.Forms.Fields {
@@ -39,5 +45,36 @@ public virtual void CannotGetRectangleIfKidsIsNullTest() {
3945
NUnit.Framework.Assert.AreEqual(FormsExceptionMessageConstant.WRONG_FORM_FIELD_ADD_ANNOTATION_TO_THE_FIELD
4046
, exception.Message);
4147
}
48+
49+
[NUnit.Framework.Test]
50+
public virtual void SetMetaInfoToCanvasMetaInfoUsedTest() {
51+
Canvas canvas = CreateCanvas();
52+
MetaInfoContainer metaInfoContainer = new MetaInfoContainer(new _IMetaInfo_62());
53+
FormsMetaInfoStaticContainer.UseMetaInfoDuringTheAction(metaInfoContainer, () => PdfFormField.SetMetaInfoToCanvas
54+
(canvas));
55+
NUnit.Framework.Assert.AreSame(metaInfoContainer, canvas.GetProperty<MetaInfoContainer>(Property.META_INFO
56+
));
57+
}
58+
59+
private sealed class _IMetaInfo_62 : IMetaInfo {
60+
public _IMetaInfo_62() {
61+
}
62+
}
63+
64+
[NUnit.Framework.Test]
65+
public virtual void SetMetaInfoToCanvasMetaInfoNotUsedTest() {
66+
Canvas canvas = CreateCanvas();
67+
PdfFormField.SetMetaInfoToCanvas(canvas);
68+
NUnit.Framework.Assert.IsNull(canvas.GetProperty<MetaInfoContainer>(Property.META_INFO));
69+
}
70+
71+
private static Canvas CreateCanvas() {
72+
using (PdfDocument document = new PdfDocument(new PdfWriter(new ByteArrayOutputStream()))) {
73+
PdfStream stream = (PdfStream)new PdfStream().MakeIndirect(document);
74+
PdfResources resources = new PdfResources();
75+
PdfCanvas pdfCanvas = new PdfCanvas(stream, resources, document);
76+
return new iText.Layout.Canvas(pdfCanvas, new Rectangle(100, 100));
77+
}
78+
}
4279
}
4380
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
namespace iText.Commons.Utils {
2+
public delegate void Action();
3+
}

itext/itext.forms/itext/forms/PdfAcroForm.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ source product.
6161
namespace iText.Forms {
6262
/// <summary>This class represents the static form technology AcroForm on a PDF file.</summary>
6363
public class PdfAcroForm : PdfObjectWrapper<PdfDictionary> {
64+
private static readonly ILogger LOGGER = ITextLogManager.GetLogger(typeof(iText.Forms.PdfAcroForm));
65+
6466
/// <summary>
6567
/// To be used with
6668
/// <see cref="SetSignatureFlags(int)"/>.
@@ -127,8 +129,6 @@ public class PdfAcroForm : PdfObjectWrapper<PdfDictionary> {
127129

128130
private XfaForm xfaForm;
129131

130-
private static ILogger logger = ITextLogManager.GetLogger(typeof(iText.Forms.PdfAcroForm));
131-
132132
/// <summary>Creates a PdfAcroForm as a wrapper of a dictionary.</summary>
133133
/// <remarks>
134134
/// Creates a PdfAcroForm as a wrapper of a dictionary.
@@ -833,7 +833,7 @@ public virtual void FlattenFields() {
833833
}
834834
}
835835
else {
836-
logger.LogError(iText.IO.Logs.IoLogMessageConstant.N_ENTRY_IS_REQUIRED_FOR_APPEARANCE_DICTIONARY);
836+
LOGGER.LogError(iText.IO.Logs.IoLogMessageConstant.N_ENTRY_IS_REQUIRED_FOR_APPEARANCE_DICTIONARY);
837837
}
838838
PdfArray fFields = GetFields();
839839
fFields.Remove(fieldObject);
@@ -1005,7 +1005,7 @@ public virtual void ReplaceField(String name, PdfFormField field) {
10051005
protected internal virtual PdfArray GetFields() {
10061006
PdfArray fields = GetPdfObject().GetAsArray(PdfName.Fields);
10071007
if (fields == null) {
1008-
logger.LogWarning(iText.IO.Logs.IoLogMessageConstant.NO_FIELDS_IN_ACROFORM);
1008+
LOGGER.LogWarning(iText.IO.Logs.IoLogMessageConstant.NO_FIELDS_IN_ACROFORM);
10091009
fields = new PdfArray();
10101010
GetPdfObject().Put(PdfName.Fields, fields);
10111011
}
@@ -1021,12 +1021,12 @@ private IDictionary<String, PdfFormField> IterateFields(PdfArray array, IDiction
10211021
int index = 1;
10221022
foreach (PdfObject field in array) {
10231023
if (field.IsFlushed()) {
1024-
logger.LogInformation(iText.IO.Logs.IoLogMessageConstant.FORM_FIELD_WAS_FLUSHED);
1024+
LOGGER.LogInformation(iText.IO.Logs.IoLogMessageConstant.FORM_FIELD_WAS_FLUSHED);
10251025
continue;
10261026
}
10271027
PdfFormField formField = PdfFormField.MakeFormField(field, document);
10281028
if (formField == null) {
1029-
logger.LogWarning(MessageFormatUtil.Format(iText.IO.Logs.IoLogMessageConstant.CANNOT_CREATE_FORMFIELD, field
1029+
LOGGER.LogWarning(MessageFormatUtil.Format(iText.IO.Logs.IoLogMessageConstant.CANNOT_CREATE_FORMFIELD, field
10301030
.GetIndirectReference() == null ? field : field.GetIndirectReference()));
10311031
continue;
10321032
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System.Threading;
2+
using iText.Commons.Utils;
3+
using iText.Layout.Renderer;
4+
5+
namespace iText.Forms.Fields {
6+
/// <summary>Class to store meta info that will be used in forms module in static context.</summary>
7+
public sealed class FormsMetaInfoStaticContainer {
8+
private static ThreadLocal<MetaInfoContainer> metaInfoForLayout = new ThreadLocal<MetaInfoContainer>();
9+
10+
private FormsMetaInfoStaticContainer() {
11+
}
12+
13+
// Empty constructor.
14+
/// <summary>Sets meta info related to forms into static context, executes the action and then cleans meta info.
15+
/// </summary>
16+
/// <remarks>
17+
/// Sets meta info related to forms into static context, executes the action and then cleans meta info.
18+
/// <para />
19+
/// Keep in mind that this instance will only be accessible from the same thread.
20+
/// </remarks>
21+
/// <param name="metaInfoContainer">instance to be set.</param>
22+
/// <param name="action">action which will be executed while meta info is set to static context.</param>
23+
public static void UseMetaInfoDuringTheAction(MetaInfoContainer metaInfoContainer, Action action) {
24+
// TODO DEVSIX-6368 We want to prevent customer code being run while meta info is in the static context
25+
try {
26+
metaInfoForLayout.Value = metaInfoContainer;
27+
action();
28+
}
29+
finally {
30+
metaInfoForLayout.Value = null;
31+
}
32+
}
33+
34+
/// <summary>Gets meta info which was set previously.</summary>
35+
/// <remarks>
36+
/// Gets meta info which was set previously.
37+
/// <para />
38+
/// Keep in mind that this operation will return meta info instance which was set previously from the same thread.
39+
/// </remarks>
40+
/// <returns>meta info instance.</returns>
41+
internal static MetaInfoContainer GetMetaInfoForLayout() {
42+
return metaInfoForLayout.Value;
43+
}
44+
}
45+
}

itext/itext.forms/itext/forms/fields/PdfFormField.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3061,6 +3061,7 @@ protected internal virtual void DrawTextAppearance(Rectangle rect, PdfFont font,
30613061
iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, new Rectangle(0, -height, 0, 2 * height)
30623062
);
30633063
modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true);
3064+
SetMetaInfoToCanvas(modelCanvas);
30643065
Style paragraphStyle = new Style().SetFont(font).SetFontSize(fontSize);
30653066
paragraphStyle.SetProperty(Property.LEADING, new Leading(Leading.MULTIPLIED, 1));
30663067
if (color != null) {
@@ -3119,6 +3120,7 @@ protected internal virtual void DrawMultiLineTextAppearance(Rectangle rect, PdfF
31193120
Rectangle areaRect = new Rectangle(0, 0, width, height);
31203121
iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, areaRect);
31213122
modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true);
3123+
SetMetaInfoToCanvas(modelCanvas);
31223124
Paragraph paragraph = CreateParagraphForTextFieldValue(value).SetFont(font).SetMargin(0).SetPadding(3).SetMultipliedLeading
31233125
(1);
31243126
if (fontSize == 0) {
@@ -3162,6 +3164,7 @@ private void DrawChoiceAppearance(Rectangle rect, float fontSize, String value,
31623164
iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, new Rectangle(3, 0, Math.Max(0, width -
31633165
widthBorder), Math.Max(0, height - heightBorder)));
31643166
modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true);
3167+
SetMetaInfoToCanvas(modelCanvas);
31653168
Div div = new Div();
31663169
if (GetFieldFlag(PdfChoiceFormField.FF_COMBO)) {
31673170
div.SetVerticalAlignment(VerticalAlignment.MIDDLE);
@@ -3458,6 +3461,7 @@ protected internal virtual void DrawButton(PdfCanvas canvas, float x, float y, f
34583461
iText.Layout.Canvas modelCanvas = new iText.Layout.Canvas(canvas, new Rectangle(0, -height, width, 2 * height
34593462
));
34603463
modelCanvas.SetProperty(Property.APPEARANCE_STREAM_LAYOUT, true);
3464+
SetMetaInfoToCanvas(modelCanvas);
34613465
modelCanvas.ShowTextAligned(paragraph, width / 2, height / 2, TextAlignment.CENTER, VerticalAlignment.MIDDLE
34623466
);
34633467
}
@@ -3523,6 +3527,13 @@ protected internal virtual void DrawPdfACheckBox(PdfCanvas canvas, float width,
35233527
}
35243528
}
35253529

3530+
internal static void SetMetaInfoToCanvas(iText.Layout.Canvas canvas) {
3531+
MetaInfoContainer metaInfo = FormsMetaInfoStaticContainer.GetMetaInfoForLayout();
3532+
if (metaInfo != null) {
3533+
canvas.SetProperty(Property.META_INFO, metaInfo);
3534+
}
3535+
}
3536+
35263537
private String GetRadioButtonValue() {
35273538
foreach (String state in GetAppearanceStates()) {
35283539
if (!"Off".Equals(state)) {

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8b4d0ca65f67858c609e5ee542119afff3329d51
1+
c715df234a8bc2d9cffa6537d53da43e1bbd1d49

0 commit comments

Comments
 (0)