You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Rami Ojares <ra...@elisa.fi> on 2004/06/23 00:47:53 UTC

[vfs] FileSystemManager construction rethought

Hi Mario,

Based on our discussions yesterday (about the configurable FileSystemManager)
and reaching the manager from DataTypes I wrote a few classes and modified some
of the existing ones.

The new ones are 

- VfsTask - replacement of the VfsTask in tasks package, this I put for now in ant package
- VfsDataType - very similar to VfsTask

These 2 above provide logger & manager for ant elements

- AntLogger - What it used to be but as a separate class

- AntHelper - provides functionality for VfsTask and VfsDataType to create default/customized
              manager, and takes care of closing it. Also makes sure that managers are reused
              as much as possible.

- FileSystemConfiguration - Data structure that holds a className and a map that holds
                            arbitrary collection of names mapped to objects. FileSystemManager
                            implementation must document what kind of configuration objects it takes.
And the changed ones are

- VFS - This works as FileSystemManager factory as before but now it is written to work with
        the FileSystemConfiguration
- FileSystemManager - configure method added. VFS already used reflection to get to a possible
                      init method but now it should be formalised in the interface and work with
                      the FileSystemConfiguration

The change in FileSystemManager makes changes necessary in FileSystemManager implementation classes.
There is already some sort of configuration system in place (FileSystemConfigBuilder) but I did not
find out how it works yet. But since you (Mario) have written this you could maybe tell how this
configuration system could be merged into existing one.

The code is not compilable but more like an informal suggestion.

- rami

***** VfsTask.java *****

package org.apache.commons.vfs.ant;

import org.apache.commons.vfs.*;
import org.apache.tools.ant.*;

/**
 * Super class of Vfs Ant tasks that takes care of FileSystemManager handling.
 */
public class VfsTask extends Task {
    
    private FileSystemManager manager;
    private AntLogger logger;
    
    protected FileSystemManager getManager() {
        if (manager == null)
            setManager(null);
        return manager;
    }
    
    protected void setManager(FileSystemConfiguration conf) {
        
        if (conf == null) {
            conf = new FileSystemConfiguration(
                "org.apache.commons.vfs.impl.StandardFileSystemManager"
            );
        }
        // put AntLogger always as logger
        conf.setProperty("logger", getLogger());
        
        this.manager = AntHelper.getManager(this, conf);
    }
    
    protected AntLogger getLogger() {
        if (logger == null)
            logger = new AntLogger(this);
        return logger;
    }
    
    /**
     * Resolves a URI to a file, relative to the project's base directory.
     *
     * @param uri The URI to resolve.
     */
    protected FileObject resolveFile(final String uri) throws FileSystemException {
        return getManager().resolveFile(getProject().getBaseDir(), uri);
    }
    
}


***** VfsDataType.java *****

package org.apache.commons.vfs.ant;

import org.apache.commons.vfs.*;
import org.apache.tools.ant.types.*;

/**
 * Super class of Vfs Ant data types that takes care of FileSystemManager
 * handling.
 */
public class VfsDataType extends DataType {
    
    private FileSystemManager manager;
    
    protected FileSystemManager getManager() {
        if (manager == null)
            setManager(null);
        return manager;
    }
    
    protected void setManager(FileSystemConfiguration conf) {
        
        if (conf == null) {
            conf = new FileSystemConfiguration(
                "org.apache.commons.vfs.impl.StandardFileSystemManager"
            );
        }
        // put AntLogger always as logger
        conf.setProperty("logger", getLogger());
        
        this.manager = AntHelper.getManager(this, conf);
    }
    
    /**
     * Resolves a URI to a file, relative to the project's base directory.
     *
     * @param uri The URI to resolve.
     */
    protected FileObject resolveFile(final String uri) throws FileSystemException {
        return getManager().resolveFile(getProject().getBaseDir(), uri);
    }
    
}


***** AntHelper.java *****

package org.apache.commons.vfs.ant;

import org.apache.commons.vfs.*;
import org.apache.tools.ant.*;
import java.util.*;

/**
 * Holds a map of FileSystemKey -> FileSystemManger
 * When a Task or DataType asks for FileSystemManger, AntHelper looks it up
 * in the map. If it does not exist, it is created, added to the map and a
 * BuildListener is added to the project so that when the project finishes it
 * closes the FileSystemManger and removes it from the map.
 */
public class AntHelper {
    
    private static Map managers = new HashMap();
    
    public static FileSystemManager getManager(ProjectComponent projectComponent, FileSystemConfiguration conf) {
        
        FileSystemKey key = new FileSystemKey(projectComponent, conf);
        
        FileSystemManager manager = (FileSystemManager) managers.get(key);
        if (manager == null) {
            manager = VFS.createManager(conf);
            projectComponent.getProject().addBuildListener(new CloseListener(key));
            managers.put(key, manager);
        }
        
        return manager;
    }
    
    static close(FileSystemKey key) {
        FileSystemManager manager = (FileSystemManager) managers.get(key);
        if (manager == null) {
            manager.close();
            managers.remove(manager);
        }
    }
    
}

/**
 * Combines Project and FileSystemConfiguration into a single key that is mapped
 * to a FileSystemManager.
 */
private class FileSystemKey {
    
    private Project project;
    private FileSystemConfiguration fsConf;
    
    FileSystemKey(Project project, FileSystemConfiguration fsConf) {
        this.project = project;
        this.fsConf = fsConf;
    }
    
    public boolean equals(Object o) {
        
        if (o == null) return false;
        
        FileSystemKey comparand;
        try {
            comparand = (FileSystemKey) o;
        }
        catch (ClassCastException cce) {
            return false;
        }
        
        if (project.equals(comparand.getProject())) {
            // since fsConf can be null we have to deal with that separately
            if (fsConf == null) {
                if (comparand.getFileSystemConfiguration() == null)
                    return true;
                else
                    return false;
            }
            
            if (fsConf.equals(comparand.getFileSystemConfiguration()))
                return true;
        }
        
        return false;
    }
    
    Project getProject() {
        return project;
    }
    
    FileSystemConfiguration getFileSystemConfiguration() {
        return fsConf;
    }
}

/**
 * Closes the VFS manager when the project finishes.
 */
private class CloseListener implements BuildListener {
    
    private FileSystemKey key;
    
    CloseListener(FileSystemKey key) {
        this.key = key;
    }
    
    public void buildFinished(BuildEvent event)
    {
        AntHelper.close(key);
    }

    public void buildStarted(BuildEvent event)
    {
    }

    public void messageLogged(BuildEvent event)
    {
    }

    public void targetFinished(BuildEvent event)
    {
    }

    public void targetStarted(BuildEvent event)
    {
    }

    public void taskFinished(BuildEvent event)
    {
    }

    public void taskStarted(BuildEvent event)
    {
    }
}

***** AntLogger.java *****

package org.apache.commons.vfs.ant;

import org.apache.commons.logging.*;
import org.apache.tools.ant.*;

/**
 * A commons-logging wrapper for Ant logging.
 */
public class AntLogger implements Log {
    
    private ProjectComponent pc;
    
    public AntLogger(ProjectComponent pc) {
        this.pc = pc;
    }
    
    public void debug(final Object o)
    {
        pc.log(String.valueOf(o), Project.MSG_DEBUG);
    }

    public void debug(Object o, Throwable throwable)
    {
        debug(o);
    }

    public void error(Object o)
    {
        pc.log(String.valueOf(o), Project.MSG_ERR);
    }

    public void error(Object o, Throwable throwable)
    {
        error(o);
    }

    public void fatal(Object o)
    {
        pc.log(String.valueOf(o), Project.MSG_ERR);
    }

    public void fatal(Object o, Throwable throwable)
    {
        fatal(o);
    }

    public void info(Object o)
    {
        pc.log(String.valueOf(o), Project.MSG_INFO);
    }

    public void info(Object o, Throwable throwable)
    {
        info(o);
    }

    public void trace(Object o)
    {
    }

    public void trace(Object o, Throwable throwable)
    {
    }

    public void warn(Object o)
    {
        pc.log(String.valueOf(o), Project.MSG_WARN);
    }

    public void warn(Object o, Throwable throwable)
    {
        warn(o);
    }

    public boolean isDebugEnabled()
    {
        return true;
    }

    public boolean isErrorEnabled()
    {
        return true;
    }

    public boolean isFatalEnabled()
    {
        return true;
    }

    public boolean isInfoEnabled()
    {
        return true;
    }

    public boolean isTraceEnabled()
    {
        return false;
    }

    public boolean isWarnEnabled()
    {
        return true;
    }
}

***** FileSystemConfiguration.java *****

package org.apache.commons.vfs;

import org.apache.commons.vfs.*;
import org.apache.tools.ant.*;
import java.util.*;

/**
 * Data structure that holds a fully qualified classname (name of the
 * FileSystemManager implementation class) and a map of parameters (name/value
 * pairs that are given to the FileSystemManager implementation class.
 */
public class FileSystemConfiguration {
    
    String className;
    Map parameters = new HashMap();
    
    public FileSystemConfiguration(String className) {
        this.className = className;
    }
    
    public void getClassName() {
        return className;
    }
    
    public void setParameter(String name, Object value) {
        parameters.put(name, value);
    }
    
    public Object getParameter(String name) {
        return parameters.get(name);
    }
    
    private Map getParameters() {
        return parameters;
    }
    
    public boolean equals(Object o) {
        
        if (o == null) return false;
        
        FileSystemConfiguration comparand;
        try {
            comparand = (FileSystemConfiguration) o;
        }
        catch (ClassCastException cce) {
            return false;
        }
        
        if (
            className.equals(comparand.getClassName()) &&
            parameters.equals(comparand.getParameters())
        )
            return true;
        else
            return false;
    }
}

***** VFS.java *****

/*
 * Copyright 2002, 2003,2004 The Apache Software Foundation.
 * 
 * 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.apache.commons.vfs;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * The main entry point for the VFS.  Used to create {@link FileSystemManager}
 * instances.
 *
 * @author <a href="mailto:adammurdoch@apache.org">Adam Murdoch</a>
 * @version $Revision: 1.8 $ $Date: 2004/05/17 20:13:20 $
 */
public class VFS
{
    private static FileSystemManager defaultSharedInstance;

    private VFS()
    {
    }

    /**
     * Returns the default shared {@link FileSystemManager} instance.
     */
    public static synchronized FileSystemManager getManager()
        throws FileSystemException
    {
        if (defaultSharedInstance == null)
        {
            FileSystemConfiguration conf = new FileSystemConfiguration(
                "org.apache.commons.vfs.impl.StandardFileSystemManager"
            );
            defaultSharedInstance = createManager(conf);
        }
        return defaultSharedInstance;
    }
    
    /**
     * Creates a FileSystemManager instance.
     * 
     * @param conf is the FileSystemConfiguration used to create a
     * FileSystemManager. If it is null then the default shared manager is
     * returned.
     */
    public static FileSystemManager createManager(FileSystemConfiguration conf) throws FileSystemException {
        
        if (conf == null)
            return getManager();
        
        try {
            Class clazz = Class.forName(conf.getClassName());
            FileSystemManager fsm = (FileSystemManager) = clazz.newInstance();
            fsm.configure(conf);
            return fsm;
        }
        catch(Exception e) {
            throw new FileSystemException("vfs/create-manager.error");
        }
    }
    
}

***** FileSystemManager - partially *****

/**
 * Called after instantiation and before use. Implementation can ignore
 * calls to this method after the first call and even throw a
 * RuntimeException if they so desire.
 */
void configure(FileSystemConfiguration conf) throws FileSystemException;


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org