diff --git a/source/java/hibernate.cfg.xml b/source/java/hibernate.cfg.xml
new file mode 100644
index 0000000000..564ec176cd
--- /dev/null
+++ b/source/java/hibernate.cfg.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ root
+
+ jdbc:mysql://127.0.0.1/avm
+ com.mysql.jdbc.Driver
+ thread
+ org.hibernate.dialect.MySQLInnoDBDialect
+ true
+ 2
+ 5
+ 20
+ 900
+ 50
+
+
+
+
+
+
diff --git a/source/java/log4j.properties b/source/java/log4j.properties
new file mode 100644
index 0000000000..ba55e67c78
--- /dev/null
+++ b/source/java/log4j.properties
@@ -0,0 +1,9 @@
+### Set logging to console.
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %5p %c{1}:%m%n
+
+### Set log levels.
+log4j.rootLogger=warn, stdout
+log4j.logger.org.hibernate=warn
diff --git a/source/java/org/alfresco/repo/avm/AVMNode.java b/source/java/org/alfresco/repo/avm/AVMNode.java
new file mode 100644
index 0000000000..6f6dc9d9a3
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/AVMNode.java
@@ -0,0 +1,243 @@
+/*
+ * 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 org.alfresco.repo.avm.hibernate.AVMNodeBean;
+import org.alfresco.repo.avm.hibernate.DirectoryNodeBean;
+
+/**
+ * Base class for all repository file system like objects.
+ * @author britt
+ */
+public abstract class AVMNode
+{
+ /**
+ * The AVMNodeBean that contains our data.
+ */
+ private AVMNodeBean fData;
+
+ /**
+ * Default constructor.
+ */
+ protected AVMNode()
+ {
+ fData = null;
+ }
+
+ /**
+ * Set the ancestor of this node.
+ * @param ancestor The ancestor to set.
+ */
+ public void setAncestor(AVMNode ancestor)
+ {
+ fData.setAncestor(ancestor.getDataBean());
+ }
+
+ /**
+ * Get the ancestor of this node.
+ * @return The ancestor of this node.
+ */
+ public AVMNode getAncestor()
+ {
+ return AVMNodeFactory.CreateFromBean(fData.getAncestor());
+ }
+
+ /**
+ * Set the merged from node.
+ * @param mergedFrom The merged from node.
+ */
+ public void setMergedFrom(AVMNode mergedFrom)
+ {
+ fData.setMergedFrom(mergedFrom.getDataBean());
+ }
+
+ /**
+ * Get the node this was merged from.
+ * @return The node this was merged from.
+ */
+ public AVMNode getMergedFrom()
+ {
+ return AVMNodeFactory.CreateFromBean(fData.getMergedFrom());
+ }
+
+ /**
+ * Should this be copied on modification.
+ */
+ public boolean shouldBeCopied()
+ {
+ return !fData.getIsNew();
+ }
+
+ /**
+ * Set to need copying or not.
+ * @param copyable Whether this should be copied.
+ */
+ public void setShouldBeCopied(boolean copyable)
+ {
+ fData.setIsNew(!copyable);
+ }
+
+ /**
+ * Get the version number.
+ * @return The version number.
+ */
+ public long getVersion()
+ {
+ return fData.getVersionID();
+ }
+
+ /**
+ * Set the version number.
+ * @param version The version number to set.
+ */
+ public void setVersion(long version)
+ {
+ fData.setVersionID(version);
+ }
+
+ /**
+ * Get the branch id of this node.
+ * @return The branch id.
+ */
+ public long getBranchID()
+ {
+ return fData.getBranchID();
+ }
+
+ /**
+ * Set the branch id on this node.
+ * @param branchID The id to set.
+ */
+ public void setBranchID(long branchID)
+ {
+ fData.setBranchID(branchID);
+ }
+
+ /**
+ * Get the (possibly null) parent.
+ * @return The parent or null.
+ */
+ public DirectoryNode getParent()
+ {
+ return (DirectoryNode)AVMNodeFactory.CreateFromBean(fData.getParent());
+ }
+
+ /**
+ * Set the parent of this node.
+ * @param parent The DirectoryNode to set.
+ */
+ public void setParent(DirectoryNode parent)
+ {
+ fData.setParent((DirectoryNodeBean)parent.getDataBean());
+ }
+
+ /**
+ * Perform a COW if required.
+ * @param lPath The lookup path.
+ * @return A 'copied' version of this node.
+ */
+ public AVMNode copyOnWrite(Lookup lPath)
+ {
+ AVMNode newMe = possiblyCopy(lPath);
+ String myName = lPath.getName();
+ lPath.upCurrentNode();
+ if (newMe == null)
+ {
+ return this;
+ }
+ Repository repos = getRepository();
+ newMe.setVersion(repos.getLatestVersion() + 1);
+ DirectoryNode parent = null;
+ if (getParent() != null)
+ {
+ parent = (DirectoryNode)lPath.getCurrentNode();
+ }
+ if (parent != null)
+ {
+ DirectoryNode newParent =
+ (DirectoryNode)parent.copyOnWrite(lPath);
+ newParent.putChild(myName, newMe);
+ newMe.setParent(newParent);
+ }
+ else // Null parent means root of repository.
+ {
+ newMe.setRepository(getRepository());
+ repos.setNewRoot((DirectoryNode)newMe);
+ }
+ newMe.setShouldBeCopied(false);
+ repos.setNew(newMe);
+ return newMe;
+ }
+
+
+ /**
+ * Possibly copy ourselves.
+ * @param lPath The Lookup for this node.
+ * @return A copy of ourself or null if no copy was necessary.
+ */
+ public abstract AVMNode possiblyCopy(Lookup lPath);
+
+ /**
+ * Handle any after recursive copy processing.
+ *
+ * @param parent The DirectoryNode that is the parent of
+ * this copied node, after recursive copying.
+ */
+ public abstract void handlePostCopy(DirectoryNode parent);
+
+ /**
+ * Set the repository for a node.
+ * @param repo The Repository to set.
+ */
+ public void setRepository(Repository repo)
+ {
+ fData.setRepository(repo.getDataBean());
+ }
+
+ /**
+ * Get the Repository we 'belong' to.
+ * @return The Repository.
+ */
+ public Repository getRepository()
+ {
+ return RepositoryFactory.GetInstance().createFromBean(fData.getRepository());
+ }
+
+ /**
+ * Get the data bean in this node.
+ * @return The data bean.
+ */
+ public AVMNodeBean getDataBean()
+ {
+ return fData;
+ }
+
+ /**
+ * Set the data bean in this node.
+ * @param bean The data bean to set.
+ */
+ public void setDataBean(AVMNodeBean bean)
+ {
+ fData = bean;
+ }
+
+ /**
+ * Get the type of this node.
+ */
+ public abstract AVMNodeType getType();
+}
diff --git a/source/java/org/alfresco/repo/avm/AVMNodeFactory.java b/source/java/org/alfresco/repo/avm/AVMNodeFactory.java
new file mode 100644
index 0000000000..2c1179b3c5
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/AVMNodeFactory.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.alfresco.repo.avm.hibernate.AVMNodeBean;
+import org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.LayeredFileNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainFileNodeBean;
+
+/**
+ * Responsible for instantiating AVMNode implementations.
+ * @author britt
+ */
+public class AVMNodeFactory
+{
+ /**
+ * Create a node from a data bean.
+ * @param bean The AVMNodeBean.
+ */
+ public static AVMNode CreateFromBean(AVMNodeBean bean)
+ {
+ if (bean == null)
+ {
+ return null;
+ }
+ if (bean instanceof PlainFileNodeBean)
+ {
+ return new PlainFileNode((PlainFileNodeBean)bean);
+ }
+ if (bean instanceof PlainDirectoryNodeBean)
+ {
+ return new PlainDirectoryNode((PlainDirectoryNodeBean)bean);
+ }
+ if (bean instanceof LayeredDirectoryNodeBean)
+ {
+ return new LayeredDirectoryNode((LayeredDirectoryNodeBean)bean);
+ }
+ assert bean instanceof LayeredFileNodeBean : "Unknown AVMNodeBean suptype.";
+ return new LayeredFileNode((LayeredFileNodeBean)bean);
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/AVMNodeType.java b/source/java/org/alfresco/repo/avm/AVMNodeType.java
new file mode 100644
index 0000000000..3b9df3163b
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/AVMNodeType.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * This defines the different types of FolderEntrys.
+ * @author britt
+ */
+public enum AVMNodeType
+{
+ PLAIN_FILE,
+ LAYERED_FILE,
+ PLAIN_DIRECTORY,
+ LAYERED_DIRECTORY
+}
diff --git a/source/java/org/alfresco/repo/avm/AVMService.java b/source/java/org/alfresco/repo/avm/AVMService.java
new file mode 100644
index 0000000000..680fabc669
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/AVMService.java
@@ -0,0 +1,190 @@
+/*
+ * 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.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This is the service interface for the [Alfresco|Addled|Advanced|Apotheosed] Versioning
+ * Model. It specifies methods that are close in functionality to the underlying
+ * implementation, and is intended, for now, as an internal interface to build a different
+ * implementation of NodeService and others.
+ * @author britt
+ */
+public interface AVMService
+{
+ /**
+ * Get an InputStream for a file node.
+ * @param version The version id to look in.
+ * @param path The simple absolute path to the file node.
+ * @return An InputStream for the designated file.
+ */
+ public InputStream getFileInputStream(int version, String path);
+
+ /**
+ * Get an output stream to a file node.
+ * @param path The simple absolute path to the file node.
+ */
+ public OutputStream getFileOutputStream(String path);
+
+ /**
+ * Get a listing of a Folder by name.
+ * @param version The version id to look in.
+ * @param path The simple absolute path to the file node.
+ * @return A List of FolderEntrys.
+ */
+ public List getDirectoryListing(int version, String path);
+
+ /**
+ * Create a new File.
+ * @param parent The simple absolute path to the parent.
+ * @param name The name to give the file.
+ */
+ public void createFile(String path, String name);
+
+ /**
+ * Create a new Folder.
+ * @param parent The simple absolute path to the parent.
+ * @param name The name to give the folder.
+ */
+ public void createDirectory(String path, String name);
+
+ /**
+ * Create a new layered file.
+ * @param srcPath The simple absolute path that the new file will shadow.
+ * @param parent The simple absolute path to the parent.
+ * @param name The name to give the new file.
+ */
+ public void createLayeredFile(String srcPath, String parent, String name);
+
+ /**
+ * Create a new layered folder.
+ * @param srcPath The simple absolute path that the new folder will shadow.
+ * @param parent The simple absolute path to the parent.
+ * @param name The name to give the new folder.
+ */
+ public void createLayeredDirectory(String srcPath, String parent, String name);
+
+ /**
+ * Retarget a layered folder.
+ * @param path Path to the layered directory.
+ * @param target The new target to aim at.
+ */
+ public void retargetLayeredFolder(String path, String target);
+
+ /**
+ * Create a new Repository. All Repositories are top level in a hierarchical
+ * sense.
+ * @param name The name to give the virtual repository.
+ */
+ public void createRepository(String name);
+
+ /**
+ * Create a branch from a given version and path.
+ * @param version The version number from which to make the branch.
+ * @param srcPath The path to the node to branch from.
+ * @param dstPath The path to the directory to contain the
+ * new branch.
+ * @param name The name to give the new branch.
+ */
+ public void createBranch(int version, String srcPath, String dstPath, String name);
+
+ /**
+ * Remove a child from its parent.
+ * @param parent The simple absolute path to the parent directory.
+ * @param name The name of the child to remove.
+ */
+ public void removeNode(String parent, String name);
+
+ /**
+ * Rename a node.
+ * @param srcParent The simple absolute path to the parent folder.
+ * @param srcName The name of the node in the src Folder.
+ * @param dstParent The simple absolute path to the destination folder.
+ * @param dstName The name that the node will have in the destination folder.
+ */
+ public void rename(String srcParent, String srcName, String dstParent, String dstName);
+
+ /**
+ * Slide a directory from one place in a layer to another uncovering what was
+ * underneath it.
+ * @param srcParent The simple absolute path to the parent folder.
+ * @param srcName The name of the node in the src Folder.
+ * @param dstParent The simple absolute path to the destination folder.
+ * @param dstName The name that the node will have in the destination folder.
+ */
+ public void slide(String srcParent, String srcName, String dstParent, String dstName);
+
+ /**
+ * Get the latest version id of the repository.
+ * @param repName The name of the repository.
+ * @return The latest version id of the repository.
+ */
+ public long getLatestVersionID(String repName);
+
+ /**
+ * Snapshot the given repositories. When this is called everything that has been added,
+ * deleted, or modified since the last time this function was called, is marked
+ * as needing to be copied, so that further modifications will trigger copy on write
+ * semantics.
+ * @param repositories The names of the repositories to snapshot.
+ */
+ public void createSnapshot(List repositories);
+
+ /**
+ * Get the set of version IDs in a Repository
+ * @param name The name of the Repository.
+ * @return A Set of version IDs
+ */
+ public Set getRepositoryVersions(String name);
+
+ /**
+ * Lookup a node by version ids and path. Note that an AVMNode is essentially
+ * informational only. There is very little you can do to an AVMNode in the absence
+ * of path information.
+ * @param version The version id to look under.
+ * @param path The simple absolute path to the parent directory.
+ * @return An AVMNode.
+ */
+ public AVMNode lookup(int version, String path);
+
+ /**
+ * Get the indirection path for a layered file or directory.
+ * @param version The version number to get.
+ * @param path The path to the node of interest.
+ * @return The indirection path.
+ */
+ public String getIndirectionPath(int version, String path);
+
+ /**
+ * Destroy a repository. This is a complete wipe of a Repository.
+ * @param name The name of the Repository.
+ */
+ public void destroyRepository(String name);
+
+ /**
+ * Purge a version from a repository. Deletes everything that lives in
+ * the given version only.
+ * @param version The version to purge.
+ * @param name The name of the Repository from which to purge it.
+ */
+ public void purgeVersion(int version, String name);
+}
diff --git a/source/java/org/alfresco/repo/avm/DirectoryNode.java b/source/java/org/alfresco/repo/avm/DirectoryNode.java
new file mode 100644
index 0000000000..dc753b7ae5
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/DirectoryNode.java
@@ -0,0 +1,83 @@
+/*
+ * 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.util.Map;
+
+import org.alfresco.repo.avm.hibernate.DirectoryEntry;
+
+/**
+ *
+ * @author britt
+ */
+public abstract class DirectoryNode extends AVMNode
+{
+ /**
+ * Does this directory directly contain the specified node.
+ * @param node The node to check.
+ * @return Whether it does.
+ */
+ public abstract boolean directlyContains(AVMNode node);
+
+ /**
+ * Put child into this directory directly. No copy on write.
+ * @param name The name to give it.
+ * @param node The child.
+ */
+ public abstract void putChild(String name, AVMNode node);
+
+ /**
+ * Lookup a child node.
+ * @param lPath The Lookup so far.
+ * @param name The name of the child to lookup.
+ * @param version The version to look under.
+ */
+ public abstract AVMNode lookupChild(Lookup lPath, String name, int version);
+
+ /**
+ * Add a child node. Fails if child already exists.
+ * Copy is possible.
+ * @param name The name to give the child.
+ * @param child The child to add.
+ * @param The lookup path.
+ */
+ public abstract boolean addChild(String name, AVMNode child,
+ Lookup lPath);
+
+ /**
+ * Remove a child node. Fails if child does not exist.
+ * Copy is possible.
+ * @param name The name of the child to remove.
+ * @param lPath The lookup path.
+ */
+ public abstract boolean removeChild(String name, Lookup lPath);
+
+ /**
+ * Remove a child directly. No copy is possible.
+ * @param name The name of the child to remove.
+ */
+ public abstract void rawRemoveChild(String name);
+
+ /**
+ * Get a directory listing.
+ * @param lPath The lookup context.
+ * @param version The version to look under.
+ * @return A Map of names to DirectoryEntries.
+ */
+ public abstract Map getListing(Lookup lPath, int version);
+}
diff --git a/source/java/org/alfresco/repo/avm/FileContent.java b/source/java/org/alfresco/repo/avm/FileContent.java
new file mode 100644
index 0000000000..7f7e5a5c9b
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/FileContent.java
@@ -0,0 +1,118 @@
+/*
+ * 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.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.avm.hibernate.ContentBean;
+import org.alfresco.repo.avm.hibernate.ContentBeanImpl;
+
+/**
+ * Content that is readable and writeable.
+ * @author britt
+ */
+public class FileContent
+{
+ /**
+ * The data containing bean.
+ */
+ private ContentBean fData;
+
+ /**
+ * Make one from a bean.
+ * @param data The Bean with the data.
+ */
+ public FileContent(ContentBean data)
+ {
+ fData = data;
+ }
+
+ /**
+ * Make a brand new one.
+ * @param superRepo The SuperRepository.
+ */
+ public FileContent(SuperRepository superRepo)
+ {
+ fData = new ContentBeanImpl(superRepo.issueContentID());
+ }
+
+ /**
+ * Copy constructor, sort of.
+ * @param other The content to copy from.
+ * @param superRepo The SuperRepository.
+ */
+ public FileContent(FileContent other, SuperRepository superRepo)
+ {
+ fData = new ContentBeanImpl(superRepo.issueContentID());
+ // TODO Something.
+ }
+
+ /**
+ * Get the number of files that refer to this content.
+ * @return The reference count.
+ */
+ public int getRefCount()
+ {
+ return fData.getRefCount();
+ }
+
+ /**
+ * Set the reference count.
+ * @param count The count to set.
+ */
+ public void setRefCount(int count)
+ {
+ fData.setRefCount(count);
+ }
+
+ /**
+ * Get an input stream from the content.
+ * @param superRepo The SuperRepository.
+ * @return An InputStream.
+ */
+ public InputStream getInputStream(SuperRepository superRepo)
+ {
+ // TODO Something.
+ return null;
+ }
+
+ /**
+ * Get an output stream to the content.
+ * @param superRepo The SuperRepository.
+ * @return an OutputStream.
+ */
+ public OutputStream getOutputStream(SuperRepository superRepo)
+ {
+ // TODO Something.
+ return null;
+ }
+
+ /**
+ * Get the underlying data bean. Don't abuse the privilege.
+ * @return The data bean.
+ */
+ public ContentBean getDataBean()
+ {
+ return fData;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/FileContentFactory.java b/source/java/org/alfresco/repo/avm/FileContentFactory.java
new file mode 100644
index 0000000000..a2a52b5133
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/FileContentFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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 org.alfresco.repo.avm.hibernate.ContentBean;
+
+/**
+ * Static method for making FileContent instances from beans.
+ * @author britt
+ */
+public class FileContentFactory
+{
+ /**
+ * Make A FileContent object from a ContentBean.
+ * @param bean The bean with the data.
+ */
+ public static FileContent CreateFileContentFromBean(ContentBean bean)
+ {
+ return new FileContent(bean);
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/FileNode.java b/source/java/org/alfresco/repo/avm/FileNode.java
new file mode 100644
index 0000000000..8bb82f8d35
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/FileNode.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * Interface for file objects.
+ * @author britt
+ */
+public abstract class FileNode extends AVMNode
+{
+ /**
+ * Get the content object associated with this node, for reading.
+ * @param version The version to get in.
+ * @return A FileContent object.
+ */
+ public abstract FileContent getContentForRead(int version);
+
+ /**
+ * Get the content object for writing. This will do COW
+ * as needed.
+ */
+ public abstract FileContent getContentForWrite(Repository repo);
+}
diff --git a/source/java/org/alfresco/repo/avm/FolderEntry.java b/source/java/org/alfresco/repo/avm/FolderEntry.java
new file mode 100644
index 0000000000..adcf05a81f
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/FolderEntry.java
@@ -0,0 +1,68 @@
+/*
+ * 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;
+
+/**
+ * A FolderEntry is a simple value class containing type
+ * information and name for an entry in a folder list.
+ * @author britt
+ */
+public class FolderEntry
+{
+ /**
+ * The name of the entry.
+ */
+ private String fName;
+
+ /**
+ * The type of the entry.
+ */
+ private AVMNodeType fType;
+
+ /**
+ * @return the name
+ */
+ public String getName()
+ {
+ return fName;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void getName(String name)
+ {
+ fName = name;
+ }
+
+ /**
+ * @return the type
+ */
+ public AVMNodeType getType()
+ {
+ return fType;
+ }
+
+ /**
+ * @param type the type to set
+ */
+ public void setType(AVMNodeType type)
+ {
+ fType = type;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java
new file mode 100644
index 0000000000..fc6b5b448e
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/LayeredDirectoryNode.java
@@ -0,0 +1,407 @@
+/*
+ * 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.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.avm.hibernate.DirectoryEntry;
+import org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBeanImpl;
+
+/**
+ * Interface for a layered directory node. Stub.
+ * @author britt
+ */
+public class LayeredDirectoryNode extends DirectoryNode
+{
+ /**
+ * The underlying bean data.
+ */
+ private LayeredDirectoryNodeBean fData;
+
+ /**
+ * Make one up from Bean data.
+ * @param data The bean with the persistent data.
+ */
+ public LayeredDirectoryNode(LayeredDirectoryNodeBean data)
+ {
+ fData = data;
+ setDataBean(data);
+ }
+
+ /**
+ * Make a new one from a specified indirection path.
+ * @param indirection The indirection path to set.
+ * @param repository The repository that owns this node.
+ */
+ public LayeredDirectoryNode(String indirection, Repository repos)
+ {
+ fData = new LayeredDirectoryNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ -1,
+ indirection);
+ setDataBean(fData);
+ repos.getSuperRepository().getSession().save(fData);
+ }
+
+ /**
+ * Kind of copy constructor, sort of.
+ * @param other The LayeredDirectoryNode we are copied from.
+ * @param repos The Repository object we use.
+ */
+ public LayeredDirectoryNode(LayeredDirectoryNode other,
+ Repository repos)
+ {
+ fData = new LayeredDirectoryNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ -1,
+ other.getUnderlying());
+ fData.setAdded(((LayeredDirectoryNodeBean)other.getDataBean()).getAdded());
+ fData.setDeleted(((LayeredDirectoryNodeBean)other.getDataBean()).getDeleted());
+ fData.setPrimaryIndirection(((LayeredDirectoryNodeBean)other.getDataBean()).getPrimaryIndirection());
+ repos.getSuperRepository().getSession().save(fData);
+ }
+
+ /**
+ * Construct one from a PlainDirectoryNode.
+ * @param other The PlainDirectoryNode.
+ * @param repos The Repository we should belong to.
+ * @param lPath The Lookup object.
+ */
+ public LayeredDirectoryNode(PlainDirectoryNode other,
+ Repository repos,
+ Lookup lPath)
+ {
+ fData = new LayeredDirectoryNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ -1,
+ null);
+ // TODO Is this right?
+ fData.setAdded(other.getListing(lPath, -1));
+ fData.setPrimaryIndirection(false);
+ repos.getSuperRepository().getSession().save(fData);
+ }
+
+ public LayeredDirectoryNode(DirectoryNode dir,
+ Repository repo,
+ Lookup srcLookup,
+ String name)
+ {
+/*
+ fAdded = new HashMap();
+ fDeleted = new HashSet();
+ fProxied = srcLookup.getIndirectionPath() + "/" + name;
+ fIsPrimaryIndirection = true;
+*/
+ }
+
+ /**
+ * Does this node have a primary indirection.
+ * @returns Whether this is a primary indirection.
+ */
+ public boolean hasPrimaryIndirection()
+ {
+ return fData.getPrimaryIndirection();
+ }
+
+ /**
+ * Set whether this has a primary indirection.
+ * @param has Whether this has a primary indirection.
+ */
+ public void setPrimaryIndirection(boolean has)
+ {
+ fData.setPrimaryIndirection(has);
+ }
+
+ /**
+ * Get the raw underlying indirection. Only meaningful
+ * for a node that hasPrimaryIndirection().
+ */
+ public String getUnderlying()
+ {
+ return fData.getIndirection();
+ }
+
+ /**
+ * Get the underlying indirection in the context of a Lookup.
+ * @param lPath The lookup path.
+ */
+ public String getUnderlying(Lookup lPath)
+ {
+ if (fData.getPrimaryIndirection())
+ {
+ return fData.getIndirection();
+ }
+ return lPath.getCurrentIndirection();
+ }
+
+ /**
+ * Get the layer id for this node.
+ * @return The layer id.
+ */
+ public long getLayerID()
+ {
+ return fData.getLayerID();
+ }
+
+ /**
+ * Set the layer id for this node.
+ * @param layerID The id to set.
+ */
+ public void setLayerID(long id)
+ {
+ fData.setLayerID(id);
+ }
+
+ /**
+ * Handle post copy on write details.
+ * @param parent
+ */
+ public void handlePostCopy(DirectoryNode parent)
+ {
+ if (parent instanceof LayeredDirectoryNode)
+ {
+ LayeredDirectoryNode dir = (LayeredDirectoryNode)parent;
+ setLayerID(dir.getLayerID());
+ // TODO Is this right?
+ setRepository(parent.getRepository());
+ }
+ }
+
+ /**
+ * Copy on write logic.
+ * @param lPath
+ * @return The copy or null.
+ */
+ public AVMNode possiblyCopy(Lookup lPath)
+ {
+ if (!shouldBeCopied())
+ {
+ return null;
+ }
+ // Otherwise we do an actual copy.
+ LayeredDirectoryNode newMe = null;
+ long newBranchID = lPath.getHighestBranch();
+ if (!lPath.isInThisLayer())
+ {
+ if (hasPrimaryIndirection())
+ {
+ newMe = new LayeredDirectoryNode(lPath.getIndirectionPath(),
+ getRepository());
+ }
+ else
+ {
+ newMe = new LayeredDirectoryNode((String)null,
+ getRepository());
+ newMe.setPrimaryIndirection(false);
+ }
+ }
+ else
+ {
+ newMe = new LayeredDirectoryNode(this,
+ getRepository());
+
+ newMe.setLayerID(getLayerID());
+ }
+ newMe.setAncestor(this);
+ newMe.setBranchID(newBranchID);
+ return newMe;
+ }
+
+ /**
+ * Insert a child node without COW.
+ * @param name The name to give the child.
+ */
+ public void putChild(String name, AVMNode node)
+ {
+ DirectoryEntry entry = new DirectoryEntry(node.getType(), node.getDataBean());
+ fData.getAdded().put(name, entry);
+ fData.getDeleted().remove(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#addChild(java.lang.String, org.alfresco.repo.avm.AVMNode, org.alfresco.repo.avm.Lookup)
+ */
+ public boolean addChild(String name, AVMNode child, Lookup lPath)
+ {
+ if (fData.getAdded().containsKey(name))
+ {
+ return false;
+ }
+ if (!fData.getDeleted().contains(name))
+ {
+ try
+ {
+ Lookup lookup = getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath));
+ DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
+ if (dir.lookupChild(lookup, name, -1) != null)
+ {
+ return false;
+ }
+ }
+ catch (AlfrescoRuntimeException re)
+ {
+ // Do nothing.
+ }
+ }
+ DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
+ toModify.putChild(name, child);
+ child.setParent(toModify);
+ child.setRepository(toModify.getRepository());
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#directlyContains(org.alfresco.repo.avm.AVMNode)
+ */
+ public boolean directlyContains(AVMNode node)
+ {
+ return fData.getAdded().containsValue(node.getDataBean());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#getListing(org.alfresco.repo.avm.Lookup, int)
+ */
+ public Map getListing(Lookup lPath, int version)
+ {
+ Map baseListing = null;
+ try
+ {
+ Lookup lookup = getRepository().getSuperRepository().lookupDirectory(version, getUnderlying(lPath));
+ DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
+ baseListing = dir.getListing(lookup, version);
+ }
+ catch (AlfrescoRuntimeException re)
+ {
+ baseListing = new HashMap();
+ }
+ Map listing = new TreeMap();
+ for (String name : baseListing.keySet())
+ {
+ if (fData.getDeleted().contains(name))
+ {
+ continue;
+ }
+ listing.put(name, baseListing.get(name));
+ }
+ for (String name : fData.getAdded().keySet())
+ {
+ listing.put(name, fData.getAdded().get(name));
+ }
+ return listing;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#lookupChild(org.alfresco.repo.avm.Lookup, java.lang.String, int)
+ */
+ public AVMNode lookupChild(Lookup lPath, String name, int version)
+ {
+ // TODO revisit the order in this.
+ if (fData.getAdded().containsKey(name))
+ {
+ return AVMNodeFactory.CreateFromBean(fData.getAdded().get(name).getChild());
+ }
+ AVMNode child = null;
+ try
+ {
+ Lookup lookup = getRepository().getSuperRepository().lookupDirectory(version, getUnderlying(lPath));
+ DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
+ child = dir.lookupChild(lookup, name, version);
+ }
+ catch (AlfrescoRuntimeException re)
+ {
+ return null;
+ }
+ if (child ==null)
+ {
+ return null;
+ }
+ if (fData.getDeleted().contains(name))
+ {
+ return null;
+ }
+ return child;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#rawRemoveChild(java.lang.String)
+ */
+ public void rawRemoveChild(String name)
+ {
+ fData.getAdded().remove(name);
+ fData.getDeleted().add(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.DirectoryNode#removeChild(java.lang.String, org.alfresco.repo.avm.Lookup)
+ */
+ public boolean removeChild(String name, Lookup lPath)
+ {
+ if (fData.getDeleted().contains(name))
+ {
+ return false;
+ }
+ if (!fData.getAdded().containsKey(name))
+ {
+ try
+ {
+ Lookup lookup = getRepository().getSuperRepository().lookupDirectory(-1, getUnderlying(lPath));
+ DirectoryNode dir = (DirectoryNode)lookup.getCurrentNode();
+ if (dir.lookupChild(lookup, name, -1) == null)
+ {
+ return false;
+ }
+ }
+ catch (AlfrescoRuntimeException re)
+ {
+ return false;
+ }
+ }
+ LayeredDirectoryNode toModify =
+ (LayeredDirectoryNode)copyOnWrite(lPath);
+ toModify.rawRemoveChild(name);
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMNode#getType()
+ */
+ public AVMNodeType getType()
+ {
+ return AVMNodeType.LAYERED_DIRECTORY;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNode.java b/source/java/org/alfresco/repo/avm/LayeredFileNode.java
new file mode 100644
index 0000000000..7ff85a540a
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/LayeredFileNode.java
@@ -0,0 +1,119 @@
+/*
+ * 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 org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.avm.hibernate.LayeredFileNodeBean;
+
+/**
+ * A LayeredFileNode behaves like a copy on write symlink.
+ * @author britt
+ */
+public class LayeredFileNode extends FileNode
+{
+ /**
+ * The data bean.
+ */
+ private LayeredFileNodeBean fData;
+
+ /**
+ * Construct one from its data bean.
+ */
+ public LayeredFileNode(LayeredFileNodeBean data)
+ {
+ fData = data;
+ setDataBean(fData);
+ }
+
+ /**
+ * Basically a copy constructor.
+ * @param other The file to make a copy of.
+ * @param repo The repository that contains us.
+ */
+ public LayeredFileNode(LayeredFileNode other, Repository repo)
+ {
+ // TODO Something.
+ }
+
+ public LayeredFileNode(FileNode file,
+ Repository repos,
+ Lookup srcLookup,
+ String name)
+ {
+ // TODO Something.
+ }
+
+
+ /**
+ * Set the repository after a copy.
+ * @param parent The parent after copying.
+ */
+ public void handlePostCopy(DirectoryNode parent)
+ {
+ if (parent != null)
+ {
+ setRepository(parent.getRepository());
+ }
+ }
+
+ /**
+ * Copy on write logic.
+ * @param lPath The path by which this was found.
+ */
+ public AVMNode possiblyCopy(Lookup lPath)
+ {
+ // LayeredFileNodes are always copied.
+ PlainFileNode newMe = new PlainFileNode(getRepository());
+ newMe.setAncestor(this);
+ return newMe;
+ }
+
+ /**
+ * Get the type of this node.
+ * @return The type.
+ */
+ public AVMNodeType getType()
+ {
+ return AVMNodeType.LAYERED_FILE;
+ }
+
+ /**
+ * Get the content of the specified version.
+ * @return A FileContent object.
+ */
+ public FileContent getContentForRead(int version)
+ {
+ Lookup lookup = getRepository().getSuperRepository().lookup(version, fData.getIndirection());
+ AVMNode node = lookup.getCurrentNode();
+ if (!(node instanceof FileNode))
+ {
+ throw new AlfrescoRuntimeException("Missing Link.");
+ }
+ FileNode file = (FileNode)node;
+ return file.getContentForRead(version);
+ }
+
+ /**
+ * Get File Content for writing. Should never be called.
+ */
+ public FileContent getContentForWrite(Repository repo)
+ {
+ assert false : "Never happens";
+ return null;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/Lookup.java b/source/java/org/alfresco/repo/avm/Lookup.java
new file mode 100644
index 0000000000..006d082823
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/Lookup.java
@@ -0,0 +1,290 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+/**
+ * This holds all the information necessary to perform operations
+ * on AVMNodes.
+ * @author britt
+ */
+public class Lookup
+{
+ /**
+ * The Repository.
+ */
+ @SuppressWarnings("unused")
+ private Repository fRepository;
+
+ /**
+ * The name of the Repository.
+ */
+ @SuppressWarnings("unused")
+ private String fRepName;
+
+ /**
+ * The components that make up this path.
+ */
+ private List fComponents;
+
+ /**
+ * Whether, at this point, a layered node has been hit.
+ * Used while building a Lookup.
+ */
+ private boolean fLayeredYet;
+
+ /**
+ * The first LayeredDirectoryNode in the path.
+ */
+ private LayeredDirectoryNode fTopLayer;
+
+ /**
+ * The path index of the top LayeredDirectoryNode in the path.
+ */
+ private int fTopLayerIndex;
+
+ /**
+ * The highest branch id seen in the lookup.
+ */
+ private long fHighestBranchID;
+
+ /**
+ * The lowest layered directory node's index seen so far.
+ */
+ private int fLowestLayerIndex;
+
+ /**
+ * The current component being looked at by this lookup.
+ */
+ private int fPosition;
+
+ /**
+ * Create a new instance.
+ */
+ public Lookup(Repository repository, String repName)
+ {
+ fRepository = repository;
+ fRepName = repName;
+ fComponents = new ArrayList();
+ fLayeredYet = false;
+ fTopLayer = null;
+ fHighestBranchID = 0;
+ fPosition = -1;
+ fTopLayerIndex = -1;
+ fLowestLayerIndex = -1;
+ }
+
+ /**
+ * Add a new node to the lookup.
+ * @param node The node to add.
+ * @param name The name of the node in the path.
+ */
+ public void add(AVMNode node, String name)
+ {
+ LookupComponent comp = new LookupComponent();
+ comp.setName(name);
+ comp.setNode(node);
+ // Bump up the highest branch id seen if necessary.
+ if (node.getBranchID() > fHighestBranchID)
+ {
+ fHighestBranchID = node.getBranchID();
+ }
+ // Set the highest branch id seen by this component in the lookup.
+ comp.setHighestBranch(fHighestBranchID);
+ // Record various things if this is layered.
+ if (node instanceof LayeredDirectoryNode)
+ {
+ LayeredDirectoryNode oNode = (LayeredDirectoryNode)node;
+ // Record the indirection path that should be used.
+ if (oNode.hasPrimaryIndirection())
+ {
+ comp.setIndirection(oNode.getUnderlying());
+ }
+ else
+ {
+ comp.setIndirection(fComponents.get(fPosition).getIndirection() + "/" + name);
+ }
+ fLayeredYet = true;
+ // Record the first layer seen.
+ if (fTopLayer == null)
+ {
+ fTopLayer = oNode;
+ fTopLayerIndex = fPosition + 1;
+ }
+ fLowestLayerIndex = fPosition + 1;
+ }
+ comp.setLowestLayerIndex(fLowestLayerIndex);
+ comp.setLayered(fLayeredYet);
+ fComponents.add(comp);
+ fPosition++;
+ }
+
+ /**
+ * Get the current node we're looking at.
+ * @return The current node.
+ */
+ public AVMNode getCurrentNode()
+ {
+ return fComponents.get(fPosition).getNode();
+ }
+
+ /**
+ * Set the current node to one higher in the lookup.
+ */
+ public void upCurrentNode()
+ {
+ fPosition--;
+ }
+
+ /**
+ * Is the current path layered.
+ * @return Whether the current position in the path is layered.
+ */
+ public boolean isLayered()
+ {
+ assert fPosition >= 0;
+ return fComponents.get(fPosition).isLayered();
+ }
+
+ /**
+ * Determine if a node is directly in this layer.
+ * @return Whether this node is directly in this layer.
+ */
+ public boolean isInThisLayer()
+ {
+ if (!isLayered())
+ {
+ return false;
+ }
+ int pos = fPosition;
+ // Special case of the top layer.
+ if (fComponents.get(pos).getNode() == fTopLayer)
+ {
+ return true;
+ }
+ while (pos > 1)
+ {
+ DirectoryNode dir = (DirectoryNode)fComponents.get(pos - 1).getNode();
+ if (!dir.directlyContains(fComponents.get(pos).getNode()))
+ {
+ return false;
+ }
+ if (dir == fTopLayer)
+ {
+ return true;
+ }
+ pos--;
+ }
+ return false;
+ }
+
+ /**
+ * Get the highest branch traversed in this lookup at the current position.
+ * @return The highest branch traversed.
+ */
+ public long getHighestBranch()
+ {
+ return fComponents.get(fPosition).getHighestBranch();
+ }
+
+ /**
+ * Get the name of the current component.
+ * @return The name.
+ */
+ public String getName()
+ {
+ return fComponents.get(fPosition).getName();
+ }
+
+ /**
+ * Get the number of nodes.
+ * @return The number of nodes.
+ */
+ public int size()
+ {
+ return fComponents.size();
+ }
+
+ /**
+ * Get the current position within the lookup.
+ * @return The current position.
+ */
+ public int getPosition()
+ {
+ return fPosition;
+ }
+
+ /**
+ * Calculate the indirection path at this node.
+ * @return The indirection path all the way down to the current node.
+ */
+ public String getIndirectionPath()
+ {
+ int lowestLayerIndex = fComponents.get(fPosition).getLowestLayerIndex();
+ // The path is the underlying path of the lowest layer that is directly contained
+ // by the top layer that is a primary indirection node.
+ for (int pos = lowestLayerIndex; pos >= fTopLayerIndex; pos--)
+ {
+ AVMNode node = fComponents.get(pos).getNode();
+ if (!(node instanceof LayeredDirectoryNode))
+ {
+ continue;
+ }
+ LayeredDirectoryNode oNode =
+ (LayeredDirectoryNode)node;
+ if (oNode.getLayerID() == fTopLayer.getLayerID())
+ {
+ if (oNode.hasPrimaryIndirection())
+ {
+ StringBuilder builder = new StringBuilder();
+ builder.append(oNode.getUnderlying());
+ for (int i = pos + 1; i <= fPosition; i++)
+ {
+ builder.append("/");
+ builder.append(fComponents.get(i).getName());
+ }
+ return builder.toString();
+ }
+ }
+ }
+ // TODO This is gross. There has to be a neater way to do this.
+ assert false : "Not reached.";
+ return "bogus";
+ }
+
+ /**
+ * Get the computed indirection for the current node.
+ * @return The indirection.
+ */
+ public String getCurrentIndirection()
+ {
+ return fComponents.get(fPosition).getIndirection();
+ }
+
+ /**
+ * Get the topmost Layered directory node. Topmost in the
+ * path lookup sense.
+ * @return The topmost layered directory node.
+ */
+ public LayeredDirectoryNode getTopLayer()
+ {
+ return fTopLayer;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/LookupComponent.java b/source/java/org/alfresco/repo/avm/LookupComponent.java
new file mode 100644
index 0000000000..8cff08efeb
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/LookupComponent.java
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+/**
+ * Represents a path component in a lookup.
+ * @author britt
+ */
+public class LookupComponent
+{
+ /**
+ * The name of this component.
+ */
+ private String fName;
+
+ /**
+ * The node of this component.
+ */
+ private AVMNode fNode;
+
+ /**
+ * The highest branch seen by this component.
+ */
+ private long fHighestBranch;
+
+ /**
+ * The indirection path (if any) for this node.
+ */
+ private String fIndirection;
+
+ /**
+ * The lowest layer index.
+ */
+ private int fLowestLayerIndex;
+
+ /**
+ * Whether this node is in a layer.
+ */
+ private boolean fLayered;
+
+ /**
+ * @return the highestBranch
+ */
+ public long getHighestBranch()
+ {
+ return fHighestBranch;
+ }
+
+ /**
+ * Create a new empty lookup component.
+ */
+ public LookupComponent()
+ {
+ }
+
+ /**
+ * @param highestBranch the highestBranch to set
+ */
+ public void setHighestBranch(long highestBranch)
+ {
+ fHighestBranch = highestBranch;
+ }
+
+ /**
+ * @return the indirection
+ */
+ public String getIndirection()
+ {
+ return fIndirection;
+ }
+
+ /**
+ * @param indirection the indirection to set
+ */
+ public void setIndirection(String indirection)
+ {
+ fIndirection = indirection;
+ }
+
+ /**
+ * @return the layered
+ */
+ public boolean isLayered()
+ {
+ return fLayered;
+ }
+
+ /**
+ * @param layered the layered to set
+ */
+ public void setLayered(boolean layered)
+ {
+ fLayered = layered;
+ }
+
+ /**
+ * @return the lowestLayerIndex
+ */
+ public int getLowestLayerIndex()
+ {
+ return fLowestLayerIndex;
+ }
+
+ /**
+ * @param lowestLayerIndex the lowestLayerIndex to set
+ */
+ public void setLowestLayerIndex(int lowestLayerIndex)
+ {
+ fLowestLayerIndex = lowestLayerIndex;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName()
+ {
+ return fName;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name)
+ {
+ fName = name;
+ }
+
+ /**
+ * @return the node
+ */
+ public AVMNode getNode()
+ {
+ return fNode;
+ }
+
+ /**
+ * @param node the node to set
+ */
+ public void setNode(AVMNode node)
+ {
+ fNode = node;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/PlainDirectoryNode.java b/source/java/org/alfresco/repo/avm/PlainDirectoryNode.java
new file mode 100644
index 0000000000..e0fdc28cc7
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/PlainDirectoryNode.java
@@ -0,0 +1,228 @@
+/*
+ * 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.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.alfresco.repo.avm.hibernate.DirectoryEntry;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBeanImpl;
+
+/**
+ * @author britt
+ *
+ */
+public class PlainDirectoryNode extends DirectoryNode
+{
+ /**
+ * The Bean data.
+ */
+ private PlainDirectoryNodeBean fData;
+
+ /**
+ * Make up a new directory with nothing in it.
+ * @param repo
+ */
+ public PlainDirectoryNode(Repository repo)
+ {
+ fData = new PlainDirectoryNodeBeanImpl(repo.getSuperRepository().issueID(),
+ repo.getLatestVersion(),
+ 0L,
+ null,
+ null,
+ null,
+ repo.getDataBean(),
+ false);
+ repo.getSuperRepository().getSession().save(fData);
+ }
+
+ /**
+ * Make one up from its bean data.
+ * @param data The bean data.
+ */
+ public PlainDirectoryNode(PlainDirectoryNodeBean data)
+ {
+ fData = data;
+ setDataBean(data);
+ }
+
+ /**
+ * Copy like constructor.
+ * @param other The other directory.
+ * @param repos The Repository Object that will own us.
+ */
+ public PlainDirectoryNode(PlainDirectoryNode other,
+ Repository repos)
+ {
+ fData = new PlainDirectoryNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ false);
+ setDataBean(fData);
+ fData.setChildren(new HashMap(((PlainDirectoryNodeBean)other.getDataBean()).getChildren()));
+ }
+
+ /**
+ * Add a child to this directory, possibly doing a copy.
+ * @param name The name of the child.
+ * @param child The child node.
+ * @param lPath The lookup path to this directory.
+ * @return Success or failure.
+ */
+ public boolean addChild(String name, AVMNode child, Lookup lPath)
+ {
+ if (fData.getChildren().containsKey(name))
+ {
+ return false;
+ }
+ DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
+ toModify.putChild(name, child);
+ child.setParent(toModify);
+ child.setRepository(toModify.getRepository());
+ return true;
+ }
+
+ /**
+ * Does this directory directly contain the given node.
+ * @param node The node to check.
+ * @return Whether it was found.
+ */
+ public boolean directlyContains(AVMNode node)
+ {
+ return fData.getChildren().containsValue(node.getDataBean());
+ }
+
+
+ /**
+ * Get a directory listing.
+ * @param lPath The lookup path.
+ * @param version Which version.
+ * @return The listing.
+ */
+ public Map getListing(Lookup lPath, int version)
+ {
+ return new TreeMap(fData.getChildren());
+ }
+
+ /**
+ * Lookup a child by name.
+ * @param lPath The lookup path so far.
+ * @param name The name to lookup.
+ * @param version The version to look under.
+ * @return The child or null.
+ */
+ public AVMNode lookupChild(Lookup lPath, String name, int version)
+ {
+ DirectoryEntry child = fData.getChildren().get(name);
+ if (child == null)
+ {
+ return null;
+ }
+ return AVMNodeFactory.CreateFromBean(child.getChild());
+ }
+
+ /**
+ * Remove a child, no copying.
+ * @param name The name of the child to remove.
+ */
+ public void rawRemoveChild(String name)
+ {
+ fData.getChildren().remove(name);
+ }
+
+ /**
+ * Remove a child. Possibly copy.
+ * @param name The name of the child to remove.
+ * @param lPath The lookup path.
+ * @return Success or failure.
+ */
+ public boolean removeChild(String name, Lookup lPath)
+ {
+ if (!fData.getChildren().containsKey(name))
+ {
+ return false;
+ }
+ DirectoryNode toModify = (DirectoryNode)copyOnWrite(lPath);
+ toModify.rawRemoveChild(name);
+ return true;
+ }
+
+ /**
+ * Put a new child node into this directory. No copy.
+ * @param name The namke of the child.
+ * @param node The node to add.
+ */
+ public void putChild(String name, AVMNode node)
+ {
+ fData.getChildren().put(name, new DirectoryEntry(node.getType(), node.getDataBean()));
+ }
+
+ /**
+ * Set repository after copy on write.
+ * @param parent The parent after copy on write.
+ */
+ public void handlePostCopy(DirectoryNode parent)
+ {
+ if (parent != null)
+ {
+ setRepository(parent.getRepository());
+ }
+ }
+
+ /**
+ * Copy on write logic.
+ * @param lPath The lookup path.
+ * @return
+ */
+ public AVMNode possiblyCopy(Lookup lPath)
+ {
+ if (!shouldBeCopied())
+ {
+ return null;
+ }
+ // Otherwise do an actual copy.
+ DirectoryNode newMe = null;
+ long newBranchID = lPath.getHighestBranch();
+ if (lPath.isLayered())
+ {
+ newMe = new LayeredDirectoryNode(this, getRepository(), lPath);
+ }
+ else
+ {
+ newMe = new PlainDirectoryNode(this, getRepository());
+ }
+ newMe.setAncestor(this);
+ newMe.setBranchID(newBranchID);
+ return newMe;
+ }
+
+ /**
+ * Get the type of this node.
+ * @return The type of this node.
+ */
+ public AVMNodeType getType()
+ {
+ return AVMNodeType.PLAIN_DIRECTORY;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/PlainFileNode.java b/source/java/org/alfresco/repo/avm/PlainFileNode.java
new file mode 100644
index 0000000000..a3c83c76d5
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/PlainFileNode.java
@@ -0,0 +1,146 @@
+/*
+ * 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 org.alfresco.repo.avm.hibernate.ContentBean;
+import org.alfresco.repo.avm.hibernate.ContentBeanImpl;
+import org.alfresco.repo.avm.hibernate.PlainFileNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainFileNodeBeanImpl;
+
+/**
+ * @author britt
+ *
+ */
+public class PlainFileNode extends FileNode
+{
+ /**
+ * The data bean.
+ */
+ private PlainFileNodeBean fData;
+
+ /**
+ * Construct one from its data bean.
+ * @param data The data bean.
+ */
+ public PlainFileNode(PlainFileNodeBean data)
+ {
+ fData = data;
+ setDataBean(data);
+ }
+
+ /**
+ * Make one from just a repository.
+ * @param repos A Repository.
+ */
+ public PlainFileNode(Repository repos)
+ {
+ ContentBean content = new ContentBeanImpl(repos.getSuperRepository().issueContentID());
+ fData = new PlainFileNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ content);
+ content.setRefCount(1);
+ // Transitive persistence should take care of content.
+ repos.getSuperRepository().getSession().save(fData);
+ setDataBean(fData);
+ }
+
+ /**
+ * Copy on write constructor.
+ * @param other The node we are being copied from.
+ * @param repos The Repository.
+ */
+ public PlainFileNode(PlainFileNode other,
+ Repository repos)
+ {
+ fData = new PlainFileNodeBeanImpl(repos.getSuperRepository().issueID(),
+ -1,
+ -1,
+ null,
+ null,
+ null,
+ repos.getDataBean(),
+ other.fData.getContent());
+ repos.getSuperRepository().getSession().save(fData);
+ fData.getContent().setRefCount(fData.getContent().getRefCount() + 1);
+ setDataBean(fData);
+ }
+
+ /**
+ * Handle setting repository after a COW.
+ * @param parent The possibly new parent directory.
+ */
+ public void handlePostCopy(DirectoryNode parent)
+ {
+ if (parent != null)
+ {
+ setRepository(parent.getRepository());
+ }
+ }
+
+ /**
+ * Copy on write logic.
+ * @param lPath The lookup path.
+ */
+ public AVMNode possiblyCopy(Lookup lPath)
+ {
+ if (!shouldBeCopied())
+ {
+ return null;
+ }
+ PlainFileNode newMe = new PlainFileNode(this, getRepository());
+ newMe.setAncestor(this);
+ newMe.setBranchID(lPath.getHighestBranch());
+ return newMe;
+ }
+
+ /**
+ * Get the type of this node.
+ * @return The type.
+ */
+ public AVMNodeType getType()
+ {
+ return AVMNodeType.PLAIN_FILE;
+ }
+
+ /**
+ * Get content for reading.
+ */
+ public FileContent getContentForRead(int version)
+ {
+ return FileContentFactory.CreateFileContentFromBean(fData.getContent());
+ }
+
+ /**
+ * Get content for writing.
+ * @param repo The Repository.
+ */
+ public FileContent getContentForWrite(Repository repo)
+ {
+ if (fData.getContent().getRefCount() > 1)
+ {
+ fData.setContent(new ContentBeanImpl(repo.getSuperRepository().issueContentID()));
+ // Need to copy the underlying file data.
+ }
+ return FileContentFactory.CreateFileContentFromBean(fData.getContent());
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/Repository.java b/source/java/org/alfresco/repo/avm/Repository.java
new file mode 100644
index 0000000000..7dc1ea28b8
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/Repository.java
@@ -0,0 +1,171 @@
+/*
+ * 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.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.repo.avm.hibernate.RepositoryBean;
+
+
+/**
+ * This is the interface between low level repository objects
+ * and the high level implementation of the repository.
+ * @author britt
+ */
+public interface Repository
+{
+ /**
+ * Inform this Repository that a Node is new and should
+ * therefore not be copied.
+ * @param node The node that is reporting itself.
+ */
+ public void setNew(AVMNode node);
+
+ /**
+ * Get the latest version id.
+ * @return The latest version.
+ */
+ public long getLatestVersion();
+
+ /**
+ * Inform this Repository that the root node is new.
+ * @param root The new root directory node.
+ */
+ public void setNewRoot(DirectoryNode root);
+
+ /**
+ * Make a snapshot. Equivalent of subversion end of commit. A new
+ * version number is issued.
+ */
+ public void createSnapshot();
+
+ /**
+ * Create a new directory.
+ * @param path The path to the directory for creation.
+ * @param name The name for the new directory.
+ */
+ public void createDirectory(String path, String name);
+
+ /**
+ * Create a layered directory over srcPath at dstPath/name.
+ * @param srcPath Fully qualified path.
+ * @param dstPath Repository path to target directory.
+ * @param name What the new layered directory should be called.
+ */
+ public void createLayeredDirectory(String srcPath, String dstPath, String name);
+
+ /**
+ * Create a new empty file.
+ * @param path The path to the directory for creation.
+ * @param name The name for the new file.
+ */
+ public void createFile(String path, String name);
+
+ /**
+ * Create a layered file over srcPath at dstPath/name
+ * @param srcPath Fully qualified path.
+ * @param dstPath Repository path.
+ * @param name The name the new layered file should have.
+ */
+ public void createLayeredFile(String srcPath, String dstPath, String name);
+
+ /**
+ * Get an input stream from an existing file.
+ * TODO Figure out nio way of doing things.
+ * @param version The version id to look under.
+ * @param path The path to the file.
+ * @return An InputStream.
+ */
+ public InputStream getInputStream(int version, String path);
+
+ /**
+ * Get a directory listing.
+ * @param version The version to look under.
+ * @param path The path to the directory.
+ * @return A List of FolderEntries.
+ */
+ public List getListing(int version, String path);
+
+ /**
+ * Get an OutputStream to an existing file. This may trigger a copy.
+ * @param path The path to the file.
+ */
+ public OutputStream getOutputStream(String path);
+
+ /**
+ * Remove a node from a directory.
+ * @param path The path to the directory.
+ * @param name The name of the node to remove.
+ */
+ public void removeNode(String path, String name);
+
+ /**
+ * This moves a node from one place in a layer to another place in
+ * the same layer without leaving a deleted entry in the source directory.
+ * @param srcPath The path containing the src node.
+ * @param srcName The name of the src node.
+ * @param dstPath The destination container.
+ * @param dstName The name of the destination node.
+ */
+ public void slide(String srcPath, String srcName, String dstPath, String dstName);
+
+ /**
+ * Get the version ids that this Repository has.
+ * @return A Set of Version IDs.
+ */
+ public Set getVersions();
+
+ /**
+ * Get the data bean.
+ * @return The data bean.
+ */
+ public RepositoryBean getDataBean();
+
+ /**
+ * Get the super repository.
+ * @return The SuperRepository.
+ */
+ public SuperRepository getSuperRepository();
+
+ /**
+ * Get a lookup object for a path.
+ * @param version The version to look under.
+ * @param path The Repository path.
+ * @return The Lookup.
+ */
+ public Lookup lookup(int version, String path);
+
+ /**
+ * Get a lookup object for a path. Directory only.
+ * @param version The version to look under.
+ * @param path The Repository path.
+ * @return The Lookup.
+ */
+ public Lookup lookupDirectory(int version, String path);
+
+ /**
+ * Get the indirection path of a layered node.
+ * @param version The version id.
+ * @param path The Repository path.
+ * @return The indirection.
+ */
+ public String getIndirectionPath(int version, String path);
+}
diff --git a/source/java/org/alfresco/repo/avm/RepositoryFactory.java b/source/java/org/alfresco/repo/avm/RepositoryFactory.java
new file mode 100644
index 0000000000..4aeb7553c0
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/RepositoryFactory.java
@@ -0,0 +1,72 @@
+/*
+ * 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 org.alfresco.repo.avm.hibernate.RepositoryBean;
+import org.alfresco.repo.avm.impl.RepositoryImpl;
+
+/**
+ * @author britt
+ *
+ */
+public class RepositoryFactory
+{
+ /**
+ * The single instance of this. So far.
+ */
+ private static RepositoryFactory fgFactory;
+
+ /**
+ * The super repository.
+ */
+ private SuperRepository fSuper;
+
+ public RepositoryFactory()
+ {
+ fSuper = null;
+ fgFactory = this;
+ }
+
+ /**
+ * Create a Repository instance from a bean.
+ * @param bean The RepositoryBean.
+ * @return A Repository instance.
+ */
+ public Repository createFromBean(RepositoryBean bean)
+ {
+ return new RepositoryImpl(fSuper, bean);
+ }
+
+ /**
+ * Set the super repository.
+ * @param superRepo
+ */
+ public void setSuperRepository(SuperRepository superRepo)
+ {
+ fSuper = superRepo;
+ }
+
+ /**
+ * Get the single instance.
+ * @return The instance.
+ */
+ public static RepositoryFactory GetInstance()
+ {
+ return fgFactory;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/SuperRepository.java b/source/java/org/alfresco/repo/avm/SuperRepository.java
new file mode 100644
index 0000000000..9027a65543
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/SuperRepository.java
@@ -0,0 +1,234 @@
+/*
+ * 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.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.hibernate.Session;
+
+/**
+ * A SuperRepository is responsible for the high level implemenation of all
+ * operations on Repositories. It is responsible for issuing Node ids, branch ids,
+ * and layer ids. Repositories themselves are responsible for issuing version ids.
+ * Paths in super repositories are of the form "repositoryname:/a/b/c/d
+ * @author britt
+ */
+public interface SuperRepository
+{
+ // Modify operations.
+
+ /**
+ * Create a new file.
+ * @param path The path to create the file in.
+ * @param name The name to give the new file.
+ */
+ public void createFile(String path, String name);
+
+ /**
+ * Create a new Directory.
+ * @param path The path to create the directory in.
+ * @param name The name to give the new directory.
+ */
+ public void createDirectory(String path, String name);
+
+ /**
+ * Create a new LayeredDirectory.
+ * @param srcPath The source path that the LayeredDirectory refers to.
+ * @param dstPath The path to create the new LayeredDirectory in.
+ * @param name The name to give the new LayeredDirectory.
+ */
+ public void createLayeredDirectory(String srcPath, String dstPath, String name);
+
+ /**
+ * Create a new LayeredFile.
+ * @param srcPath The source path that the LayeredFile refers to.
+ * @param dstPath The path to create the new LayeredFile in.
+ * @param name The name to give the new LayeredFile.
+ */
+ public void createLayeredFile(String srcPath, String dstPath, String name);
+
+ /**
+ * Create a new Repository.
+ * @param name The name to give the repository.
+ */
+ public void createRepository(String name);
+
+ /**
+ * Create a branch.
+ * @param version The version to look under.
+ * @param srcPath The path to the source node for the branch.
+ * @param dstPath The directory to put the branch in.
+ * @param name The name for the new branch.
+ */
+ public void createBranch(int version, String srcPath, String dstPath, String name);
+
+ // Modify operations.
+
+ /**
+ * Get an OutputStream to a file.
+ * @param path The path to the file.
+ * @return An OutputStream.
+ */
+ public OutputStream getOutputStream(String path);
+
+ /**
+ * Rename a node.
+ * @param srcPath The source path.
+ * @param srcName The name of the node to rename.
+ * @param dstPath The destination directory for the rename.
+ * @param dstName The name to give the renamed node.
+ */
+ public void rename(String srcPath, String srcName, String dstPath, String dstName);
+
+ /**
+ * Slide a directory in a layer to another location in the same
+ * layer uncovering what was originally shadowed.
+ * @param srcPath The source path.
+ * @param srcName The name of the directory to slide.
+ * @param dstPath The destination directory for the slide.
+ * @param dstName The name of the directory after sliding.
+ */
+ public void slide(String srcPath, String srcName, String dstPath, String dstName);
+
+ /**
+ * Create a snapshot of the given repositories.
+ * @param repositories A List of Repository names.
+ */
+ public void createSnapshot(List repositories);
+
+ // Different flavors of deletions.
+
+ /**
+ * Delete a node.
+ * @param path The path to the containing directory.
+ * @param name The name of the node to remove.
+ */
+ public void remove(String path, String name);
+
+ /**
+ * Purge a repository.
+ * @param name
+ */
+ public void destroyRepository(String name);
+
+ /**
+ * Purge a version in a repository.
+ * @param name The name of the repository.
+ * @param version The id of the version to purge.
+ */
+ public void purgeVersion(String name, int version);
+
+ // Read operations.
+
+ /**
+ * Get an InputStream from a File.
+ * @param version The version to look under.
+ * @param path The path to the file.
+ * @return An InputStream.
+ */
+ public InputStream getInputStream(int version, String path);
+
+ /**
+ * Get the listing for a directory.
+ * @param version The version to get a listing of.
+ * @param path The path to the directory.
+ * @return A List of FolderEntries.
+ */
+ public List getListing(int version, String path);
+
+ /**
+ * Get a listing of all repository names.
+ * @return A List of repository names.
+ */
+ public List getRepositoryNames();
+
+ /**
+ * Get a Set of version IDs for a given Repository.
+ * @param name The name of the repository.
+ * @return A Set of IDs.
+ */
+ public Set getRepositoryVersions(String name);
+
+ /**
+ * Issue a unique identifier for a new node.
+ * @return A new identifier.
+ */
+ public long issueID();
+
+ /**
+ * Issue an ID for content.
+ * @return A new content ID.
+ */
+ public long issueContentID();
+
+ /**
+ * Get the current Hibernate Session.
+ * @return The Hibernate Session object.
+ */
+ public Session getSession();
+
+ /**
+ * Return an OutputStream for the content object of the given id. This
+ * creates the directory path if needed.
+ * @param path The path to the file.
+ * @return An OutputStream.
+ */
+ public OutputStream createContentOutputStream(String path);
+
+ /**
+ * Gets an input stream from the content with the given id.
+ * @param version The version id.
+ * @param path The path to the file.
+ * @return An InputStream.
+ */
+ public InputStream getContentInputStream(int version, String path);
+
+ /**
+ * Get the latest version id for a given repository.
+ * @param name The name of the repository.
+ * @return The latest version id for the given repository.
+ */
+ public long getLatestVersionID(String name);
+
+ /**
+ * Get the indirection path for a layered node.
+ * @param version The version to look under.
+ * @param path The path to the node.
+ * @return The indirection path.
+ */
+ public String getIndirectionPath(int version, String path);
+
+ /**
+ * Get a lookup object for a path.
+ * @param version The version to look under.
+ * @param path The full path.
+ * @return The Lookup.
+ */
+ public Lookup lookup(int version, String path);
+
+ /**
+ * Get a lookup object for a path. Directory only.
+ * @param version The version to look under.
+ * @param path The full path.
+ * @return The Lookup.
+ */
+ public Lookup lookupDirectory(int version, String path);
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVMNode.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVMNode.hbm.xml
new file mode 100644
index 0000000000..1a943c71a3
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/AVMNode.hbm.xml
@@ -0,0 +1,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBean.java
new file mode 100644
index 0000000000..330080b585
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBean.java
@@ -0,0 +1,134 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * The base Node class for the new versioning model, at least for now.
+ * @author britt
+ */
+public interface AVMNodeBean
+{
+ /**
+ * Set the object id of this node.
+ * @param id The Object ID.
+ */
+ public void setId(long id);
+
+ /**
+ * Get the object id of this node.
+ * @return The Object ID of this node.
+ */
+ public long getId();
+
+ /**
+ * Set the version id.
+ * @param id The version id of the node.
+ */
+ public void setVersionID(long id);
+
+ /**
+ * Get the version id of this node.
+ * @return The version id.
+ */
+ public long getVersionID();
+
+ /**
+ * Set the parent of this node. This is only a canonical parent,
+ * the one that this node had at the time of its creation.
+ * @param parent The id of the parent node.
+ */
+ public void setParent(DirectoryNodeBean parent);
+
+ /**
+ * Get the parent of this node.
+ * @return The parent of this node.
+ */
+ public DirectoryNodeBean getParent();
+
+ /**
+ * Set the node that is this node's direct ancestor.
+ * @param ancestor The id of the ancestor node.
+ */
+ public void setAncestor(AVMNodeBean ancestor);
+
+ /**
+ * Get the direct ancestor of this node.
+ * @return The id of the direct ancestor of this node.
+ */
+ public AVMNodeBean getAncestor();
+
+ /**
+ * Set the node that this node was merged from.
+ * @param mergedFrom The id of the node from which this was merged.
+ */
+ public void setMergedFrom(AVMNodeBean mergedFrom);
+
+ /**
+ * Get the node that this was merged from.
+ * @return The id of the node this was merged from.
+ */
+ public AVMNodeBean getMergedFrom();
+
+ /**
+ * Set the branch id.
+ * @param branchID The branch id to set.
+ */
+ public void setBranchID(long branchID);
+
+ /**
+ * Get the branch id of this node.
+ * @return The branch id of this node.
+ */
+ public long getBranchID();
+
+ /**
+ * Set the Repository that owns this node.
+ * @param repository The repository that owns this node.
+ */
+ public void setRepository(RepositoryBean repository);
+
+ /**
+ * Get the Repository that owns this node.
+ * @return The Repository.
+ */
+ public RepositoryBean getRepository();
+
+ /**
+ * Set is new.
+ * @param isNew
+ */
+ public void setIsNew(boolean isNew);
+
+ /**
+ * Get is new.
+ * @return Whether this node is new.
+ */
+ public boolean getIsNew();
+
+ /**
+ * Set the version (for concurrency management.)
+ * @param vers The version.
+ */
+ public void setVers(long vers);
+
+ /**
+ * Get the version (for concurrency management.)
+ * @return The version.
+ */
+ public long getVers();
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBeanImpl.java
new file mode 100644
index 0000000000..82445f3db4
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/AVMNodeBeanImpl.java
@@ -0,0 +1,275 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * Base interface for versioned and layered node implementation data objects.
+ * @author britt
+ */
+public class AVMNodeBeanImpl implements AVMNodeBean
+{
+ /**
+ * The Object ID (and Primary Key)
+ */
+ private long fID;
+
+ /**
+ * The Version ID
+ */
+ private long fVersionID;
+
+ /**
+ * The Branch ID
+ */
+ private long fBranchID;
+
+ /**
+ * The ancestor of this.
+ */
+ private AVMNodeBean fAncestor;
+
+ /**
+ * The node that was merged into this.
+ */
+ private AVMNodeBean fMergedFrom;
+
+ /**
+ * The id of the parent of this.
+ */
+ private DirectoryNodeBean fParent;
+
+ /**
+ * The Repository that owns this.
+ */
+ private RepositoryBean fRepository;
+
+ /**
+ * Whether this node is new (and should therefore not be COWed).
+ */
+ private boolean fIsNew;
+
+ /**
+ * The version number (for concurrency control).
+ */
+ private long fVers;
+
+ /**
+ * Anonymous constructor.
+ */
+ public AVMNodeBeanImpl()
+ {
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The ID to set.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ * @param repository The repository.
+ */
+ public AVMNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository)
+ {
+ fID = id;
+ fVersionID = versionID;
+ fBranchID = branchID;
+ fAncestor = ancestor;
+ fMergedFrom = mergedFrom;
+ fParent = parent;
+ fRepository = repository;
+ fIsNew = true;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof AVMNodeBean))
+ {
+ return false;
+ }
+ return fID == ((AVMNodeBean)obj).getId();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode()
+ {
+ return (int)fID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setId(int)
+ */
+ public void setId(long id)
+ {
+ fID = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getId()
+ */
+ public long getId()
+ {
+ return fID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setVersionID(int)
+ */
+ public void setVersionID(long id)
+ {
+ fVersionID = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getVersionID()
+ */
+ public long getVersionID()
+ {
+ return fVersionID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setParent(int)
+ */
+ public void setParent(DirectoryNodeBean parent)
+ {
+ fParent = parent;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getParent()
+ */
+ public DirectoryNodeBean getParent()
+ {
+ return fParent;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setAncestor(int)
+ */
+ public void setAncestor(AVMNodeBean ancestor)
+ {
+ fAncestor = ancestor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getAncestor()
+ */
+ public AVMNodeBean getAncestor()
+ {
+ return fAncestor;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setMergedFrom(int)
+ */
+ public void setMergedFrom(AVMNodeBean mergedFrom)
+ {
+ fMergedFrom = mergedFrom;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getMergedFrom()
+ */
+ public AVMNodeBean getMergedFrom()
+ {
+ return fMergedFrom;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#setBranchID(int)
+ */
+ public void setBranchID(long branchID)
+ {
+ fBranchID = branchID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNode#getBranchID()
+ */
+ public long getBranchID()
+ {
+ return fBranchID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNodeBean#getRepository()
+ */
+ public RepositoryBean getRepository()
+ {
+ return fRepository;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.AVMNodeBean#setRepository(org.alfresco.proto.avm.RepositoryBean)
+ */
+ public void setRepository(RepositoryBean repository)
+ {
+ fRepository = repository;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.AVMNodeBean#getIsNew()
+ */
+ public boolean getIsNew()
+ {
+ return fIsNew;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.AVMNodeBean#setIsNew(boolean)
+ */
+ public void setIsNew(boolean isNew)
+ {
+ fIsNew = isNew;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.AVMNodeBean#getVers()
+ */
+ public long getVers()
+ {
+ return fVers;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.AVMNodeBean#setVers(java.lang.int)
+ */
+ public void setVers(long vers)
+ {
+ fVers = vers;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/Content.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/Content.hbm.xml
new file mode 100644
index 0000000000..9e0b69f80b
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/Content.hbm.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/avm/hibernate/ContentBean.java b/source/java/org/alfresco/repo/avm/hibernate/ContentBean.java
new file mode 100644
index 0000000000..551fa2a274
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/ContentBean.java
@@ -0,0 +1,61 @@
+/*
+ * 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.hibernate;
+
+/**
+ * This exists to share content across different versions.
+ * @author britt
+ */
+public interface ContentBean
+{
+ /**
+ * Set the object id.
+ * @param id The object id.
+ */
+ public void setId(long id);
+
+ /**
+ * Get the object id.
+ * @return The object id.
+ */
+ public long getId();
+
+ /**
+ * Set the reference count on this.
+ * @param refCount The reference count to set.
+ */
+ public void setRefCount(int refCount);
+
+ /**
+ * Get the reference count on this.
+ * @return The reference count.
+ */
+ public int getRefCount();
+
+ /**
+ * Set the version (for concurrency control).
+ * @param vers The version.
+ */
+ public void setVers(long vers);
+
+ /**
+ * Get the version (for concurrency control).
+ * @return The version.
+ */
+ public long getVers();
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/ContentBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/ContentBeanImpl.java
new file mode 100644
index 0000000000..426109fe2f
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/ContentBeanImpl.java
@@ -0,0 +1,124 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * @author britt
+ *
+ */
+public class ContentBeanImpl implements ContentBean
+{
+ /**
+ * The object id.
+ */
+ private long fID;
+
+ /**
+ * The reference count of this id.
+ */
+ private int fRefCount;
+
+ /**
+ * The version (for concurrency control).
+ */
+ private long fVers;
+
+ /**
+ * Basic constructor with an id.
+ */
+ public ContentBeanImpl(long id)
+ {
+ fID = id;
+ fRefCount = 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Content#setId(int)
+ */
+ public void setId(long id)
+ {
+ fID = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Content#getID()
+ */
+ public long getId()
+ {
+ return fID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Content#setRefCount(int)
+ */
+ public void setRefCount(int refCount)
+ {
+ fRefCount = refCount;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Content#getRefCount()
+ */
+ public int getRefCount()
+ {
+ return fRefCount;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof ContentBean))
+ {
+ return false;
+ }
+ return fID == ((ContentBean)obj).getId();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode()
+ {
+ return (int)fID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.ContentBean#getVers()
+ */
+ public long getVers()
+ {
+ return fVers;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.ContentBean#setVers(java.lang.int)
+ */
+ public void setVers(long vers)
+ {
+ fVers = vers;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/DirectoryEntry.java b/source/java/org/alfresco/repo/avm/hibernate/DirectoryEntry.java
new file mode 100644
index 0000000000..a3365a559b
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/DirectoryEntry.java
@@ -0,0 +1,108 @@
+/*
+ * 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.hibernate;
+
+import org.alfresco.repo.avm.AVMNodeType;
+
+/**
+ * This holds Directory Entries in directories.
+ * @author britt
+ */
+public class DirectoryEntry
+{
+ /**
+ * The type of entry a node is.
+ */
+ private AVMNodeType fType;
+
+ /**
+ * This is the actual child Node.
+ */
+ private AVMNodeBean fChild;
+
+ /**
+ * Anonymous constructor.
+ */
+ public DirectoryEntry()
+ {
+ }
+
+ /**
+ * Make one from scratch.
+ * @param type The type.
+ * @param child The child node.
+ */
+ public DirectoryEntry(AVMNodeType type, AVMNodeBean child)
+ {
+ fType = type;
+ fChild = child;
+ }
+
+ /**
+ * Set the entry type.
+ * @param type The type to set.
+ */
+ public void setEntryType(AVMNodeType type)
+ {
+ fType = type;
+ }
+
+ /**
+ * Get the entry type.
+ * @return The type.
+ */
+ public AVMNodeType getEntryType()
+ {
+ return fType;
+ }
+
+ /**
+ * Set the child.
+ * @param child The child to set.
+ */
+ public void setChild(AVMNodeBean child)
+ {
+ fChild = child;
+ }
+
+ /**
+ * Get the child.
+ * @return The child.
+ */
+ public AVMNodeBean getChild()
+ {
+ return fChild;
+ }
+
+ /**
+ * Set the type by name.
+ * @param name The name of the type.
+ */
+ public void setType(String name)
+ {
+ fType = Enum.valueOf(AVMNodeType.class, name);
+ }
+
+ /**
+ * Get the type name.
+ */
+ public String getType()
+ {
+ return fType.name();
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBean.java
new file mode 100644
index 0000000000..09402cb6e4
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBean.java
@@ -0,0 +1,22 @@
+/*
+ * 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.hibernate;
+
+
+public interface DirectoryNodeBean extends AVMNodeBean
+{
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBeanImpl.java
new file mode 100644
index 0000000000..129e971c8e
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/DirectoryNodeBeanImpl.java
@@ -0,0 +1,53 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * Base for all for all directory data types.
+ * @author britt
+ */
+public class DirectoryNodeBeanImpl extends AVMNodeBeanImpl implements DirectoryNodeBean
+{
+ /**
+ * Anonymous constructor.
+ */
+ public DirectoryNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The id to assign it.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ */
+ public DirectoryNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/FileNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/FileNodeBean.java
new file mode 100644
index 0000000000..076203a7c2
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/FileNodeBean.java
@@ -0,0 +1,27 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * Doesn't do much.
+ * @author britt
+ */
+public interface FileNodeBean extends AVMNodeBean
+{
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/FileNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/FileNodeBeanImpl.java
new file mode 100644
index 0000000000..cf32eb2457
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/FileNodeBeanImpl.java
@@ -0,0 +1,54 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * Doesn't do much.
+ * @author britt
+ */
+public class FileNodeBeanImpl extends AVMNodeBeanImpl implements FileNodeBean
+{
+ /**
+ * Anonymous constructor.
+ */
+ public FileNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The ID to set.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ */
+ public FileNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/HibernateHelper.java b/source/java/org/alfresco/repo/avm/hibernate/HibernateHelper.java
new file mode 100644
index 0000000000..654b544e6b
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/HibernateHelper.java
@@ -0,0 +1,55 @@
+/*
+ * 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.hibernate;
+
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+
+/**
+ * @author britt
+ */
+public class HibernateHelper
+{
+ private static Configuration fgCfg = null;
+ private static SessionFactory fgFactory = null;
+
+ static
+ {
+ try
+ {
+ fgCfg = new Configuration();
+ fgCfg.configure();
+ fgFactory = fgCfg.buildSessionFactory();
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace(System.err);
+ System.exit(1);
+ }
+ }
+
+ public static SessionFactory GetSessionFactory()
+ {
+ return fgFactory;
+ }
+
+ public static Configuration GetConfiguration()
+ {
+ return fgCfg;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/HibernateTxn.java b/source/java/org/alfresco/repo/avm/hibernate/HibernateTxn.java
new file mode 100644
index 0000000000..a52507e3c1
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/HibernateTxn.java
@@ -0,0 +1,93 @@
+package org.alfresco.repo.avm.hibernate;
+
+/*
+ * 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.
+ */
+
+import org.hibernate.HibernateException;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+
+/**
+ * Helper for DAOs.
+ * @author britt
+ */
+public class HibernateTxn
+{
+ /**
+ * The SessionFactory.
+ */
+ private SessionFactory fSessionFactory;
+
+ /**
+ * Make one up.
+ * @param sessionFactory The SessionFactory.
+ */
+ public HibernateTxn(SessionFactory sessionFactory)
+ {
+ fSessionFactory = sessionFactory;
+ }
+
+ /**
+ * Perform a set of operations under a single Hibernate transaction.
+ * @param callback The worker.
+ * @return Whether the operation finished with a commit.
+ */
+ public boolean perform(HibernateTxnCallback callback)
+ {
+ Session sess = null;
+ Transaction txn = null;
+ try
+ {
+ sess = fSessionFactory.openSession();
+ txn = sess.beginTransaction();
+ callback.perform(sess);
+ txn.commit();
+ return true;
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace(System.err);
+ if (txn != null)
+ {
+ try
+ {
+ txn.rollback();
+ }
+ catch (HibernateException he)
+ {
+ // Do nothing.
+ }
+ }
+ return false;
+ }
+ finally
+ {
+ if (sess != null)
+ {
+ try
+ {
+ sess.close();
+ }
+ catch (HibernateException he)
+ {
+ // Do nothing.
+ }
+ }
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/HibernateTxnCallback.java b/source/java/org/alfresco/repo/avm/hibernate/HibernateTxnCallback.java
new file mode 100644
index 0000000000..8c6c978188
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/HibernateTxnCallback.java
@@ -0,0 +1,33 @@
+/*
+ * 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.hibernate;
+
+import org.hibernate.Session;
+
+/**
+ * Worker object for Hibernate Transactions.
+ * @author britt
+ */
+public interface HibernateTxnCallback
+{
+ /**
+ * Do our work.
+ * @param sess The Hibernate session.
+ */
+ public void perform(Session sess);
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/Issuer.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/Issuer.hbm.xml
new file mode 100644
index 0000000000..4d7728a978
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/Issuer.hbm.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/avm/hibernate/Issuer.java b/source/java/org/alfresco/repo/avm/hibernate/Issuer.java
new file mode 100644
index 0000000000..206ffdbcfe
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/Issuer.java
@@ -0,0 +1,122 @@
+/*
+ * 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.hibernate;
+
+/**
+ * This is a helper class that knows how to issue identifiers.
+ * @author britt
+ */
+public class Issuer
+{
+ /**
+ * The name of this issuer. Used as the primary key in it's
+ * mapping.
+ */
+ private String fName;
+
+ /**
+ * The next number to issue.
+ */
+ private long fNext;
+
+ /**
+ * The version (for concurrency control).
+ */
+ private long fVers;
+
+ /**
+ * Anonymous constructor.
+ */
+ public Issuer()
+ {
+ }
+
+ /**
+ * Rich constructor.
+ * @param name The name of this issuer.
+ * @param next The next number to issue.
+ */
+ public Issuer(String name, long next)
+ {
+ fName = name;
+ fNext = next;
+ }
+
+ // Bean methods.
+
+ /**
+ * Set the name of this issuer.
+ * @param name The name to set.
+ */
+ public void setName(String name)
+ {
+ fName = name;
+ }
+
+ /**
+ * Get the name of this issuer.
+ * @return The name of this issuer.
+ */
+ public String getName()
+ {
+ return fName;
+ }
+
+ /**
+ * Set the next number.
+ * @param next The next number.
+ */
+ public void setNext(long next)
+ {
+ fNext = next;
+ }
+
+ /**
+ * Get the next number.
+ * @return The next number.
+ */
+ public long getNext()
+ {
+ return fNext;
+ }
+
+ /**
+ * Issue the next number.
+ * @return A serial number.
+ */
+ public long issue()
+ {
+ return fNext++;
+ }
+
+ /**
+ * @return the vers
+ */
+ public long getVers()
+ {
+ return fVers;
+ }
+
+ /**
+ * @param vers the vers to set
+ */
+ public void setVers(long vers)
+ {
+ fVers = vers;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBean.java
new file mode 100644
index 0000000000..1a1c1f5512
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBean.java
@@ -0,0 +1,68 @@
+package org.alfresco.repo.avm.hibernate;
+
+import java.util.Map;
+import java.util.Set;
+
+
+public interface LayeredDirectoryNodeBean extends DirectoryNodeBean
+{
+ /**
+ * Set the layer id.
+ * @param id The id to set.
+ */
+ public void setLayerID(long id);
+
+ /**
+ * Get the layer id.
+ * @return The layer id.
+ */
+ public long getLayerID();
+
+ /**
+ * Set the indirection.
+ * @param indirection The indirection to set.
+ */
+ public void setIndirection(String indirection);
+
+ /**
+ * Get the indirection.
+ * @return The indirection.
+ */
+ public String getIndirection();
+
+ /**
+ * Set the added map.
+ * @param added The added children.
+ */
+ public void setAdded(Map added);
+
+ /**
+ * Get the added map.
+ * @return The map of added children.
+ */
+ public Map getAdded();
+
+ /**
+ * Set the Set of deleted names.
+ * @param deleted The deleted names.
+ */
+ public void setDeleted(Set deleted);
+
+ /**
+ * Get the Set of deleted names.
+ * @return The Set of deleted names.
+ */
+ public Set getDeleted();
+
+ /**
+ * Set the primary indirection-ness of this.
+ * @param primary Whether this is a primary indirection node.
+ */
+ public void setPrimaryIndirection(boolean primary);
+
+ /**
+ * Get the primary indirection-ness of this.
+ * @return Whether this is a primary indirection node.
+ */
+ public boolean getPrimaryIndirection();
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBeanImpl.java
new file mode 100644
index 0000000000..2f20297b60
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/LayeredDirectoryNodeBeanImpl.java
@@ -0,0 +1,173 @@
+/*
+ * 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.hibernate;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Layered directories are semitransparent links to other directories.
+ * They maintain a delta of what has been changed relative to what they
+ * link to.
+ * @author britt
+ */
+public class LayeredDirectoryNodeBeanImpl extends DirectoryNodeBeanImpl implements LayeredDirectoryNodeBean
+{
+ /**
+ * The Layer ID.
+ */
+ private long fLayerID;
+
+ /**
+ * The link to the underlying directory.
+ */
+ private String fIndirection;
+
+ /**
+ * The Map of nodes added in this layer.
+ */
+ private Map fAdded;
+
+ /**
+ * The Set of names that have been deleted.
+ */
+ private Set fDeleted;
+
+ /**
+ * Whether this is a primary indirection node.
+ */
+ private boolean fPrimaryIndirection;
+
+ /**
+ * Anonymous constructor.
+ */
+ public LayeredDirectoryNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The id to assign.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent node.
+ * @param layerID The layer id of this node.
+ * @param indirection The indirection pointer of this.
+ */
+ public LayeredDirectoryNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository,
+ long layerID,
+ String indirection)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ fLayerID = layerID;
+ fIndirection = indirection;
+ fAdded = new HashMap();
+ fDeleted = new HashSet();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#setLayerID(int)
+ */
+ public void setLayerID(long id)
+ {
+ fLayerID = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#getLayerID()
+ */
+ public long getLayerID()
+ {
+ return fLayerID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#setIndirection(java.lang.String)
+ */
+ public void setIndirection(String indirection)
+ {
+ fIndirection = indirection;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#getIndirection()
+ */
+ public String getIndirection()
+ {
+ return fIndirection;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#setAdded(java.util.Map)
+ */
+ public void setAdded(Map added)
+ {
+ fAdded = added;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#getAdded()
+ */
+ public Map getAdded()
+ {
+ return fAdded;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#setDeleted(java.util.Set)
+ */
+ public void setDeleted(Set deleted)
+ {
+ fDeleted = deleted;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.LayeredDirectoryNode#getDeleted()
+ */
+ public Set getDeleted()
+ {
+ return fDeleted;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBean#getPrimaryIndirection()
+ */
+ public boolean getPrimaryIndirection()
+ {
+ return fPrimaryIndirection;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.LayeredDirectoryNodeBean#setPrimaryIndirection(boolean)
+ */
+ public void setPrimaryIndirection(boolean primary)
+ {
+ fPrimaryIndirection = primary;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBean.java
new file mode 100644
index 0000000000..f6789016b5
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBean.java
@@ -0,0 +1,37 @@
+/*
+ * 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.hibernate;
+
+/**
+ * Very much like a copy on write symlink.
+ * @author britt
+ */
+public interface LayeredFileNodeBean extends FileNodeBean
+{
+ /**
+ * Set the indirection for this node.
+ * @param indirection The indirection to set.
+ */
+ public void setIndirection(String indirection);
+
+ /**
+ * Get the indirection for this node.
+ * @return The indirection.
+ */
+ public String getIndirection();
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBeanImpl.java
new file mode 100644
index 0000000000..a033e69eb9
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/LayeredFileNodeBeanImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * @author britt
+ */
+public class LayeredFileNodeBeanImpl extends FileNodeBeanImpl implements
+ LayeredFileNodeBean
+{
+ /**
+ * The indirection.
+ */
+ private String fIndirection;
+
+ /**
+ * Anonymous constructor.
+ */
+ public LayeredFileNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The ID to set.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ * @param indirection The indirection pointer.
+ */
+ public LayeredFileNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository,
+ String indirection)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ fIndirection = indirection;
+ }
+
+ /**
+ * @see org.alfresco.repo.avm.hibernate.LayeredFileNodeBean#setIndirection(java.lang.String)
+ */
+ public void setIndirection(String indirection)
+ {
+ fIndirection = indirection;
+ }
+
+ /**
+ * @see org.alfresco.repo.avm.hibernate.LayeredFileNodeBean#getIndirection()
+ */
+ public String getIndirection()
+ {
+ return fIndirection;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBean.java
new file mode 100644
index 0000000000..2369a7d7f6
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBean.java
@@ -0,0 +1,47 @@
+/*
+ * 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.hibernate;
+
+import java.util.Map;
+
+
+public interface PlainDirectoryNodeBean extends DirectoryNodeBean
+{
+ /**
+ * Set the child map.
+ * @param children The Map to set.
+ */
+ public void setChildren(Map children);
+
+ /**
+ * Get the child map.
+ * @return The map of child names to IDs.
+ */
+ public Map getChildren();
+
+ /**
+ * Set whether this node is a root directory.
+ * @param isRoot
+ */
+ public void setIsRoot(boolean isRoot);
+
+ /**
+ * Get whether this node is a root directory.
+ * @return Whether it is.
+ */
+ public boolean getIsRoot();
+}
\ No newline at end of file
diff --git a/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBeanImpl.java
new file mode 100644
index 0000000000..aa302146be
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/PlainDirectoryNodeBeanImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.hibernate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * A plain directory node is just a map of names to AVMNodes.
+ * @author britt
+ */
+public class PlainDirectoryNodeBeanImpl extends DirectoryNodeBeanImpl implements PlainDirectoryNodeBean
+{
+ /**
+ * The child map.
+ */
+ private Map fChildren;
+
+ /**
+ * Whether this is a root node.
+ */
+ private boolean fIsRoot;
+
+ /**
+ * Anonymous constructor.
+ */
+ public PlainDirectoryNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The id to assign it.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ * @param isRoot Whether this is a root node.
+ */
+ public PlainDirectoryNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository,
+ boolean isRoot)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ fChildren = new HashMap();
+ fIsRoot = isRoot;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.PlainDirectoryNode#setChildren(java.util.Map)
+ */
+ public void setChildren(Map children)
+ {
+ fChildren = children;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.PlainDirectoryNode#getChildren()
+ */
+ public Map getChildren()
+ {
+ return fChildren;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean#getIsRoot()
+ */
+ public boolean getIsRoot()
+ {
+ return fIsRoot;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean#setIsRoot(boolean)
+ */
+ public void setIsRoot(boolean isRoot)
+ {
+ fIsRoot = isRoot;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBean.java b/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBean.java
new file mode 100644
index 0000000000..05e13ec90e
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBean.java
@@ -0,0 +1,37 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * A Plain File Node. Contains a possibly shared Content object.
+ * @author britt
+ */
+public interface PlainFileNodeBean extends FileNodeBean
+{
+ /**
+ * Set the Content object for this.
+ */
+ public void setContent(ContentBean content);
+
+ /**
+ * Get the Content object for this.
+ * @return The Content object.
+ */
+ public ContentBean getContent();
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBeanImpl.java
new file mode 100644
index 0000000000..2837cbbffb
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/PlainFileNodeBeanImpl.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hibernate;
+
+
+/**
+ * @author britt
+ *
+ */
+public class PlainFileNodeBeanImpl extends FileNodeBeanImpl implements PlainFileNodeBean
+{
+ /**
+ * The Content object.
+ */
+ private ContentBean fContent;
+
+ /**
+ * Anonymous constructor.
+ */
+ public PlainFileNodeBeanImpl()
+ {
+ super();
+ }
+
+ /**
+ * Rich constructor.
+ * @param id The ID to set.
+ * @param versionID The version id.
+ * @param branchID The branch id.
+ * @param ancestor The ancestor.
+ * @param mergedFrom The node that merged into us.
+ * @param parent The parent.
+ * @param content The content object.
+ */
+ public PlainFileNodeBeanImpl(long id,
+ long versionID,
+ long branchID,
+ AVMNodeBean ancestor,
+ AVMNodeBean mergedFrom,
+ DirectoryNodeBean parent,
+ RepositoryBean repository,
+ ContentBean content)
+ {
+ super(id, versionID, branchID, ancestor, mergedFrom, parent, repository);
+ fContent = content;
+ }
+
+ /**
+ * @see org.alfresco.repo.avm.hibernate.PlainFileNodeBean#setContent(org.alfresco.repo.avm.hibernate.ContentBean)
+ */
+ public void setContent(ContentBean content)
+ {
+ fContent = content;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.PlainFileNode#getContent()
+ */
+ public ContentBean getContent()
+ {
+ return fContent;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/Repository.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/Repository.hbm.xml
new file mode 100644
index 0000000000..f7477d2fda
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/Repository.hbm.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source/java/org/alfresco/repo/avm/hibernate/RepositoryBean.java b/source/java/org/alfresco/repo/avm/hibernate/RepositoryBean.java
new file mode 100644
index 0000000000..e6dd0445ad
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/RepositoryBean.java
@@ -0,0 +1,101 @@
+/*
+ * 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.hibernate;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This is responsible for keeping track of the root
+ * directories for different versions.
+ * @author britt
+ */
+public interface RepositoryBean
+{
+ /**
+ * Set the name of this Repository.
+ * @param name The name of the respository.
+ */
+ public void setName(String name);
+
+ /**
+ * Get the name of this Repository.
+ * @return The name.
+ */
+ public String getName();
+
+ /**
+ * Set the current root.
+ * @param root The root to set.
+ */
+ public void setRoot(DirectoryNodeBean root);
+
+ /**
+ * Get the current root.
+ * @return The current root.
+ */
+ public DirectoryNodeBean getRoot();
+
+ /**
+ * Set the roots map.
+ * @param roots The Map of version ids to roots.
+ */
+ public void setRoots(Map roots);
+
+ /**
+ * Get the roots map.
+ * @return The roots map.
+ */
+ public Map getRoots();
+
+ /**
+ * Set the next version id.
+ * @param nextVersionID The value to set.
+ */
+ public void setNextVersionID(long nextVersionID);
+
+ /**
+ * Get the next version id.
+ * @return The next version id.
+ */
+ public long getNextVersionID();
+
+ /**
+ * Set the new nodes.
+ * @param newNodes The new nodes Set to set.
+ */
+ public void setNewNodes(Set newNodes);
+
+ /**
+ * Get the new nodes.
+ * @return The new nodes associated with this Repository.
+ */
+ public Set getNewNodes();
+
+ /**
+ * Set the version (for concurrency control).
+ * @param vers The version to set.
+ */
+ public void setVers(long vers);
+
+ /**
+ * Get the version (for concurrency control).
+ * @return The version.
+ */
+ public long getVers();
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/RepositoryBeanImpl.java b/source/java/org/alfresco/repo/avm/hibernate/RepositoryBeanImpl.java
new file mode 100644
index 0000000000..df19d37549
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/RepositoryBeanImpl.java
@@ -0,0 +1,204 @@
+/*
+ * 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.hibernate;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author britt
+ *
+ */
+public class RepositoryBeanImpl implements RepositoryBean
+{
+ /**
+ * The name of this repository.
+ */
+ private String fName;
+
+ /**
+ * The current root directory.
+ */
+ private DirectoryNodeBean fRoot;
+
+ /**
+ * The root directories for all versions.
+ */
+ private Map fRoots;
+
+ /**
+ * The next version id.
+ */
+ private long fNextVersionID;
+
+ /**
+ * The nodes that are new since the last end operation.
+ */
+ private Set fNewNodes;
+
+ /**
+ * The version (for concurrency control).
+ */
+ private long fVers;
+
+ /**
+ * Anonymous constructor.
+ */
+ public RepositoryBeanImpl()
+ {
+ }
+
+ /**
+ * Rich constructor
+ * @param name The name of the Repository.
+ * @param root The current root node.
+ */
+ public RepositoryBeanImpl(String name,
+ DirectoryNodeBean root)
+ {
+ fName = name;
+ fNextVersionID = 0;
+ fRoot = root;
+ fRoots = new HashMap();
+ fNewNodes = new HashSet();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#getName()
+ */
+ public String getName()
+ {
+ return fName;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#setName(java.lang.String)
+ */
+ public void setName(String name)
+ {
+ fName = name;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#setRoot(org.alfresco.proto.avm.DirectoryNode)
+ */
+ public void setRoot(DirectoryNodeBean root)
+ {
+ fRoot = root;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#getRoot()
+ */
+ public DirectoryNodeBean getRoot()
+ {
+ return fRoot;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#setRoots(java.util.Map)
+ */
+ public void setRoots(Map roots)
+ {
+ fRoots = roots;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#getRoots()
+ */
+ public Map getRoots()
+ {
+ return fRoots;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#setNextVersionID(int)
+ */
+ public void setNextVersionID(long nextVersionID)
+ {
+ fNextVersionID = nextVersionID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.proto.avm.Repository#getNextVersionID()
+ */
+ public long getNextVersionID()
+ {
+ return fNextVersionID;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!(obj instanceof RepositoryBean))
+ {
+ return false;
+ }
+ return fName.equals(((RepositoryBean)obj).getName());
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode()
+ {
+ return fName.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#getNewNodes()
+ */
+ public Set getNewNodes()
+ {
+ return fNewNodes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#setNewNodes(java.util.Set)
+ */
+ public void setNewNodes(Set newNodes)
+ {
+ fNewNodes = newNodes;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#getVers()
+ */
+ public long getVers()
+ {
+ return fVers;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.hibernate.RepositoryBean#setVers(java.lang.int)
+ */
+ public void setVers(long vers)
+ {
+ fVers = vers;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/hibernate/TestPopulate.java b/source/java/org/alfresco/repo/avm/hibernate/TestPopulate.java
new file mode 100644
index 0000000000..0d5a1d20fb
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/hibernate/TestPopulate.java
@@ -0,0 +1,211 @@
+/*
+ * 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.hibernate;
+
+import org.alfresco.repo.avm.AVMNodeType;
+import org.alfresco.repo.avm.hibernate.ContentBean;
+import org.alfresco.repo.avm.hibernate.ContentBeanImpl;
+import org.alfresco.repo.avm.hibernate.HibernateHelper;
+import org.alfresco.repo.avm.hibernate.HibernateTxn;
+import org.alfresco.repo.avm.hibernate.HibernateTxnCallback;
+import org.alfresco.repo.avm.hibernate.Issuer;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBeanImpl;
+import org.alfresco.repo.avm.hibernate.PlainFileNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainFileNodeBeanImpl;
+import org.alfresco.repo.avm.hibernate.RepositoryBean;
+import org.alfresco.repo.avm.hibernate.RepositoryBeanImpl;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+
+import junit.framework.TestCase;
+
+public class TestPopulate extends TestCase
+{
+ /**
+ * The SessionFactory.
+ */
+ private SessionFactory fSessionFactory;
+
+ public TestPopulate(String name)
+ {
+ super(name);
+ }
+
+ protected void setUp() throws Exception
+ {
+ fSessionFactory = HibernateHelper.GetSessionFactory();
+ Configuration cfg = HibernateHelper.GetConfiguration();
+ SchemaExport se = new SchemaExport(cfg);
+ se.drop(false, true);
+ se.create(false, true);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ }
+
+ /**
+ * Add some data to persistent store.
+ */
+ public void testPopulate()
+ {
+ try
+ {
+ HibernateTxn hTxn = new HibernateTxn(fSessionFactory);
+ boolean result = hTxn.perform(
+ new HibernateTxnCallback()
+ {
+ public void perform(Session session)
+ {
+ // Set up issuers.
+ Issuer nodeIssuer = new Issuer("node", 0);
+ Issuer contentIssuer = new Issuer("content", 0);
+ Issuer repositoryIssuer = new Issuer("repository", 0);
+ // Make the initial root directory.
+ PlainDirectoryNodeBean root =
+ new PlainDirectoryNodeBeanImpl(nodeIssuer.issue(),
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ null,
+ true);
+ // Make a new repository.
+ RepositoryBean rep =
+ new RepositoryBeanImpl("main", root);
+ root.setRepository(rep);
+ session.save(rep);
+ rep.getRoots().put(rep.getNextVersionID(), root);
+ rep.setNextVersionID(rep.getNextVersionID() + 1);
+ session.save(nodeIssuer);
+ session.save(contentIssuer);
+ session.save(repositoryIssuer);
+ root.setIsNew(false);
+ }
+ });
+ assertTrue(result);
+ System.out.println("--------------------------------------------");
+ result = hTxn.perform(
+ new HibernateTxnCallback()
+ {
+ public void perform(Session session)
+ {
+ // Now read some things back, and modify some stuff.
+ Issuer nodeIssuer = (Issuer)session.get(Issuer.class, "node");
+ Issuer contentIssuer = (Issuer)session.get(Issuer.class, "content");
+ RepositoryBean rep = (RepositoryBean)session.get(RepositoryBeanImpl.class, 0L);
+ long version = rep.getNextVersionID();
+ rep.setNextVersionID(version + 1);
+ assertTrue(rep != null);
+ PlainDirectoryNodeBean root = (PlainDirectoryNodeBean)rep.getRoot();
+ PlainDirectoryNodeBean newRoot = new PlainDirectoryNodeBeanImpl(nodeIssuer.issue(),
+ version,
+ 0L,
+ root,
+ null,
+ null,
+ rep,
+ true);
+ ContentBean content = new ContentBeanImpl(contentIssuer.issue());
+ PlainFileNodeBean file = new PlainFileNodeBeanImpl(nodeIssuer.issue(),
+ version,
+ 0L,
+ null,
+ null,
+ newRoot,
+ rep,
+ content);
+ content.setRefCount(content.getRefCount() + 1);
+ newRoot.getChildren().put("foo", new DirectoryEntry(AVMNodeType.PLAIN_FILE, file));
+ session.save(content);
+ session.save(newRoot);
+ content = new ContentBeanImpl(contentIssuer.issue());
+ content.setRefCount(content.getRefCount() + 1);
+ file.setIsNew(false);
+ file = new PlainFileNodeBeanImpl(nodeIssuer.issue(),
+ version,
+ 0L,
+ null,
+ null,
+ newRoot,
+ rep,
+ content);
+ session.save(content);
+ file.setIsNew(false);
+ newRoot.getChildren().put("bar", new DirectoryEntry(AVMNodeType.PLAIN_FILE, file));
+ rep.setRoot(newRoot);
+ rep.getRoots().put(version, newRoot);
+ newRoot.setIsNew(false);
+ }
+ });
+ assertTrue(result);
+ System.out.println("-----------------------------------------------");
+ result = hTxn.perform(
+ new HibernateTxnCallback()
+ {
+ public void perform(Session session)
+ {
+ Query query = session.createQuery("from RepositoryBeanImpl r where r.name = :name");
+ query.setString("name", "main");
+ RepositoryBean rep = (RepositoryBean)query.uniqueResult();
+ PlainDirectoryNodeBean root = (PlainDirectoryNodeBean)rep.getRoot();
+ assertEquals(2, root.getChildren().size());
+ for (String name : root.getChildren().keySet())
+ {
+ System.out.println(name);
+ }
+ for (DirectoryEntry entry : root.getChildren().values())
+ {
+ assertEquals(AVMNodeType.PLAIN_FILE, entry.getEntryType());
+ }
+ }
+ });
+ assertTrue(result);
+ System.out.println("----------------------------------------------");
+ // Just check cascading deletes for the children of a directory.
+ result = hTxn.perform(
+ new HibernateTxnCallback()
+ {
+ public void perform(Session session)
+ {
+ RepositoryBean rep = (RepositoryBean)session.get(RepositoryBeanImpl.class, 0L);
+ PlainDirectoryNodeBean root = (PlainDirectoryNodeBean)rep.getRoot();
+ PlainDirectoryNodeBean prev = (PlainDirectoryNodeBean)root.getAncestor();
+ rep.setRoot(prev);
+ rep.getRoots().remove(1);
+ for (String name : root.getChildren().keySet())
+ {
+ AVMNodeBean child = root.getChildren().get(name).getChild();
+ child.setParent(null);
+ }
+ session.delete(root);
+ }
+ });
+ assertTrue(result);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace(System.err);
+ fail();
+ }
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/impl/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/impl/AVMServiceImpl.java
new file mode 100644
index 0000000000..eae37355ea
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/impl/AVMServiceImpl.java
@@ -0,0 +1,421 @@
+/*
+ * 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.impl;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.repo.avm.AVMNode;
+import org.alfresco.repo.avm.AVMService;
+import org.alfresco.repo.avm.FolderEntry;
+import org.alfresco.repo.avm.Lookup;
+import org.alfresco.repo.avm.SuperRepository;
+import org.alfresco.repo.avm.hibernate.HibernateHelper;
+import org.alfresco.repo.avm.hibernate.HibernateTxn;
+import org.alfresco.repo.avm.hibernate.HibernateTxnCallback;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+
+/**
+ * Implements the AVMService. Stub.
+ * @author britt
+ */
+public class AVMServiceImpl implements AVMService
+{
+ /**
+ * The Hibernate SessionFactory.
+ */
+ private SessionFactory fSessionFactory;
+
+ /**
+ * The HibernateTxn.
+ */
+ private HibernateTxn fTransaction;
+
+ /**
+ * The SuperRepository for each service thread.
+ */
+ private ThreadLocal fSuperRepository;
+
+ /**
+ * Basic constructor for the service.
+ */
+ public AVMServiceImpl()
+ {
+ fSessionFactory = HibernateHelper.GetSessionFactory();
+ fTransaction = new HibernateTxn(fSessionFactory);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getFileInputStream(int, java.lang.String)
+ */
+ public InputStream getFileInputStream(final int version, final String path)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public InputStream in = null;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ in = fSuperRepository.get().getInputStream(version, path);
+ }
+ };
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.in;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getFileOutputStream(java.lang.String)
+ */
+ public OutputStream getFileOutputStream(final String path)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public OutputStream out = null;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ out = fSuperRepository.get().getOutputStream(path);
+ }
+ };
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.out;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getFolderListing(int, java.lang.String)
+ */
+ public List getDirectoryListing(final int version, final String path)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public List listing;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ listing = fSuperRepository.get().getListing(version, path);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.listing;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createFile(java.lang.String, java.lang.String)
+ */
+ public void createFile(final String path, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createFile(path, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createFolder(java.lang.String, java.lang.String)
+ */
+ public void createDirectory(final String path, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createDirectory(path, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createLayeredFile(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredFile(final String srcPath, final String parent, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createLayeredFile(srcPath, parent, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createLayeredFolder(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredDirectory(final String srcPath, final String parent, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createLayeredDirectory(srcPath, parent, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createRepository(java.lang.String)
+ */
+ public void createRepository(final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createRepository(name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createBranch(int, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createBranch(final int version, final String srcPath, final String dstPath,
+ final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createBranch(version, srcPath, dstPath, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#removeNode(java.lang.String, java.lang.String)
+ */
+ public void removeNode(final String parent, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().remove(parent, name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#rename(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void rename(final String srcParent, final String srcName, final String dstParent,
+ final String dstName)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().rename(srcParent, srcName, dstParent, dstName);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#slide(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void slide(final String srcParent, final String srcName, final String dstParent,
+ final String dstName)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().slide(srcParent, srcName, dstParent, dstName);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getLatestVersionID(java.lang.String)
+ */
+ public long getLatestVersionID(final String repName)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public long latestVersionID;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ latestVersionID = fSuperRepository.get().getLatestVersionID(repName);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.latestVersionID;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#createSnapshot(java.util.List)
+ */
+ public void createSnapshot(final List repositories)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().createSnapshot(repositories);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#lookup(int, java.lang.String)
+ */
+ public AVMNode lookup(final int version, final String path)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public Lookup lookup;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ lookup = fSuperRepository.get().lookup(version, path);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.lookup.getCurrentNode();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#destroyRepository(java.lang.String)
+ */
+ public void destroyRepository(final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().destroyRepository(name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#purgeVersion(int, java.lang.String)
+ */
+ public void purgeVersion(final int version, final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ fSuperRepository.get().purgeVersion(name, version);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getIndirectionPath(java.lang.String)
+ */
+ public String getIndirectionPath(final int version, final String path)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public String indirectionPath;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ indirectionPath = fSuperRepository.get().getIndirectionPath(version, path);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.indirectionPath;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#getRepositoryVersions(java.lang.String)
+ */
+ public Set getRepositoryVersions(final String name)
+ {
+ class HTxnCallback implements HibernateTxnCallback
+ {
+ public Set versions;
+
+ public void perform(Session session)
+ {
+ fSuperRepository.set(new SuperRepositoryImpl(session));
+ versions = fSuperRepository.get().getRepositoryVersions(name);
+ }
+ }
+ HTxnCallback doit = new HTxnCallback();
+ fTransaction.perform(doit);
+ return doit.versions;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.AVMService#retargetLayeredFolder(java.lang.String, java.lang.String)
+ */
+ public void retargetLayeredFolder(String path, String target)
+ {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/impl/RepositoryImpl.java b/source/java/org/alfresco/repo/avm/impl/RepositoryImpl.java
new file mode 100644
index 0000000000..bab700cc66
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/impl/RepositoryImpl.java
@@ -0,0 +1,291 @@
+/*
+ * 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.impl;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.avm.AVMNode;
+import org.alfresco.repo.avm.DirectoryNode;
+import org.alfresco.repo.avm.FolderEntry;
+import org.alfresco.repo.avm.LayeredDirectoryNode;
+import org.alfresco.repo.avm.Lookup;
+import org.alfresco.repo.avm.PlainDirectoryNode;
+import org.alfresco.repo.avm.Repository;
+import org.alfresco.repo.avm.SuperRepository;
+import org.alfresco.repo.avm.hibernate.AVMNodeBean;
+import org.alfresco.repo.avm.hibernate.DirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBean;
+import org.alfresco.repo.avm.hibernate.PlainDirectoryNodeBeanImpl;
+import org.alfresco.repo.avm.hibernate.RepositoryBean;
+import org.alfresco.repo.avm.hibernate.RepositoryBeanImpl;
+
+/**
+ * @author britt
+ *
+ */
+public class RepositoryImpl implements Repository
+{
+ /**
+ * The data bean.
+ */
+ private RepositoryBean fData;
+
+ /**
+ * The super repository.
+ */
+ private SuperRepository fSuper;
+
+ /**
+ * Make a brand new repository.
+ * @param superRepo The SuperRepository.
+ * @param name The name of the Repository.
+ */
+ public RepositoryImpl(SuperRepository superRepo, String name)
+ {
+ fSuper = superRepo;
+ fData = new RepositoryBeanImpl(name, null);
+ fSuper.getSession().save(fData);
+ PlainDirectoryNodeBean rootBean =
+ new PlainDirectoryNodeBeanImpl(fSuper.issueID(),
+ fData.getNextVersionID(),
+ 0L,
+ null,
+ null,
+ null,
+ fData,
+ true // is root
+ );
+ fSuper.getSession().save(rootBean);
+ fData.setRoot(rootBean);
+ fData.getRoots().put(fData.getNextVersionID(), rootBean);
+ fData.setNextVersionID(fData.getNextVersionID() + 1);
+ }
+
+ /**
+ * Make one from a data bean.
+ * @param data The data.
+ */
+ public RepositoryImpl(SuperRepository superRepo, RepositoryBean data)
+ {
+ fData = data;
+ fSuper = superRepo;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#setNew(org.alfresco.repo.avm.AVMNode)
+ */
+ public void setNew(AVMNode node)
+ {
+ fData.getNewNodes().add(node.getDataBean());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getLatestVersion()
+ */
+ public long getLatestVersion()
+ {
+ return fData.getNextVersionID();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#setNewRoot(org.alfresco.repo.avm.DirectoryNode)
+ */
+ public void setNewRoot(DirectoryNode root)
+ {
+ fData.setRoot((DirectoryNodeBean)root.getDataBean());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#createSnapshot()
+ */
+ public void createSnapshot()
+ {
+ // Walk through the new nodes and mark them not new.
+ for (AVMNodeBean newBean : fData.getNewNodes())
+ {
+ newBean.setIsNew(false);
+ }
+ // Clear out the new nodes.
+ fData.getNewNodes().clear();
+ // Add the current root to the root history.
+ fData.getRoots().put(fData.getNextVersionID(), fData.getRoot());
+ // Increment the version id.
+ fData.setNextVersionID(fData.getNextVersionID() + 1);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#createDirectory(java.lang.String, java.lang.String)
+ */
+ public void createDirectory(String path, String name)
+ {
+ Lookup lPath = lookupDirectory(-1, path);
+ DirectoryNode dir = (DirectoryNode)lPath.getCurrentNode();
+ if (dir.lookupChild(lPath, name, -1) != null)
+ {
+ throw new AlfrescoRuntimeException("Child exists: " + name);
+ }
+ DirectoryNode newDir = null;
+ if (lPath.isLayered()) // Creating a directory in a layered context creates
+ // a LayeredDirectoryNode that gets its indirection from
+ // its parent.
+ {
+ newDir = new LayeredDirectoryNode((String)null, this);
+ ((LayeredDirectoryNode)newDir).setPrimaryIndirection(false);
+ }
+ else
+ {
+ newDir = new PlainDirectoryNode(this);
+ }
+ // TODO Untangle when you are going to set a new version id.
+ newDir.setVersion(fData.getNextVersionID());
+ this.setNew(newDir);
+ dir.addChild(name, newDir, lPath);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#createLayeredDirectory(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredDirectory(String srcPath, String dstPath,
+ String name)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#createFile(java.lang.String, java.lang.String)
+ */
+ public void createFile(String path, String name)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#createLayeredFile(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredFile(String srcPath, String dstPath, String name)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getInputStream(int, java.lang.String)
+ */
+ public InputStream getInputStream(int version, String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getListing(int, java.lang.String)
+ */
+ public List getListing(int version, String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getOutputStream(java.lang.String)
+ */
+ public OutputStream getOutputStream(String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#removeNode(java.lang.String, java.lang.String)
+ */
+ public void removeNode(String path, String name)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#slide(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void slide(String srcPath, String srcName, String dstPath,
+ String dstName)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getVersions()
+ */
+ public Set getVersions()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getDataBean()
+ */
+ public RepositoryBean getDataBean()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getSuperRepository()
+ */
+ public SuperRepository getSuperRepository()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#lookup(int, java.lang.String)
+ */
+ public Lookup lookup(int version, String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#lookupDirectory(int, java.lang.String)
+ */
+ public Lookup lookupDirectory(int version, String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.Repository#getIndirectionPath(int, java.lang.String)
+ */
+ public String getIndirectionPath(int version, String path)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/source/java/org/alfresco/repo/avm/impl/SuperRepositoryImpl.java b/source/java/org/alfresco/repo/avm/impl/SuperRepositoryImpl.java
new file mode 100644
index 0000000000..b9b502ec28
--- /dev/null
+++ b/source/java/org/alfresco/repo/avm/impl/SuperRepositoryImpl.java
@@ -0,0 +1,501 @@
+/*
+ * 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.impl;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Set;
+
+import org.alfresco.error.AlfrescoRuntimeException;
+import org.alfresco.repo.avm.AVMNode;
+import org.alfresco.repo.avm.DirectoryNode;
+import org.alfresco.repo.avm.FileNode;
+import org.alfresco.repo.avm.FolderEntry;
+import org.alfresco.repo.avm.LayeredDirectoryNode;
+import org.alfresco.repo.avm.LayeredFileNode;
+import org.alfresco.repo.avm.Lookup;
+import org.alfresco.repo.avm.PlainDirectoryNode;
+import org.alfresco.repo.avm.PlainFileNode;
+import org.alfresco.repo.avm.Repository;
+import org.alfresco.repo.avm.SuperRepository;
+import org.alfresco.repo.avm.hibernate.Issuer;
+import org.alfresco.repo.avm.hibernate.RepositoryBean;
+import org.hibernate.Query;
+import org.hibernate.Session;
+
+/**
+ * Implementation of a SuperRepository. This is a per thread
+ * class.
+ * @author britt
+ */
+public class SuperRepositoryImpl implements SuperRepository
+{
+ /**
+ * The Hibernate Session associated with the current operation.
+ */
+ private Session fSession;
+
+ /**
+ * The node id issuer.
+ */
+ private Issuer fNodeIssuer;
+
+ /**
+ * The content id issuer;
+ */
+ private Issuer fContentIssuer;
+
+ /**
+ * The branch id issuer.
+ */
+ private Issuer fBranchIssuer;
+
+ /**
+ * The layer id issuer.
+ */
+ private Issuer fLayerIssuer;
+
+ /**
+ * Make a new one, initialized with the session.
+ * @param session The session for this operation.
+ */
+ public SuperRepositoryImpl(Session session)
+ {
+ fSession = session;
+ fNodeIssuer = (Issuer)fSession.get(Issuer.class, "node");
+ fContentIssuer = (Issuer)fSession.get(Issuer.class, "content");
+ fBranchIssuer = (Issuer)fSession.get(Issuer.class, "branch");
+ fLayerIssuer = (Issuer)fSession.get(Issuer.class, "layer");
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createFile(java.lang.String, java.lang.String)
+ */
+ public void createFile(String path, String name)
+ {
+ String[] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ rep.createFile(pathParts[1], name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createDirectory(java.lang.String, java.lang.String)
+ */
+ public void createDirectory(String path, String name)
+ {
+ String[] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ rep.createDirectory(pathParts[1], name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createLayeredDirectory(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredDirectory(String srcPath, String dstPath,
+ String name)
+ {
+ String[] pathParts = SplitPath(dstPath);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ rep.createLayeredDirectory(srcPath, pathParts[1], name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createLayerdFile(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createLayeredFile(String srcPath, String dstPath, String name)
+ {
+ String[] pathParts = SplitPath(dstPath);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ rep.createLayeredFile(srcPath, pathParts[1], name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createRepository(java.lang.String)
+ */
+ public void createRepository(String name)
+ {
+ // Newing up the object causes it to be written to the db.
+ @SuppressWarnings("unused")
+ Repository rep = new RepositoryImpl(this, name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createBranch(int, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void createBranch(int version, String srcPath, String dstPath, String name)
+ {
+ // Lookup the src node.
+ String [] pathParts = SplitPath(srcPath);
+ Repository srcRepo = getRepositoryByName(pathParts[0]);
+ Lookup sPath = srcRepo.lookup(version, pathParts[1]);
+ // Lookup the destination direcctory.
+ pathParts = SplitPath(dstPath);
+ Repository dstRepo = getRepositoryByName(pathParts[0]);
+ Lookup dPath = dstRepo.lookupDirectory(-1, pathParts[1]);
+ DirectoryNode dirNode = (DirectoryNode)dPath.getCurrentNode();
+ AVMNode srcNode = sPath.getCurrentNode();
+ AVMNode dstNode = null;
+ if (srcNode instanceof PlainDirectoryNode)
+ {
+ dstNode = new PlainDirectoryNode((PlainDirectoryNode)srcNode, dstRepo);
+ }
+ else if (srcNode instanceof LayeredDirectoryNode)
+ {
+ dstNode =
+ new LayeredDirectoryNode((LayeredDirectoryNode)srcNode, dstRepo);
+ }
+ else if (srcNode instanceof LayeredFileNode)
+ {
+ dstNode = new LayeredFileNode((LayeredFileNode)srcNode, dstRepo);
+ }
+ else // This is a plain file.
+ {
+ dstNode = new PlainFileNode((PlainFileNode)srcNode, dstRepo);
+ }
+ dstNode.setVersion(dstRepo.getLatestVersion() + 1);
+ dstRepo.setNew(dstNode);
+ dstNode.setAncestor(srcNode);
+ dstNode.setBranchID(fBranchIssuer.issue());
+ dirNode.addChild(name, dstNode, dPath);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getOutputStream(java.lang.String)
+ */
+ public OutputStream getOutputStream(String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.getOutputStream(pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#rename(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void rename(String srcPath, String srcName, String dstPath,
+ String dstName)
+ {
+ String [] pathParts = SplitPath(srcPath);
+ Repository srcRepo = getRepositoryByName(pathParts[0]);
+ Lookup sPath = srcRepo.lookupDirectory(-1, pathParts[1]);
+ DirectoryNode srcDir = (DirectoryNode)sPath.getCurrentNode();
+ AVMNode srcNode = srcDir.lookupChild(sPath, srcName, -1);
+ if (srcNode == null)
+ {
+ throw new AlfrescoRuntimeException("Not found: " + srcName);
+ }
+ pathParts = SplitPath(dstPath);
+ Repository dstRepo = getRepositoryByName(pathParts[0]);
+ Lookup dPath = dstRepo.lookupDirectory(-1, dstPath);
+ DirectoryNode dstDir = (DirectoryNode)dPath.getCurrentNode();
+ AVMNode dstNode = dstDir.lookupChild(dPath, dstName, -1);
+ if (dstNode != null)
+ {
+ throw new AlfrescoRuntimeException("Node exists: " + dstName);
+ }
+ // We've passed the check, so we can go ahead and do the rename.
+ if (srcNode instanceof PlainDirectoryNode)
+ {
+ // If the source is layered then the renamed thing needs to be layered also.
+ if (sPath.isLayered())
+ {
+ // If this is a rename happening in the same layer we make a new
+ // OverlayedDirectoryNode that is not a primary indirection layer.
+ // Otherwise we do make the new OverlayedDirectoryNode a primary
+ // Indirection layer. This complexity begs the question of whether
+ // we should allow renames from within one layer to within another
+ // layer. Allowing it makes the logic absurdly complex.
+ if (dPath.isLayered() && dPath.getTopLayer() == sPath.getTopLayer())
+ {
+ dstNode = new LayeredDirectoryNode((PlainDirectoryNode)srcNode, dstRepo, sPath);
+ }
+ else
+ {
+ dstNode = new LayeredDirectoryNode((DirectoryNode)srcNode, dstRepo, sPath, srcName);
+ }
+ }
+ else
+ {
+ dstNode = new PlainDirectoryNode((PlainDirectoryNode)srcNode, dstRepo);
+ }
+ }
+ else if (srcNode instanceof LayeredDirectoryNode)
+ {
+ if (!sPath.isLayered() || (sPath.isInThisLayer() &&
+ srcDir instanceof LayeredDirectoryNode &&
+ ((LayeredDirectoryNode)srcDir).directlyContains(srcNode)))
+ {
+ // Use the simple 'copy' constructor.
+ dstNode =
+ new LayeredDirectoryNode((LayeredDirectoryNode)srcNode, dstRepo);
+ ((LayeredDirectoryNode)dstNode).setLayerID(((LayeredDirectoryNode)srcNode).getLayerID());
+ }
+ else
+ {
+ // The thing we are renaming does not belong to sPath's layer and therefore
+ // we need to compute the indirection path for this layer after the rename.
+ dstNode =
+ new LayeredDirectoryNode((DirectoryNode)srcNode, dstRepo, sPath, srcName);
+ ((LayeredDirectoryNode)dstNode).setLayerID(fLayerIssuer.issue());
+ }
+ }
+ else if (srcNode instanceof LayeredFileNode)
+ {
+ if (!sPath.isLayered() || (sPath.isInThisLayer() &&
+ srcDir instanceof LayeredDirectoryNode &&
+ ((LayeredDirectoryNode)srcDir).directlyContains(srcNode)))
+ {
+ // Use the simple 'copy' constructor.
+ dstNode =
+ new LayeredFileNode((LayeredFileNode)srcNode, dstRepo);
+ }
+ else
+ {
+ // Calculate the indirection path, because srcNode was not in this layer.
+ dstNode =
+ new LayeredFileNode((FileNode)srcNode, dstRepo, sPath, srcName);
+ }
+ }
+ else // This is a plain file node.
+ {
+ dstNode = new PlainFileNode((PlainFileNode)srcNode, dstRepo);
+ }
+ dstNode.setVersion(dstRepo.getLatestVersion() + 1);
+ dstRepo.setNew(dstNode);
+ dstDir.addChild(dstName, dstNode, dPath);
+ dstNode.setAncestor(srcNode);
+ pathParts = SplitPath(srcPath);
+ sPath = srcRepo.lookup(-1, pathParts[1]);
+ srcDir = (DirectoryNode)sPath.getCurrentNode();
+ srcDir.removeChild(srcName, sPath);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#slide(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void slide(String srcPath, String srcName, String dstPath,
+ String dstName)
+ {
+ String[] srcPathParts = SplitPath(srcPath);
+ String[] dstPathParts = SplitPath(dstPath);
+ if (!srcPathParts[0].equals(dstPathParts[0]))
+ {
+ throw new AlfrescoRuntimeException("Argument must be in same Repository: " + srcPathParts[0] + "!=" +
+ dstPathParts[0]);
+ }
+ Repository repo = getRepositoryByName(srcPathParts[0]);
+ repo.slide(srcPathParts[1], srcName, dstPathParts[1], dstName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createSnapshot(java.util.List)
+ */
+ public void createSnapshot(List repositories)
+ {
+ for (String repName : repositories)
+ {
+ Repository repo = getRepositoryByName(repName);
+ repo.createSnapshot();
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#remove(java.lang.String, java.lang.String)
+ */
+ public void remove(String path, String name)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository repo = getRepositoryByName(pathParts[0]);
+ repo.removeNode(pathParts[1], name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#purgeRepository(java.lang.String)
+ */
+ public void purgeRepository(String name)
+ {
+ // TODO Leave until later. Need to set up GC thread to handle this.
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#purgeVersion(java.lang.String, int)
+ */
+ public void purgeVersion(String name, int version)
+ {
+ // TODO Leave until later. Need to set up GC thread to handle this.
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getInputStream(java.lang.String)
+ */
+ public InputStream getInputStream(int version, String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository repo = getRepositoryByName(pathParts[0]);
+ return repo.getInputStream(version, pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getListing(java.lang.String)
+ */
+ public List getListing(int version, String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository repo = getRepositoryByName(pathParts[0]);
+ return repo.getListing(version, pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getRepositoryNames()
+ */
+ @SuppressWarnings("unchecked")
+ public List getRepositoryNames()
+ {
+ Query query = fSession.createQuery("select r.name from RepositoryBeanImpl r");
+ return (List)query.list();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getRepositoryVersions(java.lang.String)
+ */
+ public Set getRepositoryVersions(String name)
+ {
+ Repository rep = getRepositoryByName(name);
+ return rep.getVersions();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#issueID()
+ */
+ public long issueID()
+ {
+ return fNodeIssuer.issue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#issueContentID()
+ */
+ public long issueContentID()
+ {
+ return fContentIssuer.issue();
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getSession()
+ */
+ public Session getSession()
+ {
+ return fSession;
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#createContentOutputStream(int)
+ */
+ public OutputStream createContentOutputStream(String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.getOutputStream(pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getContentInputStream(int)
+ */
+ public InputStream getContentInputStream(int version, String path)
+ {
+ String[] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.getInputStream(version, pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#destroyRepository(java.lang.String)
+ */
+ public void destroyRepository(String name)
+ {
+ // TODO Auto-generated method stub
+ // Leave this until we have GC in place.
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getIndirectionPath(int, java.lang.String)
+ */
+ public String getIndirectionPath(int version, String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.getIndirectionPath(version, pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#getLatestVersionID(java.lang.String)
+ */
+ public long getLatestVersionID(String name)
+ {
+ Repository rep = getRepositoryByName(name);
+ return rep.getLatestVersion();
+ }
+
+ /**
+ * Get a repository by name.
+ * @param name The name of the repository.
+ * @return The Repository.
+ */
+ private Repository getRepositoryByName(String name)
+ {
+ Query query = fSession.createQuery("from repositories r where r.name = :name");
+ query.setString("name", name);
+ return new RepositoryImpl(this, (RepositoryBean)query.uniqueResult());
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#lookup(int, java.lang.String)
+ */
+ public Lookup lookup(int version, String path)
+ {
+ String [] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.lookup(version, pathParts[1]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.alfresco.repo.avm.SuperRepository#lookupDirectory(int, java.lang.String)
+ */
+ public Lookup lookupDirectory(int version, String path)
+ {
+ String[] pathParts = SplitPath(path);
+ Repository rep = getRepositoryByName(pathParts[0]);
+ return rep.lookupDirectory(version, pathParts[1]);
+ }
+
+ /**
+ * Utility to split a path, foo:/bar/baz into its repository and path parts.
+ * @param path The fully qualified path.
+ * @return The repository name and the repository path.
+ */
+ private String[] SplitPath(String path)
+ {
+ String [] pathParts = path.split(":");
+ if (pathParts.length != 2)
+ {
+ throw new AlfrescoRuntimeException("Invalid path: " + path);
+ }
+ return pathParts;
+ }
+}