tufts.oki.remoteFiling.RemoteCabinet.java Source code

Java tutorial

Introduction

Here is the source code for tufts.oki.remoteFiling.RemoteCabinet.java

Source

/*
* Copyright 2003-2010 Tufts University  Licensed under the
 * Educational Community 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.osedu.org/licenses/ECL-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.
 */

/*
 * C abinet.java
 *
 *  Created on September 17, 2003, 10:04 AM
 */

package tufts.oki.remoteFiling;

import tufts.oki.shared.*;
import org.apache.commons.net.ftp.*;

import java.io.*;
import java.util.*;
import osid.OsidException;

/**
 *  RemoteCabinet is a implementation of osid.filing.Cabinet which models a remote
 *  directory accessed via FTP.  In order to save internal memory space, a cabinet
 *  is not initialized to the entries in it until entries() is called.  The add()
 *  method is provided to allow new entries in this directory to be included in its
 *  list of entries.  The createCabinet() and createByteStore() methods are used to
 *  create a new directory or new file, respectively.
 *
 *  @author  Mark Norton - OKI compatibility.
 *  @author  Salem Berhanu - much of the FTP transactions.
 *
 */
public class RemoteCabinet extends RemoteCabinetEntry implements osid.filing.Cabinet {
    /* parent is inherited from Cabinet Entry.  */
    Vector children = null;
    tufts.oki.shared.Properties properties = null;
    private boolean initialized = false;
    //private boolean open = false;
    //private File dir = null;               //  The remote directory being modeled.

    /**
     * Initializes the feilds interited from CabinetEntry and adds a vector of children.
     * Creates a Properties object to hold properties associated with this cabinet.
     *
     * @author Mark Norton
     *
     */
    public RemoteCabinet(String displayName, osid.shared.Agent agentOwner, osid.filing.Cabinet parent,
            RemoteClient rc) {
        super(displayName, agentOwner, parent, rc);
        children = new Vector(100);
        //FilingCabinetType type = new FilingCabinetType();
        //properties = new osid_mjn.shared.Properties(type);

        if (parent == null)
            updateDisplayName("");
        else
            updateDisplayName(displayName);
    }

    /**
     *   Add the entry to the list of children.
     *
     *   @author Mark Norton
     */
    public void add(osid.filing.CabinetEntry entry, java.lang.String name) throws osid.filing.FilingException {

        /* Update the display name in entry with name.  Does this make sense?  */
        entry.updateDisplayName(name);

        /*  Add the element to the Vector array.  */
        children.addElement(entry);
    }

    /**
     *   Add the entry to the list of children.
     *
     *   @author Mark Norton
     */
    public void add(osid.filing.CabinetEntry entry) throws osid.filing.FilingException {

        /*  Add the element to the Vector array.  */
        children.addElement(entry);
    }

    /*
     *  The oldByteStore is copied into the new ByteStore.
     *
     *  @author Mark Norton
     *
     *  @return A new ByteStore with the name provided and this cabinet as parent.
     */
    public osid.filing.ByteStore copyByteStore(String name, osid.filing.ByteStore oldByteStore)
            throws osid.filing.FilingException {
        throw new osid.filing.FilingException(osid.filing.FilingException.UNIMPLEMENTED);
    }

    /**
     *  Currently unimplemented.  A lot depends on the eventual use of the filing
     *  system implemented by these classes.  Not all systems will have a restriction
     *  on available and used byes.
     *
     *  @author Mark Norton
     *
     *  @return The number of bytes available in this cabinet.
     */
    public long getAvailableBytes() throws osid.filing.FilingException {
        throw new osid.filing.FilingException(osid.filing.FilingException.UNIMPLEMENTED);
    }

    /**
     *  Currently unimplemented.  A lot depends on the eventual use of the filing
     *  system implemented by these classes.  Not all systems will have a restriction
     *  on available and used byes.
     *  <p>
     *  This could be implemented as the sum of of the sizes of the ByteStores in this
     *  directory, but its not clear what use that would be.
     *
     *  @author Mark Norton
     *
     *  @return The number of bytes used in this cabinet.
     */
    public long getUsedBytes() throws osid.filing.FilingException {
        throw new osid.filing.FilingException(osid.filing.FilingException.UNIMPLEMENTED);
    }

    /**
     *  Create a new ByteStore, add it to this Cabinet.
     *
     *  @author Mark Norton
     *
     *  @return A new ByteStore with the name provided and this cabinet as parent.
     */
    public osid.filing.ByteStore createByteStore(String name) {

        osid.filing.ByteStore bs = null;
        try {
            bs = new RemoteByteStore(name, this, rc);
            this.add(bs);
        } catch (osid.OsidException ex) {
        }
        return bs;
    }

    /**
     *  Create a new cabinet entry with
     *  the agentOwner of this new cabinet as this owner of this Cabinet.
     *
     *  @author Mark Norton
     *
     *  @return A new cabinet with the given displayName.
     */
    public osid.filing.Cabinet createCabinet(String displayName) throws osid.filing.FilingException {

        //  Create the new cabinet entry.
        osid.shared.Agent agentOwner = super.getCabinetEntryAgent();
        RemoteCabinet entry = new RemoteCabinet(displayName, agentOwner, this, rc);

        //  Make a directory on the remote file system.
        try {
            FTPClient client = rc.getClient();
            if (!client.makeDirectory(entry.getFullName()))
                throw new osid.filing.FilingException(osid.filing.FilingException.ITEM_ALREADY_EXISTS);
        } catch (java.io.IOException ex) {
            throw new osid.filing.FilingException(osid.filing.FilingException.IO_ERROR);
        }

        /*  Add the element to the Vector array.  */
        children.addElement(entry);

        return entry;
    }

    /**
     *   Creates an iterator which lists the entries in this cabinet. A check is made to
     *   see if this cabinet was previously opened.  If not, it is opened and initialized
     *   with the entries contained in it.
     *
     *   @author Mark Norton
     *
     *   @return Return an iterator for the entries in this cabinet.
     */
    public osid.filing.CabinetEntryIterator entries() throws osid.filing.FilingException {
        //  Check to see if this cabinet is unopened.  If not, intialize it.
        if (!initialized) {
            //  Initialize the directory by getting all entries contained in it.
            FTPFile[] files = null;
            try {
                String rootBase = rc.getRootBase();
                RemotePath path = new RemotePath(rootBase, this);
                String pathname = path.getPathString();
                //System.out.println("PATHNAME:"+pathname);
                FTPClient client = rc.getClient();

                files = client.listFiles(pathname); // Executes an FTP LIST command.
                osid.shared.Agent agentOwner = super.getCabinetEntryAgent();

                // Iterate over the files returned and create CabinetEntries for them.
                // Note that there is a lot of other information in the FTPFile objects which
                // could be added to the entries being created here.  In particular, creation
                // date.
                for (int i = 0; files != null && i < files.length; i++) {
                    if (files[i].isDirectory()) {
                        //System.out.println ("\tDir " + i + ": " + files[i].getName());
                        //RemoteCabinet cab = (RemoteCabinet) this.createCabinet (files[i].getName());
                        add(new RemoteCabinet(files[i].getName(), agentOwner, this, rc));
                    } else if (files[i].isFile()) {
                        //System.out.println ("\tFile " + i + ": " + files[i].getName());
                        //RemoteByteStore store = (RemoteByteStore) this.createByteStore (files[i].getName());
                        add(new RemoteByteStore(files[i].getName(), this, rc));
                    }
                    //  Unknown cases are ignored.
                }
            } catch (java.io.IOException ex1) {
                throw new osid.filing.FilingException(osid.filing.FilingException.IO_ERROR);
            }

            //  The current working directory is now intialized.
            initialized = true;
        }
        return (osid.filing.CabinetEntryIterator) new RemoteCabinetEntryIterator(children);
    }

    /**
     *  Get a cabinet entry given its name.
     *
     *  @author Mark Norton
     *
     *  @return The cabinet entry with the desired display name.  Throws ITEM_DOES_NOT_EXIST if name is unknown.
     */
    public osid.filing.CabinetEntry getCabinetEntryByName(String name) throws osid.filing.FilingException {

        for (int i = 0; i < children.size(); i++) {
            RemoteCabinetEntry entry = (RemoteCabinetEntry) children.elementAt(i);
            if (name.compareTo(entry.getDisplayName()) == 0) {
                return (osid.filing.CabinetEntry) entry;
            }
        }
        /*  ITEM_DOES_NOT_EXIST is not exactly the right sentiment for not finding the entry.  */
        throw new osid.filing.FilingException(osid.filing.FilingException.ITEM_DOES_NOT_EXIST);
    }

    /**
     *  Get a cabinet entry given its identifier.  Throws ITEM_DOES_NOT_EXIST if Id is unknown.
     *
     *  @author Mark Norton
     *
     *  @return The cabinet entry corresponding to the identifier passed.
     */
    public osid.filing.CabinetEntry getCabinetEntryById(osid.shared.Id id) throws osid.filing.FilingException {

        for (int i = 0; i < children.size(); i++) {
            RemoteCabinetEntry entry = (RemoteCabinetEntry) children.elementAt(i);
            try {
                if (id.isEqual(entry.getId())) {
                    return (osid.filing.CabinetEntry) entry;
                }
            } catch (osid.shared.SharedException ex) {
                /*  Not exactly sure what could go wrong with an Id comparison,
                 *  but the compiler insists on catching this exception.
                 *  This will fall through to ITEM_DOES_NOT_EXIST exception throw.
                 */
            }
        }
        /*  ITEM_DOES_NOT_EXIST is not exactly the right sentiment for not finding the entry.  */
        throw new osid.filing.FilingException(osid.filing.FilingException.ITEM_DOES_NOT_EXIST);
    }

    /**
     *  Return the properties associated with this cabinet as a HashMap.  This is better
     *  implmented using the expanded Properties objects defined elsewhere.
     *
     *  @author Mark Norton
     *
     *  @return The property set of the Properties object associated with this cabinet as a Map.
     */
    public java.util.Map getProperties() throws osid.filing.FilingException {
        HashMap map = properties.getPropertySet();
        return (Map) map;
    }

    /**
     *  Get the root cabinet of this cabinet.
     *
     *  @author Mark Norton
     *
     *  @return The root cabinet of this cabinet by searching up the parent links.
     */
    public osid.filing.Cabinet getRootCabinet() throws osid.filing.FilingException {
        osid.filing.Cabinet cab = this;
        while (cab.getParent() != null)
            cab = cab.getParent();
        return cab;
    }

    /**
     *  Currently, this always returns true, since cabinets are always defined to be
     *  listable.  This could be made a property instead.
     *
     *  @author Mark Norton
     *
     *  @return True if this cabinet is listable.
     */
    public boolean isListable() throws osid.filing.FilingException {
        return true;
    }

    /**
     *  Currently, this always returns true, since cabinets are defined to be managable
     *  in this implementation.  It could be made a property instead.
     *
     *  @author Mark Norton
     *
     *  @return True if this cabinet is managable.
     */
    public boolean isManageable() throws osid.filing.FilingException {
        return true;
    }

    /**
     *  Return true if this is a root cabinet, ie., its parent is null.
     *
     *  @author Mark Norton
     *
     *  @return True if this is a root cabinet (parent == null).
     */
    public boolean isRootCabinet() throws osid.filing.FilingException {
        return (this.getParent() == null);
    }

    /**
     *  Remove the entry indicated from the children of this cabinet.  The entry is
     *  identified by comparing the Ids of the entry passed to the Id of the children
     *  present.  This assumes that such Ids are globally unique.
     *  <p>
     *  No error is thrown if entry is not present.
     *  <p>
     *  Note:  remove doesn't remove the entry on the remote file system at this time.
     *
     *  @author Mark Norton
     */
    public void remove(osid.filing.CabinetEntry entry) throws osid.filing.FilingException {

        osid.shared.Id entry_id = entry.getId();
        for (int i = 0; i < children.size(); i++) {
            RemoteCabinetEntry ent = (RemoteCabinetEntry) children.elementAt(i);
            try {
                if (entry_id.isEqual(ent.getId())) {
                    children.remove(entry);
                }
            } catch (osid.shared.SharedException ex) {
                /*  Unlikely that isEqual() will throw a SharedException.  */
            }
        }
    }

    /**
     *  Return the number of children this cabinent has.
     *  <p>
     *  This is an extension to osid.filing.Cabinet to support classes which imlement
     *  javax.swing.tree.TreeModel.
     *
     *  @author Mark Norton
     *
     *  @return the number of children in this cabinet.
     */
    public int getChildCount() {
        return children.size();
    }

    /**
     *  Check to see if this cabinet is initialized.
     *
     *  @author Mark Norton
     *
     *  @return true if the cabinet is initialized.
     */
    public boolean isInitialized() {
        return this.initialized;
    }

    /**
     *  Set the initialized flag to the value given.
     *
     *  @author Mark Norton
     */
    public void setInitialized(boolean flag) {
        this.initialized = flag;
    }

    /**
     *  Get the full file name for this entry, including path to local root.
     *  <p>
     *  Warning!  This name cannot be used to open local files, since it does
     *  not include rootBase.  The absolute name can be created by concatenating
     *  rootBase and getFullName().
     *
     *  @author Mark Norton
     */
    public String getFullName() {
        StringBuffer fn = new StringBuffer(rc.getRootBase());
        fn = new StringBuffer();
        ArrayList parts = new ArrayList(100);

        //  Walk path to root.
        RemoteCabinet ptr = this;
        while (ptr.getParent() != null) {
            parts.add(0, ptr.getDisplayName());
            ptr = (RemoteCabinet) ptr.getParent();
        }

        //  Add intermediate path to file name.
        for (int i = 0; i < parts.size(); i++) {
            fn.append("/" + parts.get(i));
        }

        //  Add the final file name.
        // fn.append("/" + getDisplayName()); //:REMOVED not needed

        return fn.toString();
    }

    /**
     *  Rename the file corresponding to this cabinet and update it's display
     *  name to the new name.
     *
     *  @author Mark Norton
     */
    public void rename(String newName) throws osid.filing.FilingException {
        //  Check the name of the directory on the remote file system.
        try {
            FTPClient client = rc.getClient();
            if (getParent() == null)
                client.rename(getFullName(), rc.getRootBase() + "/" + newName);
            else
                client.rename(getFullName(), ((RemoteCabinet) getParent()).getFullName() + "/" + newName);
        } catch (java.io.IOException ex) {
            throw new osid.filing.FilingException(osid.filing.FilingException.IO_ERROR);
        }

        //  Change the name of the Cabinet.
        updateDisplayName(newName);
    }

    public String getUrl() {
        String url = "ftp://" + rc.getUserName() + ":" + rc.getPassword() + "@" + rc.getServerName()
                + this.getFullName();
        //System.out.println("CABINET URL:"+ url);
        return url;
    }
}