mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merge Web Scripts from BRANCHES/DEV/DAVE
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5361 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.web.api.framework.APIRequest;
|
|
||||||
import org.alfresco.web.api.framework.APIResponse;
|
|
||||||
import org.alfresco.web.api.framework.ScriptedAPIService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the list of available Web APIs
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class Index extends ScriptedAPIService
|
|
||||||
{
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.services.APIServiceTemplateImpl#createModel(org.alfresco.web.api.APIRequest, org.alfresco.web.api.APIResponse, java.util.Map)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
|
|
||||||
{
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
|
||||||
model.put("services", getAPIRegistry().getServices());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.web.api.framework.APIRequest;
|
|
||||||
import org.alfresco.web.api.framework.APIResponse;
|
|
||||||
import org.alfresco.web.api.framework.ScriptedAPIService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the list of available Web APIs
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class IndexUpdate extends ScriptedAPIService
|
|
||||||
{
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.services.APIServiceTemplateImpl#createModel(org.alfresco.web.api.APIRequest, org.alfresco.web.api.APIResponse, java.util.Map)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
|
|
||||||
{
|
|
||||||
List<String> tasks = new ArrayList<String>();
|
|
||||||
|
|
||||||
// reset index
|
|
||||||
String reset = req.getParameter("reset");
|
|
||||||
if (reset != null && reset.equals("on"))
|
|
||||||
{
|
|
||||||
int previousCount = getAPIRegistry().getServices().size();
|
|
||||||
getAPIRegistry().reset();
|
|
||||||
tasks.add("Reset Web API Registry; found " + getAPIRegistry().getServices().size() + " APIs. Previously, there were " + previousCount + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
// create model for rendering
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
|
||||||
model.put("tasks", tasks);
|
|
||||||
model.put("services", getAPIRegistry().getServices());
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,382 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api;
|
|
||||||
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.i18n.I18NUtil;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.StoreRef;
|
|
||||||
import org.alfresco.service.cmr.repository.TemplateImageResolver;
|
|
||||||
import org.alfresco.service.cmr.repository.TemplateNode;
|
|
||||||
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.web.api.framework.APIException;
|
|
||||||
import org.alfresco.web.api.framework.APIRequest;
|
|
||||||
import org.alfresco.web.api.framework.APIResponse;
|
|
||||||
import org.alfresco.web.api.framework.ScriptedAPIService;
|
|
||||||
import org.alfresco.web.ui.common.Utils;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alfresco Keyword (simple) Search Service
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class KeywordSearch extends ScriptedAPIService
|
|
||||||
{
|
|
||||||
// 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 SearchService searchService;
|
|
||||||
|
|
||||||
// icon resolver
|
|
||||||
protected TemplateImageResolver iconResolver = new TemplateImageResolver()
|
|
||||||
{
|
|
||||||
public String resolveImagePathForName(String filename, boolean small)
|
|
||||||
{
|
|
||||||
return Utils.getFileTypeImage(getAPIRegistry().getContext(), filename, small);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param searchService
|
|
||||||
*/
|
|
||||||
public void setSearchService(SearchService searchService)
|
|
||||||
{
|
|
||||||
this.searchService = searchService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.services.APIServiceTemplateImpl#createModel(org.alfresco.web.api.APIRequest, org.alfresco.web.api.APIResponse, java.util.Map)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// 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, APIRequest 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", createArgModel(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 APIException("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.setTotalPages(totalPages);
|
|
||||||
searchResult.setTotalResults(totalResults);
|
|
||||||
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
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -1791913270786140012L;
|
|
||||||
private float score;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param nodeRef
|
|
||||||
* @param score
|
|
||||||
*/
|
|
||||||
public SearchTemplateNode(NodeRef nodeRef, float score)
|
|
||||||
{
|
|
||||||
super(nodeRef, getServiceRegistry(), iconResolver);
|
|
||||||
this.score = score;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the result row score
|
|
||||||
*
|
|
||||||
* @return score
|
|
||||||
*/
|
|
||||||
public float getScore()
|
|
||||||
{
|
|
||||||
return score;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api;
|
|
||||||
|
|
||||||
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.web.api.framework.APIRequest;
|
|
||||||
import org.alfresco.web.api.framework.APIResponse;
|
|
||||||
import org.alfresco.web.api.framework.ScriptedAPIService;
|
|
||||||
import org.alfresco.web.config.OpenSearchConfigElement;
|
|
||||||
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 ScriptedAPIService
|
|
||||||
{
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,311 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api;
|
|
||||||
|
|
||||||
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.web.api.framework.APIException;
|
|
||||||
import org.alfresco.web.api.framework.APIRequest;
|
|
||||||
import org.alfresco.web.api.framework.APIResponse;
|
|
||||||
import org.alfresco.web.api.framework.AbstractAPIService;
|
|
||||||
import org.alfresco.web.api.framework.FormatRegistry;
|
|
||||||
import org.alfresco.web.app.servlet.HTTPProxy;
|
|
||||||
import org.alfresco.web.config.OpenSearchConfigElement;
|
|
||||||
import org.alfresco.web.config.OpenSearchConfigElement.EngineConfig;
|
|
||||||
import org.alfresco.web.config.OpenSearchConfigElement.ProxyConfig;
|
|
||||||
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 AbstractAPIService 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 APIException("OpenSearch configuration not found");
|
|
||||||
}
|
|
||||||
ProxyConfig proxyConfig = searchConfig.getProxy();
|
|
||||||
if (proxyConfig == null)
|
|
||||||
{
|
|
||||||
throw new APIException("OpenSearch proxy configuration not found");
|
|
||||||
}
|
|
||||||
proxyPath = proxyConfig.getUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIService#execute(org.alfresco.web.api.APIRequest, org.alfresco.web.api.APIResponse)
|
|
||||||
*/
|
|
||||||
public void execute(APIRequest req, APIResponse res)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
String extensionPath = req.getExtensionPath();
|
|
||||||
String[] extensionPaths = extensionPath.split("/");
|
|
||||||
if (extensionPaths.length != 2)
|
|
||||||
{
|
|
||||||
throw new APIException("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 APIException("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 APIException("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 APIException("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
|
|
||||||
SearchEngineHttpProxy proxy = new SearchEngineHttpProxy(req.getServicePath() + "/" + req.getContextPath(), engine, engineUrl, res);
|
|
||||||
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 APIException("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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface for marking that a service is API Context aware
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface APIContextAware
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the API Context
|
|
||||||
*
|
|
||||||
* @param context api context
|
|
||||||
*/
|
|
||||||
public void setAPIContext(ServletContext context);
|
|
||||||
}
|
|
@@ -1,151 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Description
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface APIDescription
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Enumeration of "required" Authentication level
|
|
||||||
*/
|
|
||||||
public enum RequiredAuthentication
|
|
||||||
{
|
|
||||||
none,
|
|
||||||
guest,
|
|
||||||
user
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumeration of "required" Transaction level
|
|
||||||
*/
|
|
||||||
public enum RequiredTransaction
|
|
||||||
{
|
|
||||||
none,
|
|
||||||
required,
|
|
||||||
requiresnew
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the source document location of this service description
|
|
||||||
*
|
|
||||||
* @return document location (path)
|
|
||||||
*/
|
|
||||||
public String getSourceLocation();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the id of this service
|
|
||||||
*
|
|
||||||
* @return service id
|
|
||||||
*/
|
|
||||||
public String getId();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the short name of this service
|
|
||||||
*
|
|
||||||
* @return service short name
|
|
||||||
*/
|
|
||||||
public String getShortName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the description of this service
|
|
||||||
*/
|
|
||||||
public String getDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the required authentication level for execution of this service
|
|
||||||
*
|
|
||||||
* @return the required authentication level
|
|
||||||
*/
|
|
||||||
public RequiredAuthentication getRequiredAuthentication();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the required transaction level
|
|
||||||
*
|
|
||||||
* @return the required transaction level
|
|
||||||
*/
|
|
||||||
public RequiredTransaction getRequiredTransaction();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the HTTP method this service is bound to
|
|
||||||
*
|
|
||||||
* @return HTTP method
|
|
||||||
*/
|
|
||||||
public String getMethod();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the URIs this service supports
|
|
||||||
*
|
|
||||||
* @return array of URIs in order specified in service description document
|
|
||||||
*/
|
|
||||||
public URI[] getURIs();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a URI by format
|
|
||||||
*
|
|
||||||
* @param format the format
|
|
||||||
* @return the URI (or null, if no URI registered for the format)
|
|
||||||
*/
|
|
||||||
public URI getURI(String format);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the default response format
|
|
||||||
*
|
|
||||||
* Note: the default response format is the first listed in the service
|
|
||||||
* description document
|
|
||||||
*
|
|
||||||
* @return default response format
|
|
||||||
*/
|
|
||||||
public String getDefaultFormat();
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service URL
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface URI
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Gets the URI response format
|
|
||||||
*
|
|
||||||
* @return format
|
|
||||||
*/
|
|
||||||
public String getFormat();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the URI
|
|
||||||
*
|
|
||||||
* @return uri
|
|
||||||
*/
|
|
||||||
public String getURI();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,273 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Description Implementation
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIDescriptionImpl implements APIDescription
|
|
||||||
{
|
|
||||||
private String sourceLocation;
|
|
||||||
private String id;
|
|
||||||
private String shortName;
|
|
||||||
private String description;
|
|
||||||
private RequiredAuthentication requiredAuthentication;
|
|
||||||
private RequiredTransaction requiredTransaction;
|
|
||||||
private String httpMethod;
|
|
||||||
private URI[] uris;
|
|
||||||
private String defaultFormat;
|
|
||||||
private Map<String, URI> uriByFormat;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the source location
|
|
||||||
*
|
|
||||||
* @param sourceLocation
|
|
||||||
*/
|
|
||||||
public void setSourceLocation(String sourceLocation)
|
|
||||||
{
|
|
||||||
this.sourceLocation = sourceLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getSourceLocation()
|
|
||||||
*/
|
|
||||||
public String getSourceLocation()
|
|
||||||
{
|
|
||||||
return this.sourceLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service id
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
*/
|
|
||||||
public void setId(String id)
|
|
||||||
{
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getId()
|
|
||||||
*/
|
|
||||||
public String getId()
|
|
||||||
{
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service short name
|
|
||||||
*
|
|
||||||
* @param shortName
|
|
||||||
*/
|
|
||||||
public void setShortName(String shortName)
|
|
||||||
{
|
|
||||||
this.shortName = shortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getShortName()
|
|
||||||
*/
|
|
||||||
public String getShortName()
|
|
||||||
{
|
|
||||||
return this.shortName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service description
|
|
||||||
*
|
|
||||||
* @param description
|
|
||||||
*/
|
|
||||||
public void setDescription(String description)
|
|
||||||
{
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getDescription()
|
|
||||||
*/
|
|
||||||
public String getDescription()
|
|
||||||
{
|
|
||||||
return this.description;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the required level of authentication
|
|
||||||
*
|
|
||||||
* @param requiredAuthentication
|
|
||||||
*/
|
|
||||||
public void setRequiredAuthentication(RequiredAuthentication requiredAuthentication)
|
|
||||||
{
|
|
||||||
this.requiredAuthentication = requiredAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getRequiredAuthentication()
|
|
||||||
*/
|
|
||||||
public RequiredAuthentication getRequiredAuthentication()
|
|
||||||
{
|
|
||||||
return this.requiredAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the required level of transaction
|
|
||||||
*
|
|
||||||
* @param requiredTransaction
|
|
||||||
*/
|
|
||||||
public void setRequiredTransaction(RequiredTransaction requiredTransaction)
|
|
||||||
{
|
|
||||||
this.requiredTransaction = requiredTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getRequiredTransaction()
|
|
||||||
*/
|
|
||||||
public RequiredTransaction getRequiredTransaction()
|
|
||||||
{
|
|
||||||
return this.requiredTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service http method
|
|
||||||
*
|
|
||||||
* @param httpMethod
|
|
||||||
*/
|
|
||||||
public void setMethod(String httpMethod)
|
|
||||||
{
|
|
||||||
this.httpMethod = httpMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getMethod()
|
|
||||||
*/
|
|
||||||
public String getMethod()
|
|
||||||
{
|
|
||||||
return this.httpMethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service URIs
|
|
||||||
*
|
|
||||||
* @param uris
|
|
||||||
*/
|
|
||||||
public void setUris(URI[] uris)
|
|
||||||
{
|
|
||||||
this.uriByFormat = new HashMap<String, URI>(uris.length);
|
|
||||||
for (URI uri : uris)
|
|
||||||
{
|
|
||||||
this.uriByFormat.put(uri.getFormat(), uri);
|
|
||||||
}
|
|
||||||
this.uris = uris;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getURIs()
|
|
||||||
*/
|
|
||||||
public URI[] getURIs()
|
|
||||||
{
|
|
||||||
return this.uris;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getURI(java.lang.String)
|
|
||||||
*/
|
|
||||||
public URI getURI(String format)
|
|
||||||
{
|
|
||||||
return this.uriByFormat.get(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default response format
|
|
||||||
*
|
|
||||||
* @param defaultFormat
|
|
||||||
*/
|
|
||||||
public void setDefaultFormat(String defaultFormat)
|
|
||||||
{
|
|
||||||
this.defaultFormat = defaultFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription#getDefaultFormat()
|
|
||||||
*/
|
|
||||||
public String getDefaultFormat()
|
|
||||||
{
|
|
||||||
return this.defaultFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Description URL Implementation
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public static class URIImpl implements APIDescription.URI
|
|
||||||
{
|
|
||||||
private String format;
|
|
||||||
private String uri;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the URI response format
|
|
||||||
*
|
|
||||||
* @param format
|
|
||||||
*/
|
|
||||||
public void setFormat(String format)
|
|
||||||
{
|
|
||||||
this.format = format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription.URI#getFormat()
|
|
||||||
*/
|
|
||||||
public String getFormat()
|
|
||||||
{
|
|
||||||
return this.format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the URI
|
|
||||||
*
|
|
||||||
* @param uri
|
|
||||||
*/
|
|
||||||
public void setUri(String uri)
|
|
||||||
{
|
|
||||||
this.uri = uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIDescription.URI#getURI()
|
|
||||||
*/
|
|
||||||
public String getURI()
|
|
||||||
{
|
|
||||||
return this.uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Exceptions.
|
|
||||||
*
|
|
||||||
* @author David Caruana
|
|
||||||
*/
|
|
||||||
public class APIException extends AlfrescoRuntimeException
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = -7338963365877285084L;
|
|
||||||
|
|
||||||
public APIException(String msgId)
|
|
||||||
{
|
|
||||||
super(msgId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public APIException(String msgId, Throwable cause)
|
|
||||||
{
|
|
||||||
super(msgId, cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public APIException(String msgId, Object ... args)
|
|
||||||
{
|
|
||||||
super(msgId, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public APIException(String msgId, Throwable cause, Object ... args)
|
|
||||||
{
|
|
||||||
super(msgId, args, cause);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Registry
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface APIRegistry
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Gets all API Services
|
|
||||||
*
|
|
||||||
* @return services
|
|
||||||
*/
|
|
||||||
public Collection<APIService> getServices();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an API Service by Id
|
|
||||||
*
|
|
||||||
* @param id service id
|
|
||||||
* @return service
|
|
||||||
*/
|
|
||||||
public APIService getService(String id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an API Service given an HTTP Method and URI
|
|
||||||
*
|
|
||||||
* @param method http method
|
|
||||||
* @param uri uri
|
|
||||||
* @return service match (pair of service and uri that matched)
|
|
||||||
*/
|
|
||||||
public APIServiceMatch findService(String method, String uri);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Servlet Context
|
|
||||||
*
|
|
||||||
* @return servlet context
|
|
||||||
*/
|
|
||||||
public ServletContext getContext();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the response format registry
|
|
||||||
*
|
|
||||||
* @return response format registry
|
|
||||||
*/
|
|
||||||
public FormatRegistry getFormatRegistry();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the API Service Template Processor
|
|
||||||
*
|
|
||||||
* @return template processor
|
|
||||||
*/
|
|
||||||
public APITemplateProcessor getTemplateProcessor();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the API Service Script Processor
|
|
||||||
*
|
|
||||||
* @return script processor
|
|
||||||
*/
|
|
||||||
public APIScriptProcessor getScriptProcessor();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the API Registry
|
|
||||||
*/
|
|
||||||
public void reset();
|
|
||||||
}
|
|
@@ -1,230 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.transaction.TransactionUtil;
|
|
||||||
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.service.transaction.TransactionService;
|
|
||||||
import org.alfresco.util.AbstractLifecycleBean;
|
|
||||||
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 APIRepositoryContext implements ApplicationContextAware, ApplicationListener
|
|
||||||
{
|
|
||||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
|
||||||
|
|
||||||
// dependencies
|
|
||||||
private TransactionService transactionService;
|
|
||||||
private NamespaceService namespaceService;
|
|
||||||
private SearchService searchService;
|
|
||||||
private NodeService nodeService;
|
|
||||||
private PersonService personService;
|
|
||||||
|
|
||||||
// company home
|
|
||||||
private StoreRef companyHomeStore;
|
|
||||||
private String companyHomePath;
|
|
||||||
private NodeRef companyHome;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 the transaction service
|
|
||||||
*
|
|
||||||
* @param transactionService
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 person service
|
|
||||||
*
|
|
||||||
* @param personService
|
|
||||||
*/
|
|
||||||
public void setPersonService(PersonService personService)
|
|
||||||
{
|
|
||||||
this.personService = personService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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()
|
|
||||||
{
|
|
||||||
TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<Object>()
|
|
||||||
{
|
|
||||||
@SuppressWarnings("synthetic-access")
|
|
||||||
public Object doWork() 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());
|
|
||||||
}
|
|
||||||
companyHome = refs.get(0);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Company Home
|
|
||||||
*
|
|
||||||
* @return company home node ref
|
|
||||||
*/
|
|
||||||
public NodeRef getCompanyHome()
|
|
||||||
{
|
|
||||||
return companyHome;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Request
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIRequest extends HttpServletRequestWrapper
|
|
||||||
{
|
|
||||||
/** Service bound to this request */
|
|
||||||
private APIServiceMatch serviceMatch;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param req
|
|
||||||
* @param serviceMatch
|
|
||||||
*/
|
|
||||||
/*package*/ APIRequest(HttpServletRequest req, APIServiceMatch serviceMatch)
|
|
||||||
{
|
|
||||||
super(req);
|
|
||||||
this.serviceMatch = serviceMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the matching API Service for this request
|
|
||||||
*
|
|
||||||
* @return the service match
|
|
||||||
*/
|
|
||||||
public APIServiceMatch getServiceMatch()
|
|
||||||
{
|
|
||||||
return serviceMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get server portion of the request
|
|
||||||
*
|
|
||||||
* e.g. scheme://host:port
|
|
||||||
*
|
|
||||||
* @return server path
|
|
||||||
*/
|
|
||||||
public String getServerPath()
|
|
||||||
{
|
|
||||||
return getScheme() + "://" + getServerName() + ":" + getServerPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Alfresco Service Context Path
|
|
||||||
*
|
|
||||||
* @return service url e.g. /alfresco/service
|
|
||||||
*/
|
|
||||||
public String getServiceContextPath()
|
|
||||||
{
|
|
||||||
return getContextPath() + getServletPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Alfresco Service Path
|
|
||||||
*
|
|
||||||
* @return service url e.g. /alfresco/service/search/keyword
|
|
||||||
*/
|
|
||||||
public String getServicePath()
|
|
||||||
{
|
|
||||||
return getServiceContextPath() + getPathInfo();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the full request URL
|
|
||||||
*
|
|
||||||
* @return request url e.g. /alfresco/service/search/keyword?q=term
|
|
||||||
*/
|
|
||||||
public String getURL()
|
|
||||||
{
|
|
||||||
return getServicePath() + (getQueryString() != null ? "?" + getQueryString() : "");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path extension beyond the path registered for this service
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* a) service registered path = /search/engine
|
|
||||||
* b) request path = /search/engine/external
|
|
||||||
*
|
|
||||||
* => /external
|
|
||||||
*
|
|
||||||
* @return extension path
|
|
||||||
*/
|
|
||||||
public String getExtensionPath()
|
|
||||||
{
|
|
||||||
String servicePath = serviceMatch.getPath();
|
|
||||||
String extensionPath = getPathInfo();
|
|
||||||
int extIdx = extensionPath.indexOf(servicePath);
|
|
||||||
if (extIdx != -1)
|
|
||||||
{
|
|
||||||
int extLength = (servicePath.endsWith("/") ? servicePath.length() : servicePath.length() + 1);
|
|
||||||
extensionPath = extensionPath.substring(extIdx + extLength);
|
|
||||||
}
|
|
||||||
return extensionPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine if Guest User?
|
|
||||||
*
|
|
||||||
* @return true => guest user
|
|
||||||
*/
|
|
||||||
public boolean isGuest()
|
|
||||||
{
|
|
||||||
return Boolean.valueOf(getParameter("guest"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Requested Format
|
|
||||||
*
|
|
||||||
* @return content type requested
|
|
||||||
*/
|
|
||||||
public String getFormat()
|
|
||||||
{
|
|
||||||
String format = getParameter("format");
|
|
||||||
return (format == null || format.length() == 0) ? "" : format;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get User Agent
|
|
||||||
*
|
|
||||||
* TODO: Expand on known agents
|
|
||||||
*
|
|
||||||
* @return MSIE / Firefox
|
|
||||||
*/
|
|
||||||
public String getAgent()
|
|
||||||
{
|
|
||||||
String userAgent = getHeader("user-agent");
|
|
||||||
if (userAgent != null)
|
|
||||||
{
|
|
||||||
if (userAgent.indexOf("Firefox/") != -1)
|
|
||||||
{
|
|
||||||
return "Firefox";
|
|
||||||
}
|
|
||||||
else if (userAgent.indexOf("MSIE") != -1)
|
|
||||||
{
|
|
||||||
return "MSIE";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletResponseWrapper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Response
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIResponse extends HttpServletResponseWrapper
|
|
||||||
{
|
|
||||||
// API Formats
|
|
||||||
public static final String HTML_FORMAT = "html";
|
|
||||||
public static final String ATOM_FORMAT = "atom";
|
|
||||||
public static final String RSS_FORMAT = "rss";
|
|
||||||
public static final String XML_FORMAT = "xml";
|
|
||||||
public static final String JSON_FORMAT = "json";
|
|
||||||
public static final String OPENSEARCH_DESCRIPTION_FORMAT = "opensearchdescription";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param res
|
|
||||||
*/
|
|
||||||
/*package*/ APIResponse(HttpServletResponse res)
|
|
||||||
{
|
|
||||||
super(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptException;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Script Processor for use in Web API
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIScriptProcessor
|
|
||||||
{
|
|
||||||
// dependencies
|
|
||||||
private ScriptService scriptService;
|
|
||||||
|
|
||||||
// api store script loader
|
|
||||||
private ScriptLoader scriptLoader;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the script service
|
|
||||||
*
|
|
||||||
* @param scriptService
|
|
||||||
*/
|
|
||||||
public void setScriptService(ScriptService scriptService)
|
|
||||||
{
|
|
||||||
this.scriptService = scriptService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the script loader
|
|
||||||
*
|
|
||||||
* @param scriptLoader
|
|
||||||
*/
|
|
||||||
public void setScriptLoader(ScriptLoader scriptLoader)
|
|
||||||
{
|
|
||||||
this.scriptLoader = scriptLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a script at the specified path (within registered API stores)
|
|
||||||
*
|
|
||||||
* @param path script path
|
|
||||||
* @return script location (or null, if not found)
|
|
||||||
*/
|
|
||||||
public ScriptLocation findScript(String path)
|
|
||||||
{
|
|
||||||
return scriptLoader.getScriptLocation(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute script
|
|
||||||
*
|
|
||||||
* @param path script path
|
|
||||||
* @param model model
|
|
||||||
* @return script result
|
|
||||||
* @throws ScriptException
|
|
||||||
*/
|
|
||||||
public Object executeScript(String path, Map<String, Object> model)
|
|
||||||
throws ScriptException
|
|
||||||
{
|
|
||||||
// locate script within api stores
|
|
||||||
ScriptLocation scriptLocation = findScript(path);
|
|
||||||
if (scriptLocation == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to locate script " + path);
|
|
||||||
}
|
|
||||||
// execute script
|
|
||||||
return executeScript(scriptLocation, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute script
|
|
||||||
*
|
|
||||||
* @param location script location
|
|
||||||
* @param model model
|
|
||||||
* @return script result
|
|
||||||
*/
|
|
||||||
public Object executeScript(ScriptLocation location, Map<String, Object> model)
|
|
||||||
{
|
|
||||||
return scriptService.executeScript(location, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset script cache
|
|
||||||
*/
|
|
||||||
public void resetCache()
|
|
||||||
{
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface APIService
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Gets the Service Description
|
|
||||||
*
|
|
||||||
* @return service description
|
|
||||||
*/
|
|
||||||
public APIDescription getDescription();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute service
|
|
||||||
*
|
|
||||||
* @param req
|
|
||||||
* @param res
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void execute(APIRequest req, APIResponse res)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
}
|
|
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a service to uri match
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface APIServiceMatch
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the uri path that matched to the service
|
|
||||||
*
|
|
||||||
* @return matching uri path
|
|
||||||
*/
|
|
||||||
public String getPath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the matching service
|
|
||||||
*
|
|
||||||
* @return service
|
|
||||||
*/
|
|
||||||
public APIService getService();
|
|
||||||
|
|
||||||
}
|
|
@@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServlet;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry point for web based services (REST style)
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIServlet extends HttpServlet
|
|
||||||
{
|
|
||||||
private static final long serialVersionUID = 4209892938069597860L;
|
|
||||||
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(APIServlet.class);
|
|
||||||
|
|
||||||
// API Services
|
|
||||||
private DeclarativeAPIRegistry apiServiceRegistry;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() throws ServletException
|
|
||||||
{
|
|
||||||
super.init();
|
|
||||||
|
|
||||||
// Retrieve all web api services and index by http url & http method
|
|
||||||
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
|
|
||||||
initContext(context);
|
|
||||||
apiServiceRegistry = (DeclarativeAPIRegistry)context.getBean("web.api.framework.registry");
|
|
||||||
apiServiceRegistry.initServices();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// - authentication (as suggested in http://www.xml.com/pub/a/2003/12/17/dive.html)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest,
|
|
||||||
* javax.servlet.http.HttpServletResponse)
|
|
||||||
*/
|
|
||||||
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
|
|
||||||
{
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Execute appropriate service
|
|
||||||
//
|
|
||||||
// TODO: Handle errors (with appropriate HTTP error responses)
|
|
||||||
|
|
||||||
String uri = req.getPathInfo();
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Processing request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
|
|
||||||
|
|
||||||
APIServiceMatch match = apiServiceRegistry.findService(req.getMethod(), uri);
|
|
||||||
if (match != null)
|
|
||||||
{
|
|
||||||
// setup service context
|
|
||||||
APIRequest apiReq = new APIRequest(req, match);
|
|
||||||
APIResponse apiRes = new APIResponse(res);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Agent: " + apiReq.getAgent());
|
|
||||||
|
|
||||||
// execute service
|
|
||||||
match.getService().execute(apiReq, apiRes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Request does not map to service.");
|
|
||||||
|
|
||||||
res.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
|
||||||
// TODO: add appropriate error detail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: exception handling
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
long end = System.currentTimeMillis();
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Processed request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : "") + " in " + (end - start) + "ms");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise any API beans that require a servlet context
|
|
||||||
*
|
|
||||||
* @param appContext application context
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void initContext(ApplicationContext appContext)
|
|
||||||
{
|
|
||||||
ServletContext servletContext = getServletContext();
|
|
||||||
Map<String, APIContextAware> contextAwareMap = appContext.getBeansOfType(APIContextAware.class, false, false);
|
|
||||||
for (APIContextAware contextAware: contextAwareMap.values())
|
|
||||||
{
|
|
||||||
contextAware.setAPIContext(servletContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import freemarker.cache.TemplateLoader;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store for holding API Service Definitions and Implementations
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface APIStore
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the base path of the store
|
|
||||||
*
|
|
||||||
* @return base path
|
|
||||||
*/
|
|
||||||
public String getBasePath();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the paths of all API Service description documents in this store
|
|
||||||
*
|
|
||||||
* @return array of description document paths
|
|
||||||
*/
|
|
||||||
public String[] getDescriptionDocumentPaths();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a description document
|
|
||||||
*
|
|
||||||
* @param documentPath description document path
|
|
||||||
* @return input stream onto description document
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public InputStream getDescriptionDocument(String documentPath)
|
|
||||||
throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the template loader for this store
|
|
||||||
*
|
|
||||||
* @return template loader
|
|
||||||
*/
|
|
||||||
public TemplateLoader getTemplateLoader();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the script loader for this store
|
|
||||||
*
|
|
||||||
* @return script loader
|
|
||||||
*/
|
|
||||||
public ScriptLoader getScriptLoader();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.util.AbstractLifecycleBean;
|
|
||||||
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.MultiTemplateLoader;
|
|
||||||
import freemarker.cache.TemplateLoader;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Store Access
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APIStores implements ApplicationContextAware, ApplicationListener
|
|
||||||
{
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
|
||||||
private APITemplateProcessor templateProcessor;
|
|
||||||
private APIScriptProcessor scriptProcessor;
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
|
||||||
*/
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
|
||||||
{
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
this.lifecycle.setApplicationContext(applicationContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
|
||||||
*/
|
|
||||||
public void onApplicationEvent(ApplicationEvent event)
|
|
||||||
{
|
|
||||||
lifecycle.onApplicationEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the template processor
|
|
||||||
*
|
|
||||||
* @param templateProcessor
|
|
||||||
*/
|
|
||||||
public void setTemplateProcessor(APITemplateProcessor templateProcessor)
|
|
||||||
{
|
|
||||||
this.templateProcessor = templateProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the script processor
|
|
||||||
*
|
|
||||||
* @param scriptProcessor
|
|
||||||
*/
|
|
||||||
public void setScriptProcessor(APIScriptProcessor scriptProcessor)
|
|
||||||
{
|
|
||||||
this.scriptProcessor = scriptProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all API Stores
|
|
||||||
*
|
|
||||||
* @return all API Stores
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Collection<APIStore> getAPIStores()
|
|
||||||
{
|
|
||||||
return applicationContext.getBeansOfType(APIStore.class, false, false).values();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Template Processor
|
|
||||||
*
|
|
||||||
* @return template processor
|
|
||||||
*/
|
|
||||||
public APITemplateProcessor getTemplateProcessor()
|
|
||||||
{
|
|
||||||
return templateProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Script Processor
|
|
||||||
*
|
|
||||||
* @return script processor
|
|
||||||
*/
|
|
||||||
public APIScriptProcessor getScriptProcessor()
|
|
||||||
{
|
|
||||||
return scriptProcessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register template loader from each API Store with Template Processor
|
|
||||||
*/
|
|
||||||
protected void initTemplateProcessor()
|
|
||||||
{
|
|
||||||
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
|
|
||||||
for (APIStore apiStore : getAPIStores())
|
|
||||||
{
|
|
||||||
TemplateLoader loader = apiStore.getTemplateLoader();
|
|
||||||
if (loader == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to retrieve template loader for api store " + apiStore.getBasePath());
|
|
||||||
}
|
|
||||||
loaders.add(loader);
|
|
||||||
}
|
|
||||||
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
|
|
||||||
templateProcessor.setTemplateLoader(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register script loader from each API Store with Script Processor
|
|
||||||
*/
|
|
||||||
protected void initScriptProcessor()
|
|
||||||
{
|
|
||||||
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
|
|
||||||
for (APIStore apiStore : getAPIStores())
|
|
||||||
{
|
|
||||||
ScriptLoader loader = apiStore.getScriptLoader();
|
|
||||||
if (loader == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to retrieve script loader for api store " + apiStore.getBasePath());
|
|
||||||
}
|
|
||||||
loaders.add(loader);
|
|
||||||
}
|
|
||||||
MultiScriptLoader loader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
|
|
||||||
scriptProcessor.setScriptLoader(loader);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hooks into Spring Application Lifecycle
|
|
||||||
*/
|
|
||||||
private class ProcessorLifecycle extends AbstractLifecycleBean
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
protected void onBootstrap(ApplicationEvent event)
|
|
||||||
{
|
|
||||||
initTemplateProcessor();
|
|
||||||
initScriptProcessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onShutdown(ApplicationEvent event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,161 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.repo.template.FreeMarkerProcessor;
|
|
||||||
import org.alfresco.repo.template.QNameAwareObjectWrapper;
|
|
||||||
import org.alfresco.util.AbstractLifecycleBean;
|
|
||||||
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.TemplateLoader;
|
|
||||||
import freemarker.template.Configuration;
|
|
||||||
import freemarker.template.TemplateExceptionHandler;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FreeMarker Processor for use in Web API
|
|
||||||
*
|
|
||||||
* Adds the ability to:
|
|
||||||
* - specify template loaders
|
|
||||||
* - caching of templates
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class APITemplateProcessor extends FreeMarkerProcessor implements ApplicationContextAware, ApplicationListener
|
|
||||||
{
|
|
||||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
|
||||||
private TemplateLoader templateLoader = null;
|
|
||||||
private String defaultEncoding;
|
|
||||||
private Configuration templateConfig;
|
|
||||||
|
|
||||||
|
|
||||||
/* (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.repo.template.FreeMarkerProcessor#getConfig()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected Configuration getConfig()
|
|
||||||
{
|
|
||||||
return templateConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the Template Loader
|
|
||||||
*
|
|
||||||
* @param templateLoader template loader
|
|
||||||
*/
|
|
||||||
public void setTemplateLoader(TemplateLoader templateLoader)
|
|
||||||
{
|
|
||||||
this.templateLoader = templateLoader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset template cache
|
|
||||||
*/
|
|
||||||
public void resetCache()
|
|
||||||
{
|
|
||||||
if (templateConfig != null)
|
|
||||||
{
|
|
||||||
templateConfig.clearTemplateCache();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise FreeMarker Configuration
|
|
||||||
*/
|
|
||||||
protected void initConfig()
|
|
||||||
{
|
|
||||||
Configuration config = new Configuration();
|
|
||||||
|
|
||||||
// setup template cache
|
|
||||||
config.setCacheStorage(new MruCacheStorage(20, 100));
|
|
||||||
|
|
||||||
// setup template loaders
|
|
||||||
config.setTemplateLoader(templateLoader);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// set template encoding
|
|
||||||
if (defaultEncoding != null)
|
|
||||||
{
|
|
||||||
config.setDefaultEncoding(defaultEncoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set output encoding
|
|
||||||
config.setOutputEncoding("UTF-8");
|
|
||||||
|
|
||||||
templateConfig = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (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)
|
|
||||||
{
|
|
||||||
initConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onShutdown(ApplicationEvent event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,320 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.repo.jscript.Node;
|
|
||||||
import org.alfresco.repo.jscript.ScriptableHashMap;
|
|
||||||
import org.alfresco.repo.template.AbsoluteUrlMethod;
|
|
||||||
import org.alfresco.repo.template.ISO8601DateFormatMethod;
|
|
||||||
import org.alfresco.repo.template.UrlEncodeMethod;
|
|
||||||
import org.alfresco.service.ServiceRegistry;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
import org.alfresco.service.cmr.repository.TemplateNode;
|
|
||||||
import org.alfresco.service.descriptor.DescriptorService;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredAuthentication;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredTransaction;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Skeleton implementation of an API Service
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public abstract class AbstractAPIService implements APIService
|
|
||||||
{
|
|
||||||
// dependencies
|
|
||||||
private APIRepositoryContext repositoryContext;
|
|
||||||
private APIRegistry apiRegistry;
|
|
||||||
private APIDescription apiDescription;
|
|
||||||
private ServiceRegistry serviceRegistry;
|
|
||||||
private DescriptorService descriptorService;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialisation
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param repositoryContext
|
|
||||||
*/
|
|
||||||
final public void setRepositoryContext(APIRepositoryContext repositoryContext)
|
|
||||||
{
|
|
||||||
this.repositoryContext = repositoryContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param serviceRegistry
|
|
||||||
*/
|
|
||||||
final public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
|
||||||
{
|
|
||||||
this.serviceRegistry = serviceRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param descriptorService
|
|
||||||
*/
|
|
||||||
final public void setDescriptorService(DescriptorService descriptorService)
|
|
||||||
{
|
|
||||||
this.descriptorService = descriptorService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the Service Description
|
|
||||||
*
|
|
||||||
* @param apiDescription
|
|
||||||
*/
|
|
||||||
final public void setDescription(APIDescription apiDescription)
|
|
||||||
{
|
|
||||||
this.apiDescription = apiDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise Service
|
|
||||||
*
|
|
||||||
* @param apiRegistry
|
|
||||||
*/
|
|
||||||
public void init(APIRegistry apiRegistry)
|
|
||||||
{
|
|
||||||
this.apiRegistry = apiRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIService#getServiceDescription()
|
|
||||||
*/
|
|
||||||
final public APIDescription getDescription()
|
|
||||||
{
|
|
||||||
return this.apiDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Service Implementation Helpers
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Repository Context
|
|
||||||
*
|
|
||||||
* @return repository context
|
|
||||||
*/
|
|
||||||
final public APIRepositoryContext getRepositoryContext()
|
|
||||||
{
|
|
||||||
return this.repositoryContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the API Registry
|
|
||||||
*
|
|
||||||
* @return API Registry
|
|
||||||
*/
|
|
||||||
final public APIRegistry getAPIRegistry()
|
|
||||||
{
|
|
||||||
return this.apiRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Alfresco Service Registry
|
|
||||||
*
|
|
||||||
* @return service registry
|
|
||||||
*/
|
|
||||||
final public ServiceRegistry getServiceRegistry()
|
|
||||||
{
|
|
||||||
return this.serviceRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Alfresco Descriptor
|
|
||||||
*
|
|
||||||
* @return descriptor
|
|
||||||
*/
|
|
||||||
final public DescriptorService getDescriptorService()
|
|
||||||
{
|
|
||||||
return this.descriptorService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Scripting Support
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a map of arguments from API Request
|
|
||||||
*
|
|
||||||
* @param req API Request
|
|
||||||
* @return argument map
|
|
||||||
*/
|
|
||||||
final protected Map<String, String> createArgModel(APIRequest req)
|
|
||||||
{
|
|
||||||
Map<String, String> args = new ScriptableHashMap<String, String>();
|
|
||||||
Enumeration names = req.getParameterNames();
|
|
||||||
while (names.hasMoreElements())
|
|
||||||
{
|
|
||||||
String name = (String)names.nextElement();
|
|
||||||
args.put(name, req.getParameter(name));
|
|
||||||
}
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a model for script usage
|
|
||||||
*
|
|
||||||
* @param req api request
|
|
||||||
* @param res api response
|
|
||||||
* @param customModel custom model entries
|
|
||||||
*
|
|
||||||
* @return script model
|
|
||||||
*/
|
|
||||||
final protected Map<String, Object> createScriptModel(APIRequest req, APIResponse res, Map<String, Object> customModel)
|
|
||||||
{
|
|
||||||
// create script model
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
|
||||||
|
|
||||||
// add repository context (only if authenticated and transaction enabled)
|
|
||||||
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
|
|
||||||
getDescription().getRequiredTransaction() != RequiredTransaction.none)
|
|
||||||
{
|
|
||||||
NodeRef companyHome = repositoryContext.getCompanyHome();
|
|
||||||
if (companyHome != null)
|
|
||||||
{
|
|
||||||
model.put("companyhome", new Node(repositoryContext.getCompanyHome(), serviceRegistry));
|
|
||||||
}
|
|
||||||
NodeRef person = repositoryContext.getPerson();
|
|
||||||
if (person != null)
|
|
||||||
{
|
|
||||||
model.put("person", new Node(person, serviceRegistry));
|
|
||||||
model.put("userhome", new Node(repositoryContext.getUserHome(person), serviceRegistry));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add api context
|
|
||||||
model.put("args", createArgModel(req));
|
|
||||||
model.put("guest", req.isGuest());
|
|
||||||
model.put("url", new URLModel(req));
|
|
||||||
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
|
|
||||||
|
|
||||||
// add custom model
|
|
||||||
if (customModel != null)
|
|
||||||
{
|
|
||||||
model.putAll(customModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// return model
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a model for template usage
|
|
||||||
*
|
|
||||||
* @param req api request
|
|
||||||
* @param res api response
|
|
||||||
* @param customModel custom model entries
|
|
||||||
*
|
|
||||||
* @return template model
|
|
||||||
*/
|
|
||||||
final protected Map<String, Object> createTemplateModel(APIRequest req, APIResponse res, Map<String, Object> customModel)
|
|
||||||
{
|
|
||||||
// create script model
|
|
||||||
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
|
|
||||||
|
|
||||||
// add repository context
|
|
||||||
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
|
|
||||||
getDescription().getRequiredTransaction() != RequiredTransaction.none)
|
|
||||||
{
|
|
||||||
NodeRef companyHome = repositoryContext.getCompanyHome();
|
|
||||||
if (companyHome != null)
|
|
||||||
{
|
|
||||||
model.put("companyhome", new TemplateNode(repositoryContext.getCompanyHome(), serviceRegistry, null));
|
|
||||||
}
|
|
||||||
NodeRef person = repositoryContext.getPerson();
|
|
||||||
if (person != null)
|
|
||||||
{
|
|
||||||
model.put("person", new TemplateNode(person, serviceRegistry, null));
|
|
||||||
model.put("userhome", new TemplateNode(repositoryContext.getUserHome(person), serviceRegistry, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add api context
|
|
||||||
model.put("args", createArgModel(req));
|
|
||||||
model.put("guest", req.isGuest());
|
|
||||||
model.put("url", new URLModel(req));
|
|
||||||
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
|
|
||||||
|
|
||||||
// add template support
|
|
||||||
model.put("xmldate", new ISO8601DateFormatMethod());
|
|
||||||
model.put("absurl", new AbsoluteUrlMethod(req.getServerPath()));
|
|
||||||
model.put("urlencode", new UrlEncodeMethod());
|
|
||||||
model.put("date", new Date());
|
|
||||||
|
|
||||||
// add custom model
|
|
||||||
if (customModel != null)
|
|
||||||
{
|
|
||||||
model.putAll(customModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a template (identified by path)
|
|
||||||
*
|
|
||||||
* @param templatePath template path
|
|
||||||
* @param model model
|
|
||||||
* @param writer output writer
|
|
||||||
*/
|
|
||||||
final protected void renderTemplate(String templatePath, Map<String, Object> model, Writer writer)
|
|
||||||
{
|
|
||||||
getAPIRegistry().getTemplateProcessor().process(templatePath, model, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a template (contents as string)
|
|
||||||
* @param template the template
|
|
||||||
* @param model model
|
|
||||||
* @param writer output writer
|
|
||||||
*/
|
|
||||||
final protected void renderString(String template, Map<String, Object> model, Writer writer)
|
|
||||||
{
|
|
||||||
getAPIRegistry().getTemplateProcessor().processString(template, model, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a script
|
|
||||||
*
|
|
||||||
* @param location script location
|
|
||||||
* @param model model
|
|
||||||
*/
|
|
||||||
final protected void executeScript(ScriptLocation location, Map<String, Object> model)
|
|
||||||
{
|
|
||||||
getAPIRegistry().getScriptProcessor().executeScript(location, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredAuthentication;
|
|
||||||
import org.alfresco.web.app.servlet.AuthenticationHelper;
|
|
||||||
import org.alfresco.web.app.servlet.AuthenticationStatus;
|
|
||||||
import org.alfresco.web.app.servlet.BaseServlet;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Alfresco Web Client Authentication Interceptor
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class AlfWebClientAuthenticator implements MethodInterceptor, APIContextAware
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(AlfWebClientAuthenticator.class);
|
|
||||||
|
|
||||||
// dependencies
|
|
||||||
private ServletContext context;
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIContextAware#setAPIContext(javax.servlet.ServletContext)
|
|
||||||
*/
|
|
||||||
public void setAPIContext(ServletContext context)
|
|
||||||
{
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param authenticationService
|
|
||||||
*/
|
|
||||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
|
||||||
{
|
|
||||||
this.authenticationService = authenticationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
String currentUser = null;
|
|
||||||
Object retVal = null;
|
|
||||||
Object[] args = invocation.getArguments();
|
|
||||||
APIRequest request = (APIRequest)args[0];
|
|
||||||
APIResponse response = (APIResponse)args[1];
|
|
||||||
APIService service = (APIService)invocation.getThis();
|
|
||||||
APIDescription description = service.getDescription();
|
|
||||||
AuthenticationStatus status = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine if user already authenticated
|
|
||||||
//
|
|
||||||
|
|
||||||
currentUser = AuthenticationUtil.getCurrentUserName();
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
|
|
||||||
//
|
|
||||||
// validate credentials
|
|
||||||
//
|
|
||||||
|
|
||||||
String ticket = request.getParameter("ticket");
|
|
||||||
boolean isGuest = request.isGuest();
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Service authentication required: " + description.getRequiredAuthentication());
|
|
||||||
logger.debug("Guest login: " + isGuest);
|
|
||||||
logger.debug("Ticket provided: " + (ticket != null && ticket.length() > 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ticket != null && ticket.length() > 0)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating ticket " + ticket);
|
|
||||||
|
|
||||||
status = AuthenticationHelper.authenticate(context, request, response, ticket);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (isGuest && description.getRequiredAuthentication() == RequiredAuthentication.guest)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating as Guest");
|
|
||||||
|
|
||||||
status = AuthenticationHelper.authenticate(context, request, response, true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating session");
|
|
||||||
|
|
||||||
status = AuthenticationHelper.authenticate(context, request, response, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// execute API service or request authorization
|
|
||||||
//
|
|
||||||
|
|
||||||
if (status != null && status != AuthenticationStatus.Failure)
|
|
||||||
{
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// authentication failed - now need to display the login page to the user, if asked to
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Redirecting to Alfresco Login");
|
|
||||||
|
|
||||||
BaseServlet.redirectToLoginPage(request, response, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
if (status != null && status != AuthenticationStatus.Failure)
|
|
||||||
{
|
|
||||||
authenticationService.clearCurrentSecurityContext();
|
|
||||||
if (currentUser != null)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.setCurrentUser(currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,194 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
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.api.framework.APIDescription.RequiredAuthentication;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP Basic Authentication Interceptor
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class BasicAuthenticator implements MethodInterceptor
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(BasicAuthenticator.class);
|
|
||||||
|
|
||||||
// dependencies
|
|
||||||
private AuthenticationService authenticationService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param authenticationService
|
|
||||||
*/
|
|
||||||
public void setAuthenticationService(AuthenticationService authenticationService)
|
|
||||||
{
|
|
||||||
this.authenticationService = authenticationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
boolean authorized = false;
|
|
||||||
String currentUser = null;
|
|
||||||
Object retVal = null;
|
|
||||||
Object[] args = invocation.getArguments();
|
|
||||||
APIRequest request = (APIRequest)args[0];
|
|
||||||
APIService service = (APIService)invocation.getThis();
|
|
||||||
APIDescription description = service.getDescription();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Determine if user already authenticated
|
|
||||||
//
|
|
||||||
|
|
||||||
currentUser = AuthenticationUtil.getCurrentUserName();
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
|
|
||||||
//
|
|
||||||
// validate credentials
|
|
||||||
//
|
|
||||||
|
|
||||||
boolean isGuest = request.isGuest();
|
|
||||||
String authorization = request.getHeader("Authorization");
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
logger.debug("Service authentication required: " + description.getRequiredAuthentication());
|
|
||||||
logger.debug("Guest login: " + isGuest);
|
|
||||||
logger.debug("Authorization provided (overrides Guest login): " + (authorization != null && authorization.length() > 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// authenticate as guest, if service allows
|
|
||||||
if (((authorization == null || authorization.length() == 0) || isGuest)
|
|
||||||
&& description.getRequiredAuthentication().equals(RequiredAuthentication.guest))
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating as Guest");
|
|
||||||
|
|
||||||
authenticationService.authenticateAsGuest();
|
|
||||||
authorized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 APIException("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 ticket " + parts[0]);
|
|
||||||
|
|
||||||
// assume a ticket has been passed
|
|
||||||
authenticationService.validate(parts[0]);
|
|
||||||
authorized = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating user " + parts[0]);
|
|
||||||
|
|
||||||
// assume username and password passed
|
|
||||||
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
|
|
||||||
{
|
|
||||||
if (description.getRequiredAuthentication().equals(RequiredAuthentication.guest))
|
|
||||||
{
|
|
||||||
authenticationService.authenticateAsGuest();
|
|
||||||
authorized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
authenticationService.authenticate(parts[0], parts[1].toCharArray());
|
|
||||||
authorized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(AuthenticationException e)
|
|
||||||
{
|
|
||||||
// failed authentication
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// execute API service or request authorization
|
|
||||||
//
|
|
||||||
|
|
||||||
if (authorized)
|
|
||||||
{
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Requesting authorization credentials");
|
|
||||||
|
|
||||||
APIResponse response = (APIResponse)args[1];
|
|
||||||
response.setStatus(401);
|
|
||||||
response.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
// reset authentication
|
|
||||||
if (authorized)
|
|
||||||
{
|
|
||||||
authenticationService.clearCurrentSecurityContext();
|
|
||||||
if (currentUser != null)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.setCurrentUser(currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,231 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.core.io.Resource;
|
|
||||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
||||||
|
|
||||||
import freemarker.cache.FileTemplateLoader;
|
|
||||||
import freemarker.cache.TemplateLoader;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ClassPath based API Store
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class ClassPathAPIStore implements APIStore, InitializingBean
|
|
||||||
{
|
|
||||||
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
|
||||||
protected String classPath;
|
|
||||||
protected File fileDir;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the class path
|
|
||||||
*
|
|
||||||
* @param classPath classpath
|
|
||||||
*/
|
|
||||||
public void setClassPath(String classPath)
|
|
||||||
{
|
|
||||||
this.classPath = classPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
||||||
*/
|
|
||||||
public void afterPropertiesSet()
|
|
||||||
throws Exception
|
|
||||||
{
|
|
||||||
ClassPathResource resource = new ClassPathResource(classPath);
|
|
||||||
fileDir = resource.getFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getBasePath()
|
|
||||||
*/
|
|
||||||
public String getBasePath()
|
|
||||||
{
|
|
||||||
return "classpath:" + classPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getDescriptionDocumentPaths()
|
|
||||||
*/
|
|
||||||
public String[] getDescriptionDocumentPaths()
|
|
||||||
{
|
|
||||||
String[] paths;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int filePathLength = fileDir.getAbsolutePath().length() +1;
|
|
||||||
List<String> documentPaths = new ArrayList<String>();
|
|
||||||
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/**/*_desc.xml");
|
|
||||||
for (Resource resource : resources)
|
|
||||||
{
|
|
||||||
if (resource instanceof FileSystemResource)
|
|
||||||
{
|
|
||||||
String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength);
|
|
||||||
documentPath = documentPath.replace('\\', '/');
|
|
||||||
documentPaths.add(documentPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paths = documentPaths.toArray(new String[documentPaths.size()]);
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
// Note: Ignore: no service description documents found
|
|
||||||
paths = new String[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getDescriptionDocument(java.lang.String)
|
|
||||||
*/
|
|
||||||
public InputStream getDescriptionDocument(String documentPath)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
File document = new File(fileDir, documentPath);
|
|
||||||
if (!document.exists())
|
|
||||||
{
|
|
||||||
throw new IOException("Description document " + documentPath + " does not exist.");
|
|
||||||
}
|
|
||||||
return new FileInputStream(document);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getTemplateLoader()
|
|
||||||
*/
|
|
||||||
public TemplateLoader getTemplateLoader()
|
|
||||||
{
|
|
||||||
FileTemplateLoader loader = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
loader = new FileTemplateLoader(fileDir);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
// Note: Can't establish loader, so return null
|
|
||||||
}
|
|
||||||
return loader;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getScriptLoader()
|
|
||||||
*/
|
|
||||||
public ScriptLoader getScriptLoader()
|
|
||||||
{
|
|
||||||
return new ClassPathScriptLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class path based script loader
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
private class ClassPathScriptLoader implements ScriptLoader
|
|
||||||
{
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.ScriptLoader#getScriptLocation(java.lang.String)
|
|
||||||
*/
|
|
||||||
public ScriptLocation getScriptLocation(String path)
|
|
||||||
{
|
|
||||||
ScriptLocation location = null;
|
|
||||||
File scriptPath = new File(fileDir, path);
|
|
||||||
if (scriptPath.exists())
|
|
||||||
{
|
|
||||||
location = new ClassPathScriptLocation(scriptPath);
|
|
||||||
}
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class path script location
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
private static class ClassPathScriptLocation implements ScriptLocation
|
|
||||||
{
|
|
||||||
private File location;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
*/
|
|
||||||
public ClassPathScriptLocation(File location)
|
|
||||||
{
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
|
|
||||||
*/
|
|
||||||
public InputStream getInputStream()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return new FileInputStream(location);
|
|
||||||
}
|
|
||||||
catch (FileNotFoundException e)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to retrieve input stream for script " + location.getAbsolutePath());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
|
|
||||||
*/
|
|
||||||
public Reader getReader()
|
|
||||||
{
|
|
||||||
return new InputStreamReader(getInputStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return location.getAbsolutePath();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,572 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
|
||||||
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredAuthentication;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredTransaction;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.URI;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.dom4j.Document;
|
|
||||||
import org.dom4j.DocumentException;
|
|
||||||
import org.dom4j.Element;
|
|
||||||
import org.dom4j.io.SAXReader;
|
|
||||||
import org.springframework.aop.framework.ProxyFactory;
|
|
||||||
import org.springframework.aop.support.RegexpMethodPointcutAdvisor;
|
|
||||||
import org.springframework.beans.BeansException;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.ApplicationContextAware;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Registry of declarative (scripted/template driven) api services
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class DeclarativeAPIRegistry implements APIRegistry, ApplicationContextAware, APIContextAware
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(DeclarativeAPIRegistry.class);
|
|
||||||
|
|
||||||
private ApplicationContext applicationContext;
|
|
||||||
private ServletContext servletContext;
|
|
||||||
private String defaultServiceImpl;
|
|
||||||
private MethodInterceptor authenticator;
|
|
||||||
private MethodInterceptor serviceLogger;
|
|
||||||
private MethodInterceptor serviceTransaction;
|
|
||||||
private FormatRegistry formatRegistry;
|
|
||||||
private APIStores stores;
|
|
||||||
|
|
||||||
// map of services by service id
|
|
||||||
// NOTE: The map is sorted by id (ascending order)
|
|
||||||
private Map<String, APIService> servicesById = new TreeMap<String, APIService>();
|
|
||||||
|
|
||||||
// map of services by url
|
|
||||||
// NOTE: The map is sorted by url (descending order)
|
|
||||||
private Map<String, APIService> servicesByURL = new TreeMap<String, APIService>(Collections.reverseOrder());
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialisation
|
|
||||||
//
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the available API Stores
|
|
||||||
*
|
|
||||||
* @param stores
|
|
||||||
*/
|
|
||||||
public void setStores(APIStores stores)
|
|
||||||
{
|
|
||||||
this.stores = stores;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service authenticator
|
|
||||||
*
|
|
||||||
* @param authenticator
|
|
||||||
*/
|
|
||||||
public void setAuthenticator(MethodInterceptor authenticator)
|
|
||||||
{
|
|
||||||
this.authenticator = authenticator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service logger
|
|
||||||
*
|
|
||||||
* @param serviceLogger
|
|
||||||
*/
|
|
||||||
public void setServiceLogger(MethodInterceptor serviceLogger)
|
|
||||||
{
|
|
||||||
this.serviceLogger = serviceLogger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the service transaction
|
|
||||||
*
|
|
||||||
* @param serviceTransaction
|
|
||||||
*/
|
|
||||||
public void setServiceTransaction(MethodInterceptor serviceTransaction)
|
|
||||||
{
|
|
||||||
this.serviceTransaction = serviceTransaction;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the default service implementation bean
|
|
||||||
*
|
|
||||||
* @param defaultServiceImpl
|
|
||||||
*/
|
|
||||||
public void setDefaultServiceImpl(String defaultServiceImpl)
|
|
||||||
{
|
|
||||||
this.defaultServiceImpl = defaultServiceImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the response format registry
|
|
||||||
*
|
|
||||||
* @param formatRegistry
|
|
||||||
*/
|
|
||||||
public void setFormatRegistry(FormatRegistry formatRegistry)
|
|
||||||
{
|
|
||||||
this.formatRegistry = formatRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIContextAware#setAPIContext(javax.servlet.ServletContext)
|
|
||||||
*/
|
|
||||||
public void setAPIContext(ServletContext context)
|
|
||||||
{
|
|
||||||
this.servletContext = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
|
||||||
*/
|
|
||||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
|
||||||
{
|
|
||||||
this.applicationContext = applicationContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise API Services
|
|
||||||
*
|
|
||||||
* Note: Each invocation of this method resets the list of the services
|
|
||||||
*/
|
|
||||||
public void initServices()
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Initialising Web API services");
|
|
||||||
|
|
||||||
// clear currently registered services
|
|
||||||
servicesById.clear();
|
|
||||||
servicesByURL.clear();
|
|
||||||
|
|
||||||
// register services
|
|
||||||
for (APIStore apiStore : stores.getAPIStores())
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Locating services within " + apiStore.getBasePath());
|
|
||||||
|
|
||||||
String basePath = apiStore.getBasePath();
|
|
||||||
String[] serviceDescPaths = apiStore.getDescriptionDocumentPaths();
|
|
||||||
for (String serviceDescPath : serviceDescPaths)
|
|
||||||
{
|
|
||||||
// build service description
|
|
||||||
APIDescription serviceDesc = null;
|
|
||||||
InputStream serviceDescIS = null;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
serviceDescIS = apiStore.getDescriptionDocument(serviceDescPath);
|
|
||||||
serviceDesc = createServiceDescription(basePath, serviceDescPath, serviceDescIS);
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
throw new APIException("Failed to read service description document " + apiStore.getBasePath() + serviceDescPath, e);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (serviceDescIS != null) serviceDescIS.close();
|
|
||||||
}
|
|
||||||
catch(IOException e)
|
|
||||||
{
|
|
||||||
// NOTE: ignore close exception
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine if service description has been registered
|
|
||||||
String id = serviceDesc.getId();
|
|
||||||
if (servicesById.containsKey(id))
|
|
||||||
{
|
|
||||||
// move to next service
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
APIService existingService = servicesById.get(id);
|
|
||||||
logger.debug("Service description document " + serviceDesc.getSourceLocation() + " overridden by " + existingService.getDescription().getSourceLocation());
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// construct service implementation
|
|
||||||
String serviceImplName = (applicationContext.containsBean("web.api." + id)) ? "web.api." + id : defaultServiceImpl;
|
|
||||||
AbstractAPIService serviceImpl = (AbstractAPIService)applicationContext.getBean(serviceImplName);
|
|
||||||
serviceImpl.setDescription(serviceDesc);
|
|
||||||
serviceImpl.init(this);
|
|
||||||
|
|
||||||
// wrap service implementation in appropriate interceptors (e.g. authentication)
|
|
||||||
APIService serviceImplIF = (APIService)serviceImpl;
|
|
||||||
if (serviceLogger != null && serviceTransaction != null && authenticator != null)
|
|
||||||
{
|
|
||||||
ProxyFactory authFactory = new ProxyFactory();
|
|
||||||
authFactory.addInterface(APIService.class);
|
|
||||||
authFactory.setTarget(serviceImplIF);
|
|
||||||
|
|
||||||
// logging interceptor
|
|
||||||
if (serviceLogger != null)
|
|
||||||
{
|
|
||||||
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", serviceLogger);
|
|
||||||
authFactory.addAdvisor(advisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// transaction interceptor
|
|
||||||
if (serviceDesc.getRequiredTransaction() != RequiredTransaction.none)
|
|
||||||
{
|
|
||||||
if (serviceTransaction == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Web API Transaction not specified");
|
|
||||||
}
|
|
||||||
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", serviceTransaction);
|
|
||||||
authFactory.addAdvisor(advisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// authentication interceptor
|
|
||||||
if (serviceDesc.getRequiredAuthentication() != RequiredAuthentication.none)
|
|
||||||
{
|
|
||||||
if (authenticator == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Web API Authenticator not specified");
|
|
||||||
}
|
|
||||||
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", authenticator);
|
|
||||||
authFactory.addAdvisor(advisor);
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceImplIF = (APIService)authFactory.getProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Found service " + serviceDescPath + " (id: " + id + ", impl: " + serviceImplName + ", auth: " + serviceDesc.getRequiredAuthentication() + ", trx: " + serviceDesc.getRequiredTransaction() + ")");
|
|
||||||
|
|
||||||
// register service and its urls
|
|
||||||
servicesById.put(id, serviceImplIF);
|
|
||||||
for (URI uri : serviceDesc.getURIs())
|
|
||||||
{
|
|
||||||
// establish static part of url template
|
|
||||||
String uriTemplate = uri.getURI();
|
|
||||||
int queryArgIdx = uriTemplate.indexOf('?');
|
|
||||||
if (queryArgIdx != -1)
|
|
||||||
{
|
|
||||||
uriTemplate = uriTemplate.substring(0, queryArgIdx);
|
|
||||||
}
|
|
||||||
int tokenIdx = uriTemplate.indexOf('{');
|
|
||||||
if (tokenIdx != -1)
|
|
||||||
{
|
|
||||||
uriTemplate = uriTemplate.substring(0, tokenIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// index service by static part of url (ensuring no other service has already claimed the url)
|
|
||||||
String uriIdx = serviceDesc.getMethod().toString() + ":" + uriTemplate;
|
|
||||||
if (servicesByURL.containsKey(uriIdx))
|
|
||||||
{
|
|
||||||
APIService existingService = servicesByURL.get(uriIdx);
|
|
||||||
if (!existingService.getDescription().getId().equals(serviceDesc.getId()))
|
|
||||||
{
|
|
||||||
throw new APIException("Service document " + existingService.getDescription().getSourceLocation() + " already defines the url '" + uriIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
servicesByURL.put(uriIdx, serviceImplIF);
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Registered Web API URL '" + uriIdx + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Registered " + servicesById.size() + " services; " + servicesByURL.size() + " URLs");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an API Service Description
|
|
||||||
*
|
|
||||||
* @param basePath
|
|
||||||
* @param serviceDescPath
|
|
||||||
* @param serviceDoc
|
|
||||||
*
|
|
||||||
* @return api service description
|
|
||||||
*/
|
|
||||||
private APIDescription createServiceDescription(String basePath, String serviceDescPath, InputStream serviceDoc)
|
|
||||||
{
|
|
||||||
SAXReader reader = new SAXReader();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Document document = reader.read(serviceDoc);
|
|
||||||
Element rootElement = document.getRootElement();
|
|
||||||
if (!rootElement.getName().equals("servicedescription"))
|
|
||||||
{
|
|
||||||
throw new APIException("Expected <servicedescription> root element - found <" + rootElement.getName() + ">");
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve id
|
|
||||||
String id = serviceDescPath.substring(0, serviceDescPath.lastIndexOf("_desc.xml")).replace('/', '.');
|
|
||||||
|
|
||||||
// retrieve http method
|
|
||||||
int methodIdx = id.lastIndexOf('_');
|
|
||||||
if (methodIdx == id.length() - 1)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to establish HTTP Method from service description: naming convention must be <name>_<method>_desc.xml");
|
|
||||||
}
|
|
||||||
String method = id.substring(id.lastIndexOf('_') + 1).toUpperCase();
|
|
||||||
|
|
||||||
// retrieve short name
|
|
||||||
Element shortNameElement = rootElement.element("shortname");
|
|
||||||
if (shortNameElement == null || shortNameElement.getTextTrim() == null || shortNameElement.getTextTrim().length() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Expected <shortname> value");
|
|
||||||
}
|
|
||||||
String shortName = shortNameElement.getTextTrim();
|
|
||||||
|
|
||||||
// retrieve description
|
|
||||||
Element descriptionElement = rootElement.element("description");
|
|
||||||
String description = descriptionElement.getTextTrim();
|
|
||||||
|
|
||||||
// retrieve urls
|
|
||||||
List urlElements = rootElement.elements("url");
|
|
||||||
if (urlElements == null || urlElements.size() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Expected at one <url> element");
|
|
||||||
}
|
|
||||||
List<APIDescription.URI> uris = new ArrayList<APIDescription.URI>();
|
|
||||||
Iterator iterElements = urlElements.iterator();
|
|
||||||
while(iterElements.hasNext())
|
|
||||||
{
|
|
||||||
// retrieve url element
|
|
||||||
Element urlElement = (Element)iterElements.next();
|
|
||||||
|
|
||||||
// retrieve url mimetype
|
|
||||||
String format = urlElement.attributeValue("format");
|
|
||||||
if (format == null)
|
|
||||||
{
|
|
||||||
// default to unspecified format
|
|
||||||
format = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve url template
|
|
||||||
String template = urlElement.attributeValue("template");
|
|
||||||
if (template == null || template.length() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Expected template attribute on <url> element");
|
|
||||||
}
|
|
||||||
|
|
||||||
APIDescriptionImpl.URIImpl uriImpl = new APIDescriptionImpl.URIImpl();
|
|
||||||
uriImpl.setFormat(format);
|
|
||||||
uriImpl.setUri(template);
|
|
||||||
uris.add(uriImpl);
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve authentication
|
|
||||||
RequiredAuthentication reqAuth = RequiredAuthentication.none;
|
|
||||||
Element authElement = rootElement.element("authentication");
|
|
||||||
if (authElement != null)
|
|
||||||
{
|
|
||||||
String reqAuthStr = authElement.getTextTrim();
|
|
||||||
if (reqAuthStr == null || reqAuthStr.length() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Expected <authentication> value");
|
|
||||||
}
|
|
||||||
reqAuth = RequiredAuthentication.valueOf(reqAuthStr);
|
|
||||||
if (reqAuth == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Authentication '" + reqAuthStr + "' is not a valid value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// retrieve transaction
|
|
||||||
RequiredTransaction reqTrx = (reqAuth == RequiredAuthentication.none) ? RequiredTransaction.none : RequiredTransaction.required;
|
|
||||||
Element trxElement = rootElement.element("transaction");
|
|
||||||
if (trxElement != null)
|
|
||||||
{
|
|
||||||
String reqTrxStr = trxElement.getTextTrim();
|
|
||||||
if (reqTrxStr == null || reqTrxStr.length() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Expected <transaction> value");
|
|
||||||
}
|
|
||||||
reqTrx = RequiredTransaction.valueOf(reqTrxStr);
|
|
||||||
if (reqTrx == null)
|
|
||||||
{
|
|
||||||
throw new APIException("Transaction '" + reqTrxStr + "' is not a valid value");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// construct service description
|
|
||||||
APIDescriptionImpl serviceDesc = new APIDescriptionImpl();
|
|
||||||
serviceDesc.setSourceLocation(basePath + "/" + serviceDescPath);
|
|
||||||
serviceDesc.setId(id);
|
|
||||||
serviceDesc.setShortName(shortName);
|
|
||||||
serviceDesc.setDescription(description);
|
|
||||||
serviceDesc.setRequiredAuthentication(reqAuth);
|
|
||||||
serviceDesc.setRequiredTransaction(reqTrx);
|
|
||||||
serviceDesc.setMethod(method);
|
|
||||||
serviceDesc.setUris(uris.toArray(new APIDescription.URI[uris.size()]));
|
|
||||||
serviceDesc.setDefaultFormat(uris.get(0).getFormat());
|
|
||||||
return serviceDesc;
|
|
||||||
}
|
|
||||||
catch(DocumentException e)
|
|
||||||
{
|
|
||||||
throw new APIException("Failed to parse service description document " + serviceDescPath, e);
|
|
||||||
}
|
|
||||||
catch(APIException e)
|
|
||||||
{
|
|
||||||
throw new APIException("Failed to parise service description document " + serviceDescPath, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getServices()
|
|
||||||
*/
|
|
||||||
public Collection<APIService> getServices()
|
|
||||||
{
|
|
||||||
return servicesById.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getService(java.lang.String)
|
|
||||||
*/
|
|
||||||
public APIService getService(String id)
|
|
||||||
{
|
|
||||||
return servicesById.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#findService(java.lang.String, java.lang.String)
|
|
||||||
*/
|
|
||||||
public APIServiceMatch findService(String method, String uri)
|
|
||||||
{
|
|
||||||
// TODO: Replace with more efficient approach
|
|
||||||
DeclarativeAPIServiceMatch apiServiceMatch = null;
|
|
||||||
String match = method.toString().toUpperCase() + ":" + uri;
|
|
||||||
for (Map.Entry<String, APIService> service : servicesByURL.entrySet())
|
|
||||||
{
|
|
||||||
String indexedPath = service.getKey();
|
|
||||||
if (match.startsWith(indexedPath))
|
|
||||||
{
|
|
||||||
String matchPath = indexedPath.substring(indexedPath.indexOf(':') +1);
|
|
||||||
apiServiceMatch = new DeclarativeAPIServiceMatch(matchPath, service.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return apiServiceMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getContext()
|
|
||||||
*/
|
|
||||||
public ServletContext getContext()
|
|
||||||
{
|
|
||||||
return servletContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getFormatRegistry()
|
|
||||||
*/
|
|
||||||
public FormatRegistry getFormatRegistry()
|
|
||||||
{
|
|
||||||
return this.formatRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getTemplateProcessor()
|
|
||||||
*/
|
|
||||||
public APITemplateProcessor getTemplateProcessor()
|
|
||||||
{
|
|
||||||
return this.stores.getTemplateProcessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIRegistry#getScriptProcessor()
|
|
||||||
*/
|
|
||||||
public APIScriptProcessor getScriptProcessor()
|
|
||||||
{
|
|
||||||
return this.stores.getScriptProcessor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.framework.APIRegistry#reset()
|
|
||||||
*/
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
getTemplateProcessor().resetCache();
|
|
||||||
getScriptProcessor().resetCache();
|
|
||||||
initServices();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Match
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public static class DeclarativeAPIServiceMatch implements APIServiceMatch
|
|
||||||
{
|
|
||||||
private String path;
|
|
||||||
private APIService service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param path
|
|
||||||
* @param service
|
|
||||||
*/
|
|
||||||
public DeclarativeAPIServiceMatch(String path, APIService service)
|
|
||||||
{
|
|
||||||
this.path = path;
|
|
||||||
this.service = service;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIServiceMatch#getPath()
|
|
||||||
*/
|
|
||||||
public String getPath()
|
|
||||||
{
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIServiceMatch#getService()
|
|
||||||
*/
|
|
||||||
public APIService getService()
|
|
||||||
{
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A map of mimetypes indexed by format.
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class FormatMap implements InitializingBean
|
|
||||||
{
|
|
||||||
private FormatRegistry registry;
|
|
||||||
private String agent;
|
|
||||||
private Map<String, String> formats;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the Format Registry
|
|
||||||
*
|
|
||||||
* @param registry
|
|
||||||
*/
|
|
||||||
public void setRegistry(FormatRegistry registry)
|
|
||||||
{
|
|
||||||
this.registry = registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the User Agent for which the formats apply
|
|
||||||
*
|
|
||||||
* @param agent
|
|
||||||
*/
|
|
||||||
public void setAgent(String agent)
|
|
||||||
{
|
|
||||||
this.agent = agent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the formats
|
|
||||||
*
|
|
||||||
* @param formats
|
|
||||||
*/
|
|
||||||
public void setFormats(Map<String, String> formats)
|
|
||||||
{
|
|
||||||
this.formats = formats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
||||||
*/
|
|
||||||
public void afterPropertiesSet() throws Exception
|
|
||||||
{
|
|
||||||
// Add formats to format registry
|
|
||||||
registry.addFormats(agent, formats);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,158 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maintains a registry of mimetypes (indexed by format and user agent)
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class FormatRegistry
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(FormatRegistry.class);
|
|
||||||
|
|
||||||
private Map<String, String> formats;
|
|
||||||
private Map<String, String> mimetypes;
|
|
||||||
private Map<String, Map<String, String>> agentFormats;
|
|
||||||
private Map<String, Map<String, String>> agentMimetypes;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*/
|
|
||||||
public FormatRegistry()
|
|
||||||
{
|
|
||||||
formats = new HashMap<String, String>();
|
|
||||||
mimetypes = new HashMap<String, String>();
|
|
||||||
agentFormats = new HashMap<String, Map<String, String>>();
|
|
||||||
agentMimetypes = new HashMap<String, Map<String, String>>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add formats
|
|
||||||
*
|
|
||||||
* @param agent
|
|
||||||
* @param formatsToAdd
|
|
||||||
*/
|
|
||||||
public void addFormats(String agent, Map<String, String> formatsToAdd)
|
|
||||||
{
|
|
||||||
// retrieve formats list for agent
|
|
||||||
Map<String, String> formatsForAgent = formats;
|
|
||||||
Map<String, String> mimetypesForAgent = mimetypes;
|
|
||||||
if (agent != null)
|
|
||||||
{
|
|
||||||
formatsForAgent = agentFormats.get(agent);
|
|
||||||
if (formatsForAgent == null)
|
|
||||||
{
|
|
||||||
formatsForAgent = new HashMap<String, String>();
|
|
||||||
mimetypesForAgent = new HashMap<String, String>();
|
|
||||||
agentFormats.put(agent, formatsForAgent);
|
|
||||||
agentMimetypes.put(agent, mimetypesForAgent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : formatsToAdd.entrySet())
|
|
||||||
{
|
|
||||||
if (logger.isWarnEnabled())
|
|
||||||
{
|
|
||||||
String mimetype = formatsForAgent.get(entry.getKey());
|
|
||||||
if (mimetype != null)
|
|
||||||
{
|
|
||||||
logger.warn("Replacing mime type '" + mimetype + "' with '" + entry.getValue() + "' for API format '" + entry.getKey() + "' (agent: " + agent + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
formatsForAgent.put(entry.getKey(), entry.getValue());
|
|
||||||
mimetypesForAgent.put(entry.getValue(), entry.getKey());
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Registered API format '" + entry.getKey() + "' with mime type '" + entry.getValue() + "' (agent: " + agent + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the mimetype for the specified user agent and format
|
|
||||||
*
|
|
||||||
* @param agent
|
|
||||||
* @param format
|
|
||||||
* @return mimetype (or null, if one is not registered)
|
|
||||||
*/
|
|
||||||
public String getMimeType(String agent, String format)
|
|
||||||
{
|
|
||||||
String mimetype = null;
|
|
||||||
|
|
||||||
if (agent != null)
|
|
||||||
{
|
|
||||||
Map<String, String> formatsForAgent = agentFormats.get(agent);
|
|
||||||
if (formatsForAgent != null)
|
|
||||||
{
|
|
||||||
mimetype = formatsForAgent.get(format);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mimetype == null)
|
|
||||||
{
|
|
||||||
mimetype = formats.get(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mimetype;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the format for the specified user agent and mimetype
|
|
||||||
*
|
|
||||||
* @param agent
|
|
||||||
* @param mimetype
|
|
||||||
* @return format (or null, if one is not registered)
|
|
||||||
*/
|
|
||||||
public String getFormat(String agent, String mimetype)
|
|
||||||
{
|
|
||||||
String format = null;
|
|
||||||
|
|
||||||
if (agent != null)
|
|
||||||
{
|
|
||||||
Map<String, String> mimetypesForAgent = agentMimetypes.get(agent);
|
|
||||||
if (mimetypesForAgent != null)
|
|
||||||
{
|
|
||||||
format = mimetypesForAgent.get(mimetype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format == null)
|
|
||||||
{
|
|
||||||
format = mimetypes.get(mimetype);
|
|
||||||
}
|
|
||||||
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Composite script loader
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class MultiScriptLoader implements ScriptLoader
|
|
||||||
{
|
|
||||||
private ScriptLoader[] loaders;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param loaders
|
|
||||||
*/
|
|
||||||
public MultiScriptLoader(ScriptLoader[] loaders)
|
|
||||||
{
|
|
||||||
this.loaders = loaders;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.ScriptLoader#getScriptLocation(java.lang.String)
|
|
||||||
*/
|
|
||||||
public ScriptLocation getScriptLocation(String path)
|
|
||||||
{
|
|
||||||
ScriptLocation location = null;
|
|
||||||
for (ScriptLoader loader : loaders)
|
|
||||||
{
|
|
||||||
location = loader.getScriptLocation(path);
|
|
||||||
if (location != null)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,578 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.transaction.TransactionUtil;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
|
||||||
import org.alfresco.service.cmr.repository.NodeService;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
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.namespace.NamespaceService;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
import org.alfresco.util.AbstractLifecycleBean;
|
|
||||||
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.TemplateLoader;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Repository based API Store
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class RepoPathAPIStore implements APIStore, ApplicationContextAware, ApplicationListener
|
|
||||||
{
|
|
||||||
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
|
|
||||||
protected StoreRef repoStore;
|
|
||||||
protected String repoPath;
|
|
||||||
protected NodeRef baseNodeRef;
|
|
||||||
protected String baseDir;
|
|
||||||
|
|
||||||
// dependencies
|
|
||||||
protected TransactionService transactionService;
|
|
||||||
protected SearchService searchService;
|
|
||||||
protected NodeService nodeService;
|
|
||||||
protected ContentService contentService;
|
|
||||||
protected NamespaceService namespaceService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets transaction service
|
|
||||||
*
|
|
||||||
* @param transactionService
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 content service
|
|
||||||
*
|
|
||||||
* @param contentService
|
|
||||||
*/
|
|
||||||
public void setContentService(ContentService contentService)
|
|
||||||
{
|
|
||||||
this.contentService = contentService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the namespace service
|
|
||||||
*
|
|
||||||
* @param namespaceService
|
|
||||||
*/
|
|
||||||
public void setNamespaceService(NamespaceService namespaceService)
|
|
||||||
{
|
|
||||||
this.namespaceService = namespaceService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the repo store
|
|
||||||
*
|
|
||||||
* @param repoStore
|
|
||||||
*/
|
|
||||||
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.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)
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onShutdown(ApplicationEvent event)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
|
||||||
*/
|
|
||||||
protected void init()
|
|
||||||
{
|
|
||||||
AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>()
|
|
||||||
{
|
|
||||||
public Object doWork() throws Exception
|
|
||||||
{
|
|
||||||
return TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<Object>()
|
|
||||||
{
|
|
||||||
public Object doWork() throws Exception
|
|
||||||
{
|
|
||||||
String query = "PATH:\"" + repoPath + "\"";
|
|
||||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
|
||||||
if (resultSet.length() == 0)
|
|
||||||
{
|
|
||||||
throw new APIException("Unable to locate repository path " + repoStore.toString() + repoPath);
|
|
||||||
}
|
|
||||||
if (resultSet.length() > 1)
|
|
||||||
{
|
|
||||||
throw new APIException("Multiple repository paths found for " + repoStore.toString() + repoPath);
|
|
||||||
}
|
|
||||||
baseNodeRef = resultSet.getNodeRef(0);
|
|
||||||
baseDir = getPath(baseNodeRef);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#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) + "/" + 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)
|
|
||||||
{
|
|
||||||
StringBuilder xpath = new StringBuilder(documentPath.length() << 1);
|
|
||||||
for (StringTokenizer t = new StringTokenizer(documentPath, "/"); t.hasMoreTokens(); /**/)
|
|
||||||
{
|
|
||||||
if (xpath.length() != 0)
|
|
||||||
{
|
|
||||||
xpath.append('/');
|
|
||||||
}
|
|
||||||
xpath.append("*[@cm:name='").append(t.nextToken()).append("']");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<NodeRef> nodes = searchService.selectNodes(baseNodeRef, xpath.toString(), null, namespaceService, false);
|
|
||||||
return (nodes.size() == 1) ? nodes.get(0) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getDescriptionDocumentPaths()
|
|
||||||
*/
|
|
||||||
public String[] getDescriptionDocumentPaths()
|
|
||||||
{
|
|
||||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<String[]>()
|
|
||||||
{
|
|
||||||
public String[] doWork() throws Exception
|
|
||||||
{
|
|
||||||
return TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<String[]>()
|
|
||||||
{
|
|
||||||
public String[] doWork() throws Exception
|
|
||||||
{
|
|
||||||
int baseDirLength = baseDir.length() +1;
|
|
||||||
List<String> documentPaths = new ArrayList<String>();
|
|
||||||
|
|
||||||
String query = "PATH:\"" + repoPath + "//*\" AND @cm\\:name:\"*_desc.xml\"";
|
|
||||||
ResultSet resultSet = searchService.query(repoStore, SearchService.LANGUAGE_LUCENE, query);
|
|
||||||
List<NodeRef> nodes = resultSet.getNodeRefs();
|
|
||||||
for (NodeRef nodeRef : nodes)
|
|
||||||
{
|
|
||||||
String nodeDir = getPath(nodeRef);
|
|
||||||
String documentPath = nodeDir.substring(baseDirLength);
|
|
||||||
documentPaths.add(documentPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return documentPaths.toArray(new String[documentPaths.size()]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getDescriptionDocument(java.lang.String)
|
|
||||||
*/
|
|
||||||
public InputStream getDescriptionDocument(final String documentPath)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<InputStream>()
|
|
||||||
{
|
|
||||||
public InputStream doWork() throws Exception
|
|
||||||
{
|
|
||||||
return TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<InputStream>()
|
|
||||||
{
|
|
||||||
public InputStream doWork() throws Exception
|
|
||||||
{
|
|
||||||
NodeRef nodeRef = findNodeRef(documentPath);
|
|
||||||
if (nodeRef == null)
|
|
||||||
{
|
|
||||||
throw new IOException("Description document " + documentPath + " does not exist.");
|
|
||||||
}
|
|
||||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
|
||||||
return reader.getContentInputStream();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getTemplateLoader()
|
|
||||||
*/
|
|
||||||
public TemplateLoader getTemplateLoader()
|
|
||||||
{
|
|
||||||
return new RepoTemplateLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIStore#getScriptLoader()
|
|
||||||
*/
|
|
||||||
public ScriptLoader getScriptLoader()
|
|
||||||
{
|
|
||||||
return new RepoScriptLoader();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<Object>()
|
|
||||||
{
|
|
||||||
public Object doWork() 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 TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<Long>()
|
|
||||||
{
|
|
||||||
public Long doWork() 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 TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<Reader>()
|
|
||||||
{
|
|
||||||
public Reader doWork() throws Exception
|
|
||||||
{
|
|
||||||
ContentReader reader = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT);
|
|
||||||
return new InputStreamReader(reader.getContentInputStream());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Repository path based script loader
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
private class RepoScriptLoader implements ScriptLoader
|
|
||||||
{
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.ScriptLoader#getScriptLocation(java.lang.String)
|
|
||||||
*/
|
|
||||||
public ScriptLocation getScriptLocation(final String path)
|
|
||||||
{
|
|
||||||
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptLocation>()
|
|
||||||
{
|
|
||||||
public ScriptLocation doWork() throws Exception
|
|
||||||
{
|
|
||||||
return TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<ScriptLocation>()
|
|
||||||
{
|
|
||||||
public ScriptLocation doWork() throws Exception
|
|
||||||
{
|
|
||||||
ScriptLocation location = null;
|
|
||||||
NodeRef nodeRef = findNodeRef(path);
|
|
||||||
if (nodeRef != null)
|
|
||||||
{
|
|
||||||
location = new RepoScriptLocation(path, nodeRef);
|
|
||||||
}
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, AuthenticationUtil.getSystemUserName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Repo path script location
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
private class RepoScriptLocation implements ScriptLocation
|
|
||||||
{
|
|
||||||
protected String path;
|
|
||||||
protected NodeRef nodeRef;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param location
|
|
||||||
*/
|
|
||||||
public RepoScriptLocation(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 TransactionUtil.executeInUserTransaction(transactionService, new TransactionUtil.TransactionWork<InputStream>()
|
|
||||||
{
|
|
||||||
public InputStream doWork() 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()
|
|
||||||
{
|
|
||||||
return new InputStreamReader(getInputStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return repoStore + "/" + baseDir + "/" + path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Locate a script
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public interface ScriptLoader
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the script location for the script at the specified path
|
|
||||||
*
|
|
||||||
* @param path path within api store
|
|
||||||
* @return script location (or null, if script does not exist at path)
|
|
||||||
*/
|
|
||||||
ScriptLocation getScriptLocation(String path);
|
|
||||||
|
|
||||||
}
|
|
@@ -1,222 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.alfresco.repo.jscript.Node;
|
|
||||||
import org.alfresco.repo.jscript.ScriptableHashMap;
|
|
||||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
|
||||||
import org.alfresco.service.cmr.repository.TemplateException;
|
|
||||||
import org.alfresco.service.cmr.repository.TemplateNode;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.mozilla.javascript.Context;
|
|
||||||
import org.mozilla.javascript.NativeArray;
|
|
||||||
import org.mozilla.javascript.Wrapper;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Script/template driven based implementation of an API Service
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class ScriptedAPIService extends AbstractAPIService
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(ScriptedAPIService.class);
|
|
||||||
|
|
||||||
private String baseTemplatePath;
|
|
||||||
private ScriptLocation executeScript;
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.AbstractAPIService#init(org.alfresco.web.api.APIRegistry)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void init(APIRegistry apiRegistry)
|
|
||||||
{
|
|
||||||
super.init(apiRegistry);
|
|
||||||
baseTemplatePath = getDescription().getId().replace('.', '/');
|
|
||||||
|
|
||||||
// Test for "execute" script
|
|
||||||
String scriptPath = baseTemplatePath + ".js";
|
|
||||||
executeScript = getAPIRegistry().getScriptProcessor().findScript(scriptPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.alfresco.web.api.APIService#execute(org.alfresco.web.api.APIRequest, org.alfresco.web.api.APIResponse)
|
|
||||||
*/
|
|
||||||
final public void execute(APIRequest req, APIResponse res) throws IOException
|
|
||||||
{
|
|
||||||
// construct data model for template
|
|
||||||
Map<String, Object> model = executeImpl(req, res);
|
|
||||||
if (model == null)
|
|
||||||
{
|
|
||||||
model = new HashMap<String, Object>(7, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute script if it exists
|
|
||||||
if (executeScript != null)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Executing script " + executeScript);
|
|
||||||
|
|
||||||
Map<String, Object> scriptModel = createScriptModel(req, res, model);
|
|
||||||
// add return model allowing script to add items to template model
|
|
||||||
Map<String, Object> returnModel = new ScriptableHashMap<String, Object>();
|
|
||||||
scriptModel.put("model", returnModel);
|
|
||||||
executeScript(executeScript, scriptModel);
|
|
||||||
mergeScriptModelIntoTemplateModel(returnModel, model);
|
|
||||||
}
|
|
||||||
|
|
||||||
// process requested format
|
|
||||||
String format = req.getFormat();
|
|
||||||
if (format == null || format.length() == 0)
|
|
||||||
{
|
|
||||||
format = getDescription().getDefaultFormat();
|
|
||||||
}
|
|
||||||
|
|
||||||
String mimetype = getAPIRegistry().getFormatRegistry().getMimeType(req.getAgent(), format);
|
|
||||||
if (mimetype == null)
|
|
||||||
{
|
|
||||||
throw new APIException("API format '" + format + "' is not registered");
|
|
||||||
}
|
|
||||||
|
|
||||||
// render output
|
|
||||||
res.setContentType(mimetype + ";charset=UTF-8");
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Response content type: " + mimetype);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Map<String, Object> templateModel = createTemplateModel(req, res, model);
|
|
||||||
renderFormatTemplate(format, templateModel, res.getWriter());
|
|
||||||
}
|
|
||||||
catch(TemplateException e)
|
|
||||||
{
|
|
||||||
throw new APIException("Failed to process format '" + format + "'", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Merge script generated model into template-ready model
|
|
||||||
*
|
|
||||||
* @param scriptModel script model
|
|
||||||
* @param templateModel template model
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
final private void mergeScriptModelIntoTemplateModel(Map<String, Object> scriptModel, Map<String, Object> templateModel)
|
|
||||||
{
|
|
||||||
for (Map.Entry<String, Object> entry : scriptModel.entrySet())
|
|
||||||
{
|
|
||||||
// retrieve script model value
|
|
||||||
Object value = entry.getValue();
|
|
||||||
|
|
||||||
// convert from js to java, if required
|
|
||||||
if (value instanceof Wrapper)
|
|
||||||
{
|
|
||||||
value = ((Wrapper)value).unwrap();
|
|
||||||
}
|
|
||||||
else if (value instanceof NativeArray)
|
|
||||||
{
|
|
||||||
value = Context.jsToJava(value, Object[].class);
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert script node to template node, if required
|
|
||||||
if (value instanceof Node)
|
|
||||||
{
|
|
||||||
value = new TemplateNode(((Node)value).getNodeRef(), getServiceRegistry(), null);
|
|
||||||
}
|
|
||||||
else if (value instanceof Collection)
|
|
||||||
{
|
|
||||||
Collection coll = (Collection)value;
|
|
||||||
Collection templateColl = new ArrayList(coll.size());
|
|
||||||
for (Object object : coll)
|
|
||||||
{
|
|
||||||
if (value instanceof Node)
|
|
||||||
{
|
|
||||||
templateColl.add(new TemplateNode(((Node)object).getNodeRef(), getServiceRegistry(), null));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
templateColl.add(object);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value = templateColl;
|
|
||||||
}
|
|
||||||
else if (value instanceof Node[])
|
|
||||||
{
|
|
||||||
Node[] nodes = (Node[])value;
|
|
||||||
TemplateNode[] templateNodes = new TemplateNode[nodes.length];
|
|
||||||
int i = 0;
|
|
||||||
for (Node node : nodes)
|
|
||||||
{
|
|
||||||
templateNodes[i++] = new TemplateNode(node.getNodeRef(), getServiceRegistry(), null);
|
|
||||||
}
|
|
||||||
value = templateNodes;
|
|
||||||
}
|
|
||||||
templateModel.put(entry.getKey(), value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute custom Java logic
|
|
||||||
*
|
|
||||||
* @param req API request
|
|
||||||
* @param res API response
|
|
||||||
* @param model basic API model
|
|
||||||
* @return custom service model
|
|
||||||
*/
|
|
||||||
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render a template (of given format) to the API Response
|
|
||||||
*
|
|
||||||
* @param format template format (null, default format)
|
|
||||||
* @param model data model to render
|
|
||||||
* @param writer where to output
|
|
||||||
*/
|
|
||||||
final protected void renderFormatTemplate(String format, Map<String, Object> model, Writer writer)
|
|
||||||
{
|
|
||||||
format = (format == null) ? "" : format;
|
|
||||||
String templatePath = baseTemplatePath + "_" + format + ".ftl";
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Rendering service template '" + templatePath + "'");
|
|
||||||
|
|
||||||
renderTemplate(templatePath, model, writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,169 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.service.descriptor.Descriptor;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Script / Template Model representing Repository Server meta-data
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class ServerModel
|
|
||||||
{
|
|
||||||
private Descriptor serverDescriptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param serverDescriptor
|
|
||||||
*/
|
|
||||||
/*package*/ ServerModel(Descriptor serverDescriptor)
|
|
||||||
{
|
|
||||||
this.serverDescriptor = serverDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the major version number, e.g. <u>1</u>.2.3
|
|
||||||
*
|
|
||||||
* @return major version number
|
|
||||||
*/
|
|
||||||
public String getVersionMajor()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersionMajor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_versionMajor()
|
|
||||||
{
|
|
||||||
return getVersionMajor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the minor version number, e.g. 1.<u>2</u>.3
|
|
||||||
*
|
|
||||||
* @return minor version number
|
|
||||||
*/
|
|
||||||
public String getVersionMinor()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersionMinor();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_versionMinor()
|
|
||||||
{
|
|
||||||
return getVersionMinor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the version revision number, e.g. 1.2.<u>3</u>
|
|
||||||
*
|
|
||||||
* @return revision number
|
|
||||||
*/
|
|
||||||
public String getVersionRevision()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersionRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_versionRevision()
|
|
||||||
{
|
|
||||||
return getVersionRevision();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the version label
|
|
||||||
*
|
|
||||||
* @return the version label
|
|
||||||
*/
|
|
||||||
public String getVersionLabel()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersionLabel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_versionLabel()
|
|
||||||
{
|
|
||||||
return getVersionLabel();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the build number
|
|
||||||
*
|
|
||||||
* @return the build number i.e. build-1
|
|
||||||
*/
|
|
||||||
public String getVersionBuild()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersionBuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_versionBuild()
|
|
||||||
{
|
|
||||||
return getVersionBuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the full version number
|
|
||||||
*
|
|
||||||
* @return full version number as major.minor.revision (label)
|
|
||||||
*/
|
|
||||||
public String getVersion()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_version()
|
|
||||||
{
|
|
||||||
return getVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the edition
|
|
||||||
*
|
|
||||||
* @return the edition
|
|
||||||
*/
|
|
||||||
public String getEdition()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getEdition();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_edition()
|
|
||||||
{
|
|
||||||
return getEdition();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the schema number
|
|
||||||
*
|
|
||||||
* @return a positive integer
|
|
||||||
*/
|
|
||||||
public int getSchema()
|
|
||||||
{
|
|
||||||
return serverDescriptor.getSchema();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int jsGet_schema()
|
|
||||||
{
|
|
||||||
return getSchema();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.i18n.I18NUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Logger
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class ServiceLogger implements MethodInterceptor
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(ServiceLogger.class);
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
Object retVal = null;
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
APIService service = (APIService)invocation.getThis();
|
|
||||||
APIDescription description = service.getDescription();
|
|
||||||
String user = AuthenticationUtil.getCurrentUserName();
|
|
||||||
String locale = I18NUtil.getLocale().toString();
|
|
||||||
logger.debug("Invoking service " + description.getId() + (user == null ? " (unauthenticated)" : " (authenticated as " + user + ")" + " (" + locale + ")"));
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
long end = System.currentTimeMillis();
|
|
||||||
logger.debug("Service " + description.getId() + " executed in " + (end - start) + "ms");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.repo.transaction.TransactionUtil;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
import org.alfresco.web.api.framework.APIDescription.RequiredTransaction;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* API Service Transaction
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class ServiceTransaction implements MethodInterceptor
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
protected static final Log logger = LogFactory.getLog(ServiceTransaction.class);
|
|
||||||
|
|
||||||
// dependencies
|
|
||||||
private TransactionService transactionService;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the transaction service
|
|
||||||
*
|
|
||||||
* @param transactionService
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(final MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
APIService service = (APIService)invocation.getThis();
|
|
||||||
final APIDescription description = service.getDescription();
|
|
||||||
|
|
||||||
// encapsulate service call within transaction
|
|
||||||
TransactionUtil.TransactionWork<Object> work = new TransactionUtil.TransactionWork<Object>()
|
|
||||||
{
|
|
||||||
public Object doWork() throws Throwable
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Begin transaction: " + description.getRequiredTransaction());
|
|
||||||
|
|
||||||
Object retVal = invocation.proceed();
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("End transaction: " + description.getRequiredTransaction());
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// execute call within transaction
|
|
||||||
Object retVal;
|
|
||||||
if (description.getRequiredTransaction() == RequiredTransaction.required)
|
|
||||||
{
|
|
||||||
retVal = TransactionUtil.executeInUserTransaction(transactionService, work);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retVal = TransactionUtil.executeInNonPropagatingUserTransaction(transactionService, work);
|
|
||||||
}
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* System Authentication Interceptor
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class SystemAuthenticator implements MethodInterceptor
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(SystemAuthenticator.class);
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
String currentUser = null;
|
|
||||||
Object retVal = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Determine if user already authenticated
|
|
||||||
//
|
|
||||||
|
|
||||||
currentUser = AuthenticationUtil.getCurrentUserName();
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Force system user
|
|
||||||
//
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authenticating as System");
|
|
||||||
|
|
||||||
AuthenticationUtil.setSystemUserAsCurrentUser();
|
|
||||||
|
|
||||||
//
|
|
||||||
// Invoke service
|
|
||||||
//
|
|
||||||
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.clearCurrentSecurityContext();
|
|
||||||
if (currentUser != null)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.setCurrentUser(currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,310 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
|
|
||||||
import org.alfresco.i18n.I18NUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
|
||||||
import org.alfresco.repo.transaction.TransactionUtil;
|
|
||||||
import org.alfresco.service.transaction.TransactionService;
|
|
||||||
import org.springframework.context.ApplicationContext;
|
|
||||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stand-alone Web API Test Server
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class TestAPIServer
|
|
||||||
{
|
|
||||||
// dependencies
|
|
||||||
protected TransactionService transactionService;
|
|
||||||
protected DeclarativeAPIRegistry apiRegistry;
|
|
||||||
|
|
||||||
/** The reader for interaction. */
|
|
||||||
private BufferedReader fIn;
|
|
||||||
|
|
||||||
/** Last command issued */
|
|
||||||
private String lastCommand = null;
|
|
||||||
|
|
||||||
/** Current user */
|
|
||||||
private String username = "admin";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the transaction service
|
|
||||||
*
|
|
||||||
* @param transactionService
|
|
||||||
*/
|
|
||||||
public void setTransactionService(TransactionService transactionService)
|
|
||||||
{
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the API Registry
|
|
||||||
*
|
|
||||||
* @param apiRegistry
|
|
||||||
*/
|
|
||||||
public void setAPIRegistry(DeclarativeAPIRegistry apiRegistry)
|
|
||||||
{
|
|
||||||
this.apiRegistry = apiRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialise the Test API Server
|
|
||||||
*
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public void init() throws Exception
|
|
||||||
{
|
|
||||||
apiRegistry.initServices();
|
|
||||||
fIn = new BufferedReader(new InputStreamReader(System.in));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main entry point.
|
|
||||||
*/
|
|
||||||
public static void main(String[] args)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/application-context.xml", "classpath:alfresco/web-api-application-context.xml", "classpath:alfresco/web-api-application-context-test.xml" };
|
|
||||||
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
|
|
||||||
TestAPIServer testServer = (TestAPIServer)context.getBean("web.api.framework.test");
|
|
||||||
testServer.init();
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Read-Eval-Print loop.
|
|
||||||
*/
|
|
||||||
public void rep()
|
|
||||||
{
|
|
||||||
// accept commands
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
System.out.print("ok> ");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// get command
|
|
||||||
final String line = fIn.readLine();
|
|
||||||
if (line.equals("exit") || line.equals("quit"))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// execute command in context of currently selected user
|
|
||||||
long startms = System.currentTimeMillis();
|
|
||||||
System.out.print(interpretCommand(line));
|
|
||||||
System.out.println("" + (System.currentTimeMillis() - startms) + "ms");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
e.printStackTrace(System.err);
|
|
||||||
System.out.println("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public String interpretCommand(final String line)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
// execute command in context of currently selected user
|
|
||||||
return AuthenticationUtil.runAs(new RunAsWork<String>()
|
|
||||||
{
|
|
||||||
public String doWork() throws Exception
|
|
||||||
{
|
|
||||||
return executeCommand(line);
|
|
||||||
}
|
|
||||||
}, username);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute a single command using the BufferedReader passed in for any data needed.
|
|
||||||
*
|
|
||||||
* TODO: Use decent parser!
|
|
||||||
*
|
|
||||||
* @param line The unparsed command
|
|
||||||
* @return The textual output of the command.
|
|
||||||
*/
|
|
||||||
protected String executeCommand(String line)
|
|
||||||
throws IOException
|
|
||||||
{
|
|
||||||
String[] command = line.split(" ");
|
|
||||||
if (command.length == 0)
|
|
||||||
{
|
|
||||||
command = new String[1];
|
|
||||||
command[0] = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
||||||
PrintStream out = new PrintStream(bout);
|
|
||||||
|
|
||||||
// repeat last command?
|
|
||||||
if (command[0].equals("r"))
|
|
||||||
{
|
|
||||||
if (lastCommand == null)
|
|
||||||
{
|
|
||||||
return "No command entered yet.";
|
|
||||||
}
|
|
||||||
return "repeating command " + lastCommand + "\n\n" + interpretCommand(lastCommand);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remember last command
|
|
||||||
lastCommand = line;
|
|
||||||
|
|
||||||
// execute command
|
|
||||||
if (command[0].equals("help"))
|
|
||||||
{
|
|
||||||
// TODO:
|
|
||||||
String helpFile = I18NUtil.getMessage("test_service.help");
|
|
||||||
ClassPathResource helpResource = new ClassPathResource(helpFile);
|
|
||||||
byte[] helpBytes = new byte[500];
|
|
||||||
InputStream helpStream = helpResource.getInputStream();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int read = helpStream.read(helpBytes);
|
|
||||||
while (read != -1)
|
|
||||||
{
|
|
||||||
bout.write(helpBytes, 0, read);
|
|
||||||
read = helpStream.read(helpBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
helpStream.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (command[0].equals("user"))
|
|
||||||
{
|
|
||||||
if (command.length == 2)
|
|
||||||
{
|
|
||||||
username = command[1];
|
|
||||||
}
|
|
||||||
out.println("using user " + username);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (command[0].equals("get"))
|
|
||||||
{
|
|
||||||
if (command.length < 2)
|
|
||||||
{
|
|
||||||
return "Syntax Error.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
String uri = command[1];
|
|
||||||
MockHttpServletRequest req = createRequest("get", uri);
|
|
||||||
MockHttpServletResponse res = new MockHttpServletResponse();
|
|
||||||
|
|
||||||
APIServiceMatch match = apiRegistry.findService(req.getMethod(), uri);
|
|
||||||
if (match == null)
|
|
||||||
{
|
|
||||||
throw new APIException("No service bound to uri '" + uri + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
APIRequest apiReq = new APIRequest(req, match);
|
|
||||||
APIResponse apiRes = new APIResponse(res);
|
|
||||||
match.getService().execute(apiReq, apiRes);
|
|
||||||
bout.write(res.getContentAsByteArray());
|
|
||||||
out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return "Syntax Error.\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
out.flush();
|
|
||||||
String retVal = new String(bout.toByteArray());
|
|
||||||
out.close();
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a Mock HTTP Servlet Request
|
|
||||||
*
|
|
||||||
* @param method
|
|
||||||
* @param uri
|
|
||||||
* @return mock http servlet request
|
|
||||||
*/
|
|
||||||
private MockHttpServletRequest createRequest(String method, String uri)
|
|
||||||
{
|
|
||||||
MockHttpServletRequest req = new MockHttpServletRequest("get", uri);
|
|
||||||
|
|
||||||
// set parameters
|
|
||||||
int iArgIndex = uri.indexOf('?');
|
|
||||||
if (iArgIndex != -1 && iArgIndex != uri.length() -1)
|
|
||||||
{
|
|
||||||
String uriArgs = uri.substring(iArgIndex +1);
|
|
||||||
String[] args = uriArgs.split("&");
|
|
||||||
for (String arg : args)
|
|
||||||
{
|
|
||||||
String[] parts = arg.split("=");
|
|
||||||
req.addParameter(parts[0], (parts.length == 2) ? parts[1] : null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set paths
|
|
||||||
req.setContextPath("/alfresco");
|
|
||||||
req.setServletPath("/service");
|
|
||||||
req.setPathInfo(iArgIndex == -1 ? uri : uri.substring(0, iArgIndex));
|
|
||||||
|
|
||||||
return req;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
|
||||||
import org.aopalliance.intercept.MethodInvocation;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trusted Authentication Interceptor
|
|
||||||
*
|
|
||||||
* Just use the currently authenticated user
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class TrustedAuthenticator implements MethodInterceptor
|
|
||||||
{
|
|
||||||
// Logger
|
|
||||||
private static final Log logger = LogFactory.getLog(TrustedAuthenticator.class);
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
|
|
||||||
*/
|
|
||||||
public Object invoke(MethodInvocation invocation)
|
|
||||||
throws Throwable
|
|
||||||
{
|
|
||||||
String currentUser = null;
|
|
||||||
Object retVal = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//
|
|
||||||
// Determine if user already authenticated
|
|
||||||
//
|
|
||||||
|
|
||||||
currentUser = AuthenticationUtil.getCurrentUserName();
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
|
|
||||||
//
|
|
||||||
// Use current authentication
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Invoke service
|
|
||||||
//
|
|
||||||
|
|
||||||
retVal = invocation.proceed();
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
AuthenticationUtil.clearCurrentSecurityContext();
|
|
||||||
if (currentUser != null)
|
|
||||||
{
|
|
||||||
AuthenticationUtil.setCurrentUser(currentUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.web.api.framework;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Script / Template Model representing API Service URLs
|
|
||||||
*
|
|
||||||
* @author davidc
|
|
||||||
*/
|
|
||||||
public class URLModel
|
|
||||||
{
|
|
||||||
private APIRequest req;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct
|
|
||||||
*
|
|
||||||
* @param req
|
|
||||||
*/
|
|
||||||
URLModel(APIRequest req)
|
|
||||||
{
|
|
||||||
this.req = req;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Context Path
|
|
||||||
*
|
|
||||||
* e.g. /alfresco
|
|
||||||
*
|
|
||||||
* @return context path
|
|
||||||
*/
|
|
||||||
public String getContext()
|
|
||||||
{
|
|
||||||
return req.getContextPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_context()
|
|
||||||
{
|
|
||||||
return getContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Service Context Path
|
|
||||||
*
|
|
||||||
* e.g. /alfresco/service
|
|
||||||
*
|
|
||||||
* @return service context path
|
|
||||||
*/
|
|
||||||
public String getServiceContext()
|
|
||||||
{
|
|
||||||
return req.getServiceContextPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_serviceContext()
|
|
||||||
{
|
|
||||||
return getServiceContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Service Path
|
|
||||||
*
|
|
||||||
* e.g. /alfresco/service/search/keyword
|
|
||||||
*
|
|
||||||
* @return service path
|
|
||||||
*/
|
|
||||||
public String getService()
|
|
||||||
{
|
|
||||||
return req.getServicePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_service()
|
|
||||||
{
|
|
||||||
return getService();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the full path
|
|
||||||
*
|
|
||||||
* e.g. /alfresco/service/search/keyword?q=term
|
|
||||||
*
|
|
||||||
* @return service path
|
|
||||||
*/
|
|
||||||
public String getFull()
|
|
||||||
{
|
|
||||||
return req.getURL();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_full()
|
|
||||||
{
|
|
||||||
return getFull();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the matching service path
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* a) service registered path = /search/engine
|
|
||||||
* b) request path = /search/engine/external
|
|
||||||
*
|
|
||||||
* => /search/engine
|
|
||||||
*
|
|
||||||
* @return matching path
|
|
||||||
*/
|
|
||||||
public String getMatch()
|
|
||||||
{
|
|
||||||
return getServiceContext() + req.getServiceMatch().getPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_match()
|
|
||||||
{
|
|
||||||
return getMatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Service Extension Path
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* a) service registered path = /search/engine
|
|
||||||
* b) request path = /search/engine/external
|
|
||||||
*
|
|
||||||
* => /external
|
|
||||||
*
|
|
||||||
* @return extension path
|
|
||||||
*/
|
|
||||||
public String getExtension()
|
|
||||||
{
|
|
||||||
return req.getExtensionPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String jsGet_extension()
|
|
||||||
{
|
|
||||||
return getExtension();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Reference in New Issue
Block a user