Merged V2.0 to HEAD

svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@5118 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@5119 .
   - OpenSearch Proxy
   svn merge svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@5121 svn://svn.alfresco.com:3691/alfresco/BRANCHES/V2.0@5122 .
   - Extract sample OpenSearch engine registrations into extension config file.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5125 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-02-13 21:21:48 +00:00
parent 2d5a480d85
commit 9067948404
14 changed files with 861 additions and 25 deletions

View File

@@ -0,0 +1,43 @@
<!-- -->
<!-- Example configuration of multiple OpenSearch engines -->
<!-- -->
<alfresco-config>
<config evaluator="string-compare" condition="OpenSearch">
<opensearch>
<engines>
<!-- -->
<!-- Example: Registration of remote Alfresco Server -->
<!-- -->
<!-- TODO: Find/Replace [host] with server host name -->
<!-- TODO: Find/Replace [port] with server port number -->
<engine label="Remote Alfresco Repository" proxy="remote">
<url type="application/atom+xml">
http://[host]:[port]/alfresco/service/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest=true&amp;format=atom
</url>
<url type="application/rss+xml">
http://[host]:[port]/alfresco/service/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest=true&amp;format=rss
</url>
</engine>
<!-- -->
<!-- Example: Registration of Alfresco's Open Talk Blog -->
<!-- -->
<engine label="Alfresco Open Source Talk" proxy="opentalk">
<url type="application/rss+xml">
http://blogs.alfresco.com/opentalk/os-query?s={searchTerms}&amp;itemstart={startIndex?}&amp;itempage={startPage?}&amp;itemlimit={count?}
</url>
</engine>
</engines>
</opensearch>
</config>
</alfresco-config>

View File

@@ -11,6 +11,7 @@
<constructor-arg>
<list>
<value>classpath:alfresco/web-api-config.xml</value>
<value>classpath:alfresco/extension/web-api-config-custom.xml</value>
</list>
</constructor-arg>
</bean>
@@ -136,6 +137,14 @@
<bean id="web.api.SearchEngines" class="org.alfresco.web.api.services.SearchEngines" parent="web.api.APITemplateService">
<property name="httpUri" value="/search/engines" />
<property name="configService" ref="web.api.Config" />
<property name="searchProxy" ref="web.api.SearchProxy" />
</bean>
<!-- Alfresco (OpenSearch) Proxy -->
<bean id="web.api.SearchProxy" class="org.alfresco.web.api.services.SearchProxy" parent="web.api.APIService">
<property name="httpUri" value="/search/engine" />
<property name="configService" ref="web.api.Config" />
<property name="formatRegistry" ref="web.api.FormatRegistry" />
</bean>
<!-- Alfresco Web Client Keyword Search Description (OpenSearch) -->

View File

@@ -10,10 +10,6 @@
</element-readers>
</plug-ins>
<config>
<!-- TODO: host, port?? -->
</config>
<!-- -->
<!-- Configuration of Open Search API -->
@@ -21,7 +17,13 @@
<config evaluator="string-compare" condition="OpenSearch">
<opensearch>
<engines>
<!-- -->
<!-- Local Alfresco Repository -->
<!-- -->
<engine label-id="current_repo" label="Alfresco Keyword Search">
<url type="application/opensearchdescription+xml">
/service/search/keywordsearchdescription.xml
@@ -36,7 +38,14 @@
/service/search/keyword?q={searchTerms}&amp;p={startPage?}&amp;c={count?}&amp;l={language?}&amp;guest={alf:guest?}
</url>
</engine>
</engines>
<proxy>
<!-- URL of Search Engine proxy -->
<url>/service/search/engine</url>
</proxy>
</opensearch>
</config>

View File

@@ -91,6 +91,29 @@ public class APIRequest extends HttpServletRequestWrapper
return getPath() + getServletPath();
}
/**
* 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(APIService service)
{
String servicePath = service.getHttpUri();
String extensionPath = getPathInfo();
int extIdx = extensionPath.indexOf(servicePath);
if (extIdx != -1)
{
extensionPath = extensionPath.substring(extIdx + servicePath.length() + 1 /* exclude leading / */);
}
return extensionPath;
}
/**
* Gets the full request URL
*

View File

@@ -116,7 +116,7 @@ public class APIServiceRegistry
// TODO: Replace with more efficient approach
for (int i = 0; i < services.size(); i++)
{
if (methods.get(i).equals(method) && uris.get(i).equals(uri))
if (methods.get(i).equals(method) && uri.startsWith(uris.get(i)))
{
apiService = services.get(i);
break;

View File

@@ -34,7 +34,9 @@ public class FormatRegistry
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;
/**
@@ -43,7 +45,9 @@ public class FormatRegistry
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>>();
}
/**
@@ -56,13 +60,16 @@ public class FormatRegistry
{
// 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);
}
}
@@ -78,6 +85,7 @@ public class FormatRegistry
}
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 + ")");
@@ -112,4 +120,32 @@ public class FormatRegistry
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;
}
}

View File

@@ -51,6 +51,7 @@ public class SearchEngines extends APIServiceTemplateImpl
// dependencies
protected ConfigService configService;
protected SearchProxy searchProxy;
/**
* @param configService
@@ -60,6 +61,14 @@ public class SearchEngines extends APIServiceTemplateImpl
this.configService = configService;
}
/**
* @param searchProxy
*/
public void setSearchProxy(SearchProxy searchProxy)
{
this.searchProxy = searchProxy;
}
/* (non-Javadoc)
* @see org.alfresco.web.api.APIService#getRequiredAuthentication()
*/
@@ -135,7 +144,7 @@ public class SearchEngines extends APIServiceTemplateImpl
for (Map.Entry<String, String> engineUrl : engineUrls.entrySet())
{
String type = engineUrl.getKey();
String url = engineUrl.getValue();
String url = searchProxy.createUrl(engineConfig, type);
if ((urlType.equals(URL_ARG_ALL)) ||
(urlType.equals(URL_ARG_DESCRIPTION) && type.equals(MimetypeMap.MIMETYPE_OPENSEARCH_DESCRIPTION)) ||

View File

@@ -0,0 +1,337 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* 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.
*/
package org.alfresco.web.api.services;
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.APIException;
import org.alfresco.web.api.APIRequest;
import org.alfresco.web.api.APIResponse;
import org.alfresco.web.api.FormatRegistry;
import org.alfresco.web.api.APIRequest.HttpMethod;
import org.alfresco.web.api.APIRequest.RequiredAuthentication;
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 APIServiceImpl 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.alfresco.web.api.APIService#getRequiredAuthentication()
*/
public RequiredAuthentication getRequiredAuthentication()
{
return APIRequest.RequiredAuthentication.None;
}
/* (non-Javadoc)
* @see org.alfresco.web.api.APIService#getHttpMethod()
*/
public HttpMethod getHttpMethod()
{
return APIRequest.HttpMethod.GET;
}
/* (non-Javadoc)
* @see org.alfresco.web.api.APIService#getDefaultFormat()
*/
public String getDefaultFormat()
{
return null;
}
/* (non-Javadoc)
* @see org.alfresco.web.api.APIService#getDescription()
*/
public String getDescription()
{
return "Issue an OpenSearch query via Alfresco";
}
/* (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(this);
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.getPath(), 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;
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* 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.
*/
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import javax.servlet.http.HttpServletResponse;
/**
* Simple server-side HTTP Request / Response
*
* @author davidc
*/
public class HTTPProxy
{
protected URL url;
protected HttpServletResponse response;
/**
* Construct
*
* @param requestUrl url to request
* @param response response to write request back to
* @throws MalformedURLException
*/
public HTTPProxy(String requestUrl, HttpServletResponse response)
throws MalformedURLException
{
this.url = new URL(requestUrl);
this.response = response;
}
/**
* Perform request
*
* @throws IOException
*/
public void service()
throws IOException
{
URLConnection connection = url.openConnection();
initialiseResponse(connection);
InputStream input = connection.getInputStream();
OutputStream output = response.getOutputStream();
try
{
writeResponse(input, output);
}
finally
{
try
{
if (input != null)
{
input.close();
}
if (output != null)
{
output.flush();
output.close();
}
}
catch(IOException e)
{
}
}
}
/**
* Initialise response
*
* @param urlConnection url connection
*/
protected void initialiseResponse(URLConnection urlConnection)
{
String type = urlConnection.getContentType();
if (type != null)
{
int encodingIdx = type.lastIndexOf("charset=");
if (encodingIdx == -1)
{
String encoding = urlConnection.getContentEncoding();
if (encoding != null && encoding.length() > 0)
{
type += ";charset=" + encoding;
}
}
response.setContentType(type);
}
}
/**
* Write response
*
* @param input input stream of request
* @param output output stream of response
* @throws IOException
*/
protected void writeResponse(InputStream input, OutputStream output)
throws IOException
{
byte[] buffer = new byte[1024];
int read = input.read(buffer);
while (read != -1)
{
output.write(buffer, 0, read);
read = input.read(buffer);
}
}
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2005 Alfresco, Inc.
*
* 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.
*/
package org.alfresco.web.app.servlet;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* HTTP Proxy Servlet
*
* Provides the ability to submit a URL request via the Alfresco Server i.e.
* the Alfresco server acts as a proxy.
*
* This servlet accepts:
*
* /proxy?endpoint=<endpointUrl>[&<argName>=<argValue>]*
*
* Where:
*
* - endpointUrl is the URL to make a request against
* - argName is the name of a URL argument to append to the request
* - argValue is the value of URL argument
*
* E.g.:
*
* /proxy?endpoint=http://www.alfresco.com&arg1=value1&arg2=value2
*
* @author davidc
*/
public class HTTPProxyServlet extends BaseServlet
{
private static final long serialVersionUID = -576405943603122206L;
/**
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException
{
String endpoint = null;
String args = null;
Map<String, String[]> parameters = req.getParameterMap();
for (Map.Entry<String, String[]> parameter : parameters.entrySet())
{
String[] values = parameter.getValue();
int startIdx = 0;
if (parameter.getKey().equals("endpoint") && values.length > 0)
{
endpoint = values[0];
startIdx++;
}
for (int i = startIdx; i < values.length; i++)
{
String arg = parameter.getKey() + "=" + values[i];
args = (args == null) ? arg : args + "&" + arg;
}
}
if (endpoint == null || endpoint.length() == 0)
{
throw new IllegalArgumentException("endpoint argument not specified");
}
String url = endpoint + ((args == null) ? "" : "?" + args);
HTTPProxy proxy = new HTTPProxy(url, res);
proxy.service();
}
/**
* Construct a "proxied" URL
*
* Note: the "proxied" URL is a relative url
*
* @param url the URL to proxy
* @return the "proxied" url
*/
public static String createProxyUrl(String url)
{
String proxy = "/proxy";
if (url != null && url.length() > 0)
{
int argIndex = url.lastIndexOf("?");
if (argIndex == -1)
{
proxy += "?endpoint=" + url;
}
else
{
proxy += "?endpoint=" + url.substring(0, argIndex) + "&" + url.substring(argIndex + 1);
}
}
return proxy;
}
}

View File

@@ -37,7 +37,9 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
{
public static final String CONFIG_ELEMENT_ID = "opensearch";
private ProxyConfig proxy;
private Set<EngineConfig> engines = new HashSet<EngineConfig>(8, 10f);
private Map<String, EngineConfig> enginesByProxy = new HashMap<String, EngineConfig>();
/**
@@ -86,9 +88,36 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
combinedElement.addEngine(plugin);
}
// set the proxy configuration
ProxyConfig proxyConfig = this.getProxy();
if (proxyConfig != null)
{
combinedElement.setProxy(proxyConfig);
}
return combinedElement;
}
/**
* Sets the proxy configuration
*
* @param proxyConfig
*/
/*package*/ void setProxy(ProxyConfig proxyConfig)
{
this.proxy = proxyConfig;
}
/**
* Gets the proxy configuration
*
* @return
*/
public ProxyConfig getProxy()
{
return this.proxy;
}
/**
* @return Returns a set of the engines
*/
@@ -97,6 +126,15 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
return this.engines;
}
/**
* @param proxy name of engine proxy
* @return associated engine config (or null, if none registered against proxy)
*/
public EngineConfig getEngine(String proxy)
{
return this.enginesByProxy.get(proxy);
}
/**
* Adds an engine
*
@@ -105,6 +143,11 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
/*package*/ void addEngine(EngineConfig engineConfig)
{
this.engines.add(engineConfig);
String proxy = engineConfig.getProxy();
if (proxy != null && proxy.length() > 0)
{
this.enginesByProxy.put(proxy, engineConfig);
}
}
@@ -117,8 +160,10 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
{
protected String label;
protected String labelId;
protected String proxy;
protected Map<String, String> urls = new HashMap<String, String>(8, 10f);
/**
* Construct
*
@@ -135,6 +180,19 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
this.labelId = labelId;
}
/**
* Construct
*
* @param label
* @param labelId
* @param proxy
*/
public EngineConfig(String label, String labelId, String proxy)
{
this(label, labelId);
this.proxy = proxy;
}
/**
* @return I18N label id
*/
@@ -151,6 +209,14 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
return label;
}
/**
* @return proxy
*/
public String getProxy()
{
return proxy;
}
/**
* Gets the urls supported by this engine
*
@@ -171,16 +237,38 @@ public class OpenSearchConfigElement extends ConfigElementAdapter
this.urls.put(mimetype, uri);
}
}
/**
* @see java.lang.Object#toString()
* Inner class representing the configuration of the OpenSearch proxy
*
* @author davidc
*/
@Override
public String toString()
public static class ProxyConfig
{
StringBuilder buffer = new StringBuilder(super.toString());
buffer.append(" {label=").append(this.label);
buffer.append(" labelId=").append(this.labelId).append(")");
return buffer.toString();
protected String url;
/**
* Construct
*
* @param url
*/
public ProxyConfig(String url)
{
if (url == null || url.length() == 0)
{
throw new IllegalArgumentException("'url' must be specified");
}
this.url = url;
}
/**
* @return url
*/
public String getUrl()
{
return url;
}
}

View File

@@ -23,6 +23,7 @@ import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.xml.elementreader.ConfigElementReader;
import org.alfresco.web.config.OpenSearchConfigElement.EngineConfig;
import org.alfresco.web.config.OpenSearchConfigElement.ProxyConfig;
import org.dom4j.Element;
@@ -37,9 +38,11 @@ public class OpenSearchElementReader implements ConfigElementReader
public static final String ELEMENT_ENGINES = "engines";
public static final String ELEMENT_ENGINE = "engine";
public static final String ELEMENT_URL = "url";
public static final String ELEMENT_PROXY = "proxy";
public static final String ATTR_TYPE = "type";
public static final String ATTR_LABEL = "label";
public static final String ATTR_LABEL_ID = "label-id";
public static final String ATTR_PROXY = "proxy";
/**
@@ -71,7 +74,8 @@ public class OpenSearchElementReader implements ConfigElementReader
Element engineElem = engines.next();
String label = engineElem.attributeValue(ATTR_LABEL);
String labelId = engineElem.attributeValue(ATTR_LABEL_ID);
EngineConfig engineCfg = new EngineConfig(label, labelId);
String proxy = engineElem.attributeValue(ATTR_PROXY);
EngineConfig engineCfg = new EngineConfig(label, labelId, proxy);
// construct urls for engine
Iterator<Element> urlsConfig = engineElem.elementIterator(ELEMENT_URL);
@@ -87,6 +91,20 @@ public class OpenSearchElementReader implements ConfigElementReader
configElement.addEngine(engineCfg);
}
}
// extract proxy configuration
String url = null;
Element proxyElem = element.element(ELEMENT_PROXY);
if (proxyElem != null)
{
Element urlElem = proxyElem.element(ELEMENT_URL);
if (urlElem != null)
{
url = urlElem.getTextTrim();
ProxyConfig proxyCfg = new ProxyConfig(url);
configElement.setProxy(proxyCfg);
}
}
}
return configElement;

View File

@@ -12,6 +12,7 @@ import javax.faces.context.ResponseWriter;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.api.services.SearchProxy;
import org.alfresco.web.app.Application;
import org.alfresco.web.config.OpenSearchConfigElement;
import org.alfresco.web.config.OpenSearchConfigElement.EngineConfig;
@@ -28,7 +29,6 @@ import org.springframework.web.jsf.FacesContextUtils;
public class UIOpenSearch extends SelfRenderingComponent
{
protected final static String SCRIPTS_WRITTEN = "_alfOpenSearchScripts";
protected final static String ATOM_TYPE = "application/atom+xml";
protected final static String ENGINE_ID_PREFIX = "eng";
// ------------------------------------------------------------------------------
@@ -205,6 +205,8 @@ public class UIOpenSearch extends SelfRenderingComponent
// get the web api config service object from spring
ConfigService cfgSvc = (ConfigService)FacesContextUtils.
getRequiredWebApplicationContext(context).getBean("web.api.Config");
SearchProxy searchProxy = (SearchProxy)FacesContextUtils.
getRequiredWebApplicationContext(context).getBean("web.api.SearchProxy");
if (cfgSvc != null)
{
// get the OpenSearch configuration
@@ -229,11 +231,10 @@ public class UIOpenSearch extends SelfRenderingComponent
}
// locate search engine template url of most appropriate response type
Map<String, String> urls = engineCfg.getUrls();
String url = urls.get(MimetypeMap.MIMETYPE_ATOM);
String url = searchProxy.createUrl(engineCfg, MimetypeMap.MIMETYPE_ATOM);
if (url == null)
{
url = urls.get(MimetypeMap.MIMETYPE_RSS);
url = searchProxy.createUrl(engineCfg, MimetypeMap.MIMETYPE_RSS);
}
if (url != null)

View File

@@ -246,6 +246,11 @@
<servlet-class>org.alfresco.web.api.APIServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>proxyServlet</servlet-name>
<servlet-class>org.alfresco.web.app.servlet.HTTPProxyServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>workflowDefinitionImageServlet</servlet-name>
<servlet-class>org.alfresco.web.app.servlet.WorkflowDefinitionImageServlet</servlet-class>
@@ -321,6 +326,11 @@
<url-pattern>/service/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>proxyServlet</servlet-name>
<url-pattern>/proxy</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JBPMDeployProcessServlet</servlet-name>
<url-pattern>/jbpm/deployprocess</url-pattern>