1 /*
2 * Copyright (c) 2002-2025 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit.util;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.io.ObjectInputStream;
20 import java.io.ObjectOutputStream;
21 import java.nio.charset.Charset;
22
23 /**
24 * <span style="color:red">INTERNAL API - SUBJECT TO CHANGE AT ANY TIME - USE AT YOUR OWN RISK.</span><br>
25 *
26 * A holder for a key/value pair that represents a file to upload.
27 *
28 * @author Brad Clarke
29 * @author David D. Kilzer
30 * @author Mike Bowler
31 * @author Ahmed Ashour
32 * @author Ronald Brill
33 * @author Michael Lueck
34 */
35 public class KeyDataPair extends NameValuePair {
36
37 private final File fileObject_;
38 private final String fileName_;
39 private final String mimeType_;
40 private transient Charset charset_;
41 private byte[] data_;
42
43 /**
44 * Creates an instance.
45 *
46 * @param key the key
47 * @param file the file
48 * @param fileName the name of the file
49 * @param mimeType the MIME type
50 * @param charset the charset encoding
51 */
52 public KeyDataPair(final String key, final File file, final String fileName,
53 final String mimeType, final String charset) {
54 this(key, file, fileName, mimeType, Charset.forName(charset));
55 }
56
57 /**
58 * Creates an instance.
59 *
60 * @param key the key
61 * @param file the file
62 * @param fileName the name of the file
63 * @param mimeType the MIME type
64 * @param charset the charset encoding
65 */
66 public KeyDataPair(final String key, final File file, final String fileName,
67 final String mimeType, final Charset charset) {
68 this(key,
69 (file == null) ? "" : file.getName(),
70 (file != null && file.exists()) ? file : null,
71 fileName,
72 mimeType,
73 charset,
74 null);
75 }
76
77 /**
78 * Private constructor setting plain properties.
79 *
80 * @param name will be passed as name to the super constructor
81 * @param value will be passed as value to the super constructor
82 * @param file the file, may be null
83 * @param fileName the filename, may be null
84 * @param mimeType the mimetype, may be null
85 * @param charset the charset, may be null
86 */
87 private KeyDataPair(final String name, final String value, final File file,
88 final String fileName, final String mimeType, final Charset charset,
89 final byte[] data) {
90 super(name, value);
91
92 fileObject_ = file;
93 fileName_ = fileName;
94
95 mimeType_ = mimeType;
96 charset_ = charset;
97
98 data_ = data;
99 }
100
101 /**
102 * {@inheritDoc}
103 */
104 @Override
105 @SuppressWarnings("PMD.UselessOverridingMethod")
106 public boolean equals(final Object object) {
107 // this is overwritten to make FindBugs happy
108 // and to make it clear, that we really want to have
109 // the same equals semantic like our parent class
110 return super.equals(object);
111 }
112
113 /**
114 * {@inheritDoc}
115 */
116 @Override
117 @SuppressWarnings("PMD.UselessOverridingMethod")
118 public int hashCode() {
119 // this is overwritten to make FindBugs happy
120 // and to make it clear, that we really want to have
121 // the same hashCode as our parent class
122 return super.hashCode();
123 }
124
125 /**
126 * @return the {@link File} object if the file exists, else {@code null}
127 */
128 public File getFile() {
129 return fileObject_;
130 }
131
132 /**
133 * @return the fileName
134 */
135 public String getFileName() {
136 return fileName_;
137 }
138
139 /**
140 * Gets the charset encoding for this file upload.
141 * @return the charset
142 */
143 public Charset getCharset() {
144 return charset_;
145 }
146
147 /**
148 * Gets the MIME type for this file upload.
149 * @return the MIME type
150 */
151 public String getMimeType() {
152 return mimeType_;
153 }
154
155 /**
156 * Gets in-memory data assigned to file value.
157 * @return {@code null} if the file content should be used.
158 */
159 public byte[] getData() {
160 return data_;
161 }
162
163 /**
164 * Sets file value data. If nothing is set, the file content will be used.
165 * @param data byte array with file data.
166 */
167 public void setData(final byte[] data) {
168 data_ = data;
169 }
170
171 private void writeObject(final ObjectOutputStream oos) throws IOException {
172 oos.defaultWriteObject();
173 oos.writeObject(charset_ == null ? null : charset_.name());
174 }
175
176 private void readObject(final ObjectInputStream ois) throws ClassNotFoundException, IOException {
177 ois.defaultReadObject();
178 final String charsetName = (String) ois.readObject();
179 if (charsetName != null) {
180 charset_ = Charset.forName(charsetName);
181 }
182 }
183
184 /**
185 * {@inheritDoc}
186 *
187 * Specialization of inherited method which will copy all fields
188 * and make sure that the value in the base class is not null, by calling
189 * the constructor with the current value
190 */
191 @Override
192 public KeyDataPair normalized() {
193 return new KeyDataPair(
194 this.getName(),
195 this.getValue(),
196 this.fileObject_,
197 this.fileName_,
198 this.mimeType_,
199 this.charset_,
200 this.data_);
201 }
202 }