Merged 5.1.N (5.1.2) to 5.2.N (5.2.1)

125605 rmunteanu: Merged 5.1.1 (5.1.1) to 5.1.N (5.1.2)
      125498 slanglois: MNT-16155 Update source headers - remove svn:eol-style property on Java and JSP source files


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/DEV/5.2.N/root@125783 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Raluca Munteanu
2016-04-26 13:03:25 +00:00
parent 9a889c69ea
commit 386a4aca06
327 changed files with 55062 additions and 55062 deletions

View File

@@ -1,91 +1,91 @@
package org.alfresco.repo.web.scripts.bean;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.events.types.Event;
import org.alfresco.events.types.RepositoryEventImpl;
import org.alfresco.repo.events.EventPreparator;
import org.alfresco.repo.events.EventPublisher;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Common code between Get based login and POST based login
*/
/* package scope */ abstract class AbstractLoginBean extends DeclarativeWebScript
{
// dependencies
private AuthenticationService authenticationService;
protected EventPublisher eventPublisher;
/**
* @param authenticationService AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @param eventPublisher EventPublisher
*/
public void setEventPublisher(EventPublisher eventPublisher)
{
this.eventPublisher = eventPublisher;
}
/* (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)
{
return null;
}
protected Map<String, Object> login(final String username, String password)
{
try
{
// get ticket
authenticationService.authenticate(username, password.toCharArray());
eventPublisher.publishEvent(new EventPreparator(){
@Override
public Event prepareEvent(String user, String networkId, String transactionId)
{
// TODO need to fix up to pass correct seqNo and alfrescoClientId
return new RepositoryEventImpl(-1l, "login", transactionId, networkId, new Date().getTime(),
username, null);
}
});
// add ticket to model for javascript and template access
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("username", username);
model.put("ticket", authenticationService.getCurrentTicket());
return model;
}
catch(AuthenticationException e)
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Login failed");
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
package org.alfresco.repo.web.scripts.bean;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.events.types.Event;
import org.alfresco.events.types.RepositoryEventImpl;
import org.alfresco.repo.events.EventPreparator;
import org.alfresco.repo.events.EventPublisher;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Common code between Get based login and POST based login
*/
/* package scope */ abstract class AbstractLoginBean extends DeclarativeWebScript
{
// dependencies
private AuthenticationService authenticationService;
protected EventPublisher eventPublisher;
/**
* @param authenticationService AuthenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @param eventPublisher EventPublisher
*/
public void setEventPublisher(EventPublisher eventPublisher)
{
this.eventPublisher = eventPublisher;
}
/* (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)
{
return null;
}
protected Map<String, Object> login(final String username, String password)
{
try
{
// get ticket
authenticationService.authenticate(username, password.toCharArray());
eventPublisher.publishEvent(new EventPreparator(){
@Override
public Event prepareEvent(String user, String networkId, String transactionId)
{
// TODO need to fix up to pass correct seqNo and alfrescoClientId
return new RepositoryEventImpl(-1l, "login", transactionId, networkId, new Date().getTime(),
username, null);
}
});
// add ticket to model for javascript and template access
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("username", username);
model.put("ticket", authenticationService.getCurrentTicket());
return model;
}
catch(AuthenticationException e)
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Login failed");
}
finally
{
AuthenticationUtil.clearCurrentSecurityContext();
}
}
}

View File

@@ -1,39 +1,39 @@
package org.alfresco.repo.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* WebScript java backed bean implementation - to return information about the
* authentication system, such as account mutability.
*
* @author Kevin Roast
*/
public class Authentication extends DeclarativeWebScript
{
private MutableAuthenticationService authenticationService;
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = (MutableAuthenticationService)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)
{
Map<String, Object> model = new HashMap<String, Object>(2);
model.put("creationAllowed", this.authenticationService.isAuthenticationCreationAllowed());
return model;
}
package org.alfresco.repo.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* WebScript java backed bean implementation - to return information about the
* authentication system, such as account mutability.
*
* @author Kevin Roast
*/
public class Authentication extends DeclarativeWebScript
{
private MutableAuthenticationService authenticationService;
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = (MutableAuthenticationService)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)
{
Map<String, Object> model = new HashMap<String, Object>(2);
model.put("creationAllowed", this.authenticationService.isAuthenticationCreationAllowed());
return model;
}
}

View File

@@ -1,389 +1,389 @@
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.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.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
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.SearchLanguageConversion;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.springframework.extensions.surf.util.URLEncoder;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* 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;
protected NodeService nodeService;
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
@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
*/
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(" ");
searchTerms = searchTerms.replaceAll("\"", "&quot;");
// Escape special characters in the terms, so that they can't confuse the parser
for (int i=0; i<terms.length; i++)
{
terms[i] = SearchLanguageConversion.escapeLuceneQuery(terms[i]);
}
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);
// Make the search resilient to invalid nodes
if (!nodeService.exists(node))
{
continue;
}
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
*/
public SearchTemplateNode(NodeRef nodeRef, float score)
{
super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver());
this.score = score;
}
/**
* Gets the result row score
*/
public float getScore()
{
return score;
}
@Override
public String getUrl()
{
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
URLEncoder.encode(getName()) } );
}
}
}
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.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.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
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.SearchLanguageConversion;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.extensions.surf.util.I18NUtil;
import org.springframework.extensions.surf.util.ParameterCheck;
import org.springframework.extensions.surf.util.URLEncoder;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* 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;
protected NodeService nodeService;
public void setSearchService(SearchService searchService)
{
this.searchService = searchService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
@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
*/
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(" ");
searchTerms = searchTerms.replaceAll("\"", "&quot;");
// Escape special characters in the terms, so that they can't confuse the parser
for (int i=0; i<terms.length; i++)
{
terms[i] = SearchLanguageConversion.escapeLuceneQuery(terms[i]);
}
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);
// Make the search resilient to invalid nodes
if (!nodeService.exists(node))
{
continue;
}
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
*/
public SearchTemplateNode(NodeRef nodeRef, float score)
{
super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver());
this.score = score;
}
/**
* Gets the result row score
*/
public float getScore()
{
return score;
}
@Override
public String getUrl()
{
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
URLEncoder.encode(getName()) } );
}
}
}

View File

@@ -1,47 +1,47 @@
package org.alfresco.repo.web.scripts.bean;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Login and establish a ticket
*
* @author davidc
*/
public class Login extends AbstractLoginBean
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
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
{
return login(username, password);
}
catch(WebScriptException e)
{
status.setCode(e.getStatus());
status.setMessage(e.getMessage());
status.setRedirect(true);
return null;
}
}
package org.alfresco.repo.web.scripts.bean;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Login and establish a ticket
*
* @author davidc
*/
public class Login extends AbstractLoginBean
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
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
{
return login(username, password);
}
catch(WebScriptException e)
{
status.setCode(e.getStatus());
status.setMessage(e.getMessage());
status.setRedirect(true);
return null;
}
}
}

View File

@@ -1,75 +1,75 @@
package org.alfresco.repo.web.scripts.bean;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Post based login script
*/
public class LoginPost extends AbstractLoginBean
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
// Extract user and password from JSON POST
Content c = req.getContent();
if (c == null)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body.");
}
// TODO accept xml type.
// extract username and password from JSON object
JSONObject json;
try
{
json = new JSONObject(c.getContent());
String username = json.getString("username");
String password = json.getString("password");
if (username == null || username.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified");
}
if (password == null)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified");
}
try
{
return login(username, password);
}
catch(WebScriptException e)
{
status.setCode(e.getStatus());
status.setMessage(e.getMessage());
status.setRedirect(true);
return null;
}
}
catch (JSONException jErr)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Unable to parse JSON POST body: " + jErr.getMessage());
}
catch (IOException ioErr)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR,
"Unable to retrieve POST body: " + ioErr.getMessage());
}
}
package org.alfresco.repo.web.scripts.bean;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.extensions.surf.util.Content;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
/**
* Post based login script
*/
public class LoginPost extends AbstractLoginBean
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
{
// Extract user and password from JSON POST
Content c = req.getContent();
if (c == null)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Missing POST body.");
}
// TODO accept xml type.
// extract username and password from JSON object
JSONObject json;
try
{
json = new JSONObject(c.getContent());
String username = json.getString("username");
String password = json.getString("password");
if (username == null || username.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Username not specified");
}
if (password == null)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Password not specified");
}
try
{
return login(username, password);
}
catch(WebScriptException e)
{
status.setCode(e.getStatus());
status.setMessage(e.getMessage());
status.setRedirect(true);
return null;
}
}
catch (JSONException jErr)
{
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
"Unable to parse JSON POST body: " + jErr.getMessage());
}
catch (IOException ioErr)
{
throw new WebScriptException(Status.STATUS_INTERNAL_SERVER_ERROR,
"Unable to retrieve POST body: " + ioErr.getMessage());
}
}
}

View File

@@ -1,186 +1,186 @@
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.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.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 ConfigService
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
/**
* @param searchProxy 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;
}
}
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.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.surf.util.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.config.OpenSearchConfigElement;
import org.springframework.extensions.webscripts.DeclarativeWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.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 ConfigService
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
/**
* @param searchProxy 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;
}
}
}

View File

@@ -1,317 +1,317 @@
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.net.URLConnection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
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.app.servlet.HTTPProxy;
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;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.FormatRegistry;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
/**
* 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 FormatRegistry
*/
public void setFormatRegistry(FormatRegistry formatRegistry)
{
this.formatRegistry = formatRegistry;
}
/**
* @param configService 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.getRuntime() instanceof WebScriptServletRuntime))
{
throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment");
}
HttpServletResponse servletRes = WebScriptServletRuntime.getHttpServletResponse(res);
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServerPath() + req.getServiceContextPath(),
engine, engineUrl, servletRes, Collections.singletonMap("User-Agent", req.getHeader("User-Agent")));
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;
private Map<String, String> headers;
/**
* Construct
*
* @param rootPath String
* @param engine String
* @param engineUrl String
* @param response HttpServletResponse
* @param headers request headers
* @throws MalformedURLException
*/
public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response, Map<String, String> headers)
throws MalformedURLException
{
super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response);
this.engine = engine;
this.rootPath = rootPath;
this.headers = headers;
}
/* (non-Javadoc)
* @see org.alfresco.web.app.servlet.HTTPProxy#setRequestHeaders(java.net.URLConnection)
*/
@Override
protected void setRequestHeaders(URLConnection urlConnection)
{
if (headers != null)
{
for (Map.Entry<String, String> entry: headers.entrySet())
{
urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
/* (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;
}
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.net.URLConnection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
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.app.servlet.HTTPProxy;
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;
import org.springframework.extensions.config.Config;
import org.springframework.extensions.config.ConfigService;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.FormatRegistry;
import org.springframework.extensions.webscripts.WebScriptException;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
/**
* 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 FormatRegistry
*/
public void setFormatRegistry(FormatRegistry formatRegistry)
{
this.formatRegistry = formatRegistry;
}
/**
* @param configService 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.getRuntime() instanceof WebScriptServletRuntime))
{
throw new WebScriptException("Search Proxy must be executed in HTTP Servlet environment");
}
HttpServletResponse servletRes = WebScriptServletRuntime.getHttpServletResponse(res);
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServerPath() + req.getServiceContextPath(),
engine, engineUrl, servletRes, Collections.singletonMap("User-Agent", req.getHeader("User-Agent")));
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;
private Map<String, String> headers;
/**
* Construct
*
* @param rootPath String
* @param engine String
* @param engineUrl String
* @param response HttpServletResponse
* @param headers request headers
* @throws MalformedURLException
*/
public SearchEngineHttpProxy(String rootPath, String engine, String engineUrl, HttpServletResponse response, Map<String, String> headers)
throws MalformedURLException
{
super(engineUrl.startsWith("/") ? rootPath + engineUrl : engineUrl, response);
this.engine = engine;
this.rootPath = rootPath;
this.headers = headers;
}
/* (non-Javadoc)
* @see org.alfresco.web.app.servlet.HTTPProxy#setRequestHeaders(java.net.URLConnection)
*/
@Override
protected void setRequestHeaders(URLConnection urlConnection)
{
if (headers != null)
{
for (Map.Entry<String, String> entry: headers.entrySet())
{
urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
/* (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;
}
}

View File

@@ -1,26 +1,26 @@
package org.alfresco.repo.web.scripts.bean;
import java.io.IOException;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
/**
* WebScript java backed bean implementation - to simple return a STATUS_OK message
* as a touch point for SSO authentication mechanisms on the web-tier. Such as NTLM.
*
* @author Kevin Roast
*/
public class Touch extends AbstractWebScript
{
/* (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
{
res.setStatus(Status.STATUS_OK);
res.getWriter().close();
}
package org.alfresco.repo.web.scripts.bean;
import java.io.IOException;
import org.springframework.extensions.webscripts.AbstractWebScript;
import org.springframework.extensions.webscripts.Status;
import org.springframework.extensions.webscripts.WebScriptRequest;
import org.springframework.extensions.webscripts.WebScriptResponse;
/**
* WebScript java backed bean implementation - to simple return a STATUS_OK message
* as a touch point for SSO authentication mechanisms on the web-tier. Such as NTLM.
*
* @author Kevin Roast
*/
public class Touch extends AbstractWebScript
{
/* (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
{
res.setStatus(Status.STATUS_OK);
res.getWriter().close();
}
}