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    private final FileReplicator replicator;
038    private final VfsComponent replicatorComponent;
039
040    public PrivilegedFileReplicator(final FileReplicator replicator) {
041        this.replicator = replicator;
042        if (replicator instanceof VfsComponent) {
043            replicatorComponent = (VfsComponent) replicator;
044        } else {
045            replicatorComponent = null;
046        }
047    }
048
049    /**
050     * Sets the Logger to use for the component.
051     *
052     * @param logger The logger.
053     */
054    @Override
055    public void setLogger(final Log logger) {
056        if (replicatorComponent != null) {
057            replicatorComponent.setLogger(logger);
058        }
059    }
060
061    /**
062     * Sets the context for the replicator.
063     *
064     * @param context The component context.
065     */
066    @Override
067    public void setContext(final VfsComponentContext context) {
068        if (replicatorComponent != null) {
069            replicatorComponent.setContext(context);
070        }
071    }
072
073    /**
074     * Initializes the component.
075     *
076     * @throws FileSystemException if an error occurs.
077     */
078    @Override
079    public void init() throws FileSystemException {
080        if (replicatorComponent != null) {
081            try {
082                AccessController.doPrivileged(new InitAction());
083            } catch (final PrivilegedActionException e) {
084                throw new FileSystemException("vfs.impl/init-replicator.error", e);
085            }
086        }
087    }
088
089    /**
090     * Closes the replicator.
091     */
092    @Override
093    public void close() {
094        if (replicatorComponent != null) {
095            AccessController.doPrivileged(new CloseAction());
096        }
097    }
098
099    /**
100     * Creates a local copy of the file, and all its descendants.
101     *
102     * @param srcFile The source FileObject.
103     * @param selector The file selector.
104     * @return The replicated file.
105     * @throws FileSystemException if an error occurs.
106     */
107    @Override
108    public File replicateFile(final FileObject srcFile, final FileSelector selector) throws FileSystemException {
109        try {
110            final ReplicateAction action = new ReplicateAction(srcFile, selector);
111            return AccessController.doPrivileged(action);
112        } catch (final PrivilegedActionException e) {
113            throw new FileSystemException("vfs.impl/replicate-file.error", e, srcFile.getName());
114        }
115    }
116
117    /**
118     * An action that initialises the wrapped replicator.
119     */
120    private class InitAction implements PrivilegedExceptionAction<Object> {
121        /**
122         * Performs the action.
123         */
124        @Override
125        public Object run() throws Exception {
126            replicatorComponent.init();
127            return null;
128        }
129    }
130
131    /**
132     * An action that replicates a file using the wrapped replicator.
133     */
134    private class ReplicateAction implements PrivilegedExceptionAction<File> {
135        private final FileObject srcFile;
136        private final FileSelector selector;
137
138        public ReplicateAction(final FileObject srcFile, final FileSelector selector) {
139            this.srcFile = srcFile;
140            this.selector = selector;
141        }
142
143        /**
144         * Performs the action.
145         *
146         * @throws Exception if an error occurs.
147         */
148        @Override
149        public File run() throws Exception {
150            // TODO - Do not pass the selector through. It is untrusted
151            // TODO - Need to determine which files can be read
152            return replicator.replicateFile(srcFile, selector);
153        }
154    }
155
156    /**
157     * An action that closes the wrapped replicator.
158     */
159    private class CloseAction implements PrivilegedAction<Object> {
160        /**
161         * Performs the action.
162         */
163        @Override
164        public Object run() {
165            replicatorComponent.close();
166            return null;
167        }
168    }
169}