/* * 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. */ /* * ByteStore.java * * Created on September 20, 2003, 7:39 PM * * The software contained in this file is copyright 2003 by Mark J. Norton, all rights reserved. */ package tufts.oki.localFiling; import java.io.*; import java.lang.*; import java.util.*; import tufts.oki.shared.*; /** * Implements the ByteStore class on a local filing system. Care must be taken to use * absolute local file names when creating the LocalByteStore. Two methods are provided * for getting the bytes in the byte store: getBytes(), and read(). One method is * provided for saving bytes in a file: write(). * * @author Mark Norton * */ public class LocalByteStore extends LocalCabinetEntry implements osid.filing.ByteStore { //private static final org.apache.log4j.Logger Log = org.apache.log4j.Logger.getLogger(LocalByteStore.class); //private byte[] byte_store; // This is the actual byte storage buffer. (UNUSED) private int used = 0; // Bytes written to the buffer. private String mime_type = null; // The mime type of this byte store. private boolean writable = true; // Is it writable? private boolean readable = true; // Is it readable? private boolean appendable = true; // Is it appendable? private File file = null; /** * Create a ByteStore object given a display name and parent. * * @author Mark Norton * */ public LocalByteStore(String displayName, osid.filing.Cabinet parent) throws osid.OsidException { super (displayName, parent.getCabinetEntryAgent(), parent); //System.out.println ("LocalByteStore creator - name: " + displayName); //byte_store = new byte[1024]; // UNUSED file = new File (displayName); //System.out.println ("LocalByteStore creator - absolute path: " + file.getAbsolutePath()); updateDisplayName (file.getName()); if (tufts.vue.DEBUG.IO && Log.isDebugEnabled()) Log.debug("CREATED in " + parent + ": " + this); } // initialCapacity version not actually supported: // /** // * Create a new ByteStore object given a display name, parent, and capacity. // * // * @author Mark Norton // * // */ // public LocalByteStore(String displayName, osid.filing.Cabinet parent, int initialCapacity) throws osid.OsidException { // super (displayName, parent.getCabinetEntryAgent(), parent); // //byte_store = new byte[initialCapacity]; // UNUSED // //file = new File (((LocalCabinet)parent).getPath(), displayName); // file = new File (displayName); // updateDisplayName (file.getName()); // if (tufts.vue.DEBUG.IO && Log.isDebugEnabled()) Log.debug("CREATED in " + parent + ": " + this + "; w/capacity=" + initialCapacity); // } @Override public final boolean isCabinet() { return false; } /** * Commit any pending I/O operations. * In this implementation, commit() doesn't do anything. * * @author Mark Norton */ public void commit() { } /** * Get the digest string. Currently, this is unimplemented. * * @author Mark Norton * * @return A digest string. */ public String getDigest(osid.shared.Type algorithmType) throws osid.filing.FilingException { throw new osid.filing.FilingException (osid.filing.FilingException.UNIMPLEMENTED); } /** * Get an interator over all digest algorithm types supported. Currently unimplemented. * * @author Mark Norton * * @return A TypeIterator which lists all Digest Algorithm Types. */ public osid.shared.TypeIterator getDigestAlgorithmTypes() throws osid.filing.FilingException { throw new osid.filing.FilingException (osid.filing.FilingException.UNIMPLEMENTED); } /** * Get the MIME type of this byte store. * * @author Mark Norton * * @return The mime type of this byte store. */ public String getMimeType() { return mime_type; } /** * Determine if this byte store is readable. * * @author Mark Norton * * @return True if this byte store is readable. */ public boolean isReadable() { return readable; } /** * Update this byte store to being read only. * * @author Mark Norton */ public void updateReadOnly() { readable = true; writable = false; } /** * Determine if this byte store is writable. * @author Mark Norton * * @return True if this byte store is writable. */ public boolean isWritable() { return writable; } /** * Force this byte store to be marked as writable. * * @author Mark Norton */ public void updateWritable() { writable = true; } /** * Determine if this byte store can be appeneded. * * @author Mark Norton * * @return True if this byte store can be appended. */ public boolean canAppend() { return appendable; } /** * Force this byte store to be marked as appendable. * * @author Mark Norton */ public void updateAppendOnly() { appendable = true; } /** * Get the current length of the file associated with this byte store.. * * @author Mark Norton * * @return The current length of this byte store. */ public long length() throws osid.filing.FilingException { return file.length(); } /** * Return the number of bytes used in this byte store. * Note that this method is not part of osid.filing.ByteStore. * * @author Mark Norton * * @return The number of bytes currently written in the buffer. */ public int used() { return used; } /** * Check to see if the mime type passed is valid. If so, set the * byte store mime type to it. Return the current mime type, which * may be the old one if new one isn't valid. * * @author Mark Norton * * @return The current mime type of this byte store. */ public String updateMimeType(String mimeType) { mime_type = mimeType; return mime_type; } /** * Return a URL string for this LocalByteStore. */ public String getUrl() { try { return getFile().toURL().toString(); } catch (Throwable t) { Log.debug("failed to create URL from file: " + getFile(), t); return getFile().toString(); } //String fn = getFile().getAbsolutePath(); //return"file://" + fn; } /** * Rename the file corresponding to this byte store and update it's display * name to the new name. * * @author Mark Norton */ /** * Get the bytes in a file associated with this byte store. */ public byte[] getBytes() throws osid.filing.FilingException { // Open the file for input access. FileInputStream stream = null; try { stream = new FileInputStream (file); } catch (java.io.IOException ex1) { throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR); } // Allocate a buffer to hold the file. Note that this must fit in memory and be // small in size than Integer.MAX_VALUE. if (file.length() > (long) Integer.MAX_VALUE) throw new osid.filing.FilingException ("File is too big to read."); int len = (int) file.length(); byte[] buf = new byte[len]; // Copy the file stream into a buffer. try { for (int i = 0; i < len; i++) { buf[i] = (byte)stream.read(); } stream.close(); } catch (java.io.IOException ex) { throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR); } return buf; } /** * Iterate over bytes given a version. Version is ignored if null. * * @author Mark Norton * * @return A ByteValueIterator which lists all bytes saved in this byte store. */ public osid.shared.ByteValueIterator read(java.util.Calendar version) throws osid.filing.FilingException { byte[] buf = getBytes(); // Create an iterator over the buffer. osid.shared.ByteValueIterator it = (osid.shared.ByteValueIterator) new ByteValueIterator(buf); return it; } /** * * Replace the contents of the file associated with this ByteStore with the contents * of the buffer provided. * * @author Mark Norton */ public void write(byte[] b) throws osid.filing.FilingException { // Open the file for output access. FileOutputStream stream = null; try { stream = new FileOutputStream (file); } catch (java.io.IOException ex1) { throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR); } // Copy the buffer to the file stream. try { for (int i = 0; i < b.length; i++) { stream.write((int)b[i]); } stream.close(); } catch (java.io.IOException ex) { throw new osid.filing.FilingException (osid.filing.FilingException.IO_ERROR); } } /** * Append the byte passed to the byte store. * <br> * A clarification request has been made to SourceForge on this method. The * value passed is declared as int, but documented as byte. Until this is * cleared up, this method throws UNIMPLEMENTED. * * @author Mark Norton */ public void writeByte (int b) throws osid.filing.FilingException { throw new osid.filing.FilingException (osid.filing.FilingException.UNIMPLEMENTED); } /** * Write the bytes passed to the offset given. If this set of bytes would * extend beyond the current size of the byte store, it is expanded. Note that * len is redundant in this interface, as b.length should equal len. * <p> * Note also that any previous data in the range of off to off+len will be * overwritten with the new bytes. * * @author Mark Norton */ public void writeBytesAtOffset (byte[] b, int off, int len) throws osid.filing.FilingException { throw new osid.filing.FilingException (osid.filing.FilingException.UNIMPLEMENTED); } /** * Get the File associated with this LocalByteStore. * * @author Mark Norton */ public File getFile() { return file; } /** * Rename the file corresponding to this byte store and update it's display * name to the new name. * * @author Mark Norton */ public void rename (String absolute, String newName) throws osid.filing.FilingException { File dst = new File (absolute); file.renameTo (dst); updateDisplayName (newName); } }