/*
* 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.
*/
/*
* FileManager.java
*
* Created on September 16, 2003, 9:31 AM
*
* The software contained in this file is copyright 2003 by Mark J. Norton, all rights reserved.
*/
package tufts.oki.remoteFiling;
import org.apache.commons.net.ftp.*;
import tufts.oki.shared.*;
import tufts.oki.OsidManager;
import java.io.*;
import java.util.*;
/**
* The RemoteFilingManager provides a means to represent a remote file system logically
* in memory. Operations on the remote file system is implemented using FTP.
* The RemoteFileManager creates the FTP client and active session. Since osid.filing
* doesn't have provisions in ByteStore or Cabinet for opening a stream, those operations
* are included in the RemoteFilingManager. Remote files may be opened for read or
* write access. Paired with a local file manager, file uploading and downloading
* is possible.
* <p>
* The remote filing manager also implements the concept of current working directory
* and provides a number of methods for operating on it or its entries.
*
* @author Mark Norton
*
*/
public class RemoteFilingManager extends tufts.oki.OsidManager implements osid.filing.FilingManager {
private static final int BUFFER_SIZE = 1024; // Size of buffer to use.
//private String rootBase = null; // Path to the remote file system root.
private RemoteCabinet root = null; // The root cabinet for a client-session.
private RemoteCabinet cwd = null; // The current working directory.
/** Creates a new instance of the RemoteFileManager */
public RemoteFilingManager() {
super();
}
/**
* Create a client by connecting to the given host using the given username & password.
* The rootBase is initialized by grabbing the current working directory after establishing
* the connection. A root cabinet named "/" is created to represent the remote root
* in the file system.
* <p>
* The remote server name, username, and password are all cached in the RemoteFilingManager.
* This is necessary to re-establish connections that time out remotely.
*
* @author Mark Norton
*/
public void createClient(String host, String username, String password) throws osid.filing.FilingException {
try {
RemoteClient rc = new RemoteClient (host, username, password);
FTPClient client = rc.getClient();
tufts.oki.shared.Agent agent = new tufts.oki.shared.Agent(username, new tufts.oki.shared.AgentPersonType());
this.root = new RemoteCabinet("/", agent, null,rc);
this.cwd = this.root; // Set the root as current working directory.
cwd.entries();
}
catch (osid.shared.SharedException ex2) {
throw new osid.filing.FilingException (osid.filing.FilingException.OPERATION_FAILED);
}
catch (osid.OsidException ex3) {
throw new osid.filing.FilingException (osid.filing.FilingException.OPERATION_FAILED);
}
}
/**
* Return the root RemoteCabinet.
*/
public RemoteCabinet getRoot () {
return root;
}
/**
* No mention is made if the entry in question is a cabinet or not. Since only
* root cabinets exist at FilingManager level, we can probably assume that the
* search for this entry should recurse to sub-cabinents.
*
* @author Mark Norton
*
*/
public osid.filing.CabinetEntry getCabinetEntry(osid.shared.Id id) throws osid.filing.FilingException {
osid.filing.CabinetEntry found = null;
/* Search the root cabinets for the entry with id. */
RemoteCabinet entry = root;
osid.shared.Id entry_id = root.getId();
/* Check to see if the entry we are looking for is a root cabinet. */
try {
if (entry_id.isEqual(id))
found = entry;
/* Otherwise, check sub-cabinets to see if it's in there. */
else {
try {
found = entry.getCabinetEntryById(id);
}
catch (osid.filing.FilingException ex) {
/* An UNKNOWN_ID exception is expected. Continue search. */
}
}
}
catch (osid.shared.SharedException ex) {
/* isEqual doesn't really throw an exception. */
}
/* If found is null at this point, we didn't find it. */
if (found == null)
throw new osid.filing.FilingException (osid.filing.FilingException.ITEM_DOES_NOT_EXIST);
return found;
}
/**
* The documentation indicates that the cabinet being deleted must be empty and
* that the owner must have permissions to do this. Permissions are not implemented
* at this time.
* <br>
* The cabinet entry being deleted is assumed to be a root cabinet. To delete
* sub-cabinets, see Cabinet.remove(); If the entry is not found, nothing happens.
*
* @author Mark Norton
*
*/
public void delete(osid.shared.Id cabinetEntryId) throws osid.filing.FilingException {
throw new osid.filing.FilingException (osid.filing.FilingException.UNIMPLEMENTED);
}
/**
* Return an iterator over all root cabinets. Since a remote filing system can only
* have a single root, a temp vector is created and the single root added to it.
*
* @author Mark Norton
*
* return A CabinetEntryIterator which lists all root cabinets.
*/
public osid.filing.CabinetEntryIterator listRoots() throws osid.filing.FilingException {
Vector vect = new Vector(10);
vect.add (root);
osid.filing.CabinetEntryIterator it = (osid.filing.CabinetEntryIterator) new RemoteCabinetEntryIterator(vect);
return it;
}
/* Remote File System Operations */
/* ----------------------------- */
/**
* Get the current working directory as a RemoteCabinet object.
*
* @author Mark Norton
*/
public RemoteCabinet getWorkingDirectory () {
return this.cwd;
}
/**
* Set the working directory to the Cabinet indicated.
*
* @author Mark Norton
*/
//These method's should be either in RemoteClient or RemoteClient should be passed to them
//Commented them, NEED TO REDESIGN- Anoop
public void setWorkingDirectory (RemoteCabinet cabinet) throws osid.filing.FilingException {
throw new osid.filing.FilingException(osid.filing.FilingException.UNSUPPORTED_OPERATION );
/**
cwd = cabinet;
// Do a remote Change Working Directory command.
try {
FTPClient client = RemoteClient.getClient();
String current = client.printWorkingDirectory();
client.changeWorkingDirectory(cabinet.getFullName());
}
catch (java.io.IOException ex) {
throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR);
}
*/
}
/**
* Set the working directory to the Cabinet name indicated. Supports changing
* directories to a sub-directory in the curent working directory. Also supports
* a popd type command by passing "..", which causes the parent of the current
* directory to become active.
*
* @author Mark Norton
*/
public void setWorkingDirectory (String cabName) throws osid.filing.FilingException {
throw new osid.filing.FilingException(osid.filing.FilingException.UNSUPPORTED_OPERATION );
/**
osid.filing.CabinetEntry entry = cwd.getCabinetEntryByName(cabName);
if (!(entry instanceof RemoteCabinet)) {
throw new osid.filing.FilingException (osid.filing.FilingException.NOT_A_CABINET);
}
// Check the popd case where name is given as "..".
if (cabName.compareTo("..") == 0) {
entry = cwd.getParent();
}
// Check for the local cabinet case.
else {
entry = cwd.getCabinetEntryByName(cabName);
}
// Change the working directory remotely.
try {
FTPClient client = RemoteClient.getClient();
String current = client.printWorkingDirectory();
client.changeWorkingDirectory(current+ "/" + entry.getDisplayName());
}
catch (java.io.IOException ex) {
throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR);
}
cwd = (RemoteCabinet) entry;
cwd.entries(); // Make sure it is initialized
*/
}
/**
* List the contents of the current working directory by returning a
* CabinetEntryIterator for entries in this directory. Note that the entries
* in this iterator are RemoteCabinetEntry's.
*
* @author Mark Norton
*/
public osid.filing.CabinetEntryIterator list () throws osid.filing.FilingException {
return cwd.entries();
}
}