mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-31 17:39:05 +00:00
Moved web script classes and definitions out of web-client project and into remote-api
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8956 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
111
source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java
Normal file
111
source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.alfresco.web.scripts.TestWebScriptServer;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Base unit test class for web scripts.
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public abstract class BaseWebScriptTest extends TestCase
|
||||
{
|
||||
/** Standard HTTP method names */
|
||||
protected static final String METHOD_POST = "post";
|
||||
protected static final String METHOD_GET = "get";
|
||||
protected static final String METHOD_PUT = "put";
|
||||
protected static final String METHOD_DELETE = "delete";
|
||||
|
||||
/** Test web script server */
|
||||
private static TestWebScriptServer server = null;
|
||||
|
||||
protected static TestWebScriptServer getServer()
|
||||
{
|
||||
if (BaseWebScriptTest.server == null)
|
||||
{
|
||||
BaseWebScriptTest.server = TestWebScriptRepoServer.getTestServer();
|
||||
}
|
||||
return BaseWebScriptTest.server;
|
||||
}
|
||||
|
||||
/**
|
||||
* "GET" the url and check for the expected status code
|
||||
*
|
||||
* @param url
|
||||
* @param expectedStatus
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
protected MockHttpServletResponse getRequest(String url, int expectedStatus)
|
||||
throws IOException
|
||||
{
|
||||
return sendRequest(METHOD_GET, url, expectedStatus, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* "POST" the url and check for the expected status code
|
||||
*
|
||||
* @param url
|
||||
* @param expectedStatus
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
protected MockHttpServletResponse postRequest(String url, int expectedStatus, String body, String contentType)
|
||||
throws IOException
|
||||
{
|
||||
return sendRequest(METHOD_POST, url, expectedStatus, body, contentType);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param method
|
||||
* @param url
|
||||
* @param expectedStatus
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private MockHttpServletResponse sendRequest(String method, String url, int expectedStatus, String body, String contentType)
|
||||
throws IOException
|
||||
{
|
||||
MockHttpServletResponse response = BaseWebScriptTest.getServer().submitRequest(method, url, new HashMap<String, String>(), body, contentType);
|
||||
if (expectedStatus != response.getStatus())
|
||||
{
|
||||
if (response.getStatus() == 500)
|
||||
{
|
||||
System.out.println(response.getContentAsString());
|
||||
}
|
||||
fail("The expected status code (" + expectedStatus + ") was not returned.");
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
850
source/java/org/alfresco/repo/web/scripts/RepoStore.java
Normal file
850
source/java/org/alfresco/repo/web/scripts/RepoStore.java
Normal file
@@ -0,0 +1,850 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.model.filefolder.FileFolderServiceImpl;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.tenant.TenantDeployer;
|
||||
import org.alfresco.repo.tenant.TenantDeployerService;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.web.scripts.ScriptContent;
|
||||
import org.alfresco.web.scripts.ScriptLoader;
|
||||
import org.alfresco.web.scripts.Store;
|
||||
import org.alfresco.web.scripts.WebScript;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
|
||||
import freemarker.cache.TemplateLoader;
|
||||
|
||||
|
||||
/**
|
||||
* Repository based Web Script Store
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepoStore implements Store, TenantDeployer
|
||||
{
|
||||
protected boolean mustExist = false;
|
||||
protected StoreRef repoStore;
|
||||
protected String repoPath;
|
||||
protected Map<String, NodeRef> baseNodeRefs;
|
||||
|
||||
// dependencies
|
||||
protected RetryingTransactionHelper retryingTransactionHelper;
|
||||
protected SearchService searchService;
|
||||
protected NodeService nodeService;
|
||||
protected ContentService contentService;
|
||||
protected FileFolderService fileService;
|
||||
protected NamespaceService namespaceService;
|
||||
protected PermissionService permissionService;
|
||||
protected TenantDeployerService tenantDeployerService;
|
||||
|
||||
|
||||
/**
|
||||
* Sets helper that provides transaction callbacks
|
||||
*/
|
||||
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search service
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content service
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file service
|
||||
*/
|
||||
public void setFileFolderService(FileFolderService fileService)
|
||||
{
|
||||
this.fileService = fileService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace service
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permission service
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tenant deployer service
|
||||
*/
|
||||
public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
|
||||
{
|
||||
this.tenantDeployerService = tenantDeployerService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the repo store must exist
|
||||
*
|
||||
* @param mustExist
|
||||
*/
|
||||
public void setMustExist(boolean mustExist)
|
||||
{
|
||||
this.mustExist = mustExist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repo store
|
||||
*/
|
||||
public void setStore(String repoStore)
|
||||
{
|
||||
this.repoStore = new StoreRef(repoStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the repo path
|
||||
*
|
||||
* @param repoPath repoPath
|
||||
*/
|
||||
public void setPath(String repoPath)
|
||||
{
|
||||
this.repoPath = repoPath;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#init()
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#init()
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
if (baseNodeRefs == null)
|
||||
{
|
||||
baseNodeRefs = new HashMap<String, NodeRef>(1);
|
||||
}
|
||||
|
||||
getBaseNodeRef();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
baseNodeRefs.remove(tenantDeployerService.getCurrentUserDomain());
|
||||
}
|
||||
|
||||
private NodeRef getBaseNodeRef()
|
||||
{
|
||||
String tenantDomain = tenantDeployerService.getCurrentUserDomain();
|
||||
NodeRef baseNodeRef = baseNodeRefs.get(tenantDomain);
|
||||
if (baseNodeRef == null)
|
||||
{
|
||||
baseNodeRef = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<NodeRef>()
|
||||
{
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Exception
|
||||
{
|
||||
String query = "PATH:\"" + repoPath + "\"";
|
||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
||||
if (resultSet.length() == 1)
|
||||
{
|
||||
return resultSet.getNodeRef(0);
|
||||
}
|
||||
else if (mustExist)
|
||||
{
|
||||
throw new WebScriptException("Web Script Store " + repoStore.toString() + repoPath + " must exist; it was not found");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
// TODO clear on deleteTenant
|
||||
baseNodeRefs.put(tenantDomain, baseNodeRef);
|
||||
}
|
||||
return baseNodeRef;
|
||||
}
|
||||
|
||||
private String getBaseDir()
|
||||
{
|
||||
return getPath(getBaseNodeRef());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#exists()
|
||||
*/
|
||||
public boolean exists()
|
||||
{
|
||||
return (getBaseNodeRef() != null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getBasePath()
|
||||
*/
|
||||
public String getBasePath()
|
||||
{
|
||||
return repoStore.toString() + repoPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display path for the specified node
|
||||
*
|
||||
* @param nodeRef
|
||||
* @return display path
|
||||
*/
|
||||
protected String getPath(NodeRef nodeRef)
|
||||
{
|
||||
return nodeService.getPath(nodeRef).toDisplayPath(nodeService, permissionService) +
|
||||
"/" + nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node ref for the specified path within this repo store
|
||||
*
|
||||
* @param documentPath
|
||||
* @return node ref
|
||||
*/
|
||||
protected NodeRef findNodeRef(String documentPath)
|
||||
{
|
||||
NodeRef node = null;
|
||||
try
|
||||
{
|
||||
String[] pathElements = documentPath.split("/");
|
||||
List<String> pathElementsList = Arrays.asList(pathElements);
|
||||
FileInfo file = fileService.resolveNamePath(getBaseNodeRef(), pathElementsList);
|
||||
node = file.getNodeRef();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// NOTE: return null
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript)
|
||||
*/
|
||||
public String[] getScriptDocumentPaths(final WebScript script)
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String[]>()
|
||||
{
|
||||
public String[] doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<String[]>()
|
||||
{
|
||||
public String[] execute() throws Exception
|
||||
{
|
||||
int baseDirLength = getBaseDir().length() +1;
|
||||
List<String> documentPaths = null;
|
||||
String scriptPath = script.getDescription().getScriptPath();
|
||||
NodeRef scriptNodeRef = (scriptPath.length() == 0) ? getBaseNodeRef() : findNodeRef(scriptPath);
|
||||
if (scriptNodeRef != null)
|
||||
{
|
||||
org.alfresco.service.cmr.repository.Path repoScriptPath = nodeService.getPath(scriptNodeRef);
|
||||
String id = script.getDescription().getId().substring(scriptPath.length() + (scriptPath.length() > 0 ? 1 : 0));
|
||||
String query = "+PATH:\"" + repoScriptPath.toPrefixString(namespaceService) + "//*\" +QNAME:" + id + "*";
|
||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
||||
documentPaths = new ArrayList<String>(resultSet.length());
|
||||
List<NodeRef> nodes = resultSet.getNodeRefs();
|
||||
for (NodeRef nodeRef : nodes)
|
||||
{
|
||||
String name = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME);
|
||||
if (name.startsWith(id))
|
||||
{
|
||||
String nodeDir = getPath(nodeRef);
|
||||
String documentPath = nodeDir.substring(baseDirLength);
|
||||
documentPaths.add(documentPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return documentPaths != null ? documentPaths.toArray(new String[documentPaths.size()]) : new String[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getDescriptionDocumentPaths()
|
||||
*/
|
||||
public String[] getDescriptionDocumentPaths()
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String[]>()
|
||||
{
|
||||
public String[] doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<String[]>()
|
||||
{
|
||||
public String[] execute() throws Exception
|
||||
{
|
||||
int baseDirLength = getBaseDir().length() +1;
|
||||
|
||||
String query = "+PATH:\"" + repoPath + "//*\" +QNAME:*.desc.xml";
|
||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
||||
List<String> documentPaths = new ArrayList<String>(resultSet.length());
|
||||
List<NodeRef> nodes = resultSet.getNodeRefs();
|
||||
for (NodeRef nodeRef : nodes)
|
||||
{
|
||||
String nodeDir = getPath(nodeRef);
|
||||
if (nodeDir.endsWith(".desc.xml"))
|
||||
{
|
||||
String documentPath = nodeDir.substring(baseDirLength);
|
||||
documentPaths.add(documentPath);
|
||||
}
|
||||
}
|
||||
|
||||
return documentPaths.toArray(new String[documentPaths.size()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getAllDocumentPaths()
|
||||
*/
|
||||
public String[] getAllDocumentPaths()
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String[]>()
|
||||
{
|
||||
public String[] doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<String[]>()
|
||||
{
|
||||
public String[] execute() throws Exception
|
||||
{
|
||||
int baseDirLength = getBaseDir().length() +1;
|
||||
|
||||
String query = "+PATH:\"" + repoPath + "//*\" +TYPE:\"{http://www.alfresco.org/model/content/1.0}content\"";
|
||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
||||
List<String> documentPaths = new ArrayList<String>(resultSet.length());
|
||||
List<NodeRef> nodes = resultSet.getNodeRefs();
|
||||
for (NodeRef nodeRef : nodes)
|
||||
{
|
||||
String nodeDir = getPath(nodeRef);
|
||||
documentPaths.add(nodeDir.substring(baseDirLength));
|
||||
}
|
||||
|
||||
return documentPaths.toArray(new String[documentPaths.size()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#lastModified(java.lang.String)
|
||||
*/
|
||||
public long lastModified(final String documentPath) throws IOException
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Long>()
|
||||
{
|
||||
public Long doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Long>()
|
||||
{
|
||||
public Long execute() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getReader(
|
||||
findNodeRef(documentPath), ContentModel.PROP_CONTENT);
|
||||
return reader.getLastModified();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#hasDocument(java.lang.String)
|
||||
*/
|
||||
public boolean hasDocument(final String documentPath)
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Boolean>()
|
||||
{
|
||||
public Boolean doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Boolean>()
|
||||
{
|
||||
public Boolean execute() throws Exception
|
||||
{
|
||||
NodeRef nodeRef = findNodeRef(documentPath);
|
||||
return (nodeRef != null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getDescriptionDocument(java.lang.String)
|
||||
*/
|
||||
public InputStream getDocument(final String documentPath)
|
||||
throws IOException
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<InputStream>()
|
||||
{
|
||||
public InputStream doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<InputStream>()
|
||||
{
|
||||
public InputStream execute() throws Exception
|
||||
{
|
||||
NodeRef nodeRef = findNodeRef(documentPath);
|
||||
if (nodeRef == null)
|
||||
{
|
||||
throw new IOException("Document " + documentPath + " does not exist.");
|
||||
}
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
if (reader == null || !reader.exists())
|
||||
{
|
||||
throw new IOException("Failed to read content at " + documentPath + " (content reader does not exist)");
|
||||
}
|
||||
return reader.getContentInputStream();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#createDocument(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void createDocument(String documentPath, String content) throws IOException
|
||||
{
|
||||
String[] pathElements = documentPath.split("/");
|
||||
String[] folderElements = new String[pathElements.length -1];
|
||||
System.arraycopy(pathElements, 0, folderElements, 0, pathElements.length -1);
|
||||
List<String> folderElementsList = Arrays.asList(folderElements);
|
||||
|
||||
// create folder
|
||||
FileInfo pathInfo;
|
||||
if (folderElementsList.size() == 0)
|
||||
{
|
||||
pathInfo = fileService.getFileInfo(getBaseNodeRef());
|
||||
}
|
||||
else
|
||||
{
|
||||
pathInfo = FileFolderServiceImpl.makeFolders(fileService, getBaseNodeRef(), folderElementsList, ContentModel.TYPE_FOLDER);
|
||||
}
|
||||
|
||||
// create file
|
||||
String fileName = pathElements[pathElements.length -1];
|
||||
if (fileService.searchSimple(pathInfo.getNodeRef(), fileName) != null)
|
||||
{
|
||||
throw new IOException("Document " + documentPath + " already exists");
|
||||
}
|
||||
FileInfo fileInfo = fileService.create(pathInfo.getNodeRef(), fileName, ContentModel.TYPE_CONTENT);
|
||||
ContentWriter writer = fileService.getWriter(fileInfo.getNodeRef());
|
||||
writer.putContent(content);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#updateDocument(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void updateDocument(String documentPath, String content) throws IOException
|
||||
{
|
||||
String[] pathElements = documentPath.split("/");
|
||||
|
||||
// get parent folder
|
||||
NodeRef parentRef;
|
||||
if (pathElements.length == 1)
|
||||
{
|
||||
parentRef = getBaseNodeRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
parentRef = findNodeRef(documentPath.substring(0, documentPath.lastIndexOf('/')));
|
||||
}
|
||||
|
||||
// update file
|
||||
String fileName = pathElements[pathElements.length -1];
|
||||
if (fileService.searchSimple(parentRef, fileName) == null)
|
||||
{
|
||||
throw new IOException("Document " + documentPath + " does not exists");
|
||||
}
|
||||
FileInfo fileInfo = fileService.create(parentRef, fileName, ContentModel.TYPE_CONTENT);
|
||||
ContentWriter writer = fileService.getWriter(fileInfo.getNodeRef());
|
||||
writer.putContent(content);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getTemplateLoader()
|
||||
*/
|
||||
public TemplateLoader getTemplateLoader()
|
||||
{
|
||||
return new RepoTemplateLoader();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Store#getScriptLoader()
|
||||
*/
|
||||
public ScriptLoader getScriptLoader()
|
||||
{
|
||||
return new RepoScriptLoader();
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
|
||||
*/
|
||||
public void onEnableTenant()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
|
||||
*/
|
||||
public void onDisableTenant()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository path based template loader
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
private class RepoTemplateLoader implements TemplateLoader
|
||||
{
|
||||
/* (non-Javadoc)
|
||||
* @see freemarker.cache.TemplateLoader#findTemplateSource(java.lang.String)
|
||||
*/
|
||||
public Object findTemplateSource(final String name)
|
||||
throws IOException
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
RepoTemplateSource source = null;
|
||||
NodeRef nodeRef = findNodeRef(name);
|
||||
if (nodeRef != null)
|
||||
{
|
||||
source = new RepoTemplateSource(nodeRef);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object)
|
||||
*/
|
||||
public long getLastModified(Object templateSource)
|
||||
{
|
||||
return ((RepoTemplateSource)templateSource).lastModified();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see freemarker.cache.TemplateLoader#getReader(java.lang.Object, java.lang.String)
|
||||
*/
|
||||
public Reader getReader(Object templateSource, String encoding) throws IOException
|
||||
{
|
||||
return ((RepoTemplateSource)templateSource).getReader();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see freemarker.cache.TemplateLoader#closeTemplateSource(java.lang.Object)
|
||||
*/
|
||||
public void closeTemplateSource(Object arg0) throws IOException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository (content) node template source
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
private class RepoTemplateSource
|
||||
{
|
||||
protected final NodeRef nodeRef;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param ref
|
||||
*/
|
||||
private RepoTemplateSource(NodeRef ref)
|
||||
{
|
||||
this.nodeRef = ref;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (o instanceof RepoTemplateSource)
|
||||
{
|
||||
return nodeRef.equals(((RepoTemplateSource)o).nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
public int hashCode()
|
||||
{
|
||||
return nodeRef.hashCode();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString()
|
||||
{
|
||||
return nodeRef.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last modified time of the content
|
||||
*
|
||||
* @return last modified time
|
||||
*/
|
||||
public long lastModified()
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Long>()
|
||||
{
|
||||
public Long doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Long>()
|
||||
{
|
||||
public Long execute() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
return reader.getLastModified();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the content reader
|
||||
*
|
||||
* @return content reader
|
||||
* @throws IOException
|
||||
*/
|
||||
public Reader getReader() throws IOException
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Reader>()
|
||||
{
|
||||
public Reader doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Reader>()
|
||||
{
|
||||
public Reader execute() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
return new InputStreamReader(reader.getContentInputStream(), reader.getEncoding());
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository path based script loader
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
private class RepoScriptLoader implements ScriptLoader
|
||||
{
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
|
||||
*/
|
||||
public ScriptContent getScript(final String path)
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptContent>()
|
||||
{
|
||||
public ScriptContent doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<ScriptContent>()
|
||||
{
|
||||
public ScriptContent execute() throws Exception
|
||||
{
|
||||
ScriptContent location = null;
|
||||
NodeRef nodeRef = findNodeRef(path);
|
||||
if (nodeRef != null)
|
||||
{
|
||||
location = new RepoScriptContent(path, nodeRef);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repo path script location
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
private class RepoScriptContent implements ScriptContent
|
||||
{
|
||||
protected String path;
|
||||
protected NodeRef nodeRef;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param location
|
||||
*/
|
||||
public RepoScriptContent(String path, NodeRef nodeRef)
|
||||
{
|
||||
this.path = path;
|
||||
this.nodeRef = nodeRef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<InputStream>()
|
||||
{
|
||||
public InputStream doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<InputStream>()
|
||||
{
|
||||
public InputStream execute() throws Exception
|
||||
{
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
return reader.getContentInputStream();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
|
||||
*/
|
||||
public Reader getReader()
|
||||
{
|
||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
||||
try
|
||||
{
|
||||
return new InputStreamReader(getInputStream(), reader.getEncoding());
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unsupported Encoding", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptContent#getPath()
|
||||
*/
|
||||
public String getPath()
|
||||
{
|
||||
return repoStore + getBaseDir() + "/" + path;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptContent#getPathDescription()
|
||||
*/
|
||||
public String getPathDescription()
|
||||
{
|
||||
return "/" + path + " (in repository store " + repoStore.toString() + getBaseDir() + ")";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptContent#isSecure()
|
||||
*/
|
||||
public boolean isSecure()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
484
source/java/org/alfresco/repo/web/scripts/Repository.java
Normal file
484
source/java/org/alfresco/repo/web/scripts/Repository.java
Normal file
@@ -0,0 +1,484 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.tenant.TenantDeployer;
|
||||
import org.alfresco.repo.tenant.TenantDeployerService;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.model.FileFolderService;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.model.FileNotFoundException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
|
||||
/**
|
||||
* Provision of Repository Context
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class Repository implements ApplicationContextAware, ApplicationListener, TenantDeployer
|
||||
{
|
||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
||||
|
||||
// dependencies
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
private NamespaceService namespaceService;
|
||||
private SearchService searchService;
|
||||
private NodeService nodeService;
|
||||
private FileFolderService fileFolderService;
|
||||
private PersonService personService;
|
||||
private AVMService avmService;
|
||||
private TenantDeployerService tenantDeployerService;
|
||||
|
||||
// company home
|
||||
private StoreRef companyHomeStore;
|
||||
private String companyHomePath;
|
||||
private Map<String, NodeRef> companyHomeRefs;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the Company Home Store
|
||||
*
|
||||
* @param companyHomeStore
|
||||
*/
|
||||
public void setCompanyHomeStore(String companyHomeStore)
|
||||
{
|
||||
this.companyHomeStore = new StoreRef(companyHomeStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Company Home Path
|
||||
*
|
||||
* @param companyHomePath
|
||||
*/
|
||||
public void setCompanyHomePath(String companyHomePath)
|
||||
{
|
||||
this.companyHomePath = companyHomePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets helper that provides transaction callbacks
|
||||
*/
|
||||
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace service
|
||||
*
|
||||
* @param namespaceService
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the search service
|
||||
*
|
||||
* @param searchService
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node service
|
||||
*
|
||||
* @param nodeService
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file folder service
|
||||
*
|
||||
* @param nodeService
|
||||
*/
|
||||
public void setFileFolderService(FileFolderService fileFolderService)
|
||||
{
|
||||
this.fileFolderService = fileFolderService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the person service
|
||||
*
|
||||
* @param personService
|
||||
*/
|
||||
public void setPersonService(PersonService personService)
|
||||
{
|
||||
this.personService = personService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tenant deployer service
|
||||
*
|
||||
* @param tenantDeployerService
|
||||
*/
|
||||
public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
|
||||
{
|
||||
this.tenantDeployerService = tenantDeployerService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the AVM service
|
||||
*
|
||||
* @param avmService
|
||||
*/
|
||||
public void setAvmService(AVMService avmService)
|
||||
{
|
||||
this.avmService = avmService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
lifecycle.setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
lifecycle.onApplicationEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks into Spring Application Lifecycle
|
||||
*/
|
||||
private class ProcessorLifecycle extends AbstractLifecycleBean
|
||||
{
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
initContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise Repository Context
|
||||
*/
|
||||
protected void initContext()
|
||||
{
|
||||
tenantDeployerService.register(this);
|
||||
|
||||
if (companyHomeRefs == null)
|
||||
{
|
||||
companyHomeRefs = new HashMap<String, NodeRef>(1);
|
||||
}
|
||||
|
||||
getCompanyHome();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the root home of the company home store
|
||||
*
|
||||
* @return root node ref
|
||||
*/
|
||||
public NodeRef getRootHome()
|
||||
{
|
||||
return nodeService.getRootNode(companyHomeStore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Company Home
|
||||
*
|
||||
* @return company home node ref
|
||||
*/
|
||||
public NodeRef getCompanyHome()
|
||||
{
|
||||
String tenantDomain = tenantDeployerService.getCurrentUserDomain();
|
||||
NodeRef companyHomeRef = companyHomeRefs.get(tenantDomain);
|
||||
if (companyHomeRef == null)
|
||||
{
|
||||
companyHomeRef = AuthenticationUtil.runAs(new RunAsWork<NodeRef>()
|
||||
{
|
||||
public NodeRef doWork() throws Exception
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<NodeRef>()
|
||||
{
|
||||
public NodeRef execute() throws Exception
|
||||
{
|
||||
List<NodeRef> refs = searchService.selectNodes(nodeService.getRootNode(companyHomeStore), companyHomePath, null, namespaceService, false);
|
||||
if (refs.size() != 1)
|
||||
{
|
||||
throw new IllegalStateException("Invalid company home path: " + companyHomePath + " - found: " + refs.size());
|
||||
}
|
||||
return refs.get(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
|
||||
companyHomeRefs.put(tenantDomain, companyHomeRef);
|
||||
}
|
||||
return companyHomeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently authenticated person
|
||||
*
|
||||
* @return person node ref
|
||||
*/
|
||||
public NodeRef getPerson()
|
||||
{
|
||||
NodeRef person = null;
|
||||
String currentUserName = AuthenticationUtil.getCurrentUserName();
|
||||
if (personService.personExists(currentUserName))
|
||||
{
|
||||
person = personService.getPerson(currentUserName);
|
||||
}
|
||||
return person;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the user home of the currently authenticated person
|
||||
*
|
||||
* @param person person
|
||||
* @return user home of person
|
||||
*/
|
||||
public NodeRef getUserHome(NodeRef person)
|
||||
{
|
||||
return (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to convert a Web Script Request URL to a Node Ref
|
||||
*
|
||||
* 1) Node - {store_type}/{store_id}/{node_id}
|
||||
*
|
||||
* Resolve to node via its Node Reference.
|
||||
*
|
||||
* 2) Path - {store_type}/{store_id}/{path}
|
||||
*
|
||||
* Resolve to node via its display path.
|
||||
*
|
||||
* 3) AVM Path - {store_id}/{path}
|
||||
*
|
||||
* Resolve to AVM node via its display path
|
||||
*
|
||||
* 4) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
|
||||
*
|
||||
* Resolve to node via its child qname path.
|
||||
*
|
||||
* @param referenceType one of node, path, avmpath or qname
|
||||
* @return reference array of reference segments (as described above for each reference type)
|
||||
*/
|
||||
public NodeRef findNodeRef(String referenceType, String[] reference)
|
||||
{
|
||||
NodeRef nodeRef = null;
|
||||
|
||||
if (referenceType.equals("avmpath"))
|
||||
{
|
||||
if (reference.length == 0)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
|
||||
}
|
||||
String path = reference[0] + ":/";
|
||||
if (reference.length > 1)
|
||||
{
|
||||
Object[] pathElements = ArrayUtils.subarray(reference, 1, reference.length);
|
||||
path += StringUtils.join(pathElements, "/");
|
||||
}
|
||||
AVMNodeDescriptor nodeDesc = avmService.lookup(-1, path);
|
||||
if (nodeDesc != null)
|
||||
{
|
||||
nodeRef = AVMNodeConverter.ToNodeRef(-1, path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// construct store reference
|
||||
if (reference.length < 3)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
|
||||
}
|
||||
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
|
||||
if (nodeService.exists(storeRef))
|
||||
{
|
||||
if (referenceType.equals("node"))
|
||||
{
|
||||
// find the node the rest of the path is relative to
|
||||
NodeRef relRef = new NodeRef(storeRef, reference[2]);
|
||||
if (nodeService.exists(relRef))
|
||||
{
|
||||
// are there any relative path elements to process?
|
||||
if (reference.length == 3 || reference.length == 4)
|
||||
{
|
||||
// just the NodeRef can be specified
|
||||
nodeRef = relRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
// process optional path elements
|
||||
List<String> paths = new ArrayList<String>(reference.length - 3);
|
||||
for (int i=3; i<reference.length; i++)
|
||||
{
|
||||
paths.add(reference[i]);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
NodeRef parentRef = nodeService.getPrimaryParent(relRef).getParentRef();
|
||||
FileInfo fileInfo = fileFolderService.resolveNamePath(parentRef, paths);
|
||||
nodeRef = fileInfo.getNodeRef();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// NOTE: return null node ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (referenceType.equals("path"))
|
||||
{
|
||||
// NOTE: special case for avm based path
|
||||
if (reference[0].equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
String path = reference[1] + ":/";
|
||||
if (reference.length > 2)
|
||||
{
|
||||
Object[] pathElements = ArrayUtils.subarray(reference, 2, reference.length);
|
||||
path += StringUtils.join(pathElements, "/");
|
||||
}
|
||||
AVMNodeDescriptor nodeDesc = avmService.lookup(-1, path);
|
||||
if (nodeDesc != null)
|
||||
{
|
||||
nodeRef = AVMNodeConverter.ToNodeRef(-1, path);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
|
||||
//NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
NodeRef rootNodeRef = getCompanyHome();
|
||||
if (reference.length == 3)
|
||||
{
|
||||
nodeRef = rootNodeRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
String[] path = new String[reference.length - /*2*/3];
|
||||
System.arraycopy(reference, /*2*/3, path, 0, path.length);
|
||||
|
||||
try
|
||||
{
|
||||
FileInfo fileInfo = fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList(path));
|
||||
nodeRef = fileInfo.getNodeRef();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
// NOTE: return null node ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// TODO: Implement 'qname' style
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
|
||||
*/
|
||||
public void onEnableTenant()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
|
||||
*/
|
||||
public void onDisableTenant()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#init()
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
initContext();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
companyHomeRefs.remove(tenantDeployerService.getCurrentUserDomain());
|
||||
}
|
||||
}
|
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2008 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.cache.SimpleCache;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.tenant.TenantDeployer;
|
||||
import org.alfresco.repo.tenant.TenantDeployerService;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.web.scripts.AbstractRuntimeContainer;
|
||||
import org.alfresco.web.scripts.Authenticator;
|
||||
import org.alfresco.web.scripts.Description;
|
||||
import org.alfresco.web.scripts.Registry;
|
||||
import org.alfresco.web.scripts.ServerModel;
|
||||
import org.alfresco.web.scripts.WebScript;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.WebScriptResponse;
|
||||
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
||||
import org.alfresco.web.scripts.Description.RequiredTransaction;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) container for Web Scripts
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryContainer extends AbstractRuntimeContainer implements TenantDeployer
|
||||
{
|
||||
// Logger
|
||||
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class);
|
||||
|
||||
/** Component Dependencies */
|
||||
private Repository repository;
|
||||
private RepositoryImageResolver imageResolver;
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
private AuthorityService authorityService;
|
||||
private PermissionService permissionService;
|
||||
private DescriptorService descriptorService;
|
||||
private TenantDeployerService tenantDeployerService;
|
||||
private ObjectFactory registryFactory;
|
||||
private SimpleCache<String, Registry> webScriptsRegistryCache;
|
||||
|
||||
/**
|
||||
* @param webScriptsRegistryCache
|
||||
*/
|
||||
public void setWebScriptsRegistryCache(SimpleCache<String, Registry> webScriptsRegistryCache)
|
||||
{
|
||||
this.webScriptsRegistryCache = webScriptsRegistryCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param registryFactory
|
||||
*/
|
||||
public void setRegistryFactory(ObjectFactory registryFactory) {
|
||||
this.registryFactory = registryFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param repository
|
||||
*/
|
||||
public void setRepository(Repository repository)
|
||||
{
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageResolver
|
||||
*/
|
||||
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
|
||||
{
|
||||
this.imageResolver = imageResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param permissionService
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param retryingTransactionHelper
|
||||
*/
|
||||
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param descriptorService
|
||||
*/
|
||||
public void setDescriptorService(DescriptorService descriptorService)
|
||||
{
|
||||
this.descriptorService = descriptorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorityService
|
||||
*/
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tenantDeployerService
|
||||
*/
|
||||
public void setTenantDeployerService(TenantDeployerService tenantDeployerService)
|
||||
{
|
||||
this.tenantDeployerService = tenantDeployerService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Container#getDescription()
|
||||
*/
|
||||
public ServerModel getDescription()
|
||||
{
|
||||
return new RepositoryServerModel(descriptorService.getServerDescriptor());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getScriptParameters()
|
||||
*/
|
||||
public Map<String, Object> getScriptParameters()
|
||||
{
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.putAll(super.getScriptParameters());
|
||||
addRepoParameters(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getTemplateParameters()
|
||||
*/
|
||||
public Map<String, Object> getTemplateParameters()
|
||||
{
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.putAll(super.getTemplateParameters());
|
||||
params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver());
|
||||
addRepoParameters(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Repository specific parameters
|
||||
*
|
||||
* @param params
|
||||
*/
|
||||
private void addRepoParameters(Map<String, Object> params)
|
||||
{
|
||||
if (AlfrescoTransactionSupport.getTransactionId() != null && AuthenticationUtil.getCurrentAuthentication() != null)
|
||||
{
|
||||
NodeRef rootHome = repository.getRootHome();
|
||||
if (rootHome != null && permissionService.hasPermission(rootHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
|
||||
{
|
||||
params.put("roothome", rootHome);
|
||||
}
|
||||
NodeRef companyHome = repository.getCompanyHome();
|
||||
if (companyHome != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
|
||||
{
|
||||
params.put("companyhome", companyHome);
|
||||
}
|
||||
NodeRef person = repository.getPerson();
|
||||
if (person != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
|
||||
{
|
||||
params.put("person", person);
|
||||
params.put("userhome", repository.getUserHome(person));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.RuntimeContainer#executeScript(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse, org.alfresco.web.scripts.Authenticator)
|
||||
*/
|
||||
public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, Authenticator auth)
|
||||
throws IOException
|
||||
{
|
||||
WebScript script = scriptReq.getServiceMatch().getWebScript();
|
||||
Description desc = script.getDescription();
|
||||
RequiredAuthentication required = desc.getRequiredAuthentication();
|
||||
boolean isGuest = scriptReq.isGuest();
|
||||
|
||||
if (required == RequiredAuthentication.none)
|
||||
{
|
||||
// MT-context will pre-authenticate (see MTWebScriptAuthenticationFilter)
|
||||
if (! AuthenticationUtil.isMtEnabled())
|
||||
{
|
||||
// TODO revisit - cleared here, in-lieu of WebClient clear
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
transactionedExecute(script, scriptReq, scriptRes);
|
||||
}
|
||||
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
|
||||
}
|
||||
else
|
||||
{
|
||||
String currentUser = null;
|
||||
|
||||
try
|
||||
{
|
||||
//
|
||||
// Determine if user already authenticated
|
||||
//
|
||||
currentUser = AuthenticationUtil.getCurrentUserName();
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
||||
logger.debug("Authentication required: " + required);
|
||||
logger.debug("Guest login: " + isGuest);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply appropriate authentication to Web Script invocation
|
||||
//
|
||||
if (auth == null || auth.authenticate(required, isGuest))
|
||||
{
|
||||
if (required == RequiredAuthentication.admin && !authorityService.hasAdminAuthority())
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
|
||||
}
|
||||
|
||||
// Execute Web Script
|
||||
transactionedExecute(script, scriptReq, scriptRes);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
//
|
||||
// Reset authentication for current thread
|
||||
//
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
if (currentUser != null)
|
||||
{
|
||||
AuthenticationUtil.setCurrentUser(currentUser);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script within required level of transaction
|
||||
*
|
||||
* @param scriptReq
|
||||
* @param scriptRes
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
|
||||
throws IOException
|
||||
{
|
||||
final Description description = script.getDescription();
|
||||
if (description.getRequiredTransaction() == RequiredTransaction.none)
|
||||
{
|
||||
script.execute(scriptReq, scriptRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// encapsulate script within transaction
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Begin transaction: " + description.getRequiredTransaction());
|
||||
|
||||
script.execute(scriptReq, scriptRes);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("End transaction: " + description.getRequiredTransaction());
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
if (description.getRequiredTransaction() == RequiredTransaction.required)
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(work);
|
||||
}
|
||||
else
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(work, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRegistry()
|
||||
*/
|
||||
@Override
|
||||
public Registry getRegistry()
|
||||
{
|
||||
String tenantDomain = tenantDeployerService.getCurrentUserDomain();
|
||||
Registry registry = webScriptsRegistryCache.get(tenantDomain);
|
||||
if (registry == null)
|
||||
{
|
||||
init();
|
||||
registry = webScriptsRegistryCache.get(tenantDomain);
|
||||
}
|
||||
return registry;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
destroy();
|
||||
init();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant()
|
||||
*/
|
||||
public void onEnableTenant()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant()
|
||||
*/
|
||||
public void onDisableTenant()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#init()
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
tenantDeployerService.register(this);
|
||||
|
||||
Registry registry = (Registry)registryFactory.getObject();
|
||||
webScriptsRegistryCache.put(tenantDeployerService.getCurrentUserDomain(), registry);
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.tenant.TenantDeployer#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
webScriptsRegistryCache.remove(tenantDeployerService.getCurrentUserDomain());
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.alfresco.service.cmr.repository.FileTypeImageSize;
|
||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
|
||||
/**
|
||||
* Web Scripts Image Resolver
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryImageResolver
|
||||
implements ServletContextAware, InitializingBean
|
||||
{
|
||||
private ServletContext servletContext;
|
||||
private TemplateImageResolver imageResolver;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
|
||||
*/
|
||||
public void setServletContext(ServletContext context)
|
||||
{
|
||||
this.servletContext = context;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public void afterPropertiesSet()
|
||||
throws Exception
|
||||
{
|
||||
this.imageResolver = new TemplateImageResolver()
|
||||
{
|
||||
public String resolveImagePathForName(String filename, FileTypeImageSize size)
|
||||
{
|
||||
return FileTypeImageUtils.getFileTypeImage(servletContext, filename, size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return image resolver
|
||||
*/
|
||||
public TemplateImageResolver getImageResolver()
|
||||
{
|
||||
return this.imageResolver;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.jscript.ValueConverter;
|
||||
import org.alfresco.scripts.ScriptException;
|
||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.alfresco.web.scripts.MultiScriptLoader;
|
||||
import org.alfresco.web.scripts.ScriptContent;
|
||||
import org.alfresco.web.scripts.ScriptLoader;
|
||||
import org.alfresco.web.scripts.ScriptProcessor;
|
||||
import org.alfresco.web.scripts.SearchPath;
|
||||
import org.alfresco.web.scripts.Store;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) Web Script Processor
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryScriptProcessor implements ScriptProcessor
|
||||
{
|
||||
// dependencies
|
||||
protected ScriptService scriptService;
|
||||
protected ScriptLoader scriptLoader;
|
||||
protected SearchPath searchPath;
|
||||
|
||||
// Javascript Converter
|
||||
private ValueConverter valueConverter = new ValueConverter();
|
||||
|
||||
|
||||
/**
|
||||
* @param scriptService
|
||||
*/
|
||||
public void setScriptService(ScriptService scriptService)
|
||||
{
|
||||
this.scriptService = scriptService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchPath
|
||||
*/
|
||||
public void setSearchPath(SearchPath searchPath)
|
||||
{
|
||||
this.searchPath = searchPath;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#findScript(java.lang.String)
|
||||
*/
|
||||
public ScriptContent findScript(String path)
|
||||
{
|
||||
return scriptLoader.getScript(path);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(java.lang.String, java.util.Map)
|
||||
*/
|
||||
public Object executeScript(String path, Map<String, Object> model)
|
||||
throws ScriptException
|
||||
{
|
||||
// locate script within web script stores
|
||||
ScriptContent scriptContent = findScript(path);
|
||||
if (scriptContent == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to locate script " + path);
|
||||
}
|
||||
// execute script
|
||||
return executeScript(scriptContent, model);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(org.alfresco.web.scripts.ScriptContent, java.util.Map)
|
||||
*/
|
||||
public Object executeScript(ScriptContent content, Map<String, Object> model)
|
||||
{
|
||||
return scriptService.executeScript("javascript", new RepositoryScriptLocation(content), model);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#unwrapValue(java.lang.Object)
|
||||
*/
|
||||
public Object unwrapValue(Object value)
|
||||
{
|
||||
return (value instanceof Serializable) ? valueConverter.convertValueForRepo((Serializable)value) : value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register script loader from each Web Script Store with Script Processor
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
|
||||
for (Store apiStore : searchPath.getStores())
|
||||
{
|
||||
ScriptLoader loader = apiStore.getScriptLoader();
|
||||
if (loader == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath());
|
||||
}
|
||||
loaders.add(loader);
|
||||
}
|
||||
scriptLoader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Script Location Facade
|
||||
*/
|
||||
private static class RepositoryScriptLocation implements ScriptLocation
|
||||
{
|
||||
private ScriptContent content;
|
||||
|
||||
private RepositoryScriptLocation(ScriptContent content)
|
||||
{
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
return content.getInputStream();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
|
||||
*/
|
||||
public Reader getReader()
|
||||
{
|
||||
return content.getReader();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#isSecure()
|
||||
*/
|
||||
public boolean isSecure()
|
||||
{
|
||||
return content.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return content.getPathDescription();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.alfresco.web.scripts.ServerModel;
|
||||
|
||||
|
||||
/**
|
||||
* Script / Template Model representing Repository Server meta-data
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryServerModel implements ServerModel
|
||||
{
|
||||
private Descriptor serverDescriptor;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param serverDescriptor
|
||||
*/
|
||||
/*package*/ RepositoryServerModel(Descriptor serverDescriptor)
|
||||
{
|
||||
this.serverDescriptor = serverDescriptor;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getContainerName()
|
||||
*/
|
||||
public String getContainerName()
|
||||
{
|
||||
return "Repository";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionMajor()
|
||||
*/
|
||||
public String getVersionMajor()
|
||||
{
|
||||
return serverDescriptor.getVersionMajor();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionMinor()
|
||||
*/
|
||||
public String getVersionMinor()
|
||||
{
|
||||
return serverDescriptor.getVersionMinor();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionRevision()
|
||||
*/
|
||||
public String getVersionRevision()
|
||||
{
|
||||
return serverDescriptor.getVersionRevision();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionLabel()
|
||||
*/
|
||||
public String getVersionLabel()
|
||||
{
|
||||
return serverDescriptor.getVersionLabel();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionBuild()
|
||||
*/
|
||||
public String getVersionBuild()
|
||||
{
|
||||
return serverDescriptor.getVersionBuild();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersion()
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return serverDescriptor.getVersion();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getEdition()
|
||||
*/
|
||||
public String getEdition()
|
||||
{
|
||||
return serverDescriptor.getEdition();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getSchema()
|
||||
*/
|
||||
public int getSchema()
|
||||
{
|
||||
return serverDescriptor.getSchema();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.repo.template.FreeMarkerProcessor;
|
||||
import org.alfresco.repo.template.QNameAwareObjectWrapper;
|
||||
import org.alfresco.service.cmr.repository.ProcessorExtension;
|
||||
import org.alfresco.util.AbstractLifecycleBean;
|
||||
import org.alfresco.web.scripts.SearchPath;
|
||||
import org.alfresco.web.scripts.Store;
|
||||
import org.alfresco.web.scripts.TemplateProcessor;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
|
||||
import freemarker.cache.MruCacheStorage;
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) Web Script Template Processor
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryTemplateProcessor extends FreeMarkerProcessor
|
||||
implements TemplateProcessor, ApplicationContextAware, ApplicationListener
|
||||
{
|
||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
||||
protected SearchPath searchPath;
|
||||
protected String defaultEncoding;
|
||||
protected Configuration templateConfig;
|
||||
protected FreeMarkerProcessor freeMarkerProcessor;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
|
||||
*/
|
||||
public void setDefaultEncoding(String defaultEncoding)
|
||||
{
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding()
|
||||
*/
|
||||
public String getDefaultEncoding()
|
||||
{
|
||||
return this.defaultEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchPath
|
||||
*/
|
||||
public void setSearchPath(SearchPath searchPath)
|
||||
{
|
||||
this.searchPath = searchPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the freemarker processor
|
||||
*
|
||||
* @param freeMarkerProcessor the free marker processor
|
||||
*/
|
||||
public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor)
|
||||
{
|
||||
this.freeMarkerProcessor = freeMarkerProcessor;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig()
|
||||
*/
|
||||
@Override
|
||||
protected Configuration getConfig()
|
||||
{
|
||||
return templateConfig;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.TemplateProcessor#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
if (templateConfig != null)
|
||||
{
|
||||
templateConfig.clearTemplateCache();
|
||||
}
|
||||
initConfig();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.TemplateProcessor#hasTemplate(java.lang.String)
|
||||
*/
|
||||
public boolean hasTemplate(String templatePath)
|
||||
{
|
||||
boolean hasTemplate = false;
|
||||
try
|
||||
{
|
||||
Template template = templateConfig.getTemplate(templatePath);
|
||||
hasTemplate = (template != null);
|
||||
}
|
||||
catch(FileNotFoundException e)
|
||||
{
|
||||
// NOTE: return false as template is not found
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new WebScriptException("Failed to retrieve template " + templatePath, e);
|
||||
}
|
||||
return hasTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise FreeMarker Configuration
|
||||
*/
|
||||
protected void initConfig()
|
||||
{
|
||||
Configuration config = new Configuration();
|
||||
|
||||
// setup template cache
|
||||
config.setCacheStorage(new MruCacheStorage(20, 100));
|
||||
config.setTemplateUpdateDelay(0);
|
||||
|
||||
// setup template loaders
|
||||
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
|
||||
for (Store apiStore : searchPath.getStores())
|
||||
{
|
||||
TemplateLoader loader = apiStore.getTemplateLoader();
|
||||
if (loader == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath());
|
||||
}
|
||||
loaders.add(loader);
|
||||
}
|
||||
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
|
||||
config.setTemplateLoader(loader);
|
||||
|
||||
// use our custom object wrapper that can deal with QNameMap objects directly
|
||||
config.setObjectWrapper(new QNameAwareObjectWrapper());
|
||||
|
||||
// rethrow any exception so we can deal with them
|
||||
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
|
||||
// turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists()
|
||||
config.setLocalizedLookup(false);
|
||||
|
||||
// set template encoding
|
||||
if (defaultEncoding != null)
|
||||
{
|
||||
config.setDefaultEncoding(defaultEncoding);
|
||||
}
|
||||
|
||||
// set output encoding
|
||||
config.setOutputEncoding("UTF-8");
|
||||
|
||||
templateConfig = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tempory fix to initialise this template processor with the freeMarker extensions expected by
|
||||
* the templates.
|
||||
*/
|
||||
private void initProcessorExtensions()
|
||||
{
|
||||
for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions())
|
||||
{
|
||||
this.registerProcessorExtension(processorExtension);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
lifecycle.setApplicationContext(applicationContext);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
lifecycle.onApplicationEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks into Spring Application Lifecycle
|
||||
*/
|
||||
private class ProcessorLifecycle extends AbstractLifecycleBean
|
||||
{
|
||||
@Override
|
||||
protected void onBootstrap(ApplicationEvent event)
|
||||
{
|
||||
initProcessorExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.web.scripts.TestWebScriptServer;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
|
||||
/**
|
||||
* Stand-alone Web Script Test Server
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class TestWebScriptRepoServer extends TestWebScriptServer
|
||||
{
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
|
||||
/**
|
||||
* Sets helper that provides transaction callbacks
|
||||
*/
|
||||
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authenticationService
|
||||
*/
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Main entry point.
|
||||
*/
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
TestWebScriptServer testServer = getTestServer();
|
||||
testServer.rep();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
StringWriter strWriter = new StringWriter();
|
||||
PrintWriter printWriter = new PrintWriter(strWriter);
|
||||
e.printStackTrace(printWriter);
|
||||
System.out.println(strWriter.toString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an instance of the TestWebScriptServer
|
||||
*
|
||||
* @return Test Server
|
||||
*/
|
||||
public static TestWebScriptServer getTestServer()
|
||||
{
|
||||
String[] CONFIG_LOCATIONS = new String[]
|
||||
{
|
||||
"classpath:alfresco/application-context.xml",
|
||||
"classpath:alfresco/webscript-framework-application-context.xml",
|
||||
"classpath:alfresco/web-scripts-application-context.xml",
|
||||
"classpath:alfresco/web-scripts-application-context-test.xml"
|
||||
};
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
|
||||
TestWebScriptServer testServer = (TestWebScriptRepoServer)context.getBean("webscripts.test");
|
||||
return testServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret a single command using the BufferedReader passed in for any data needed.
|
||||
*
|
||||
* @param line The unparsed command
|
||||
* @return The textual output of the command.
|
||||
*/
|
||||
@Override
|
||||
protected String interpretCommand(final String line)
|
||||
throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (username.startsWith("TICKET_"))
|
||||
{
|
||||
try
|
||||
{
|
||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
authenticationService.validate(username);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return executeCommand(line);
|
||||
}
|
||||
finally
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
executeCommand("user admin");
|
||||
}
|
||||
|
||||
// execute command in context of currently selected user
|
||||
return AuthenticationUtil.runAs(new RunAsWork<String>()
|
||||
{
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
return executeCommand(line);
|
||||
}
|
||||
}, username);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Writer;
|
||||
import java.net.SocketException;
|
||||
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.avm.AVMNodeDescriptor;
|
||||
import org.alfresco.service.cmr.avm.AVMService;
|
||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptResponse;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* AVM Remote Store service.
|
||||
*
|
||||
* @see BaseRemoteStore for API methods.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class AVMRemoteStore extends BaseRemoteStore
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(AVMRemoteStore.class);
|
||||
|
||||
private String rootPath;
|
||||
private AVMService avmService;
|
||||
|
||||
|
||||
/**
|
||||
* @param rootPath the root path under which to process store requests
|
||||
*/
|
||||
public void setRootPath(String rootPath)
|
||||
{
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param avmService the AVMService to set
|
||||
*/
|
||||
public void setAvmService(AVMService avmService)
|
||||
{
|
||||
this.avmService = avmService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the last modified timestamp for the document.
|
||||
*
|
||||
* @param path document path to an existing document
|
||||
*/
|
||||
@Override
|
||||
protected void lastModified(WebScriptResponse res, String path)
|
||||
throws IOException
|
||||
{
|
||||
String avmPath = buildAVMPath(path);
|
||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||
if (desc == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to locate AVM file: " + avmPath);
|
||||
}
|
||||
|
||||
Writer out = res.getWriter();
|
||||
out.write(Long.toString(desc.getModDate()));
|
||||
out.close();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#getDocument(org.alfresco.web.scripts.WebScriptResponse, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected void getDocument(WebScriptResponse res, String path) throws IOException
|
||||
{
|
||||
String avmPath = buildAVMPath(path);
|
||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||
if (desc == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to locate file: " + avmPath);
|
||||
}
|
||||
|
||||
ContentReader 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#hasDocument(org.alfresco.web.scripts.WebScriptResponse, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
protected void hasDocument(WebScriptResponse res, String path) throws IOException
|
||||
{
|
||||
String avmPath = buildAVMPath(path);
|
||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||
|
||||
Writer out = res.getWriter();
|
||||
out.write(Boolean.toString(desc != null));
|
||||
out.close();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#createDocument(org.alfresco.web.scripts.WebScriptResponse, java.lang.String, java.io.InputStream)
|
||||
*/
|
||||
@Override
|
||||
protected void createDocument(WebScriptResponse res, String path, InputStream content)
|
||||
{
|
||||
String avmPath = buildAVMPath(path);
|
||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||
if (desc != null)
|
||||
{
|
||||
throw new WebScriptException("Unable to create, file already exists: " + avmPath);
|
||||
}
|
||||
|
||||
String[] parts = AVMNodeConverter.SplitBase(avmPath);
|
||||
this.avmService.createFile(parts[0], parts[1], content);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.bean.BaseRemoteStore#updateDocument(org.alfresco.web.scripts.WebScriptResponse, java.lang.String, java.io.InputStream)
|
||||
*/
|
||||
@Override
|
||||
protected void updateDocument(WebScriptResponse res, String path, InputStream content)
|
||||
{
|
||||
String avmPath = buildAVMPath(path);
|
||||
AVMNodeDescriptor desc = this.avmService.lookup(-1, avmPath);
|
||||
if (desc == null)
|
||||
{
|
||||
throw new WebScriptException("Unable to locate file for update: " + avmPath);
|
||||
}
|
||||
|
||||
ContentWriter writer = this.avmService.getContentWriter(avmPath);
|
||||
writer.putContent(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path root path relative
|
||||
*
|
||||
* @return full AVM path to document including store and root path components
|
||||
*/
|
||||
private String buildAVMPath(String path)
|
||||
{
|
||||
return this.store + ":/" + this.rootPath + "/" + path;
|
||||
}
|
||||
}
|
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.web.scripts.AbstractWebScript;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.WebScriptResponse;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Remote Store service.
|
||||
*
|
||||
* Responsible for providing remote HTTP based access to a store. Designed to be accessed
|
||||
* from a web-tier application to remotely mirror a WebScript Store instance.
|
||||
*
|
||||
* Request format:
|
||||
* <servicepath>/<method>/<path>
|
||||
*
|
||||
* Example:
|
||||
* /service/remotestore/lastmodified/sites/xyz/pages/page.xml
|
||||
*
|
||||
* where:
|
||||
* /service/remotestore -> service path
|
||||
* /lastmodified -> method name
|
||||
* /sites/../page.xml -> document path
|
||||
*
|
||||
* Note: path is relative to the root path as configured for this webscript bean
|
||||
*
|
||||
* For content create and update the request should be POSTed and the content sent as the
|
||||
* payload of the request content.
|
||||
*
|
||||
* Supported method API:
|
||||
* GET lastmodified -> return long timestamp of a document
|
||||
* GET has -> return true/false of existence for a document
|
||||
* GET get -> return document content - in addition the usual HTTP headers for the
|
||||
* character encoding, content type, length and modified date will be supplied
|
||||
* POST create -> create a new document with request content payload
|
||||
* POST update -> update an existing document with request content payload
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public abstract class BaseRemoteStore extends AbstractWebScript
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(BaseRemoteStore.class);
|
||||
|
||||
protected String store;
|
||||
protected ContentService contentService;
|
||||
protected MimetypeService mimetypeService;
|
||||
|
||||
|
||||
/**
|
||||
* @param store the store name of the store to process document requests against
|
||||
*/
|
||||
public void setStore(String store)
|
||||
{
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentService the ContentService to set
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mimetypeService the MimetypeService to set
|
||||
*/
|
||||
public void setMimetypeService(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the webscript based on the request parameters
|
||||
*/
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
|
||||
{
|
||||
// NOTE: This web script must be executed in a HTTP Servlet environment
|
||||
if (!(req instanceof WebScriptServletRequest))
|
||||
{
|
||||
throw new WebScriptException("Remote Store access must be executed in HTTP Servlet environment");
|
||||
}
|
||||
|
||||
HttpServletRequest httpReq = ((WebScriptServletRequest)req).getHttpServletRequest();
|
||||
|
||||
// break down and validate the request - expecting method name and document path
|
||||
String extPath = req.getExtensionPath();
|
||||
String[] extParts = extPath == null ? new String[0] : extPath.split("/");
|
||||
if (extParts.length < 1)
|
||||
{
|
||||
throw new WebScriptException("Remote Store expecting method name.");
|
||||
}
|
||||
if (extParts.length < 2)
|
||||
{
|
||||
throw new WebScriptException("Remote Store expecting document path.");
|
||||
}
|
||||
|
||||
// build path as a string and as a list of path elements
|
||||
String path = req.getExtensionPath().substring(extParts[0].length() + 1);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Remote store method: " + extParts[0] + " path: " + path);
|
||||
|
||||
// TODO: support storeref name override as argument (i.e. for AVM virtualisation)
|
||||
|
||||
try
|
||||
{
|
||||
// generate enum from string method name - so we can use a fast switch table lookup
|
||||
APIMethod method = APIMethod.valueOf(extParts[0].toUpperCase());
|
||||
switch (method)
|
||||
{
|
||||
case LASTMODIFIED:
|
||||
lastModified(res, path);
|
||||
break;
|
||||
|
||||
case HAS:
|
||||
hasDocument(res, path);
|
||||
break;
|
||||
|
||||
case GET:
|
||||
getDocument(res, path);
|
||||
break;
|
||||
|
||||
case CREATE:
|
||||
createDocument(res, path, httpReq.getInputStream());
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
updateDocument(res, path, httpReq.getInputStream());
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException enumErr)
|
||||
{
|
||||
throw new WebScriptException("Unknown method specified to remote store API: " + extParts[0]);
|
||||
}
|
||||
catch (IOException ioErr)
|
||||
{
|
||||
throw new WebScriptException("Error during remote store API: " + ioErr.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to break down webscript extension path into path component elements
|
||||
*/
|
||||
protected List<String> getPathParts(String[] extPaths)
|
||||
{
|
||||
List<String> pathParts = new ArrayList<String>(extPaths.length - 1);
|
||||
for (int i=1; i<extPaths.length; i++)
|
||||
{
|
||||
pathParts.add(extPaths[i]);
|
||||
}
|
||||
return pathParts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last modified timestamp for the document.
|
||||
*
|
||||
* @param path document path to an existing document
|
||||
*/
|
||||
protected abstract void lastModified(WebScriptResponse res, String path)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Determines if the document exists
|
||||
*
|
||||
* @param path document path
|
||||
* @return true => exists, false => does not exist
|
||||
*/
|
||||
protected abstract void hasDocument(WebScriptResponse res, String path)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Gets a document
|
||||
*
|
||||
* @param path document path
|
||||
* @return input stream onto document
|
||||
*
|
||||
* @throws IOException if the document does not exist in the store
|
||||
*/
|
||||
protected abstract void getDocument(WebScriptResponse res, String path)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Creates a document.
|
||||
*
|
||||
* @param path document path
|
||||
* @param content content of the document to write
|
||||
*
|
||||
* @throws IOException if the document already exists or the create fails
|
||||
*/
|
||||
protected abstract void createDocument(WebScriptResponse res, String path, InputStream content);
|
||||
|
||||
/**
|
||||
* Updates an existing document.
|
||||
*
|
||||
* @param path document path
|
||||
* @param content content to update the document with
|
||||
*
|
||||
* @throws IOException if the document does not exist or the update fails
|
||||
*/
|
||||
protected abstract void updateDocument(WebScriptResponse res, String path, InputStream content);
|
||||
|
||||
|
||||
/**
|
||||
* Enum representing the API method on the Store.
|
||||
*/
|
||||
private enum APIMethod
|
||||
{
|
||||
LASTMODIFIED,
|
||||
HAS,
|
||||
GET,
|
||||
CREATE,
|
||||
UPDATE
|
||||
};
|
||||
}
|
283
source/java/org/alfresco/repo/web/scripts/bean/ContentGet.java
Normal file
283
source/java/org/alfresco/repo/web/scripts/bean/ContentGet.java
Normal file
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.web.scripts.Repository;
|
||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
import org.alfresco.service.cmr.repository.ContentReader;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
import org.alfresco.service.cmr.repository.MimetypeService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.URLEncoder;
|
||||
import org.alfresco.web.scripts.AbstractWebScript;
|
||||
import org.alfresco.web.scripts.Cache;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.WebScriptResponse;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Content Retrieval Service
|
||||
*
|
||||
* Stream content from the Repository.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class ContentGet extends AbstractWebScript
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(ContentGet.class);
|
||||
|
||||
private static final String NODE_URL = "/api/node/content/{0}/{1}/{2}/{3}";
|
||||
|
||||
// Component dependencies
|
||||
private Repository repository;
|
||||
private NamespaceService namespaceService;
|
||||
private PermissionService permissionService;
|
||||
private NodeService nodeService;
|
||||
private ContentService contentService;
|
||||
private MimetypeService mimetypeService;
|
||||
|
||||
/**
|
||||
* @param repository
|
||||
*/
|
||||
public void setRepository(Repository repository)
|
||||
{
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param namespaceService
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param permissionService
|
||||
*/
|
||||
public void setPermissionService(PermissionService permissionService)
|
||||
{
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeService
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param contentService
|
||||
*/
|
||||
public void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mimetypeService
|
||||
*/
|
||||
public void setMimetypeService(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res)
|
||||
throws IOException
|
||||
{
|
||||
// NOTE: This web script must be executed in a HTTP Servlet environment
|
||||
if (!(req instanceof WebScriptServletRequest))
|
||||
{
|
||||
throw new WebScriptException("Content retrieval must be executed in HTTP Servlet environment");
|
||||
}
|
||||
HttpServletRequest httpReq = ((WebScriptServletRequest)req).getHttpServletRequest();
|
||||
HttpServletResponse httpRes = ((WebScriptServletResponse)res).getHttpServletResponse();
|
||||
|
||||
// convert web script URL to node reference in Repository
|
||||
String match = req.getServiceMatch().getPath();
|
||||
String[] matchParts = match.split("/");
|
||||
String extensionPath = req.getExtensionPath();
|
||||
String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/");
|
||||
String[] path = new String[extParts.length -1];
|
||||
System.arraycopy(extParts, 1, path, 0, extParts.length -1);
|
||||
NodeRef nodeRef = repository.findNodeRef(matchParts[2], path);
|
||||
if (nodeRef == null)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path));
|
||||
}
|
||||
|
||||
// determine content property
|
||||
QName propertyQName = ContentModel.PROP_CONTENT;
|
||||
String contentPart = extParts[0];
|
||||
if (contentPart.length() > 0 && contentPart.charAt(0) == ';')
|
||||
{
|
||||
if (contentPart.length() < 2)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Content property malformed");
|
||||
}
|
||||
String propertyName = contentPart.substring(1);
|
||||
if (propertyName.length() > 0)
|
||||
{
|
||||
propertyQName = QName.createQName(propertyName, namespaceService);
|
||||
}
|
||||
}
|
||||
|
||||
// determine attachment
|
||||
boolean attach = Boolean.valueOf(req.getParameter("a"));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Retrieving content from node ref " + nodeRef.toString() + " (property: " + propertyQName.toString() + ") (attach: " + attach + ")");
|
||||
|
||||
// check that the user has at least READ_CONTENT access - else redirect to the login page
|
||||
if (permissionService.hasPermission(nodeRef, PermissionService.READ_CONTENT) == AccessStatus.DENIED)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Permission denied");
|
||||
}
|
||||
|
||||
// check If-Modified-Since header and set Last-Modified header as appropriate
|
||||
Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
|
||||
long modifiedSince = httpReq.getDateHeader("If-Modified-Since");
|
||||
if (modifiedSince > 0L)
|
||||
{
|
||||
// round the date to the ignore millisecond value which is not supplied by header
|
||||
long modDate = (modified.getTime() / 1000L) * 1000L;
|
||||
if (modDate <= modifiedSince)
|
||||
{
|
||||
httpRes.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// handle attachment
|
||||
if (attach == true)
|
||||
{
|
||||
// set header based on filename - will force a Save As from the browse if it doesn't recognize it
|
||||
// this is better than the default response of the browser trying to display the contents
|
||||
httpRes.setHeader("Content-Disposition", "attachment");
|
||||
}
|
||||
|
||||
// get the content reader
|
||||
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
|
||||
if (reader == null || !reader.exists())
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to locate content for node ref " + nodeRef + " (property: " + propertyQName.toString() + ")");
|
||||
}
|
||||
|
||||
// establish mimetype
|
||||
String mimetype = reader.getMimetype();
|
||||
if (mimetype == null || mimetype.length() == 0)
|
||||
{
|
||||
mimetype = MimetypeMap.MIMETYPE_BINARY;
|
||||
int extIndex = extensionPath.lastIndexOf('.');
|
||||
if (extIndex != -1)
|
||||
{
|
||||
String ext = extensionPath.substring(extIndex + 1);
|
||||
String mt = mimetypeService.getMimetypesByExtension().get(ext);
|
||||
if (mt != null)
|
||||
{
|
||||
mimetype = mt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// set mimetype for the content and the character encoding + length for the stream
|
||||
httpRes.setContentType(mimetype);
|
||||
httpRes.setCharacterEncoding(reader.getEncoding());
|
||||
httpRes.setHeader("Content-Length", Long.toString(reader.getSize()));
|
||||
|
||||
// set caching
|
||||
Cache cache = new Cache();
|
||||
cache.setNeverCache(false);
|
||||
cache.setMustRevalidate(true);
|
||||
cache.setLastModified(modified);
|
||||
res.setCache(cache);
|
||||
|
||||
// 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: " + nodeRef + "\n\tcontent: " + reader);
|
||||
}
|
||||
catch (ContentIOException e2)
|
||||
{
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Client aborted stream read:\n\tnode: " + nodeRef + "\n\tcontent: " + reader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to generate a URL to a content node for downloading content from the server.
|
||||
* The content is supplied directly in the reponse. This generally means a browser will
|
||||
* attempt to open the content directly if possible, else it will prompt to save the file.
|
||||
*
|
||||
* @param ref NodeRef of the content node to generate URL for (cannot be null)
|
||||
* @param name File name end element to return on the url (used by the browser on Save)
|
||||
*
|
||||
* @return URL to download the content from the specified node
|
||||
*/
|
||||
public final static String generateNodeURL(NodeRef ref, String name)
|
||||
{
|
||||
return MessageFormat.format(NODE_URL, new Object[] {
|
||||
ref.getStoreRef().getProtocol(),
|
||||
ref.getStoreRef().getIdentifier(),
|
||||
ref.getId(),
|
||||
URLEncoder.encode(name) } );
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
|
||||
|
||||
/**
|
||||
* Javascript Debugger
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JavascriptDebugger extends DeclarativeWebScript
|
||||
{
|
||||
// dependencies
|
||||
private AlfrescoRhinoScriptDebugger debugger;
|
||||
|
||||
/**
|
||||
* @param ticketComponent
|
||||
*/
|
||||
public void setDebugger(AlfrescoRhinoScriptDebugger debugger)
|
||||
{
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
// construct model
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("visible", debugger.isVisible());
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
|
||||
|
||||
/**
|
||||
* Javascript Debugger
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JavascriptDebuggerPost extends DeclarativeWebScript
|
||||
{
|
||||
// dependencies
|
||||
private AlfrescoRhinoScriptDebugger debugger;
|
||||
|
||||
/**
|
||||
* @param ticketComponent
|
||||
*/
|
||||
public void setDebugger(AlfrescoRhinoScriptDebugger debugger)
|
||||
{
|
||||
this.debugger = debugger;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
String visibleStr = req.getParameter("visible");
|
||||
boolean visible = Boolean.valueOf(visibleStr);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
debugger.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
debugger.hide();
|
||||
}
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("visible", debugger.isVisible());
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.template.TemplateNode;
|
||||
import org.alfresco.repo.web.scripts.RepositoryImageResolver;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateException;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.alfresco.util.URLEncoder;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco Keyword (simple) Search Service
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class KeywordSearch extends DeclarativeWebScript
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(KeywordSearch.class);
|
||||
|
||||
// search parameters
|
||||
// TODO: allow configuration of search store
|
||||
protected static final StoreRef SEARCH_STORE = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
|
||||
protected static final int DEFAULT_ITEMS_PER_PAGE = 10;
|
||||
protected static final String QUERY_FORMAT = "query_";
|
||||
|
||||
// dependencies
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected RepositoryImageResolver imageResolver;
|
||||
protected SearchService searchService;
|
||||
|
||||
/**
|
||||
* @param searchService
|
||||
*/
|
||||
public void setSearchService(SearchService searchService)
|
||||
{
|
||||
this.searchService = searchService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageResolver
|
||||
*/
|
||||
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
|
||||
{
|
||||
this.imageResolver = imageResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceRegistry
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
//
|
||||
// process arguments
|
||||
//
|
||||
|
||||
String searchTerms = req.getParameter("q");
|
||||
ParameterCheck.mandatoryString("q", searchTerms);
|
||||
String startPageArg = req.getParameter("p");
|
||||
int startPage = 1;
|
||||
try
|
||||
{
|
||||
startPage = new Integer(startPageArg);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
// NOTE: use default startPage
|
||||
}
|
||||
String itemsPerPageArg = req.getParameter("c");
|
||||
int itemsPerPage = DEFAULT_ITEMS_PER_PAGE;
|
||||
try
|
||||
{
|
||||
itemsPerPage = new Integer(itemsPerPageArg);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
// NOTE: use default itemsPerPage
|
||||
}
|
||||
Locale locale = I18NUtil.getLocale();
|
||||
String language = req.getParameter("l");
|
||||
if (language != null && language.length() > 0)
|
||||
{
|
||||
// NOTE: Simple conversion from XML Language Id to Java Locale Id
|
||||
locale = new Locale(language.replace("-", "_"));
|
||||
}
|
||||
|
||||
//
|
||||
// execute the search
|
||||
//
|
||||
|
||||
SearchResult results = search(searchTerms, startPage, itemsPerPage, locale, req);
|
||||
|
||||
//
|
||||
// create model
|
||||
//
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("search", results);
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the search
|
||||
*
|
||||
* @param searchTerms
|
||||
* @param startPage
|
||||
* @return
|
||||
*/
|
||||
private SearchResult search(String searchTerms, int startPage, int itemsPerPage, Locale locale, WebScriptRequest req)
|
||||
{
|
||||
SearchResult searchResult = null;
|
||||
ResultSet results = null;
|
||||
|
||||
try
|
||||
{
|
||||
// construct search statement
|
||||
String[] terms = searchTerms.split(" ");
|
||||
Map<String, Object> statementModel = new HashMap<String, Object>(7, 1.0f);
|
||||
statementModel.put("args", createArgs(req));
|
||||
statementModel.put("terms", terms);
|
||||
Writer queryWriter = new StringWriter(1024);
|
||||
renderFormatTemplate(QUERY_FORMAT, statementModel, queryWriter);
|
||||
String query = queryWriter.toString();
|
||||
|
||||
// execute query
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Search parameters: searchTerms=" + searchTerms + ", startPage=" + startPage + ", itemsPerPage=" + itemsPerPage + ", search locale=" + locale.toString());
|
||||
logger.debug("Issuing lucene search: " + query);
|
||||
}
|
||||
|
||||
SearchParameters parameters = new SearchParameters();
|
||||
parameters.addStore(SEARCH_STORE);
|
||||
parameters.setLanguage(SearchService.LANGUAGE_LUCENE);
|
||||
parameters.setQuery(query);
|
||||
if (locale != null)
|
||||
{
|
||||
parameters.addLocale(locale);
|
||||
}
|
||||
results = searchService.query(parameters);
|
||||
int totalResults = results.length();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Results: " + totalResults + " rows (limited: " + results.getResultSetMetaData().getLimitedBy() + ")");
|
||||
|
||||
// are we out-of-range
|
||||
int totalPages = (totalResults / itemsPerPage);
|
||||
totalPages += (totalResults % itemsPerPage != 0) ? 1 : 0;
|
||||
if (totalPages != 0 && (startPage < 1 || startPage > totalPages))
|
||||
{
|
||||
throw new WebScriptException("Start page " + startPage + " is outside boundary of " + totalPages + " pages");
|
||||
}
|
||||
|
||||
// construct search result
|
||||
searchResult = new SearchResult();
|
||||
searchResult.setSearchTerms(searchTerms);
|
||||
searchResult.setLocale(locale);
|
||||
searchResult.setItemsPerPage(itemsPerPage);
|
||||
searchResult.setStartPage(startPage);
|
||||
searchResult.setTotalResults(totalResults);
|
||||
if (totalResults == 0)
|
||||
{
|
||||
searchResult.setTotalPages(0);
|
||||
searchResult.setStartIndex(0);
|
||||
searchResult.setTotalPageItems(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
searchResult.setTotalPages(totalPages);
|
||||
searchResult.setStartIndex(((startPage -1) * itemsPerPage) + 1);
|
||||
searchResult.setTotalPageItems(Math.min(itemsPerPage, totalResults - searchResult.getStartIndex() + 1));
|
||||
}
|
||||
SearchTemplateNode[] nodes = new SearchTemplateNode[searchResult.getTotalPageItems()];
|
||||
for (int i = 0; i < searchResult.getTotalPageItems(); i++)
|
||||
{
|
||||
NodeRef node = results.getNodeRef(i + searchResult.getStartIndex() - 1);
|
||||
float score = results.getScore(i + searchResult.getStartIndex() - 1);
|
||||
nodes[i] = new SearchTemplateNode(node, score);
|
||||
}
|
||||
searchResult.setResults(nodes);
|
||||
return searchResult;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null)
|
||||
{
|
||||
results.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Result
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public static class SearchResult
|
||||
{
|
||||
private String id;
|
||||
private String searchTerms;
|
||||
private Locale locale;
|
||||
private int itemsPerPage;
|
||||
private int totalPages;
|
||||
private int totalResults;
|
||||
private int totalPageItems;
|
||||
private int startPage;
|
||||
private int startIndex;
|
||||
private SearchTemplateNode[] results;
|
||||
|
||||
|
||||
public int getItemsPerPage()
|
||||
{
|
||||
return itemsPerPage;
|
||||
}
|
||||
|
||||
/*package*/ void setItemsPerPage(int itemsPerPage)
|
||||
{
|
||||
this.itemsPerPage = itemsPerPage;
|
||||
}
|
||||
|
||||
public TemplateNode[] getResults()
|
||||
{
|
||||
return results;
|
||||
}
|
||||
|
||||
/*package*/ void setResults(SearchTemplateNode[] results)
|
||||
{
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public int getStartIndex()
|
||||
{
|
||||
return startIndex;
|
||||
}
|
||||
|
||||
/*package*/ void setStartIndex(int startIndex)
|
||||
{
|
||||
this.startIndex = startIndex;
|
||||
}
|
||||
|
||||
public int getStartPage()
|
||||
{
|
||||
return startPage;
|
||||
}
|
||||
|
||||
/*package*/ void setStartPage(int startPage)
|
||||
{
|
||||
this.startPage = startPage;
|
||||
}
|
||||
|
||||
public int getTotalPageItems()
|
||||
{
|
||||
return totalPageItems;
|
||||
}
|
||||
|
||||
/*package*/ void setTotalPageItems(int totalPageItems)
|
||||
{
|
||||
this.totalPageItems = totalPageItems;
|
||||
}
|
||||
|
||||
public int getTotalPages()
|
||||
{
|
||||
return totalPages;
|
||||
}
|
||||
|
||||
/*package*/ void setTotalPages(int totalPages)
|
||||
{
|
||||
this.totalPages = totalPages;
|
||||
}
|
||||
|
||||
public int getTotalResults()
|
||||
{
|
||||
return totalResults;
|
||||
}
|
||||
|
||||
/*package*/ void setTotalResults(int totalResults)
|
||||
{
|
||||
this.totalResults = totalResults;
|
||||
}
|
||||
|
||||
public String getSearchTerms()
|
||||
{
|
||||
return searchTerms;
|
||||
}
|
||||
|
||||
/*package*/ void setSearchTerms(String searchTerms)
|
||||
{
|
||||
this.searchTerms = searchTerms;
|
||||
}
|
||||
|
||||
public Locale getLocale()
|
||||
{
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return XML 1.0 Language Identification
|
||||
*/
|
||||
public String getLocaleId()
|
||||
{
|
||||
return locale.toString().replace('_', '-');
|
||||
}
|
||||
|
||||
/*package*/ void setLocale(Locale locale)
|
||||
{
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public String getId()
|
||||
{
|
||||
if (id == null)
|
||||
{
|
||||
id = GUID.generate();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search result row template node
|
||||
*/
|
||||
public class SearchTemplateNode extends TemplateNode
|
||||
{
|
||||
protected final static String URL = "/api/node/content/{0}/{1}/{2}/{3}";
|
||||
|
||||
private static final long serialVersionUID = -1791913270786140012L;
|
||||
private float score;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param nodeRef
|
||||
* @param score
|
||||
*/
|
||||
public SearchTemplateNode(NodeRef nodeRef, float score)
|
||||
{
|
||||
super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver());
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result row score
|
||||
*
|
||||
* @return score
|
||||
*/
|
||||
public float getScore()
|
||||
{
|
||||
return score;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.template.BaseContentNode#getUrl()
|
||||
*/
|
||||
@Override
|
||||
public String getUrl()
|
||||
{
|
||||
return MessageFormat.format(URL, new Object[] {
|
||||
getNodeRef().getStoreRef().getProtocol(),
|
||||
getNodeRef().getStoreRef().getIdentifier(),
|
||||
getNodeRef().getId(),
|
||||
URLEncoder.encode(getName()) } );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
97
source/java/org/alfresco/repo/web/scripts/bean/Login.java
Normal file
97
source/java/org/alfresco/repo/web/scripts/bean/Login.java
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Login and establish a ticket
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class Login extends DeclarativeWebScript
|
||||
{
|
||||
// dependencies
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
/**
|
||||
* @param authenticationService
|
||||
*/
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
// extract username and password
|
||||
String username = req.getParameter("u");
|
||||
if (username == null || username.length() == 0)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified");
|
||||
}
|
||||
String password = req.getParameter("pw");
|
||||
if (password == null)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// get ticket
|
||||
authenticationService.authenticate(username, password.toCharArray());
|
||||
|
||||
// add ticket to model for javascript and template access
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("ticket", authenticationService.getCurrentTicket());
|
||||
return model;
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Login failed");
|
||||
}
|
||||
finally
|
||||
{
|
||||
authenticationService.clearCurrentSecurityContext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.TicketComponent;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Login Ticket
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class LoginTicket extends DeclarativeWebScript
|
||||
{
|
||||
// dependencies
|
||||
private TicketComponent ticketComponent;
|
||||
|
||||
/**
|
||||
* @param ticketComponent
|
||||
*/
|
||||
public void setTicketComponent(TicketComponent ticketComponent)
|
||||
{
|
||||
this.ticketComponent = ticketComponent;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
// retrieve ticket from request and current ticket
|
||||
String ticket = req.getExtensionPath();
|
||||
if (ticket == null && ticket.length() == 0)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Ticket not specified");
|
||||
}
|
||||
|
||||
// construct model for ticket
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("ticket", ticket);
|
||||
|
||||
try
|
||||
{
|
||||
String ticketUser = ticketComponent.validateTicket(ticket);
|
||||
|
||||
// do not go any further if tickets are different
|
||||
if (!AuthenticationUtil.getCurrentUserName().equals(ticketUser))
|
||||
{
|
||||
status.setRedirect(true);
|
||||
status.setCode(HttpServletResponse.SC_NOT_FOUND);
|
||||
status.setMessage("Ticket not found");
|
||||
}
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
status.setRedirect(true);
|
||||
status.setCode(HttpServletResponse.SC_NOT_FOUND);
|
||||
status.setMessage("Ticket not found");
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.TicketComponent;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Delete Login Ticket
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class LoginTicketDelete extends DeclarativeWebScript
|
||||
{
|
||||
// dependencies
|
||||
private AuthenticationService authenticationService;
|
||||
private TicketComponent ticketComponent;
|
||||
|
||||
/**
|
||||
* @param ticketComponent
|
||||
*/
|
||||
public void setTicketComponent(TicketComponent ticketComponent)
|
||||
{
|
||||
this.ticketComponent = ticketComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authenticationService
|
||||
*/
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
// retrieve ticket from request and current ticket
|
||||
String ticket = req.getExtensionPath();
|
||||
if (ticket == null && ticket.length() == 0)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Ticket not specified");
|
||||
}
|
||||
|
||||
// construct model for ticket
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("ticket", ticket);
|
||||
|
||||
try
|
||||
{
|
||||
String ticketUser = ticketComponent.validateTicket(ticket);
|
||||
|
||||
// do not go any further if tickets are different
|
||||
if (!AuthenticationUtil.getCurrentUserName().equals(ticketUser))
|
||||
{
|
||||
status.setCode(HttpServletResponse.SC_NOT_FOUND);
|
||||
status.setMessage("Ticket not found");
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete the ticket
|
||||
authenticationService.invalidateTicket(ticket);
|
||||
status.setMessage("Deleted Ticket " + ticket);
|
||||
}
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
status.setCode(HttpServletResponse.SC_NOT_FOUND);
|
||||
status.setMessage("Ticket not found");
|
||||
}
|
||||
|
||||
status.setRedirect(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement;
|
||||
import org.alfresco.web.scripts.DeclarativeWebScript;
|
||||
import org.alfresco.web.scripts.Status;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* List of (server-side) registered Search Engines
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class SearchEngines extends DeclarativeWebScript
|
||||
{
|
||||
// url argument values
|
||||
public static final String URL_ARG_DESCRIPTION = "description";
|
||||
public static final String URL_ARG_TEMPLATE = "template";
|
||||
public static final String URL_ARG_ALL = "all";
|
||||
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(SearchEngines.class);
|
||||
|
||||
// dependencies
|
||||
protected ConfigService configService;
|
||||
protected SearchProxy searchProxy;
|
||||
|
||||
/**
|
||||
* @param configService
|
||||
*/
|
||||
public void setConfigService(ConfigService configService)
|
||||
{
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchProxy
|
||||
*/
|
||||
public void setSearchProxy(SearchProxy searchProxy)
|
||||
{
|
||||
this.searchProxy = searchProxy;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
String urlType = req.getParameter("type");
|
||||
if (urlType == null || urlType.length() == 0)
|
||||
{
|
||||
urlType = URL_ARG_DESCRIPTION;
|
||||
}
|
||||
else if (!urlType.equals(URL_ARG_DESCRIPTION) && !urlType.equals(URL_ARG_TEMPLATE) && !urlType.equals(URL_ARG_ALL))
|
||||
{
|
||||
urlType = URL_ARG_DESCRIPTION;
|
||||
}
|
||||
|
||||
//
|
||||
// retrieve open search engines configuration
|
||||
//
|
||||
|
||||
Set<UrlTemplate> urls = getUrls(urlType);
|
||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
||||
model.put("urltype", urlType);
|
||||
model.put("engines", urls);
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve registered search engines
|
||||
*
|
||||
* @return set of search engines
|
||||
*/
|
||||
private Set<UrlTemplate> getUrls(String urlType)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Search Engine parameters: urltype=" + urlType);
|
||||
|
||||
Set<UrlTemplate> urls = new HashSet<UrlTemplate>();
|
||||
Config config = configService.getConfig("OpenSearch");
|
||||
|
||||
OpenSearchConfigElement searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID);
|
||||
for (OpenSearchConfigElement.EngineConfig engineConfig : searchConfig.getEngines())
|
||||
{
|
||||
Map<String, String> engineUrls = engineConfig.getUrls();
|
||||
for (Map.Entry<String, String> engineUrl : engineUrls.entrySet())
|
||||
{
|
||||
String type = engineUrl.getKey();
|
||||
String url = searchProxy.createUrl(engineConfig, type);
|
||||
|
||||
if ((urlType.equals(URL_ARG_ALL)) ||
|
||||
(urlType.equals(URL_ARG_DESCRIPTION) && type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) ||
|
||||
(urlType.equals(URL_ARG_TEMPLATE) && !type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)))
|
||||
{
|
||||
String label = engineConfig.getLabel();
|
||||
String labelId = engineConfig.getLabelId();
|
||||
if (labelId != null && labelId.length() > 0)
|
||||
{
|
||||
String i18nLabel = I18NUtil.getMessage(labelId);
|
||||
if (i18nLabel == null && label == null)
|
||||
{
|
||||
label = (i18nLabel == null) ? "$$" + labelId + "$$" : i18nLabel;
|
||||
}
|
||||
}
|
||||
urls.add(new UrlTemplate(label, type, url));
|
||||
}
|
||||
|
||||
// TODO: Extract URL templates from OpenSearch description
|
||||
else if (urlType.equals(URL_ARG_TEMPLATE) &&
|
||||
type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION))
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Retrieved " + urls.size() + " engine registrations");
|
||||
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Model object for representing a registered search engine
|
||||
*/
|
||||
public static class UrlTemplate
|
||||
{
|
||||
private String type;
|
||||
private String label;
|
||||
private String url;
|
||||
private UrlTemplate engine;
|
||||
|
||||
public UrlTemplate(String label, String type, String url)
|
||||
{
|
||||
this.label = label;
|
||||
this.type = type;
|
||||
this.url = url;
|
||||
this.engine = null;
|
||||
}
|
||||
|
||||
public UrlTemplate(String label, String type, String url, UrlTemplate engine)
|
||||
{
|
||||
this(label, type, url);
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getUrlType()
|
||||
{
|
||||
return (type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION) ? "description" : "template");
|
||||
}
|
||||
|
||||
public UrlTemplate getEngine()
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
317
source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java
Normal file
317
source/java/org/alfresco/repo/web/scripts/bean/SearchProxy.java
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.bean;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.config.Config;
|
||||
import org.alfresco.config.ConfigService;
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig;
|
||||
import org.alfresco.web.scripts.AbstractWebScript;
|
||||
import org.alfresco.web.scripts.FormatRegistry;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.WebScriptRequest;
|
||||
import org.alfresco.web.scripts.WebScriptResponse;
|
||||
import org.alfresco.web.scripts.servlet.HTTPProxy;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.dom4j.Attribute;
|
||||
import org.dom4j.Document;
|
||||
import org.dom4j.DocumentException;
|
||||
import org.dom4j.Element;
|
||||
import org.dom4j.XPath;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.SAXReader;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco OpenSearch Proxy Service
|
||||
*
|
||||
* Provides the ability to submit a request to a registered search engine
|
||||
* via the Alfresco server.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class SearchProxy extends AbstractWebScript implements InitializingBean
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(SearchProxy.class);
|
||||
|
||||
// dependencies
|
||||
protected FormatRegistry formatRegistry;
|
||||
protected ConfigService configService;
|
||||
protected OpenSearchConfigElement searchConfig;
|
||||
protected String proxyPath;
|
||||
|
||||
/**
|
||||
* @param formatRegistry
|
||||
*/
|
||||
public void setFormatRegistry(FormatRegistry formatRegistry)
|
||||
{
|
||||
this.formatRegistry = formatRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param configService
|
||||
*/
|
||||
public void setConfigService(ConfigService configService)
|
||||
{
|
||||
this.configService = configService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
Config config = configService.getConfig("OpenSearch");
|
||||
searchConfig = (OpenSearchConfigElement)config.getConfigElement(OpenSearchConfigElement.CONFIG_ELEMENT_ID);
|
||||
if (searchConfig == null)
|
||||
{
|
||||
throw new WebScriptException("OpenSearch configuration not found");
|
||||
}
|
||||
ProxyConfig proxyConfig = searchConfig.getProxy();
|
||||
if (proxyConfig == null)
|
||||
{
|
||||
throw new WebScriptException("OpenSearch proxy configuration not found");
|
||||
}
|
||||
proxyPath = proxyConfig.getUrl();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res)
|
||||
throws IOException
|
||||
{
|
||||
String extensionPath = req.getExtensionPath();
|
||||
String[] extensionPaths = extensionPath.split("/");
|
||||
if (extensionPaths.length != 2)
|
||||
{
|
||||
throw new WebScriptException("OpenSearch engine has not been specified as /{engine}/{format}");
|
||||
}
|
||||
|
||||
// retrieve search engine configuration
|
||||
String engine = extensionPaths[0];
|
||||
EngineConfig engineConfig = searchConfig.getEngine(engine);
|
||||
if (engineConfig == null)
|
||||
{
|
||||
throw new WebScriptException("OpenSearch engine '" + engine + "' does not exist");
|
||||
}
|
||||
|
||||
// retrieve engine url as specified by format
|
||||
String format = extensionPaths[1];
|
||||
String mimetype = formatRegistry.getMimeType(null, format);
|
||||
if (mimetype == null)
|
||||
{
|
||||
throw new WebScriptException("Format '" + format + "' does not map to a registered mimetype");
|
||||
}
|
||||
Map<String, String> engineUrls = engineConfig.getUrls();
|
||||
String engineUrl = engineUrls.get(mimetype);
|
||||
if (engineUrl == null)
|
||||
{
|
||||
throw new WebScriptException("Url mimetype '" + mimetype + "' does not exist for engine '" + engine + "'");
|
||||
}
|
||||
|
||||
// replace template url arguments with actual arguments specified on request
|
||||
int engineUrlArgIdx = engineUrl.indexOf("?");
|
||||
if (engineUrlArgIdx != -1)
|
||||
{
|
||||
engineUrl = engineUrl.substring(0, engineUrlArgIdx);
|
||||
}
|
||||
if (req.getQueryString() != null)
|
||||
{
|
||||
engineUrl += "?" + req.getQueryString();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Mapping engine '" + engine + "' (mimetype '" + mimetype + "') to url '" + engineUrl + "'");
|
||||
|
||||
// issue request against search engine
|
||||
// NOTE: This web script must be executed in a HTTP servlet environment
|
||||
if (!(res instanceof WebScriptServletResponse))
|
||||
{
|
||||
throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment");
|
||||
}
|
||||
HttpServletResponse servletRes = ((WebScriptServletResponse)res).getHttpServletResponse();
|
||||
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), engine, engineUrl, servletRes);
|
||||
proxy.service();
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenSearch HTTPProxy
|
||||
*
|
||||
* This proxy remaps OpenSearch links (e.g. previous, next) found in search results.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
private class SearchEngineHttpProxy extends HTTPProxy
|
||||
{
|
||||
private final static String ATOM_NS_URI = "http://www.w3.org/2005/Atom";
|
||||
private final static String ATOM_NS_PREFIX = "atom";
|
||||
private final static String ATOM_LINK_XPATH = "atom:link[@rel=\"first\" or @rel=\"last\" or @rel=\"next\" or @rel=\"previous\" or @rel=\"self\" or @rel=\"alternate\"]";
|
||||
private String engine;
|
||||
private String rootPath;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param requestUrl
|
||||
* @param response
|
||||
* @throws MalformedURLException
|
||||
*/
|
||||
public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response)
|
||||
throws MalformedURLException
|
||||
{
|
||||
super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response);
|
||||
this.engine = engine;
|
||||
this.rootPath = rootPath;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.app.servlet.HTTPProxy#writeResponse(java.io.InputStream, java.io.OutputStream)
|
||||
*/
|
||||
@Override
|
||||
protected void writeResponse(InputStream input, OutputStream output)
|
||||
throws IOException
|
||||
{
|
||||
if (response.getContentType().startsWith(MimetypeMap.MIMETYPE_ATOM) ||
|
||||
response.getContentType().startsWith(MimetypeMap.MIMETYPE_RSS))
|
||||
{
|
||||
// Only post-process ATOM and RSS feeds
|
||||
// Replace all navigation links with "proxied" versions
|
||||
SAXReader reader = new SAXReader();
|
||||
try
|
||||
{
|
||||
Document document = reader.read(input);
|
||||
Element rootElement = document.getRootElement();
|
||||
|
||||
XPath xpath = rootElement.createXPath(ATOM_LINK_XPATH);
|
||||
Map<String,String> uris = new HashMap<String,String>();
|
||||
uris.put(ATOM_NS_PREFIX, ATOM_NS_URI);
|
||||
xpath.setNamespaceURIs(uris);
|
||||
|
||||
List nodes = xpath.selectNodes(rootElement);
|
||||
Iterator iter = nodes.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
Element element = (Element)iter.next();
|
||||
Attribute hrefAttr = element.attribute("href");
|
||||
String mimetype = element.attributeValue("type");
|
||||
if (mimetype == null || mimetype.length() == 0)
|
||||
{
|
||||
mimetype = MimetypeMap.MIMETYPE_HTML;
|
||||
}
|
||||
String url = createUrl(engine, hrefAttr.getValue(), mimetype);
|
||||
if (url.startsWith("/"))
|
||||
{
|
||||
url = rootPath + url;
|
||||
}
|
||||
hrefAttr.setValue(url);
|
||||
}
|
||||
|
||||
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
|
||||
XMLWriter writer = new XMLWriter(output, outputFormat);
|
||||
writer.write(rootElement);
|
||||
writer.flush();
|
||||
}
|
||||
catch(DocumentException e)
|
||||
{
|
||||
throw new IOException(e.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
super.writeResponse(input, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a "proxied" search engine url
|
||||
*
|
||||
* @param engine engine name (as identified by <engine proxy="<name>">)
|
||||
* @param mimetype url to proxy (as identified by mimetype)
|
||||
* @return "proxied" url
|
||||
*/
|
||||
public String createUrl(OpenSearchConfigElement.EngineConfig engine, String mimetype)
|
||||
{
|
||||
Map<String, String> urls = engine.getUrls();
|
||||
String url = urls.get(mimetype);
|
||||
if (url != null)
|
||||
{
|
||||
String proxy = engine.getProxy();
|
||||
if (proxy != null && !mimetype.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION))
|
||||
{
|
||||
url = createUrl(proxy, url, mimetype);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a "proxied" search engine url
|
||||
*
|
||||
* @param engine engine name (as identified by <engine proxy="<name>">)
|
||||
* @param url engine url
|
||||
* @param mimetype mimetype of url
|
||||
* @return "proxied" url
|
||||
*/
|
||||
public String createUrl(String engine, String url, String mimetype)
|
||||
{
|
||||
String format = formatRegistry.getFormat(null, mimetype);
|
||||
if (format == null)
|
||||
{
|
||||
throw new WebScriptException("Mimetype '" + mimetype + "' is not registered.");
|
||||
}
|
||||
|
||||
String proxyUrl = null;
|
||||
int argIdx = url.indexOf("?");
|
||||
if (argIdx == -1)
|
||||
{
|
||||
proxyUrl = proxyPath + "/" + engine + "/" + format;
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyUrl = proxyPath + "/" + engine + "/" + format + url.substring(argIdx);
|
||||
}
|
||||
return proxyUrl;
|
||||
}
|
||||
}
|
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.ConfigException;
|
||||
import org.alfresco.config.element.ConfigElementAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* Custom config element that represents the config data for open search
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class OpenSearchConfigElement extends ConfigElementAdapter
|
||||
{
|
||||
public static final String CONFIG_ELEMENT_ID = "opensearch";
|
||||
|
||||
private ProxyConfig proxy;
|
||||
private Set<EngineConfig> engines = new HashSet<EngineConfig>(8, 10f);
|
||||
private Map<String, EngineConfig> enginesByProxy = new HashMap<String, EngineConfig>();
|
||||
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public OpenSearchConfigElement()
|
||||
{
|
||||
super(CONFIG_ELEMENT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param name Name of the element this config element represents
|
||||
*/
|
||||
public OpenSearchConfigElement(String name)
|
||||
{
|
||||
super(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.config.ConfigElement#getChildren()
|
||||
*/
|
||||
public List<ConfigElement> getChildren()
|
||||
{
|
||||
throw new ConfigException("Reading the open search config via the generic interfaces is not supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.alfresco.config.ConfigElement#combine(org.alfresco.config.ConfigElement)
|
||||
*/
|
||||
public ConfigElement combine(ConfigElement configElement)
|
||||
{
|
||||
OpenSearchConfigElement newElement = (OpenSearchConfigElement) configElement;
|
||||
OpenSearchConfigElement combinedElement = new OpenSearchConfigElement();
|
||||
|
||||
// add all the plugins from this element
|
||||
for (EngineConfig plugin : this.getEngines())
|
||||
{
|
||||
combinedElement.addEngine(plugin);
|
||||
}
|
||||
|
||||
// add all the plugins from the given element
|
||||
for (EngineConfig plugin : newElement.getEngines())
|
||||
{
|
||||
combinedElement.addEngine(plugin);
|
||||
}
|
||||
|
||||
// set the proxy configuration
|
||||
ProxyConfig proxyConfig = this.getProxy();
|
||||
if (proxyConfig != null)
|
||||
{
|
||||
combinedElement.setProxy(proxyConfig);
|
||||
}
|
||||
|
||||
return combinedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the proxy configuration
|
||||
*
|
||||
* @param proxyConfig
|
||||
*/
|
||||
/*package*/ void setProxy(ProxyConfig proxyConfig)
|
||||
{
|
||||
this.proxy = proxyConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the proxy configuration
|
||||
*
|
||||
* @return The proxy configuration
|
||||
*/
|
||||
public ProxyConfig getProxy()
|
||||
{
|
||||
return this.proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a set of the engines
|
||||
*/
|
||||
public Set<EngineConfig> getEngines()
|
||||
{
|
||||
return this.engines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param proxy name of engine proxy
|
||||
* @return associated engine config (or null, if none registered against proxy)
|
||||
*/
|
||||
public EngineConfig getEngine(String proxy)
|
||||
{
|
||||
return this.enginesByProxy.get(proxy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an engine
|
||||
*
|
||||
* @param pluginConfig A pre-configured engine config object
|
||||
*/
|
||||
/*package*/ void addEngine(EngineConfig engineConfig)
|
||||
{
|
||||
this.engines.add(engineConfig);
|
||||
String proxy = engineConfig.getProxy();
|
||||
if (proxy != null && proxy.length() > 0)
|
||||
{
|
||||
this.enginesByProxy.put(proxy, engineConfig);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class representing the configuration of an OpenSearch engine
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public static class EngineConfig
|
||||
{
|
||||
protected String label;
|
||||
protected String labelId;
|
||||
protected String proxy;
|
||||
protected Map<String, String> urls = new HashMap<String, String>(8, 10f);
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param label
|
||||
* @param labelId
|
||||
*/
|
||||
public EngineConfig(String label, String labelId)
|
||||
{
|
||||
if ((label == null || label.length() == 0) && (labelId == null || labelId.length() == 0))
|
||||
{
|
||||
throw new IllegalArgumentException("'label' or 'label-id' must be specified");
|
||||
}
|
||||
this.label = label;
|
||||
this.labelId = labelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param label
|
||||
* @param labelId
|
||||
* @param proxy
|
||||
*/
|
||||
public EngineConfig(String label, String labelId, String proxy)
|
||||
{
|
||||
this(label, labelId);
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return I18N label id
|
||||
*/
|
||||
public String getLabelId()
|
||||
{
|
||||
return labelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return label
|
||||
*/
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return proxy
|
||||
*/
|
||||
public String getProxy()
|
||||
{
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the urls supported by this engine
|
||||
*
|
||||
* @return urls
|
||||
*/
|
||||
public Map<String, String> getUrls()
|
||||
{
|
||||
return urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a url
|
||||
*
|
||||
* @param pluginConfig A pre-configured plugin config object
|
||||
*/
|
||||
/*package*/ void addUrl(String mimetype, String uri)
|
||||
{
|
||||
this.urls.put(mimetype, uri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class representing the configuration of the OpenSearch proxy
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public static class ProxyConfig
|
||||
{
|
||||
protected String url;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param url
|
||||
*/
|
||||
public ProxyConfig(String url)
|
||||
{
|
||||
if (url == null || url.length() == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("'url' must be specified");
|
||||
}
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return url
|
||||
*/
|
||||
public String getUrl()
|
||||
{
|
||||
return url;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.config;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.alfresco.config.ConfigElement;
|
||||
import org.alfresco.config.ConfigException;
|
||||
import org.alfresco.config.xml.elementreader.ConfigElementReader;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.EngineConfig;
|
||||
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement.ProxyConfig;
|
||||
import org.dom4j.Element;
|
||||
|
||||
|
||||
/**
|
||||
* Custom element reader to parse config for the open search
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class OpenSearchElementReader implements ConfigElementReader
|
||||
{
|
||||
public static final String ELEMENT_OPENSEARCH = "opensearch";
|
||||
public static final String ELEMENT_ENGINES = "engines";
|
||||
public static final String ELEMENT_ENGINE = "engine";
|
||||
public static final String ELEMENT_URL = "url";
|
||||
public static final String ELEMENT_PROXY = "proxy";
|
||||
public static final String ATTR_TYPE = "type";
|
||||
public static final String ATTR_LABEL = "label";
|
||||
public static final String ATTR_LABEL_ID = "label-id";
|
||||
public static final String ATTR_PROXY = "proxy";
|
||||
|
||||
|
||||
/**
|
||||
* @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public ConfigElement parse(Element element)
|
||||
{
|
||||
OpenSearchConfigElement configElement = null;
|
||||
|
||||
if (element != null)
|
||||
{
|
||||
String elementName = element.getName();
|
||||
if (elementName.equals(ELEMENT_OPENSEARCH) == false)
|
||||
{
|
||||
throw new ConfigException("OpenSearchElementReader can only parse " + ELEMENT_OPENSEARCH
|
||||
+ "elements, the element passed was '" + elementName + "'");
|
||||
}
|
||||
|
||||
// go through the registered engines
|
||||
configElement = new OpenSearchConfigElement();
|
||||
Element pluginsElem = element.element(ELEMENT_ENGINES);
|
||||
if (pluginsElem != null)
|
||||
{
|
||||
Iterator<Element> engines = pluginsElem.elementIterator(ELEMENT_ENGINE);
|
||||
while(engines.hasNext())
|
||||
{
|
||||
// construct engine
|
||||
Element engineElem = engines.next();
|
||||
String label = engineElem.attributeValue(ATTR_LABEL);
|
||||
String labelId = engineElem.attributeValue(ATTR_LABEL_ID);
|
||||
String proxy = engineElem.attributeValue(ATTR_PROXY);
|
||||
EngineConfig engineCfg = new EngineConfig(label, labelId, proxy);
|
||||
|
||||
// construct urls for engine
|
||||
Iterator<Element> urlsConfig = engineElem.elementIterator(ELEMENT_URL);
|
||||
while (urlsConfig.hasNext())
|
||||
{
|
||||
Element urlConfig = urlsConfig.next();
|
||||
String type = urlConfig.attributeValue(ATTR_TYPE);
|
||||
String url = urlConfig.getTextTrim();
|
||||
engineCfg.addUrl(type, url);
|
||||
}
|
||||
|
||||
// register engine config
|
||||
configElement.addEngine(engineCfg);
|
||||
}
|
||||
}
|
||||
|
||||
// extract proxy configuration
|
||||
String url = null;
|
||||
Element proxyElem = element.element(ELEMENT_PROXY);
|
||||
if (proxyElem != null)
|
||||
{
|
||||
Element urlElem = proxyElem.element(ELEMENT_URL);
|
||||
if (urlElem != null)
|
||||
{
|
||||
url = urlElem.getTextTrim();
|
||||
ProxyConfig proxyCfg = new ProxyConfig(url);
|
||||
configElement.setProxy(proxyCfg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return configElement;
|
||||
}
|
||||
}
|
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.facebook;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.web.scripts.Authenticator;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
||||
import org.alfresco.web.scripts.facebook.FacebookServletRequest;
|
||||
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Web Script Authenticator that supports Facebook authentication
|
||||
* mechanism.
|
||||
*
|
||||
* Upon success, the request is authenticated as the Facebook User Id.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class FacebookAuthenticatorFactory implements ServletAuthenticatorFactory
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(FacebookAuthenticator.class);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(org.alfresco.web.scripts.servlet.WebScriptServletRequest, org.alfresco.web.scripts.servlet.WebScriptServletResponse)
|
||||
*/
|
||||
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
|
||||
{
|
||||
if (!(req instanceof FacebookServletRequest))
|
||||
{
|
||||
throw new WebScriptException("Facebook request is required; instead a " + req.getClass().getName() + " has been provided");
|
||||
}
|
||||
return new FacebookAuthenticator((FacebookServletRequest)req, res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Web Script Authenticator that supports Facebook authentication
|
||||
* mechanism.
|
||||
*
|
||||
* Upon success, the request is authenticated as the Facebook User Id.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class FacebookAuthenticator implements Authenticator
|
||||
{
|
||||
|
||||
// FBML for Facebook login redirect
|
||||
private static final String LOGIN_REDIRECT = "<fb:redirect url=\"http://www.facebook.com/login.php?api_key=%s&v=1.0%s\">";
|
||||
|
||||
|
||||
// dependencies
|
||||
private FacebookServletRequest fbReq;
|
||||
private WebScriptServletResponse fbRes;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param authenticationService
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public FacebookAuthenticator(FacebookServletRequest req, WebScriptServletResponse res)
|
||||
{
|
||||
this.fbReq = req;
|
||||
this.fbRes = res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
||||
*/
|
||||
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
String sessionKey = fbReq.getSessionKey();
|
||||
String user = fbReq.getUserId();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("fb_sig_session_key = '" + sessionKey + "'");
|
||||
logger.debug("fb_sig_user = '" + user + "'");
|
||||
}
|
||||
|
||||
if ((sessionKey == null || sessionKey.length() == 0) || (user == null || user.length() == 0))
|
||||
{
|
||||
// session has not been established, redirect to login
|
||||
|
||||
String apiKey = fbReq.getApiKey();
|
||||
String canvas = (fbReq.isInCanvas()) ? "&canvas" : "";
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("fb_sig_api_key = '" + apiKey + "'");
|
||||
logger.debug("fb_sig_in_canvas = '" + canvas + "'");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
String redirect = String.format(LOGIN_REDIRECT, apiKey, canvas);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Facebook session not established; redirecting via " + redirect);
|
||||
|
||||
fbRes.getWriter().write(redirect);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new WebScriptException("Redirect to login failed", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Facebook session established; authenticating as user " + user);
|
||||
|
||||
// session has been established, authenticate as Facebook user id
|
||||
AuthenticationUtil.setCurrentUser(user);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.portlet;
|
||||
|
||||
import javax.portlet.RenderRequest;
|
||||
import javax.portlet.RenderResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.web.scripts.Authenticator;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
||||
import org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory;
|
||||
import org.alfresco.web.scripts.portlet.WebScriptPortletRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Portlet authenticator
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JSR168PortletAuthenticatorFactory implements PortletAuthenticatorFactory
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(JSR168PortletAuthenticatorFactory.class);
|
||||
|
||||
// dependencies
|
||||
private AuthenticationService unprotAuthenticationService;
|
||||
private TransactionService txnService;
|
||||
|
||||
/**
|
||||
* @param authenticationService
|
||||
*/
|
||||
public void setUnprotAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.unprotAuthenticationService = authenticationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transactionService
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.txnService = transactionService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
|
||||
*/
|
||||
public Authenticator create(RenderRequest req, RenderResponse res)
|
||||
{
|
||||
return new JSR168PortletAuthenticator(req, res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Portlet authenticator
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class JSR168PortletAuthenticator implements Authenticator
|
||||
{
|
||||
// dependencies
|
||||
private RenderRequest req;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param authenticationService
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public JSR168PortletAuthenticator(RenderRequest req, RenderResponse res)
|
||||
{
|
||||
this.req = req;
|
||||
}
|
||||
|
||||
/*(non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
|
||||
*/
|
||||
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
// first look for the username key in the session - we add this by hand for some portals
|
||||
// when the WebScriptPortletRequest is created
|
||||
String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME);
|
||||
if (portalUser == null)
|
||||
{
|
||||
portalUser = req.getRemoteUser();
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("JSR-168 Remote user: " + portalUser);
|
||||
}
|
||||
|
||||
if (isGuest || portalUser == null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating as Guest");
|
||||
|
||||
// authenticate as guest
|
||||
AuthenticationUtil.setCurrentUser(AuthenticationUtil.getGuestUserName());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating as user " + portalUser);
|
||||
|
||||
UserTransaction txn = null;
|
||||
try
|
||||
{
|
||||
txn = txnService.getUserTransaction();
|
||||
txn.begin();
|
||||
|
||||
if (!unprotAuthenticationService.authenticationExists(portalUser))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "User " + portalUser + " is not a known Alfresco user");
|
||||
}
|
||||
AuthenticationUtil.setCurrentUser(portalUser);
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Error authenticating user: " + portalUser, err);
|
||||
}
|
||||
finally
|
||||
{
|
||||
try
|
||||
{
|
||||
if (txn != null)
|
||||
{
|
||||
txn.rollback();
|
||||
}
|
||||
}
|
||||
catch (Exception tex)
|
||||
{
|
||||
// nothing useful we can do with this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.servlet;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationException;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.util.Base64;
|
||||
import org.alfresco.web.scripts.Authenticator;
|
||||
import org.alfresco.web.scripts.WebScriptException;
|
||||
import org.alfresco.web.scripts.Description.RequiredAuthentication;
|
||||
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
|
||||
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP Basic Authentication
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class BasicHttpAuthenticatorFactory implements ServletAuthenticatorFactory
|
||||
{
|
||||
// Logger
|
||||
private static Log logger = LogFactory.getLog(BasicHttpAuthenticator.class);
|
||||
|
||||
// Component dependencies
|
||||
private AuthenticationService authenticationService;
|
||||
|
||||
|
||||
/**
|
||||
* @param authenticationService
|
||||
*/
|
||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(org.alfresco.web.scripts.servlet.WebScriptServletRequest, org.alfresco.web.scripts.servlet.WebScriptServletResponse)
|
||||
*/
|
||||
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
|
||||
{
|
||||
return new BasicHttpAuthenticator(req, res);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* HTTP Basic Authentication
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class BasicHttpAuthenticator implements Authenticator
|
||||
{
|
||||
// dependencies
|
||||
private WebScriptServletRequest servletReq;
|
||||
private WebScriptServletResponse servletRes;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param authenticationService
|
||||
* @param req
|
||||
* @param res
|
||||
*/
|
||||
public BasicHttpAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res)
|
||||
{
|
||||
this.servletReq = req;
|
||||
this.servletRes = res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
|
||||
*/
|
||||
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
|
||||
{
|
||||
boolean authorized = false;
|
||||
|
||||
//
|
||||
// validate credentials
|
||||
//
|
||||
|
||||
HttpServletRequest req = servletReq.getHttpServletRequest();
|
||||
HttpServletResponse res = servletRes.getHttpServletResponse();
|
||||
String authorization = req.getHeader("Authorization");
|
||||
String ticket = req.getParameter("alf_ticket");
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
|
||||
logger.debug("URL ticket provided: " + (ticket != null && ticket.length() > 0));
|
||||
}
|
||||
|
||||
// authenticate as guest, if service allows
|
||||
if (isGuest && RequiredAuthentication.guest == required)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating as Guest");
|
||||
|
||||
authenticationService.authenticateAsGuest();
|
||||
authorized = true;
|
||||
}
|
||||
|
||||
// authenticate as specified by explicit ticket on url
|
||||
else if (ticket != null && ticket.length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating (URL argument) ticket " + ticket);
|
||||
|
||||
// assume a ticket has been passed
|
||||
authenticationService.validate(ticket);
|
||||
authorized = true;
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
// failed authentication
|
||||
}
|
||||
}
|
||||
|
||||
// authenticate as specified by HTTP Basic Authentication
|
||||
else if (authorization != null && authorization.length() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
String[] authorizationParts = authorization.split(" ");
|
||||
if (!authorizationParts[0].equalsIgnoreCase("basic"))
|
||||
{
|
||||
throw new WebScriptException("Authorization '" + authorizationParts[0] + "' not supported.");
|
||||
}
|
||||
String decodedAuthorisation = new String(Base64.decode(authorizationParts[1]));
|
||||
String[] parts = decodedAuthorisation.split(":");
|
||||
|
||||
if (parts.length == 1)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating (BASIC HTTP) ticket " + parts[0]);
|
||||
|
||||
// assume a ticket has been passed
|
||||
authenticationService.validate(parts[0]);
|
||||
authorized = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Authenticating (BASIC HTTP) user " + parts[0]);
|
||||
|
||||
// assume username and password passed
|
||||
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
|
||||
{
|
||||
if (required == RequiredAuthentication.guest)
|
||||
{
|
||||
authenticationService.authenticateAsGuest();
|
||||
authorized = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
authenticationService.authenticate(parts[0], parts[1].toCharArray());
|
||||
authorized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(AuthenticationException e)
|
||||
{
|
||||
// failed authentication
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// request credentials if not authorized
|
||||
//
|
||||
|
||||
if (!authorized)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Requesting authorization credentials");
|
||||
|
||||
res.setStatus(401);
|
||||
res.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
|
||||
}
|
||||
return authorized;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
* As a special exception to the terms and conditions of version 2.0 of
|
||||
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||
* FLOSS exception. You should have recieved a copy of the text describing
|
||||
* the FLOSS exception, and it is also available here:
|
||||
* http://www.alfresco.com/legal/licensing"
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.site;
|
||||
|
||||
import org.alfresco.repo.web.scripts.BaseWebScriptTest;
|
||||
import org.alfresco.util.GUID;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
|
||||
/**
|
||||
* Unit test to test site Web Script API
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
public class TestSiteService extends BaseWebScriptTest
|
||||
{
|
||||
private static final String URL_SITES = "/api/sites";
|
||||
|
||||
public void testCreateSite() throws Exception
|
||||
{
|
||||
String shortName = GUID.generate();
|
||||
|
||||
// == Create a new site ==
|
||||
|
||||
JSONObject site = new JSONObject();
|
||||
site.put("sitePreset", "myPreset");
|
||||
site.put("shortName", shortName);
|
||||
site.put("title", "myTitle");
|
||||
site.put("description", "myDescription");
|
||||
site.put("isPublic", true);
|
||||
|
||||
MockHttpServletResponse response = postRequest(URL_SITES, 200, site.toString(), "application/json");
|
||||
|
||||
JSONObject result = new JSONObject(response.getContentAsString());
|
||||
|
||||
assertEquals("myPreset", result.get("sitePreset"));
|
||||
assertEquals(shortName, result.get("shortName"));
|
||||
assertEquals("myTitle", result.get("title"));
|
||||
assertEquals("myDescription", result.get("description"));
|
||||
assertTrue(result.getBoolean("isPublic"));
|
||||
|
||||
// == Create a site with a duplicate shortName ==
|
||||
|
||||
response = postRequest(URL_SITES, 500, site.toString(), "application/json");
|
||||
result = new JSONObject(response.getContentAsString());
|
||||
}
|
||||
|
||||
public void testGetSites() throws Exception
|
||||
{
|
||||
// == Test basic GET with no filters ==
|
||||
|
||||
MockHttpServletResponse response = getRequest(URL_SITES, 200);
|
||||
JSONArray result = new JSONArray(response.getContentAsString());
|
||||
|
||||
// TODO formalise this test once i can be sure that i know what's already in the site store
|
||||
// ie: .. i need to clean up after myself in this test
|
||||
|
||||
System.out.println(response.getContentAsString());
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user