Merge Web Scripts from BRANCHES/DEV/DAVE

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5352 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2007-03-08 14:47:01 +00:00
parent b8b6e0043e
commit bea1a12b32
47 changed files with 157 additions and 3337 deletions

View File

@@ -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;
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);
}

View File

@@ -1,123 +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;
/**
* API Service
*
* @author davidc
*/
public interface APIDescription
{
/**
* 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 APIRequest.RequiredAuthentication getRequiredAuthentication();
/**
* 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();
}
}

View File

@@ -1,142 +0,0 @@
package org.alfresco.web.api;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.api.APIRequest.RequiredAuthentication;
public class APIDescriptionImpl implements APIDescription
{
private String sourceLocation;
private String id;
private String shortName;
private String description;
private RequiredAuthentication requiredAuthentication;
private String httpMethod;
private URI[] uris;
private String defaultFormat;
private Map<String, URI> uriByFormat;
public void setId(String id)
{
this.id = id;
}
public String getId()
{
return this.id;
}
public void setShortName(String shortName)
{
this.shortName = shortName;
}
public String getShortName()
{
return this.shortName;
}
public void setDescription(String description)
{
this.description = description;
}
public String getDescription()
{
return this.description;
}
public void setRequiredAuthentication(RequiredAuthentication requiredAuthentication)
{
this.requiredAuthentication = requiredAuthentication;
}
public RequiredAuthentication getRequiredAuthentication()
{
return this.requiredAuthentication;
}
public void setMethod(String httpMethod)
{
this.httpMethod = httpMethod;
}
public String getMethod()
{
return this.httpMethod;
}
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;
}
public URI[] getURIs()
{
return this.uris;
}
public URI getURI(String format)
{
return this.uriByFormat.get(format);
}
public void setDefaultFormat(String defaultFormat)
{
this.defaultFormat = defaultFormat;
}
public String getDefaultFormat()
{
return this.defaultFormat;
}
public static class URIImpl implements APIDescription.URI
{
private String format;
private String uri;
public void setFormat(String format)
{
this.format = format;
}
public String getFormat()
{
return this.format;
}
public void setUri(String uri)
{
this.uri = uri;
}
public String getURI()
{
return this.uri;
}
}
public void setSourceLocation(String sourceLocation)
{
this.sourceLocation = sourceLocation;
}
public String getSourceLocation()
{
return this.sourceLocation;
}
}

View File

@@ -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;
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);
}
}

View File

@@ -1,30 +0,0 @@
package org.alfresco.web.api;
import java.util.Collection;
import javax.servlet.ServletContext;
public interface APIRegistry
{
public ServletContext getContext();
/**
* Gets an API Service given an HTTP Method and URI
*
* @param method
* @param uri
* @return
*/
public APIServiceMatch findService(String method, String uri);
public APIService getService(String id);
public Collection<APIService> getServices();
public FormatRegistry getFormatRegistry();
public APITemplateProcessor getTemplateProcessor();
//public APIScriptProcessor getScriptProcessor();
}

View File

@@ -1,182 +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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
/**
* API Service Request
*
* @author davidc
*/
public class APIRequest extends HttpServletRequestWrapper
{
private APIServiceMatch serviceMatch;
/**
* Enumeration of "required" Authentication level
*/
public enum RequiredAuthentication
{
none,
guest,
user
}
/**
* Construct
*
* @param req
*/
/*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;
}
/**
* Gets the Alfresco Context URL
*
* @return context url e.g. http://localhost:port/alfresco
*/
public String getPath()
{
return getScheme() + "://" + getServerName() + ":" + getServerPort() + getContextPath();
}
/**
* Gets the Alfresco Service URL
*
* @return service url e.g. http://localhost:port/alfresco/service
*/
public String getServicePath()
{
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()
{
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;
}
/**
* Gets the full request URL
*
* @return request url e.g. http://localhost:port/alfresco/service/text?searchTerms=dsfsdf
*/
public String getUrl()
{
return getScheme() + "://" + getServerName() + ":" + getServerPort() + getPathInfo() + (getQueryString() != null ? "?" + getQueryString() : "");
}
/**
* Gets the currently authenticated username
*
* @return username
*/
public String getAuthenticatedUsername()
{
return AuthenticationUtil.getCurrentUserName();
}
/**
* 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;
}
}

View File

@@ -1,55 +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 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 OPENSEARCH_DESCRIPTION_FORMAT = "opensearchdescription";
/**
* Construct
*
* @param res
*/
/*package*/ APIResponse(HttpServletResponse res)
{
super(res);
}
}

View File

@@ -1,48 +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;
/**
* API Service
*
* @author davidc
*/
public interface APIService
{
public APIDescription getDescription();
/**
* Execute service
*
* @param req
* @param res
* @throws IOException
*/
public void execute(APIRequest req, APIResponse res)
throws IOException;
}

View File

@@ -1,10 +0,0 @@
package org.alfresco.web.api;
public interface APIServiceMatch
{
public String getPath();
public APIService getService();
}

View File

@@ -1,138 +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.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 = new DeclarativeAPIServiceRegistry(context);
}
// 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();
// APIRequest request = new APIRequest(req);
// APIResponse response = new APIResponse(res);
//
// try
// {
// //
// // Execute appropriate service
// //
// // TODO: Handle errors (with appropriate HTTP error responses)
//
// APIRequest.HttpMethod method = request.getHttpMethod();
// String uri = request.getPathInfo();
//
// if (logger.isDebugEnabled())
// logger.debug("Processing request (" + request.getHttpMethod() + ") " + request.getRequestURL() + (request.getQueryString() != null ? "?" + request.getQueryString() : "") + " (agent: " + request.getAgent() + ")");
//
// APIServiceDescription service = apiServiceRegistry.get(method, uri);
// if (service != null)
// {
// // TODO: Wrap in single transaction
// service.execute(request, response);
// }
// else
// {
// if (logger.isDebugEnabled())
// logger.debug("Request does not map to service.");
//
// response.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 (" + request.getHttpMethod() + ") " + request.getRequestURL() + (request.getQueryString() != null ? "?" + request.getQueryString() : "") + " in " + (end - start) + "ms");
// }
}
/**
* Initialise any API beans that require a servlet context
*
* @param appContext application context
*/
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);
}
}
}

View File

@@ -1,22 +0,0 @@
package org.alfresco.web.api;
import java.io.IOException;
import java.io.InputStream;
import freemarker.cache.TemplateLoader;
public interface APIStore
{
public String getBasePath();
public String[] getDescriptionDocumentPaths();
public InputStream getDescriptionDocument(String documentPath)
throws IOException;
public TemplateLoader getTemplateLoader();
public ScriptLoader getScriptLoader();
}

View File

@@ -1,94 +0,0 @@
package org.alfresco.web.api;
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;
public class APIStores implements ApplicationContextAware, ApplicationListener
{
private ApplicationContext applicationContext;
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
private APITemplateProcessor templateProcessor;
/* (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)
{
initTemplateProcessor();
initScriptProcessor();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
this.lifecycle.setApplicationContext(applicationContext);
}
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);
}
protected void initScriptProcessor()
{
}
@SuppressWarnings("unchecked")
public Collection<APIStore> getAPIStores()
{
return applicationContext.getBeansOfType(APIStore.class, false, false).values();
}
public void setTemplateProcessor(APITemplateProcessor templateProcessor)
{
this.templateProcessor = templateProcessor;
}
public APITemplateProcessor getTemplateProcessor()
{
return templateProcessor;
}
}

View File

@@ -1,150 +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 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;
}
/**
* 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)
{
}
}
}

View File

@@ -1,153 +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.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
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.descriptor.DescriptorService;
/**
* Skeleton implementation of an API Service
*
* @author davidc
*/
public abstract class AbstractAPIService implements APIService
{
// dependencies
private APIRegistry apiRegistry;
private APIDescription apiDescription;
private ServiceRegistry serviceRegistry;
private DescriptorService descriptorService;
//
// Initialisation
//
final public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
final public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
final public void setDescription(APIDescription apiDescription)
{
this.apiDescription = apiDescription;
}
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
//
final public APIRegistry getAPIRegistry()
{
return this.apiRegistry;
}
final public ServiceRegistry getServiceRegistry()
{
return this.serviceRegistry;
}
final public DescriptorService getDescriptorService()
{
return this.descriptorService;
}
//
// Basic Templating Support
//
/**
* Create a basic API model
*
* @param req api request
* @param res api response
* @return template model
*/
final protected Map<String, Object> createAPIModel(APIRequest req, APIResponse res)
{
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("xmldate", new ISO8601DateFormatMethod());
model.put("absurl", new AbsoluteUrlMethod(req.getPath()));
model.put("urlencode", new UrlEncodeMethod());
model.put("date", new Date());
model.put("agent", descriptorService.getServerDescriptor());
model.put("request", req);
model.put("response", res);
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);
}
}

View File

@@ -1,171 +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 javax.servlet.ServletContext;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
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() == APIRequest.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;
}
}

View File

@@ -1,193 +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 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.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(APIRequest.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(APIRequest.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;
}
}

View File

@@ -1,116 +0,0 @@
package org.alfresco.web.api;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
public class ClassPathAPIStore implements APIStore, InitializingBean
{
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
private String classPath;
private String classPathDir;
public void setClassPath(String classPath)
{
this.classPath = classPath;
}
public void afterPropertiesSet()
throws Exception
{
ClassPathResource resource = new ClassPathResource(classPath);
classPathDir = resource.getURL().toExternalForm();
}
public String getBasePath()
{
return "classpath:" + classPath;
}
public String[] getDescriptionDocumentPaths()
{
String[] paths = null;
try
{
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/**/*_desc.xml");
paths = new String[resources.length];
int i = 0;
for (Resource resource : resources)
{
paths[i++] = resource.getURL().toExternalForm().substring(classPathDir.length());
}
}
catch(IOException e)
{
// Note: Ignore: no service description documents found
paths = new String[0];
}
return paths;
}
public InputStream getDescriptionDocument(String documentPath)
throws IOException
{
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(classPathDir + "/" + documentPath);
return resource.getInputStream();
}
public static void main(String[] args)
throws Exception
{
ClassPathAPIStore store = new ClassPathAPIStore();
store.setClassPath("alfresco/templates/api");
store.afterPropertiesSet();
String[] paths = store.getDescriptionDocumentPaths();
InputStream is = store.getDescriptionDocument(paths[0]);
is.close();
TemplateLoader loader = store.getTemplateLoader();
Object obj = loader.findTemplateSource("KeywordSearch_view_atom.ftl");
}
public TemplateLoader getTemplateLoader()
{
FileTemplateLoader loader = null;
try
{
File classPathFile = new File(new URI(classPathDir));
loader = new FileTemplateLoader(classPathFile);
}
catch (URISyntaxException e)
{
// Note: Can't establish loader, so return null
}
catch (IOException e)
{
// Note: Can't establish loader, so return null
}
return loader;
}
public ScriptLoader getScriptLoader()
{
// TODO Auto-generated method stub
return null;
}
}

View File

@@ -1,454 +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.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.APIDescription.URI;
import org.alfresco.web.api.APIRequest.RequiredAuthentication;
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;
/**
* Registry of Web API Services methods
*
* @author davidc
*/
public class DeclarativeAPIRegistry implements APIRegistry, ApplicationContextAware, APIContextAware
{
// TODO: Support different kinds of uri resolution (e.g. regex:/search/.*) ??
// 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 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());
public void setAuthenticator(MethodInterceptor authenticator)
{
this.authenticator = authenticator;
}
public void setServiceLogger(MethodInterceptor serviceLogger)
{
this.serviceLogger = serviceLogger;
}
public void setDefaultServiceImpl(String defaultServiceImpl)
{
this.defaultServiceImpl = defaultServiceImpl;
}
public void setStores(APIStores stores)
{
this.stores = stores;
}
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
{
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 " + existingService.getDescription().getSourceLocation() + " overridden by " + serviceDesc.getSourceLocation());
}
continue;
}
// construct service implementation
String serviceImplName = (applicationContext.containsBean("web.api.services." + id)) ? "web.api.services." + 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 && authenticator != null)
{
ProxyFactory authFactory = new ProxyFactory();
authFactory.addInterface(APIService.class);
authFactory.setTarget(serviceImplIF);
// authentication interceptor
if (serviceDesc.getRequiredAuthentication() != APIRequest.RequiredAuthentication.none)
{
if (authenticator == null)
{
throw new APIException("Web API Authenticator not specified");
}
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", authenticator);
authFactory.addAdvisor(advisor);
}
// logging interceptor
if (serviceLogger != null)
{
RegexpMethodPointcutAdvisor advisor = new RegexpMethodPointcutAdvisor(".*execute", serviceLogger);
authFactory.addAdvisor(advisor);
}
serviceImplIF = (APIService)authFactory.getProxy();
}
if (logger.isDebugEnabled())
logger.debug("Found service " + serviceDescPath + " (id: " + id + ", impl: " + serviceImplName + ")");
// 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");
}
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");
}
}
// construct service description
APIDescriptionImpl serviceDesc = new APIDescriptionImpl();
serviceDesc.setSourceLocation(basePath + "/" + serviceDescPath);
serviceDesc.setId(id);
serviceDesc.setShortName(shortName);
serviceDesc.setDescription(description);
serviceDesc.setRequiredAuthentication(reqAuth);
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);
}
}
/**
* Gets an API Service given an HTTP Method and URI
*
* @param method
* @param uri
* @return
*/
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;
}
public ServletContext getContext()
{
return servletContext;
}
public APIService getService(String id)
{
return servicesById.get(id);
}
public void setFormatRegistry(FormatRegistry formatRegistry)
{
this.formatRegistry = formatRegistry;
}
public FormatRegistry getFormatRegistry()
{
return this.formatRegistry;
}
public APITemplateProcessor getTemplateProcessor()
{
return this.stores.getTemplateProcessor();
}
public void setAPIContext(ServletContext context)
{
this.servletContext = context;
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
}
public Collection<APIService> getServices()
{
return servicesById.values();
}
public static class DeclarativeAPIServiceMatch implements APIServiceMatch
{
private String path;
private APIService service;
public DeclarativeAPIServiceMatch(String path, APIService service)
{
this.path = path;
this.service = service;
}
public String getPath()
{
return path;
}
public APIService getService()
{
return service;
}
}
}

View File

@@ -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;
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);
}
}

View File

@@ -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;
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;
}
}

View File

@@ -22,13 +22,14 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.api.services;
package org.alfresco.web.api;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.api.APIRequest;
import org.alfresco.web.api.APIResponse;
import org.alfresco.web.api.ScriptedAPIService;
import org.alfresco.web.api.framework.APIRequest;
import org.alfresco.web.api.framework.APIResponse;
import org.alfresco.web.api.framework.ScriptedAPIService;
/**
@@ -43,8 +44,9 @@ public class Index extends ScriptedAPIService
* @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> createModel(APIRequest req, APIResponse res, Map<String, Object> model)
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;
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.api.services;
package org.alfresco.web.api;
import java.io.StringWriter;
import java.io.Writer;
@@ -40,10 +40,10 @@ 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.APIException;
import org.alfresco.web.api.APIRequest;
import org.alfresco.web.api.APIResponse;
import org.alfresco.web.api.ScriptedAPIService;
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;
@@ -89,7 +89,7 @@ public class KeywordSearch extends ScriptedAPIService
* @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> createModel(APIRequest req, APIResponse res, Map<String, Object> model)
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
{
//
// process arguments
@@ -129,12 +129,13 @@ public class KeywordSearch extends ScriptedAPIService
// execute the search
//
SearchResult results = search(searchTerms, startPage, itemsPerPage, locale, req.getParameterMap());
SearchResult results = search(searchTerms, startPage, itemsPerPage, locale, req);
//
// append to model
// create model
//
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("search", results);
return model;
}
@@ -142,13 +143,11 @@ public class KeywordSearch extends ScriptedAPIService
/**
* Execute the search
*
* @param searchTerms The search terms
* @param startPage The page number to start at
* @param itemsPerPage The number of items to show on a page
* @param locale The current locale
* @return The search result
* @param searchTerms
* @param startPage
* @return
*/
private SearchResult search(String searchTerms, int startPage, int itemsPerPage, Locale locale, Map reqParams)
private SearchResult search(String searchTerms, int startPage, int itemsPerPage, Locale locale, APIRequest req)
{
SearchResult searchResult = null;
ResultSet results = null;
@@ -158,7 +157,7 @@ public class KeywordSearch extends ScriptedAPIService
// construct search statement
String[] terms = searchTerms.split(" ");
Map<String, Object> statementModel = new HashMap<String, Object>(7, 1.0f);
statementModel.put("args", reqParams);
statementModel.put("args", createArgModel(req));
statementModel.put("terms", terms);
Writer queryWriter = new StringWriter(1024);
renderFormatTemplate(QUERY_FORMAT, statementModel, queryWriter);

View File

@@ -1,10 +0,0 @@
package org.alfresco.web.api;
import org.alfresco.service.cmr.repository.ScriptLocation;
public interface ScriptLoader
{
ScriptLocation getScriptLocation(String path);
}

View File

@@ -1,132 +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.Writer;
import java.util.Map;
import org.alfresco.service.cmr.repository.TemplateException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Script 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;
@Override
public void init(APIRegistry apiRegistry)
{
super.init(apiRegistry);
baseTemplatePath = getDescription().getId().replace('.', '/');
// TODO: Test for .js script
}
/* (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 = createAPIModel(req, res);
model = createModel(req, res, model);
// TODO: execute script if it exists
// 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
{
renderFormatTemplate(format, model, res.getWriter());
}
catch(TemplateException e)
{
throw new APIException("Failed to process format '" + format + "'", e);
}
}
/**
* Create a custom service model
*
* @param req API request
* @param res API response
* @param model basic API model
* @return custom service model
*/
protected Map<String, Object> createModel(APIRequest req, APIResponse res, Map<String, Object> model)
{
return model;
}
/**
* 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);
}
}

View File

@@ -22,8 +22,9 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.api.services;
package org.alfresco.web.api;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -32,9 +33,9 @@ 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.APIRequest;
import org.alfresco.web.api.APIResponse;
import org.alfresco.web.api.ScriptedAPIService;
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;
@@ -76,7 +77,7 @@ public class SearchEngines extends ScriptedAPIService
}
@Override
protected Map<String, Object> createModel(APIRequest req, APIResponse res, Map<String, Object> model)
protected Map<String, Object> executeImpl(APIRequest req, APIResponse res)
{
String urlType = req.getParameter("type");
if (urlType == null || urlType.length() == 0)
@@ -93,6 +94,7 @@ public class SearchEngines extends ScriptedAPIService
//
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;

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.api.services;
package org.alfresco.web.api;
import java.io.IOException;
import java.io.InputStream;
@@ -38,11 +38,11 @@ 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.AbstractAPIService;
import org.alfresco.web.api.FormatRegistry;
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;

View File

@@ -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;
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;
}
}

View File

@@ -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;
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;
}
}

View File

@@ -1,214 +0,0 @@
package org.alfresco.web.api;
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.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;
public class TestAPIServer
{
/**
* The reader for interaction.
*/
private BufferedReader fIn;
private APIRegistry apiRegistry;
/**
* Last command issued
*/
private String lastCommand = null;
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
TestAPIServer test = new TestAPIServer();
test.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);
}
}
/**
* Make up a new console.
*/
public TestAPIServer()
{
fIn = new BufferedReader(new InputStreamReader(System.in));
String[] CONFIG_LOCATIONS = new String[] { "classpath:alfresco/application-context.xml", "classpath:alfresco/web-api-application-context.xml" };
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
DeclarativeAPIRegistry testAPIRegistry = (DeclarativeAPIRegistry)context.getBean("web.api.test.Registry");
testAPIRegistry.initServices();
apiRegistry = testAPIRegistry;
}
/**
* 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("");
}
}
}
/**
* 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.
*/
private String interpretCommand(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("req"))
{
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();
}
out.flush();
String retVal = new String(bout.toByteArray());
out.close();
return retVal;
}
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 path info
req.setPathInfo(iArgIndex == -1 ? uri : uri.substring(0, iArgIndex));
return req;
}
}

View File

@@ -36,7 +36,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.api.SearchProxy;
import org.alfresco.web.app.Application;
import org.alfresco.web.config.OpenSearchConfigElement;
import org.alfresco.web.config.OpenSearchConfigElement.EngineConfig;
@@ -266,9 +266,9 @@ public class UIOpenSearch extends SelfRenderingComponent
// get the web api config service object from spring
ConfigService cfgSvc = (ConfigService)FacesContextUtils.
getRequiredWebApplicationContext(context).getBean("web.api.Config");
getRequiredWebApplicationContext(context).getBean("web.api.framework.config");
SearchProxy searchProxy = (SearchProxy)FacesContextUtils.
getRequiredWebApplicationContext(context).getBean("web.api.SearchProxy");
getRequiredWebApplicationContext(context).getBean("web.api.org.alfresco.repository.searchproxy_get");
if (cfgSvc != null)
{
// get the OpenSearch configuration