Reversed incorrect checkin

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7438 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2007-11-26 17:17:01 +00:00
parent 82134bf1f0
commit fe7a8e8ca8
120 changed files with 12732 additions and 2228 deletions

View File

@@ -0,0 +1,100 @@
##
## Meta commands
##
ok> help
List this help.
ok> r
Repeat last command.
ok> user [<userName>]
Switch to specified <userName>. If <userName> is omitted, the currently
selected user is shown.
A ticket may be specified instead of username.
ok> quit | exit
Quit this Web Script server.
##
## HTTP Requests
##
ok> get <path>
Issue a HTTP GET request to the Web Script located at <path>. The response
is dumped to the console.
<path> URL relative to /alfresco/service
e.g. get /blog/search?q=tutorial
ok> put <path>
Issue a HTTP PUT request to the Web Script located at <path>. The response
is dumped to the console.
<path> URL relative to /alfresco/service
ok> post <path>
Issue a HTTP POST request to the Web Script located at <path>. The response
is dumped to the console.
<path> URL relative to /alfresco/service
ok> delete <path>
Issue a HTTP DELETE request to the Web Script located at <path>. The response
is dumped to the console.
<path> URL relative to /alfresco/service
ok> tunnel <encoding> <method> <path>
Tunnel a request via POST.
The actual <method> is encoded as either the URL parameter named alf:method or
the request header named X-HTTP-Method-Override as specified via the <encoding>
parameter:
param - encode method as URL parameter
header - encode method in Request Header
e.g. to tunnel 'get /index' via post (where method is encoded in header) issue
tunnel header get /index
##
## Request Header Commands
##
ok> header
Show all defined headers.
ok> var <headerName>=<headerValue>
Define or update a header value.
<headerName> header name
<headerValue> header value
e.g.
header alf-force-success=true
ok> header <headerName>=
Delete an existing header value.
<headerName> header name
##
## end
##

View File

@@ -0,0 +1,86 @@
##
## Web Script Response Codes
##
webscript.code.100.name=Continue
webscript.code.100.description=Client can continue.
webscript.code.101.name=Switching Protocols
webscript.code.101.description=The server is switching protocols according to Upgrade header.
webscript.code.200.name=OK
webscript.code.200.description=The request succeeded normally.
webscript.code.201.name=Created
webscript.code.201.description=Request succeeded and created a new resource on the server.
webscript.code.202.name=Accepted
webscript.code.202.description=Request was accepted for processing, but was not completed.
webscript.code.203.name=Non authoritative information
webscript.code.203.description=The meta information presented by the client did not originate from the server.
webscript.code.204.name=No ContentSC_NO_CONTENT
webscript.code.204.description=The request succeeded but that there was no new information to return.
webscript.code.205.name=Reset Content
webscript.code.205.description=The agent SHOULD reset the document view which caused the request to be sent.
webscript.code.206.name=Partial Content
webscript.code.206.description=The server has fulfilled the partial GET request for the resource.
webscript.code.300.name=Multiple Choices
webscript.code.300.description=The requested resource corresponds to any one of a set of representations, each with its own specific location.
webscript.code.301.name=Moved Permanently
webscript.code.301.description=The resource has permanently moved to a new location, and that future references should use a new URI with their requests.
webscript.code.302.name=Moved Temporarily
webscript.code.302.description=The resource has temporarily moved to another location, but that future references should still use the original URI to access the resource.
webscript.code.303.name=See Other
webscript.code.303.description=The response to the request can be found under a different URI.
webscript.code.304.name=Not Modified
webscript.code.304.description=A conditional GET operation found that the resource was available and not modified.
webscript.code.305.name=Use Proxy
webscript.code.305.description=The requested resource MUST be accessed through the proxy given by the Location field.
webscript.code.400.name=Bad Request
webscript.code.400.description=Request sent by the client was syntactically incorrect.
webscript.code.401.name=Unauthorized
webscript.code.401.description=The request requires HTTP authentication.
webscript.code.402.name=Payment Required
webscript.code.402.description=Reserved for future use.
webscript.code.403.name=Forbidden
webscript.code.403.description=Server understood the request but refused to fulfill it.
webscript.code.404.name=Not Found
webscript.code.404.description=Requested resource is not available.
webscript.code.405.name=Method Not Allowed
webscript.code.405.description=The method specified in the Request-Line is not allowed for the resource identified by the Request-URI.
webscript.code.406.name=Not Acceptable
webscript.code.406.description=The resource identified by the request is only capable of generating response entities which have content characteristics not acceptable according to the accept headers sent in the request.
webscript.code.407.name=Proxy Authentication Required
webscript.code.407.description=The client MUST first authenticate itself with the proxy.
webscript.code.408.name=Request Timeout
webscript.code.408.description=The client did not produce a request within the time that the server was prepared to wait.
webscript.code.409.name=Conflict
webscript.code.409.description=Request could not be completed due to a conflict with the current state of the resource.
webscript.code.410.name=Gone
webscript.code.410.description=Resource is no longer available at the server and no forwarding address is known.
webscript.code.411.name=Length required
webscript.code.411.description=Request cannot be handled without a defined Content-Length.
webscript.code.412.name=Precondition Failed
webscript.code.412.description=The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server.
webscript.code.413.name=Request Entity Too Large
webscript.code.413.description=The server is refusing to process the request because the request entity is larger than the server is willing or able to process.
webscript.code.414.name=Request URI Too Long
webscript.code.414.description=The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret.
webscript.code.415.name=Unsupported Media Type
webscript.code.415.description=The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.
webscript.code.416.name=Requested Range Not Satisfiable
webscript.code.416.description=The server cannot serve the requested byte range.
webscript.code.417.name=Expectation Failed
webscript.code.417.description=Server could not meet the expectation given in the Expect request header.
webscript.code.500.name=Internal Error
webscript.code.500.description=An error inside the HTTP server which prevented it from fulfilling the request.
webscript.code.501.name=Not Implemented
webscript.code.501.description=The HTTP server does not support the functionality needed to fulfill the request.
webscript.code.502.name=Bad Gateway
webscript.code.502.description=HTTP server received an invalid response from a server it consulted when acting as a proxy or gateway.
webscript.code.503.name=Service Unavailable
webscript.code.503.description=The HTTP server is temporarily overloaded, and unable to handle the request.
webscript.code.504.name=Gateway Timeout
webscript.code.504.description=Server did not receive a timely response from the upstream server while acting as a gateway or proxy.
webscript.code.505.name=HTTP version not supported
webscript.code.505.description=Server does not support or refuses to support the HTTP protocol version that was used in the request message.
##
## Test Web Script Server Help
##
testserver.help=alfresco/messages/webscripts-test-help.txt

View File

@@ -0,0 +1,46 @@
<style>
<!--
#app5607893292_appbody { padding-left: 7px; }
-->
</style>
<div id="appbody">
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Web Script Status ${status.code} - ${status.codeName}</span></nobr></td>
</tr>
</table>
<br>
<table>
<tr><td><b>Error:</b><td>${status.codeName} (${status.code}) - ${status.codeDescription}
<tr><td>&nbsp;
<tr><td><b>Message:</b><td>${status.message!"<i>&lt;Not specified&gt;</i>"}
<#if status.exception?exists>
<tr><td>&nbsp;
<@recursestack status.exception/>
</#if>
<tr><td><b>Server</b>:<td>Alfresco ${server.edition} v${server.version} schema ${server.schema}
<tr><td><b>Time</b>:<td>${date?datetime}
<tr><td>&nbsp;
</table>
</div>
<#macro recursestack exception>
<#if exception.cause?exists>
<@recursestack exception=exception.cause/>
</#if>
<tr><td><b>Exception:</b><td>${exception.class.name}<#if exception.message?exists> - ${exception.message}</#if>
<tr><td><td>&nbsp;
<#if exception.cause?exists == false>
<#list exception.stackTrace as element>
<tr><td><td>${element}
</#list>
<#else>
<tr><td><td>${exception.stackTrace[0]}
</#if>
<tr><td><td>&nbsp;
</#macro>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Web Scripts Home</shortname>
<description>Web Scripts Home</description>
<url>/</url>
<url>/index</url>
</webscript>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Scripts Home</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<form action="${url.serviceContext}${url.match}" method="post">
<input type="hidden" name="reset" value="on">
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Web Scripts Home</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<tr><td><td>${webscripts?size} Web Scripts - <a href="http://wiki.alfresco.com/wiki/HTTP_API">Online documentation</a>. <input type="submit" name="submit" value="Refresh list of Web Scripts">
</table>
</form>
<br>
<br>
<span class="mainSubTitle">Index</span>
<table>
<tr><td><a href="${url.serviceContext}/index/all">Browse all Web Scripts</a>
<tr><td><a href="${url.serviceContext}/index/uri/">Browse by Web Script URL</a>
<tr><td><a href="${url.serviceContext}/index/package/">Browse by Web Script Package</a>
</table>
<br>
<br>
<span class="mainSubTitle">Maintenance</span>
<table>
<tr><td><a href="${url.serviceContext}/api/javascript/debugger">Alfresco Javascript Debugger</a>
<tr><td><a href="${url.serviceContext}/installer>Web Script Installer</a>
</table>
</body>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Web Script Maintenance</shortname>
<description>Maintain index of Web Scripts</description>
<url>/index?reset={reset?}</url>
<url>/?reset={reset?}</url>
</webscript>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Alfresco Web Scripts Maintenance</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Alfresco Web Scripts Maintenance</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
</table>
<br>
<table>
<tr align="left"><td><b>Maintenance Completed</tr>
<#list tasks as task>
<tr><td>${task}<td></tr>
</#list>
</table>
<br>
<table><tr><td><a href="${url.serviceContext}${url.match}">List Web Scripts</a></td></tr></table>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>All Web Scripts Index</shortname>
<description>Retrieve an index of all Web Scripts</description>
<url>/index/all</url>
<url>/index/all.mediawiki</url>
</webscript>

View File

@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Index of All Web Scripts</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Index of All Web Scripts</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<tr><td><td>${webscripts?size} Web Scripts
</table>
<br>
<table>
<tr><td><a href="${url.serviceContext}/index">Back to Web Scripts Home</a>
</table>
<br>
<#macro recursepackage package>
<#if package.scripts?size &gt; 0>
<span class="mainSubTitle">Package: <a href="${url.serviceContext}/index/package${package.path}">${package.path}</a></span><br><br>
<#list package.scripts as webscript>
<#assign desc = webscript.description>
<span class="mainSubTitle">${desc.shortName}</span>
<table>
<#list desc.URIs as uri>
<tr><td><a href="${url.serviceContext}${uri}">${desc.method} ${url.serviceContext}${uri}</a>
</#list>
<tr><td>
</table>
<table>
<#if desc.description??><tr><td>Description:<td>${desc.description}<#else></#if>
<tr><td>Authentication:<td>${desc.requiredAuthentication}
<tr><td>Transaction:<td>${desc.requiredTransaction}
<tr><td>Format Style:<td>${desc.formatStyle}
<tr><td>Default Format:<td>${desc.defaultFormat!"<i>Determined at run-time</i>"}
<tr><td>
<tr><td>Id:<td><a href="${url.serviceContext}/script/${desc.id}">${desc.id}</a>
<tr><td>Description:<td><a href="${url.serviceContext}/description/${desc.id}">${desc.storePath}/${desc.descPath}</a>
</table>
<br>
</#list>
</#if>
<#list package.children as childpath>
<@recursepackage package=childpath/>
</#list>
</#macro>
<@recursepackage package=rootpackage/>
</body>
</html>

View File

@@ -0,0 +1,64 @@
Back to [[HTTP API]].
'''NOTE: This document describes features to be found in Alfresco v2.1 onwards.'''
= Introduction =
Welcome to the reference documentation for the Alfresco [[HTTP API]].
This document was generated from the Alfresco Server URL
GET <nowiki>http://</nowiki><host>:<port>${url.service}
on ${date?datetime} using Alfresco v${server.version}.
= Web Script Reference =
This section provides technical information for all ${webscripts?size} [[Web Scripts]], organized by Web Script Package.
Documentation for each Web Script includes:
* Short Name
* Description
* Available URL templates
* Default [[Web Scripts Framework#HTTP Response Formats|response format]]
* How to specify an alternative response
* Authentication requirements
* Transaction requirements
* Location of Web Script description document
<#macro recursepackage package>
<#if package.scripts?size &gt; 0>
== Package: ${package.path} ==
<#list package.scripts as webscript>
<#assign desc = webscript.description>
=== ${desc.shortName} ===
<#if desc.description??><#if desc.description?ends_with(".")>${desc.description}<#else>${desc.description}.</#if><#else><i>[No description supplied]</i></#if>
<#list desc.URIs as uri>
[http://localhost:8080${url.serviceContext}${uri} ${desc.method} ${url.serviceContext}${uri}]
</#list>
Requirements:
* Default Format: ${desc.defaultFormat!"<i>Determined at run-time</i>"}
* Authentication: ${desc.requiredAuthentication}
* Transaction: ${desc.requiredTransaction}
* Format Style: ${desc.formatStyle}
Definition:
* Id: ${desc.id}
* Description: ${desc.storePath}/${desc.descPath}
</#list>
</#if>
<#list package.children as childpath>
<@recursepackage package=childpath/>
</#list>
</#macro>
<@recursepackage package=rootpackage/>

View File

@@ -0,0 +1,5 @@
<webscript>
<shortname>Web Script Package Index</shortname>
<description>Provide an index of Web Scripts for the specified Web Script package</description>
<url>/index/package/{package}</url>
</webscript>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Index of Web Scripts Package '${package.path}'</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Index of Web Scripts Package '${package.path}'</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<tr><td><td>${package.scripts?size} Web Scripts
</table>
<br>
<table>
<tr><td><a href="${url.serviceContext}/index">Back to Web Scripts Home</a>
<#if package.parent?exists>
<tr><td><a href="${url.serviceContext}/index/package${package.parent.path}">Up to ${package.parent.path}</a>
</#if>
</table>
<br>
<#if package.children?size &gt; 0>
<table>
<@recurseuri package=package/>
</table>
<br>
</#if>
<#macro recurseuri package>
<#list package.children as childpath>
<#if childpath.scripts?size &gt; 0>
<tr><td><a href="${url.serviceContext}/index/package${childpath.path}">${childpath.path}</a>
</#if>
<@recurseuri package=childpath/>
</#list>
</#macro>
<#list package.scripts as webscript>
<#assign desc = webscript.description>
<span class="mainSubTitle">${desc.shortName}</span>
<table>
<#list desc.URIs as uri>
<tr><td><a href="${url.serviceContext}${uri}">${desc.method} ${url.serviceContext}${uri}</a>
</#list>
<tr><td>
</table>
<table>
<#if desc.description??><tr><td>Description:<td>${desc.description}<#else></#if>
<tr><td>Authentication:<td>${desc.requiredAuthentication}
<tr><td>Transaction:<td>${desc.requiredTransaction}
<tr><td>Format Style:<td>${desc.formatStyle}
<tr><td>Default Format:<td>${desc.defaultFormat!"<i>Determined at run-time</i>"}
<tr><td>
<tr><td>Id:<td><a href="${url.serviceContext}/script/${desc.id}">${desc.id}</a>
<tr><td>Description:<td><a href="${url.serviceContext}/description/${desc.id}">${desc.storePath}/${desc.descPath}</a>
</table>
<br>
</#list>
</body>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Web Script URI Index</shortname>
<description>Provide an index of Web Scripts for the specified Web Script URI</description>
<url>/index/uri/{uri}</url>
<format>argument</format>
</webscript>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Index of Web Scripts URI '${uri.path}'</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Index of Web Scripts URI '${uri.path}'</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<tr><td><td>${uri.scripts?size} Web Scripts
</table>
<br>
<table>
<tr><td><a href="${url.serviceContext}/index">Back to Web Scripts Home</a>
<#if uri.parent?exists>
<tr><td><a href="${url.serviceContext}/index/uri${uri.parent.path}">Up to ${uri.parent.path}</a>
</#if>
</table>
<br>
<#if uri.children?size &gt; 0>
<table>
<@recurseuri uri=uri/>
</table>
<br>
</#if>
<#macro recurseuri uri>
<#list uri.children as childpath>
<#if childpath.scripts?size &gt; 0>
<tr><td><a href="${url.serviceContext}/index/uri${childpath.path}">${childpath.path}</a>
</#if>
<@recurseuri uri=childpath/>
</#list>
</#macro>
<#list uri.scripts as webscript>
<#assign desc = webscript.description>
<span class="mainSubTitle">${desc.shortName}</span>
<table>
<#list desc.URIs as uri>
<tr><td><a href="${url.serviceContext}${uri}">${desc.method} ${url.serviceContext}${uri}</a>
</#list>
<tr><td>
</table>
<table>
<#if desc.description??><tr><td>Description:<td>${desc.description}<#else></#if>
<tr><td>Authentication:<td>${desc.requiredAuthentication}
<tr><td>Transaction:<td>${desc.requiredTransaction}
<tr><td>Format Style:<td>${desc.formatStyle}
<tr><td>Default Format:<td>${desc.defaultFormat!"<i>Determined at run-time</i>"}
<tr><td>
<tr><td>Id:<td><a href="${url.serviceContext}/script/${desc.id}">${desc.id}</a>
<tr><td>Description:<td><a href="${url.serviceContext}/description/${desc.id}">${desc.storePath}/${desc.descPath}</a>
</table>
<br>
</#list>
</body>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Web Script Description</shortname>
<description>Retrieve description document for identified Web Script</description>
<url>/description/{serviceId}</url>
<format>argument</format>
</webscript>

View File

@@ -0,0 +1,7 @@
<webscript>
<shortname>Display Web Script</shortname>
<description>Full inspection of Web Script implementation - useful for diagnostics and download/upload</description>
<url>/script/{serviceId}</url>
<format>argument</format>
<authentication>admin</authentication>
</webscript>

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Script: ${script.id}</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css"/>
</head>
<body>
<table>
<tr><td><nobr><span class="mainTitle">Web Script: ${script.id}</span></nobr></td></tr>
<tr><td>Alfresco ${server.edition} v${server.version}</td></tr>
<tr><td>Generated from ${url.full} on ${date?datetime}</td></tr>
</table>
<p/>
<table>
<span class="mainSubTitle">Script Properties</span>
<tr><td>Id:</td><td>${script.id}</td></tr>
<tr><td>Short Name:</td><td>${script.shortName}</td></tr>
<tr><td>Description:</td><td>${script.description}</td></tr>
<tr><td>Authentication:</td><td>${script.requiredAuthentication}</td></tr>
<tr><td>Transaction:</td><td>${script.requiredTransaction}</td></tr>
<tr><td>Method:</td><td>${script.method}</td></tr>
<#list script.URIs as URI>
<tr><td>URL Template:</td><td>${URI}</td></tr>
</#list>
<tr><td>Format Style:</td><td>${script.formatStyle}</td></tr>
<tr><td>Default Format:</td><td>${script.defaultFormat!"[undefined}]"}</td></tr>
<tr><td>Implementation:</td><td>${script_class}</td></tr>
</table>
<p/>
<#list stores as store>
<span class="mainSubTitle">Store: ${store.path}</span>
<p/>
<table>
<#if store.files?size == 0>
<tr><td>[No implementation files]</td></tr>
<#else>
<p/>
<#list store.files as file>
<tr><td><span class="mainSubTitle">File: ${file.path}</span> <#if file.overridden>[overridden]</#if></td></tr>
<tr><td><pre>${file.content?html}</pre></td></tr>
</#list>
</#if>
</table>
<p/>
</#list>
<!-- Web Script meta-data -->
<span style="display:none">
<webscript scriptid="${script.id}" xmlns="http://www.alfresco.org/webscript/1.0">
<#list stores as store>
<#list store.files as file>
<file path="${file.path}" store="${store.path}"><![CDATA[${file.content}]]></file>
</#list>
</#list>
</webscript>
</span>
<!-- End: Web Script meta-data -->
</body>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Web Script Installer Form</shortname>
<description>Web Script Installer Form</description>
<url>/installer</url>
<authentication>admin</authentication>
</webscript>

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Script Installer</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Web Scripts Installer</span></nobr></td>
</tr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<p>
<form action="${url.service}" method="post" enctype="multipart/form-data">
<tr><td><td>Web Script:
<tr><td><td><input type="file" name="webscript">
<tr><td><td>&nbsp;
<tr><td><td><input type="submit" name="submit" value="Install">
</form>
<tr><td><td>&nbsp;
<tr><td><td>&nbsp;
<tr><td><td>To create a Web Script file that can be installed:
<tr><td><td>&nbsp;
<tr><td><td>1) Display the full definition of the Web Script via the URL <a href="${url.serviceContext}/script/scriptdump.get">${url.serviceContext}/script/{scriptid}</a>
<tr><td><td>&nbsp;
<tr><td><td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.g. to display the "AVM Browse Sample", issue <a href="${url.serviceContext}/script/org/alfresco/sample/avmbrowse.get">${url.serviceContext}/script/org/alfresco/sample/avmbrowse.get</a>
<tr><td><td>&nbsp;
<tr><td><td>2) Save the the HTML page displayed in step 1
</table>
</body>
</html>

View File

@@ -0,0 +1,6 @@
<webscript>
<shortname>Install Web Script</shortname>
<description>Install Web Script</description>
<url>/installer</url>
<authentication>admin</authentication>
</webscript>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Installed Web Script: ${installedScript.id}</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css"/>
</head>
<body>
<table>
<tr><td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco"/><td><nobr><span class="mainTitle">Installed Web Script: ${installedScript.id}</span></nobr>
<tr><td><td>Alfresco ${server.edition} v${server.version}
<tr><td><td>${date?datetime}
</table>
<p/>
<table>
<tr><td><a href="${url.serviceContext}/script/${installedScript.id}">Inspect ${installedScript.id}</a>
<tr><td><a href="${url.serviceContext}/">Back to Web Scripts Home</a>
</table>
<p/>
<table>
<span class="mainSubTitle">Script Properties</span>
<tr><td>Id:</td><td>${installedScript.id}</td></tr>
<tr><td>Short Name:</td><td>${installedScript.shortName}</td></tr>
<tr><td>Description:</td><td>${installedScript.description}</td></tr>
<tr><td>Authentication:</td><td>${installedScript.requiredAuthentication}</td></tr>
<tr><td>Transaction:</td><td>${installedScript.requiredTransaction}</td></tr>
<tr><td>Method:</td><td>${installedScript.method}</td></tr>
<#list installedScript.URIs as URI>
<tr><td>URL Template:</td><td>${URI}</td></tr>
</#list>
<tr><td>Format Style:</td><td>${installedScript.formatStyle}</td></tr>
<tr><td>Default Format:</td><td>${installedScript.defaultFormat}</td></tr>
</table>
<p/>
<table>
<span class="mainSubTitle">Files Installed</span>
<#list installedFiles as file>
<tr><td>${file.path}<td>(store: ${file.store})
</#list>
</table>
</body>
</html>

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Script Status ${status.code} - ${status.codeName}</title>
<link rel="stylesheet" href="${url.context}/css/main.css" TYPE="text/css">
</head>
<body>
<table>
<tr>
<td><img src="${url.context}/images/logo/AlfrescoLogo32.png" alt="Alfresco" /></td>
<td><nobr><span class="mainTitle">Web Script Status ${status.code} - ${status.codeName}</span></nobr></td>
</tr>
</table>
<br>
<table>
<tr><td>The Web Script <a href="${url.full}">${url.service}</a> has responded with a status of ${status.code} - ${status.codeName}.
</table>
<br>
<table>
<tr><td><b>${status.code} Description:</b><td> ${status.codeDescription}
<tr><td>&nbsp;
<tr><td><b>Message:</b><td>${status.message!"<i>&lt;Not specified&gt;</i>"}
<#if status.exception?exists>
<tr><td>&nbsp;
<@recursestack status.exception/>
</#if>
<tr><td><b>Server</b>:<td>Alfresco ${server.edition} v${server.version} schema ${server.schema}
<tr><td><b>Time</b>:<td>${date?datetime}
<tr><td>&nbsp;
<#if webscript?exists>
<tr><td><b>Diagnostics</b>:<td><a href="${url.serviceContext}/script/${webscript.id}">Inspect Web Script (${webscript.id})</a>
</#if>
</table>
</body>
</html>
<#macro recursestack exception>
<#if exception.cause?exists>
<@recursestack exception=exception.cause/>
</#if>
<tr><td><b>Exception:</b><td>${exception.class.name}<#if exception.message?exists> - ${exception.message}</#if>
<tr><td><td>&nbsp;
<#if exception.cause?exists == false>
<#list exception.stackTrace as element>
<tr><td><td>${element}
</#list>
<#else>
<tr><td><td>${exception.stackTrace[0]}
</#if>
<tr><td><td>&nbsp;
</#macro>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<response>
<status>
<code>${status.code}</code>
<name>${status.codeName}</name>
<description>${status.codeDescription}</description>
</status>
<message>${status.message!""}</message>
<exception><#if status.exception?exists>${status.exception.class.name}<#if status.exception.message?exists> - ${status.exception.message}</#if></#if></exception>
<callstack>
<#if status.exception?exists>
<@recursestack status.exception/>
</#if>
</callstack>
<server>Alfresco ${server.edition} v${server.version} schema ${server.schema}</server>
<time>${date?datetime}</time>
</response>
<#macro recursestack exception>
<#if exception.cause?exists>
<@recursestack exception=exception.cause/>
</#if>
<#if exception.cause?exists == false>
${exception}
<#list exception.stackTrace as element>
${element}
</#list>
<#else>
${exception}
${exception.stackTrace[0]}
</#if>
</#macro>

View File

@@ -19,4 +19,10 @@
</constructor-arg>
</bean>
<bean id="pagerenderer.templateprocessor" class="org.alfresco.web.app.servlet.PageTemplateProcessor">
<property name="freeMarkerProcessor" ref="freeMarkerProcessor" />
<property name="serviceRegistry" ref="ServiceRegistry" />
<!-- <property name="defaultEncoding"><value>UTF-8</value></property> -->
</bean>
</beans>

View File

@@ -0,0 +1,27 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- -->
<!-- API Testing -->
<!-- -->
<bean id="webscripts.test" class="org.alfresco.web.scripts.TestWebScriptServer">
<property name="registry" ref="webscripts.registry" />
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="authenticationService" ref="authenticationService" />
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="configService" ref="webClientConfigService" />
<property name="messages">
<bean class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>alfresco/messages/webscripts</value>
</list>
</property>
</bean>
</property>
</bean>
</beans>

View File

@@ -3,10 +3,156 @@
<beans>
<!-- -->
<!-- -->
<!-- Web Script Storage -->
<!-- -->
<bean id="webscripts.repostore" class="org.alfresco.web.scripts.RepoStore" abstract="true">
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="nodeService" ref="nodeService" />
<property name="namespaceService" ref="namespaceService" />
<property name="contentService" ref="contentService" />
<property name="fileFolderService" ref="fileFolderService" />
<property name="searchService" ref="SearchService" />
<property name="permissionService" ref="PermissionService" />
</bean>
<bean id="webscripts.classpathstore" class="org.alfresco.web.scripts.ClassPathStore" abstract="true" />
<bean parent="webscripts.repostore">
<property name="store"><value>workspace://SpacesStore</value></property>
<property name="path"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/cm:extensionwebscripts</value></property>
</bean>
<bean parent="webscripts.repostore">
<property name="mustExist"><value>true</value></property>
<property name="store"><value>workspace://SpacesStore</value></property>
<property name="path"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/cm:webscripts</value></property>
</bean>
<bean parent="webscripts.classpathstore">
<property name="classPath"><value>alfresco/extension/templates/webscripts</value></property>
</bean>
<bean parent="webscripts.classpathstore">
<property name="mustExist"><value>true</value></property>
<property name="classPath"><value>alfresco/templates/webscripts</value></property>
</bean>
<bean id="webscripts.storage" class="org.alfresco.web.scripts.WebScriptStorage">
<property name="templateProcessor" ref="webscripts.templateprocessor" />
<property name="scriptProcessor" ref="webscripts.scriptprocessor" />
</bean>
<!-- -->
<!-- Web Script Context -->
<!-- -->
<bean id="webscripts.resources" class="org.alfresco.i18n.ResourceBundleBootstrapComponent">
<property name="resourceBundles">
<list>
<value>alfresco.messages.webscripts</value>
</list>
</property>
</bean>
<bean id="webscripts.context" class="org.alfresco.web.scripts.WebScriptContext">
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="namespaceService" ref="namespaceService" />
<property name="nodeService" ref="nodeService" />
<property name="personService" ref="personService" />
<property name="searchService" ref="searchService" />
<property name="companyHomeStore"><value>${spaces.store}</value></property>
<property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property>
</bean>
<bean id="webscripts.templateprocessor" class="org.alfresco.web.scripts.TemplateProcessor">
<property name="freeMarkerProcessor" ref="freeMarkerProcessor" />
<property name="serviceRegistry" ref="ServiceRegistry" />
<!-- <property name="defaultEncoding"><value>UTF-8</value></property> -->
</bean>
<bean id="webscripts.scriptprocessor" class="org.alfresco.web.scripts.ScriptProcessor">
<property name="scriptService" ref="ScriptService" />
</bean>
<!-- -->
<!-- Web Script Registry -->
<!-- -->
<bean id="webscripts.registry" class="org.alfresco.web.scripts.DeclarativeWebScriptRegistry">
<property name="storage" ref="webscripts.storage" />
<property name="formatRegistry" ref="webscripts.formatregistry" />
<property name="defaultWebScript"><value>webscript_default</value></property>
</bean>
<!-- Alfresco Web Client Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.webclient" class="org.alfresco.web.scripts.WebClientAuthenticator" />
<!-- HTTP Basic Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.basic" class="org.alfresco.web.scripts.BasicHttpAuthenticator">
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<!-- JSR-168 Authenticator (Portal based) -->
<bean id="webscripts.authenticator.jsr168" class="org.alfresco.web.scripts.portlet.JSR168PortletAuthenticator">
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<!-- -->
<bean id="webscripts.authenticator.jsr168.webclient" class="org.alfresco.web.scripts.portlet.WebClientPortletAuthenticator">
<property name="scriptContext" ref="webscripts.context" />
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<!-- -->
<!-- Response Formats -->
<!-- -->
<!-- Format Registry -->
<bean id="webscripts.formatregistry" class="org.alfresco.web.scripts.FormatRegistry" />
<!-- Format Map -->
<bean id="webscripts.formatmap" class="org.alfresco.web.scripts.FormatMap" abstract="true">
<property name="registry" ref="webscripts.formatregistry" />
</bean>
<!-- Default set of API Formats -->
<bean id="webscripts.formats" parent="webscripts.formatmap">
<property name="formats">
<props>
<prop key="html">text/html</prop>
<prop key="text">text/plain</prop>
<prop key="xml">text/xml</prop>
<prop key="atom">application/atom+xml</prop>
<prop key="rss">application/rss+xml</prop>
<prop key="json">application/json</prop>
<prop key="opensearchdescription">application/opensearchdescription+xml</prop>
<prop key="mediawiki">text/plain</prop>
<prop key="portlet">text/html</prop>
<prop key="fbml">text/html</prop>
</props>
</property>
</bean>
<!-- IE Specific set of API Formats -->
<bean id="webscripts.formats.IE" parent="webscripts.formatmap">
<property name="agent"><value>MSIE</value></property>
<property name="formats">
<props>
<prop key="atom">text/xml</prop>
<prop key="rss">text/xml</prop>
<prop key="opensearchdescription">text/xml</prop>
</props>
</property>
</bean>
<!-- -->
<!-- Web Script Configuration -->
<!-- -->
<!-- -->
<bean id="webscripts.configsource" class="org.alfresco.config.source.UrlConfigSource">
<constructor-arg>
@@ -23,193 +169,100 @@
<ref bean="webscripts.configsource" />
</constructor-arg>
</bean>
<!-- -->
<!-- API Testing -->
<!-- -->
<bean id="webscripts.test" class="org.alfresco.repo.web.scripts.TestWebScriptRepoServer">
<property name="container" ref="webscripts.container" />
<property name="authenticationService" ref="authenticationService" />
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="messages">
<bean class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>alfresco/messages/webscripts</value>
</list>
</property>
</bean>
</property>
</bean>
<!-- -->
<!-- Web Script Storage -->
<!-- -->
<bean id="webscripts.repostore" class="org.alfresco.repo.web.scripts.RepoStore" abstract="true">
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="nodeService" ref="nodeService" />
<property name="namespaceService" ref="namespaceService" />
<property name="contentService" ref="contentService" />
<property name="fileFolderService" ref="fileFolderService" />
<property name="searchService" ref="SearchService" />
<property name="permissionService" ref="PermissionService" />
</bean>
<bean name="webscripts.store.repo.extension" parent="webscripts.repostore">
<property name="store"><value>workspace://SpacesStore</value></property>
<property name="path"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/cm:extensionwebscripts</value></property>
</bean>
<bean name="webscripts.store.repo" parent="webscripts.repostore">
<property name="mustExist"><value>true</value></property>
<property name="store"><value>workspace://SpacesStore</value></property>
<property name="path"><value>/${spaces.company_home.childname}/${spaces.dictionary.childname}/cm:webscripts</value></property>
</bean>
<bean id="webscripts.store.client.extension" parent="webscripts.classpathstore">
<property name="classPath"><value>alfresco/extension/templates/webscripts</value></property>
</bean>
<bean id="webscripts.store.client" parent="webscripts.classpathstore">
<property name="mustExist"><value>true</value></property>
<property name="classPath"><value>alfresco/templates/webscripts</value></property>
</bean>
<bean id="webscripts.searchpath" class="org.alfresco.web.scripts.SearchPath">
<property name="searchPath">
<list>
<ref bean="webscripts.store.repo.extension" />
<ref bean="webscripts.store.repo" />
<ref bean="webscripts.store.client.extension" />
<ref bean="webscripts.store.client" />
<ref bean="webscripts.store" />
</list>
</property>
</bean>
<!-- -->
<!-- Web Script Repository (Server-Tier) Container -->
<!-- -->
<!-- -->
<!-- Base implementations of a Web Script Backing Bean -->
<!-- -->
<bean id="webscripts.repo" class="org.alfresco.repo.web.scripts.Repository">
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="namespaceService" ref="namespaceService" />
<property name="nodeService" ref="nodeService" />
<property name="personService" ref="personService" />
<property name="fileFolderService" ref="fileFolderService" />
<property name="searchService" ref="searchService" />
<property name="companyHomeStore"><value>${spaces.store}</value></property>
<property name="companyHomePath"><value>/${spaces.company_home.childname}</value></property>
</bean>
<bean id="webscripts.repo.imageresolver" class="org.alfresco.repo.web.scripts.RepositoryImageResolver" />
<bean id="webscripts.repo.templateprocessor" class="org.alfresco.repo.web.scripts.RepositoryTemplateProcessor">
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="freeMarkerProcessor" ref="freeMarkerProcessor" />
<property name="searchPath" ref="webscripts.searchpath" />
<!-- <property name="defaultEncoding"><value>UTF-8</value></property> -->
</bean>
<bean id="webscripts.repo.scriptprocessor" class="org.alfresco.repo.web.scripts.RepositoryScriptProcessor">
<property name="searchPath" ref="webscripts.searchpath" />
</bean>
<bean id="webscripts.container" class="org.alfresco.repo.web.scripts.RepositoryContainer">
<property name="name"><value>Repository</value></property>
<property name="transactionHelper" ref="retryingTransactionHelper" />
<property name="permissionService" ref="permissionService" />
<property name="repository" ref="webscripts.repo" />
<property name="repositoryImageResolver" ref="webscripts.repo.imageresolver" />
<property name="registry" ref="webscripts.registry" />
<property name="formatRegistry" ref="webscripts.formatregistry" />
<property name="templateProcessor" ref="webscripts.repo.templateprocessor" />
<property name="scriptProcessor" ref="webscripts.repo.scriptprocessor" />
<!-- Abstract API Service -->
<bean id="webscript" abstract="true">
<property name="scriptContext" ref="webscripts.context" />
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="descriptorService" ref="DescriptorService" />
</bean>
<!-- Scripted API Service -->
<bean id="webscript_default" parent="webscript" class="org.alfresco.web.scripts.DeclarativeWebScript" singleton="false"/>
<!-- -->
<!-- Web Script Authenticators -->
<!-- -->
<!-- Alfresco Web Client Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.webclient" class="org.alfresco.repo.web.scripts.servlet.WebClientAuthenticatorFactory" />
<!-- HTTP Basic Authenticator (Servlet based) -->
<bean id="webscripts.authenticator.basic" class="org.alfresco.repo.web.scripts.servlet.BasicHttpAuthenticatorFactory">
<property name="authenticationService" ref="AuthenticationService" />
<!-- -->
<!-- Facebook Web Scripts -->
<!-- -->
<bean id="facebook.service" class="org.alfresco.web.scripts.facebook.FacebookService">
<property name="registry" ref="webscripts.registry" />
</bean>
<!-- JSR-168 Authenticator (Portal based) -->
<bean id="webscripts.authenticator.jsr168" class="org.alfresco.repo.web.scripts.portlet.JSR168PortletAuthenticatorFactory">
<property name="authenticationService" ref="AuthenticationService" />
</bean>
<bean id="webscripts.authenticator.jsr168.webclient" class="org.alfresco.repo.web.scripts.portlet.WebClientPortletAuthenticatorFactory">
<property name="repository" ref="webscripts.repo" />
<property name="authenticationService" ref="AuthenticationService" />
<bean id="facebook.authenticator" class="org.alfresco.web.scripts.facebook.FacebookAuthenticator"/>
<!-- -->
<!-- Custom Java Web Script Backing Beans -->
<!-- -->
<!-- List of available Web APIs -->
<bean id="webscript.org.alfresco.index.get" class="org.alfresco.web.scripts.bean.Index" parent="webscript" singleton="false"/>
<alias name="webscript.org.alfresco.index.get" alias="webscript.org.alfresco.indexall.get"/>
<bean id="webscript.org.alfresco.indexuri.get" class="org.alfresco.web.scripts.bean.IndexURI" parent="webscript" />
<bean id="webscript.org.alfresco.indexpackage.get" class="org.alfresco.web.scripts.bean.IndexPackage" parent="webscript" />
<!-- Maintain list of available Web APIs -->
<bean id="webscript.org.alfresco.index.post" class="org.alfresco.web.scripts.bean.IndexUpdate" parent="webscript" >
<property name="facebookService" ref="facebook.service"/>
</bean>
<!-- Facebook Authenticator -->
<bean id="webscripts.authenticator.facebook" class="org.alfresco.repo.web.scripts.facebook.FacebookAuthenticatorFactory" />
<!-- Retrieve Web Script Description Document -->
<bean id="webscript.org.alfresco.scriptdescription.get" class="org.alfresco.web.scripts.bean.ServiceDescription" parent="webscript" />
<!-- Web Script Dump -->
<bean id="webscript.org.alfresco.scriptdump.get" class="org.alfresco.web.scripts.bean.ServiceDump" parent="webscript" >
<property name="storage" ref="webscripts.storage"/>
</bean>
<!-- -->
<!-- API Beans -->
<!-- -->
<!-- Web Script Install -->
<bean id="webscript.org.alfresco.scriptinstall.post" class="org.alfresco.web.scripts.bean.ServiceInstall" parent="webscript" >
<property name="storage" ref="webscripts.storage"/>
</bean>
<!-- Javascript APIs -->
<bean id="webscript.org.alfresco.jsdebugger.get" class="org.alfresco.repo.web.scripts.bean.JavascriptDebugger" parent="webscript">
<bean id="webscript.org.alfresco.jsdebugger.get" class="org.alfresco.web.scripts.bean.JavascriptDebugger" parent="webscript">
<property name="debugger" ref="rhinoScriptDebugger" />
</bean>
<bean id="webscript.org.alfresco.jsdebugger.post" class="org.alfresco.repo.web.scripts.bean.JavascriptDebuggerPost" parent="webscript">
<bean id="webscript.org.alfresco.jsdebugger.post" class="org.alfresco.web.scripts.bean.JavascriptDebuggerPost" parent="webscript">
<property name="debugger" ref="rhinoScriptDebugger" />
</bean>
<!-- Authentication APIs -->
<bean id="webscript.org.alfresco.repository.login.get" class="org.alfresco.repo.web.scripts.bean.Login" parent="webscript">
<bean id="webscript.org.alfresco.repository.login.get" class="org.alfresco.web.scripts.bean.Login" parent="webscript">
<property name="authenticationService" ref="authenticationService" />
</bean>
<bean id="webscript.org.alfresco.repository.loginticket.get" class="org.alfresco.repo.web.scripts.bean.LoginTicket" parent="webscript">
<bean id="webscript.org.alfresco.repository.loginticket.get" class="org.alfresco.web.scripts.bean.LoginTicket" parent="webscript">
<property name="ticketComponent" ref="ticketComponent" />
</bean>
<bean id="webscript.org.alfresco.repository.loginticket.delete" class="org.alfresco.repo.web.scripts.bean.LoginTicketDelete" parent="webscript">
<bean id="webscript.org.alfresco.repository.loginticket.delete" class="org.alfresco.web.scripts.bean.LoginTicketDelete" parent="webscript">
<property name="authenticationService" ref="authenticationService" />
<property name="ticketComponent" ref="ticketComponent" />
</bean>
<!-- List of registered (OpenSearch) search engines -->
<bean id="webscript.org.alfresco.repository.search.searchengines.get" class="org.alfresco.repo.web.scripts.bean.SearchEngines" parent="webscript">
<bean id="webscript.org.alfresco.repository.search.searchengines.get" class="org.alfresco.web.scripts.bean.SearchEngines" parent="webscript">
<property name="configService" ref="webscripts.config" />
<property name="searchProxy" ref="webscript.org.alfresco.repository.search.searchproxy.get" />
</bean>
<!-- Alfresco Web Client Keyword Search (OpenSearch) -->
<bean id="webscript.org.alfresco.repository.search.keywordsearch.get" class="org.alfresco.repo.web.scripts.bean.KeywordSearch" parent="webscript">
<bean id="webscript.org.alfresco.repository.search.keywordsearch.get" class="org.alfresco.web.scripts.bean.KeywordSearch" parent="webscript">
<property name="searchService" ref="SearchService" />
<property name="serviceRegistry" ref="ServiceRegistry" />
<property name="repositoryImageResolver" ref="webscripts.repo.imageresolver" />
</bean>
<!-- Alfresco (OpenSearch) Proxy -->
<bean id="webscript.org.alfresco.repository.search.searchproxy.get" class="org.alfresco.repo.web.scripts.bean.SearchProxy" parent="webscript">
<bean id="webscript.org.alfresco.repository.search.searchproxy.get" class="org.alfresco.web.scripts.bean.SearchProxy" parent="webscript">
<property name="configService" ref="webscripts.config" />
<property name="formatRegistry" ref="webscripts.formatregistry" />
</bean>
<!-- Content Retrieval -->
<bean id="webscript.org.alfresco.repository.store.content.get" class="org.alfresco.repo.web.scripts.bean.ContentGet" parent="webscript">
<property name="repository" ref="webscripts.repo" />
<property name="namespaceService" ref="NamespaceService" />
<property name="permissionService" ref="PermissionService" />
<property name="nodeService" ref="NodeService" />
<property name="contentService" ref="ContentService" />
<property name="mimetypeService" ref="MimetypeService" />
</bean>
<bean id="webscript.org.alfresco.repository.store.content.get" class="org.alfresco.web.scripts.bean.ContentGet" parent="webscript"/>
</beans>

View File

@@ -1,250 +0,0 @@
package org.alfresco.repo.web.scripts;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.AbstractRuntimeContainer;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Description;
import org.alfresco.web.scripts.ServerModel;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.Description.RequiredTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class RepositoryContainer extends AbstractRuntimeContainer
{
// Logger
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class);
/** Component Dependencies */
private Repository repository;
private RepositoryImageResolver imageResolver;
private RetryingTransactionHelper retryingTransactionHelper;
private AuthorityService authorityService;
private PermissionService permissionService;
private DescriptorService descriptorService;
public void setRepository(Repository repository)
{
this.repository = repository;
}
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
public void setAuthorityService(AuthorityService authorityService)
{
this.authorityService = authorityService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Container#getDescription()
*/
public ServerModel getDescription()
{
return new RepositoryServerModel(descriptorService.getServerDescriptor());
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getScriptParameters()
*/
public Map<String, Object> getScriptParameters()
{
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(super.getScriptParameters());
addRepoParameters(params);
return params;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getTemplateParameters()
*/
public Map<String, Object> getTemplateParameters()
{
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(super.getTemplateParameters());
params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver());
addRepoParameters(params);
return params;
}
/**
* Add Repository specific parameters
*
* @param params
*/
private void addRepoParameters(Map<String, Object> params)
{
if (AlfrescoTransactionSupport.getTransactionId() != null)
{
NodeRef rootHome = repository.getRootHome();
if (rootHome != null && permissionService.hasPermission(rootHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("roothome", rootHome);
}
NodeRef companyHome = repository.getCompanyHome();
if (companyHome != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("companyhome", companyHome);
}
NodeRef person = repository.getPerson();
if (person != null && permissionService.hasPermission(companyHome, PermissionService.READ).equals(AccessStatus.ALLOWED))
{
params.put("person", person);
params.put("userhome", repository.getUserHome(person));
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.RuntimeContainer#executeScript(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse, org.alfresco.web.scripts.Authenticator)
*/
public void executeScript(WebScriptRequest scriptReq, WebScriptResponse scriptRes, Authenticator auth)
throws IOException
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
Description desc = script.getDescription();
RequiredAuthentication required = desc.getRequiredAuthentication();
boolean isGuest = scriptReq.isGuest();
if (required == RequiredAuthentication.none)
{
AuthenticationUtil.clearCurrentSecurityContext();
transactionedExecute(script, scriptReq, scriptRes);
}
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
}
else
{
String currentUser = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
{
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
logger.debug("Authentication required: " + required);
logger.debug("Guest login: " + isGuest);
}
//
// Apply appropriate authentication to Web Script invocation
//
if (auth == null || auth.authenticate(required, isGuest))
{
if (required == RequiredAuthentication.admin && !authorityService.hasAdminAuthority())
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
}
// Execute Web Script
transactionedExecute(script, scriptReq, scriptRes);
}
}
finally
{
//
// Reset authentication for current thread
//
AuthenticationUtil.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
}
}
/**
* Execute script within required level of transaction
*
* @param scriptReq
* @param scriptRes
* @throws IOException
*/
protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
throws IOException
{
final Description description = script.getDescription();
if (description.getRequiredTransaction() == RequiredTransaction.none)
{
script.execute(scriptReq, scriptRes);
}
else
{
// encapsulate script within transaction
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
script.execute(scriptReq, scriptRes);
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return null;
}
};
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
retryingTransactionHelper.doInTransaction(work);
}
else
{
retryingTransactionHelper.doInTransaction(work, false, true);
}
}
}
}

View File

@@ -1,50 +0,0 @@
package org.alfresco.repo.web.scripts;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.web.ui.common.Utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.context.ServletContextAware;
public class RepositoryImageResolver
implements ServletContextAware, InitializingBean
{
private ServletContext servletContext;
private TemplateImageResolver imageResolver;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.servletContext = context;
}
/*(non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet()
throws Exception
{
this.imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return Utils.getFileTypeImage(servletContext, filename, size);
}
};
}
/**
* @return image resolver
*/
public TemplateImageResolver getImageResolver()
{
return this.imageResolver;
}
}

View File

@@ -1,125 +0,0 @@
package org.alfresco.repo.web.scripts;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.alfresco.service.cmr.repository.ScriptException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService;
import org.alfresco.web.scripts.MultiScriptLoader;
import org.alfresco.web.scripts.ScriptContent;
import org.alfresco.web.scripts.ScriptLoader;
import org.alfresco.web.scripts.ScriptProcessor;
import org.alfresco.web.scripts.SearchPath;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.factory.InitializingBean;
public class RepositoryScriptProcessor implements ScriptProcessor, InitializingBean
{
// dependencies
protected ScriptService scriptService;
protected ScriptLoader scriptLoader;
protected SearchPath searchPath;
/**
* Sets the script service
*
* @param scriptService
*/
public void setScriptService(ScriptService scriptService)
{
this.scriptService = scriptService;
}
public void setSearchPath(SearchPath searchPath)
{
this.searchPath = searchPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#findScript(java.lang.String)
*/
public ScriptContent findScript(String path)
{
return scriptLoader.getScript(path);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(java.lang.String, java.util.Map)
*/
public Object executeScript(String path, Map<String, Object> model)
throws ScriptException
{
// locate script within web script stores
ScriptContent scriptContent = findScript(path);
if (scriptContent == null)
{
throw new WebScriptException("Unable to locate script " + path);
}
// execute script
return executeScript(scriptContent, model);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#executeScript(org.alfresco.web.scripts.ScriptContent, java.util.Map)
*/
public Object executeScript(ScriptContent content, Map<String, Object> model)
{
return scriptService.executeScript("javascript", new RepositoryScriptLocation(content), model);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptProcessor#reset()
*/
public void reset()
{
// NOOP
}
private static class RepositoryScriptLocation implements ScriptLocation
{
private ScriptContent content;
private RepositoryScriptLocation(ScriptContent content)
{
this.content = content;
}
public InputStream getInputStream()
{
return content.getInputStream();
}
public Reader getReader()
{
return content.getReader();
}
}
/**
* Register script loader from each Web Script Store with Script Processor
*/
public void afterPropertiesSet()
{
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
for (Store apiStore : searchPath.getStores())
{
ScriptLoader loader = apiStore.getScriptLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
scriptLoader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
}
}

View File

@@ -1,159 +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.repo.web.scripts;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.TestWebScriptServer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Stand-alone Web Script Test Server
*
* @author davidc
*/
public class TestWebScriptRepoServer extends TestWebScriptServer
{
private RetryingTransactionHelper retryingTransactionHelper;
private AuthenticationService authenticationService;
/**
* Sets helper that provides transaction callbacks
*/
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
TestWebScriptServer testServer = getTestServer();
testServer.rep();
}
catch(Throwable e)
{
StringWriter strWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(strWriter);
e.printStackTrace(printWriter);
System.out.println(strWriter.toString());
}
finally
{
System.exit(0);
}
}
/**
* Retrieve an instance of the TestWebScriptServer
*
* @return Test Server
*/
public static TestWebScriptServer getTestServer()
{
String[] CONFIG_LOCATIONS = new String[]
{
"classpath:alfresco/application-context.xml",
"classpath:alfresco/web-framework-application-context.xml",
"classpath:alfresco/web-scripts-application-context.xml",
"classpath:alfresco/web-client-application-context.xml"
};
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
TestWebScriptServer testServer = (TestWebScriptRepoServer)context.getBean("webscripts.test");
return testServer;
}
/**
* Interpret a single command using the BufferedReader passed in for any data needed.
*
* @param line The unparsed command
* @return The textual output of the command.
*/
@Override
protected String interpretCommand(final String line)
throws IOException
{
try
{
if (username.startsWith("TICKET_"))
{
try
{
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
authenticationService.validate(username);
return null;
}
});
return executeCommand(line);
}
finally
{
authenticationService.clearCurrentSecurityContext();
}
}
}
catch(AuthenticationException e)
{
executeCommand("user admin");
}
// execute command in context of currently selected user
return AuthenticationUtil.runAs(new RunAsWork<String>()
{
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception
{
return executeCommand(line);
}
}, username);
}
}

View File

@@ -1,143 +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.repo.web.scripts.facebook;
import java.io.IOException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.facebook.FacebookServletRequest;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class FacebookAuthenticatorFactory implements ServletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(FacebookAuthenticator.class);
/* (non-Javadoc)
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
if (!(req instanceof FacebookServletRequest))
{
throw new WebScriptException("Facebook request is required; instead a " + req.getClass().getName() + " has been provided");
}
return new FacebookAuthenticator((FacebookServletRequest)req, res);
}
/**
* Web Script Authenticator that supports Facebook authentication
* mechanism.
*
* Upon success, the request is authenticated as the Facebook User Id.
*
* @author davidc
*/
public class FacebookAuthenticator implements Authenticator
{
// FBML for Facebook login redirect
private static final String LOGIN_REDIRECT = "<fb:redirect url=\"http://www.facebook.com/login.php?api_key=%s&v=1.0%s\">";
// dependencies
private FacebookServletRequest fbReq;
private WebScriptServletResponse fbRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public FacebookAuthenticator(FacebookServletRequest req, WebScriptServletResponse res)
{
this.fbReq = req;
this.fbRes = res;
}
/* (non-Javadoc)
* @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
String sessionKey = fbReq.getSessionKey();
String user = fbReq.getUserId();
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_session_key = '" + sessionKey + "'");
logger.debug("fb_sig_user = '" + user + "'");
}
if ((sessionKey == null || sessionKey.length() == 0) || (user == null || user.length() == 0))
{
// session has not been established, redirect to login
String apiKey = fbReq.getApiKey();
String canvas = (fbReq.isInCanvas()) ? "&canvas" : "";
if (logger.isDebugEnabled())
{
logger.debug("fb_sig_api_key = '" + apiKey + "'");
logger.debug("fb_sig_in_canvas = '" + canvas + "'");
}
try
{
String redirect = String.format(LOGIN_REDIRECT, apiKey, canvas);
if (logger.isDebugEnabled())
logger.debug("Facebook session not established; redirecting via " + redirect);
fbRes.getWriter().write(redirect);
}
catch (IOException e)
{
throw new WebScriptException("Redirect to login failed", e);
}
return false;
}
if (logger.isDebugEnabled())
logger.debug("Facebook session established; authenticating as user " + user);
// session has been established, authenticate as Facebook user id
AuthenticationUtil.setCurrentUser(user);
return true;
}
}
}

View File

@@ -1,134 +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.repo.web.scripts.portlet;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory;
import org.alfresco.web.scripts.portlet.WebScriptPortletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JSR168PortletAuthenticatorFactory implements PortletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(JSR168PortletAuthenticatorFactory.class);
// dependencies
private AuthenticationService authenticationService;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public Authenticator create(RenderRequest req, RenderResponse res)
{
return new JSR168PortletAuthenticator(req, res);
}
/**
* Portlet authenticator
*
* @author davidc
*/
public class JSR168PortletAuthenticator implements Authenticator
{
// dependencies
private RenderRequest req;
private RenderResponse res;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public JSR168PortletAuthenticator(RenderRequest req, RenderResponse res)
{
this.req = req;
this.res = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.WebScriptPortletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
// first look for the username key in the session - we add this by hand for some portals
// when the WebScriptPortletRequest is created
String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME);
if (portalUser == null)
{
portalUser = req.getRemoteUser();
}
if (logger.isDebugEnabled())
{
logger.debug("JSR-168 Remote user: " + portalUser);
}
if (isGuest || portalUser == null)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
// authenticate as guest
AuthenticationUtil.setCurrentUser(AuthenticationUtil.getGuestUserName());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as user " + portalUser);
if (!authenticationService.authenticationExists(portalUser))
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "User " + portalUser + " is not a known Alfresco user");
}
AuthenticationUtil.setCurrentUser(portalUser);
}
return true;
}
}
}

View File

@@ -1,198 +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.repo.web.scripts.portlet;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.web.scripts.Repository;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.bean.repository.User;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory;
import org.alfresco.web.scripts.portlet.WebScriptPortletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Portlet authenticator which synchronizes with the Alfresco Web Client authentication
*
* @author davidc
*/
public class WebClientPortletAuthenticatorFactory implements PortletAuthenticatorFactory
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientPortletAuthenticatorFactory.class);
// dependencies
private AuthenticationService authenticationService;
private Repository repository;
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* @param scriptContext
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.portlet.PortletAuthenticatorFactory#create(javax.portlet.RenderRequest, javax.portlet.RenderResponse)
*/
public Authenticator create(RenderRequest req, RenderResponse res)
{
return new WebClientPortletAuthenticator(req, res);
}
public class WebClientPortletAuthenticator implements Authenticator
{
// dependencies
private RenderRequest req;
private RenderResponse res;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public WebClientPortletAuthenticator(RenderRequest req, RenderResponse res)
{
this.req = req;
this.res = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
PortletSession session = req.getPortletSession();
// first look for the username key in the session - we add this by hand for some portals
// when the WebScriptPortletRequest is created
String portalUser = (String)req.getPortletSession().getAttribute(WebScriptPortletRequest.ALFPORTLETUSERNAME);
if (portalUser == null)
{
portalUser = req.getRemoteUser();
}
if (logger.isDebugEnabled())
{
logger.debug("JSR-168 Remote user: " + portalUser);
}
if (isGuest || portalUser == null)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
// authenticate as guest
AuthenticationUtil.setCurrentUser(AuthenticationUtil.getGuestUserName());
if (logger.isDebugEnabled())
logger.debug("Setting Web Client authentication context for guest");
createWebClientUser(session);
removeSessionInvalidated(session);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as user " + portalUser);
AuthenticationUtil.setCurrentUser(portalUser);
// determine if Web Client context needs to be updated
User user = getWebClientUser(session);
if (user == null || !portalUser.equals(user.getUserName()))
{
if (logger.isDebugEnabled())
logger.debug("Setting Web Client authentication context for user " + portalUser);
createWebClientUser(session);
removeSessionInvalidated(session);
}
}
return true;
}
/**
* Helper. Remove Web Client session invalidated flag
*
* @param session
*/
private void removeSessionInvalidated(PortletSession session)
{
session.removeAttribute(AuthenticationHelper.SESSION_INVALIDATED, PortletSession.APPLICATION_SCOPE);
}
/**
* Helper. Create Web Client session user
*
* @param session
*/
private void createWebClientUser(PortletSession session)
{
NodeRef personRef = repository.getPerson();
User user = new User(authenticationService.getCurrentUserName(), authenticationService.getCurrentTicket(), personRef);
NodeRef homeRef = repository.getUserHome(personRef);
if (homeRef != null)
{
user.setHomeSpaceId(homeRef.getId());
}
session.setAttribute(AuthenticationHelper.AUTHENTICATION_USER, user, PortletSession.APPLICATION_SCOPE);
}
/**
* Helper. Get Web Client session user
*
* @param session
* @return
*/
private User getWebClientUser(PortletSession session)
{
return (User)session.getAttribute(AuthenticationHelper.AUTHENTICATION_USER, PortletSession.APPLICATION_SCOPE);
}
}
}

View File

@@ -1,33 +0,0 @@
package org.alfresco.repo.web.scripts.portlet;
import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletSecurityException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.alfresco.web.app.Application;
import org.alfresco.web.scripts.portlet.WebScriptPortlet;
public class WebScriptRepoPortlet extends WebScriptPortlet
{
@Override
public void processAction(ActionRequest req, ActionResponse res) throws PortletException, PortletSecurityException, IOException
{
Application.setInPortalServer(true);
super.processAction(req, res);
}
@Override
public void render(RenderRequest req, RenderResponse res) throws PortletException, PortletSecurityException, IOException
{
Application.setInPortalServer(true);
super.render(req, res);
}
}

View File

@@ -1,204 +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.repo.web.scripts.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.Base64;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class BasicHttpAuthenticatorFactory implements ServletAuthenticatorFactory
{
// Logger
private static Log logger = LogFactory.getLog(BasicHttpAuthenticator.class);
// Component dependencies
private AuthenticationService authenticationService;
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
return new BasicHttpAuthenticator(req, res);
}
/**
* HTTP Basic Authentication
*
* @author davidc
*/
public class BasicHttpAuthenticator implements Authenticator
{
// dependencies
private WebScriptServletRequest servletReq;
private WebScriptServletResponse servletRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public BasicHttpAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res)
{
this.servletReq = req;
this.servletRes = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Authenticator#authenticate(org.alfresco.web.scripts.Description.RequiredAuthentication, boolean)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
boolean authorized = false;
//
// validate credentials
//
HttpServletRequest req = servletReq.getHttpServletRequest();
HttpServletResponse res = servletRes.getHttpServletResponse();
String authorization = req.getHeader("Authorization");
String ticket = req.getParameter("alf_ticket");
if (logger.isDebugEnabled())
{
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
logger.debug("URL ticket provided: " + (ticket != null && ticket.length() > 0));
}
// authenticate as guest, if service allows
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by explicit ticket on url
else if (ticket != null && ticket.length() > 0)
{
try
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (URL argument) ticket " + ticket);
// assume a ticket has been passed
authenticationService.validate(ticket);
authorized = true;
}
catch(AuthenticationException e)
{
// failed authentication
}
}
// authenticate as specified by HTTP Basic Authentication
else if (authorization != null && authorization.length() > 0)
{
try
{
String[] authorizationParts = authorization.split(" ");
if (!authorizationParts[0].equalsIgnoreCase("basic"))
{
throw new WebScriptException("Authorization '" + authorizationParts[0] + "' not supported.");
}
String decodedAuthorisation = new String(Base64.decode(authorizationParts[1]));
String[] parts = decodedAuthorisation.split(":");
if (parts.length == 1)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) user " + parts[0]);
// assume username and password passed
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
{
if (required == RequiredAuthentication.guest)
{
authenticationService.authenticateAsGuest();
authorized = true;
}
}
else
{
authenticationService.authenticate(parts[0], parts[1].toCharArray());
authorized = true;
}
}
}
catch(AuthenticationException e)
{
// failed authentication
}
}
//
// request credentials if not authorized
//
if (!authorized)
{
if (logger.isDebugEnabled())
logger.debug("Requesting authorization credentials");
res.setStatus(401);
res.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
}
return authorized;
}
}
}

View File

@@ -1,164 +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.repo.web.scripts.servlet;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.ServletContextAware;
public class WebClientAuthenticatorFactory implements ServletAuthenticatorFactory, ServletContextAware
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientAuthenticator.class);
// dependencies
private ServletContext context;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.context = context;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.servlet.ServletAuthenticatorFactory#create(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public Authenticator create(WebScriptServletRequest req, WebScriptServletResponse res)
{
return new WebClientAuthenticator(req, res);
}
/**
* Alfresco Web Client Authentication
*
* @author davidc
*/
public class WebClientAuthenticator implements Authenticator
{
// dependencies
private WebScriptServletRequest servletReq;
private WebScriptServletResponse servletRes;
/**
* Construct
*
* @param authenticationService
* @param req
* @param res
*/
public WebClientAuthenticator(WebScriptServletRequest req, WebScriptServletResponse res)
{
this.servletReq = req;
this.servletRes = res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest)
{
AuthenticationStatus status = null;
try
{
//
// validate credentials
//
HttpServletRequest req = servletReq.getHttpServletRequest();
HttpServletResponse res = servletRes.getHttpServletResponse();
String ticket = req.getParameter("ticket");
if (logger.isDebugEnabled())
{
logger.debug("Alfresco 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, req, res, ticket);
}
else
{
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
status = AuthenticationHelper.authenticate(context, req, res, true);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating session");
status = AuthenticationHelper.authenticate(context, req, res, false, false);
}
}
//
// if not authorized, redirect to login page
//
if (status == null || status == AuthenticationStatus.Failure)
{
// 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(req, res, context);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to authenticate", e);
}
return !(status == null || status == AuthenticationStatus.Failure);
}
}
}

View File

@@ -38,6 +38,7 @@ import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;

View File

@@ -51,23 +51,22 @@ import org.alfresco.config.ConfigService;
import org.alfresco.config.JNDIConstants;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.repo.template.ClassPathRepoTemplateLoader;
import org.alfresco.service.cmr.avm.AVMNotFoundException;
import org.alfresco.service.cmr.avm.AVMService;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.Cache;
import org.alfresco.web.scripts.Runtime;
import org.alfresco.web.scripts.AbstractRuntime;
import org.alfresco.web.scripts.Authenticator;
import org.alfresco.web.scripts.Match;
import org.alfresco.web.scripts.WebScriptCache;
import org.alfresco.web.scripts.WebScriptMatch;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptRequestURLImpl;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.WebScriptResponseImpl;
import org.alfresco.web.scripts.Description.RequiredAuthentication;
import org.alfresco.web.scripts.servlet.WebScriptServlet;
import org.alfresco.web.scripts.WebScriptRuntime;
import org.alfresco.web.scripts.WebScriptServlet;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptURLRequest;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
@@ -78,6 +77,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
@@ -109,7 +109,6 @@ public class PageRendererServlet extends WebScriptServlet
// timeout to reload default page cache from
private static final int DEFAULT_PAGE_CONFIG_CACHE_TIMEOUT = 30000;
private ServiceRegistry serviceRegistry;
private PageTemplateProcessor templateProcessor;
private WebScriptTemplateLoader webscriptTemplateLoader;
private Map<String, ExpiringValueCache<PageDefinition>> defaultPageDefMap = null;
@@ -121,18 +120,15 @@ public class PageRendererServlet extends WebScriptServlet
// init beans
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
serviceRegistry = (ServiceRegistry)context.getBean("serviceRegistry");
templateProcessor = (PageTemplateProcessor)context.getBean("pagerenderer.templateprocessor");
webscriptTemplateLoader = new WebScriptTemplateLoader();
// TODO: Refactor to use web script stores
// ClassPathRepoTemplateLoader repoLoader = new ClassPathRepoTemplateLoader(
// serviceRegistry.getNodeService(),
// serviceRegistry.getContentService(),
// templateProcessor.getDefaultEncoding());
// templateProcessor.setTemplateLoader(new MultiTemplateLoader(new TemplateLoader[]{
// webscriptTemplateLoader, repoLoader}));
// templateProcessor.initConfig();
ClassPathRepoTemplateLoader repoLoader = new ClassPathRepoTemplateLoader(
serviceRegistry.getNodeService(),
serviceRegistry.getContentService(),
templateProcessor.getDefaultEncoding());
templateProcessor.setTemplateLoader(new MultiTemplateLoader(new TemplateLoader[]{
webscriptTemplateLoader, repoLoader}));
templateProcessor.initConfig();
// we use a specific config service instance
configService = (ConfigService)context.getBean("pagerenderer.config");
@@ -476,7 +472,7 @@ public class PageRendererServlet extends WebScriptServlet
/**
* WebScript runtime for the PageRenderer servlet.
*/
private class PageRendererWebScriptRuntime extends AbstractRuntime
private class PageRendererWebScriptRuntime extends WebScriptRuntime
{
private PageComponent component;
private PageRendererContext context;
@@ -488,7 +484,7 @@ public class PageRendererServlet extends WebScriptServlet
PageRendererWebScriptRuntime(
PageComponent component, PageRendererContext context, String webScript, String executeUrl, String encoding)
{
super(PageRendererServlet.this.container);
super(registry, serviceRegistry);
this.component = component;
this.context = context;
this.webScript = webScript;
@@ -498,14 +494,6 @@ public class PageRendererServlet extends WebScriptServlet
logger.debug("Constructing runtime for url: " + executeUrl);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.Runtime#getName()
*/
public String getName()
{
return "Page Renderer";
}
@Override
protected String getScriptUrl()
{
@@ -513,7 +501,7 @@ public class PageRendererServlet extends WebScriptServlet
}
@Override
protected WebScriptRequest createRequest(Match match)
protected WebScriptRequest createRequest(WebScriptMatch match)
{
// set the component properties as the additional request attributes
Map<String, String> attributes = new HashMap<String, String>();
@@ -521,7 +509,7 @@ public class PageRendererServlet extends WebScriptServlet
// add the "well known" attributes - such as avm store
attributes.put("store", this.context.AVMStore);
attributes.put("theme", this.context.Theme);
return new WebScriptPageRendererRequest(this, scriptUrl, match, attributes);
return new WebScriptPageRendererRequest(scriptUrl, match, attributes);
}
@Override
@@ -534,7 +522,7 @@ public class PageRendererServlet extends WebScriptServlet
this.baOut = new ByteArrayOutputStream(4096);
BufferedWriter wrOut = new BufferedWriter(
encoding == null ? new OutputStreamWriter(baOut) : new OutputStreamWriter(baOut, encoding));
return new WebScriptPageRendererResponse(this, context, component.Id, wrOut, baOut);
return new WebScriptPageRendererResponse(context, component.Id, wrOut, baOut);
}
catch (UnsupportedEncodingException err)
{
@@ -542,6 +530,13 @@ public class PageRendererServlet extends WebScriptServlet
}
}
@Override
protected boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res)
{
// TODO: what authentication here?
return true;
}
@Override
protected String getScriptMethod()
{
@@ -568,32 +563,21 @@ public class PageRendererServlet extends WebScriptServlet
throw new AlfrescoRuntimeException("Unsupported encoding.", err);
}
}
@Override
protected Authenticator createAuthenticator()
{
return null;
}
}
/**
* Simple implementation of a WebScript URL Request for a webscript on the page
*/
private class WebScriptPageRendererRequest extends WebScriptRequestURLImpl
private class WebScriptPageRendererRequest extends WebScriptURLRequest
{
private Map<String, String> attributes;
WebScriptPageRendererRequest(Runtime runtime, String scriptUrl, Match match, Map<String, String> attributes)
WebScriptPageRendererRequest(String scriptUrl, WebScriptMatch match, Map<String, String> attributes)
{
super(runtime, scriptUrl, match);
super(scriptUrl, match);
this.attributes = attributes;
}
//
// TODO: Refactor attribute methods - implement getScriptParameters and getTemplateParameters instead
//
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttribute(java.lang.String)
*/
@@ -632,7 +616,7 @@ public class PageRendererServlet extends WebScriptServlet
/**
* Implementation of a WebScript Response object for PageRenderer servlet
*/
private class WebScriptPageRendererResponse extends WebScriptResponseImpl
private class WebScriptPageRendererResponse implements WebScriptResponse
{
private Writer outWriter;
private OutputStream outStream;
@@ -640,9 +624,8 @@ public class PageRendererServlet extends WebScriptServlet
private String componentId;
public WebScriptPageRendererResponse(
Runtime runtime, PageRendererContext context, String componentId, Writer outWriter, OutputStream outStream)
PageRendererContext context, String componentId, Writer outWriter, OutputStream outStream)
{
super(runtime);
this.context = context;
this.componentId = componentId;
this.outWriter = outWriter;
@@ -678,7 +661,7 @@ public class PageRendererServlet extends WebScriptServlet
// not supported
}
public void setCache(Cache cache)
public void setCache(WebScriptCache cache)
{
// not supported
}

View File

@@ -24,8 +24,7 @@
*/
package org.alfresco.web.app.servlet;
import org.alfresco.web.scripts.PresentationTemplateProcessor;
import org.alfresco.web.scripts.TemplateProcessor;
/**
* Extension to the webscripts TemplateProcessor class to allow the default encoding
@@ -33,7 +32,19 @@ import org.alfresco.web.scripts.PresentationTemplateProcessor;
*
* @author Kevin Roast
*/
public class PageTemplateProcessor extends PresentationTemplateProcessor
public class PageTemplateProcessor extends TemplateProcessor
{
public String getDefaultEncoding()
{
return this.defaultEncoding;
}
}
/**
* Initialise FreeMarker Configuration
*/
public void initConfig()
{
super.initConfig();
templateConfig.setTemplateUpdateDelay(0);
}
}

View File

@@ -26,14 +26,17 @@ package org.alfresco.web.bean.ajax;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.repo.template.CropContentMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.template.UrlEncodeMethod;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;

View File

@@ -32,14 +32,22 @@ import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.repo.template.CropContentMethod;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.template.UrlEncodeMethod;
import org.alfresco.repo.template.Workflow;
import org.alfresco.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.service.cmr.workflow.WorkflowService;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.web.app.servlet.BaseTemplateContentServlet;
import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Bean used by an AJAX control to send information back on the requested workflow task.

View File

@@ -0,0 +1,133 @@
/*
* 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.config;
import java.util.List;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.element.ConfigElementAdapter;
/**
* @author David Caruana
*/
public class ServerConfigElement extends ConfigElementAdapter
{
public static final String CONFIG_ELEMENT_ID = "server";
private String scheme = null;
private String hostname = null;
private Integer port = null;
/**
* Default constructor
*/
public ServerConfigElement()
{
super(CONFIG_ELEMENT_ID);
}
/**
* Constructor
*
* @param name Name of the element this config element represents
*/
public ServerConfigElement(String name)
{
super(name);
}
/**
* @see org.alfresco.config.element.ConfigElementAdapter#getChildren()
*/
public List<ConfigElement> getChildren()
{
throw new ConfigException("Reading the Server config via the generic interfaces is not supported");
}
/**
* @see org.alfresco.config.element.ConfigElementAdapter#combine(org.alfresco.config.ConfigElement)
*/
public ConfigElement combine(ConfigElement configElement)
{
ServerConfigElement newElement = (ServerConfigElement)configElement;
ServerConfigElement combinedElement = new ServerConfigElement();
combinedElement.setScheme(newElement.getScheme());
combinedElement.setHostName(newElement.getHostName());
combinedElement.setPort(newElement.getPort());
return combinedElement;
}
/**
* @return server scheme
*/
public String getScheme()
{
return scheme;
}
/**
* @param scheme
*/
public void setScheme(String scheme)
{
this.scheme = scheme;
}
/**
* @return server hostname
*/
public String getHostName()
{
return hostname;
}
/**
* @param hostname
*/
public void setHostName(String hostname)
{
this.hostname = hostname;
}
/**
* @return server port
*/
public Integer getPort()
{
return port;
}
/**
* @param port
*/
public void setPort(Integer port)
{
this.port = port;
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.config;
import org.alfresco.config.ConfigElement;
import org.alfresco.config.ConfigException;
import org.alfresco.config.xml.elementreader.ConfigElementReader;
import org.dom4j.Element;
/**
* @author David Caruana
*/
public class ServerElementReader implements ConfigElementReader
{
public static final String ELEMENT_SCHEME = "scheme";
public static final String ELEMENT_HOSTNAME = "hostname";
public static final String ELEMENT_PORT = "port";
/**
* @see org.alfresco.config.xml.elementreader.ConfigElementReader#parse(org.dom4j.Element)
*/
@SuppressWarnings("unchecked")
public ConfigElement parse(Element element)
{
ServerConfigElement configElement = new ServerConfigElement();
if (element != null)
{
if (ServerConfigElement.CONFIG_ELEMENT_ID.equals(element.getName()) == false)
{
throw new ConfigException("ServerElementReader can only parse config elements of type '" + ServerConfigElement.CONFIG_ELEMENT_ID + "'");
}
Element schemeElem = element.element(ELEMENT_SCHEME);
if (schemeElem != null)
{
configElement.setScheme(schemeElem.getTextTrim());
}
Element hostnameElem = element.element(ELEMENT_HOSTNAME);
if (hostnameElem != null)
{
configElement.setHostName(hostnameElem.getTextTrim());
}
Element portElem = element.element(ELEMENT_PORT);
if (portElem != null)
{
try
{
Integer port = new Integer(portElem.getTextTrim());
configElement.setPort(port);
}
catch(NumberFormatException e)
{
throw new ConfigException("Server port is not a number", e);
}
}
}
return configElement;
}
}

View File

@@ -0,0 +1,721 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.Writer;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.template.AbsoluteUrlMethod;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateService;
import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.alfresco.web.scripts.facebook.FacebookModel;
import org.alfresco.web.scripts.facebook.FacebookServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Skeleton implementation of a Web Script
*
* @author davidc
*/
public abstract class AbstractWebScript implements WebScript
{
// Logger
private static final Log logger = LogFactory.getLog(AbstractWebScript.class);
// dependencies
private WebScriptContext scriptContext;
private WebScriptRegistry scriptRegistry;
private WebScriptDescription description;
private ServiceRegistry serviceRegistry;
private DescriptorService descriptorService;
// Status Template cache
private Map<String, StatusTemplate> statusTemplates = new HashMap<String, StatusTemplate>();
private ReentrantReadWriteLock statusTemplateLock = new ReentrantReadWriteLock();
//
// Initialisation
//
/**
* @param scriptContext
*/
final public void setScriptContext(WebScriptContext scriptContext)
{
this.scriptContext = scriptContext;
}
/**
* @param serviceRegistry
*/
final public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* @param descriptorService
*/
final public void setDescriptorService(DescriptorService descriptorService)
{
this.descriptorService = descriptorService;
}
/**
* Sets the Service Description
*
* @param description
*/
final public void setDescription(WebScriptDescription description)
{
this.description = description;
}
/**
* Initialise Web Script
*
* @param scriptRegistry
*/
public void init(WebScriptRegistry scriptRegistry)
{
this.scriptRegistry = scriptRegistry;
this.statusTemplateLock.writeLock().lock();
try
{
this.statusTemplates.clear();
}
finally
{
this.statusTemplateLock.writeLock().unlock();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#getDescription()
*/
final public WebScriptDescription getDescription()
{
return this.description;
}
//
// Service Implementation Helpers
//
/**
* Gets the Repository Context
*
* @return repository context
*/
final public WebScriptContext getRepositoryContext()
{
return this.scriptContext;
}
/**
* Gets the Web Script Registry
*
* @return Web Script Registry
*/
final public WebScriptRegistry getWebScriptRegistry()
{
return this.scriptRegistry;
}
/**
* Gets the Alfresco Service Registry
*
* @return service registry
*/
final public ServiceRegistry getServiceRegistry()
{
return this.serviceRegistry;
}
/**
* Gets the Alfresco Descriptor
*
* @return descriptor
*/
final public DescriptorService getDescriptorService()
{
return this.descriptorService;
}
//
// Scripting Support
//
/**
* Create a map of arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String> createScriptArgs(WebScriptRequest req)
{
Map<String, String> args = new ScriptableHashMap<String, String>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameter(name));
}
return args;
}
/**
* Create a map of arguments from Web Script Request (for templating)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String> createTemplateArgs(WebScriptRequest req)
{
Map<String, String> args = new HashMap<String, String>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameter(name));
}
return args;
}
/**
* Create a map of (array) arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, Map<String, String>> createScriptArgsM(WebScriptRequest req)
{
Map<String, Map<String, String>> args = new ScriptableHashMap<String, Map<String, String>>();
String[] names = req.getParameterNames();
for (String name : names)
{
ScriptableHashMap<String, String> values = new ScriptableHashMap<String, String>();
int i = 0;
for (String value : req.getParameterValues(name))
{
values.put(new Integer(i++).toString(), value);
}
args.put(name, values);
}
return args;
}
/**
* Create a map of (array) arguments from Web Script Request (for scripting)
*
* @param req Web Script Request
* @return argument map
*/
final protected Map<String, String[]> createTemplateArgsM(WebScriptRequest req)
{
Map<String, String[]> args = new HashMap<String, String[]>();
String[] names = req.getParameterNames();
for (String name : names)
{
args.put(name, req.getParameterValues(name));
}
return args;
}
/**
* Create a model for script usage
*
* @param req web script request
* @param res web script response
* @param customModel custom model entries
*
* @return script model
*/
final protected Map<String, Object> createScriptModel(WebScriptRequest req, WebScriptResponse res, Map<String, Object> customModel)
{
// create script model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
// add repository context (only if authenticated and transaction enabled)
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
getDescription().getRequiredTransaction() != RequiredTransaction.none)
{
NodeRef rootHome = scriptContext.getRootHome();
if (rootHome != null)
{
model.put("roothome", rootHome);
}
NodeRef companyHome = scriptContext.getCompanyHome();
if (companyHome != null)
{
model.put("companyhome", companyHome);
}
NodeRef person = scriptContext.getPerson();
if (person != null)
{
model.put("person", person);
model.put("userhome", scriptContext.getUserHome(person));
}
}
// add web script context
model.put("args", createScriptArgs(req));
model.put("argsM", createScriptArgsM(req));
model.put("guest", req.isGuest());
model.put("url", new URLModel(req));
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
// TODO: Refactor creation of runtime specific parameters with
// Web Script F/W extraction
if (req instanceof WebScriptServletRequest)
{
model.put("formdata", ((WebScriptServletRequest)req).getFormData());
}
if (req instanceof FacebookServletRequest)
{
model.put("facebook", new FacebookModel(((FacebookServletRequest)req)));
}
// add custom model
if (customModel != null)
{
model.putAll(customModel);
}
// return model
return model;
}
/**
* Create a model for template usage
*
* @param req web script request
* @param res web script response
* @param customModel custom model entries
*
* @return template model
*/
final protected Map<String, Object> createTemplateModel(WebScriptRequest req, WebScriptResponse res, Map<String, Object> customModel)
{
// create template model
Map<String, Object> model = new HashMap<String, Object>(8, 1.0f);
// add repository context
if (getDescription().getRequiredAuthentication() != RequiredAuthentication.none &&
getDescription().getRequiredTransaction() != RequiredTransaction.none)
{
NodeRef rootHome = scriptContext.getRootHome();
if (rootHome != null)
{
model.put("roothome", rootHome);
}
NodeRef companyHome = scriptContext.getCompanyHome();
if (companyHome != null)
{
model.put("companyhome", companyHome);
}
NodeRef person = scriptContext.getPerson();
if (person != null)
{
model.put("person", person);
model.put("userhome", scriptContext.getUserHome(person));
}
}
// add web script context
model.put("args", createTemplateArgs(req));
model.put("argsM", createTemplateArgsM(req));
model.put("guest", req.isGuest());
model.put("url", new URLModel(req));
model.put("webscript", getDescription());
model.put("server", new ServerModel(descriptorService.getServerDescriptor()));
// TODO: Refactor creation of runtime specific parameters with
// Web Script F/W extraction
if (req instanceof FacebookServletRequest)
{
model.put("facebook", new FacebookModel(((FacebookServletRequest)req)));
}
// add template support
model.put("absurl", new AbsoluteUrlMethod(req.getServerPath()));
model.put("scripturl", new ScriptUrlMethod(req, res));
model.put("clienturlfunction", new ClientUrlFunctionMethod(res));
model.put("date", new Date());
model.put(TemplateService.KEY_IMAGE_RESOLVER, getWebScriptRegistry().getTemplateImageResolver());
// add custom model
if (customModel != null)
{
model.putAll(customModel);
}
return model;
}
/**
* Render a template (identified by path)
*
* @param templatePath template path
* @param model model
* @param writer output writer
*/
final protected void renderTemplate(String templatePath, Map<String, Object> model, Writer writer)
{
long start = System.currentTimeMillis();
getWebScriptRegistry().getTemplateProcessor().process(templatePath, model, writer);
if (logger.isDebugEnabled())
logger.debug("Rendered template " + templatePath + " in " + (System.currentTimeMillis() - start) + "ms");
}
/**
* 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)
{
getWebScriptRegistry().getTemplateProcessor().processString(template, model, writer);
}
/**
* Render an explicit response status template
*
* @param req web script request
* @param res web script response
* @param status web script status
* @param format format
* @param model model
* @throws IOException
*/
final protected void sendStatus(WebScriptRequest req, WebScriptResponse res, WebScriptStatus status, WebScriptCache cache, String format, Map<String, Object> model)
throws IOException
{
// locate status template
// NOTE: search order...
// NOTE: package path is recursed to root package
// 1) script located <scriptid>.<format>.<status>.ftl
// 2) script located <scriptid>.<format>.status.ftl
// 3) package located <scriptpath>/<format>.<status>.ftl
// 4) package located <scriptpath>/<format>.status.ftl
// 5) default <status>.ftl
// 6) default status.ftl
int statusCode = status.getCode();
String statusFormat = (format == null) ? "" : format;
String scriptId = getDescription().getId();
StatusTemplate template = getStatusTemplate(scriptId, statusCode, statusFormat);
// render output
String mimetype = getWebScriptRegistry().getFormatRegistry().getMimeType(req.getAgent(), template.format);
if (mimetype == null)
{
throw new WebScriptException("Web Script format '" + template.format + "' is not registered");
}
if (logger.isDebugEnabled())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Sending status " + statusCode + " (Template: " + template.path + ")");
logger.debug("Rendering response: content type=" + mimetype);
}
res.reset();
res.setCache(cache);
res.setStatus(req.forceSuccessStatus() ? HttpServletResponse.SC_OK : statusCode);
res.setContentType(mimetype + ";charset=UTF-8");
renderTemplate(template.path, model, res.getWriter());
}
/**
* Find status template
*
* Note: This method caches template search results
*
* @param scriptId
* @param statusCode
* @param format
* @return status template (or null if not found)
*/
private StatusTemplate getStatusTemplate(String scriptId, int statusCode, String format)
{
StatusTemplate statusTemplate = null;
statusTemplateLock.readLock().lock();
try
{
String key = statusCode + "." + format;
statusTemplate = statusTemplates.get(key);
if (statusTemplate == null)
{
// Upgrade read lock to write lock
statusTemplateLock.readLock().unlock();
statusTemplateLock.writeLock().lock();
try
{
// Check again
statusTemplate = statusTemplates.get(key);
if (statusTemplate == null)
{
// Locate template in web script store
statusTemplate = getScriptStatusTemplate(scriptId, statusCode, format);
if (statusTemplate == null)
{
WebScriptPath path = getWebScriptRegistry().getPackage(Path.concatPath("/", getDescription().getScriptPath()));
statusTemplate = getPackageStatusTemplate(path, statusCode, format);
if (statusTemplate == null)
{
statusTemplate = getDefaultStatusTemplate(statusCode);
}
}
if (logger.isDebugEnabled())
logger.debug("Caching template " + statusTemplate.path + " for web script " + scriptId + " and status " + statusCode + " (format: " + format + ")");
statusTemplates.put(key, statusTemplate);
}
}
finally
{
// Downgrade lock to read
statusTemplateLock.readLock().lock();
statusTemplateLock.writeLock().unlock();
}
}
return statusTemplate;
}
finally
{
statusTemplateLock.readLock().unlock();
}
}
/**
* Find a script specific status template
*
* @param scriptId
* @param statusCode
* @param format
* @return status template (or null, if not found)
*/
private StatusTemplate getScriptStatusTemplate(String scriptId, int statusCode, String format)
{
String path = scriptId + "." + format + "." + statusCode + ".ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
path = scriptId + "." + format + ".status.ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
return null;
}
/**
* Find a package specific status template
*
* @param scriptPath
* @param statusCode
* @param format
* @return status template (or null, if not found)
*/
private StatusTemplate getPackageStatusTemplate(WebScriptPath scriptPath, int statusCode, String format)
{
while(scriptPath != null)
{
String path = Path.concatPath(scriptPath.getPath(), format + "." + statusCode + ".ftl");
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
path = Path.concatPath(scriptPath.getPath(), format + ".status.ftl");
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, format);
}
scriptPath = scriptPath.getParent();
}
return null;
}
/**
* Find default status template
*
* @param statusCode
* @return status template
*/
private StatusTemplate getDefaultStatusTemplate(int statusCode)
{
String path = statusCode + ".ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, WebScriptResponse.HTML_FORMAT);
}
path = "status.ftl";
if (getWebScriptRegistry().getTemplateProcessor().hasTemplate(path))
{
return new StatusTemplate(path, WebScriptResponse.HTML_FORMAT);
}
throw new WebScriptException("Default status template /status.ftl could not be found");
}
/**
* Execute a script
*
* @param location script location
* @param model model
*/
final protected void executeScript(ScriptLocation location, Map<String, Object> model)
{
long start = System.currentTimeMillis();
getWebScriptRegistry().getScriptProcessor().executeScript(location, model);
if (logger.isDebugEnabled())
logger.debug("Executed script " + location.toString() + " in " + (System.currentTimeMillis() - start) + "ms");
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path or qname
* @return reference array of reference segments (as described above for each reference type)
*/
protected NodeRef findNodeRef(String referenceType, String[] reference)
{
NodeRef nodeRef = null;
// construct store reference
if (reference.length < 3)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
}
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
NodeService nodeService = serviceRegistry.getNodeService();
if (nodeService.exists(storeRef))
{
if (referenceType.equals("node"))
{
NodeRef urlRef = new NodeRef(storeRef, reference[2]);
if (nodeService.exists(urlRef))
{
nodeRef = urlRef;
}
}
else if (referenceType.equals("path"))
{
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
// NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
NodeRef rootNodeRef = getRepositoryContext().getCompanyHome();
if (reference.length == 3)
{
nodeRef = rootNodeRef;
}
else
{
String[] path = new String[reference.length - /*2*/3];
System.arraycopy(reference, /*2*/3, path, 0, path.length);
try
{
FileFolderService ffService = serviceRegistry.getFileFolderService();
FileInfo fileInfo = ffService.resolveNamePath(rootNodeRef, Arrays.asList(path));
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
else
{
// TODO: Implement 'qname' style
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
}
}
return nodeRef;
}
/**
* Status Template
*/
private class StatusTemplate
{
/**
* Construct
*
* @param path
* @param format
*/
private StatusTemplate(String path, String format)
{
this.path = path;
this.format = format;
}
private String path;
private String format;
}
}

View File

@@ -0,0 +1,174 @@
/*
* 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.scripts;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.util.Base64;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Basic Authentication Interceptor
*
* @author davidc
*/
public class BasicHttpAuthenticator implements WebScriptServletAuthenticator
{
// Logger
private static final Log logger = LogFactory.getLog(BasicHttpAuthenticator.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 boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest preq, WebScriptServletResponse pres)
{
boolean authorized = false;
//
// validate credentials
//
HttpServletRequest req = preq.getHttpServletRequest();
HttpServletResponse res = pres.getHttpServletResponse();
String authorization = req.getHeader("Authorization");
String ticket = req.getParameter("alf_ticket");
if (logger.isDebugEnabled())
{
logger.debug("HTTP Authorization provided: " + (authorization != null && authorization.length() > 0));
logger.debug("URL ticket provided: " + (ticket != null && ticket.length() > 0));
}
// authenticate as guest, if service allows
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
authenticationService.authenticateAsGuest();
authorized = true;
}
// authenticate as specified by explicit ticket on url
else if (ticket != null && ticket.length() > 0)
{
try
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (URL argument) ticket " + ticket);
// assume a ticket has been passed
authenticationService.validate(ticket);
authorized = true;
}
catch(AuthenticationException e)
{
// failed authentication
}
}
// authenticate as specified by HTTP Basic Authentication
else if (authorization != null && authorization.length() > 0)
{
try
{
String[] authorizationParts = authorization.split(" ");
if (!authorizationParts[0].equalsIgnoreCase("basic"))
{
throw new WebScriptException("Authorization '" + authorizationParts[0] + "' not supported.");
}
String decodedAuthorisation = new String(Base64.decode(authorizationParts[1]));
String[] parts = decodedAuthorisation.split(":");
if (parts.length == 1)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) ticket " + parts[0]);
// assume a ticket has been passed
authenticationService.validate(parts[0]);
authorized = true;
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating (BASIC HTTP) user " + parts[0]);
// assume username and password passed
if (parts[0].equals(AuthenticationUtil.getGuestUserName()))
{
if (required == RequiredAuthentication.guest)
{
authenticationService.authenticateAsGuest();
authorized = true;
}
}
else
{
authenticationService.authenticate(parts[0], parts[1].toCharArray());
authorized = true;
}
}
}
catch(AuthenticationException e)
{
// failed authentication
}
}
//
// request credentials if not authorized
//
if (!authorized)
{
if (logger.isDebugEnabled())
logger.debug("Requesting authorization credentials");
res.setStatus(401);
res.setHeader("WWW-Authenticate", "Basic realm=\"Alfresco\"");
}
return authorized;
}
}

View File

@@ -0,0 +1,344 @@
/*
* 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.scripts;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import freemarker.cache.FileTemplateLoader;
import freemarker.cache.TemplateLoader;
/**
* ClassPath based Web Script Store
*
* @author davidc
*/
public class ClassPathStore implements WebScriptStore, InitializingBean
{
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
protected boolean mustExist = false;
protected String classPath;
protected File fileDir;
/**
* Sets whether the class path must exist
*
* If it must exist, but it doesn't exist, an exception is thrown
* on initialisation of the store
*
* @param mustExist
*/
public void setMustExist(boolean mustExist)
{
this.mustExist = mustExist;
}
/**
* Sets the class path
*
* @param classPath classpath
*/
public void setClassPath(String classPath)
{
this.classPath = classPath;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet()
throws Exception
{
ClassPathResource resource = new ClassPathResource(classPath);
if (resource.exists())
{
fileDir = resource.getFile();
}
else if (mustExist)
{
throw new WebScriptException("Web Script Store classpath:" + classPath + " must exist; it was not found");
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#exists()
*/
public boolean exists()
{
return (fileDir != null);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getBasePath()
*/
public String getBasePath()
{
return "classpath:" + classPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocumentPaths()
*/
public String[] getDescriptionDocumentPaths()
{
String[] paths;
try
{
int filePathLength = fileDir.getAbsolutePath().length() +1;
List<String> documentPaths = new ArrayList<String>();
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/**/*.desc.xml");
for (Resource resource : resources)
{
if (resource instanceof FileSystemResource)
{
String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength);
documentPath = documentPath.replace('\\', '/');
documentPaths.add(documentPath);
}
}
paths = documentPaths.toArray(new String[documentPaths.size()]);
}
catch(IOException e)
{
// Note: Ignore: no service description documents found
paths = new String[0];
}
return paths;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getScriptDocumentPaths(org.alfresco.web.scripts.WebScript)
*/
public String[] getScriptDocumentPaths(WebScript script)
{
String[] paths;
try
{
int filePathLength = fileDir.getAbsolutePath().length() +1;
List<String> documentPaths = new ArrayList<String>();
String scriptPaths = script.getDescription().getId() + ".*";
Resource[] resources = resolver.getResources("classpath*:" + classPath + "/" + scriptPaths);
for (Resource resource : resources)
{
if (resource instanceof FileSystemResource)
{
String documentPath = resource.getFile().getAbsolutePath().substring(filePathLength);
documentPath = documentPath.replace('\\', '/');
documentPaths.add(documentPath);
}
}
paths = documentPaths.toArray(new String[documentPaths.size()]);
}
catch(IOException e)
{
// Note: Ignore: no service description documents found
paths = new String[0];
}
return paths;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#hasDocument(java.lang.String)
*/
public boolean hasDocument(String documentPath)
{
File document = new File(fileDir, documentPath);
return document.exists();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getDescriptionDocument(java.lang.String)
*/
public InputStream getDocument(String documentPath)
throws IOException
{
File document = new File(fileDir, documentPath);
if (!document.exists())
{
throw new IOException("Document " + documentPath + " does not exist within store " + getBasePath());
}
return new FileInputStream(document);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#createDocument(java.lang.String, java.lang.String)
*/
public void createDocument(String documentPath, String content) throws IOException
{
File document = new File(fileDir, documentPath);
// create directory
File path = document.getParentFile();
path.mkdirs();
// create file
if (!document.createNewFile())
{
throw new IOException("Document " + documentPath + " already exists");
}
OutputStream output = new FileOutputStream(document);
try
{
PrintWriter writer = new PrintWriter(output);
writer.write(content);
writer.flush();
}
finally
{
output.flush();
output.close();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getTemplateLoader()
*/
public TemplateLoader getTemplateLoader()
{
FileTemplateLoader loader = null;
try
{
loader = new FileTemplateLoader(fileDir);
}
catch (IOException e)
{
// Note: Can't establish loader, so return null
}
return loader;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptStore#getScriptLoader()
*/
public ScriptLoader getScriptLoader()
{
return new ClassPathScriptLoader();
}
/**
* Class path based script loader
*
* @author davidc
*/
private class ClassPathScriptLoader implements ScriptLoader
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptLocation getScriptLocation(String path)
{
ScriptLocation location = null;
File scriptPath = new File(fileDir, path);
if (scriptPath.exists())
{
location = new ClassPathScriptLocation(scriptPath);
}
return location;
}
}
/**
* Class path script location
*
* @author davidc
*/
private static class ClassPathScriptLocation implements ScriptLocation
{
private File location;
/**
* Construct
*
* @param location
*/
public ClassPathScriptLocation(File location)
{
this.location = location;
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
*/
public InputStream getInputStream()
{
try
{
return new FileInputStream(location);
}
catch (FileNotFoundException e)
{
throw new WebScriptException("Unable to retrieve input stream for script " + location.getAbsolutePath());
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
*/
public Reader getReader()
{
try
{
return new InputStreamReader(getInputStream(), "UTF-8");
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unsupported Encoding", e);
}
}
@Override
public String toString()
{
return location.getAbsolutePath();
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* 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.scripts;
import java.util.List;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;
/**
* @author David Caruana
*
* Custom FreeMarker Template language method.
* <p>
* Render a client side javascript function to build urls to this service.
*
* <p>
* Usage: clientUrlFunction(String funcName)
*/
public final class ClientUrlFunctionMethod implements TemplateMethodModelEx
{
WebScriptResponse res;
/**
* Construct
*/
public ClientUrlFunctionMethod(WebScriptResponse res)
{
this.res = res;
}
/**
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
*/
public Object exec(List args) throws TemplateModelException
{
String result = "";
if (args.size() != 0)
{
Object arg0 = args.get(0);
if (arg0 instanceof TemplateScalarModel)
{
String arg = ((TemplateScalarModel)arg0).getAsString();
result = res.getEncodeScriptUrlFunction(arg);
}
}
return result;
}
}

View File

@@ -0,0 +1,267 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.jscript.ScriptableHashMap;
import org.alfresco.repo.jscript.ValueConverter;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Script/template driven based implementation of an Web Script
*
* @author davidc
*/
public class DeclarativeWebScript extends AbstractWebScript
{
// Logger
private static final Log logger = LogFactory.getLog(DeclarativeWebScript.class);
// Script Context
private String basePath;
private ScriptLocation executeScript;
// Javascript Converter
private ValueConverter valueConverter = new ValueConverter();
/* (non-Javadoc)
* @see org.alfresco.web.scripts.AbstractWebScript#init(org.alfresco.web.scripts.WebScriptRegistry)
*/
@Override
public void init(WebScriptRegistry apiRegistry)
{
super.init(apiRegistry);
basePath = getDescription().getId();
// Test for "execute" script
String scriptPath = basePath + ".js";
executeScript = getWebScriptRegistry().getScriptProcessor().findScript(scriptPath);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
final public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
// retrieve requested format
String format = req.getFormat();
if (format == null || format.length() == 0)
{
format = getDescription().getDefaultFormat();
}
try
{
// establish mimetype from format
String mimetype = getWebScriptRegistry().getFormatRegistry().getMimeType(req.getAgent(), format);
if (mimetype == null)
{
throw new WebScriptException("Web Script format '" + format + "' is not registered");
}
// construct model for script / template
WebScriptStatus status = new WebScriptStatus();
WebScriptCache cache = new WebScriptCache(getDescription().getRequiredCache());
Map<String, Object> model = executeImpl(req, status, cache);
if (model == null)
{
model = new HashMap<String, Object>(7, 1.0f);
}
model.put("status", status);
model.put("cache", cache);
// extract any request attributes and add them to the model - this is useful for requests
// that wish to pass further arbituary data into a webscript model
for (String name : req.getAttributeNames())
{
model.put(name, req.getAttribute(name));
}
// execute script if it exists
if (executeScript != null)
{
if (logger.isDebugEnabled())
logger.debug("Executing script " + executeScript);
Map<String, Object> scriptModel = createScriptModel(req, res, model);
// add return model allowing script to add items to template model
Map<String, Object> returnModel = new ScriptableHashMap<String, Object>();
scriptModel.put("model", returnModel);
executeScript(executeScript, scriptModel);
mergeScriptModelIntoTemplateModel(returnModel, model);
}
// create model for template rendering
Map<String, Object> templateModel = createTemplateModel(req, res, model);
// is a redirect to a status specific template required?
if (status.getRedirect())
{
sendStatus(req, res, status, cache, format, templateModel);
}
else
{
// render output
int statusCode = status.getCode();
if (statusCode != HttpServletResponse.SC_OK && !req.forceSuccessStatus())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Setting status " + statusCode);
res.setStatus(statusCode);
}
// apply cache
res.setCache(cache);
String callback = req.getJSONCallback();
if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null)
{
if (logger.isDebugEnabled())
logger.debug("Rendering JSON callback response: content type=" + MimetypeMap.MIMETYPE_TEXT_JAVASCRIPT + ", status=" + statusCode + ", callback=" + callback);
// NOTE: special case for wrapping JSON results in a javascript function callback
res.setContentType(MimetypeMap.MIMETYPE_TEXT_JAVASCRIPT + ";charset=UTF-8");
res.getOutputStream().write((callback + "(").getBytes());
}
else
{
if (logger.isDebugEnabled())
logger.debug("Rendering response: content type=" + mimetype + ", status=" + statusCode);
res.setContentType(mimetype + ";charset=UTF-8");
}
// render response according to requested format
renderFormatTemplate(format, templateModel, res.getWriter());
if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null)
{
// NOTE: special case for wrapping JSON results in a javascript function callback
res.getOutputStream().write(")".getBytes());
}
}
}
catch(Throwable e)
{
if (logger.isInfoEnabled())
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
// extract status code, if specified
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
if (e instanceof WebScriptException)
{
statusCode = ((WebScriptException)e).getStatus();
}
// send status
WebScriptStatus status = new WebScriptStatus();
status.setCode(statusCode);
status.setMessage(e.getMessage());
status.setException(e);
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(true);
Map<String, Object> customModel = new HashMap<String, Object>();
customModel.put("status", status);
Map<String, Object> templateModel = createTemplateModel(req, res, customModel);
sendStatus(req, res, status, cache, format, templateModel);
}
}
/**
* Merge script generated model into template-ready model
*
* @param scriptModel script model
* @param templateModel template model
*/
@SuppressWarnings("unchecked")
final private void mergeScriptModelIntoTemplateModel(Map<String, Object> scriptModel, Map<String, Object> templateModel)
{
for (Map.Entry<String, Object> entry : scriptModel.entrySet())
{
// retrieve script model value
Object value = entry.getValue();
Object templateValue = (value instanceof Serializable) ? valueConverter.convertValueForRepo((Serializable)value) : value;
templateModel.put(entry.getKey(), templateValue);
}
}
/**
* Execute custom Java logic
*
* @param req Web Script request
* @param status Web Script status
* @return custom service model
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
return null;
}
/**
* Execute custom Java logic
*
* @param req Web Script request
* @param status Web Script status
* @param cache Web Script cache
* @return custom service model
*/
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status, WebScriptCache cache)
{
// NOTE: Redirect to those web scripts implemented before cache support
return executeImpl(req, status);
}
/**
* Render a template (of given format) to the Web Script 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 = basePath + "." + format + ".ftl";
if (logger.isDebugEnabled())
logger.debug("Rendering template '" + templatePath + "'");
renderTemplate(templatePath, model, writer);
}
}

View File

@@ -0,0 +1,788 @@
/*
* 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.scripts;
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.service.cmr.repository.FileTypeImageSize;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.alfresco.web.ui.common.Utils;
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.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.web.context.ServletContextAware;
/**
* Registry of declarative (scripted/template driven) Web Scripts
*
* @author davidc
*/
public class DeclarativeWebScriptRegistry extends AbstractLifecycleBean
implements WebScriptRegistry, ServletContextAware, InitializingBean
{
// Logger
private static final Log logger = LogFactory.getLog(DeclarativeWebScriptRegistry.class);
private ServletContext servletContext;
private String defaultWebScript;
private FormatRegistry formatRegistry;
private WebScriptStorage storage;
private TemplateImageResolver imageResolver;
// map of web scripts by id
// NOTE: The map is sorted by id (ascending order)
private Map<String, WebScript> webscriptsById = new TreeMap<String, WebScript>();
// map of web scripts by url
// NOTE: The map is sorted by url (descending order)
private Map<String, URLIndex> webscriptsByURL = new TreeMap<String, URLIndex>(Collections.reverseOrder());
// map of web script packages by path
private Map<String, Path> packageByPath = new TreeMap<String, Path>();
// map of web script uris by path
private Map<String, Path> uriByPath = new TreeMap<String, Path>();
//
// Initialisation
//
/**
* Sets the available Web Script Stores
*
* @param storage
*/
public void setStorage(WebScriptStorage storage)
{
this.storage = storage;
}
/**
* Sets the default service implementation bean
*
* @param defaultWebScript
*/
public void setDefaultWebScript(String defaultWebScript)
{
this.defaultWebScript = defaultWebScript;
}
/**
* Sets the response format registry
*
* @param formatRegistry
*/
public void setFormatRegistry(FormatRegistry formatRegistry)
{
this.formatRegistry = formatRegistry;
}
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.servletContext = context;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
this.imageResolver = new TemplateImageResolver()
{
public String resolveImagePathForName(String filename, FileTypeImageSize size)
{
return Utils.getFileTypeImage(servletContext, filename, size);
}
};
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#reset()
*/
public void reset()
{
long startTime = System.currentTimeMillis();
try
{
getTemplateProcessor().resetCache();
getScriptProcessor().resetCache();
initWebScripts();
}
finally
{
if (logger.isInfoEnabled())
logger.info("Registered " + webscriptsById.size() + " Web Scripts, " + webscriptsByURL.size() + " URLs (in " + (System.currentTimeMillis() - startTime) + "ms)");
}
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onBootstrap(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onBootstrap(ApplicationEvent event)
{
reset();
}
/* (non-Javadoc)
* @see org.alfresco.util.AbstractLifecycleBean#onShutdown(org.springframework.context.ApplicationEvent)
*/
@Override
protected void onShutdown(ApplicationEvent event)
{
}
/**
* Initialise Web Scripts
*
* Note: Each invocation of this method resets the list of the services
*/
private void initWebScripts()
{
if (logger.isDebugEnabled())
logger.debug("Initialising Web Scripts");
// clear currently registered services
webscriptsById.clear();
webscriptsByURL.clear();
packageByPath.clear();
packageByPath.put("/", new Path("/"));
uriByPath.clear();
uriByPath.put("/", new Path("/"));
// register services
for (WebScriptStore apiStore : storage.getStores())
{
if (logger.isDebugEnabled())
logger.debug("Locating Web Scripts within " + apiStore.getBasePath());
String[] serviceDescPaths = apiStore.getDescriptionDocumentPaths();
for (String serviceDescPath : serviceDescPaths)
{
try
{
// build service description
WebScriptDescription serviceDesc = null;
InputStream serviceDescIS = null;
try
{
serviceDescIS = apiStore.getDocument(serviceDescPath);
serviceDesc = createDescription(apiStore, serviceDescPath, serviceDescIS);
}
catch(IOException e)
{
throw new WebScriptException("Failed to read Web Script description document " + apiStore.getBasePath() + serviceDescPath, e);
}
finally
{
try
{
if (serviceDescIS != null) serviceDescIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
// determine if service description has been registered
String id = serviceDesc.getId();
if (webscriptsById.containsKey(id))
{
// move to next service
if (logger.isDebugEnabled())
{
WebScript existingService = webscriptsById.get(id);
WebScriptDescription existingDesc = existingService.getDescription();
String msg = "Web Script description document " + serviceDesc.getStorePath() + "/" + serviceDesc.getDescPath();
msg += " overridden by " + existingDesc.getStorePath() + "/" + existingDesc.getDescPath();
logger.debug(msg);
}
continue;
}
// construct service implementation
ApplicationContext applicationContext = getApplicationContext();
String beanName = "webscript." + id.replace('/', '.');
String serviceImplName = (applicationContext.containsBean(beanName)) ? beanName : defaultWebScript;
AbstractWebScript serviceImpl = (AbstractWebScript)applicationContext.getBean(serviceImplName);
serviceImpl.setDescription(serviceDesc);
serviceImpl.init(this);
if (logger.isDebugEnabled())
logger.debug("Found Web Script " + id + " (desc: " + serviceDescPath + ", impl: " + serviceImplName + ", auth: " +
serviceDesc.getRequiredAuthentication() + ", trx: " + serviceDesc.getRequiredTransaction() + ", format style: " +
serviceDesc.getFormatStyle() + ", default format: " + serviceDesc.getDefaultFormat() + ")");
// register service and its urls
webscriptsById.put(id, serviceImpl);
for (String uriTemplate : serviceDesc.getURIs())
{
// establish static part of url template
boolean wildcard = false;
boolean extension = true;
int queryArgIdx = uriTemplate.indexOf('?');
if (queryArgIdx != -1)
{
uriTemplate = uriTemplate.substring(0, queryArgIdx);
}
int tokenIdx = uriTemplate.indexOf('{');
if (tokenIdx != -1)
{
uriTemplate = uriTemplate.substring(0, tokenIdx);
wildcard = true;
}
if (serviceDesc.getFormatStyle() != WebScriptDescription.FormatStyle.argument)
{
int extIdx = uriTemplate.lastIndexOf(".");
if (extIdx != -1)
{
uriTemplate = uriTemplate.substring(0, extIdx);
}
extension = false;
}
// index service by static part of url (ensuring no other service has already claimed the url)
String uriIdx = serviceDesc.getMethod().toString() + ":" + uriTemplate;
if (webscriptsByURL.containsKey(uriIdx))
{
URLIndex urlIndex = webscriptsByURL.get(uriIdx);
WebScript existingService = urlIndex.script;
if (!existingService.getDescription().getId().equals(serviceDesc.getId()))
{
String msg = "Web Script document " + serviceDesc.getDescPath() + " is attempting to define the url '" + uriIdx + "' already defined by " + existingService.getDescription().getDescPath();
throw new WebScriptException(msg);
}
}
else
{
URLIndex urlIndex = new URLIndex(uriTemplate, wildcard, extension, serviceImpl);
webscriptsByURL.put(uriIdx, urlIndex);
if (logger.isDebugEnabled())
logger.debug("Registered Web Script URL '" + uriIdx + "'");
}
}
// build path indexes to web script
registerPackage(serviceImpl);
registerURIs(serviceImpl);
}
catch(WebScriptException e)
{
if (logger.isWarnEnabled())
{
Throwable c = e;
String cause = c.getMessage();
while (c.getCause() != null && !c.getCause().equals(c))
{
c = c.getCause();
cause += " ; " + c.getMessage();
}
String msg = "Unable to register script " + apiStore.getBasePath() + "/" + serviceDescPath + " due to error: " + cause;
logger.warn(msg);
}
else
{
throw e;
}
}
}
}
}
/**
* Register a Web Script Package
*
* @param script
*/
private void registerPackage(WebScript script)
{
WebScriptDescription desc = script.getDescription();
Path path = packageByPath.get("/");
String[] parts = desc.getScriptPath().split("/");
for (String part : parts)
{
Path subpath = packageByPath.get(Path.concatPath(path.getPath(), part));
if (subpath == null)
{
subpath = path.createChildPath(part);
packageByPath.put(subpath.getPath(), subpath);
}
path = subpath;
}
path.addScript(script);
}
/**
* Register a Web Script URI
*
* @param script
*/
private void registerURIs(WebScript script)
{
WebScriptDescription desc = script.getDescription();
for (String uri : desc.getURIs())
{
Path path = uriByPath.get("/");
String[] parts = uri.split("/");
for (String part : parts)
{
if (part.indexOf("?") != -1)
{
part = part.substring(0, part.indexOf("?"));
}
Path subpath = uriByPath.get(Path.concatPath(path.getPath(), part));
if (subpath == null)
{
subpath = path.createChildPath(part);
uriByPath.put(subpath.getPath(), subpath);
}
path = subpath;
}
path.addScript(script);
}
}
/**
* Create an Web Script Description
*
* @param store
* @param serviceDescPath
* @param serviceDoc
*
* @return web script service description
*/
private WebScriptDescription createDescription(WebScriptStore store, String serviceDescPath, InputStream serviceDoc)
{
SAXReader reader = new SAXReader();
try
{
// retrieve script path
int iPathIdx = serviceDescPath.lastIndexOf('/');
String scriptPath = serviceDescPath.substring(0, iPathIdx == -1 ? 0 : iPathIdx);
// retrieve script id
String id = serviceDescPath.substring(0, serviceDescPath.lastIndexOf(".desc.xml"));
// retrieve http method
int methodIdx = id.lastIndexOf('.');
if (methodIdx == -1 || (methodIdx == id.length() - 1))
{
throw new WebScriptException("Unable to establish HTTP Method from web script description: naming convention must be <name>.<method>.desc.xml");
}
String method = id.substring(methodIdx + 1).toUpperCase();
// parse description document
Document document = reader.read(serviceDoc);
Element rootElement = document.getRootElement();
if (!rootElement.getName().equals("webscript"))
{
throw new WebScriptException("Expected <webscript> root element - found <" + rootElement.getName() + ">");
}
// retrieve short name
Element shortNameElement = rootElement.element("shortname");
if (shortNameElement == null || shortNameElement.getTextTrim() == null || shortNameElement.getTextTrim().length() == 0)
{
throw new WebScriptException("Expected <shortname> value");
}
String shortName = shortNameElement.getTextTrim();
// retrieve description
String description = null;
Element descriptionElement = rootElement.element("description");
if (descriptionElement != null)
{
description = descriptionElement.getTextTrim();
}
// retrieve urls
List urlElements = rootElement.elements("url");
if (urlElements == null || urlElements.size() == 0)
{
throw new WebScriptException("Expected at least one <url> element");
}
List<String> uris = new ArrayList<String>();
Iterator iterElements = urlElements.iterator();
while(iterElements.hasNext())
{
// retrieve url element
Element urlElement = (Element)iterElements.next();
// retrieve url template
String template = urlElement.getTextTrim();
if (template == null || template.length() == 0)
{
// NOTE: for backwards compatibility only
template = urlElement.attributeValue("template");
if (template == null || template.length() == 0)
{
throw new WebScriptException("Expected <url> element value");
}
}
uris.add(template);
}
// 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 WebScriptException("Expected <authentication> value");
}
reqAuth = RequiredAuthentication.valueOf(reqAuthStr);
if (reqAuth == null)
{
throw new WebScriptException("Authentication '" + reqAuthStr + "' is not a valid value");
}
}
// retrieve transaction
RequiredTransaction reqTrx = (reqAuth == RequiredAuthentication.none) ? RequiredTransaction.none : RequiredTransaction.required;
Element trxElement = rootElement.element("transaction");
if (trxElement != null)
{
String reqTrxStr = trxElement.getTextTrim();
if (reqTrxStr == null || reqTrxStr.length() == 0)
{
throw new WebScriptException("Expected <transaction> value");
}
reqTrx = RequiredTransaction.valueOf(reqTrxStr);
if (reqTrx == null)
{
throw new WebScriptException("Transaction '" + reqTrxStr + "' is not a valid value");
}
}
// retrieve format
String defaultFormat = "html";
FormatStyle formatStyle = FormatStyle.any;
Element formatElement = rootElement.element("format");
if (formatElement != null)
{
// establish if default is set explicitly
String attrDefaultValue = formatElement.attributeValue("default");
if (attrDefaultValue != null)
{
defaultFormat = (attrDefaultValue.length() == 0) ? null : attrDefaultValue;
}
// establish format declaration style
String formatStyleStr = formatElement.getTextTrim();
if (formatStyleStr != null && formatStyleStr.length() > 0)
{
formatStyle = FormatStyle.valueOf(formatStyleStr);
if (formatStyle == null)
{
throw new WebScriptException("Format Style '" + formatStyle + "' is not a valid value");
}
}
}
// retrieve caching
WebScriptCache cache = new WebScriptCache();
Element cacheElement = rootElement.element("cache");
if (cacheElement != null)
{
Element neverElement = cacheElement.element("never");
if (neverElement != null)
{
String neverStr = neverElement.getTextTrim();
boolean neverBool = (neverStr == null || neverStr.length() == 0) ? true : Boolean.valueOf(neverStr);
cache.setNeverCache(neverBool);
}
Element publicElement = cacheElement.element("public");
if (publicElement != null)
{
String publicStr = publicElement.getTextTrim();
boolean publicBool = (publicStr == null || publicStr.length() == 0) ? true : Boolean.valueOf(publicStr);
cache.setIsPublic(publicBool);
}
Element revalidateElement = cacheElement.element("mustrevalidate");
if (revalidateElement != null)
{
String revalidateStr = revalidateElement.getTextTrim();
boolean revalidateBool = (revalidateStr == null || revalidateStr.length() == 0) ? true : Boolean.valueOf(revalidateStr);
cache.setMustRevalidate(revalidateBool);
}
}
// construct service description
WebScriptDescriptionImpl serviceDesc = new WebScriptDescriptionImpl();
serviceDesc.setStore(store);
serviceDesc.setScriptPath(scriptPath);
serviceDesc.setDescPath(serviceDescPath);
serviceDesc.setId(id);
serviceDesc.setShortName(shortName);
serviceDesc.setDescription(description);
serviceDesc.setRequiredAuthentication(reqAuth);
serviceDesc.setRequiredTransaction(reqTrx);
serviceDesc.setRequiredCache(cache);
serviceDesc.setMethod(method);
serviceDesc.setUris(uris.toArray(new String[uris.size()]));
serviceDesc.setDefaultFormat(defaultFormat);
serviceDesc.setFormatStyle(formatStyle);
return serviceDesc;
}
catch(DocumentException e)
{
throw new WebScriptException("Failed to parse web script description document " + serviceDescPath, e);
}
catch(WebScriptException e)
{
throw new WebScriptException("Failed to parse web script description document " + serviceDescPath, e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getPackage(java.lang.String)
*/
public WebScriptPath getPackage(String scriptPackage)
{
return packageByPath.get(scriptPackage);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getUri(java.lang.String)
*/
public WebScriptPath getUri(String scriptUri)
{
return uriByPath.get(scriptUri);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getWebScripts()
*/
public Collection<WebScript> getWebScripts()
{
return webscriptsById.values();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getWebScript(java.lang.String)
*/
public WebScript getWebScript(String id)
{
return webscriptsById.get(id);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#findWebScript(java.lang.String, java.lang.String)
*/
public WebScriptMatch findWebScript(String method, String uri)
{
long startTime = System.currentTimeMillis();
// TODO: Replace with more efficient approach
String matchedPath = null;
DeclarativeWebScriptMatch apiServiceMatch = null;
String match = method.toString().toUpperCase() + ":" + uri;
String matchNoExt = method.toString().toUpperCase() + ":" + ((uri.indexOf('.') != -1) ? uri.substring(0, uri.indexOf('.')) : uri);
// locate full match - on URI and METHOD
for (Map.Entry<String, URLIndex> entry : webscriptsByURL.entrySet())
{
URLIndex urlIndex = entry.getValue();
String index = entry.getKey();
String test = urlIndex.includeExtension ? match : matchNoExt;
if ((urlIndex.wildcardPath && test.startsWith(index)) || (!urlIndex.wildcardPath && test.equals(index)))
{
apiServiceMatch = new DeclarativeWebScriptMatch(urlIndex.path, urlIndex.script);
break;
}
else if ((urlIndex.wildcardPath && uri.startsWith(urlIndex.path)) || (!urlIndex.wildcardPath && uri.equals(urlIndex.path)))
{
matchedPath = urlIndex.path;
}
}
// locate URI match
if (apiServiceMatch == null && matchedPath != null)
{
apiServiceMatch = new DeclarativeWebScriptMatch(matchedPath);
}
if (logger.isDebugEnabled())
logger.debug("Web Script index lookup for uri " + uri + " took " + (System.currentTimeMillis() - startTime) + "ms");
return apiServiceMatch;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getContext()
*/
public ServletContext getContext()
{
return servletContext;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getFormatRegistry()
*/
public FormatRegistry getFormatRegistry()
{
return this.formatRegistry;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getTemplateProcessor()
*/
public TemplateProcessor getTemplateProcessor()
{
return this.storage.getTemplateProcessor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getTemplateImageResolver()
*/
public TemplateImageResolver getTemplateImageResolver()
{
return this.imageResolver;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRegistry#getScriptProcessor()
*/
public ScriptProcessor getScriptProcessor()
{
return this.storage.getScriptProcessor();
}
/**
* Web Script Match
*
* @author davidc
*/
public static class DeclarativeWebScriptMatch implements WebScriptMatch
{
private String path;
private WebScript service;
private Kind kind;
/**
* Construct
*
* @param path
* @param service
*/
public DeclarativeWebScriptMatch(String path, WebScript service)
{
this.kind = Kind.FULL;
this.path = path;
this.service = service;
}
/**
* Construct
*
* @param path
* @param service
*/
public DeclarativeWebScriptMatch(String path)
{
this.kind = Kind.URI;
this.path = path;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getKind()
*/
public Kind getKind()
{
return this.kind;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getPath()
*/
public String getPath()
{
return path;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptMatch#getWebScript()
*/
public WebScript getWebScript()
{
return service;
}
@Override
public String toString()
{
return path;
}
}
/**
* Web Script URL Index Entry
*/
private static class URLIndex
{
private URLIndex(String path, boolean wildcardPath, boolean includeExtension, WebScript script)
{
this.path = path;
this.wildcardPath = wildcardPath;
this.includeExtension = includeExtension;
this.script = script;
}
private String path;
private boolean wildcardPath;
private boolean includeExtension;
private WebScript script;
}
}

View File

@@ -0,0 +1,333 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.jscript.Scopeable;
import org.alfresco.repo.jscript.ScriptNode;
import org.alfresco.repo.jscript.ScriptNode.ScriptContent;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FilenameUtils;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable;
/**
* Form Data
*
* @author davidc
*/
public class FormData implements Serializable, Scopeable
{
private static final long serialVersionUID = 1832644544828452385L;
private Scriptable scope;
private HttpServletRequest req;
private ServletFileUpload upload;
private Map<String, FormField> fields = null;
private Map<String, String> parameters = null;
private Map<String, ScriptContent> files = null;
private String encoding = null;
/**
* Construct
*
* @param req
*/
public FormData(HttpServletRequest req)
{
this.req = req;
}
/* (non-Javadoc)
* @see org.alfresco.repo.jscript.Scopeable#setScope(org.mozilla.javascript.Scriptable)
*/
public void setScope(Scriptable scope)
{
this.scope = scope;
}
/**
* Determine if multi-part form data has been provided
*
* @return true => multi-part
*/
public boolean getIsMultiPart()
{
return upload.isMultipartContent(req);
}
/**
* Determine if form data has specified field
*
* @param name field to look for
* @return true => form data contains field
*/
public boolean hasField(String name)
{
Map<String, FormField> fields = getFieldsMap();
return fields.containsKey(name);
}
/**
* Gets the Form fields
*
* @return array of FormField
*/
public Scriptable getFields()
{
Map<String, FormField> fieldsMap = getFieldsMap();
Object[] fields = new Object[fieldsMap.values().size()];
fieldsMap.values().toArray(fields);
return Context.getCurrentContext().newArray(this.scope, fields);
}
/**
* Gets parameters encoded in the form data
*
* @return map (name, value) of parameters
*/
/*package*/ Map<String, String> getParameters()
{
return getParametersMap();
}
/**
* Gets files encoded in form data
*
* @return map (name, ScriptContent) of files
*/
/*package*/ Map<String, ScriptContent> getFiles()
{
return getFilesMap();
}
/**
* Helper to parse servlet request form data
*
* @return map of all form fields
*/
private Map<String, FormField> getFieldsMap()
{
// NOTE: This class is not thread safe - it is expected to be constructed on each thread.
if (fields == null)
{
FileItemFactory factory = new DiskFileItemFactory();
upload = new ServletFileUpload(factory);
encoding = req.getCharacterEncoding();
upload.setHeaderEncoding(encoding);
try
{
List<FileItem> fileItems = upload.parseRequest(req);
fields = new HashMap<String, FormField>();
for (FileItem fileItem : fileItems)
{
FormField formField = new FormField(fileItem);
fields.put(fileItem.getFieldName(), formField);
}
}
catch(FileUploadException e)
{
// NOTE: assume no files can be located
fields = Collections.emptyMap();
}
}
return fields;
}
/**
* Helper to parse servlet request form data
*
* @return map of all form parameters
*/
private Map<String, String> getParametersMap()
{
if (parameters == null)
{
Map<String, FormField> fields = getFieldsMap();
parameters = new HashMap<String, String>();
for (Map.Entry<String, FormField> entry : fields.entrySet())
{
FormField field = entry.getValue();
if (!field.getIsFile())
{
parameters.put(entry.getKey(), field.getValue());
}
}
}
return parameters;
}
/**
* Helper to parse servlet request form data
*
* @return map of all form files
*/
private Map<String, ScriptContent> getFilesMap()
{
if (files == null)
{
Map<String, FormField> fields = getFieldsMap();
files = new HashMap<String, ScriptContent>();
for (Map.Entry<String, FormField> entry : fields.entrySet())
{
FormField field = entry.getValue();
if (field.getIsFile())
{
files.put(entry.getKey(), field.getContent());
}
}
}
return files;
}
/**
* Form Field
*
* @author davidc
*/
public class FormField implements Serializable
{
private FileItem file;
/**
* Construct
*
* @param file
*/
public FormField(FileItem file)
{
this.file = file;
}
/**
* @return field name
*/
public String getName()
{
return file.getFieldName();
}
public String jsGet_name()
{
return getName();
}
/**
* @return true => field represents a file
*/
public boolean getIsFile()
{
return !file.isFormField();
}
public boolean jsGet_isFile()
{
return getIsFile();
}
/**
* @return field value (for file, attempts conversion to string)
*/
public String getValue()
{
try
{
return (file.isFormField() && encoding != null) ? file.getString(encoding) : file.getString();
}
catch (UnsupportedEncodingException e)
{
throw new AlfrescoRuntimeException("Unable to decode form field", e);
}
}
public String jsGet_value()
{
return getValue();
}
/**
* @return field as content
*/
public ScriptContent getContent()
{
try
{
return new ScriptNode.ScriptContentStream(file.getInputStream(), getMimetype(), null);
}
catch(IOException e)
{
return null;
}
}
public ScriptContent jsGet_content()
{
return getContent();
}
/**
* @return mimetype
*/
public String getMimetype()
{
return file.getContentType();
}
public String jsGet_mimetype()
{
return getMimetype();
}
/**
* @return filename (only for file fields, otherwise null)
*/
public String getFilename()
{
// workaround a bug in IE where the full path is returned
return FilenameUtils.getName(file.getName());
}
public String jsGet_filename()
{
return getFilename();
}
}
}

View File

@@ -0,0 +1,83 @@
/*
* 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.scripts;
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

@@ -0,0 +1,158 @@
/*
* 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.scripts;
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 Web Script format '" + entry.getKey() + "' (agent: " + agent + ")");
}
}
formatsForAgent.put(entry.getKey(), entry.getValue());
mimetypesForAgent.put(entry.getValue(), entry.getKey());
if (logger.isDebugEnabled())
logger.debug("Registered Web Script 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

@@ -0,0 +1,66 @@
/*
* 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.scripts;
import org.alfresco.service.cmr.repository.ScriptLocation;
/**
* Composite script loader
*
* @author davidc
*/
public class MultiScriptLoader implements ScriptLoader
{
private ScriptLoader[] loaders;
/**
* Construct
*
* @param loaders
*/
public MultiScriptLoader(ScriptLoader[] loaders)
{
this.loaders = loaders;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptLocation getScriptLocation(String path)
{
ScriptLocation location = null;
for (ScriptLoader loader : loaders)
{
location = loader.getScriptLocation(path);
if (location != null)
{
break;
}
}
return location;
}
}

View File

@@ -0,0 +1,149 @@
/*
* 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.scripts;
import java.util.Map;
import java.util.TreeMap;
/**
* Basic implementation of a Web Script Path
*
* Used for package & url trees.
*
* @author davidc
*/
public class Path implements WebScriptPath
{
private String path;
private Path parent = null;
private Map<String, Path> children = new TreeMap<String, Path>();
private Map<String, WebScript> scripts = new TreeMap<String, WebScript>();
/**
* Helper to concatenate paths
*
* @param path1
* @param path2
* @return concatenated path
*/
public static String concatPath(String path1, String path2)
{
return path1.equals("/") ? path1 + path2 : path1 + "/" + path2;
}
/**
* Construct
*
* @param path
*/
public Path(String path)
{
this.path = path;
}
/**
* Create a Child Path
*
* @param path child path name
* @return child path
*/
public Path createChildPath(String path)
{
Path child = new Path(concatPath(this.path, path));
child.parent = this;
children.put(child.path, child);
return child;
}
/**
* Associate Web Script with Path
*
* @param script
*/
public void addScript(WebScript script)
{
scripts.put(script.getDescription().getId(), script);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getChildren()
*/
public WebScriptPath[] getChildren()
{
WebScriptPath[] childrenArray = new WebScriptPath[children.size()];
return children.values().toArray(childrenArray);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getScripts()
*/
public WebScript[] getScripts()
{
WebScript[] scriptsArray = new WebScript[scripts.size()];
return scripts.values().toArray(scriptsArray);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getName()
*/
public String getName()
{
String name = "";
int i = path.lastIndexOf("/");
if (i != -1 && i != (path.length() -1))
{
name = path.substring(i + 1);
}
return name;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getParent()
*/
public WebScriptPath getParent()
{
return parent;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptPath#getPath()
*/
public String getPath()
{
return path;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString()
{
return path;
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts;
package org.alfresco.web.scripts;
import java.io.IOException;
import java.io.InputStream;
@@ -46,17 +46,13 @@ import org.alfresco.service.cmr.repository.ContentService;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.ScriptContent;
import org.alfresco.web.scripts.ScriptLoader;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -71,7 +67,7 @@ import freemarker.cache.TemplateLoader;
*
* @author davidc
*/
public class RepoStore implements Store, ApplicationContextAware, ApplicationListener
public class RepoStore implements WebScriptStore, ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected boolean mustExist = false;
@@ -626,21 +622,21 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ScriptLoader#getScriptLocation(java.lang.String)
*/
public ScriptContent getScript(final String path)
public ScriptLocation getScriptLocation(final String path)
{
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptContent>()
return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<ScriptLocation>()
{
public ScriptContent doWork() throws Exception
public ScriptLocation doWork() throws Exception
{
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<ScriptContent>()
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<ScriptLocation>()
{
public ScriptContent execute() throws Exception
public ScriptLocation execute() throws Exception
{
ScriptContent location = null;
ScriptLocation location = null;
NodeRef nodeRef = findNodeRef(path);
if (nodeRef != null)
{
location = new RepoScriptContent(path, nodeRef);
location = new RepoScriptLocation(path, nodeRef);
}
return location;
}
@@ -655,7 +651,7 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
*
* @author davidc
*/
private class RepoScriptContent implements ScriptContent
private class RepoScriptLocation implements ScriptLocation
{
protected String path;
protected NodeRef nodeRef;
@@ -665,7 +661,7 @@ public class RepoStore implements Store, ApplicationContextAware, ApplicationLis
*
* @param location
*/
public RepoScriptContent(String path, NodeRef nodeRef)
public RepoScriptLocation(String path, NodeRef nodeRef)
{
this.path = path;
this.nodeRef = nodeRef;

View File

@@ -0,0 +1,46 @@
/*
* 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.scripts;
import org.alfresco.service.cmr.repository.ScriptLocation;
/**
* Locate a script
*
* @author davidc
*/
public interface ScriptLoader
{
/**
* Gets the script location for the script at the specified path
*
* @param path path within api store
* @return script location (or null, if script does not exist at path)
*/
ScriptLocation getScriptLocation(String path);
}

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.scripts;
import java.util.Map;
import org.alfresco.service.cmr.repository.ScriptException;
import org.alfresco.service.cmr.repository.ScriptLocation;
import org.alfresco.service.cmr.repository.ScriptService;
/**
* Script Processor for use in Web Script
*
* @author davidc
*/
public class ScriptProcessor
{
// dependencies
private ScriptService scriptService;
// script loader
private ScriptLoader scriptLoader;
/**
* Sets the script service
*
* @param scriptService
*/
public void setScriptService(ScriptService scriptService)
{
this.scriptService = scriptService;
}
/**
* Sets the script loader
*
* @param scriptLoader
*/
public void setScriptLoader(ScriptLoader scriptLoader)
{
this.scriptLoader = scriptLoader;
}
/**
* Find a script at the specified path (within registered Web Script stores)
*
* @param path script path
* @return script location (or null, if not found)
*/
public ScriptLocation findScript(String path)
{
return scriptLoader.getScriptLocation(path);
}
/**
* Execute script
*
* @param path script path
* @param model model
* @return script result
* @throws ScriptException
*/
public Object executeScript(String path, Map<String, Object> model)
throws ScriptException
{
// locate script within web script stores
ScriptLocation scriptLocation = findScript(path);
if (scriptLocation == null)
{
throw new WebScriptException("Unable to locate script " + path);
}
// execute script
return executeScript(scriptLocation, model);
}
/**
* Execute script
*
* @param location script location
* @param model model
* @return script result
*/
public Object executeScript(ScriptLocation location, Map<String, Object> model)
{
return scriptService.executeScript("javascript", location, model);
}
/**
* Reset script cache
*/
public void resetCache()
{
// NOOP
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.scripts;
import java.util.List;
import org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;
/**
* @author David Caruana
*
* Custom FreeMarker Template language method.
* <p>
* Render script url independent of script hosting environment e.g. render inside / outside
* portal.
* <p>
* Usage: scripturl(String url)
*/
public final class ScriptUrlMethod implements TemplateMethodModelEx
{
WebScriptRequest req;
WebScriptResponse res;
/**
* Construct
*
* @param basePath base path used to construct absolute url
*/
public ScriptUrlMethod(WebScriptRequest req, WebScriptResponse res)
{
this.req = req;
this.res = res;
}
/**
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
*/
public Object exec(List args) throws TemplateModelException
{
String result = "";
if (args.size() != 0)
{
Object arg0 = args.get(0);
boolean prefixServiceUrl = true;
if (args.size() == 2 && args.get(1) instanceof TemplateBooleanModel)
{
prefixServiceUrl = ((TemplateBooleanModel)args.get(1)).getAsBoolean();
}
if (arg0 instanceof TemplateScalarModel)
{
String arg = ((TemplateScalarModel)arg0).getAsString();
StringBuffer buf = new StringBuffer(128);
buf.append(prefixServiceUrl ? req.getServicePath() : "");
buf.append(arg);
if (arg.length() != 0)
{
if (arg.indexOf('?') == -1)
{
buf.append('?');
}
else
{
buf.append('&');
}
}
else
{
buf.append('?');
}
buf.append("guest=" + (req.isGuest() ? "true" : ""));
if (req.getFormatStyle() == FormatStyle.argument)
{
buf.append("&format=");
buf.append(req.getFormat());
}
result = res.encodeScriptUrl(buf.toString());
}
}
return result;
}
}

View File

@@ -1,122 +1,169 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.web.scripts.ServerModel;
/**
* Script / Template Model representing Repository Server meta-data
*
* @author davidc
*/
public class RepositoryServerModel implements ServerModel
{
private Descriptor serverDescriptor;
/**
* Construct
*
* @param serverDescriptor
*/
/*package*/ RepositoryServerModel(Descriptor serverDescriptor)
{
this.serverDescriptor = serverDescriptor;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getContainerName()
*/
public String getContainerName()
{
return "Repository";
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionMajor()
*/
public String getVersionMajor()
{
return serverDescriptor.getVersionMajor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionMinor()
*/
public String getVersionMinor()
{
return serverDescriptor.getVersionMinor();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionRevision()
*/
public String getVersionRevision()
{
return serverDescriptor.getVersionRevision();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionLabel()
*/
public String getVersionLabel()
{
return serverDescriptor.getVersionLabel();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersionBuild()
*/
public String getVersionBuild()
{
return serverDescriptor.getVersionBuild();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getVersion()
*/
public String getVersion()
{
return serverDescriptor.getVersion();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getEdition()
*/
public String getEdition()
{
return serverDescriptor.getEdition();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.ServerModel#getSchema()
*/
public int getSchema()
{
return serverDescriptor.getSchema();
}
}
/*
* 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.scripts;
import org.alfresco.service.descriptor.Descriptor;
/**
* Script / Template Model representing Repository Server meta-data
*
* @author davidc
*/
public class ServerModel
{
private Descriptor serverDescriptor;
/**
* Construct
*
* @param serverDescriptor
*/
/*package*/ ServerModel(Descriptor serverDescriptor)
{
this.serverDescriptor = serverDescriptor;
}
/**
* Gets the major version number, e.g. <u>1</u>.2.3
*
* @return major version number
*/
public String getVersionMajor()
{
return serverDescriptor.getVersionMajor();
}
public String jsGet_versionMajor()
{
return getVersionMajor();
}
/**
* Gets the minor version number, e.g. 1.<u>2</u>.3
*
* @return minor version number
*/
public String getVersionMinor()
{
return serverDescriptor.getVersionMinor();
}
public String jsGet_versionMinor()
{
return getVersionMinor();
}
/**
* Gets the version revision number, e.g. 1.2.<u>3</u>
*
* @return revision number
*/
public String getVersionRevision()
{
return serverDescriptor.getVersionRevision();
}
public String jsGet_versionRevision()
{
return getVersionRevision();
}
/**
* Gets the version label
*
* @return the version label
*/
public String getVersionLabel()
{
return serverDescriptor.getVersionLabel();
}
public String jsGet_versionLabel()
{
return getVersionLabel();
}
/**
* Gets the build number
*
* @return the build number i.e. build-1
*/
public String getVersionBuild()
{
return serverDescriptor.getVersionBuild();
}
public String jsGet_versionBuild()
{
return getVersionBuild();
}
/**
* Gets the full version number
*
* @return full version number as major.minor.revision (label)
*/
public String getVersion()
{
return serverDescriptor.getVersion();
}
public String jsGet_version()
{
return getVersion();
}
/**
* Gets the edition
*
* @return the edition
*/
public String getEdition()
{
return serverDescriptor.getEdition();
}
public String jsGet_edition()
{
return getEdition();
}
/**
* Gets the schema number
*
* @return a positive integer
*/
public int getSchema()
{
return serverDescriptor.getSchema();
}
public int jsGet_schema()
{
return getSchema();
}
}

View File

@@ -1,205 +1,218 @@
package org.alfresco.repo.web.scripts;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.repo.template.FreeMarkerProcessor;
import org.alfresco.repo.template.QNameAwareObjectWrapper;
import org.alfresco.service.cmr.repository.ProcessorExtension;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.SearchPath;
import org.alfresco.web.scripts.Store;
import org.alfresco.web.scripts.TemplateProcessor;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import freemarker.cache.MruCacheStorage;
import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
public class RepositoryTemplateProcessor extends FreeMarkerProcessor
implements TemplateProcessor, ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected SearchPath searchPath;
protected String defaultEncoding;
protected Configuration templateConfig;
protected FreeMarkerProcessor freeMarkerProcessor;
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
*/
public void setDefaultEncoding(String defaultEncoding)
{
this.defaultEncoding = defaultEncoding;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding()
*/
public String getDefaultEncoding()
{
return this.defaultEncoding;
}
public void setSearchPath(SearchPath searchPath)
{
this.searchPath = searchPath;
}
/**
* Set the freemarker processor
*
* @param freeMarkerProcessor the free marker processor
*/
public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor)
{
this.freeMarkerProcessor = freeMarkerProcessor;
}
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#getConfig()
*/
@Override
protected Configuration getConfig()
{
return templateConfig;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#reset()
*/
public void reset()
{
if (templateConfig != null)
{
templateConfig.clearTemplateCache();
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.TemplateProcessor#hasTemplate(java.lang.String)
*/
public boolean hasTemplate(String templatePath)
{
boolean hasTemplate = false;
try
{
Template template = templateConfig.getTemplate(templatePath);
hasTemplate = (template != null);
}
catch(FileNotFoundException e)
{
// NOTE: return false as template is not found
}
catch(IOException e)
{
throw new WebScriptException("Failed to retrieve template " + templatePath, e);
}
return hasTemplate;
}
/**
* Initialise FreeMarker Configuration
*/
protected void initConfig()
{
Configuration config = new Configuration();
// setup template cache
config.setCacheStorage(new MruCacheStorage(20, 100));
config.setTemplateUpdateDelay(0);
// setup template loaders
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
for (Store apiStore : searchPath.getStores())
{
TemplateLoader loader = apiStore.getTemplateLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
config.setTemplateLoader(loader);
// use our custom object wrapper that can deal with QNameMap objects directly
config.setObjectWrapper(new QNameAwareObjectWrapper());
// rethrow any exception so we can deal with them
config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
// turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists()
config.setLocalizedLookup(false);
// set template encoding
if (defaultEncoding != null)
{
config.setDefaultEncoding(defaultEncoding);
}
// set output encoding
config.setOutputEncoding("UTF-8");
templateConfig = config;
}
/**
* Tempory fix to initialise this template processor with the freeMarker extensions expected by
* the templates.
*/
private void initProcessorExtensions()
{
for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions())
{
this.registerProcessorExtension(processorExtension);
}
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initConfig();
initProcessorExtensions();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}
/*
* 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.scripts;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.alfresco.repo.template.FreeMarkerProcessor;
import org.alfresco.repo.template.QNameAwareObjectWrapper;
import org.alfresco.service.cmr.repository.ProcessorExtension;
import org.alfresco.util.AbstractLifecycleBean;
import org.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.Template;
import freemarker.template.TemplateExceptionHandler;
/**
* FreeMarker Processor for use in Web Scripts
*
* Adds the ability to:
* - specify template loaders
* - caching of templates
*
* @author davidc
*/
public class TemplateProcessor extends FreeMarkerProcessor implements ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
protected TemplateLoader templateLoader = null;
protected String defaultEncoding;
protected Configuration templateConfig;
protected FreeMarkerProcessor freeMarkerProcessor;
/* (non-Javadoc)
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
*/
public void setDefaultEncoding(String defaultEncoding)
{
this.defaultEncoding = defaultEncoding;
}
/* (non-Javadoc)
* @see org.alfresco.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;
}
/**
* Set the freemarker processor
*
* @param freeMarkerProcessor the free marker processor
*/
public void setFreeMarkerProcessor(FreeMarkerProcessor freeMarkerProcessor)
{
this.freeMarkerProcessor = freeMarkerProcessor;
}
/**
* Reset template cache
*/
public void resetCache()
{
if (templateConfig != null)
{
templateConfig.clearTemplateCache();
}
}
/**
* Determines if a template exists
*
* @param template
* @return true => exists
*/
public boolean hasTemplate(String templatePath)
{
boolean hasTemplate = false;
try
{
Template template = templateConfig.getTemplate(templatePath);
hasTemplate = (template != null);
}
catch(FileNotFoundException e)
{
// NOTE: return false as template is not found
}
catch(IOException e)
{
throw new WebScriptException("Failed to retrieve template " + templatePath, e);
}
return hasTemplate;
}
/**
* Initialise FreeMarker Configuration
*/
protected void initConfig()
{
Configuration config = new Configuration();
// setup template cache
config.setCacheStorage(new MruCacheStorage(20, 100));
// 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);
// turn off locale sensitive lookup - to save numerous wasted calls to nodeservice.exists()
config.setLocalizedLookup(false);
// set template encoding
if (defaultEncoding != null)
{
config.setDefaultEncoding(defaultEncoding);
}
// set output encoding
config.setOutputEncoding("UTF-8");
templateConfig = config;
}
/**
* Tempory fix to initialise this template processor with the freeMarker extensions expected by
* the templates.
*/
private void initProcessorExtensions()
{
for (ProcessorExtension processorExtension : this.freeMarkerProcessor.getProcessorExtensions())
{
this.registerProcessorExtension(processorExtension);
}
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initConfig();
initProcessorExtensions();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}

View File

@@ -0,0 +1,536 @@
/*
* 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.scripts;
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 java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.config.ServerConfigElement;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
/**
* Stand-alone Web Script Test Server
*
* @author davidc
*/
public class TestWebScriptServer
{
// dependencies
protected AuthenticationService authenticationService;
protected DeclarativeWebScriptRegistry registry;
protected ConfigService configService;
protected ServiceRegistry serviceRegistry;
protected RetryingTransactionHelper retryingTransactionHelper;
/** Server Configuration */
private ServerConfigElement serverConfig;
/** The reader for interaction. */
private BufferedReader fIn;
/** Last command issued */
private String lastCommand = null;
/** Current user */
private String username = "admin";
/** Current headers */
private Map<String, String> headers = new HashMap<String, String>();
/** I18N Messages */
private MessageSource m_messages;
/**
* Sets helper that provides transaction callbacks
*/
public void setTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
{
this.retryingTransactionHelper = retryingTransactionHelper;
}
/**
* Sets the Web Script Registry
*
* @param registry
*/
public void setRegistry(DeclarativeWebScriptRegistry registry)
{
this.registry = registry;
}
/**
* Sets the Service Registry
*
* @param registry
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/**
* Sets the Config Service
*
* @param configService
*/
public void setConfigService(ConfigService configService)
{
this.configService = configService;
}
/**
* @param authenticationService
*/
public void setAuthenticationService(AuthenticationService authenticationService)
{
this.authenticationService = authenticationService;
}
/**
* Sets the Messages resource bundle
*
* @param messages
* @throws IOException
*/
public void setMessages(MessageSource messages)
throws IOException
{
this.m_messages = messages;
}
/**
* Initialise the Test Web Script Server
*
* @throws Exception
*/
public void init()
{
Config config = configService.getConfig("Server");
serverConfig = (ServerConfigElement)config.getConfigElement(ServerConfigElement.CONFIG_ELEMENT_ID);
}
/**
* Main entry point.
*/
public static void main(String[] args)
{
try
{
TestWebScriptServer testServer = getTestServer();
testServer.rep();
}
catch(Throwable e)
{
StringWriter strWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(strWriter);
e.printStackTrace(printWriter);
System.out.println(strWriter.toString());
}
finally
{
System.exit(0);
}
}
/**
* Retrieve an instance of the TestWebScriptServer
*
* @return Test Server
*/
public static TestWebScriptServer getTestServer()
{
String[] CONFIG_LOCATIONS = new String[]
{
"classpath:alfresco/application-context.xml",
"classpath:alfresco/web-scripts-application-context.xml",
"classpath:alfresco/web-client-application-context.xml",
"classpath:alfresco/web-scripts-application-context-test.xml"
};
ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_LOCATIONS);
TestWebScriptServer testServer = (TestWebScriptServer)context.getBean("webscripts.test");
testServer.init();
return testServer;
}
/**
* Submit a Web Script Request
*
* @param method http method
* @param uri web script uri (relative to /alfresco/service)
* @return response
* @throws IOException
*/
public MockHttpServletResponse submitRequest(String method, String uri)
throws IOException
{
MockHttpServletRequest req = createRequest(method, uri);
MockHttpServletResponse res = new MockHttpServletResponse();
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, null, req, res, serverConfig);
runtime.executeScript();
return res;
}
/**
* Submit a Web Script Request
*
* @param method http method
* @param uri web script uri (relative to /alfresco/service)
* @param headers headers
* @return response
* @throws IOException
*/
public MockHttpServletResponse submitRequest(String method, String uri, Map<String, String> headers)
throws IOException
{
MockHttpServletRequest req = createRequest(method, uri);
for (Map.Entry<String, String> header: headers.entrySet())
{
req.addHeader(header.getKey(), header.getValue());
}
MockHttpServletResponse res = new MockHttpServletResponse();
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, null, req, res, serverConfig);
runtime.executeScript();
return res;
}
/**
* A Read-Eval-Print loop.
*/
/*package*/ void rep()
{
// accept commands
fIn = new BufferedReader(new InputStreamReader(System.in));
while (true)
{
System.out.print("ok> ");
try
{
// get command
final String line = fIn.readLine();
if (line.equals("exit") || line.equals("quit"))
{
return;
}
// execute command in context of currently selected user
long startms = System.currentTimeMillis();
System.out.print(interpretCommand(line));
System.out.println("" + (System.currentTimeMillis() - startms) + "ms");
}
catch (Exception e)
{
e.printStackTrace(System.err);
System.out.println("");
}
}
}
/**
* Interpret a single command using the BufferedReader passed in for any data needed.
*
* @param line The unparsed command
* @return The textual output of the command.
*/
private String interpretCommand(final String line)
throws IOException
{
try
{
if (username.startsWith("TICKET_"))
{
try
{
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
authenticationService.validate(username);
return null;
}
});
return executeCommand(line);
}
finally
{
authenticationService.clearCurrentSecurityContext();
}
}
}
catch(AuthenticationException e)
{
executeCommand("user admin");
}
// execute command in context of currently selected user
return AuthenticationUtil.runAs(new RunAsWork<String>()
{
@SuppressWarnings("synthetic-access")
public String doWork() throws Exception
{
return executeCommand(line);
}
}, username);
}
/**
* 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 executeCommand(String line)
throws IOException
{
String[] command = line.split(" ");
if (command.length == 0)
{
command = new String[1];
command[0] = line;
}
ByteArrayOutputStream bout = new ByteArrayOutputStream();
PrintStream out = new PrintStream(bout);
// repeat last command?
if (command[0].equals("r"))
{
if (lastCommand == null)
{
return "No command entered yet.";
}
return "repeating command " + lastCommand + "\n\n" + interpretCommand(lastCommand);
}
// remember last command
lastCommand = line;
// execute command
if (command[0].equals("help"))
{
String helpFile = m_messages.getMessage("testserver.help", null, null);
ClassPathResource helpResource = new ClassPathResource(helpFile);
byte[] helpBytes = new byte[500];
InputStream helpStream = helpResource.getInputStream();
try
{
int read = helpStream.read(helpBytes);
while (read != -1)
{
bout.write(helpBytes, 0, read);
read = helpStream.read(helpBytes);
}
}
finally
{
helpStream.close();
}
}
else if (command[0].equals("user"))
{
if (command.length == 2)
{
username = command[1];
}
out.println("using user " + username);
}
else if (command[0].equals("get") ||
command[0].equals("put") ||
command[0].equals("post") ||
command[0].equals("delete"))
{
String uri = (command.length > 1) ? command[1] : null;
MockHttpServletResponse res = submitRequest(command[0], uri, headers);
bout.write(("Response status: " + res.getStatus()).getBytes());
out.println();
bout.write(res.getContentAsByteArray());
out.println();
}
else if (command[0].equals("tunnel"))
{
if (command.length < 4)
{
return "Syntax Error.\n";
}
if (command[1].equals("param"))
{
String uri = command[3];
if (uri.indexOf('?') == -1)
{
uri += "?alf:method=" + command[2];
}
else
{
uri += "&alf:method=" + command[2];
}
MockHttpServletResponse res = submitRequest("post", uri, headers);
bout.write(res.getContentAsByteArray());
out.println();
}
else if (command[1].equals("header"))
{
Map<String, String> tunnelheaders = new HashMap<String, String>();
tunnelheaders.putAll(headers);
tunnelheaders.put("X-HTTP-Method-Override", command[2]);
MockHttpServletResponse res = submitRequest("post", command[3], tunnelheaders);
bout.write(res.getContentAsByteArray());
out.println();
}
else
{
return "Syntax Error.\n";
}
}
else if (command[0].equals("header"))
{
if (command.length == 1)
{
for (Map.Entry<String, String> entry : headers.entrySet())
{
out.println(entry.getKey() + " = " + entry.getValue());
}
}
else if (command.length == 2)
{
String[] param = command[1].split("=");
if (param.length == 0)
{
return "Syntax Error.\n";
}
if (param.length == 1)
{
headers.remove(param[0]);
out.println("deleted header " + param[0]);
}
else if (param.length == 2)
{
headers.put(param[0], param[1]);
out.println("set header " + param[0] + " = " + headers.get(param[0]));
}
else
{
return "Syntax Error.\n";
}
}
else
{
return "Syntax Error.\n";
}
}
else if (command[0].equals("reset"))
{
registry.reset();
out.println("Registry reset.");
}
else
{
return "Syntax Error.\n";
}
out.flush();
String retVal = new String(bout.toByteArray());
out.close();
return retVal;
}
/**
* Create a Mock HTTP Servlet Request
*
* @param method
* @param uri
* @return mock http servlet request
* @throws UnsupportedEncodingException
*/
private MockHttpServletRequest createRequest(String method, String uri)
throws UnsupportedEncodingException
{
MockHttpServletRequest req = new MockHttpServletRequest(method, uri);
req.setContextPath("/alfresco");
req.setServletPath("/service");
if (uri != null)
{
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) ? URLDecoder.decode(parts[1], "UTF-8") : null);
}
req.setQueryString(URLDecoder.decode(uriArgs, "UTF-8"));
}
String requestURI = "/alfresco/service" + (iArgIndex == -1 ? uri : uri.substring(0, iArgIndex));
req.setRequestURI(URLDecoder.decode(requestURI, "UTF-8"));
}
return req;
}
}

View File

@@ -0,0 +1,174 @@
/*
* 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.scripts;
/**
* Script / Template Model representing Web Script URLs
*
* @author davidc
*/
public class URLModel
{
private WebScriptRequest req;
/**
* Construct
*
* @param req
* @param res
*/
URLModel(WebScriptRequest req)
{
this.req = req;
}
/**
* Gets the Context Path
*
* e.g. /alfresco
*
* @return context path
*/
public String getContext()
{
return req.getContextPath();
}
public String jsGet_context()
{
return getContext();
}
/**
* Gets the Service Context Path
*
* e.g. /alfresco/service
*
* @return service context path
*/
public String getServiceContext()
{
return req.getServiceContextPath();
}
public String jsGet_serviceContext()
{
return getServiceContext();
}
/**
* Gets the Service Path
*
* e.g. /alfresco/service/search/keyword
*
* @return service path
*/
public String getService()
{
return req.getServicePath();
}
public String jsGet_service()
{
return getService();
}
/**
* Gets the full path
*
* e.g. /alfresco/service/search/keyword?q=term
*
* @return service path
*/
public String getFull()
{
return req.getURL();
}
public String jsGet_full()
{
return getFull();
}
/**
* Gets the URL arguments (query string)
*
* @return args (query string)
*/
public String getArgs()
{
String args = req.getQueryString();
return (args == null) ? "" : args;
}
public String jsGet_args()
{
return getArgs();
}
/**
* Gets the matching service path
*
* e.g.
* a) service registered path = /search/engine
* b) request path = /search/engine/external
*
* => /search/engine
*
* @return matching path
*/
public String getMatch()
{
return req.getServiceMatch().getPath();
}
public String jsGet_match()
{
return getMatch();
}
/**
* Gets the Service Extension Path
*
* e.g.
* a) service registered path = /search/engine
* b) request path = /search/engine/external
*
* => /external
*
* @return extension path
*/
public String getExtension()
{
return req.getExtensionPath();
}
public String jsGet_extension()
{
return getExtension();
}
}

View File

@@ -0,0 +1,128 @@
/*
* 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.scripts;
import java.io.IOException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.web.app.servlet.AuthenticationHelper;
import org.alfresco.web.app.servlet.AuthenticationStatus;
import org.alfresco.web.app.servlet.BaseServlet;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.ServletContextAware;
/**
* Alfresco Web Client Authentication Interceptor
*
* @author davidc
*/
public class WebClientAuthenticator implements WebScriptServletAuthenticator, ServletContextAware
{
// Logger
private static final Log logger = LogFactory.getLog(WebClientAuthenticator.class);
// dependencies
private ServletContext context;
/* (non-Javadoc)
* @see org.springframework.web.context.ServletContextAware#setServletContext(javax.servlet.ServletContext)
*/
public void setServletContext(ServletContext context)
{
this.context = context;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptServletAuthenticator#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
public boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest preq, WebScriptServletResponse pres)
{
AuthenticationStatus status = null;
try
{
//
// validate credentials
//
HttpServletRequest req = preq.getHttpServletRequest();
HttpServletResponse res = pres.getHttpServletResponse();
String ticket = req.getParameter("ticket");
if (logger.isDebugEnabled())
{
logger.debug("Alfresco 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, req, res, ticket);
}
else
{
if (isGuest && RequiredAuthentication.guest == required)
{
if (logger.isDebugEnabled())
logger.debug("Authenticating as Guest");
status = AuthenticationHelper.authenticate(context, req, res, true);
}
else
{
if (logger.isDebugEnabled())
logger.debug("Authenticating session");
status = AuthenticationHelper.authenticate(context, req, res, false, false);
}
}
//
// if not authorized, redirect to login page
//
if (status == null || status == AuthenticationStatus.Failure)
{
// 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(req, res, context);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to authenticate", e);
}
return !(status == null || status == AuthenticationStatus.Failure);
}
}

View File

@@ -0,0 +1,53 @@
/*
* 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.scripts;
import java.io.IOException;
/**
* Web Script
*
* @author davidc
*/
public interface WebScript
{
/**
* Gets the Service Description
*
* @return service description
*/
public WebScriptDescription getDescription();
/**
* Execute service
*
* @param req
* @param res
* @throws IOException
*/
public void execute(WebScriptRequest req, WebScriptResponse res)
throws IOException;
}

View File

@@ -0,0 +1,162 @@
/*
* 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.scripts;
import java.util.Date;
/**
* Web Script Cache
*
* Records the desired cache requirements for the Web Script
*
* @author davidc
*/
public class WebScriptCache implements WebScriptDescription.RequiredCache
{
private boolean neverCache = true;
private boolean isPublic = false;
private boolean mustRevalidate = true;
private Date lastModified = null;
private String eTag = null;
private Long maxAge = null;
/**
* Construct
*/
public WebScriptCache()
{
}
/**
* Construct
*
* @param requiredCache
*/
public WebScriptCache(WebScriptDescription.RequiredCache requiredCache)
{
neverCache = requiredCache.getNeverCache();
isPublic = requiredCache.getIsPublic();
mustRevalidate = requiredCache.getMustRevalidate();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getNeverCache()
*/
public boolean getNeverCache()
{
return neverCache;
}
/**
* @param neverCache
*/
public void setNeverCache(boolean neverCache)
{
this.neverCache = neverCache;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getIsPublic()
*/
public boolean getIsPublic()
{
return isPublic;
}
/**
* @param isPublic
*/
public void setIsPublic(boolean isPublic)
{
this.isPublic = isPublic;
}
/**
* @return last modified
*/
public Date getLastModified()
{
return lastModified;
}
/**
* @param lastModified
*/
public void setLastModified(Date lastModified)
{
this.lastModified = lastModified;
}
/**
* @return ETag
*/
public String getETag()
{
return eTag;
}
/**
* @param tag ETag
*/
public void setETag(String tag)
{
eTag = tag;
}
/**
* @return Max Age (seconds)
*/
public Long getMaxAge()
{
return maxAge;
}
/**
* @param maxAge Max Age (seconds)
*/
public void setMaxAge(Long maxAge)
{
this.maxAge = maxAge;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription.RequiredCache#getMustRevalidate()
*/
public boolean getMustRevalidate()
{
return mustRevalidate;
}
/**
* @param mustRevalidate
*/
public void setMustRevalidate(boolean mustRevalidate)
{
this.mustRevalidate = mustRevalidate;
}
}

View File

@@ -22,20 +22,14 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts;
package org.alfresco.web.scripts;
import java.util.Arrays;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.model.FileNotFoundException;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
@@ -43,7 +37,6 @@ import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.PersonService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.util.AbstractLifecycleBean;
import org.alfresco.web.scripts.WebScriptException;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -56,7 +49,7 @@ import org.springframework.context.ApplicationListener;
*
* @author davidc
*/
public class Repository implements ApplicationContextAware, ApplicationListener
public class WebScriptContext implements ApplicationContextAware, ApplicationListener
{
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
@@ -65,7 +58,6 @@ public class Repository implements ApplicationContextAware, ApplicationListener
private NamespaceService namespaceService;
private SearchService searchService;
private NodeService nodeService;
private FileFolderService fileFolderService;
private PersonService personService;
// company home
@@ -131,17 +123,7 @@ public class Repository implements ApplicationContextAware, ApplicationListener
{
this.nodeService = nodeService;
}
/**
* Sets the file folder service
*
* @param nodeService
*/
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
/**
* Sets the person service
*
@@ -254,79 +236,4 @@ public class Repository implements ApplicationContextAware, ApplicationListener
return (NodeRef)nodeService.getProperty(person, ContentModel.PROP_HOMEFOLDER);
}
/**
* Helper to convert a Web Script Request URL to a Node Ref
*
* 1) Node - {store_type}/{store_id}/{node_id}
*
* Resolve to node via its Node Reference.
*
* 2) Path - {store_type}/{store_id}/{path}
*
* Resolve to node via its display path.
*
* 3) QName - {store_type}/{store_id}/{child_qname_path} TODO: Implement
*
* Resolve to node via its child qname path.
*
* @param referenceType one of node, path or qname
* @return reference array of reference segments (as described above for each reference type)
*/
public NodeRef findNodeRef(String referenceType, String[] reference)
{
NodeRef nodeRef = null;
// construct store reference
if (reference.length < 3)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Reference " + Arrays.toString(reference) + " is not properly formed");
}
StoreRef storeRef = new StoreRef(reference[0], reference[1]);
if (nodeService.exists(storeRef))
{
if (referenceType.equals("node"))
{
NodeRef urlRef = new NodeRef(storeRef, reference[2]);
if (nodeService.exists(urlRef))
{
nodeRef = urlRef;
}
}
else if (referenceType.equals("path"))
{
// TODO: Allow a root path to be specified - for now, hard-code to Company Home
// NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
NodeRef rootNodeRef = getCompanyHome();
if (reference.length == 3)
{
nodeRef = rootNodeRef;
}
else
{
String[] path = new String[reference.length - /*2*/3];
System.arraycopy(reference, /*2*/3, path, 0, path.length);
try
{
FileInfo fileInfo = fileFolderService.resolveNamePath(rootNodeRef, Arrays.asList(path));
nodeRef = fileInfo.getNodeRef();
}
catch (FileNotFoundException e)
{
// NOTE: return null node ref
}
}
}
else
{
// TODO: Implement 'qname' style
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Web Script Node URL specified an invalid reference style of '" + referenceType + "'");
}
}
return nodeRef;
}
}

View File

@@ -0,0 +1,196 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.InputStream;
/**
* Web Script Description
*
* @author davidc
*/
public interface WebScriptDescription
{
/**
* Enumeration of "required" Authentication level
*/
public enum RequiredAuthentication
{
none,
guest,
user,
admin
}
/**
* Enumeration of "required" Transaction level
*/
public enum RequiredTransaction
{
none,
required,
requiresnew
}
/**
* Caching requirements
*/
public interface RequiredCache
{
/**
* Determine if Web Script should ever be cached
*
* @return true => do not cache, false => caching may or not occur
*/
public boolean getNeverCache();
/**
* Determine if Web Script content is for public caching
*
* @return true => content is public, so allow cache
*/
public boolean getIsPublic();
/**
* Must cache re-validate to ensure content is fresh
*
* @return true => must re-validate
*/
public boolean getMustRevalidate();
}
/**
* Enumeration of ways to specify format
*/
public enum FormatStyle
{
any, // any of the following styles
extension, // /a/b/c.x
argument // /a/b/c?format=x
}
/**
* Gets the root path of the store of this web script
*
* @return root path of store
*/
public String getStorePath();
/**
* Gets the path within the store of this web script
*
* @return path within store
*/
public String getScriptPath();
/**
* Gets the path of the description xml document for this web script
*
* @return document location (path)
*/
public String getDescPath();
/**
* Gets the description xml document for this web script
*
* @return source document
*/
public InputStream getDescDocument()
throws IOException;
/**
* Gets the id of this service
*
* @return service id
*/
public String getId();
/**
* Gets the short name of this service
*
* @return service short name
*/
public String getShortName();
/**
* Gets the description of this service
*/
public String getDescription();
/**
* Gets the required authentication level for execution of this service
*
* @return the required authentication level
*/
public RequiredAuthentication getRequiredAuthentication();
/**
* Gets the required transaction level
*
* @return the required transaction level
*/
public RequiredTransaction getRequiredTransaction();
/**
* Gets the required level of caching
* @return
*/
public RequiredCache getRequiredCache();
/**
* 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 String[] getURIs();
/**
* Gets the style of Format discriminator supported by this web script
*
* @return format style
*/
public FormatStyle getFormatStyle();
/**
* Gets the default response format
*
* Note: the default response format is the first listed in the service
* description document
*
* @return default response format (or null, if format not known until run-time)
*/
public String getDefaultFormat();
}

View File

@@ -0,0 +1,296 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.InputStream;
/**
* Implementation of a Web Script Description
*
* @author davidc
*/
public class WebScriptDescriptionImpl implements WebScriptDescription
{
private WebScriptStore store;
private String scriptPath;
private String descPath;
private String id;
private String shortName;
private String description;
private RequiredAuthentication requiredAuthentication;
private RequiredTransaction requiredTransaction;
private RequiredCache requiredCache;
private FormatStyle formatStyle;
private String httpMethod;
private String[] uris;
private String defaultFormat;
/**
* Sets the web description store
*
* @param store store
*/
public void setStore(WebScriptStore store)
{
this.store = store;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getStorePath()
*/
public String getStorePath()
{
return store.getBasePath();
}
/**
* Sets the script path
*
* @param scriptPath
*/
public void setScriptPath(String scriptPath)
{
this.scriptPath = scriptPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getScriptPath()
*/
public String getScriptPath()
{
return scriptPath;
}
/**
* Sets the desc path
*
* @param descPath
*/
public void setDescPath(String descPath)
{
this.descPath = descPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescPath()
*/
public String getDescPath()
{
return descPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescDocument()
*/
public InputStream getDescDocument()
throws IOException
{
return store.getDocument(descPath);
}
/**
* Sets the service id
*
* @param id
*/
public void setId(String id)
{
this.id = id;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getId()
*/
public String getId()
{
return this.id;
}
/**
* Sets the service short name
*
* @param shortName
*/
public void setShortName(String shortName)
{
this.shortName = shortName;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getShortName()
*/
public String getShortName()
{
return this.shortName;
}
/**
* Sets the service description
*
* @param description
*/
public void setDescription(String description)
{
this.description = description;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDescription()
*/
public String getDescription()
{
return this.description;
}
/**
* Sets the required level of authentication
*
* @param requiredAuthentication
*/
public void setRequiredAuthentication(RequiredAuthentication requiredAuthentication)
{
this.requiredAuthentication = requiredAuthentication;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredAuthentication()
*/
public RequiredAuthentication getRequiredAuthentication()
{
return this.requiredAuthentication;
}
/**
* Sets the required level of transaction
*
* @param requiredTransaction
*/
public void setRequiredTransaction(RequiredTransaction requiredTransaction)
{
this.requiredTransaction = requiredTransaction;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredTransaction()
*/
public RequiredTransaction getRequiredTransaction()
{
return this.requiredTransaction;
}
/**
* Sets the required cache
*
* @param requiredCache
*/
public void setRequiredCache(RequiredCache requiredCache)
{
this.requiredCache = requiredCache;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getRequiredCache()
*/
public RequiredCache getRequiredCache()
{
return this.requiredCache;
}
/**
* Sets the format style
*
* @param formatStyle
*/
public void setFormatStyle(FormatStyle formatStyle)
{
this.formatStyle = formatStyle;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getFormatStyle()
*/
public FormatStyle getFormatStyle()
{
return this.formatStyle;
}
/**
* Sets the service http method
*
* @param httpMethod
*/
public void setMethod(String httpMethod)
{
this.httpMethod = httpMethod;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getMethod()
*/
public String getMethod()
{
return this.httpMethod;
}
/**
* Sets the service URIs
*
* @param uris
*/
public void setUris(String[] uris)
{
this.uris = uris;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getURIs()
*/
public String[] getURIs()
{
return this.uris;
}
/**
* Sets the default response format
*
* @param defaultFormat
*/
public void setDefaultFormat(String defaultFormat)
{
this.defaultFormat = defaultFormat;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptDescription#getDefaultFormat()
*/
public String getDefaultFormat()
{
return this.defaultFormat;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.scripts;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.error.AlfrescoRuntimeException;
/**
* Web Script Exceptions.
*
* @author David Caruana
*/
public class WebScriptException extends AlfrescoRuntimeException
{
private static final long serialVersionUID = -7338963365877285084L;
private int status = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
public WebScriptException(int status, String msgId)
{
this(msgId);
this.status = status;
}
public WebScriptException(String msgId)
{
super(msgId);
}
public WebScriptException(String msgId, Throwable cause)
{
super(msgId, cause);
}
public WebScriptException(String msgId, Object ... args)
{
super(msgId, args);
}
public WebScriptException(String msgId, Throwable cause, Object ... args)
{
super(msgId, args, cause);
}
public int getStatus()
{
return status;
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.scripts;
/**
* Represents a URL request to Web Script match
*
* @author davidc
*/
public interface WebScriptMatch
{
public enum Kind
{
/** URL request matches on URI only */
URI,
/** URL request matches on URI and Method */
FULL
};
/**
* Gets the kind of Match
*/
public Kind getKind();
/**
* Gets the part of the request URL that matched the Web Script URL Template
*
* @return matching url path
*/
public String getPath();
/**
* Gets the matching web script
*
* @return service (or null, if match kind is URI)
*/
public WebScript getWebScript();
}

View File

@@ -0,0 +1,70 @@
/*
* 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.scripts;
/**
* Web Script Path
*
* @author davidc
*/
public interface WebScriptPath
{
/**
* Gets the full path
*
* @return path
*/
public String getPath();
/**
* Gets the name of the path (last path segment)
*
* @return name
*/
public String getName();
/**
* Gets the parent path
*
* @return path
*/
public WebScriptPath getParent();
/**
* Gets the child paths
*
* @return child paths
*/
public WebScriptPath[] getChildren();
/**
* Gets Web Scripts associated with this path
*
* @return web scripts
*/
public WebScript[] getScripts();
}

View File

@@ -0,0 +1,120 @@
/*
* 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.scripts;
import java.util.Collection;
import javax.servlet.ServletContext;
import org.alfresco.service.cmr.repository.TemplateImageResolver;
/**
* Web Scripts Registry
*
* @author davidc
*/
public interface WebScriptRegistry
{
/**
* Gets a Web Script Package
*
* @param packagePath
* @return web script path representing package
*/
public WebScriptPath getPackage(String packagePath);
/**
* Gets a Web Script URL
*
* @param uriPath
* @return web script path representing uri
*/
public WebScriptPath getUri(String uriPath);
/**
* Gets all Web Scripts
*
* @return web scripts
*/
public Collection<WebScript> getWebScripts();
/**
* Gets a Web Script by Id
*
* @param id web script id
* @return web script
*/
public WebScript getWebScript(String id);
/**
* Gets a Web Script given an HTTP Method and URI
*
* @param method http method
* @param uri uri
* @return service match (pair of service and uri that matched)
*/
public WebScriptMatch findWebScript(String method, String uri);
/**
* Gets the Servlet Context
*
* @return servlet context
*/
public ServletContext getContext();
/**
* Gets the response format registry
*
* @return response format registry
*/
public FormatRegistry getFormatRegistry();
/**
* Gets the Template Processor
*
* @return template processor
*/
public TemplateProcessor getTemplateProcessor();
/**
* Gets the Template Image Resolver
*
* @return template image resolver
*/
public TemplateImageResolver getTemplateImageResolver();
/**
* Gets the Script Processor
*
* @return script processor
*/
public ScriptProcessor getScriptProcessor();
/**
* Resets the Registry
*/
public void reset();
}

View File

@@ -0,0 +1,199 @@
/*
* 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.scripts;
import org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
/**
* Web Script Request
*
* @author davidc
*/
public interface WebScriptRequest
{
/**
* Gets the matching API Service for this request
*
* @return the service match
*/
public WebScriptMatch getServiceMatch();
/**
* Get server portion of the request
*
* e.g. scheme://host:port
*
* @return server path
*/
public String getServerPath();
/**
* Gets the Alfresco Context Path
*
* @return context url e.g. /alfresco
*/
public String getContextPath();
/**
* Gets the Alfresco Web Script Context Path
*
* @return service url e.g. /alfresco/service
*/
public String getServiceContextPath();
/**
* Gets the Alfresco Service Path
*
* @return service url e.g. /alfresco/service/search/keyword
*/
public String getServicePath();
/**
* Gets the full request URL
*
* @return request url e.g. /alfresco/service/search/keyword?q=term
*/
public String getURL();
/**
* Gets the service specific path
*
* @return request path e.g. /search/keyword
*/
public String getPathInfo();
/**
* Gets the query String
*
* @return query string e.g. q=alfresco&format=atom
*/
public String getQueryString();
/**
* Gets the names of all parameters on the Url
*
* @return the names (empty, if none)
*/
public String[] getParameterNames();
/**
* Gets the value of the named parameter
*
* @param name parameter name
* @return parameter value (or null, if parameter does not exist)
*/
public String getParameter(String name);
/**
* Gets the (array) value of the named parameter
*
* Note: An array of one item is returned when a "single value" named parameter
* is requested
*
* @param name parameter name
* @return array of values (or null, if parameter does not exist)
*/
public String[] getParameterValues(String name);
/**
*
* @return
*/
public String[] getAttributeNames();
/**
*
* @param name
* @return
*/
public Object getAttribute(String name);
/**
*
* @return
*/
public Object[] getAttributeValues();
/**
* 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();
/**
* Determine if Guest User?
*
* @return true => guest user
*/
public boolean isGuest();
/**
* Get Requested Format
*
* @return content type requested
*/
public String getFormat();
/**
* Get the style the Format was specified in
*
* @return format style (excludes any)
*/
public FormatStyle getFormatStyle();
/**
* Get User Agent
*
* TODO: Expand on known agents
*
* @return MSIE / Firefox
*/
public String getAgent();
/**
* Get the JSON callback method
*
* @return method (or null, if not specified)
*/
public String getJSONCallback();
/**
* Force response to return SUCCESS (200) code
*
* Note: This is to support clients who cannot support non-success codes
* e.g. Flash player
*
* @return true => force return of 200, otherwise return status explicitly set
*/
public boolean forceSuccessStatus();
}

View File

@@ -0,0 +1,151 @@
/*
* 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.scripts;
import org.alfresco.web.scripts.WebScriptDescription.FormatStyle;
/**
* Basic Implementation of a Web Script Request
*
* @author davidc
*/
public abstract class WebScriptRequestImpl implements WebScriptRequest
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getExtensionPath()
*/
public String getExtensionPath()
{
String extensionPath = "";
WebScriptMatch match = getServiceMatch();
if (match != null)
{
String matchPath = getServiceMatch().getPath();
String pathInfo = getPathInfo();
if (pathInfo != null)
{
extensionPath = pathInfo.substring(matchPath.length());
}
}
return extensionPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#isGuest()
*/
public boolean isGuest()
{
return Boolean.valueOf(getParameter("guest"));
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getFormat()
*/
public String getFormat()
{
String format = null;
WebScriptMatch match = getServiceMatch();
if (match != null)
{
FormatStyle style = getServiceMatch().getWebScript().getDescription().getFormatStyle();
// extract format from extension
if (style == FormatStyle.extension || style == FormatStyle.any)
{
String pathInfo = getPathInfo();
if (pathInfo != null)
{
int extIdx = pathInfo.lastIndexOf('.');
if (extIdx != -1)
{
format = pathInfo.substring(extIdx +1);
}
}
}
// extract format from argument
if (style == FormatStyle.argument || style == FormatStyle.any)
{
String argFormat = getParameter("format");
if (argFormat != null)
{
if (format != null && format.length() > 0)
{
throw new WebScriptException("Format specified both in extension and format argument");
}
format = argFormat;
}
}
}
return (format == null || format.length() == 0) ? "" : format;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getFormatStyle()
*/
public FormatStyle getFormatStyle()
{
WebScriptMatch match = getServiceMatch();
if (match == null)
{
return FormatStyle.any;
}
FormatStyle style = match.getWebScript().getDescription().getFormatStyle();
if (style != FormatStyle.any)
{
return style;
}
else
{
String argFormat = getParameter("format");
if (argFormat != null && argFormat.length() > 0)
{
return FormatStyle.argument;
}
else
{
return FormatStyle.extension;
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getJSONCallback()
*/
public String getJSONCallback()
{
return getParameter("alf_callback");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#forceSuccessStatus()
*/
public boolean forceSuccessStatus()
{
return false;
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
/**
* Web Script Response
*
* @author davidc
*/
public interface WebScriptResponse
{
// API Formats
public static final String HTML_FORMAT = "html";
public static final String ATOM_FORMAT = "atom";
public static final String RSS_FORMAT = "rss";
public static final String XML_FORMAT = "xml";
public static final String JSON_FORMAT = "json";
public static final String OPENSEARCH_DESCRIPTION_FORMAT = "opensearchdescription";
/**
* Sets the Response Status
*
* @param status
*/
public void setStatus(int status);
/**
* Sets the Content Type
*
* @param contentType
*/
public void setContentType(String contentType);
/**
* Sets the Cache control
*
* @param cache cache control
*/
public void setCache(WebScriptCache cache);
/**
* Gets the Writer
*
* @return writer
* @throws IOException
*/
public Writer getWriter() throws IOException;
/**
* Gets the Output Stream
*
* @return output stream
* @throws IOException
*/
public OutputStream getOutputStream() throws IOException;
/**
* Clears response buffer
*/
public void reset();
/**
* Encode a script URL
*
* Note: Some Web Script Runtime environments (e.g. JSR-168, JSF) require urls to be re-written.
*
* @param url to encode
* @return encoded url
*/
public String encodeScriptUrl(String url);
/**
* Return a client side javascript function to build urls to this service
*
* @param name Generated function name
*
* @return javascript function definition
*/
public String getEncodeScriptUrlFunction(String name);
}

View File

@@ -0,0 +1,453 @@
/*
* 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.scripts;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
import org.alfresco.web.scripts.WebScriptDescription.RequiredTransaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Encapsulates the execution of a single Web Script.
*
* Provides support for logging, transactions and authentication.
*
* Sub-classes of WebScriptRuntime maintain the execution environment e.g. servlet
* request & response.
*
* A new instance of WebScriptRuntime is required for each new execution environment.
*
* @author davidc
*/
public abstract class WebScriptRuntime
{
// Logger
protected static final Log logger = LogFactory.getLog(WebScriptRuntime.class);
/** Component Dependencies */
private WebScriptRegistry registry;
private ServiceRegistry serviceRegistry;
private RetryingTransactionHelper retryingTransactionHelper;
private AuthorityService authorityService;
/**
* Construct
*
* @param registry web script registry
* @param serviceRegistry service registry
*/
public WebScriptRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry)
{
this.registry = registry;
this.serviceRegistry = serviceRegistry;
this.authorityService = serviceRegistry.getAuthorityService();
this.retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
}
/**
* Execute the Web Script encapsulated by this Web Script Runtime
*/
public void executeScript()
{
long startRuntime = System.currentTimeMillis();
String method = getScriptMethod();
String scriptUrl = null;
try
{
// extract script url
scriptUrl = getScriptUrl();
if (scriptUrl == null || scriptUrl.length() == 0)
{
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, "Script URL not specified");
}
if (logger.isDebugEnabled())
logger.debug("Processing script url (" + method + ") " + scriptUrl);
WebScriptMatch match = registry.findWebScript(method, scriptUrl);
if (match == null || match.getKind() == WebScriptMatch.Kind.URI)
{
if (match == null)
{
String msg = "Script url " + scriptUrl + " does not map to a Web Script.";
if (logger.isDebugEnabled())
logger.debug(msg);
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, msg);
}
else
{
String msg = "Script url " + scriptUrl + " does not support the method " + method;
if (logger.isDebugEnabled())
logger.debug(msg);
throw new WebScriptException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
}
}
// create web script request & response
final WebScriptRequest scriptReq = createRequest(match);
final WebScriptResponse scriptRes = createResponse();
if (logger.isDebugEnabled())
logger.debug("Agent: " + scriptReq.getAgent());
long startScript = System.currentTimeMillis();
final WebScript script = match.getWebScript();
final WebScriptDescription description = script.getDescription();
try
{
if (logger.isDebugEnabled())
{
String user = AuthenticationUtil.getCurrentUserName();
String locale = I18NUtil.getLocale().toString();
String reqFormat = scriptReq.getFormat();
String format = (reqFormat == null || reqFormat.length() == 0) ? "default" : scriptReq.getFormat();
WebScriptDescription desc = scriptReq.getServiceMatch().getWebScript().getDescription();
logger.debug("Format style: " + desc.getFormatStyle() + ", Default format: " + desc.getDefaultFormat());
logger.debug("Invoking Web Script " + description.getId() + (user == null ? " (unauthenticated)" : " (authenticated as " + user + ") (format " + format + ") (" + locale + ")"));
}
// execute script within required level of authentication
authenticatedExecute(scriptReq, scriptRes);
}
finally
{
if (logger.isDebugEnabled())
{
long endScript = System.currentTimeMillis();
logger.debug("Web Script " + description.getId() + " executed in " + (endScript - startScript) + "ms");
}
}
}
catch(Throwable e)
{
if (logger.isInfoEnabled())
logger.info("Caught exception & redirecting to status template: " + e.getMessage());
if (logger.isDebugEnabled())
{
StringWriter writer = new StringWriter();
PrintWriter printWriter = new PrintWriter(writer);
e.printStackTrace(printWriter);
logger.debug("Caught exception: " + writer.toString());
}
// extract status code, if specified
int statusCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
if (e instanceof WebScriptException)
{
statusCode = ((WebScriptException)e).getStatus();
}
// create web script status for status template rendering
WebScriptStatus status = new WebScriptStatus();
status.setCode(statusCode);
status.setMessage(e.getMessage());
status.setException(e);
// create basic model for status template rendering
WebScriptRequest req = createRequest(null);
WebScriptResponse res = createResponse();
Map<String, Object> model = new HashMap<String, Object>();
model.put("status", status);
model.put("url", new URLModel(req));
model.put("server", new ServerModel(serviceRegistry.getDescriptorService().getServerDescriptor()));
model.put("date", new Date());
// locate status template
// NOTE: search order...
// 1) root located <status>.ftl
// 2) root located status.ftl
String templatePath = getStatusCodeTemplate(statusCode);
if (!registry.getTemplateProcessor().hasTemplate(templatePath))
{
templatePath = getStatusTemplate();
if (!registry.getTemplateProcessor().hasTemplate(templatePath))
{
throw new WebScriptException("Failed to find status template " + templatePath + " (format: " + WebScriptResponse.HTML_FORMAT + ")");
}
}
// render output
if (logger.isDebugEnabled())
{
logger.debug("Force success status header in response: " + req.forceSuccessStatus());
logger.debug("Sending status " + statusCode + " (Template: " + templatePath + ")");
logger.debug("Rendering response: content type=" + MimetypeMap.MIMETYPE_HTML);
}
res.reset();
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(true);
res.setCache(cache);
res.setStatus(req.forceSuccessStatus() ? HttpServletResponse.SC_OK : statusCode);
res.setContentType(MimetypeMap.MIMETYPE_HTML + ";charset=UTF-8");
try
{
registry.getTemplateProcessor().process(templatePath, model, res.getWriter());
}
catch (IOException e1)
{
throw new WebScriptException("Internal error", e1);
}
}
finally
{
long endRuntime = System.currentTimeMillis();
if (logger.isDebugEnabled())
logger.debug("Processed script url (" + method + ") " + scriptUrl + " in " + (endRuntime - startRuntime) + "ms");
}
}
/**
* Execute script whilst authenticated
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @throws IOException
*/
protected void authenticatedExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
throws IOException
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
WebScriptDescription desc = script.getDescription();
RequiredAuthentication required = desc.getRequiredAuthentication();
boolean isGuest = scriptReq.isGuest();
if (required == RequiredAuthentication.none)
{
transactionedExecute(scriptReq, scriptRes);
}
else if ((required == RequiredAuthentication.user || required == RequiredAuthentication.admin) && isGuest)
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
}
else
{
String currentUser = null;
try
{
//
// Determine if user already authenticated
//
currentUser = AuthenticationUtil.getCurrentUserName();
if (logger.isDebugEnabled())
{
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
logger.debug("Authentication required: " + required);
logger.debug("Guest login: " + isGuest);
}
//
// Apply appropriate authentication to Web Script invocation
//
if (authenticate(required, isGuest, scriptReq, scriptRes))
{
if (required == RequiredAuthentication.admin && !authorityService.hasAdminAuthority())
{
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
}
// Execute Web Script
transactionedExecute(scriptReq, scriptRes);
}
}
finally
{
//
// Reset authentication for current thread
//
AuthenticationUtil.clearCurrentSecurityContext();
if (currentUser != null)
{
AuthenticationUtil.setCurrentUser(currentUser);
}
if (logger.isDebugEnabled())
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
}
}
}
/**
* Execute script within required level of transaction
*
* @param scriptReq
* @param scriptRes
* @throws IOException
*/
protected void transactionedExecute(final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
throws IOException
{
final WebScript script = scriptReq.getServiceMatch().getWebScript();
final WebScriptDescription description = script.getDescription();
if (description.getRequiredTransaction() == RequiredTransaction.none)
{
wrappedExecute(scriptReq, scriptRes);
}
else
{
// encapsulate script within transaction
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
{
public Object execute() throws Exception
{
if (logger.isDebugEnabled())
logger.debug("Begin transaction: " + description.getRequiredTransaction());
wrappedExecute(scriptReq, scriptRes);
if (logger.isDebugEnabled())
logger.debug("End transaction: " + description.getRequiredTransaction());
return null;
}
};
if (description.getRequiredTransaction() == RequiredTransaction.required)
{
retryingTransactionHelper.doInTransaction(work);
}
else
{
retryingTransactionHelper.doInTransaction(work, false, true);
}
}
}
/**
* Execute Web Script with pre & post hooks
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @throws IOException
*/
protected void wrappedExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
throws IOException
{
boolean execute = preExecute(scriptReq, scriptRes);
if (execute)
{
WebScript script = scriptReq.getServiceMatch().getWebScript();
script.execute(scriptReq, scriptRes);
postExecute(scriptReq, scriptRes);
}
}
/**
* Get the Web Script Method e.g. get, post
*
* @return web script method
*/
protected abstract String getScriptMethod();
/**
* Get the Web Script Url
*
* @return web script url
*/
protected abstract String getScriptUrl();
/**
* Create a Web Script Request
*
* @param match web script matching the script method and url
* @return web script request
*/
protected abstract WebScriptRequest createRequest(WebScriptMatch match);
/**
* Create a Web Script Response
*
* @return web script response
*/
protected abstract WebScriptResponse createResponse();
/**
* Authenticate Web Script execution
*
* @param required required level of authentication
* @param isGuest is the request accessed as Guest
*
* @return true if authorised, false otherwise
*/
// TODO: DC - This method to be refactored during Web Script F/W extraction
protected abstract boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res);
/**
* Pre-execution hook
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
* @return true => execute script, false => do not execute script
*/
protected boolean preExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
return true;
}
/**
* Post-execution hook
*
* Note: this hook is not invoked if the script is not executed.
*
* @param scriptReq Web Script Request
* @param scriptRes Web Script Response
*/
protected void postExecute(WebScriptRequest scriptReq, WebScriptResponse scriptRes)
{
}
protected String getStatusCodeTemplate(int statusCode)
{
return "/" + statusCode + ".ftl";
}
protected String getStatusTemplate()
{
return "/status.ftl";
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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.scripts;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.config.Config;
import org.alfresco.config.ConfigService;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
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 Scripts
*
* @author davidc
*/
public class WebScriptServlet extends HttpServlet
{
private static final long serialVersionUID = 4209892938069597860L;
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServlet.class);
// Component Dependencies
protected DeclarativeWebScriptRegistry registry;
protected ServiceRegistry serviceRegistry;
protected WebScriptServletAuthenticator authenticator;
protected ConfigService configService;
/** Host Server Configuration */
protected static ServerConfigElement serverConfig;
@Override
public void init() throws ServletException
{
super.init();
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
registry = (DeclarativeWebScriptRegistry)context.getBean("webscripts.registry");
serviceRegistry = (ServiceRegistry)context.getBean(ServiceRegistry.SERVICE_REGISTRY);
configService = (ConfigService)context.getBean("webClientConfigService");
// retrieve authenticator via servlet initialisation parameter
String authenticatorId = getInitParameter("authenticator");
if (authenticatorId == null || authenticatorId.length() == 0)
{
authenticatorId = getDefaultAuthenticator();
}
Object bean = context.getBean(authenticatorId);
if (bean == null || !(bean instanceof WebScriptServletAuthenticator))
{
throw new ServletException("Initialisation parameter 'authenticator' does not refer to a Web Script authenticator (" + authenticatorId + ")");
}
authenticator = (WebScriptServletAuthenticator)bean;
// retrieve host server configuration
Config config = configService.getConfig("Server");
serverConfig = (ServerConfigElement)config.getConfigElement(ServerConfigElement.CONFIG_ELEMENT_ID);
// servlet specific initialisation
initServlet(context);
}
/*
* (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
{
if (logger.isDebugEnabled())
logger.debug("Processing request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
if (req.getCharacterEncoding() == null)
{
req.setCharacterEncoding("UTF-8");
}
WebScriptRuntime runtime = new WebScriptServletRuntime(registry, serviceRegistry, authenticator, req, res, serverConfig);
runtime.executeScript();
}
/**
* Servlet specific initialisation
*
* @param context
*/
protected void initServlet(ApplicationContext context)
{
// NOOP
}
/**
* @return default authenticator (bean name)
*/
protected String getDefaultAuthenticator()
{
return "webscripts.authenticator.webclient";
}
}

View File

@@ -0,0 +1,48 @@
/*
* 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.scripts;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* Web Script Authenticator for the HTTP Servlet environment
*
* @author davidc
*/
public interface WebScriptServletAuthenticator
{
/**
* Authenticate Web Script execution
*
* @param required required level of authentication
* @param isGuest is Guest accessing the web script
* @param req http servlet request
* @param res http servlet response
*
* @return true if authorised to execute the script, false otherwise
*/
// TODO: DC - This method to be refactored during Web Script F/W extraction
public boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptServletRequest req, WebScriptServletResponse res);
}

View File

@@ -0,0 +1,357 @@
/*
* 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.scripts;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import org.alfresco.web.config.ServerConfigElement;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Servlet Web Script Request
*
* @author davidc
*/
public class WebScriptServletRequest extends WebScriptRequestImpl
{
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServletRequest.class);
/** Server Config */
private ServerConfigElement serverConfig;
/** HTTP Request */
private HttpServletRequest req;
/** Service bound to this request */
private WebScriptMatch serviceMatch;
/** Form data associated with multipart/form-data */
private FormData formData;
/**
* Construct
*
* @param req
* @param serviceMatch
*/
public WebScriptServletRequest(HttpServletRequest req, WebScriptMatch serviceMatch)
{
this(null, req, serviceMatch);
}
/**
* Construct
*
* @param serverConfig
* @param req
* @param serviceMatch
*/
public WebScriptServletRequest(ServerConfigElement serverConfig, HttpServletRequest req, WebScriptMatch serviceMatch)
{
this.serverConfig = serverConfig;
this.req = req;
this.serviceMatch = serviceMatch;
String contentType = req.getContentType();
if (logger.isDebugEnabled())
logger.debug("Content Type: " + contentType);
if (contentType != null && contentType.startsWith("multipart/form-data"))
{
formData = new FormData(req);
}
}
/**
* Gets the HTTP Servlet Request
*
* @return HTTP Servlet Request
*/
public HttpServletRequest getHttpServletRequest()
{
return req;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceMatch()
*/
public WebScriptMatch getServiceMatch()
{
return serviceMatch;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServerPath()
*/
public String getServerPath()
{
return getServerScheme() + "://" + getServerName() + ":" + getServerPort();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getContextPath()
*/
public String getContextPath()
{
return req.getContextPath();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath()
*/
public String getServiceContextPath()
{
return req.getContextPath() + req.getServletPath();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServicePath()
*/
public String getServicePath()
{
String pathInfo = getPathInfo();
return getServiceContextPath() + ((pathInfo == null) ? "" : pathInfo);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getURL()
*/
public String getURL()
{
return getServicePath() + (req.getQueryString() != null ? "?" + req.getQueryString() : "");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo()
*/
public String getPathInfo()
{
// NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring(getServiceContextPath().length());
try
{
return URLDecoder.decode(pathInfo, "UTF-8");
}
catch(UnsupportedEncodingException e)
{
throw new WebScriptException("Failed to retrieve path info", e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getQueryString()
*/
public String getQueryString()
{
return req.getQueryString();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameterNames()
*/
public String[] getParameterNames()
{
if (formData == null)
{
Set<String> keys = req.getParameterMap().keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
else
{
Set<String> keys = formData.getParameters().keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameter(java.lang.String)
*/
public String getParameter(String name)
{
if (formData == null)
{
return req.getParameter(name);
}
else
{
return formData.getParameters().get(name);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getArrayParameter(java.lang.String)
*/
public String[] getParameterValues(String name)
{
if (formData == null)
{
return req.getParameterValues(name);
}
else
{
String value = formData.getParameters().get(name);
return (value == null ) ? new String[] {} : new String[] {value};
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
{
return null;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeNames()
*/
public String[] getAttributeNames()
{
return new String[0];
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getAttributeValues()
*/
public Object[] getAttributeValues()
{
return new String[0];
}
/**
* Get User Agent
*
* TODO: Expand on known agents
*
* @return MSIE / Firefox
*/
public String getAgent()
{
String userAgent = req.getHeader("user-agent");
if (userAgent != null)
{
if (userAgent.indexOf("Firefox/") != -1)
{
return "Firefox";
}
else if (userAgent.indexOf("MSIE") != -1)
{
return "MSIE";
}
}
return null;
}
/**
* Get Server Scheme
*
* @return server scheme
*/
private String getServerScheme()
{
String scheme = null;
if (serverConfig != null)
{
scheme = serverConfig.getScheme();
}
if (scheme == null)
{
scheme = req.getScheme();
}
return scheme;
}
/**
* Get Server Name
*
* @return server name
*/
private String getServerName()
{
String name = null;
if (serverConfig != null)
{
name = serverConfig.getHostName();
}
if (name == null)
{
name = req.getServerName();
}
return name;
}
/**
* Get Server Port
*
* @return server name
*/
private int getServerPort()
{
Integer port = null;
if (serverConfig != null)
{
port = serverConfig.getPort();
}
if (port == null)
{
port = req.getServerPort();
}
return port;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequestImpl#forceSuccessStatus()
*/
@Override
public boolean forceSuccessStatus()
{
String forceSuccess = req.getHeader("alf-force-success-response");
return Boolean.valueOf(forceSuccess);
}
/**
* Gets the Form data associated with this request
*
* @return form data, or null if request is not multipart/form-data encoded
*/
public FormData getFormData()
{
return formData;
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.scripts;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.util.CachingDateFormat;
import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* HTTP Servlet Web Script Response
*
* @author davidc
*/
public class WebScriptServletResponse implements WebScriptResponse
{
// Logger
private static final Log logger = LogFactory.getLog(WebScriptServletResponse.class);
// Servlet Response
private HttpServletResponse res;
/**
* Construct
*
* @param res
*/
WebScriptServletResponse(HttpServletResponse res)
{
this.res = res;
}
/**
* Gets the HTTP Servlet Response
*
* @return HTTP Servlet Response
*/
public HttpServletResponse getHttpServletResponse()
{
return res;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#setStatus(int)
*/
public void setStatus(int status)
{
res.setStatus(status);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#setContentType(java.lang.String)
*/
public void setContentType(String contentType)
{
res.setContentType(contentType);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#setCache(org.alfresco.web.scripts.WebScriptCache)
*/
public void setCache(WebScriptCache cache)
{
// set Cache-Control
String cacheControl = "";
String pragma = "";
if (cache.getIsPublic())
{
cacheControl += "public";
}
if (cache.getNeverCache())
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + "no-cache";
pragma += (pragma.length() > 0) ? ", " : "" + "no-cache";
}
if (cache.getMaxAge() != null && cache.getNeverCache() == false)
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + " max-age=" + cache.getMaxAge();
}
if (cache.getMustRevalidate() && cache.getNeverCache() == false)
{
cacheControl += (cacheControl.length() > 0 ? ", " : "") + " must-revalidate";
}
if (cacheControl.length() > 0)
{
res.setHeader("Cache-Control", cacheControl);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header Cache-Control: " + cacheControl);
}
if (pragma.length() > 0)
{
res.setHeader("Pragma", pragma);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header Pragma: " + pragma);
}
// set ETag
if (cache.getETag() != null)
{
String eTag = "\"" + cache.getETag() + "\"";
res.setHeader("ETag", eTag);
if (logger.isDebugEnabled())
logger.debug("Cache - set response header ETag: " + eTag);
}
// set Last Modified
if (cache.getLastModified() != null)
{
res.setDateHeader("Last-Modified", cache.getLastModified().getTime());
if (logger.isDebugEnabled())
{
SimpleDateFormat formatter = getHTTPDateFormat();
String lastModified = formatter.format(cache.getLastModified());
logger.debug("Cache - set response header Last-Modified: " + lastModified);
}
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#reset()
*/
public void reset()
{
try
{
res.reset();
}
catch(IllegalStateException e)
{
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getWriter()
*/
public Writer getWriter() throws IOException
{
return res.getWriter();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream()
*/
public OutputStream getOutputStream() throws IOException
{
return res.getOutputStream();
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String)
*/
public String encodeScriptUrl(String url)
{
return url;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String)
*/
public String getEncodeScriptUrlFunction(String name)
{
return Utils.encodeJavascript(ENCODE_FUNCTION.replace("$name$", name));
}
private static final String ENCODE_FUNCTION = "{ $name$: function(url) { return url; } }";
/**
* Helper to return a HTTP Date Formatter
*
* @return HTTP Date Formatter
*/
private static SimpleDateFormat getHTTPDateFormat()
{
if (s_dateFormat.get() != null)
{
return s_dateFormat.get();
}
SimpleDateFormat formatter = CachingDateFormat.getDateFormat("EEE, dd MMM yyyy kk:mm:ss zzz", false);
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
s_dateFormat.set(formatter);
return s_dateFormat.get();
}
private static ThreadLocal<SimpleDateFormat> s_dateFormat = new ThreadLocal<SimpleDateFormat>();
}

View File

@@ -0,0 +1,149 @@
/*
* 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.scripts;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.web.config.ServerConfigElement;
import org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication;
/**
* HTTP Servlet Web Script Runtime
*
* @author davidc
*/
public class WebScriptServletRuntime extends WebScriptRuntime
{
protected HttpServletRequest req;
protected HttpServletResponse res;
protected WebScriptServletAuthenticator authenticator;
protected ServerConfigElement serverConfig;
/**
* Construct
*
* @param registry
* @param serviceRegistry
* @param authenticator
* @param req
* @param res
*/
public WebScriptServletRuntime(WebScriptRegistry registry, ServiceRegistry serviceRegistry, WebScriptServletAuthenticator authenticator,
HttpServletRequest req, HttpServletResponse res, ServerConfigElement serverConfig)
{
super(registry, serviceRegistry);
this.req = req;
this.res = res;
this.authenticator = authenticator;
this.serverConfig = serverConfig;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptMethod()
*/
@Override
protected String getScriptMethod()
{
// Is this an overloaded POST request?
String method = req.getMethod();
if (method.equalsIgnoreCase("post"))
{
boolean overloadParam = false;
String overload = req.getHeader("X-HTTP-Method-Override");
if (overload == null || overload.length() == 0)
{
overload = req.getParameter("alf_method");
overloadParam = true;
}
if (overload != null && overload.length() > 0)
{
if (logger.isDebugEnabled())
logger.debug("POST is tunnelling method '" + overload + "' as specified by " + (overloadParam ? "alf_method parameter" : "X-HTTP-Method-Override header"));
method = overload;
}
}
return method;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl()
*/
@Override
protected String getScriptUrl()
{
// NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat
String requestURI = req.getRequestURI();
String pathInfo = requestURI.substring((req.getContextPath() + req.getServletPath()).length());
try
{
return URLDecoder.decode(pathInfo, "UTF-8");
}
catch(UnsupportedEncodingException e)
{
throw new WebScriptException("Failed to retrieve path info", e);
}
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
*/
@Override
protected WebScriptRequest createRequest(WebScriptMatch match)
{
return new WebScriptServletRequest(serverConfig, req, match);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#createResponse()
*/
@Override
protected WebScriptResponse createResponse()
{
return new WebScriptServletResponse(res);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRuntime#authenticate(org.alfresco.web.scripts.WebScriptDescription.RequiredAuthentication, boolean)
*/
@Override
protected boolean authenticate(RequiredAuthentication required, boolean isGuest, WebScriptRequest req, WebScriptResponse res)
{
boolean authorised = true;
if (authenticator != null)
{
authorised = authenticator.authenticate(required, isGuest, (WebScriptServletRequest)req, (WebScriptServletResponse)res);
}
return authorised;
}
}

View File

@@ -0,0 +1,178 @@
/*
* 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.scripts;
import javax.servlet.http.HttpServletResponse;
import org.alfresco.i18n.I18NUtil;
/**
* Web Script Status
*
* Records the outcome of a Web Script.
*
* @author davidc
*/
public class WebScriptStatus
{
private Throwable exception = null;
private int code = HttpServletResponse.SC_OK;
private String message = "";
private boolean redirect = false;
/**
* @param exception
*/
public void setException(Throwable exception)
{
this.exception = exception;
}
/**
* @return exception
*/
public Throwable getException()
{
return exception;
}
public Throwable jsGet_exception()
{
return getException();
}
/**
* @param message
*/
public void setMessage(String message)
{
this.message = message;
}
public void jsSet_message(String message)
{
setMessage(message);
}
/**
* @return message
*/
public String getMessage()
{
return message;
}
public String jsGet_message()
{
return getMessage();
}
/**
* @param redirect redirect to status code response
*/
public void setRedirect(boolean redirect)
{
this.redirect = redirect;
}
public void jsSet_redirect(boolean redirect)
{
setRedirect(redirect);
}
/**
* @return redirect to status code response
*/
public boolean getRedirect()
{
return redirect;
}
public boolean jsGet_redirect()
{
return getRedirect();
}
/**
* @see javax.servlet.http.HTTPServletResponse
*
* @param code status code
*/
public void setCode(int code)
{
this.code = code;
}
public void jsSet_code(int code)
{
this.code = code;
}
/**
* @return status code
*/
public int getCode()
{
return code;
}
public int jsGet_code()
{
return getCode();
}
/**
* Gets the short name of the status code
*
* @return status code name
*/
public String getCodeName()
{
return I18NUtil.getMessage("webscript.code." + code + ".name");
}
public String jsGet_codeName()
{
return getCodeName();
}
/**
* Gets the description of the status code
*
* @return status code description
*/
public String getCodeDescription()
{
return I18NUtil.getMessage("webscript.code." + code + ".description");
}
public String jsGet_codeDescription()
{
return getCodeDescription();
}
}

View File

@@ -0,0 +1,207 @@
/*
* 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.scripts;
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;
/**
* Web Script Storage
*
* @author davidc
*/
public class WebScriptStorage implements ApplicationContextAware, ApplicationListener
{
private ApplicationContext applicationContext;
private ProcessorLifecycle lifecycle = new ProcessorLifecycle();
private TemplateProcessor templateProcessor;
private ScriptProcessor scriptProcessor;
/* (non-Javadoc)
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
*/
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
{
this.applicationContext = applicationContext;
this.lifecycle.setApplicationContext(applicationContext);
}
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(ApplicationEvent event)
{
lifecycle.onApplicationEvent(event);
}
/**
* Sets the template processor
*
* @param templateProcessor
*/
public void setTemplateProcessor(TemplateProcessor templateProcessor)
{
this.templateProcessor = templateProcessor;
}
/**
* Sets the script processor
*
* @param scriptProcessor
*/
public void setScriptProcessor(ScriptProcessor scriptProcessor)
{
this.scriptProcessor = scriptProcessor;
}
/**
* Gets all Web Script Stores
*
* @return all Web Script Stores
*/
@SuppressWarnings("unchecked")
public Collection<WebScriptStore> getStores()
{
Collection<WebScriptStore> allstores = applicationContext.getBeansOfType(WebScriptStore.class, false, false).values();
Collection<WebScriptStore> stores = new ArrayList<WebScriptStore>();
for (WebScriptStore store : allstores)
{
if (store.exists())
{
stores.add(store);
}
}
return stores;
}
/**
* Gets the Web Script Store for the given Store path
*
* @param storePath
* @return store (or null, if not found)
*/
public WebScriptStore getStore(String storePath)
{
Collection<WebScriptStore> stores = getStores();
for (WebScriptStore store : stores)
{
if (store.getBasePath().equals(storePath))
{
return store;
}
}
return null;
}
/**
* Gets the Template Processor
*
* @return template processor
*/
public TemplateProcessor getTemplateProcessor()
{
return templateProcessor;
}
/**
* Gets the Script Processor
*
* @return script processor
*/
public ScriptProcessor getScriptProcessor()
{
return scriptProcessor;
}
/**
* Register template loader from each Web Script Store with Template Processor
*/
protected void initTemplateProcessor()
{
List<TemplateLoader> loaders = new ArrayList<TemplateLoader>();
for (WebScriptStore apiStore : getStores())
{
TemplateLoader loader = apiStore.getTemplateLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve template loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiTemplateLoader loader = new MultiTemplateLoader(loaders.toArray(new TemplateLoader[loaders.size()]));
templateProcessor.setTemplateLoader(loader);
}
/**
* Register script loader from each Web Script Store with Script Processor
*/
protected void initScriptProcessor()
{
List<ScriptLoader> loaders = new ArrayList<ScriptLoader>();
for (WebScriptStore apiStore : getStores())
{
ScriptLoader loader = apiStore.getScriptLoader();
if (loader == null)
{
throw new WebScriptException("Unable to retrieve script loader for Web Script store " + apiStore.getBasePath());
}
loaders.add(loader);
}
MultiScriptLoader loader = new MultiScriptLoader(loaders.toArray(new ScriptLoader[loaders.size()]));
scriptProcessor.setScriptLoader(loader);
}
/**
* Hooks into Spring Application Lifecycle
*/
private class ProcessorLifecycle extends AbstractLifecycleBean
{
@Override
protected void onBootstrap(ApplicationEvent event)
{
initTemplateProcessor();
initScriptProcessor();
}
@Override
protected void onShutdown(ApplicationEvent event)
{
}
}
}

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.scripts;
import java.io.IOException;
import java.io.InputStream;
import freemarker.cache.TemplateLoader;
/**
* Store for holding Web Script Definitions and Implementations
*
* @author davidc
*/
public interface WebScriptStore
{
/**
* Determines whether the store actually exists
*
* @return true => it does exist
*/
public boolean exists();
/**
* Gets the base path of the store
*
* @return base path
*/
public String getBasePath();
/**
* Gets the paths of all Web Script description documents in this store
*
* @return array of description document paths
*/
public String[] getDescriptionDocumentPaths();
/**
* Gets the paths of all implementation files for a given Web Script
*
* @param script web script
* @return array of implementation document paths
*/
public String[] getScriptDocumentPaths(WebScript script);
/**
* Determines if the document exists
*
* @param documentPath document path
* @return true => exists, false => does not exist
*/
public boolean hasDocument(String documentPath);
/**
* Gets a document
*
* @param documentPath document path
* @return input stream onto document
*
* @throws IOException
*/
public InputStream getDocument(String documentPath)
throws IOException;
/**
* Creates a document
*
* @param documentPath
* @param content
*
* @throws IOException
*/
public void createDocument(String documentPath, String content)
throws IOException;
/**
* Gets the template loader for this store
*
* @return template loader
*/
public TemplateLoader getTemplateLoader();
/**
* Gets the script loader for this store
*
* @return script loader
*/
public ScriptLoader getScriptLoader();
}

View File

@@ -0,0 +1,248 @@
/*
* 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.scripts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Web Script Request implementation that acts upon a string representation
* of a URL
*
* @author davidc
*/
public abstract class WebScriptURLRequest extends WebScriptRequestImpl
{
/** Script Url components */
protected String contextPath;
protected String servletPath;
protected String pathInfo;
protected String queryString;
protected Map<String, String> queryArgs;
protected Map<String, List<String>> queryArgsMulti;
/** Service bound to this request */
protected WebScriptMatch serviceMatch;
/**
* Splits a Web Script Url into its component parts
*
* @param scriptUrl url e.g. /alfresco/service/mytasks?f=1
* @return url parts [0] = context (e.g. alfresco), [1] = servlet (e.g. service), [2] = script (e.g. mytasks), [3] = args (e.g. f=1)
*/
public static String[] splitURL(String scriptUrl)
{
String[] urlParts = new String[4];
String path;
String queryString;
int argsIndex = scriptUrl.indexOf("?");
if (argsIndex != -1)
{
path = scriptUrl.substring(0, argsIndex);
queryString = scriptUrl.substring(argsIndex + 1);
}
else
{
path = scriptUrl;
queryString = null;
}
String[] pathSegments = path.split("/");
String pathInfo = "";
for (int i = 3; i < pathSegments.length; i++)
{
pathInfo += "/" + pathSegments[i];
}
urlParts[0] = "/" + pathSegments[1]; // context path
urlParts[1] = "/" + pathSegments[2]; // servlet path
urlParts[2] = pathInfo; // path info
urlParts[3] = queryString; // query string
return urlParts;
}
/**
* Construct
*
* @param scriptUrl
* @param serviceMatch
*/
public WebScriptURLRequest(String scriptUrl, WebScriptMatch serviceMatch)
{
this(splitURL(scriptUrl), serviceMatch);
}
/**
* Construct
*
* @param scriptUrlParts
* @param serviceMatch
*/
public WebScriptURLRequest(String[] scriptUrlParts, WebScriptMatch serviceMatch)
{
this.contextPath = scriptUrlParts[0];
this.servletPath = scriptUrlParts[1];
this.pathInfo = scriptUrlParts[2];
this.queryString = scriptUrlParts[3];
this.queryArgs = new HashMap<String, String>();
this.queryArgsMulti = new HashMap<String, List<String>>();
if (this.queryString != null)
{
String[] args = this.queryString.split("&");
for (String arg : args)
{
String[] parts = arg.split("=");
if (this.queryArgs.containsKey(parts[0]))
{
List<String> values = this.queryArgsMulti.get(parts[0]);
if (values == null)
{
values = new ArrayList<String>();
this.queryArgsMulti.put(parts[0], values);
}
values.add(parts.length == 2 ? parts[1] : "");
}
else
{
this.queryArgs.put(parts[0], parts.length == 2 ? parts[1] : "");
}
}
}
this.serviceMatch = serviceMatch;
}
@Override
public String toString()
{
return "Request Service Match: " + serviceMatch +
" URL: " + this.contextPath + this.servletPath + this.pathInfo + "?" + queryString;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceMatch()
*/
public WebScriptMatch getServiceMatch()
{
return serviceMatch;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getContextPath()
*/
public String getContextPath()
{
return contextPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath()
*/
public String getServiceContextPath()
{
return getContextPath() + servletPath;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getServicePath()
*/
public String getServicePath()
{
return getServiceContextPath() + pathInfo;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getURL()
*/
public String getURL()
{
return getServicePath() + (queryString != null ? "?" + queryString : "");
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo()
*/
public String getPathInfo()
{
return pathInfo;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getQueryString()
*/
public String getQueryString()
{
return queryString;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameterNames()
*/
public String[] getParameterNames()
{
Set<String> keys = queryArgs.keySet();
String[] names = new String[keys.size()];
keys.toArray(names);
return names;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getParameter(java.lang.String)
*/
public String getParameter(String name)
{
return queryArgs.get(name);
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScriptRequest#getArrayParameter(java.lang.String)
*/
public String[] getParameterValues(String name)
{
List<String> values = queryArgsMulti.get(name);
if (values != null)
{
String[] array = new String[values.size()];
values.toArray(array);
return array;
}
else
{
String value = queryArgs.get(name);
if (value != null)
{
return new String[]{value};
}
}
return null;
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.IOException;
import java.net.SocketException;
@@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.repo.web.scripts.Repository;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentService;
@@ -46,12 +45,12 @@ import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.Cache;
import org.alfresco.web.scripts.WebScriptCache;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.servlet.WebScriptServletRequest;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptServletRequest;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -68,62 +67,6 @@ public class ContentGet extends AbstractWebScript
// Logger
private static final Log logger = LogFactory.getLog(ContentGet.class);
// Component dependencies
private Repository repository;
private NamespaceService namespaceService;
private PermissionService permissionService;
private NodeService nodeService;
private ContentService contentService;
private MimetypeService mimetypeService;
/**
* @param repository
*/
public void setRepository(Repository repository)
{
this.repository = repository;
}
/**
* @param namespaceService
*/
public void setNamespaceService(NamespaceService namespaceService)
{
this.namespaceService = namespaceService;
}
/**
* @param permissionService
*/
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* @param nodeService
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
/**
* @param contentService
*/
public void setContentService(ContentService contentService)
{
this.contentService = contentService;
}
/**
* @param mimetypeService
*/
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.WebScript#execute(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
@@ -146,7 +89,7 @@ public class ContentGet extends AbstractWebScript
String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/");
String[] path = new String[extParts.length -1];
System.arraycopy(extParts, 1, path, 0, extParts.length -1);
NodeRef nodeRef = repository.findNodeRef(matchParts[2], path);
NodeRef nodeRef = findNodeRef(matchParts[2], path);
if (nodeRef == null)
{
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find " + matchParts[2] + " reference " + Arrays.toString(path));
@@ -164,6 +107,7 @@ public class ContentGet extends AbstractWebScript
String propertyName = contentPart.substring(1);
if (propertyName.length() > 0)
{
NamespaceService namespaceService = getServiceRegistry().getNamespaceService();
propertyQName = QName.createQName(propertyName, namespaceService);
}
}
@@ -175,12 +119,14 @@ public class ContentGet extends AbstractWebScript
logger.debug("Retrieving content from node ref " + nodeRef.toString() + " (property: " + propertyQName.toString() + ") (attach: " + attach + ")");
// check that the user has at least READ_CONTENT access - else redirect to the login page
PermissionService permissionService = getServiceRegistry().getPermissionService();
if (permissionService.hasPermission(nodeRef, PermissionService.READ_CONTENT) == AccessStatus.DENIED)
{
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Permission denied");
}
// check If-Modified-Since header and set Last-Modified header as appropriate
NodeService nodeService = getServiceRegistry().getNodeService();
Date modified = (Date)nodeService.getProperty(nodeRef, ContentModel.PROP_MODIFIED);
long modifiedSince = httpReq.getDateHeader("If-Modified-Since");
if (modifiedSince > 0L)
@@ -203,6 +149,7 @@ public class ContentGet extends AbstractWebScript
}
// get the content reader
ContentService contentService = getServiceRegistry().getContentService();
ContentReader reader = contentService.getReader(nodeRef, propertyQName);
if (reader == null || !reader.exists())
{
@@ -213,12 +160,13 @@ public class ContentGet extends AbstractWebScript
String mimetype = reader.getMimetype();
if (mimetype == null || mimetype.length() == 0)
{
MimetypeService mimetypeMap = getServiceRegistry().getMimetypeService();
mimetype = MimetypeMap.MIMETYPE_BINARY;
int extIndex = extensionPath.lastIndexOf('.');
if (extIndex != -1)
{
String ext = extensionPath.substring(extIndex + 1);
String mt = mimetypeService.getMimetypesByExtension().get(ext);
String mt = mimetypeMap.getMimetypesByExtension().get(ext);
if (mt != null)
{
mimetype = mt;
@@ -232,7 +180,7 @@ public class ContentGet extends AbstractWebScript
httpRes.setHeader("Content-Length", Long.toString(reader.getSize()));
// set caching
Cache cache = new Cache();
WebScriptCache cache = new WebScriptCache();
cache.setNeverCache(false);
cache.setMustRevalidate(true);
cache.setLastModified(modified);

View File

@@ -0,0 +1,56 @@
/*
* 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.scripts.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of all Web Scripts
*
* @author davidc
*/
public class Index extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("webscripts", getWebScriptRegistry().getWebScripts());
model.put("rooturl", getWebScriptRegistry().getUri("/"));
model.put("rootpackage", getWebScriptRegistry().getPackage("/"));
return model;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.scripts.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptPath;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of a Web Script Package
*
* @author davidc
*/
public class IndexPackage extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script package
String packagePath = req.getExtensionPath();
if (packagePath == null || packagePath.length() == 0)
{
packagePath = "/";
}
if (!packagePath.startsWith("/"))
{
packagePath = "/" + packagePath;
}
// locate web script package
WebScriptPath path = getWebScriptRegistry().getPackage(packagePath);
if (path == null)
{
throw new WebScriptException("Web Script Package '" + packagePath + "' not found");
}
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("package", path);
return model;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.scripts.bean;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptPath;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
* Index of a Web Script URI
*
* @author davidc
*/
public class IndexURI extends DeclarativeWebScript
{
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script package
String uriPath = req.getExtensionPath();
if (uriPath == null || uriPath.length() == 0)
{
uriPath = "/";
}
if (!uriPath.startsWith("/"))
{
uriPath = "/" + uriPath;
}
// locate web script package
WebScriptPath path = getWebScriptRegistry().getUri(uriPath);
if (path == null)
{
throw new WebScriptException("Web Script URI '" + uriPath + "' not found");
}
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("uri", path);
return model;
}
}

View File

@@ -0,0 +1,90 @@
/*
* 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.scripts.bean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.alfresco.web.scripts.facebook.FacebookService;
/**
* Retrieves the list of available Web Scripts
*
* @author davidc
*/
public class IndexUpdate extends DeclarativeWebScript
{
// component dependencies
private FacebookService facebookService;
/**
* @param facebookService facebook service
*/
public void setFacebookService(FacebookService facebookService)
{
this.facebookService = facebookService;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
List<String> tasks = new ArrayList<String>();
// reset index
String reset = req.getParameter("reset");
if (reset != null && reset.equals("on"))
{
// reset list of web scripts
int previousCount = getWebScriptRegistry().getWebScripts().size();
getWebScriptRegistry().reset();
tasks.add("Reset Web Scripts Registry; found " + getWebScriptRegistry().getWebScripts().size() + " Web Scripts. Previously, there were " + previousCount + ".");
// reset facebook service
// TODO: Determine more appropriate place to put this
int appCount = facebookService.getAppModels().size();
if (appCount > 0)
{
facebookService.reset();
tasks.add("Reset " + appCount + " Facebook Applications.");
}
}
// create model for rendering
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
model.put("tasks", tasks);
model.put("webscripts", getWebScriptRegistry().getWebScripts());
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.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.Map;
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -56,7 +56,7 @@ public class JavascriptDebugger extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// construct model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -30,7 +30,7 @@ import java.util.Map;
import org.alfresco.repo.jscript.AlfrescoRhinoScriptDebugger;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -56,7 +56,7 @@ public class JavascriptDebuggerPost extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
String visibleStr = req.getParameter("visible");
boolean visible = Boolean.valueOf(visibleStr);

View File

@@ -22,12 +22,10 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
@@ -35,23 +33,20 @@ import java.util.Map;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.template.TemplateNode;
import org.alfresco.repo.web.scripts.RepositoryImageResolver;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.repository.TemplateException;
import org.alfresco.service.cmr.search.ResultSet;
import org.alfresco.service.cmr.search.SearchParameters;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.URLEncoder;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
/**
@@ -71,8 +66,6 @@ public class KeywordSearch extends DeclarativeWebScript
protected static final String QUERY_FORMAT = "query_";
// dependencies
protected ServiceRegistry serviceRegistry;
protected RepositoryImageResolver imageResolver;
protected SearchService searchService;
/**
@@ -83,27 +76,11 @@ public class KeywordSearch extends DeclarativeWebScript
this.searchService = searchService;
}
/**
* @param imageResolver
*/
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
{
this.imageResolver = imageResolver;
}
/**
* @param serviceRegistry
*/
public void setServiceRegistry(ServiceRegistry serviceRegistry)
{
this.serviceRegistry = serviceRegistry;
}
/* (non-Javadoc)
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
//
// process arguments
@@ -389,7 +366,7 @@ public class KeywordSearch extends DeclarativeWebScript
*/
public SearchTemplateNode(NodeRef nodeRef, float score)
{
super(nodeRef, serviceRegistry, KeywordSearch.this.imageResolver.getImageResolver());
super(nodeRef, getServiceRegistry(), getWebScriptRegistry().getTemplateImageResolver());
this.score = score;
}
@@ -409,19 +386,11 @@ public class KeywordSearch extends DeclarativeWebScript
@Override
public String getUrl()
{
try
{
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
StringUtils.replace(URLEncoder.encode(getName(), "UTF-8"), "+", "%20") } );
}
catch (UnsupportedEncodingException err)
{
throw new TemplateException("Failed to encode content URL for node: " + getNodeRef(), err);
}
return MessageFormat.format(URL, new Object[] {
getNodeRef().getStoreRef().getProtocol(),
getNodeRef().getStoreRef().getIdentifier(),
getNodeRef().getId(),
URLEncoder.encode(getName()) } );
}
}
}

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -32,9 +32,9 @@ import javax.servlet.http.HttpServletResponse;
import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -60,7 +60,7 @@ public class Login extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract username and password
String username = req.getParameter("u");

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -33,9 +33,9 @@ import org.alfresco.repo.security.authentication.AuthenticationException;
import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.TicketComponent;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -61,7 +61,7 @@ public class LoginTicket extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// retrieve ticket from request and current ticket
String ticket = req.getExtensionPath();

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.Map;
@@ -34,9 +34,9 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil;
import org.alfresco.repo.security.authentication.TicketComponent;
import org.alfresco.service.cmr.security.AuthenticationService;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
/**
@@ -71,7 +71,7 @@ public class LoginTicketDelete extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// retrieve ticket from request and current ticket
String ticket = req.getExtensionPath();

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.util.HashMap;
import java.util.HashSet;
@@ -35,8 +35,8 @@ import org.alfresco.i18n.I18NUtil;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.config.OpenSearchConfigElement;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.Status;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -80,7 +80,7 @@ public class SearchEngines extends DeclarativeWebScript
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
*/
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
String urlType = req.getParameter("type");
if (urlType == null || urlType.length() == 0)

View File

@@ -22,7 +22,7 @@
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.web.scripts.bean;
package org.alfresco.web.scripts.bean;
import java.io.IOException;
import java.io.InputStream;
@@ -47,7 +47,7 @@ import org.alfresco.web.scripts.FormatRegistry;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
import org.alfresco.web.scripts.servlet.WebScriptServletResponse;
import org.alfresco.web.scripts.WebScriptServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.web.scripts.bean;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.web.scripts.AbstractWebScript;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptDescription;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptResponse;
/**
* Retrieves a Web Script Description Document
*
* @author davidc
*/
public class ServiceDescription extends AbstractWebScript
{
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
{
// extract web script id
String scriptId = req.getExtensionPath();
if (scriptId == null || scriptId.length() == 0)
{
throw new WebScriptException("Web Script Id not provided");
}
// locate web script
WebScript script = getWebScriptRegistry().getWebScript(scriptId);
if (script == null)
{
throw new WebScriptException("Web Script Id '" + scriptId + "' not found");
}
// retrieve description document
WebScriptDescription desc = script.getDescription();
InputStream serviceDescIS = null;
try
{
serviceDescIS = desc.getDescDocument();
OutputStream out = res.getOutputStream();
res.setContentType(MimetypeMap.MIMETYPE_XML + ";charset=UTF-8");
byte[] buffer = new byte[2048];
int read = serviceDescIS.read(buffer);
while (read != -1)
{
out.write(buffer, 0, read);
read = serviceDescIS.read(buffer);
}
}
catch(IOException e)
{
throw new WebScriptException("Failed to read Web Script description document for '" + scriptId + "'", e);
}
finally
{
try
{
if (serviceDescIS != null) serviceDescIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
}
}

View File

@@ -0,0 +1,192 @@
/*
* 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.scripts.bean;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.alfresco.web.scripts.DeclarativeWebScript;
import org.alfresco.web.scripts.WebScript;
import org.alfresco.web.scripts.WebScriptException;
import org.alfresco.web.scripts.WebScriptRequest;
import org.alfresco.web.scripts.WebScriptStatus;
import org.alfresco.web.scripts.WebScriptStorage;
import org.alfresco.web.scripts.WebScriptStore;
/**
* Dumps everything known about the specified Web Script
*
* @author davidc
*/
public class ServiceDump extends DeclarativeWebScript
{
private WebScriptStorage storage;
public void setStorage(WebScriptStorage storage)
{
this.storage = storage;
}
@Override
protected Map<String, Object> executeImpl(WebScriptRequest req, WebScriptStatus status)
{
// extract web script id
String scriptId = req.getExtensionPath();
if (scriptId == null || scriptId.length() == 0)
{
throw new WebScriptException("Web Script Id not provided");
}
// locate web script
WebScript script = getWebScriptRegistry().getWebScript(scriptId);
if (script == null)
{
throw new WebScriptException("Web Script Id '" + scriptId + "' not found");
}
// construct model
Map<String, Object> model = new HashMap<String, Object>(7, 1.0f);
Map<String, String> implPaths = new HashMap<String, String>();
List<Store> modelStores = new ArrayList<Store>();
model.put("script", script.getDescription());
model.put("script_class", script.getClass().toString());
model.put("stores", modelStores);
// locate web script stores
Collection<WebScriptStore> stores = storage.getStores();
for (WebScriptStore store : stores)
{
Store modelStore = new Store();
modelStore.path = store.getBasePath();
// locate script implementation files
String[] scriptPaths = store.getScriptDocumentPaths(script);
for (String scriptPath : scriptPaths)
{
Implementation impl = new Implementation();
impl.path = scriptPath;
impl.overridden = implPaths.containsKey(scriptPath);
// extract implementation content
InputStream documentIS = null;
try
{
documentIS = store.getDocument(scriptPath);
InputStreamReader isReader = new InputStreamReader(documentIS);
StringWriter stringWriter = new StringWriter();
char[] buffer = new char[2048];
int read = isReader.read(buffer);
while (read != -1)
{
stringWriter.write(buffer, 0, read);
read = isReader.read(buffer);
}
impl.content = stringWriter.toString();
}
catch(IOException e)
{
impl.throwable = e;
}
finally
{
try
{
if (documentIS != null) documentIS.close();
}
catch(IOException e)
{
// NOTE: ignore close exception
}
}
// record web script implementation file against store
modelStore.files.add(impl);
}
// record store in list of stores
modelStores.add(modelStore);
}
return model;
}
public static class Store
{
private String path;
private Collection<Implementation> files = new ArrayList<Implementation>();
public String getPath()
{
return path;
}
public Collection<Implementation> getFiles()
{
return files;
}
}
public static class Implementation
{
private String path;
private boolean overridden;
private String content;
private Exception throwable;
public String getPath()
{
return path;
}
public String getContent()
{
return content;
}
public boolean getOverridden()
{
return overridden;
}
public Throwable getException()
{
return throwable;
}
}
}

Some files were not shown because too many files have changed in this diff Show More