package org.dcache.chimera.nfsv41.door.proxy; import java.io.IOException; import java.security.PrivilegedAction; import java.util.Optional; import javax.security.auth.Subject; import org.dcache.auth.Origin; import org.dcache.nfs.ChimeraNFSException; import org.dcache.nfs.v4.AbstractNFSv4Operation; import org.dcache.nfs.v4.CompoundContext; import org.dcache.nfs.v4.NFSv4OperationFactory; import org.dcache.nfs.v4.xdr.nfs_argop4; import org.dcache.nfs.v4.xdr.nfs_opnum4; import org.dcache.nfs.v4.xdr.nfs_resop4; import org.dcache.xdr.OncRpcException; /** * NFS operation factory which uses Proxy IO adapter for read requests */ public class ProxyIoMdsOpFactory implements NFSv4OperationFactory { private final ProxyIoFactory _proxyIoFactory; private final NFSv4OperationFactory _inner; public ProxyIoMdsOpFactory(ProxyIoFactory proxyIoFactory, NFSv4OperationFactory inner) { _proxyIoFactory = proxyIoFactory; _inner = inner; } @Override public AbstractNFSv4Operation getOperation(nfs_argop4 opArgs) { final AbstractNFSv4Operation operation; switch (opArgs.argop) { case nfs_opnum4.OP_READ: operation = new ProxyIoREAD(opArgs, _proxyIoFactory); break; case nfs_opnum4.OP_WRITE: operation = new ProxyIoWRITE(opArgs, _proxyIoFactory); break; case nfs_opnum4.OP_CLOSE: operation = new ProxyIoClose(opArgs); break; default: operation = _inner.getOperation(opArgs); } return new AbstractNFSv4Operation(opArgs, opArgs.argop) { @Override public void process(CompoundContext context, nfs_resop4 result) throws ChimeraNFSException, IOException, OncRpcException { Optional<IOException> optionalException = Subject.doAs(context.getSubject(), (PrivilegedAction<Optional<IOException>>) () -> { try { context.getSubject().getPrincipals().add( new Origin(context.getRemoteSocketAddress().getAddress())); operation.process(context, result); } catch (IOException e) { return Optional.of(e); } return Optional.empty(); }); if(optionalException.isPresent()) { throw optionalException.get(); } } }; } }