358 lines
8.3 KiB
Java

/*
* Copyright (C) 2006 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
* http://www.alfresco.org/legal/license.txt
*
* 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.alfresco.repo.avm;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.Serializable;
import java.util.Formatter;
/**
* Content that is readable and writeable.
* @author britt
*/
class FileContentImpl implements FileContent, Serializable
{
static final long serialVersionUID = -7450825236235397307L;
/**
* The Object ID.
*/
private long fID;
/**
* The reference count of this FileContent.
*/
private int fRefCount;
/**
* The version (for concurrency control).
*/
private long fVers;
/**
* The name of the file.
*/
private String fName;
/**
* The directory path of the file.
*/
private String fPath;
/**
* Default constructor.
*/
public FileContentImpl()
{
fName = null;
fPath = null;
}
/**
* Make a brand new one.
* @param id The id for this content.
*/
public FileContentImpl(long id)
{
fID = id;
fRefCount = 1;
// Initialize the contents.
try
{
OutputStream out = getOutputStream();
out.close();
}
catch (IOException ie)
{
throw new AVMException("File data error.", ie);
}
SuperRepository.GetInstance().getSession().save(this);
}
/**
* Initialize with the given content.
* @param id
* @param content
*/
public FileContentImpl(long id, File content)
{
fID = id;
fRefCount = 1;
// Initialize the contents.
try
{
OutputStream out = getOutputStream();
InputStream in = new FileInputStream(content);
byte [] buff = new byte[8192];
int count;
while ((count = in.read(buff)) != -1)
{
out.write(buff, 0, count);
}
out.close();
in.close();
}
catch (IOException ie)
{
throw new AVMException("I/O Error.", ie);
}
SuperRepository.GetInstance().getSession().save(this);
}
/**
* Copy constructor, sort of.
* @param other The content to copy from.
* @param id The id for this content.
*/
public FileContentImpl(FileContent other, long id)
{
fID = id;
fRefCount = 1;
// Copy the contents from other to this.
BufferedInputStream in = new BufferedInputStream(other.getInputStream());
BufferedOutputStream out = new BufferedOutputStream(getOutputStream());
try
{
byte [] buff = new byte[4096]; // Nyah, nyah.
int bytesRead;
while ((bytesRead = in.read(buff)) != -1)
{
out.write(buff, 0, bytesRead);
}
out.flush();
out.close();
in.close();
}
catch (IOException ie)
{
throw new AVMException("I/O failure in Copy on Write.", ie);
}
SuperRepository.GetInstance().getSession().save(this);
}
/**
* Get this FileContent's reference count.
* @return The reference count.
*/
public int getRefCount()
{
return fRefCount;
}
/**
* Set the reference count on this.
* @param count The reference count to set.
*/
public void setRefCount(int count)
{
fRefCount = count;
}
/**
* Get an InputStream from this FileContent.
* @return An InputStream.
*/
public InputStream getInputStream()
{
try
{
return new FileInputStream(getContentPath());
}
catch (IOException ie)
{
throw new AVMException("Could not open for reading: " + getContentPath(), ie);
}
}
/**
* Gets an ouptut stream to this node.
* @return An OutputStream.
*/
public OutputStream getOutputStream()
{
try
{
File dir = new File(getDirectoryPath());
if (!dir.exists())
{
dir.mkdirs();
}
return new FileOutputStream(getContentPath());
}
catch (IOException ie)
{
throw new AVMException("Could not open for writing: " + getContentPath(), ie);
}
}
/**
* Get a random access file from this content. It's the responsibility of
* the caller of this to insure that this object has been copied if the
* access argument is a write mode.
* @param access The access more for RandomAccessFile.
* @return A RandomAccessFile.
*/
public RandomAccessFile getRandomAccess(String access)
{
try
{
return new RandomAccessFile(getContentPath(), access);
}
catch (IOException ie)
{
throw new AVMException("Could not open for random access: " + getContentPath(), ie);
}
}
/**
* Delete the contents of this file from the backing store.
*/
public void delete()
{
File file = new File(getContentPath());
file.delete();
}
/**
* Get the length of this content.
* @return The length of the content.
*/
public long getLength()
{
File file = new File(getContentPath());
return file.length();
}
/**
* Retrieve the full path for this content.
* @return The full path for this content.
*/
private synchronized String getContentPath()
{
if (fName == null)
{
calcPathData();
}
return fName;
}
/**
* Get the directory path for this content.
* @return The directory path.
*/
private synchronized String getDirectoryPath()
{
if (fPath == null)
{
calcPathData();
}
return fPath;
}
/**
* Calculate the path data.
*/
private void calcPathData()
{
Formatter form = new Formatter(new StringBuilder());
form.format("%016x", fID);
String name = form.toString();
form = new Formatter(new StringBuilder());
form.format("/%02x/%02x/%02x",
(fID & 0xff000000) >> 24,
(fID & 0xff0000) >> 16,
(fID & 0xff00) >> 8);
String dir = form.toString();
fPath = SuperRepository.GetInstance().getStorageRoot() + dir;
fName = fPath + "/" + name;
}
/**
* Set the version for concurrency control.
* @param vers The value to set.
*/
protected void setVers(long vers)
{
fVers = vers;
}
/**
* Get the version for concurrency control.
* @return The version.
*/
protected long getVers()
{
return fVers;
}
/**
* Set the object id. For Hibernate.
* @param id
*/
protected void setId(long id)
{
fID = id;
}
/**
* Get the object id.
* @return The object id.
*/
public long getId()
{
return fID;
}
/**
* Equals predicate. Based on object ID.
* @param obj The obect to compare against.
* @return Equality.
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (!(obj instanceof FileContent))
{
return false;
}
return fID == ((FileContent)obj).getId();
}
/**
* Generate a hashCode.
* @return The hashCode.
*/
@Override
public int hashCode()
{
return (int)fID;
}
}