Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* JBoss, Home of Professional Open Source
* Copyright 2009, JBoss Inc., and individual contributors as indicated
* by the @authors tag.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.vfs.util.automount;
import static org.jboss.vfs.VFSMessages.MESSAGES;
import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import org.jboss.vfs.TempFileProvider;
import org.jboss.vfs.VFS;
import org.jboss.vfs.VFSLogger;
import org.jboss.vfs.VFSUtils;
import org.jboss.vfs.VirtualFile;
import org.jboss.vfs.util.PathTokenizer;
/**
* Utility used to manage mounting Virtual FileSystems.
*
* @author John Bailey
*/
public class Automounter {
/* Root entry in the tree. */
private static final RegistryEntry rootEntry = new RegistryEntry();
/* Map of owners and their references */
private static final ConcurrentMap> ownerReferences = new ConcurrentHashMap>();
/* Provider of temp files/directories*/
private static TempFileProvider tempFileProvider;
/**
* Private constructor
*/
private Automounter() {
}
/**
* Mount provided {@link VirtualFile} (if not mounted) and set the owner to be the provided target. (Self owned mount)
*
* @param target VirtualFile to mount
* @param mountOptions optional configuration to use for mounting
* @throws IOException when the target can not be mounted.
*/
public static void mount(VirtualFile target, MountOption... mountOptions) throws IOException {
mount(new VirtualFileOwner(target), target, mountOptions);
}
/**
* Mount provided {@link VirtualFile} (if not mounted) and add an owner entry. Also creates a back-reference to from the owner to the target.
*
* @param owner Object that owns the reference to the mount
* @param target VirtualFile to mount
* @param mountOptions optional configuration to use for mounting
* @throws IOException when the target can not be mounted.
*/
public static void mount(Object owner, VirtualFile target, MountOption... mountOptions) throws IOException {
mount(new SimpleMountOwner(owner), target, mountOptions);
}
/**
* Mount provided {@link VirtualFile} (if not mounted) and add an owner entry. Also creates a back-reference to from the owner to the target.
*
* @param owner VirtualFile that owns the reference to the mount
* @param target VirtualFile to mount
* @param mountOptions optional configuration to use for mounting
* @throws IOException when the target can not be mounted.
*/
public static void mount(VirtualFile owner, VirtualFile target, MountOption... mountOptions) throws IOException {
mount(new VirtualFileOwner(owner), target, mountOptions);
}
/**
* Mount provided {@link VirtualFile} (if not mounted) and add an owner entry. Also creates a back-reference to from the owner to the target.
*
* @param owner MountOwner that owns the reference to the mount
* @param target VirtualFile to mount
* @param mountOptions optional configuration to use for mounting
* @throws IOException when the target can not be mounted
*/
public static void mount(MountOwner owner, VirtualFile target, MountOption... mountOptions) throws IOException {
final RegistryEntry targetEntry = getEntry(target);
targetEntry.mount(target, getMountConfig(mountOptions));
targetEntry.inboundReferences.add(owner);
ownerReferences.putIfAbsent(owner, new HashSet());
ownerReferences.get(owner).add(targetEntry);
}
/**
* Creates a MountConfig and applies the provided mount options
*
* @param mountOptions options to use for mounting
* @return a MountConfig
*/
private static MountConfig getMountConfig(MountOption[] mountOptions) {
final MountConfig config = new MountConfig();
for (MountOption option : mountOptions) {
option.applyTo(config);
}
return config;
}
/**
* Add handle to owner, to be auto closed.
*
* @param owner the handle owner
* @param handle the handle
* @return add result
*/
public static boolean addHandle(VirtualFile owner, Closeable handle) {
RegistryEntry entry = getEntry(owner);
return entry.handles.add(handle);
}
/**
* Remove handle from owner.
*
* @param owner the handle owner
* @param handle the handle
* @return remove result
*/
public static boolean removeHandle(VirtualFile owner, Closeable handle) {
RegistryEntry entry = getEntry(owner);
return entry.handles.remove(handle);
}
/**
* Cleanup all references from the owner. Cleanup any mounted entries that become un-referenced in the process.
*
* @param owner {@link Object} to cleanup references for
*/
public static void cleanup(Object owner) {
cleanup(new SimpleMountOwner(owner));
}
/**
* Cleanup all references from the owner. Cleanup any mounted entries that become un-referenced in the process.
*
* @param owner {@link Object} to cleanup references for
*/
public static void cleanup(VirtualFile owner) {
cleanup(new VirtualFileOwner(owner));
}
/**
* Cleanup all references from the {@link MountOwner}. Cleanup any mounted entries that become un-referenced in the process.
*
* @param owner {@link MountOwner} to cleanup references for
*/
public static void cleanup(MountOwner owner) {
final Set references = ownerReferences.remove(owner);
if (references != null) {
for (RegistryEntry entry : references) {
entry.removeInboundReference(owner);
}
}
owner.onCleanup();
}
/**
* Determines whether a target {@link VirtualFile} is mounted.
*
* @param target target to check
* @return true if mounted, false otherwise
*/
public static boolean isMounted(VirtualFile target) {
return getEntry(target).isMounted();
}
/**
* Get the entry from the tree creating the entry if not present.
*
* @param virtualFile entry's owner file
* @return registry entry
*/
static RegistryEntry getEntry(VirtualFile virtualFile) {
if (virtualFile == null) {
throw MESSAGES.nullArgument("VirutalFile");
}
return rootEntry.find(virtualFile);
}
private static TempFileProvider getTempFileProvider() throws IOException {
if (tempFileProvider == null) { tempFileProvider = TempFileProvider.create("automount", Executors.newScheduledThreadPool(2)); }
return tempFileProvider;
}
static class RegistryEntry {
private final ConcurrentMap children = new ConcurrentHashMap();
private final Set inboundReferences = new HashSet();
private final List handles = new LinkedList();
private final AtomicBoolean mounted = new AtomicBoolean();
private void mount(VirtualFile target, MountConfig mountConfig) throws IOException {
if (mounted.compareAndSet(false, true)) {
if (target.isFile()) {
VFSLogger.ROOT_LOGGER.debugf("Automounting: %s with options %s", target, mountConfig);
final TempFileProvider provider = getTempFileProvider();
if (mountConfig.mountExpanded()) {
if (mountConfig.copyTarget()) { handles.add(VFS.mountZipExpanded(target, target, provider)); } else {
handles.add(VFS.mountZipExpanded(target.getPhysicalFile(), target, provider));
}
} else {
if (mountConfig.copyTarget()) { handles.add(VFS.mountZip(target, target, provider)); } else {
handles.add(VFS.mountZip(target.getPhysicalFile(), target, provider));
}
}
}
}
}
private void removeInboundReference(MountOwner owner) {
inboundReferences.remove(owner);
if (inboundReferences.isEmpty()) {
cleanup();
}
}
void cleanup() {
if (mounted.compareAndSet(true, false)) {
VFSUtils.safeClose(handles);
handles.clear();
final Collection entries = getEntriesRecursive();
for (RegistryEntry entry : entries) {
entry.cleanup();
}
}
}
private boolean isMounted() {
return mounted.get();
}
private RegistryEntry find(VirtualFile file) {
return find(PathTokenizer.getTokens(file.getPathName()));
}
private RegistryEntry find(List path) {
if (path.isEmpty()) {
return this;
}
final String current = path.remove(0);
children.putIfAbsent(current, new RegistryEntry());
final RegistryEntry childEntry = children.get(current);
return childEntry.find(path);
}
private Collection getEntriesRecursive() {
final List allHandles = new LinkedList();
collectEntries(this, allHandles);
return allHandles;
}
private void collectEntries(RegistryEntry registryEntry, List entries) {
for (RegistryEntry childEntry : registryEntry.children.values()) {
collectEntries(childEntry, entries);
entries.add(childEntry);
}
}
}
}