Refactored RemoteStore client (i.e. on web-tier) to use Connector framework for remote operations.

Remote AVM store now expects 'admin' auth level for all operations, and fixed to handle AuthenticationDenied exceptions.
Added example config to use remote AVM store as primary lookup location (with fall back to web-app classpath) for model XML files - NOT on by default - as still need to add the avm sitestore to bootstrap/patch.
Improvements to web-framework model object caching - use of "sentinel" pattern to cache missing values.
Model object persister ordering now maintained as per Spring config order.
ModelObjectManager now more aggressively throws out exceptions when errors occur loading model objects.
Fix to RendererFactory to be thread safe (!)
Other small fixes, clean up and productisation in web-framework.
Useful toString() methods added to various classes for debugging.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@9471 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Kevin Roast
2008-06-13 13:52:01 +00:00
parent 132c0af749
commit 54b809411d
3 changed files with 73 additions and 48 deletions

View File

@@ -2,6 +2,6 @@
<shortname>Remote AVM Store</shortname> <shortname>Remote AVM Store</shortname>
<description>Remote service mirroring the Store interface - to an AVM store</description> <description>Remote service mirroring the Store interface - to an AVM store</description>
<url>/remotestore/{method}/{path}</url> <url>/remotestore/{method}/{path}</url>
<authentication>none</authentication> <authentication>admin</authentication>
<format default="">argument</format> <format default="">argument</format>
</webscript> </webscript>

View File

@@ -2,6 +2,6 @@
<shortname>Remote AVM Store</shortname> <shortname>Remote AVM Store</shortname>
<description>Remote service mirroring the Store interface - to an AVM store</description> <description>Remote service mirroring the Store interface - to an AVM store</description>
<url>/remotestore/{method}/{path}</url> <url>/remotestore/{method}/{path}</url>
<authentication>none</authentication> <authentication>admin</authentication>
<format default="">argument</format> <format default="">argument</format>
</webscript> </webscript>

View File

@@ -31,11 +31,13 @@ import java.net.SocketException;
import org.alfresco.repo.avm.AVMNodeConverter; import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.content.MimetypeMap; import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.permissions.AccessDeniedException;
import org.alfresco.service.cmr.avm.AVMNodeDescriptor; import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
import org.alfresco.service.cmr.avm.AVMService; import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException; import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptResponse; import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse; import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
@@ -108,53 +110,62 @@ public class AVMRemoteStore extends BaseRemoteStore
throw new WebScriptException("Unable to locate file: " + avmPath); throw new WebScriptException("Unable to locate file: " + avmPath);
} }
ContentReader reader = this.avmService.getContentReader(-1, avmPath); ContentReader reader;
if (reader == null)
{
throw new WebScriptException("No content found for AVM file: " + avmPath);
}
// establish mimetype
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = path.lastIndexOf('.');
if (extIndex != -1)
{
String ext = path.substring(extIndex + 1);
String mt = this.mimetypeService.getMimetypesByExtension().get(ext);
if (mt != null)
{
mimetype = mt;
}
}
}
// set mimetype for the content and the character encoding + length for the stream
WebScriptServletResponse httpRes = (WebScriptServletResponse)res;
httpRes.setContentType(mimetype);
httpRes.getHttpServletResponse().setCharacterEncoding(reader.getEncoding());
httpRes.getHttpServletResponse().setDateHeader("Last-Modified", desc.getModDate());
httpRes.setHeader("Content-Length", Long.toString(reader.getSize()));
// get the content and stream directly to the response output stream
// assuming the repository is capable of streaming in chunks, this should allow large files
// to be streamed directly to the browser response stream.
try try
{ {
reader.getContent(res.getOutputStream()); reader = this.avmService.getContentReader(-1, avmPath);
if (reader == null)
{
throw new WebScriptException("No content found for AVM file: " + avmPath);
}
// establish mimetype
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = path.lastIndexOf('.');
if (extIndex != -1)
{
String ext = path.substring(extIndex + 1);
String mt = this.mimetypeService.getMimetypesByExtension().get(ext);
if (mt != null)
{
mimetype = mt;
}
}
}
// set mimetype for the content and the character encoding + length for the stream
WebScriptServletResponse httpRes = (WebScriptServletResponse)res;
httpRes.setContentType(mimetype);
httpRes.getHttpServletResponse().setCharacterEncoding(reader.getEncoding());
httpRes.getHttpServletResponse().setDateHeader("Last-Modified", desc.getModDate());
httpRes.setHeader("Content-Length", Long.toString(reader.getSize()));
// get the content and stream directly to the response output stream
// assuming the repository is capable of streaming in chunks, this should allow large files
// to be streamed directly to the browser response stream.
try
{
reader.getContent(res.getOutputStream());
}
catch (SocketException e1)
{
// the client cut the connection - our mission was accomplished apart from a little error message
if (logger.isInfoEnabled())
logger.info("Client aborted stream read:\n\tnode: " + avmPath + "\n\tcontent: " + reader);
}
catch (ContentIOException e2)
{
if (logger.isInfoEnabled())
logger.info("Client aborted stream read:\n\tnode: " + avmPath + "\n\tcontent: " + reader);
}
} }
catch (SocketException e1) catch (AccessDeniedException ae)
{ {
// the client cut the connection - our mission was accomplished apart from a little error message res.setStatus(Status.STATUS_UNAUTHORIZED);
if (logger.isInfoEnabled())
logger.info("Client aborted stream read:\n\tnode: " + avmPath + "\n\tcontent: " + reader);
}
catch (ContentIOException e2)
{
if (logger.isInfoEnabled())
logger.info("Client aborted stream read:\n\tnode: " + avmPath + "\n\tcontent: " + reader);
} }
} }
@@ -186,7 +197,14 @@ public class AVMRemoteStore extends BaseRemoteStore
} }
String[] parts = AVMNodeConverter.SplitBase(avmPath); String[] parts = AVMNodeConverter.SplitBase(avmPath);
this.avmService.createFile(parts[0], parts[1], content); try
{
this.avmService.createFile(parts[0], parts[1], content);
}
catch (AccessDeniedException ae)
{
res.setStatus(Status.STATUS_UNAUTHORIZED);
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -202,8 +220,15 @@ public class AVMRemoteStore extends BaseRemoteStore
throw new WebScriptException("Unable to locate file for update: " + avmPath); throw new WebScriptException("Unable to locate file for update: " + avmPath);
} }
ContentWriter writer = this.avmService.getContentWriter(avmPath); try
writer.putContent(content); {
ContentWriter writer = this.avmService.getContentWriter(avmPath);
writer.putContent(content);
}
catch (AccessDeniedException ae)
{
res.setStatus(Status.STATUS_UNAUTHORIZED);
}
} }
/** /**