1 /*
2 * junixsocket
3 *
4 * Copyright 2009-2026 Christian Kohlschütter
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.newsclub.net.unix.rmi;
19
20 import java.io.Closeable;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.io.ObjectInput;
24
25 import com.kohlschutter.annotations.compiletime.SuppressFBWarnings;
26
27 /**
28 * A specialized subclass of {@link RemoteFileDescriptorBase}, specifically for
29 * {@link FileInputStream}s.
30 *
31 * @author Christian Kohlschütter
32 */
33 public final class RemoteFileInput extends RemoteFileDescriptorBase<FileInputStream> implements
34 Closeable {
35 private static final long serialVersionUID = 1L;
36
37 /**
38 * Creates an uninitialized instance; used for externalization.
39 *
40 * @see #readExternal(ObjectInput)
41 */
42 public RemoteFileInput() {
43 super();
44 }
45
46 /**
47 * Creates a new {@link RemoteFileInput} instance, encapsulating a {@link FileInputStream} so that
48 * it can be shared with other processes via RMI.
49 *
50 * @param socketFactory The socket factory.
51 * @param fin The {@link FileInputStream}.
52 * @throws IOException if the operation fails.
53 */
54 public RemoteFileInput(AFUNIXRMISocketFactory socketFactory, FileInputStream fin)
55 throws IOException {
56 super(socketFactory, fin, fin.getFD(), RemoteFileDescriptorBase.MAGIC_VALUE_MASK
57 | RemoteFileDescriptorBase.BIT_READABLE);
58 }
59
60 /**
61 * Returns a FileInputStream for the given instance. This either is the actual instance provided
62 * by the constructor or a new instance created from the file descriptor.
63 *
64 * @return The FileInputStream.
65 * @throws IOException if the operation fails.
66 */
67 public FileInputStream asFileInputStream() throws IOException {
68 if ((getMagicValue() & RemoteFileDescriptorBase.BIT_READABLE) == 0) {
69 throw new IOException("FileDescriptor is not readable");
70 }
71
72 return resource.accumulateAndGet(null, (prev, x) -> {
73 if (prev != null) {
74 return prev;
75 }
76 return new FileInputStream(getFileDescriptor()) {
77 @Override
78 @SuppressFBWarnings("USO_UNSAFE_OBJECT_SYNCHRONIZATION")
79 public void close() throws IOException {
80 super.close();
81
82 synchronized (RemoteFileInput.this) {
83 RemoteFileInput.this.close();
84 }
85 }
86 };
87 });
88 }
89 }