1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.file;
16
17 import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
18 import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
19
20 import java.io.IOException;
21 import java.nio.charset.Charset;
22 import java.nio.charset.StandardCharsets;
23 import java.time.Instant;
24 import java.time.ZoneId;
25 import java.time.format.DateTimeFormatter;
26
27 import org.apache.commons.io.FileUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.htmlunit.BrowserVersion;
31 import org.htmlunit.corejs.javascript.Context;
32 import org.htmlunit.corejs.javascript.NativeArray;
33 import org.htmlunit.corejs.javascript.ScriptableObject;
34 import org.htmlunit.javascript.JavaScriptEngine;
35 import org.htmlunit.javascript.configuration.JsxClass;
36 import org.htmlunit.javascript.configuration.JsxConstructor;
37 import org.htmlunit.javascript.configuration.JsxFunction;
38 import org.htmlunit.javascript.configuration.JsxGetter;
39 import org.htmlunit.util.KeyDataPair;
40
41
42
43
44
45
46
47 @JsxClass
48 public class File extends Blob {
49
50 private static final DateTimeFormatter LAST_MODIFIED_DATE_FORMATTER
51 = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z");
52
53 private static class FileBackend implements Backend {
54 private static final Log LOG = LogFactory.getLog(FileBackend.class);
55
56 private final java.io.File file_;
57
58 FileBackend(final String pathname) {
59 super();
60 file_ = new java.io.File(pathname);
61 }
62
63 @Override
64 public String getName() {
65 return file_.getName();
66 }
67
68 @Override
69 public long getLastModified() {
70 return file_.lastModified();
71 }
72
73 @Override
74 public long getSize() {
75 return file_.length();
76 }
77
78 @Override
79 public String getType(final BrowserVersion browserVersion) {
80 return browserVersion.getUploadMimeType(file_);
81 }
82
83 @Override
84 public String getText() throws IOException {
85 return FileUtils.readFileToString(file_, StandardCharsets.UTF_8);
86 }
87
88 @Override
89 public byte[] getBytes(final int start, final int end) {
90 final byte[] result = new byte[end - start];
91 try {
92 System.arraycopy(FileUtils.readFileToByteArray(file_), start, result, 0, result.length);
93 }
94 catch (final IOException e) {
95 LOG.error("FileBackend.getBytes failed", e);
96 }
97 return result;
98 }
99
100
101
102
103 @Override
104 public KeyDataPair getKeyDataPair(final String name, final String fileName, final String contentType) {
105 return new KeyDataPair(name, file_, fileName, contentType, (Charset) null);
106 }
107 }
108
109
110
111
112 public File() {
113 super();
114 }
115
116
117
118
119
120
121
122
123 @JsxConstructor
124 public void jsConstructor(final NativeArray fileBits, final String fileName,
125 final ScriptableObject properties) throws IOException {
126 if (fileBits == null
127 || JavaScriptEngine.isUndefined(fileBits)
128 || fileName == null
129 || JavaScriptEngine.isUndefined(fileName)) {
130 throw JavaScriptEngine.typeError("Failed to construct 'File': 2 arguments required.");
131 }
132
133 setBackend(InMemoryBackend.create(fileBits, fileName,
134 extractFileTypeOrDefault(properties),
135 extractLastModifiedOrDefault(properties)));
136 }
137
138 File(final String pathname) {
139 super();
140 setBackend(new FileBackend(pathname));
141 }
142
143
144
145
146
147 @JsxGetter
148 public String getName() {
149 return getBackend().getName();
150 }
151
152
153
154
155
156 @JsxGetter({CHROME, EDGE})
157 public String getLastModifiedDate() {
158 final Context cx = Context.getCurrentContext();
159 final ZoneId zoneid = cx.getTimeZone().toZoneId();
160
161
162 String date = LAST_MODIFIED_DATE_FORMATTER.format(Instant.ofEpochMilli(getLastModified()).atZone(zoneid));
163 date += DateTimeFormatter.ofPattern(" (zzzz)", cx.getLocale())
164 .format(Instant.ofEpochMilli(getLastModified()).atZone(zoneid));
165 return date;
166 }
167
168
169
170
171
172 @JsxGetter
173 public long getLastModified() {
174 return getBackend().getLastModified();
175 }
176
177
178
179
180
181 @JsxGetter
182 public String getWebkitRelativePath() {
183 return "";
184 }
185
186
187
188
189 @JsxFunction
190 public void slice() {
191
192 }
193 }