You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by oz...@apache.org on 2004/09/20 09:56:38 UTC
cvs commit: jakarta-slide/src/stores/org/apache/slide/store/file AbstractSimpleStore.java SimpleFileStoreTest.java CountdownStore.java SimpleFileStore.java
ozeigermann 2004/09/20 00:56:38
Added: src/stores/org/apache/slide/store/file
AbstractSimpleStore.java SimpleFileStoreTest.java
CountdownStore.java SimpleFileStore.java
Log:
Added new simple file store donated by Alon Salant in
http://issues.apache.org/bugzilla/show_bug.cgi?id=31177
Revision Changes Path
1.1 jakarta-slide/src/stores/org/apache/slide/store/file/AbstractSimpleStore.java
Index: AbstractSimpleStore.java
===================================================================
/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/file/AbstractSimpleStore.java,v 1.1 2004/09/20 07:56:38 ozeigermann Exp $
* $Revision: 1.1 $
* $Date: 2004/09/20 07:56:38 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.store.file;
import java.util.*;
import javax.transaction.xa.*;
import org.apache.slide.common.*;
import org.apache.slide.store.*;
import org.apache.slide.content.*;
import org.apache.slide.structure.*;
import org.apache.slide.util.logger.*;
import org.apache.commons.logging.*;
/**
* AbstractSimpleStore provides a minimal implementation to support creating a Slide Store.
* It no-ops most methods and leaves abstract those methods you must implement to support
* basic create/retrieve/update/remove.
* <p>
* For locking and security your implementation should be paired with
* org.apache.slide.store.mem.TransientSecurityStore and
* org.apache.slide.store.mem.TransientLockStore.
*
* @see SimpleFileStore
* @author Alon Salant
*/
public abstract class AbstractSimpleStore
extends AbstractServiceBase
implements ContentStore, NodeStore, RevisionDescriptorStore, RevisionDescriptorsStore
{
private static final Log log = LogFactory.getLog(AbstractSimpleStore.class);
// ==== Service Methods ================================
public void setParameters(Hashtable parameters)
throws ServiceParameterErrorException, ServiceParameterMissingException
{
log("setParameters(" + parameters + ")");
}
public void connect() throws ServiceConnectionFailedException
{
}
public void reset() throws ServiceResetFailedException
{
}
public void disconnect() throws ServiceDisconnectionFailedException
{
}
public boolean isConnected() throws ServiceAccessException
{
return true;
}
public int getTransactionTimeout() throws XAException
{
return 0;
}
public boolean setTransactionTimeout(int seconds) throws XAException
{
return false;
}
public boolean isSameRM(XAResource rm) throws XAException
{
return false;
}
public Xid[] recover(int flag) throws XAException
{
return new Xid[0];
}
public int prepare(Xid txId) throws XAException
{
return XA_RDONLY;
}
public void forget(Xid txId) throws XAException
{
}
public void rollback(Xid txId) throws XAException
{
}
public void end(Xid txId, int flags) throws XAException
{
}
public void start(Xid txId, int flags) throws XAException
{
}
public void commit(Xid txId, boolean onePhase) throws XAException
{
}
// ==== ContentStore Methods ================================
public abstract NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionNotFoundException;
public abstract void createRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionAlreadyExistException;
public abstract void storeRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionNotFoundException;
public void removeRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException
{
log("removeRevisionContent(" + uri + ")");
}
// ==== NodeStore Methods ================================
public abstract void storeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException;
public abstract void createObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectAlreadyExistsException;
public abstract void removeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException;
public abstract ObjectNode retrieveObject(Uri uri)
throws ServiceAccessException, ObjectNotFoundException;
// ==== RevisionDescriptorsStore Methods ================================
public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri)
throws ServiceAccessException, RevisionDescriptorNotFoundException
{
log("retrieveRevisionDescriptors(" + uri + ")");
NodeRevisionNumber rev = new NodeRevisionNumber(1, 0);
Hashtable workingRevisions = new Hashtable();
workingRevisions.put("1.0", rev);
Hashtable latestRevisionNumbers = new Hashtable();
latestRevisionNumbers.put("1.0", rev);
Hashtable branches = new Hashtable();
branches.put(rev, new Vector());
return new NodeRevisionDescriptors(uri.toString(),
rev,
workingRevisions,
latestRevisionNumbers,
branches,
false);
}
public void createRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors)
throws ServiceAccessException
{
log("createRevisionDescriptors(" + uri + ")");
}
public void storeRevisionDescriptors(Uri uri, NodeRevisionDescriptors revisionDescriptors)
throws ServiceAccessException, RevisionDescriptorNotFoundException
{
log("storeRevisionDescriptors(" + uri + ")");
}
public void removeRevisionDescriptors(Uri uri) throws ServiceAccessException
{
log("removeRevisionDescriptors(" + uri + ")");
}
// ==== RevisionDescriptorStore Methods ================================
public void createRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException
{
log("createRevisionDescriptor(" + uri + ")");
}
public void storeRevisionDescriptor(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionDescriptorNotFoundException
{
log("storeRevisionDescriptor(" + uri + ")");
}
public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber)
throws ServiceAccessException
{
log("removeRevisionDescriptor(" + uri + ")");
}
public abstract NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri, NodeRevisionNumber revisionNumber)
throws ServiceAccessException, RevisionDescriptorNotFoundException;
protected void log(String msg)
{
if (getLogger() == null)
System.out.println(this.getClass().getName() + ": " + msg);
else
getLogger().log(msg, this.getClass().getName(), Logger.DEBUG);
}
}
1.1 jakarta-slide/src/stores/org/apache/slide/store/file/SimpleFileStoreTest.java
Index: SimpleFileStoreTest.java
===================================================================
/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/file/SimpleFileStoreTest.java,v 1.1 2004/09/20 07:56:38 ozeigermann Exp $
* $Revision: 1.1 $
* $Date: 2004/09/20 07:56:38 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.store.file;
import java.io.*;
import org.apache.commons.logging.*;
import org.apache.slide.common.*;
import org.apache.slide.content.*;
import org.apache.slide.structure.*;
import org.apache.slide.authenticate.*;
import junit.framework.*;
/**
* @author Alon Salant
*/
public class SimpleFileStoreTest
extends TestCase
{
private static final Log log = LogFactory.getLog(SimpleFileStoreTest.class);
Domain domain;
NamespaceAccessToken namespace;
public SimpleFileStoreTest(String s)
{
super(s);
}
public void setUp() throws Exception
{
Domain.init(new FileInputStream("WEB-INF/properties/TestDomain.xml"));
namespace = Domain.accessNamespace(null, "slide");
}
public void tearDown() throws Exception
{
}
public void testCreateFile() throws Exception
{
String path = "/test.txt";
File file = new File("files/test.txt");
try
{
SlideToken token = new SlideTokenWrapper(new SlideTokenImpl());
token.setForceSecurity(false);
token.setForceLock(false);
token.setCredentialsToken(new CredentialsToken(""));
Content content = namespace.getContentHelper();
Structure structure = namespace.getStructureHelper();
structure.create(token, new SubjectNode(), path);
assertTrue(file.exists());
assertTrue(file.isDirectory());
NodeRevisionContent newContent = new NodeRevisionContent();
newContent.setContent("delete me, please".getBytes());
content.create(token, path, new NodeRevisionDescriptor(), newContent);
NodeRevisionContent createdContent = content.retrieve(token, path, new NodeRevisionDescriptor());
assertNotNull(createdContent);
assertEquals(new String(newContent.getContent()), new String(createdContent.getContent()));
}
finally
{
if (file.exists()) file.delete();
}
}
}
1.1 jakarta-slide/src/stores/org/apache/slide/store/file/CountdownStore.java
Index: CountdownStore.java
===================================================================
/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/file/CountdownStore.java,v 1.1 2004/09/20 07:56:38 ozeigermann Exp $
* $Revision: 1.1 $
* $Date: 2004/09/20 07:56:38 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.store.file;
import java.util.*;
import javax.transaction.xa.*;
import org.apache.slide.store.*;
import org.apache.slide.store.file.*;
import org.apache.slide.content.*;
import org.apache.slide.common.*;
import org.apache.slide.structure.*;
import org.apache.slide.util.logger.*;
/**
* CountdownStore is an AbstractSimpleStore implementation that shows how
* to support the Store APIs with a little bit of code.
* <p>
* It presents nested directories 10 .. 1 and a file 0.txt in
* the directory 1. This structure is defined in code. You can get some
* funky things to happen by trying to change this structure through a
* webdav client since this implementation seems to support all
* operations but does not preserve state.
*
* @author Alon Salant
*/
public class CountdownStore
extends AbstractSimpleStore
{
// ==== ContentStore Methods ================================
public NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionNotFoundException
{
log("retrieveRevisionContent(" + uri + ")");
NodeRevisionContent nrc = new NodeRevisionContent();
nrc.setContent("blast off!!".getBytes());
return nrc;
}
public void createRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionAlreadyExistException
{
log("createRevisionContent(" + uri + ")");
}
public void storeRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionNotFoundException
{
log("storeRevisionContent(" + uri + ")");
}
public void removeRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException
{
log("removeRevisionContent(" + uri + ")");
}
// ==== NodeStore Methods ================================
public void storeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException
{
log("storeObject(" + uri + ")");
}
public void createObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectAlreadyExistsException
{
log("createObject(" + uri + ")");
}
public void removeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException
{
log("removeObject(" + uri + ")");
}
public ObjectNode retrieveObject(Uri uri)
throws ServiceAccessException, ObjectNotFoundException
{
log("retrieveObject(" + uri + ")");
SubjectNode subject = new SubjectNode(uri.toString());
if (uri.toString().endsWith("0.txt")) return subject;
if (uri.isStoreRoot())
{
subject.addChild(new SubjectNode("9"));
return subject;
}
int count = Integer.parseInt(uri.toString().substring(uri.toString().length() - 1));
if (count > 1)
{
subject.addChild(new SubjectNode(count - 1 + ""));
return subject;
}
subject.addChild(new SubjectNode("0.txt"));
return subject;
}
// ==== RevisionDescriptorStore Methods ================================
public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri,
NodeRevisionNumber revisionNumber) throws ServiceAccessException,
RevisionDescriptorNotFoundException
{
log("retrieveRevisionDescriptor(" + uri + ")");
NodeRevisionDescriptor descriptor = new NodeRevisionDescriptor(new NodeRevisionNumber(1, 0),
NodeRevisionDescriptors.MAIN_BRANCH,
new Vector(),
new Hashtable());
descriptor.setCreationDate(new Date(0));
descriptor.setLastModified(new Date(new Date().getTime() - 2000));
descriptor.setModificationDate(descriptor.getLastModifiedAsDate());
if (uri.toString().endsWith("0.txt"))
{
descriptor.setContentLength("blast off!!".getBytes().length);
}
else
{
descriptor.setResourceType("<collection/>");
}
return descriptor;
}
}
1.1 jakarta-slide/src/stores/org/apache/slide/store/file/SimpleFileStore.java
Index: SimpleFileStore.java
===================================================================
/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/file/SimpleFileStore.java,v 1.1 2004/09/20 07:56:38 ozeigermann Exp $
* $Revision: 1.1 $
* $Date: 2004/09/20 07:56:38 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.store.file;
import java.util.*;
import java.io.*;
import org.apache.slide.content.*;
import org.apache.slide.common.*;
import org.apache.slide.structure.*;
import org.apache.slide.store.file.*;
/**
* SimpleFileStore implements ContentStore, NodeStore, RevisionDescriptorStore,
* and RevisionDescriptorsStore backed by a file system. Unlike the
* org.apache.slide.store.txfile.* implementations, SimpleFileStore does not support
* transactions, locking, security or versioning. But it will work by pointing it an
* existing directory on your file system and does not need to keep track of any other
* information other than what it can find in the file system.
* <p>
* See <a href="http://www.mail-archive.com/slide-user@jakarta.apache.org/msg07390.html">this
* slide-user thread</a> for some history on this implementation.
* <p>
* SimpleFileStore needs to be deployed with implementations of LockStore and SecurityStore.
* A sample Domain.xml entry looks like:
* <p>
* <pre>
* <store name="simple">
* <nodestore classname="org.apache.slide.store.file.SimpleFileStore">
* <parameter name="rootpath">webapps/slidespace/files</parameter>
* </nodestore>
* <contentstore>
* <reference store="nodestore"/>
* </contentstore>
* <revisiondescriptorsstore>
* <reference store="nodestore"/>
* </revisiondescriptorsstore>
* <revisiondescriptorstore>
* <reference store="nodestore"/>
* </revisiondescriptorstore>
* <securitystore classname="org.apache.slide.store.mem.TransientSecurityStore"/>
* <lockstore classname="org.apache.slide.store.mem.TransientLockStore"/>
* </store>
* <scope match="/simple" store="simple"/>
* </pre>
*
* @author Alon Salant
*/
public class SimpleFileStore
extends AbstractSimpleStore
{
private static final String ROOT_PARAM = "rootpath";
private static final String COLLECTION_TYPE = "<collection/>";
private File root;
public void setParameters(Hashtable parameters)
throws ServiceParameterErrorException, ServiceParameterMissingException
{
log("setParameters(" + parameters + ")");
if (parameters.get(ROOT_PARAM) == null) throw new ServiceParameterErrorException(this, ROOT_PARAM);
File root = new File((String) parameters.get(ROOT_PARAM));
if (!root.exists()) throw new ServiceParameterErrorException(this, ROOT_PARAM + ": " + root + " does not exist");
this.root = root;
log("Initialized with file root " + root);
}
public NodeRevisionContent retrieveRevisionContent(Uri uri, NodeRevisionDescriptor revisionDescriptor)
throws ServiceAccessException, RevisionNotFoundException
{
log("retrieveRevisionContent(" + uri + ")");
File file = getFile(uri);
InputStream in = null;
try
{
in = new FileInputStream(file);
NodeRevisionContent nrc = new NodeRevisionContent();
nrc.setContent(new FileInputStream(file));
return nrc;
}
catch (FileNotFoundException e)
{
throw new RevisionNotFoundException(uri.toString(), revisionDescriptor.getRevisionNumber());
}
finally
{
try
{
if (in != null) in.close();
}
catch (IOException e)
{
throw new ServiceAccessException(this, e);
}
}
}
public void createRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionAlreadyExistException
{
log("createRevisionContent(" + uri + ")");
File file = getFile(uri);
if (file.exists()) throw new RevisionAlreadyExistException(uri.toString(), revisionDescriptor.getRevisionNumber());
try
{
write(revisionContent.streamContent(), new FileOutputStream(file));
}
catch (IOException e)
{
throw new ServiceAccessException(this, e);
}
}
public void storeRevisionContent(Uri uri,
NodeRevisionDescriptor revisionDescriptor,
NodeRevisionContent revisionContent)
throws ServiceAccessException, RevisionNotFoundException
{
log("storeRevisionContent(" + uri + ")");
File file = getFile(uri);
if (!file.exists()) throw new RevisionNotFoundException(uri.toString(), revisionDescriptor.getRevisionNumber());
if (file.isDirectory())
{
if (!file.delete()) throw new ServiceAccessException(this, "unable to remove directory " + file +
" in order to create a file with the same name");
revisionDescriptor.removeProperty(NodeRevisionDescriptor.RESOURCE_TYPE);
}
try
{
write(revisionContent.streamContent(), new FileOutputStream(file));
}
catch (IOException e)
{
throw new ServiceAccessException(this, e);
}
}
public void storeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException
{
log("storeObject(" + uri + ")");
File file = getFile(uri);
if (!file.exists()) throw new ObjectNotFoundException(uri);
}
/**
* Creates a new object as a directory. This will always create a directory, since there
* appears to be no way to know the type of the resource being created.
* <p>
* storeRevisionContent() will be called after the object is created and will
* remove the directory and create a file.
*/
public void createObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectAlreadyExistsException
{
log("createObject(" + uri + ")");
File file = getFile(uri);
if (file.exists()) throw new ObjectAlreadyExistsException(uri.toString());
if (!file.mkdir()) throw new ServiceAccessException(this, "Unable to create " + uri.toString());
}
public void removeObject(Uri uri, ObjectNode object)
throws ServiceAccessException, ObjectNotFoundException
{
log("removeObject(" + uri + ")");
File file = getFile(uri);
if (!file.exists()) throw new ObjectNotFoundException(uri);
if (file.isDirectory() && !(file.listFiles().length == 0))
throw new ServiceAccessException(this, uri.toString() + " is not empty");
if (!file.delete()) throw new ServiceAccessException(this, "Unable to delete " + uri.toString());
}
/**
* Return SubjectNode for normal use. Create SubjectNode with Uri.toString().
* For folders add children as SubjectNodes created with file/folder name.
*/
public ObjectNode retrieveObject(Uri uri)
throws ServiceAccessException, ObjectNotFoundException
{
log("retrieveObject(" + uri + ")");
File file = getFile(uri);
if (!file.exists()) throw new ObjectNotFoundException(uri);
SubjectNode subject = new SubjectNode(uri.toString());
if (file.isFile()) return subject;
File[] children = file.listFiles();
for (int i = 0; i < children.length; i++)
{
subject.addChild(new SubjectNode(children[i].getName()));
}
return subject;
}
/**
* Set resourceType to "<collection/>" for folders and set the contentLength for files.
* Also set created and modified dates.
*/
public NodeRevisionDescriptor retrieveRevisionDescriptor(Uri uri,
NodeRevisionNumber revisionNumber)
throws ServiceAccessException, RevisionDescriptorNotFoundException
{
log("retrieveRevisionDescriptor(" + uri + ")");
File file = getFile(uri);
if (!file.exists()) throw new RevisionDescriptorNotFoundException(uri.toString());
NodeRevisionDescriptor descriptor = new NodeRevisionDescriptor(new NodeRevisionNumber(1, 0),
NodeRevisionDescriptors.MAIN_BRANCH,
new Vector(),
new Hashtable());
descriptor.setCreationDate(new Date(file.lastModified()));
descriptor.setLastModified(descriptor.getCreationDateAsDate());
descriptor.setModificationDate(descriptor.getCreationDateAsDate());
if (file.isDirectory())
{
descriptor.setResourceType(COLLECTION_TYPE);
}
else
{
descriptor.setContentLength(file.length());
}
return descriptor;
}
private void write(InputStream in, OutputStream out) throws IOException
{
byte buffer[] = new byte[2048];
int len = buffer.length;
try
{
while (true)
{
len = in.read(buffer);
if (len == -1) break;
out.write(buffer, 0, len);
}
}
finally
{
try { in.close(); }
finally { out.close(); }
}
}
private File getFile(Uri uri)
{
File file = new File(root, uri.getRelative());
return file;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org