1 /*
2 * Copyright (c) 2002-2026 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;
16
17 import java.io.ByteArrayInputStream;
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.Serializable;
22 import java.nio.file.Files;
23
24 import org.apache.commons.io.FileUtils;
25 import org.htmlunit.util.ArrayUtils;
26
27 /**
28 * Wrapper for content downloaded from a remote server.
29 *
30 * @author Marc Guillemot
31 * @author Ronald Brill
32 */
33 public interface DownloadedContent extends Serializable {
34
35 /**
36 * Implementation keeping content in memory.
37 */
38 class InMemory implements DownloadedContent {
39 private final byte[] bytes_;
40
41 InMemory(final byte[] byteArray) {
42 if (byteArray == null) {
43 bytes_ = ArrayUtils.EMPTY_BYTE_ARRAY;
44 }
45 else {
46 bytes_ = byteArray;
47 }
48 }
49
50 @Override
51 public InputStream getInputStream() {
52 return new ByteArrayInputStream(bytes_);
53 }
54
55 @Override
56 public void cleanUp() {
57 // nothing to do
58 }
59
60 @Override
61 public boolean isEmpty() {
62 return length() == 0;
63 }
64
65 @Override
66 public long length() {
67 return bytes_.length;
68 }
69 }
70
71 /**
72 * Implementation keeping content on the file system.
73 */
74 class OnFile implements DownloadedContent {
75 private final File file_;
76 private final boolean temporary_;
77
78 /**
79 * Ctor.
80 *
81 * @param file the file
82 * @param temporary if true, the file will be deleted when cleanUp() is called.
83 */
84 OnFile(final File file, final boolean temporary) {
85 file_ = file;
86 temporary_ = temporary;
87 }
88
89 @Override
90 public InputStream getInputStream() throws IOException {
91 return Files.newInputStream(file_.toPath());
92 }
93
94 @Override
95 public void cleanUp() {
96 if (temporary_) {
97 FileUtils.deleteQuietly(file_);
98 }
99 }
100
101 @Override
102 public boolean isEmpty() {
103 return false;
104 }
105
106 @Override
107 protected void finalize() throws Throwable {
108 super.finalize();
109 cleanUp();
110 }
111
112 @Override
113 public long length() {
114 if (file_ == null) {
115 return 0;
116 }
117 return file_.length();
118 }
119 }
120
121 /**
122 * Returns a new {@link InputStream} allowing to read the downloaded content.
123 * @return the InputStream
124 * @throws IOException in case of problem accessing the content
125 */
126 InputStream getInputStream() throws IOException;
127
128 /**
129 * Clean up resources associated to this content.
130 */
131 void cleanUp();
132
133 /**
134 * Returns true if the content is empty.
135 * @return true or false
136 */
137 boolean isEmpty();
138
139 /**
140 * Returns the number of bytes.
141 * @return the length
142 */
143 long length();
144 }