/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.fs.service.def;
import java.io.IOException;
import java.io.VMFile;
import java.io.VMIOUtils;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Map;
import java.util.TreeMap;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import org.apache.log4j.Logger;
import org.jnode.driver.Device;
import org.jnode.driver.DeviceAlreadyRegisteredException;
import org.jnode.driver.DeviceUtils;
import org.jnode.driver.DriverException;
import org.jnode.fs.FileSystem;
import org.jnode.fs.FileSystemException;
import org.jnode.fs.FileSystemType;
import org.jnode.fs.service.FileSystemService;
import org.jnode.java.io.VMFileSystemAPI;
import org.jnode.naming.InitialNaming;
import org.jnode.plugin.Plugin;
import org.jnode.plugin.PluginDescriptor;
import org.jnode.plugin.PluginException;
/**
* @author epr
*/
public class FileSystemPlugin extends Plugin implements FileSystemService {
/** My logger */
private static final Logger log = Logger.getLogger(FileSystemPlugin.class);
/** Manager of fs types */
private final FileSystemTypeManager fsTypeManager;
/** Manager of mounted filesystems */
private final FileSystemManager fsm;
/** The FS-API implementation */
private final FileSystemAPIImpl api;
/** The mounter */
private FileSystemMounter mounter;
/** The device of the VFS filesystem */
private final VirtualFSDevice vfsDev;
/** The virtual filesystem */
private final VirtualFS vfs;
/**
* Create a new instance
*
*/
public FileSystemPlugin(PluginDescriptor descriptor) {
super(descriptor);
this.fsTypeManager = new FileSystemTypeManager(descriptor.getExtensionPoint("types"));
this.fsm = new FileSystemManager();
this.vfsDev = new VirtualFSDevice();
this.vfs = new VirtualFS(vfsDev);
this.api = new FileSystemAPIImpl(fsm, vfs);
}
/**
* Gets all registered file system types. All instances of the returned
* collection are instanceof FileSystemType.
*/
public Collection<FileSystemType<?>> fileSystemTypes() {
return fsTypeManager.fileSystemTypes();
}
/**
* Register a mounted filesystem
*
* @param fs
*/
public void registerFileSystem(FileSystem<?> fs) {
fsm.registerFileSystem(fs);
}
/**
* Unregister a mounted filesystem
*
* @param device
*/
public FileSystem<?> unregisterFileSystem(final Device device) {
return AccessController.doPrivileged(new PrivilegedAction<FileSystem<?>>() {
public FileSystem<?> run() {
api.unregisterFileSystem(device);
return fsm.unregisterFileSystem(device);
}
});
}
/**
* Gets the filesystem registered on the given device.
*
* @param device
* @return null if no filesystem was found.
*/
public FileSystem<?> getFileSystem(Device device) {
return fsm.getFileSystem(device);
}
/**
* Gets all registered filesystems.
*/
public Collection<FileSystem<?>> fileSystems() {
return fsm.fileSystems();
}
/**
* Mount the given filesystem at the fullPath, using the fsPath as root of
* the to be mounted filesystem.
*
* @param fullPath
* @param fs
* @param fsPath Null or empty to use the root of the filesystem.
*/
public void mount(String fullPath, FileSystem<?> fs, String fsPath) throws IOException {
if (fsPath != null) {
fsPath = VMFile.getNormalizedPath(fsPath);
}
api.mount(VMFile.getNormalizedPath(fullPath), fs, fsPath);
}
/**
* Return a map (fullPath -> FileSystem) of mount points
* @return a copy of the internal map, sorted by fullPath
*/
public Map<String, FileSystem<?>> getMountPoints() {
return api.getMountPoints();
}
public Map<String, String> getDeviceMountPoints() {
Map<String, FileSystem<?>> mounts = api.getMountPoints();
Map<String, String> result = new TreeMap<String, String>();
for (Map.Entry<String, FileSystem<?>> stringFileSystemEntry : mounts.entrySet()) {
FileSystem<?> fs = (FileSystem<?>) stringFileSystemEntry.getValue();
result.put(fs.getDevice().getId(), stringFileSystemEntry.getKey());
}
return result;
}
/**
* Is the given directory a mount.
* @param fullPath
* @return {@code true} if the director is a mount, otherwise {@code false}.
*/
public boolean isMount(String fullPath) {
return api.isMount(VMFile.getNormalizedPath(fullPath));
}
/**
* Gets the filesystem API.
*/
public VMFileSystemAPI getApi() {
return api;
}
/**
* Start this plugin
*/
protected void startPlugin() throws PluginException {
try {
DeviceUtils.getDeviceManager().register(vfsDev);
VMIOUtils.setAPI(getApi(), this);
mounter = new FileSystemMounter(this);
InitialNaming.bind(NAME, this);
mounter.start();
} catch (NamingException ex) {
throw new PluginException(ex);
} catch (DeviceAlreadyRegisteredException ex) {
throw new PluginException(ex);
} catch (DriverException ex) {
throw new PluginException(ex);
}
}
/**
* Stop this plugin
*/
protected void stopPlugin() {
mounter.stop();
InitialNaming.unbind(NAME);
VMIOUtils.resetAPI(this);
mounter = null;
try {
DeviceUtils.getDeviceManager().unregister(vfsDev);
} catch (NameNotFoundException ex) {
log.error("Cannot find devicemanager", ex);
} catch (DriverException ex) {
log.error("Cannot unregister vfs device", ex);
}
}
public <T extends FileSystemType<?>> T getFileSystemType(Class<T> name)
throws FileSystemException {
T result = fsTypeManager.getSystemType(name);
if (result == null) {
throw new FileSystemException("FileSystemType " + name + " doesn't exist");
}
return result;
}
}