001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.vfs2.impl;
018
019import java.io.File;
020import java.security.AccessController;
021import java.security.PrivilegedAction;
022import java.security.PrivilegedActionException;
023import java.security.PrivilegedExceptionAction;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.vfs2.FileObject;
027import org.apache.commons.vfs2.FileSelector;
028import org.apache.commons.vfs2.FileSystemException;
029import org.apache.commons.vfs2.provider.FileReplicator;
030import org.apache.commons.vfs2.provider.VfsComponent;
031import org.apache.commons.vfs2.provider.VfsComponentContext;
032
033/**
034 * A file replicator that wraps another file replicator, performing the replication as a privileged action.
035 */
036public class PrivilegedFileReplicator implements FileReplicator, VfsComponent {
037
038    /**
039     * An action that closes the wrapped replicator.
040     */
041    private final class CloseAction implements PrivilegedAction<Object> {
042        /**
043         * Performs the action.
044         */
045        @Override
046        public Object run() {
047            replicatorComponent.close();
048            return null;
049        }
050    }
051    /**
052     * An action that initializes the wrapped replicator.
053     */
054    private final class InitAction implements PrivilegedExceptionAction<Object> {
055        /**
056         * Performs the action.
057         */
058        @Override
059        public Object run() throws Exception {
060            replicatorComponent.init();
061            return null;
062        }
063    }
064
065    /**
066     * An action that replicates a file using the wrapped replicator.
067     */
068    private final class ReplicateAction implements PrivilegedExceptionAction<File> {
069        private final FileObject srcFile;
070        private final FileSelector selector;
071
072        ReplicateAction(final FileObject srcFile, final FileSelector selector) {
073            this.srcFile = srcFile;
074            this.selector = selector;
075        }
076
077        /**
078         * Performs the action.
079         *
080         * @throws Exception if an error occurs.
081         */
082        @Override
083        public File run() throws Exception {
084            // TODO - Do not pass the selector through. It is untrusted
085            // TODO - Need to determine which files can be read
086            return replicator.replicateFile(srcFile, selector);
087        }
088    }
089
090    private final FileReplicator replicator;
091
092    private final VfsComponent replicatorComponent;
093
094    /**
095     * Constructs a new instance.
096     *
097     * @param replicator The replicator.
098     */
099    public PrivilegedFileReplicator(final FileReplicator replicator) {
100        this.replicator = replicator;
101        if (replicator instanceof VfsComponent) {
102            replicatorComponent = (VfsComponent) replicator;
103        } else {
104            replicatorComponent = null;
105        }
106    }
107
108    /**
109     * Closes the replicator.
110     */
111    @Override
112    public void close() {
113        if (replicatorComponent != null) {
114            AccessController.doPrivileged(new CloseAction());
115        }
116    }
117
118    /**
119     * Initializes the component.
120     *
121     * @throws FileSystemException if an error occurs.
122     */
123    @Override
124    public void init() throws FileSystemException {
125        if (replicatorComponent != null) {
126            try {
127                AccessController.doPrivileged(new InitAction());
128            } catch (final PrivilegedActionException e) {
129                throw new FileSystemException("vfs.impl/init-replicator.error", e);
130            }
131        }
132    }
133
134    /**
135     * Creates a local copy of the file, and all its descendants.
136     *
137     * @param srcFile The source FileObject.
138     * @param selector The file selector.
139     * @return The replicated file.
140     * @throws FileSystemException if an error occurs.
141     */
142    @Override
143    public File replicateFile(final FileObject srcFile, final FileSelector selector) throws FileSystemException {
144        try {
145            final ReplicateAction action = new ReplicateAction(srcFile, selector);
146            return AccessController.doPrivileged(action);
147        } catch (final PrivilegedActionException e) {
148            throw new FileSystemException("vfs.impl/replicate-file.error", e, srcFile.getName());
149        }
150    }
151
152    /**
153     * Sets the context for the replicator.
154     *
155     * @param context The component context.
156     */
157    @Override
158    public void setContext(final VfsComponentContext context) {
159        if (replicatorComponent != null) {
160            replicatorComponent.setContext(context);
161        }
162    }
163
164    /**
165     * Sets the Logger to use for the component.
166     *
167     * @param logger The logger.
168     */
169    @Override
170    public void setLogger(final Log logger) {
171        if (replicatorComponent != null) {
172            replicatorComponent.setLogger(logger);
173        }
174    }
175}