mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-02 17:35:18 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3277 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
358 lines
8.3 KiB
Java
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;
|
|
}
|
|
}
|