You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@synapse.apache.org by ra...@apache.org on 2010/09/23 08:04:34 UTC

svn commit: r1000332 [5/27] - in /synapse/branches/commons-vfs-2-synapse-2.0: ./ core/ core/src/ core/src/main/ core/src/main/java/ core/src/main/java/org/ core/src/main/java/org/apache/ core/src/main/java/org/apache/commons/ core/src/main/java/org/apa...

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileMonitor.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,691 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileListener;
+import org.apache.commons.vfs.FileMonitor;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.provider.AbstractFileSystem;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * A polling {@link FileMonitor} implementation.<br />
+ * <br />
+ * The DefaultFileMonitor is a Thread based polling file system monitor with a 1
+ * second delay.<br />
+ * <br />
+ * <b>Design:</b>
+ * <p>
+ * There is a Map of monitors known as FileMonitorAgents. With the thread running,
+ * each FileMonitorAgent object is asked to "check" on the file it is
+ * responsible for.
+ * To do this check, the cache is cleared.
+ * </p>
+ * <ul>
+ * <li>If the file existed before the refresh and it no longer exists, a delete
+ * event is fired.</li>
+ * <li>If the file existed before the refresh and it still exists, check the
+ * last modified timestamp to see if that has changed.</li>
+ * <li>If it has, fire a change event.</li>
+ * </ul>
+ * <p>
+ * With each file delete, the FileMonitorAgent of the parent is asked to
+ * re-build its
+ * list of children, so that they can be accurately checked when there are new
+ * children.<br/>
+ * New files are detected during each "check" as each file does a check for new
+ * children.
+ * If new children are found, create events are fired recursively if recursive
+ * descent is
+ * enabled.
+ * </p>
+ * <p>
+ * For performance reasons, added a delay that increases as the number of files
+ * monitored
+ * increases. The default is a delay of 1 second for every 1000 files processed.
+ * </p>
+ * <br /><b>Example usage:</b><br /><pre>
+ * FileSystemManager fsManager = VFS.getManager();
+ * FileObject listendir = fsManager.resolveFile("/home/username/monitored/");
+ * <p/>
+ * DefaultFileMonitor fm = new DefaultFileMonitor(new CustomFileListener());
+ * fm.setRecursive(true);
+ * fm.addFile(listendir);
+ * fm.start();
+ * </pre>
+ * <i>(where CustomFileListener is a class that implements the FileListener
+ * interface.)</i>
+ *
+ * @author <a href="mailto:xknight@users.sourceforge.net">Christopher Ottley</a>
+ * @version $Revision: 804548 $ $Date: 2009-08-16 07:42:32 +0530 (Sun, 16 Aug 2009) $
+ */
+public class DefaultFileMonitor implements Runnable, FileMonitor
+{
+    private static final Log LOG = LogFactory.getLog(DefaultFileMonitor.class);
+
+    private static final long DEFAULT_DELAY = 1000;
+
+    private static final int DEFAULT_MAX_FILES = 1000;
+
+    /**
+     * Map from FileName to FileObject being monitored.
+     */
+    private final Map monitorMap = new HashMap();
+
+    /**
+     * The low priority thread used for checking the files being monitored.
+     */
+    private Thread monitorThread;
+
+    /**
+     * File objects to be removed from the monitor map.
+     */
+    private Stack deleteStack = new Stack();
+
+    /**
+     * File objects to be added to the monitor map.
+     */
+    private Stack addStack = new Stack();
+
+    /**
+     * A flag used to determine if the monitor thread should be running.
+     */
+    private boolean shouldRun = true;
+
+    /**
+     * A flag used to determine if adding files to be monitored should be recursive.
+     */
+    private boolean recursive;
+
+    /**
+     * Set the delay between checks
+     */
+    private long delay = DEFAULT_DELAY;
+
+    /**
+     * Set the number of files to check until a delay will be inserted
+     */
+    private int checksPerRun = DEFAULT_MAX_FILES;
+
+    /**
+     * A listener object that if set, is notified on file creation and deletion.
+     */
+    private final FileListener listener;
+
+    public DefaultFileMonitor(final FileListener listener)
+    {
+        this.listener = listener;
+    }
+
+    /**
+     * Access method to get the recursive setting when adding files for monitoring.
+     * @return true if monitoring is enabled for children.
+     */
+    public boolean isRecursive()
+    {
+        return this.recursive;
+    }
+
+    /**
+     * Access method to set the recursive setting when adding files for monitoring.
+     * @param newRecursive true if monitoring should be enabled for children.
+     */
+    public void setRecursive(final boolean newRecursive)
+    {
+        this.recursive = newRecursive;
+    }
+
+    /**
+     * Access method to get the current FileListener object notified when there
+     * are changes with the files added.
+     * @return The FileListener.
+     */
+    FileListener getFileListener()
+    {
+        return this.listener;
+    }
+
+    /**
+     * Adds a file to be monitored.
+     * @param file The FileObject to monitor.
+     */
+    public void addFile(final FileObject file)
+    {
+        doAddFile(file);
+        try
+        {
+            // add all direct children too
+            if (file.getType().hasChildren())
+            {
+                // Traverse the children
+                final FileObject[] children = file.getChildren();
+                for (int i = 0; i < children.length; i++)
+                {
+                    doAddFile(children[i]);
+                }
+            }
+        }
+        catch (FileSystemException fse)
+        {
+            LOG.error(fse.getLocalizedMessage(), fse);
+        }
+    }
+
+    /**
+     * Adds a file to be monitored.
+     * @param file The FileObject to add.
+     */
+    private void doAddFile(final FileObject file)
+    {
+        synchronized (this.monitorMap)
+        {
+            if (this.monitorMap.get(file.getName()) == null)
+            {
+                this.monitorMap.put(file.getName(), new FileMonitorAgent(this,
+                    file));
+
+                try
+                {
+                    if (this.listener != null)
+                    {
+                        file.getFileSystem().addListener(file, this.listener);
+                    }
+
+                    if (file.getType().hasChildren() && this.recursive)
+                    {
+                        // Traverse the children
+                        final FileObject[] children = file.getChildren();
+                        for (int i = 0; i < children.length; i++)
+                        {
+                            this.addFile(children[i]); // Add depth first
+                        }
+                    }
+
+                }
+                catch (FileSystemException fse)
+                {
+                    LOG.error(fse.getLocalizedMessage(), fse);
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Removes a file from being monitored.
+     * @param file The FileObject to remove from monitoring.
+     */
+    public void removeFile(final FileObject file)
+    {
+        synchronized (this.monitorMap)
+        {
+            FileName fn = file.getName();
+            if (this.monitorMap.get(fn) != null)
+            {
+                FileObject parent;
+                try
+                {
+                    parent = file.getParent();
+                }
+                catch (FileSystemException fse)
+                {
+                    parent = null;
+                }
+
+                this.monitorMap.remove(fn);
+
+                if (parent != null)
+                { // Not the root
+                    FileMonitorAgent parentAgent =
+                        (FileMonitorAgent) this.monitorMap.get(parent.getName());
+                    if (parentAgent != null)
+                    {
+                        parentAgent.resetChildrenList();
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Queues a file for removal from being monitored.
+     * @param file The FileObject to be removed from being monitored.
+     */
+    protected void queueRemoveFile(final FileObject file)
+    {
+        this.deleteStack.push(file);
+    }
+
+    /**
+     * Get the delay between runs.
+     * @return The delay period.
+     */
+    public long getDelay()
+    {
+        return delay;
+    }
+
+    /**
+     * Set the delay between runs.
+     * @param delay The delay period.
+     */
+    public void setDelay(long delay)
+    {
+        if (delay > 0)
+        {
+            this.delay = delay;
+        }
+        else
+        {
+            this.delay = DEFAULT_DELAY;
+        }
+    }
+
+    /**
+     * get the number of files to check per run.
+     * @return The number of files to check per iteration.
+     */
+    public int getChecksPerRun()
+    {
+        return checksPerRun;
+    }
+
+    /**
+     * set the number of files to check per run.
+     * a additional delay will be added if there are more files to check
+     *
+     * @param checksPerRun a value less than 1 will disable this feature
+     */
+    public void setChecksPerRun(int checksPerRun)
+    {
+        this.checksPerRun = checksPerRun;
+    }
+
+    /**
+     * Queues a file for addition to be monitored.
+     * @param file The FileObject to add.
+     */
+    protected void queueAddFile(final FileObject file)
+    {
+        this.addStack.push(file);
+    }
+
+    /**
+     * Starts monitoring the files that have been added.
+     */
+    public void start()
+    {
+        if (this.monitorThread == null)
+        {
+            this.monitorThread = new Thread(this);
+            this.monitorThread.setDaemon(true);
+            this.monitorThread.setPriority(Thread.MIN_PRIORITY);
+        }
+        this.monitorThread.start();
+    }
+
+    /**
+     * Stops monitoring the files that have been added.
+     */
+    public void stop()
+    {
+        this.shouldRun = false;
+    }
+
+    /**
+     * Asks the agent for each file being monitored to check its file for changes.
+     */
+    public void run()
+    {
+        mainloop:
+        while (!monitorThread.isInterrupted() && this.shouldRun)
+        {
+            while (!this.deleteStack.empty())
+            {
+                this.removeFile((FileObject) this.deleteStack.pop());
+            }
+
+            // For each entry in the map
+            Object[] fileNames;
+            synchronized (this.monitorMap)
+            {
+                fileNames = this.monitorMap.keySet().toArray();
+            }
+            for (int iterFileNames = 0; iterFileNames < fileNames.length;
+                 iterFileNames++)
+            {
+                FileName fileName = (FileName) fileNames[iterFileNames];
+                FileMonitorAgent agent;
+                synchronized (this.monitorMap)
+                {
+                    agent = (FileMonitorAgent) this.monitorMap.get(fileName);
+                }
+                if (agent != null)
+                {
+                    agent.check();
+                }
+
+                if (getChecksPerRun() > 0)
+                {
+                    if ((iterFileNames % getChecksPerRun()) == 0)
+                    {
+                        try
+                        {
+                            Thread.sleep(getDelay());
+                        }
+                        catch (InterruptedException e)
+                        {
+                            // Woke up.
+                        }
+                    }
+                }
+
+                if (monitorThread.isInterrupted() || !this.shouldRun)
+                {
+                    continue mainloop;
+                }
+            }
+
+            while (!this.addStack.empty())
+            {
+                this.addFile((FileObject) this.addStack.pop());
+            }
+
+            try
+            {
+                Thread.sleep(getDelay());
+            }
+            catch (InterruptedException e)
+            {
+                continue;
+            }
+        }
+
+        this.shouldRun = true;
+    }
+
+    /**
+     * File monitor agent.
+     */
+    private static final class FileMonitorAgent
+    {
+        private final FileObject file;
+        private final DefaultFileMonitor fm;
+
+        private boolean exists;
+        private long timestamp;
+        private Map children;
+
+        private FileMonitorAgent(DefaultFileMonitor fm, FileObject file)
+        {
+            this.fm = fm;
+            this.file = file;
+
+            this.refresh();
+            this.resetChildrenList();
+
+            try
+            {
+                this.exists = this.file.exists();
+            }
+            catch (FileSystemException fse)
+            {
+                this.exists = false;
+                this.timestamp = -1;
+            }
+
+            if (this.exists)
+            {
+                try
+                {
+                    this.timestamp = this.file.getContent().getLastModifiedTime();
+                }
+                catch (FileSystemException fse)
+                {
+                    this.timestamp = -1;
+                }
+            }
+        }
+
+        private void resetChildrenList()
+        {
+            try
+            {
+                if (this.file.getType().hasChildren())
+                {
+                    this.children = new HashMap();
+                    FileObject[] childrenList = this.file.getChildren();
+                    for (int i = 0; i < childrenList.length; i++)
+                    {
+                        this.children.put(childrenList[i].getName(), new
+                            Object()); // null?
+                    }
+                }
+            }
+            catch (FileSystemException fse)
+            {
+                this.children = null;
+            }
+        }
+
+
+        /**
+         * Clear the cache and re-request the file object
+         */
+        private void refresh()
+        {
+            try
+            {
+                this.file.refresh();
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+
+        /**
+         * Recursively fires create events for all children if recursive descent is
+         * enabled. Otherwise the create event is only fired for the initial
+         * FileObject.
+         * @param child The child to add.
+         */
+        private void fireAllCreate(FileObject child)
+        {
+            // Add listener so that it can be triggered
+            if (this.fm.getFileListener() != null)
+            {
+                child.getFileSystem().addListener(child, this.fm.getFileListener());
+            }
+
+            ((AbstractFileSystem) child.getFileSystem()).fireFileCreated(child);
+
+            // Remove it because a listener is added in the queueAddFile
+            if (this.fm.getFileListener() != null)
+            {
+                child.getFileSystem().removeListener(child,
+                    this.fm.getFileListener());
+            }
+
+            this.fm.queueAddFile(child); // Add
+
+            try
+            {
+
+                if (this.fm.isRecursive())
+                {
+                    if (child.getType().hasChildren())
+                    {
+                        FileObject[] newChildren = child.getChildren();
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            fireAllCreate(newChildren[i]);
+                        }
+                    }
+                }
+
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+        /**
+         * Only checks for new children. If children are removed, they'll
+         * eventually be checked.
+         */
+        private void checkForNewChildren()
+        {
+            try
+            {
+                if (this.file.getType().hasChildren())
+                {
+                    FileObject[] newChildren = this.file.getChildren();
+                    if (this.children != null)
+                    {
+                        // See which new children are not listed in the current children map.
+                        Map newChildrenMap = new HashMap();
+                        Stack missingChildren = new Stack();
+
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            newChildrenMap.put(newChildren[i].getName(), new
+                                Object()); // null ?
+                            // If the child's not there
+                            if
+                                (!this.children.containsKey(newChildren[i].getName()))
+                            {
+                                missingChildren.push(newChildren[i]);
+                            }
+                        }
+
+                        this.children = newChildrenMap;
+
+                        // If there were missing children
+                        if (!missingChildren.empty())
+                        {
+
+                            while (!missingChildren.empty())
+                            {
+                                FileObject child = (FileObject)
+                                    missingChildren.pop();
+                                this.fireAllCreate(child);
+                            }
+                        }
+
+                    }
+                    else
+                    {
+                        // First set of children - Break out the cigars
+                        if (newChildren.length > 0)
+                        {
+                            this.children = new HashMap();
+                        }
+                        for (int i = 0; i < newChildren.length; i++)
+                        {
+                            this.children.put(newChildren[i].getName(), new
+                                Object()); // null?
+                            this.fireAllCreate(newChildren[i]);
+                        }
+                    }
+                }
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+        private void check()
+        {
+            this.refresh();
+
+            try
+            {
+                // If the file existed and now doesn't
+                if (this.exists && !this.file.exists())
+                {
+                    this.exists = this.file.exists();
+                    this.timestamp = -1;
+
+                    // Fire delete event
+
+                    ((AbstractFileSystem)
+                        this.file.getFileSystem()).fireFileDeleted(this.file);
+
+                    // Remove listener in case file is re-created. Don't want to fire twice.
+                    if (this.fm.getFileListener() != null)
+                    {
+                        this.file.getFileSystem().removeListener(this.file,
+                            this.fm.getFileListener());
+                    }
+
+                    // Remove from map
+                    this.fm.queueRemoveFile(this.file);
+                }
+                else if (this.exists && this.file.exists())
+                {
+
+                    // Check the timestamp to see if it has been modified
+                    if (this.timestamp != this.file.getContent().getLastModifiedTime())
+                    {
+                        this.timestamp = this.file.getContent().getLastModifiedTime();
+                        // Fire change event
+
+                        // Don't fire if it's a folder because new file children
+                        // and deleted files in a folder have their own event triggered.
+                        if (!this.file.getType().hasChildren())
+                        {
+                            ((AbstractFileSystem)
+                                this.file.getFileSystem()).fireFileChanged(this.file);
+                        }
+                    }
+
+                }
+                else if (!this.exists && this.file.exists())
+                {
+                    this.exists = this.file.exists();
+                    this.timestamp = this.file.getContent().getLastModifiedTime();
+                    // Don't fire if it's a folder because new file children
+                    // and deleted files in a folder have their own event triggered.
+                    if (!this.file.getType().hasChildren())
+                    {
+                        ((AbstractFileSystem)
+                                this.file.getFileSystem()).fireFileCreated(this.file);
+                    }
+                }
+
+                this.checkForNewChildren();
+
+            }
+            catch (FileSystemException fse)
+            {
+                LOG.error(fse.getLocalizedMessage(), fse);
+            }
+        }
+
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileReplicator.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,252 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSelector;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.VfsLog;
+import org.apache.commons.vfs.provider.AbstractVfsComponent;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.util.Messages;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ * A simple file replicator and temporary file store.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 804548 $ $Date: 2009-08-16 07:42:32 +0530 (Sun, 16 Aug 2009) $
+ */
+public class DefaultFileReplicator
+    extends AbstractVfsComponent
+    implements FileReplicator, TemporaryFileStore
+{
+    private static final char[] TMP_RESERVED_CHARS = new char[]
+        {
+            '?', '/', '\\', ' ', '&', '"', '\'', '*', '#', ';', ':', '<', '>', '|'
+        };
+    private static Log log = LogFactory.getLog(DefaultFileReplicator.class);
+
+    private static final int MASK = 0xffff;
+
+    private final ArrayList copies = new ArrayList();
+    private File tempDir;
+    private long filecount;
+    private boolean tempDirMessageLogged;
+
+    /**
+     * constructor to set the location of the temporary directory.
+     *
+     * @param tempDir The temporary directory.
+     */
+    public DefaultFileReplicator(final File tempDir)
+    {
+        this.tempDir = tempDir;
+    }
+
+    public DefaultFileReplicator()
+    {
+    }
+
+    /**
+     * Initialises this component.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void init() throws FileSystemException
+    {
+        if (tempDir == null)
+        {
+            String baseTmpDir = System.getProperty("java.io.tmpdir");
+
+            tempDir = new File(baseTmpDir, "vfs_cache").getAbsoluteFile();
+        }
+
+        filecount = new Random().nextInt() & MASK;
+
+        if (!tempDirMessageLogged)
+        {
+            final String message = Messages.getString("vfs.impl/temp-dir.info", tempDir);
+            VfsLog.info(getLogger(), log, message);
+
+            tempDirMessageLogged = true;
+        }
+    }
+
+    /**
+     * Closes the replicator, deleting all temporary files.
+     */
+    public void close()
+    {
+        // Delete the temporary files
+        synchronized (copies)
+        {
+            while (copies.size() > 0)
+            {
+                final File file = (File) removeFile();
+                deleteFile(file);
+            }
+        }
+
+        // Clean up the temp directory, if it is empty
+        if (tempDir != null && tempDir.exists() && tempDir.list().length == 0)
+        {
+            tempDir.delete();
+            tempDir = null;
+        }
+    }
+
+    /**
+     * physically deletes the file from the filesystem
+     * @param file The File to delete.
+     */
+    protected void deleteFile(File file)
+    {
+        try
+        {
+            final FileObject fileObject = getContext().toFileObject(file);
+            fileObject.delete(Selectors.SELECT_ALL);
+        }
+        catch (final FileSystemException e)
+        {
+            final String message = Messages.getString("vfs.impl/delete-temp.warn", file.getName());
+            VfsLog.warn(getLogger(), log, message, e);
+        }
+    }
+
+    /**
+     * removes a file from the copies list. Will be used for cleanup. <br/>
+     * Notice: The system awaits that the returning object can be cast to a java.io.File
+     * @return the File that was removed.
+     */
+    protected Object removeFile()
+    {
+        synchronized (copies)
+        {
+            return copies.remove(0);
+        }
+    }
+
+    /**
+     * removes a instance from the list of copies
+     * @param file The File to remove.
+     */
+    protected void removeFile(Object file)
+    {
+        synchronized (copies)
+        {
+            copies.remove(file);
+        }
+    }
+
+    /**
+     * Allocates a new temporary file.
+     * @param baseName the base file name.
+     * @return The created File.
+     * @throws FileSystemException if an error occurs.
+     */
+    public File allocateFile(final String baseName) throws FileSystemException
+    {
+        // Create a unique-ish file name
+        final String basename = createFilename(baseName);
+        synchronized (this)
+        {
+            filecount++;
+        }
+
+        return createAndAddFile(tempDir, basename);
+    }
+
+    protected File createAndAddFile(final File parent, final String basename) throws FileSystemException
+    {
+        final File file = createFile(tempDir, basename);
+
+        // Keep track to delete later
+        addFile(file);
+
+        return file;
+    }
+
+    protected void addFile(Object file)
+    {
+        synchronized (copies)
+        {
+            copies.add(file);
+        }
+    }
+
+    protected long getFilecount()
+    {
+        return filecount;
+    }
+
+    /**
+     * create the temporary file name
+     * @param baseName The base to prepend to the file name being created.
+     * @return the name of the File.
+     */
+    protected String createFilename(final String baseName)
+    {
+        // BUG29007
+        // return baseName + "_" + getFilecount() + ".tmp";
+
+        // imario@apache.org: BUG34976 get rid of maybe reserved and dangerous characters
+        // e.g. to allow replication of http://hostname.org/fileservlet?file=abc.txt
+        String safeBasename = UriParser.encode(baseName, TMP_RESERVED_CHARS).replace('%', '_');
+        return "tmp_" + getFilecount() + "_" + safeBasename;
+    }
+
+    /**
+     * create the temporary file
+     * @param parent The file to use as the parent of the file being created.
+     * @param name The name of the file to create.
+     * @return The File that was created.
+     * @throws FileSystemException if an error occurs creating the file.
+     */
+    protected File createFile(final File parent, final String name) throws FileSystemException
+    {
+        return new File(parent, UriParser.decode(name));
+    }
+
+    /**
+     * Creates a local copy of the file, and all its descendents.
+     * @param srcFile The file to copy.
+     * @param selector The FileSelector.
+     * @return the created File.
+     * @throws FileSystemException if an error occurs copying the file.
+     */
+    public File replicateFile(final FileObject srcFile,
+                              final FileSelector selector)
+        throws FileSystemException
+    {
+        final String basename = srcFile.getName().getBaseName();
+        final File file = allocateFile(basename);
+
+        // Copy from the source file
+        final FileObject destFile = getContext().toFileObject(file);
+        destFile.copyFrom(srcFile, selector);
+
+        return file;
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemConfigBuilder.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticator;
+
+/**
+ * Default options usable for all filesystems.
+ * @author <a href="http://commons.apache.org/vfs/team-list.html">Commons VFS team</a>
+ */
+public class DefaultFileSystemConfigBuilder extends FileSystemConfigBuilder
+{
+    /** The default FileSystemConfigBuilder */
+    private static final DefaultFileSystemConfigBuilder BUILDER = new DefaultFileSystemConfigBuilder();
+
+    public static DefaultFileSystemConfigBuilder getInstance()
+    {
+        return BUILDER;
+    }
+
+    /**
+     * Sets the user authenticator to get authentication informations.
+     * @param opts The FileSystemOptions.
+     * @param userAuthenticator The UserAuthenticator.
+     * @throws FileSystemException if an error occurs setting the UserAuthenticator.
+     */
+    public void setUserAuthenticator(FileSystemOptions opts, UserAuthenticator userAuthenticator)
+            throws FileSystemException
+    {
+        setParam(opts, "userAuthenticator", userAuthenticator);
+    }
+
+    /**
+     * @see #setUserAuthenticator
+     * @param opts The FileSystemOptions.
+     * @return The UserAuthenticator.
+     */
+    public UserAuthenticator getUserAuthenticator(FileSystemOptions opts)
+    {
+        return (UserAuthenticator) getParam(opts, "userAuthenticator");
+    }
+
+    protected Class getConfigClass()
+    {
+        return DefaultFileSystemConfigBuilder.class;
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultFileSystemManager.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,1170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.vfs.CacheStrategy;
+import org.apache.commons.vfs.FileContentInfoFactory;
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystem;
+import org.apache.commons.vfs.FileSystemConfigBuilder;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.FileType;
+import org.apache.commons.vfs.FilesCache;
+import org.apache.commons.vfs.NameScope;
+import org.apache.commons.vfs.VFS;
+import org.apache.commons.vfs.cache.SoftRefFilesCache;
+import org.apache.commons.vfs.operations.FileOperationProvider;
+import org.apache.commons.vfs.provider.AbstractFileName;
+import org.apache.commons.vfs.provider.AbstractFileProvider;
+import org.apache.commons.vfs.provider.DefaultURLStreamHandler;
+import org.apache.commons.vfs.provider.FileProvider;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.LocalFileProvider;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.UriParser;
+import org.apache.commons.vfs.provider.VfsComponent;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URLStreamHandler;
+import java.net.URLStreamHandlerFactory;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A default file system manager implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 804548 $ $Date: 2006-03-30 21:16:24 +0200 (Do, 30 Mrz
+ *          2006) $
+ */
+public class DefaultFileSystemManager implements FileSystemManager
+{
+    /**
+     * The provider for local files.
+     */
+    private LocalFileProvider localFileProvider;
+
+    /**
+     * The default provider.
+     */
+    private FileProvider defaultProvider;
+
+    /**
+     * The file replicator to use.
+     */
+    private FileReplicator fileReplicator;
+
+    /**
+     * Mapping from URI scheme to FileProvider.
+     */
+    private final Map providers = new HashMap();
+
+    /**
+     * All components used by this manager.
+     */
+    private final ArrayList components = new ArrayList();
+
+    /**
+     * The base file to use for relative URI.
+     */
+    private FileObject baseFile;
+
+    /**
+     * The files cache
+     */
+    private FilesCache filesCache;
+
+    /**
+     * The cache strategy
+     */
+    private CacheStrategy fileCacheStrategy;
+
+    /**
+     * Class which decorates all returned fileObjects
+     */
+    private Class fileObjectDecorator;
+    private Constructor fileObjectDecoratorConst;
+
+    /**
+     * The class to use to determine the content-type (mime-type)
+     */
+    private FileContentInfoFactory fileContentInfoFactory;
+
+    /**
+     * The logger to use.
+     */
+    private Log log = LogFactory.getLog(getClass());
+
+    /**
+     * The context to pass to providers.
+     */
+    private final DefaultVfsComponentContext context = new DefaultVfsComponentContext(
+            this);
+
+    private TemporaryFileStore tempFileStore;
+    private final FileTypeMap map = new FileTypeMap();
+    private final VirtualFileProvider vfsProvider = new VirtualFileProvider();
+    private boolean init;
+
+    private final Map operationProviders = new HashMap();
+
+    /**
+     * Returns the logger used by this manager.
+     * @return the Logger.
+     */
+    protected Log getLogger()
+    {
+        return log;
+    }
+
+    /**
+     * Registers a file system provider. The manager takes care of all lifecycle
+     * management. A provider may be registered multiple times.
+     *
+     * @param urlScheme
+     *            The scheme the provider will handle.
+     * @param provider
+     *            The provider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addProvider(final String urlScheme, final FileProvider provider)
+            throws FileSystemException
+    {
+        addProvider(new String[] {urlScheme}, provider);
+    }
+
+    /**
+     * Registers a file system provider. The manager takes care of all lifecycle
+     * management. A provider may be registered multiple times.
+     *
+     * @param urlSchemes
+     *            The schemes the provider will handle.
+     * @param provider
+     *            The provider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addProvider(final String[] urlSchemes,
+            final FileProvider provider) throws FileSystemException
+    {
+        // Warn about duplicate providers
+        for (int i = 0; i < urlSchemes.length; i++)
+        {
+            final String scheme = urlSchemes[i];
+            if (providers.containsKey(scheme))
+            {
+                throw new FileSystemException(
+                        "vfs.impl/multiple-providers-for-scheme.error", scheme);
+            }
+        }
+
+        // Contextualise the component (if not already)
+        setupComponent(provider);
+
+        // Add to map
+        for (int i = 0; i < urlSchemes.length; i++)
+        {
+            final String scheme = urlSchemes[i];
+            providers.put(scheme, provider);
+        }
+
+        if (provider instanceof LocalFileProvider && localFileProvider == null)
+        {
+            localFileProvider = (LocalFileProvider) provider;
+        }
+    }
+
+    /**
+     * Returns true if this manager has a provider for a particular scheme.
+     * @param scheme The scheme to check.
+     * @return true if a provider is configured for this scheme, false otherwise.
+     */
+    public boolean hasProvider(final String scheme)
+    {
+        return providers.containsKey(scheme);
+    }
+
+    /**
+     * Adds an filename extension mapping.
+     *
+     * @param extension The file name extension.
+     * @param scheme The scheme to use for files with this extension.
+     */
+    public void addExtensionMap(final String extension, final String scheme)
+    {
+        map.addExtension(extension, scheme);
+    }
+
+    /**
+     * Adds a mime type mapping.
+     *
+     * @param mimeType The mime type.
+     * @param scheme The scheme to use for files with this mime type.
+     */
+    public void addMimeTypeMap(final String mimeType, final String scheme)
+    {
+        map.addMimeType(mimeType, scheme);
+    }
+
+    /**
+     * Sets the default provider. This is the provider that will handle URI with
+     * unknown schemes. The manager takes care of all lifecycle management.
+     * @param provider The FileProvider.
+     * @throws FileSystemException if an error occurs setting the provider.
+     */
+    public void setDefaultProvider(final FileProvider provider)
+            throws FileSystemException
+    {
+        setupComponent(provider);
+        defaultProvider = provider;
+    }
+
+    /**
+     * Returns the filesCache implementation used to cache files.
+     * @return The FilesCache.
+     */
+    public FilesCache getFilesCache()
+    {
+        return filesCache;
+    }
+
+    /**
+     * Sets the filesCache implementation used to cache files.
+     * @param filesCache The FilesCache.
+     * @throws FileSystemException if an error occurs setting the cache..
+     */
+    public void setFilesCache(final FilesCache filesCache)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.filesCache = filesCache;
+    }
+
+    /**
+     * <p>
+     * Set the cache strategy to use when dealing with file object data. You can
+     * set it only once before the FileSystemManager is initialized.
+     * <p />
+     * <p>
+     * The default is {@link CacheStrategy#ON_RESOLVE}
+     * </p>
+     *
+     * @param fileCacheStrategy The CacheStrategy to use.
+     * @throws FileSystemException
+     *             if this is not possible. e.g. it is already set.
+     */
+    public void setCacheStrategy(final CacheStrategy fileCacheStrategy)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.fileCacheStrategy = fileCacheStrategy;
+    }
+
+    /**
+     * Get the cache strategy used.
+     * @return The CacheStrategy.
+     */
+    public CacheStrategy getCacheStrategy()
+    {
+        return fileCacheStrategy;
+    }
+
+    /**
+     * Get the file object decorator used.
+     * @return The decorator.
+     */
+    public Class getFileObjectDecorator()
+    {
+        return fileObjectDecorator;
+    }
+
+    /**
+     * The constructor associated to the fileObjectDecorator.
+     * We cache it here for performance reasons.
+     * @return The decorator's Constructor.
+     */
+    public Constructor getFileObjectDecoratorConst()
+    {
+        return fileObjectDecoratorConst;
+    }
+
+    /**
+     * Set a fileObject decorator to be used for ALL returned file objects.
+     *
+     * @param fileObjectDecorator must be inherted from {@link DecoratedFileObject} a has to provide a
+     * constructor with a single {@link FileObject} as argument
+     * @throws FileSystemException if an error occurs setting the decorator.
+     */
+    public void setFileObjectDecorator(Class fileObjectDecorator) throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+        if (!DecoratedFileObject.class.isAssignableFrom(fileObjectDecorator))
+        {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName());
+        }
+
+        try
+        {
+            fileObjectDecoratorConst = fileObjectDecorator.getConstructor(new Class[]{FileObject.class});
+        }
+        catch (NoSuchMethodException e)
+        {
+            throw new FileSystemException("vfs.impl/invalid-decorator.error", fileObjectDecorator.getName(), e);
+        }
+
+        this.fileObjectDecorator = fileObjectDecorator;
+    }
+
+    /**
+     * get the fileContentInfoFactory used to determine the infos of a file
+     * content.
+     * @return The FileContentInfoFactory.
+     */
+    public FileContentInfoFactory getFileContentInfoFactory()
+    {
+        return fileContentInfoFactory;
+    }
+
+    /**
+     * set the fileContentInfoFactory used to determine the infos of a file
+     * content.
+     * @param fileContentInfoFactory The FileContentInfoFactory.
+     * @throws FileSystemException if an error occurs setting the FileContentInfoFactory.
+     */
+    public void setFileContentInfoFactory(FileContentInfoFactory fileContentInfoFactory)
+            throws FileSystemException
+    {
+        if (init)
+        {
+            throw new FileSystemException("vfs.impl/already-inited.error");
+        }
+
+        this.fileContentInfoFactory = fileContentInfoFactory;
+    }
+
+    /**
+     * Sets the file replicator to use. The manager takes care of all lifecycle
+     * management.
+     * @param replicator The FileReplicator.
+     * @throws FileSystemException if an error occurs setting the replicator.
+     */
+    public void setReplicator(final FileReplicator replicator)
+            throws FileSystemException
+    {
+        setupComponent(replicator);
+        fileReplicator = replicator;
+    }
+
+    /**
+     * Sets the temporary file store to use. The manager takes care of all
+     * lifecycle management.
+     * @param tempFileStore The temporary FileStore.
+     * @throws FileSystemException if an error occurs adding the file store.
+     */
+    public void setTemporaryFileStore(final TemporaryFileStore tempFileStore)
+            throws FileSystemException
+    {
+        setupComponent(tempFileStore);
+        this.tempFileStore = tempFileStore;
+    }
+
+    /**
+     * Sets the logger to use.
+     * @param log The Logger to use.
+     */
+    public void setLogger(final Log log)
+    {
+        this.log = log;
+    }
+
+    /**
+     * Initialises a component, if it has not already been initialised.
+     * @param component The component to setup.
+     * @throws FileSystemException if an error occurs.
+     */
+    private void setupComponent(final Object component)
+            throws FileSystemException
+    {
+        if (!components.contains(component))
+        {
+            if (component instanceof VfsComponent)
+            {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.setLogger(getLogger());
+                vfsComponent.setContext(context);
+                vfsComponent.init();
+            }
+            components.add(component);
+        }
+    }
+
+    /**
+     * Closes a component, if it has not already been closed.
+     * @param component The component to close.
+     */
+    private void closeComponent(final Object component)
+    {
+        if (component != null && components.contains(component))
+        {
+            if (component instanceof VfsComponent)
+            {
+                final VfsComponent vfsComponent = (VfsComponent) component;
+                vfsComponent.close();
+            }
+            components.remove(component);
+        }
+    }
+
+    /**
+     * Returns the file replicator.
+     *
+     * @return The file replicator. Never returns null.
+     * @throws FileSystemException if there is no FileReplicator.
+     */
+    public FileReplicator getReplicator() throws FileSystemException
+    {
+        if (fileReplicator == null)
+        {
+            throw new FileSystemException("vfs.impl/no-replicator.error");
+        }
+        return fileReplicator;
+    }
+
+    /**
+     * Returns the temporary file store.
+     *
+     * @return The file store. Never returns null.
+     * @throws FileSystemException if there is no TemporaryFileStore.
+     */
+    public TemporaryFileStore getTemporaryFileStore()
+            throws FileSystemException
+    {
+        if (tempFileStore == null)
+        {
+            throw new FileSystemException("vfs.impl/no-temp-file-store.error");
+        }
+        return tempFileStore;
+    }
+
+    /**
+     * Initialises this manager.
+     * @throws FileSystemException if an error occurs during initialization.
+     */
+    public void init() throws FileSystemException
+    {
+        if (filesCache == null)
+        {
+            // filesCache = new DefaultFilesCache();
+            filesCache = new SoftRefFilesCache();
+        }
+        if (fileContentInfoFactory == null)
+        {
+            fileContentInfoFactory = new FileContentInfoFilenameFactory();
+        }
+
+        if (fileCacheStrategy == null)
+        {
+            fileCacheStrategy = CacheStrategy.ON_RESOLVE;
+        }
+
+        setupComponent(filesCache);
+        setupComponent(vfsProvider);
+
+        init = true;
+    }
+
+    /**
+     * Closes all files created by this manager, and cleans up any temporary
+     * files. Also closes all providers and the replicator.
+     */
+    public void close()
+    {
+        if (!init)
+        {
+            return;
+        }
+
+        // Close the providers.
+        for (Iterator iterator = providers.values().iterator(); iterator
+                .hasNext();)
+        {
+            final Object provider = iterator.next();
+            closeComponent(provider);
+        }
+
+        // Close the other components
+        closeComponent(defaultProvider);
+        closeComponent(fileReplicator);
+        closeComponent(tempFileStore);
+
+        components.clear();
+        providers.clear();
+        filesCache.close();
+        localFileProvider = null;
+        defaultProvider = null;
+        fileReplicator = null;
+        tempFileStore = null;
+        init = false;
+    }
+
+    /**
+     * Free all resources used by unused filesystems created by this manager.
+     */
+    public void freeUnusedResources()
+    {
+        if (!init)
+        {
+            return;
+        }
+
+        // Close the providers.
+        for (Iterator iterator = providers.values().iterator(); iterator
+                .hasNext();)
+        {
+            final AbstractFileProvider provider = (AbstractFileProvider) iterator
+                    .next();
+            provider.freeUnusedResources();
+        }
+    }
+
+    /**
+     * Sets the base file to use when resolving relative URI.
+     * @param baseFile The new base FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setBaseFile(final FileObject baseFile)
+            throws FileSystemException
+    {
+        this.baseFile = baseFile;
+    }
+
+    /**
+     * Sets the base file to use when resolving relative URI.
+     * @param baseFile The new base FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void setBaseFile(final File baseFile) throws FileSystemException
+    {
+        this.baseFile = getLocalFileProvider().findLocalFile(baseFile);
+    }
+
+    /**
+     * Returns the base file used to resolve relative URI.
+     * @return The FileObject that represents the base file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject getBaseFile() throws FileSystemException
+    {
+        return baseFile;
+    }
+
+    /**
+     * Locates a file by URI.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final String uri) throws FileSystemException
+    {
+        // return resolveFile(baseFile, uri);
+        return resolveFile(getBaseFile(), uri);
+    }
+
+    /**
+     * Locate a file by URI, use the FileSystemOptions for file-system creation.
+     * @param uri The URI of the file to locate.
+     * @param fileSystemOptions The options for the FileSystem.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+
+    public FileObject resolveFile(final String uri,
+            final FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        // return resolveFile(baseFile, uri, fileSystemOptions);
+        return resolveFile(getBaseFile(), uri, fileSystemOptions);
+    }
+
+    /**
+     * Locates a file by URI.
+     * @param baseFile The base File to use to locate the file.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final File baseFile, final String uri)
+            throws FileSystemException
+    {
+        final FileObject baseFileObj = getLocalFileProvider().findLocalFile(
+                baseFile);
+        return resolveFile(baseFileObj, uri);
+    }
+
+    /**
+     * Resolves a URI, relative to a base file.
+     * @param baseFile The base FileOjbect to use to locate the file.
+     * @param uri The URI of the file to locate.
+     * @return The FileObject for the located file.
+     * @throws FileSystemException if the file cannot be located or an error occurs.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String uri)
+            throws FileSystemException
+    {
+        return resolveFile(baseFile, uri, baseFile == null ? null : baseFile
+                .getFileSystem().getFileSystemOptions());
+    }
+
+    /**
+     * Resolves a URI, realtive to a base file with specified FileSystem
+     * configuration.
+     * @param baseFile The base file.
+     * @param uri The file name. May be a fully qualified or relative path or a url.
+     * @param fileSystemOptions Options to pass to the file system.
+     * @return A FileObject representing the target file.
+     * @throws FileSystemException if an error occurs accessing the file.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String uri,
+            final FileSystemOptions fileSystemOptions)
+            throws FileSystemException
+    {
+        final FileObject realBaseFile;
+        if (baseFile != null && VFS.isUriStyle()
+                && baseFile.getName().getType() == FileType.FILE)
+        {
+            realBaseFile = baseFile.getParent();
+        }
+        else
+        {
+            realBaseFile = baseFile;
+        }
+        // TODO: use resolveName and use this name to resolve the fileObject
+
+        UriParser.checkUriEncoding(uri);
+
+        if (uri == null)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        // Extract the scheme
+        final String scheme = UriParser.extractScheme(uri);
+        if (scheme != null)
+        {
+            // An absolute URI - locate the provider
+            final FileProvider provider = (FileProvider) providers.get(scheme);
+            if (provider != null)
+            {
+                return provider.findFile(realBaseFile, uri, fileSystemOptions);
+            }
+            // Otherwise, assume a local file
+        }
+
+        // Handle absolute file names
+        if (localFileProvider != null
+                && localFileProvider.isAbsoluteLocalName(uri))
+        {
+            return localFileProvider.findLocalFile(uri);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider
+            if (defaultProvider == null)
+            {
+                throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                        new Object[] {scheme, uri});
+            }
+            return defaultProvider.findFile(realBaseFile, uri, fileSystemOptions);
+        }
+
+        // Assume a relative name - use the supplied base file
+        if (realBaseFile == null)
+        {
+            throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
+        }
+
+        return realBaseFile.resolveFile(uri);
+    }
+
+    /**
+     * Resolves a name, relative to the file. If the supplied name is an
+     * absolute path, then it is resolved relative to the root of the file
+     * system that the file belongs to. If a relative name is supplied, then it
+     * is resolved relative to this file name.
+     * @param root The base FileName.
+     * @param path The path to the file relative to the base FileName or an absolute path.
+     * @return The constructed FileName.
+     * @throws FileSystemException if an error occurs constructing the FileName.
+     */
+    public FileName resolveName(final FileName root, final String path)
+            throws FileSystemException
+    {
+        return resolveName(root, path, NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Resolves a name, relative to the root.
+     *
+     * @param base the base filename
+     * @param name the name
+     * @param scope the {@link NameScope}
+     * @return The FileName of the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName resolveName(final FileName base, final String name,
+            final NameScope scope) throws FileSystemException
+    {
+        final FileName realBase;
+        if (base != null && VFS.isUriStyle() && base.getType() == FileType.FILE)
+        {
+            realBase = base.getParent();
+        }
+        else
+        {
+            realBase = base;
+        }
+
+        final StringBuffer buffer = new StringBuffer(name);
+
+        // Adjust separators
+        UriParser.fixSeparators(buffer);
+        String scheme = UriParser.extractScheme(buffer.toString());
+
+        // Determine whether to prepend the base path
+        if (name.length() == 0 || (scheme == null && buffer.charAt(0) != FileName.SEPARATOR_CHAR))
+        {
+            // Supplied path is not absolute
+            if (!VFS.isUriStyle())
+            {
+                // when using uris the parent already do have the trailing "/"
+                buffer.insert(0, FileName.SEPARATOR_CHAR);
+            }
+            buffer.insert(0, realBase.getPath());
+        }
+
+        // // UriParser.canonicalizePath(buffer, 0, name.length());
+
+        // Normalise the path
+        FileType fileType = UriParser.normalisePath(buffer);
+
+        // Check the name is ok
+        final String resolvedPath = buffer.toString();
+        if (!AbstractFileName
+                .checkName(realBase.getPath(), resolvedPath, scope))
+        {
+            throw new FileSystemException(
+                    "vfs.provider/invalid-descendent-name.error", name);
+        }
+
+        String fullPath;
+        if (scheme != null)
+        {
+            fullPath = resolvedPath;
+        }
+        else
+        {
+            scheme = realBase.getScheme();
+            fullPath = realBase.getRootURI() + resolvedPath;
+        }
+        final FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider != null)
+        {
+            // todo: extend the filename parser to be able to parse
+            // only a pathname and take the missing informations from
+            // the base. Then we can get rid of the string operation.
+            // // String fullPath = base.getRootURI() +
+            // resolvedPath.substring(1);
+
+            return provider.parseUri(realBase, fullPath);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider - if possible
+            if (defaultProvider != null)
+            {
+                return defaultProvider.parseUri(realBase, fullPath);
+            }
+        }
+
+        // todo: avoid fallback to this point
+        // this happens if we have a virtual filesystem (no provider for scheme)
+        return ((AbstractFileName) realBase).createName(resolvedPath, fileType);
+    }
+
+    /**
+     * Resolve the uri to a filename.
+     * @param uri The URI to resolve.
+     * @return The FileName of the file.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileName resolveURI(String uri) throws FileSystemException
+    {
+        UriParser.checkUriEncoding(uri);
+
+        if (uri == null)
+        {
+            throw new IllegalArgumentException();
+        }
+
+        // Extract the scheme
+        final String scheme = UriParser.extractScheme(uri);
+        if (scheme != null)
+        {
+            // An absolute URI - locate the provider
+            final FileProvider provider = (FileProvider) providers.get(scheme);
+            if (provider != null)
+            {
+                return provider.parseUri(null, uri);
+            }
+
+            // Otherwise, assume a local file
+        }
+
+        // Handle absolute file names
+        if (localFileProvider != null
+                && localFileProvider.isAbsoluteLocalName(uri))
+        {
+            return localFileProvider.parseUri(null, uri);
+        }
+
+        if (scheme != null)
+        {
+            // An unknown scheme - hand it to the default provider
+            if (defaultProvider == null)
+            {
+                throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                        new Object[] {scheme, uri});
+            }
+            return defaultProvider.parseUri(null, uri);
+        }
+
+        // Assume a relative name - use the supplied base file
+        if (baseFile == null)
+        {
+            throw new FileSystemException("vfs.impl/find-rel-file.error", uri);
+        }
+
+        return resolveName(baseFile.getName(), uri, NameScope.FILE_SYSTEM);
+    }
+
+    /**
+     * Converts a local file into a {@link FileObject}.
+     * @param file The input File.
+     * @return the create FileObject
+     * @throws FileSystemException if an error occurs creating the file naem.
+     */
+    public FileObject toFileObject(final File file) throws FileSystemException
+    {
+        return getLocalFileProvider().findLocalFile(file);
+    }
+
+    /**
+     * Creates a layered file system.
+     * @param scheme The scheme to use.
+     * @param file The FileObject.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final String scheme,
+            final FileObject file) throws FileSystemException
+    {
+        final FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-provider.error",
+                    new Object[] {scheme, file});
+        }
+        return provider.createFileSystem(scheme, file, file.getFileSystem().getFileSystemOptions());
+    }
+
+    /**
+     * Creates a layered file system.
+     * @param file The FileObject to use.
+     * @return The layered FileObject.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createFileSystem(final FileObject file)
+            throws FileSystemException
+    {
+        final String scheme = map.getScheme(file);
+        if (scheme == null)
+        {
+            throw new FileSystemException(
+                    "vfs.impl/no-provider-for-file.error", file);
+        }
+
+        return createFileSystem(scheme, file);
+    }
+
+    /**
+     * Determines if a layered file system can be created for a given file.
+     *
+     * @param file The file to check for.
+     * @return true if the FileSystem can be created.
+     * @throws FileSystemException if an error occurs.
+     */
+    public boolean canCreateFileSystem(final FileObject file)
+            throws FileSystemException
+    {
+        return map.getScheme(file) != null;
+    }
+
+    /**
+     * Creates a virtual file system.
+     * @param rootFile The FileObject to use.
+     * @return The FileObject in the VirtualFileSystem.
+     * @throws FileSystemException if an error occurs creating the file.
+     */
+    public FileObject createVirtualFileSystem(final FileObject rootFile)
+            throws FileSystemException
+    {
+        return vfsProvider.createFileSystem(rootFile);
+    }
+
+    /**
+     * Creates an empty virtual file system.
+     * @param rootUri The URI to use as the root of the FileSystem.
+     * @return A FileObject in the virtual FileSystem.
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileObject createVirtualFileSystem(final String rootUri)
+            throws FileSystemException
+    {
+        return vfsProvider.createFileSystem(rootUri);
+    }
+
+    /**
+     * Locates the local file provider.
+     * @return The LocalFileProvider.
+     * @throws FileSystemException if an error occurs.
+     */
+    private LocalFileProvider getLocalFileProvider() throws FileSystemException
+    {
+        if (localFileProvider == null)
+        {
+            throw new FileSystemException(
+                    "vfs.impl/no-local-file-provider.error");
+        }
+        return localFileProvider;
+    }
+
+    /**
+     * Get the URLStreamHandlerFactory.
+     * @return The URLStreamHandlerFactory.
+     */
+    public URLStreamHandlerFactory getURLStreamHandlerFactory()
+    {
+        return new VfsStreamHandlerFactory();
+    }
+
+    /**
+     * Closes the given filesystem.<br />
+     * If you use VFS as singleton it is VERY dangerous to call this method
+     * @param filesystem The FileSystem to close.
+     */
+    public void closeFileSystem(FileSystem filesystem)
+    {
+        // inform the cache ...
+        getFilesCache().clear(filesystem);
+
+        // just in case the cache didnt call _closeFileSystem
+        _closeFileSystem(filesystem);
+    }
+
+    /**
+     * Closes the given filesystem.<br />
+     * If you use VFS as singleton it is VERY dangerous to call this method
+     * @param filesystem The FileSystem to close.
+     */
+    public void _closeFileSystem(FileSystem filesystem)
+    {
+        FileProvider provider = (FileProvider) providers.get(filesystem
+                .getRootName().getScheme());
+        if (provider != null)
+        {
+            ((AbstractFileProvider) provider).closeFileSystem(filesystem);
+        }
+    }
+
+    /**
+     * This is an internal class because it needs access to the private member
+     * providers.
+     */
+    final class VfsStreamHandlerFactory implements URLStreamHandlerFactory
+    {
+        public URLStreamHandler createURLStreamHandler(final String protocol)
+        {
+            FileProvider provider = (FileProvider) providers.get(protocol);
+            if (provider != null)
+            {
+                return new DefaultURLStreamHandler(context);
+            }
+
+            // Route all other calls to the default URLStreamHandlerFactory
+            return new URLStreamHandlerProxy();
+        }
+    }
+
+    /**
+     * Get the schemes currently available.
+     * @return The array of scheme names.
+     */
+    public String[] getSchemes()
+    {
+        String[] schemes = new String[providers.size()];
+        providers.keySet().toArray(schemes);
+        return schemes;
+    }
+
+    /**
+     * Get the capabilities for a given scheme.
+     *
+     * @param scheme The scheme to located.
+     * @return A Collection of capabilities.
+     * @throws FileSystemException if the given scheme is not konwn
+     */
+    public Collection getProviderCapabilities(final String scheme)
+            throws FileSystemException
+    {
+        FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-scheme.error",
+                    new Object[] {scheme});
+        }
+
+        return provider.getCapabilities();
+    }
+
+    /**
+     * Get the configuration builder for the given scheme.
+     * @param scheme The scheme to locate.
+     * @return The FileSystemConfigBuilder for the scheme.
+     * @throws FileSystemException if the given scheme is not konwn
+     */
+    public FileSystemConfigBuilder getFileSystemConfigBuilder(final String scheme)
+            throws FileSystemException
+    {
+        FileProvider provider = (FileProvider) providers.get(scheme);
+        if (provider == null)
+        {
+            throw new FileSystemException("vfs.impl/unknown-scheme.error", new Object[] {scheme});
+        }
+
+        return provider.getConfigBuilder();
+    }
+
+    // -- OPERATIONS --
+
+    /**
+     * Adds the specified FileOperationProvider for the specified scheme.
+     * Several FileOperationProvider's might be registered for the same scheme.
+     * For example, for "file" scheme we can register SvnWsOperationProvider and
+     * CvsOperationProvider.
+     *
+     * @param scheme The scheme the provider should be registered for.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs adding the provider.
+     */
+    public void addOperationProvider(final String scheme,
+            final FileOperationProvider operationProvider)
+            throws FileSystemException
+    {
+        addOperationProvider(new String[] {scheme}, operationProvider);
+    }
+
+    /**
+     * @see FileSystemManager#addOperationProvider(String,
+     *      org.apache.commons.vfs.operations.FileOperationProvider)
+     *
+     * @param schemes The array of schemes the provider should apply to.
+     * @param operationProvider The FileOperationProvider.
+     * @throws FileSystemException if an error occurs.
+     */
+    public void addOperationProvider(final String[] schemes,
+            final FileOperationProvider operationProvider)
+            throws FileSystemException
+    {
+        for (int i = 0; i < schemes.length; i++)
+        {
+            final String scheme = schemes[i];
+
+            if (!operationProviders.containsKey(scheme))
+            {
+                final List providers = new ArrayList();
+                operationProviders.put(scheme, providers);
+            }
+
+            final List providers = (List) operationProviders.get(scheme);
+
+            if (providers.contains(operationProvider))
+            {
+                throw new FileSystemException(
+                        "vfs.operation/operation-provider-already-added.error", scheme);
+            }
+
+            setupComponent(operationProvider);
+
+            providers.add(operationProvider);
+        }
+    }
+
+    /**
+     * @param scheme
+     *            the scheme for wich we want to get the list af registered
+     *            providers.
+     *
+     * @return the registered FileOperationProviders for the specified scheme.
+     *         If there were no providers registered for the scheme, it returns
+     *         null.
+     *
+     * @throws FileSystemException if an error occurs.
+     */
+    public FileOperationProvider[] getOperationProviders(final String scheme)
+            throws FileSystemException
+    {
+
+        List providers = (List) operationProviders.get(scheme);
+        if (providers == null || providers.size() == 0)
+        {
+            return null;
+        }
+        return (FileOperationProvider[]) providers.toArray(new FileOperationProvider[] {});
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultProviderConfiguration.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+
+/**
+ * Same as {@link ProviderConfiguration} but for the default provider.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision: 480428 $ $Date: 2006-11-29 11:45:24 +0530 (Wed, 29 Nov 2006) $
+ */
+public class DefaultProviderConfiguration extends ProviderConfiguration
+{
+    public boolean isDefault()
+    {
+        return true;
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/DefaultVfsComponentContext.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileName;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.FileReplicator;
+import org.apache.commons.vfs.provider.TemporaryFileStore;
+import org.apache.commons.vfs.provider.VfsComponentContext;
+
+import java.io.File;
+
+
+/**
+ * The default context implementation.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 764356 $ $Date: 2009-04-13 09:36:01 +0530 (Mon, 13 Apr 2009) $
+ */
+final class DefaultVfsComponentContext
+    implements VfsComponentContext
+{
+    private final DefaultFileSystemManager manager;
+
+    public DefaultVfsComponentContext(final DefaultFileSystemManager manager)
+    {
+        this.manager = manager;
+    }
+
+    /**
+     * Locate a file by name.
+     */
+    public FileObject resolveFile(final FileObject baseFile, final String name,
+                                  final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        return manager.resolveFile(baseFile, name, fileSystemOptions);
+    }
+
+    /**
+     * Locate a file by name.
+     */
+    public FileObject resolveFile(final String name, final FileSystemOptions fileSystemOptions)
+        throws FileSystemException
+    {
+        return manager.resolveFile(name, fileSystemOptions);
+    }
+
+    public FileName parseURI(String uri) throws FileSystemException
+    {
+        return manager.resolveURI(uri);
+    }
+
+    /**
+     * Returns a {@link FileObject} for a local file.
+     */
+    public FileObject toFileObject(File file)
+        throws FileSystemException
+    {
+        return manager.toFileObject(file);
+    }
+
+    /**
+     * Locates a file replicator for the provider to use.
+     */
+    public FileReplicator getReplicator() throws FileSystemException
+    {
+        return manager.getReplicator();
+    }
+
+    /**
+     * Locates a temporary file store for the provider to use.
+     */
+    public TemporaryFileStore getTemporaryFileStore() throws FileSystemException
+    {
+        return manager.getTemporaryFileStore();
+    }
+
+    /**
+     * Returns the filesystem manager for the current context
+     *
+     * @return the filesystem manager
+     */
+    public FileSystemManager getFileSystemManager()
+    {
+        return manager;
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileContentInfoFilenameFactory.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileContentInfo;
+import org.apache.commons.vfs.FileContentInfoFactory;
+
+import java.net.FileNameMap;
+import java.net.URLConnection;
+
+/**
+ * The FileContentInfoFilenameFactory.<br>
+ * Uses the filename extension to determine the content-type.<br>
+ * The content-encoding is not resolved.
+ *
+ * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
+ * @version $Revision: 764356 $ $Date: 2009-04-13 09:36:01 +0530 (Mon, 13 Apr 2009) $
+ */
+public class FileContentInfoFilenameFactory implements FileContentInfoFactory
+{
+    public FileContentInfo create(FileContent fileContent)
+    {
+        String contentType = null;
+
+        String name = fileContent.getFile().getName().getBaseName();
+        if (name != null)
+        {
+            FileNameMap fileNameMap = URLConnection.getFileNameMap();
+            contentType = fileNameMap.getContentTypeFor(name);
+        }
+
+        return new DefaultFileContentInfo(contentType, null);
+    }
+}

Added: synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java
URL: http://svn.apache.org/viewvc/synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java?rev=1000332&view=auto
==============================================================================
--- synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java (added)
+++ synapse/branches/commons-vfs-2-synapse-2.0/core/src/main/java/org/apache/commons/vfs/impl/FileTypeMap.java Thu Sep 23 06:04:21 2010
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.commons.vfs.impl;
+
+import org.apache.commons.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A helper class that determines the provider to use for a file.
+ *
+ * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
+ * @version $Revision: 764356 $ $Date: 2009-04-13 09:36:01 +0530 (Mon, 13 Apr 2009) $
+ */
+class FileTypeMap
+{
+    private final Map mimeTypeMap = new HashMap();
+    private final Map extensionMap = new HashMap();
+
+    /**
+     * Adds a MIME type mapping.
+     */
+    public void addMimeType(final String mimeType, final String scheme)
+    {
+        mimeTypeMap.put(mimeType, scheme);
+    }
+
+    /**
+     * Adds a filename extension mapping.
+     */
+    public void addExtension(final String extension, final String scheme)
+    {
+        extensionMap.put(extension, scheme);
+    }
+
+    /**
+     * Finds the provider to use to create a filesystem from a given file.
+     */
+    public String getScheme(final FileObject file) throws FileSystemException
+    {
+        // Check the file's mime type for a match
+        final FileContent content = file.getContent();
+        // final String mimeType = (String) content.getAttribute("content-type");
+        final String mimeType = content.getContentInfo().getContentType();
+        if (mimeType != null)
+        {
+            return (String) mimeTypeMap.get(mimeType);
+        }
+
+        // Check the file's extension for a match
+        final String extension = file.getName().getExtension();
+        return (String) extensionMap.get(extension);
+    }
+}