mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moved remote-api master into its own directory
This commit is contained in:
154
remote-api/src/main/antlr3/org/alfresco/rest/antlr/WhereClause.g
Normal file
154
remote-api/src/main/antlr3/org/alfresco/rest/antlr/WhereClause.g
Normal file
@@ -0,0 +1,154 @@
|
||||
grammar WhereClause;
|
||||
|
||||
options
|
||||
{
|
||||
// antlr will generate java lexer and parser
|
||||
language = Java;
|
||||
// generated parser should create abstract syntax tree
|
||||
output = AST;
|
||||
}
|
||||
|
||||
//package, we have to add package declaration on top of it
|
||||
@lexer::header {
|
||||
package org.alfresco.rest.antlr;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.WhereCompiler;
|
||||
}
|
||||
|
||||
@lexer::members {
|
||||
|
||||
@Override
|
||||
public void recover(RecognitionException e)
|
||||
{
|
||||
throw new InvalidQueryException(WhereCompiler.resolveMessage(e));
|
||||
}
|
||||
}
|
||||
//package, we have to add package declaration on top of it
|
||||
@parser::header {
|
||||
package org.alfresco.rest.antlr;
|
||||
import org.alfresco.rest.framework.resource.parameters.where.InvalidQueryException;
|
||||
}
|
||||
|
||||
@parser::members {
|
||||
|
||||
// These methods are here to force the parser to error instead of suppressing problems.
|
||||
// @Override
|
||||
// public void reportError(RecognitionException e) {
|
||||
// System.out.println("CUSTOM ERROR...\n" + e);
|
||||
// throw new InvalidQueryException(e.getMessage());
|
||||
// }
|
||||
|
||||
@Override
|
||||
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException
|
||||
{
|
||||
throw new MismatchedTokenException(ttype, input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object recoverFromMismatchedSet(IntStream input, RecognitionException e, BitSet follow) throws RecognitionException
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
//
|
||||
// @Override
|
||||
// public String getErrorMessage(RecognitionException e, String[] tokenNames)
|
||||
// {
|
||||
// System.out.println("THROW ME...\n" + e);
|
||||
// throw new InvalidQueryException(e.getMessage());
|
||||
// }
|
||||
// End of methods here to force the parser to error instead of supressing problems.
|
||||
}
|
||||
|
||||
@rulecatch
|
||||
{
|
||||
catch(RecognitionException e)
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
// ***************** lexer rules:
|
||||
NEGATION: ('not'|'NOT')WS;
|
||||
EXISTS: 'exists'|'EXISTS';
|
||||
IN: WS('in'|'IN');
|
||||
MATCHES: WS('matches'|'MATCHES');
|
||||
BETWEEN: WS('between'|'BETWEEN');
|
||||
OR: WS('or'|'OR')WS;
|
||||
AND: WS('and'|'AND')WS;
|
||||
EQUALS: WS?'='WS?;
|
||||
LESSTHAN: WS?'<'WS?;
|
||||
GREATERTHAN: WS?'>'WS?;
|
||||
LESSTHANOREQUALS: WS?'<='WS?;
|
||||
GREATERTHANOREQUALS: WS?'>='WS?;
|
||||
LEFTPAREN: '(';
|
||||
RIGHTPAREN: ')';
|
||||
COMMA: ',';
|
||||
COLON: ':';
|
||||
SINGLEQUOTE: '\'';
|
||||
PROPERTYVALUE: (SINGLEQUOTE (~SINGLEQUOTE|'\\'SINGLEQUOTE)* SINGLEQUOTE) |IDENTIFIERDIGIT+;
|
||||
PROPERTYNAME: '/'? IDENTIFIER ('/'IDENTIFIER)*;
|
||||
fragment IDENTIFIERLETTERORDIGIT: (IDENTIFIERLETTER | IDENTIFIERDIGIT);
|
||||
fragment IDENTIFIER : (IDENTIFIERLETTER (IDENTIFIERLETTERORDIGIT* | (IDENTIFIERLETTERORDIGIT* COLON IDENTIFIERLETTERORDIGIT*)));
|
||||
WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; };
|
||||
fragment IDENTIFIERLETTER // any Unicode character that is a Java letter (see below)
|
||||
: '\u0041'..'\u005a' // A-Z
|
||||
| '\u005f' // _
|
||||
| '\u0061'..'\u007a' // a-z
|
||||
| '\u00c0'..'\u00d6' // À-Ö
|
||||
| '\u00d8'..'\u00f6' // Ø-ö
|
||||
| '\u00f8'..'\u00ff' // ø-ÿ
|
||||
| '\u0100'..'\u1fff'
|
||||
| '\u3040'..'\u318f'
|
||||
| '\u3300'..'\u337f'
|
||||
| '\u3400'..'\u3d2d'
|
||||
| '\u4e00'..'\u9fff'
|
||||
| '\uf900'..'\ufaff'
|
||||
;
|
||||
fragment IDENTIFIERDIGIT
|
||||
: '\u0030'..'\u0039' // 0-9
|
||||
| '\u0660'..'\u0669' // Arabic 0-9
|
||||
| '\u06f0'..'\u06f9' // Arabic-Indic 0-9
|
||||
| '\u0966'..'\u096f' // Devanagari 0-9
|
||||
| '\u09e6'..'\u09ef' // Bengali 0-9
|
||||
| '\u0a66'..'\u0a6f' // Gurmukhi 0-9
|
||||
| '\u0ae6'..'\u0aef' // Gujarati 0-9
|
||||
| '\u0b66'..'\u0b6f' // Oriya 0-9
|
||||
| '\u0be7'..'\u0bef' // Tamil 0-9
|
||||
| '\u0c66'..'\u0c6f' // Telugu 0-9
|
||||
| '\u0ce6'..'\u0cef' // Kannada 0-9
|
||||
| '\u0d66'..'\u0d6f' // Malayalam 0-9
|
||||
| '\u0e50'..'\u0e59' // Thai 0-9
|
||||
| '\u0ed0'..'\u0ed9' // Lao 0-9
|
||||
| '\u1040'..'\u1049' // Myanmar 0-9
|
||||
;
|
||||
|
||||
// ***************** parser rules:
|
||||
whereclause : WS? LEFTPAREN! WS? predicate RIGHTPAREN! WS?;
|
||||
predicate : simplepredicate
|
||||
| simplepredicate (AND simplepredicate)+ -> ^(AND simplepredicate+)
|
||||
| simplepredicate (OR simplepredicate)+ -> ^(OR simplepredicate+);
|
||||
simplepredicate : allowedpredicates -> allowedpredicates
|
||||
| NEGATION allowedpredicates -> ^(NEGATION allowedpredicates);
|
||||
allowedpredicates : comparisonpredicate | existspredicate | betweenpredicate | inpredicate | matchespredicate;
|
||||
comparisonpredicate: PROPERTYNAME comparisonoperator value -> ^(comparisonoperator PROPERTYNAME value);
|
||||
comparisonoperator: EQUALS|LESSTHAN|GREATERTHAN|LESSTHANOREQUALS|GREATERTHANOREQUALS;
|
||||
existspredicate: EXISTS LEFTPAREN WS? PROPERTYNAME RIGHTPAREN -> ^(EXISTS PROPERTYNAME);
|
||||
betweenpredicate: PROPERTYNAME BETWEEN LEFTPAREN WS? propertyvaluepair RIGHTPAREN -> ^(BETWEEN PROPERTYNAME propertyvaluepair);
|
||||
inpredicate: PROPERTYNAME IN LEFTPAREN WS? propertyvaluelist RIGHTPAREN -> ^(IN PROPERTYNAME propertyvaluelist);
|
||||
matchespredicate: PROPERTYNAME MATCHES LEFTPAREN WS? value RIGHTPAREN -> ^(MATCHES PROPERTYNAME value);
|
||||
propertyvaluepair: value COMMA value -> value+;
|
||||
propertyvaluelist: value (COMMA value)* -> value+;
|
||||
value: a=PROPERTYVALUE -> ^(PROPERTYVALUE[$a] )
|
||||
| b=PROPERTYNAME -> ^(PROPERTYVALUE[$b] ); //rewrite this a propertyvalue
|
||||
selectClause: PROPERTYNAME (COMMA PROPERTYNAME)* -> PROPERTYNAME+;
|
||||
// ****
|
||||
// SOME NOTES
|
||||
// () - Parentheses. Used to group several elements, so they are treated as one single token
|
||||
// ? - Any token followed by ? occurs 0 or 1 times
|
||||
// * - Any token followed by * can occur 0 or more times
|
||||
// + - Any token followed by + can occur 1 or more times
|
||||
// . - Any character/token can occur one time
|
||||
// ~ - Any character/token following the ~ may not occur at the current place
|
||||
// .. - Between two characters .. spans a range which accepts every character between both boundaries inclusive
|
||||
// ****
|
33
remote-api/src/main/apptest/apptest.readme.txt
Normal file
33
remote-api/src/main/apptest/apptest.readme.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
AppClientTest is a tool for testing an AtomPub Service.
|
||||
|
||||
http://code.google.com/p/feedvalidator/wiki/AppClientTest
|
||||
|
||||
1) To install and test installation...
|
||||
|
||||
$ svn co http://feedvalidator.googlecode.com/svn/trunk/apptestsuite/client/validator/ validator
|
||||
$ python validator/appclienttest.py --output=results.html "http://bitworking.org/projects/apptestsite/app.cgi/service/;service_document"
|
||||
$ firefox results.html
|
||||
|
||||
The above has been encapsulated in...
|
||||
|
||||
/projects/remote-api/source/test/apptest/install.sh
|
||||
|
||||
2) To execute appclienttest against Alfresco
|
||||
|
||||
/projects/remote-api/source/test/apptest/test.sh
|
||||
|
||||
|
||||
3) Note: appclienttest.py arguments...
|
||||
|
||||
-h, --help show this help message and exit
|
||||
--credentials=FILE FILE that contains a name and password on separate lines
|
||||
with an optional third line with the authentication type
|
||||
of 'ClientLogin <service>'.
|
||||
--output=FILE FILE to store test results
|
||||
--verbose Print extra information while running.
|
||||
--quiet Do not print anything while running.
|
||||
--debug Print low level HTTP information while running.
|
||||
--html Output is formatted in HTML
|
||||
--record=DIR Record all the responses to be used later in playback
|
||||
mode.
|
||||
--playback=DIR Playback responses stored from a previous run.
|
2
remote-api/src/main/apptest/credentials.txt
Normal file
2
remote-api/src/main/apptest/credentials.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
admin
|
||||
admin
|
5
remote-api/src/main/apptest/install.sh
Normal file
5
remote-api/src/main/apptest/install.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
# ! /bin/sh
|
||||
|
||||
svn co http://feedvalidator.googlecode.com/svn/trunk/apptestsuite/client/validator/ validator
|
||||
python validator/appclienttest.py --html --verbose --output=results.html "http://bitworking.org/projects/apptestsite/app.cgi/service/;service_document"
|
||||
open results.html
|
2963
remote-api/src/main/apptest/results.html
Normal file
2963
remote-api/src/main/apptest/results.html
Normal file
File diff suppressed because it is too large
Load Diff
4
remote-api/src/main/apptest/test.sh
Normal file
4
remote-api/src/main/apptest/test.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
# ! /bin/sh
|
||||
|
||||
python validator/appclienttest.py --html --credentials=credentials.txt --verbose --output=results.html "http://localhost:8080/alfresco/service/api/repository"
|
||||
open results.html
|
24
remote-api/src/main/generated/WhereClause.tokens
Normal file
24
remote-api/src/main/generated/WhereClause.tokens
Normal file
@@ -0,0 +1,24 @@
|
||||
AND=4
|
||||
BETWEEN=5
|
||||
COLON=6
|
||||
COMMA=7
|
||||
EQUALS=8
|
||||
EXISTS=9
|
||||
GREATERTHAN=10
|
||||
GREATERTHANOREQUALS=11
|
||||
IDENTIFIER=12
|
||||
IDENTIFIERDIGIT=13
|
||||
IDENTIFIERLETTER=14
|
||||
IDENTIFIERLETTERORDIGIT=15
|
||||
IN=16
|
||||
LEFTPAREN=17
|
||||
LESSTHAN=18
|
||||
LESSTHANOREQUALS=19
|
||||
MATCHES=20
|
||||
NEGATION=21
|
||||
OR=22
|
||||
PROPERTYNAME=23
|
||||
PROPERTYVALUE=24
|
||||
RIGHTPAREN=25
|
||||
SINGLEQUOTE=26
|
||||
WS=27
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Repository
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.heartbeat;
|
||||
|
||||
import org.alfresco.heartbeat.datasender.HBData;
|
||||
import org.alfresco.heartbeat.jobs.HeartBeatJobScheduler;
|
||||
import org.alfresco.repo.descriptor.DescriptorDAO;
|
||||
import org.alfresco.repo.thumbnail.ThumbnailDefinition;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* This class collects rendition request counts for HeartBeat. A rendition (such as "doclib") is always to the same
|
||||
* target mimetype, but there may be different source mimetypes. As a result that may be multiple sets of data with
|
||||
* the same rendition. It is also likely there will be multiple renditions reported in the same batch of data.
|
||||
* <ul>
|
||||
* <li>Collector ID: <b>acs.repository.renditions</b></li>
|
||||
* <li>Data:
|
||||
* <ul>
|
||||
* <li><b>rendition:</b> String - The name of the rendition.</li>
|
||||
* <li><b>count:</b> Integer - The number of times a rendition and sourceMimetype combination has been requested.</li>
|
||||
* <li><b>sourceMimetype:</b> String - The source mimetype for the rendition.</li>
|
||||
* <li><b>targetMimetype:</b> String - The target mimetype for the rendition.</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* @author adavis
|
||||
*/
|
||||
public class RenditionsDataCollector extends HBBaseDataCollector implements InitializingBean
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(RenditionsDataCollector.class);
|
||||
|
||||
private DescriptorDAO currentRepoDescriptorDAO;
|
||||
|
||||
// Map keyed on rendition id to a Map keyed on source mimetypes to a count of the number of times it has been requested.
|
||||
private final Map<ThumbnailDefinition, Map<String, AtomicInteger>> renditionRequests = new ConcurrentHashMap<>();
|
||||
|
||||
public RenditionsDataCollector(String collectorId, String collectorVersion, String cronExpression,
|
||||
HeartBeatJobScheduler hbJobScheduler)
|
||||
{
|
||||
super(collectorId, collectorVersion, cronExpression, hbJobScheduler);
|
||||
}
|
||||
|
||||
public void setCurrentRepoDescriptorDAO(DescriptorDAO currentRepoDescriptorDAO)
|
||||
{
|
||||
this.currentRepoDescriptorDAO = currentRepoDescriptorDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
PropertyCheck.mandatory(this, "currentRepoDescriptorDAO", currentRepoDescriptorDAO);
|
||||
}
|
||||
|
||||
public void recordRenditionRequest(ThumbnailDefinition rendition, String sourceMimetype)
|
||||
{
|
||||
// Increment the count of renditions. Atomically creates missing parts of the Map structures.
|
||||
renditionRequests.computeIfAbsent(rendition,
|
||||
k -> new ConcurrentHashMap<>()).computeIfAbsent(sourceMimetype,
|
||||
k -> new AtomicInteger()).incrementAndGet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HBData> collectData()
|
||||
{
|
||||
List<HBData> collectedData = new LinkedList<>();
|
||||
|
||||
String systemId = this.currentRepoDescriptorDAO.getDescriptor().getId();
|
||||
String collectorId = this.getCollectorId();
|
||||
String collectorVersion = this.getCollectorVersion();
|
||||
Date timestamp = new Date();
|
||||
|
||||
// We don't mind if new renditions are added while we iterate, as we will pick them up next time.
|
||||
for (ThumbnailDefinition rendition : renditionRequests.keySet())
|
||||
{
|
||||
String renditionName = rendition.getName();
|
||||
String targetMimetype = rendition.getMimetype();
|
||||
for (Map.Entry<String, AtomicInteger> entry: renditionRequests.remove(rendition).entrySet())
|
||||
{
|
||||
String sourceMimetype = entry.getKey();
|
||||
AtomicInteger count = entry.getValue();
|
||||
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
values.put("rendition", renditionName);
|
||||
values.put("count", count.intValue());
|
||||
values.put("sourceMimetype", sourceMimetype);
|
||||
values.put("targetMimetype", targetMimetype);
|
||||
|
||||
// Decided it would be simpler to be able to combine results in Kibana from different nodes
|
||||
// and days if the data was flattened (denormalized) out at this point. It is very likely
|
||||
// that different nodes would have different sets of sourceMimetypes which would make summing
|
||||
// the counts harder to do, if there was a single entry for each rendition with a nested
|
||||
// structure for each sourceMimetype.
|
||||
collectedData.add(new HBData(systemId, collectorId, collectorVersion, timestamp, values));
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug(renditionName+" "+count+" "+sourceMimetype+" "+targetMimetype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return collectedData;
|
||||
}
|
||||
}
|
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS base url based on the request, repository id and binding.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractBaseUrlGenerator implements BaseUrlGenerator
|
||||
{
|
||||
private boolean overrideContext;
|
||||
private String contextOverride;
|
||||
private boolean overrideServletPath;
|
||||
private String servletPathOverride;
|
||||
private PathGenerator pathGenerator;
|
||||
|
||||
public void setPathGenerator(PathGenerator pathGenerator)
|
||||
{
|
||||
this.pathGenerator = pathGenerator;
|
||||
}
|
||||
|
||||
public void setOverrideContext(boolean overrideContext)
|
||||
{
|
||||
this.overrideContext = overrideContext;
|
||||
}
|
||||
|
||||
private String fixup(String urlSegment)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int beginIndex = 0;
|
||||
int endIndex = urlSegment.length();
|
||||
if(urlSegment != null)
|
||||
{
|
||||
if(!urlSegment.equals("") && !urlSegment.startsWith("/"))
|
||||
{
|
||||
sb.append("/");
|
||||
}
|
||||
if(urlSegment.endsWith("/"))
|
||||
{
|
||||
endIndex -= 1;
|
||||
}
|
||||
}
|
||||
sb.append(urlSegment.substring(beginIndex, endIndex));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setContextOverride(String contextOverride)
|
||||
{
|
||||
this.contextOverride = fixup(contextOverride);
|
||||
}
|
||||
|
||||
public void setOverrideServletPath(boolean overrideServletPath)
|
||||
{
|
||||
this.overrideServletPath = overrideServletPath;
|
||||
}
|
||||
|
||||
public void setServletPathOverride(String servletPathOverride)
|
||||
{
|
||||
this.servletPathOverride = fixup(servletPathOverride);
|
||||
}
|
||||
|
||||
protected abstract String getServerPath(HttpServletRequest request);
|
||||
|
||||
public String getContextPath(HttpServletRequest httpReq)
|
||||
{
|
||||
if(overrideContext)
|
||||
{
|
||||
return contextOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
return httpReq.getContextPath();
|
||||
}
|
||||
}
|
||||
|
||||
public String getServletPath(HttpServletRequest req)
|
||||
{
|
||||
if(overrideServletPath)
|
||||
{
|
||||
return servletPathOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
return req.getServletPath();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id)
|
||||
{
|
||||
StringBuilder url = new StringBuilder();
|
||||
|
||||
String contextPath = getContextPath(req);
|
||||
if(contextPath != null && !contextPath.equals(""))
|
||||
{
|
||||
url.append(contextPath);
|
||||
}
|
||||
|
||||
String servletPath = getServletPath(req);
|
||||
if(servletPath != null && !servletPath.equals(""))
|
||||
{
|
||||
url.append(servletPath);
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
if(url.length() == 0 || url.charAt(0) != '/')
|
||||
{
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
if(repositoryId != null)
|
||||
{
|
||||
url.append(repositoryId == null ? TenantUtil.DEFAULT_TENANT : repositoryId);
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
if(operation != null)
|
||||
{
|
||||
url.append(operation);
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
if(id != null)
|
||||
{
|
||||
url.append(id);
|
||||
}
|
||||
|
||||
int length = url.length();
|
||||
if(length > 0 && url.charAt(length - 1) == '/')
|
||||
{
|
||||
url.deleteCharAt(length - 1);
|
||||
}
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding)
|
||||
{
|
||||
StringBuilder url = new StringBuilder();
|
||||
String serverPath = getServerPath(req);
|
||||
url.append(serverPath);
|
||||
|
||||
String contextPath = getContextPath(req);
|
||||
if(contextPath != null && !contextPath.equals(""))
|
||||
{
|
||||
url.append(contextPath);
|
||||
}
|
||||
|
||||
String servletPath = getServletPath(req);
|
||||
if(servletPath != null && !servletPath.equals(""))
|
||||
{
|
||||
url.append(servletPath);
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
if(url.length() > 0 && url.charAt(url.length() - 1) != '/')
|
||||
{
|
||||
url.append("/");
|
||||
}
|
||||
|
||||
pathGenerator.generatePath(req, url, repositoryId, binding);
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet;
|
||||
|
||||
/**
|
||||
* Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class AtomPubCMISDispatcher extends CMISServletDispatcher
|
||||
{
|
||||
@Override
|
||||
protected Binding getBinding()
|
||||
{
|
||||
return Binding.atom;
|
||||
}
|
||||
|
||||
protected HttpServlet getServlet()
|
||||
{
|
||||
HttpServlet servlet = new CmisAtomPubServlet();
|
||||
return servlet;
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS base url based on the request, repository id and binding.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface BaseUrlGenerator
|
||||
{
|
||||
String getContextPath(HttpServletRequest httpReq);
|
||||
String getServletPath(HttpServletRequest req);
|
||||
String getBaseUrl(HttpServletRequest req, String repositoryId, Binding binding);
|
||||
String getRequestURI(HttpServletRequest req, String repositoryId, String operation, String id);
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet;
|
||||
|
||||
/**
|
||||
* Dispatches OpenCMIS requests to the OpenCMIS Browser Binding servlet.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class BrowserCMISDispatcher extends CMISServletDispatcher
|
||||
{
|
||||
@Override
|
||||
protected Binding getBinding()
|
||||
{
|
||||
return Binding.browser;
|
||||
}
|
||||
|
||||
protected HttpServlet getServlet()
|
||||
{
|
||||
HttpServlet servlet = new CmisBrowserBindingServlet();
|
||||
return servlet;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
/**
|
||||
* Dispatches OpenCMIS requests to the appropriate handler.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface CMISDispatcher
|
||||
{
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException;
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import org.apache.chemistry.opencmis.commons.enums.BindingType;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* A registry of OpenCMIS bindings to dispatchers.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface CMISDispatcherRegistry
|
||||
{
|
||||
/*
|
||||
* Supported CMIS bindings
|
||||
*/
|
||||
public static enum Binding
|
||||
{
|
||||
atom, browser;
|
||||
|
||||
public BindingType getOpenCmisBinding()
|
||||
{
|
||||
BindingType bindingType = null;
|
||||
|
||||
if(this == atom)
|
||||
{
|
||||
bindingType = BindingType.ATOMPUB;
|
||||
}
|
||||
else if(this == browser)
|
||||
{
|
||||
bindingType = BindingType.BROWSER;
|
||||
}
|
||||
|
||||
return bindingType;
|
||||
}
|
||||
};
|
||||
|
||||
public static class Endpoint
|
||||
{
|
||||
private Binding binding;
|
||||
private String version;
|
||||
|
||||
public Endpoint(Binding binding, String version)
|
||||
{
|
||||
super();
|
||||
this.binding = binding;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Binding getBinding()
|
||||
{
|
||||
return binding;
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result
|
||||
+ ((binding == null) ? 0 : binding.hashCode());
|
||||
result = prime * result
|
||||
+ ((version == null) ? 0 : version.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Endpoint other = (Endpoint) obj;
|
||||
if (binding != other.binding)
|
||||
return false;
|
||||
if (version == null) {
|
||||
if (other.version != null)
|
||||
return false;
|
||||
} else if (!version.equals(other.version))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher);
|
||||
public CMISDispatcher getDispatcher(WebScriptRequest req);
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* A registry of OpenCMIS bindings to dispatchers.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class CMISDispatcherRegistryImpl implements CMISDispatcherRegistry
|
||||
{
|
||||
private Map<Endpoint, CMISDispatcher> registry = new HashMap<Endpoint, CMISDispatcher>();
|
||||
|
||||
@Override
|
||||
public void registerDispatcher(Endpoint endpoint, CMISDispatcher dispatcher)
|
||||
{
|
||||
registry.put(endpoint, dispatcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CMISDispatcher getDispatcher(WebScriptRequest req)
|
||||
{
|
||||
CMISDispatcher dispatcher = null;
|
||||
|
||||
Match match = req.getServiceMatch();
|
||||
Map<String, String> templateVars = match.getTemplateVars();
|
||||
String bindingStr = templateVars.get("binding");
|
||||
String apiVersion = templateVars.get("apiVersion");
|
||||
if(bindingStr != null && apiVersion != null)
|
||||
{
|
||||
Binding binding = null;
|
||||
try
|
||||
{
|
||||
binding = Binding.valueOf(bindingStr);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
// nothing to do, binding remains null
|
||||
}
|
||||
|
||||
if(binding != null)
|
||||
{
|
||||
Endpoint endpoint = new Endpoint(binding, apiVersion);
|
||||
dispatcher = registry.get(endpoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.web.scripts.TenantWebScriptServletRequest;
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.apache.chemistry.opencmis.commons.impl.Constants;
|
||||
import org.apache.chemistry.opencmis.server.shared.Dispatcher;
|
||||
import org.apache.commons.collections.map.HashedMap;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
|
||||
|
||||
/**
|
||||
* Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class CMISHttpServletRequest implements HttpServletRequest
|
||||
{
|
||||
protected WebScriptRequest req;
|
||||
protected HttpServletRequest httpReq;
|
||||
protected String networkId;
|
||||
protected String operation;
|
||||
protected String id; // object id (or path for browser binding)
|
||||
protected String serviceName;
|
||||
protected BaseUrlGenerator baseUrlGenerator;
|
||||
protected Binding binding;
|
||||
protected Descriptor currentDescriptor;
|
||||
|
||||
public CMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator, Binding binding, Descriptor currentDescriptor,
|
||||
TenantAdminService tenantAdminService)
|
||||
{
|
||||
this.req = req;
|
||||
this.serviceName = serviceName;
|
||||
this.baseUrlGenerator = baseUrlGenerator;
|
||||
this.binding = binding;
|
||||
|
||||
String pathInfo = req.getPathInfo();
|
||||
WebScriptRequest baseReq = getBaseRequest(req);
|
||||
if(!pathInfo.startsWith("/cmis") && (baseReq instanceof TenantWebScriptServletRequest))
|
||||
{
|
||||
TenantWebScriptServletRequest servletReq = (TenantWebScriptServletRequest)baseReq;
|
||||
|
||||
String tenant = servletReq.getTenant();
|
||||
if(tenant.equalsIgnoreCase(TenantUtil.DEFAULT_TENANT))
|
||||
{
|
||||
String user = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
String domain = tenantAdminService.getUserDomain(user);
|
||||
if(domain == null || domain.equals(TenantService.DEFAULT_DOMAIN))
|
||||
{
|
||||
this.networkId = tenant;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.networkId = domain;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.networkId = tenant;
|
||||
}
|
||||
}
|
||||
|
||||
Match match = req.getServiceMatch();
|
||||
Map<String, String> templateVars = match.getTemplateVars();
|
||||
|
||||
HttpServletRequest httpReq = WebScriptServletRuntime.getHttpServletRequest(req);
|
||||
this.httpReq = httpReq;
|
||||
this.operation = templateVars.get("operation");
|
||||
this.id = templateVars.get("id");
|
||||
|
||||
addAttributes();
|
||||
}
|
||||
|
||||
/*
|
||||
* Recursively unwrap req if it is a WrappingWebScriptRequest
|
||||
*/
|
||||
private WebScriptRequest getBaseRequest(WebScriptRequest req)
|
||||
{
|
||||
WebScriptRequest ret = req;
|
||||
while(ret instanceof WrappingWebScriptRequest)
|
||||
{
|
||||
WrappingWebScriptRequest wrapping = (WrappingWebScriptRequest)req;
|
||||
ret = wrapping.getNext();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
protected void addAttributes()
|
||||
{
|
||||
if(networkId != null)
|
||||
{
|
||||
httpReq.setAttribute(Constants.PARAM_REPOSITORY_ID, networkId);
|
||||
}
|
||||
httpReq.setAttribute("serviceName", serviceName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String arg0)
|
||||
{
|
||||
if(arg0.equals(Dispatcher.BASE_URL_ATTRIBUTE))
|
||||
{
|
||||
return baseUrlGenerator.getBaseUrl(this, networkId, binding);
|
||||
}
|
||||
else
|
||||
{
|
||||
return httpReq.getAttribute(arg0);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Enumeration getAttributeNames()
|
||||
{
|
||||
Enumeration e = httpReq.getAttributeNames();
|
||||
List attrNames = new ArrayList();
|
||||
while(e.hasMoreElements())
|
||||
{
|
||||
attrNames.add(e.nextElement());
|
||||
}
|
||||
attrNames.add(Dispatcher.BASE_URL_ATTRIBUTE);
|
||||
final Iterator it = attrNames.iterator();
|
||||
|
||||
return new Enumeration()
|
||||
{
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
public Object nextElement()
|
||||
{
|
||||
return it.next();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding()
|
||||
{
|
||||
return httpReq.getCharacterEncoding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContentLength()
|
||||
{
|
||||
return httpReq.getContentLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
return httpReq.getContentType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException
|
||||
{
|
||||
return httpReq.getInputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalAddr()
|
||||
{
|
||||
return httpReq.getLocalAddr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalName()
|
||||
{
|
||||
return httpReq.getLocalName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLocalPort()
|
||||
{
|
||||
return httpReq.getLocalPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale()
|
||||
{
|
||||
return httpReq.getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getLocales()
|
||||
{
|
||||
return httpReq.getLocales();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParameter(String arg0)
|
||||
{
|
||||
if(arg0.equals(Constants.PARAM_REPOSITORY_ID))
|
||||
{
|
||||
return networkId;
|
||||
}
|
||||
return httpReq.getParameter(arg0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map getParameterMap()
|
||||
{
|
||||
Map map = httpReq.getParameterMap();
|
||||
Map ret = new HashedMap(map);
|
||||
if(networkId != null)
|
||||
{
|
||||
ret.put(Constants.PARAM_REPOSITORY_ID, new String[] { networkId });
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Enumeration getParameterNames()
|
||||
{
|
||||
final Enumeration e = httpReq.getParameterNames();
|
||||
List l = new ArrayList();
|
||||
while(e.hasMoreElements())
|
||||
{
|
||||
l.add(e.nextElement());
|
||||
}
|
||||
if(networkId != null)
|
||||
{
|
||||
l.add(Constants.PARAM_REPOSITORY_ID);
|
||||
}
|
||||
final Iterator it = l.iterator();
|
||||
Enumeration ret = new Enumeration()
|
||||
{
|
||||
@Override
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nextElement()
|
||||
{
|
||||
return it.next();
|
||||
}
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getParameterValues(String arg0)
|
||||
{
|
||||
return httpReq.getParameterValues(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProtocol()
|
||||
{
|
||||
return httpReq.getProtocol();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException
|
||||
{
|
||||
return httpReq.getReader();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getRealPath(String arg0)
|
||||
{
|
||||
return httpReq.getRealPath(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteAddr()
|
||||
{
|
||||
return httpReq.getRemoteAddr();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteHost()
|
||||
{
|
||||
return httpReq.getRemoteHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemotePort()
|
||||
{
|
||||
return httpReq.getRemotePort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestDispatcher getRequestDispatcher(String arg0)
|
||||
{
|
||||
return httpReq.getRequestDispatcher(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScheme()
|
||||
{
|
||||
return httpReq.getScheme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerName()
|
||||
{
|
||||
return httpReq.getServerName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getServerPort()
|
||||
{
|
||||
return httpReq.getServerPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure()
|
||||
{
|
||||
return httpReq.isSecure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String arg0)
|
||||
{
|
||||
httpReq.removeAttribute(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String arg0, Object arg1)
|
||||
{
|
||||
httpReq.setAttribute(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException
|
||||
{
|
||||
httpReq.setCharacterEncoding(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthType()
|
||||
{
|
||||
return httpReq.getAuthType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath()
|
||||
{
|
||||
String contextPath = baseUrlGenerator.getContextPath(httpReq);
|
||||
return contextPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cookie[] getCookies()
|
||||
{
|
||||
return httpReq.getCookies();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDateHeader(String arg0)
|
||||
{
|
||||
return httpReq.getDateHeader(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String arg0)
|
||||
{
|
||||
return httpReq.getHeader(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getHeaderNames()
|
||||
{
|
||||
return httpReq.getHeaderNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getHeaders(String arg0)
|
||||
{
|
||||
return httpReq.getHeaders(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntHeader(String arg0)
|
||||
{
|
||||
return httpReq.getIntHeader(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod()
|
||||
{
|
||||
return httpReq.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathInfo()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder("/");
|
||||
sb.append(networkId == null ? TenantUtil.DEFAULT_TENANT : networkId);
|
||||
if(operation != null)
|
||||
{
|
||||
sb.append("/");
|
||||
sb.append(operation);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPathTranslated()
|
||||
{
|
||||
return httpReq.getPathTranslated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryString()
|
||||
{
|
||||
StringBuilder queryString = new StringBuilder();
|
||||
String reqQueryString = httpReq.getQueryString();
|
||||
|
||||
if(networkId != null && networkId.length() > 0)
|
||||
{
|
||||
if (reqQueryString != null)
|
||||
{
|
||||
queryString.append(reqQueryString + "&");
|
||||
}
|
||||
queryString.append("repositoryId=" + networkId);
|
||||
if(operation == null || operation.isEmpty())
|
||||
{
|
||||
queryString.append("&cmisselector=");
|
||||
queryString.append(Constants.SELECTOR_REPOSITORY_INFO);
|
||||
}
|
||||
return queryString.toString();
|
||||
}
|
||||
return reqQueryString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteUser()
|
||||
{
|
||||
return httpReq.getRemoteUser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestURI()
|
||||
{
|
||||
String requestURI = baseUrlGenerator.getRequestURI(httpReq, networkId, operation, id);
|
||||
return requestURI;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer getRequestURL()
|
||||
{
|
||||
return httpReq.getRequestURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRequestedSessionId()
|
||||
{
|
||||
return httpReq.getRequestedSessionId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletPath()
|
||||
{
|
||||
String servletPath = baseUrlGenerator.getServletPath(httpReq);
|
||||
return servletPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession()
|
||||
{
|
||||
return httpReq.getSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getSession(boolean arg0)
|
||||
{
|
||||
return httpReq.getSession(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal()
|
||||
{
|
||||
return httpReq.getUserPrincipal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequestedSessionIdFromCookie()
|
||||
{
|
||||
return httpReq.isRequestedSessionIdFromCookie();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequestedSessionIdFromURL()
|
||||
{
|
||||
return httpReq.isRequestedSessionIdFromURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequestedSessionIdFromUrl()
|
||||
{
|
||||
return httpReq.isRequestedSessionIdFromURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRequestedSessionIdValid()
|
||||
{
|
||||
return httpReq.isRequestedSessionIdValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserInRole(String arg0)
|
||||
{
|
||||
return httpReq.isUserInRole(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
return httpReq.authenticate(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void login(String username, String password) throws ServletException
|
||||
{
|
||||
httpReq.login(username, password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout() throws ServletException
|
||||
{
|
||||
httpReq.logout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Part> getParts() throws IOException, ServletException
|
||||
{
|
||||
return httpReq.getParts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Part getPart(String name) throws IOException, ServletException
|
||||
{
|
||||
return httpReq.getPart(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getServletContext()
|
||||
{
|
||||
return httpReq.getServletContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncContext startAsync() throws IllegalStateException
|
||||
{
|
||||
return httpReq.startAsync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
|
||||
{
|
||||
return httpReq.startAsync(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncStarted()
|
||||
{
|
||||
return httpReq.isAsyncStarted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAsyncSupported()
|
||||
{
|
||||
return httpReq.isAsyncSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncContext getAsyncContext()
|
||||
{
|
||||
return httpReq.getAsyncContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DispatcherType getDispatcherType()
|
||||
{
|
||||
return httpReq.getDispatcherType();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps an OpenCMIS HttpServletResponse for specific mapping to the Alfresco implementation of OpenCMIS.
|
||||
*
|
||||
* @author janv
|
||||
*/
|
||||
public class CMISHttpServletResponse implements HttpServletResponse
|
||||
{
|
||||
protected HttpServletResponse httpResp;
|
||||
|
||||
protected Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf
|
||||
|
||||
private final static String HDR_CONTENT_DISPOSITION = "Content-Disposition";
|
||||
|
||||
private final static String ATTACHMENT = "attachment";
|
||||
private final static String INLINE = "inline";
|
||||
|
||||
public CMISHttpServletResponse(WebScriptResponse res, Set<String> nonAttachContentTypes)
|
||||
{
|
||||
httpResp = WebScriptServletRuntime.getHttpServletResponse(res);
|
||||
this.nonAttachContentTypes = nonAttachContentTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCookie(Cookie cookie)
|
||||
{
|
||||
httpResp.addCookie(cookie);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsHeader(String name)
|
||||
{
|
||||
return httpResp.containsHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeURL(String url)
|
||||
{
|
||||
return httpResp.encodeURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeRedirectURL(String url)
|
||||
{
|
||||
return httpResp.encodeRedirectURL(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeUrl(String url)
|
||||
{
|
||||
return encodeUrl(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeRedirectUrl(String url)
|
||||
{
|
||||
return httpResp.encodeRedirectUrl(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int sc, String msg) throws IOException
|
||||
{
|
||||
httpResp.sendError(sc, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendError(int sc) throws IOException
|
||||
{
|
||||
httpResp.sendError(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRedirect(String location) throws IOException
|
||||
{
|
||||
httpResp.sendRedirect(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDateHeader(String name, long date)
|
||||
{
|
||||
httpResp.setDateHeader(name, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDateHeader(String name, long date)
|
||||
{
|
||||
httpResp.addDateHeader(name, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
httpResp.setHeader(name, getStringHeaderValue(name, value, httpResp.getContentType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
httpResp.addHeader(name, getStringHeaderValue(name, value, httpResp.getContentType()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String getStringHeaderValue(String name, String value, String contentType)
|
||||
{
|
||||
if (HDR_CONTENT_DISPOSITION.equals(name))
|
||||
{
|
||||
if (! nonAttachContentTypes.contains(contentType))
|
||||
{
|
||||
if (value.startsWith(INLINE))
|
||||
{
|
||||
// force attachment
|
||||
value = ATTACHMENT+value.substring(INLINE.length());
|
||||
}
|
||||
else if (! value.startsWith(ATTACHMENT))
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected - header could not be set: "+name+" = "+value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIntHeader(String name, int value)
|
||||
{
|
||||
httpResp.setIntHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIntHeader(String name, int value)
|
||||
{
|
||||
httpResp.addIntHeader(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(int sc)
|
||||
{
|
||||
httpResp.setStatus(sc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(int sc, String sm)
|
||||
{
|
||||
httpResp.setStatus(sc, sm);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatus()
|
||||
{
|
||||
return httpResp.getStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return httpResp.getHeader(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaders(String name)
|
||||
{
|
||||
return httpResp.getHeaders(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getHeaderNames()
|
||||
{
|
||||
return httpResp.getHeaderNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCharacterEncoding()
|
||||
{
|
||||
return httpResp.getCharacterEncoding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
return httpResp.getContentType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletOutputStream getOutputStream() throws IOException
|
||||
{
|
||||
return httpResp.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter getWriter() throws IOException
|
||||
{
|
||||
return httpResp.getWriter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterEncoding(String charset)
|
||||
{
|
||||
httpResp.setCharacterEncoding(charset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLength(int len)
|
||||
{
|
||||
httpResp.setContentLength(len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentType(String type)
|
||||
{
|
||||
httpResp.setContentType(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBufferSize(int size)
|
||||
{
|
||||
httpResp.setBufferSize(size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSize()
|
||||
{
|
||||
return httpResp.getBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBuffer() throws IOException
|
||||
{
|
||||
httpResp.flushBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBuffer()
|
||||
{
|
||||
httpResp.resetBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommitted()
|
||||
{
|
||||
return httpResp.isCommitted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
httpResp.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLocale(Locale loc)
|
||||
{
|
||||
httpResp.setLocale(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale()
|
||||
{
|
||||
return httpResp.getLocale();
|
||||
}
|
||||
}
|
@@ -0,0 +1,601 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import javax.servlet.SessionTrackingMode;
|
||||
import javax.servlet.descriptor.JspConfigDescriptor;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Endpoint;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
|
||||
import org.apache.chemistry.opencmis.commons.server.CmisServiceFactory;
|
||||
import org.apache.chemistry.opencmis.server.impl.CmisRepositoryContextListener;
|
||||
import org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
|
||||
|
||||
/**
|
||||
* Dispatches OpenCMIS requests to a servlet e.g. the OpenCMIS AtomPub servlet.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public abstract class CMISServletDispatcher implements CMISDispatcher
|
||||
{
|
||||
private DescriptorService descriptorService;
|
||||
private Descriptor currentDescriptor;
|
||||
protected CmisServiceFactory cmisServiceFactory;
|
||||
protected HttpServlet servlet;
|
||||
protected CMISDispatcherRegistry registry;
|
||||
protected String serviceName;
|
||||
protected BaseUrlGenerator baseUrlGenerator;
|
||||
protected String version;
|
||||
protected CmisVersion cmisVersion;
|
||||
protected TenantAdminService tenantAdminService;
|
||||
|
||||
private Set<String> nonAttachContentTypes = Collections.emptySet(); // pre-configured whitelist, eg. images & pdf
|
||||
|
||||
public void setTenantAdminService(TenantAdminService tenantAdminService)
|
||||
{
|
||||
this.tenantAdminService = tenantAdminService;
|
||||
}
|
||||
|
||||
public void setDescriptorService(DescriptorService descriptorService)
|
||||
{
|
||||
this.descriptorService = descriptorService;
|
||||
}
|
||||
|
||||
public void setVersion(String version)
|
||||
{
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public void setBaseUrlGenerator(BaseUrlGenerator baseUrlGenerator)
|
||||
{
|
||||
this.baseUrlGenerator = baseUrlGenerator;
|
||||
}
|
||||
|
||||
public void setRegistry(CMISDispatcherRegistry registry)
|
||||
{
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public void setCmisServiceFactory(CmisServiceFactory cmisServiceFactory)
|
||||
{
|
||||
this.cmisServiceFactory = cmisServiceFactory;
|
||||
}
|
||||
|
||||
public void setServiceName(String serviceName)
|
||||
{
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public String getServiceName()
|
||||
{
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public void setCmisVersion(String cmisVersion)
|
||||
{
|
||||
this.cmisVersion = CmisVersion.fromValue(cmisVersion);
|
||||
}
|
||||
|
||||
public void setNonAttachContentTypes(Set<String> nonAttachWhiteList)
|
||||
{
|
||||
this.nonAttachContentTypes = nonAttachWhiteList;
|
||||
}
|
||||
|
||||
protected synchronized Descriptor getCurrentDescriptor()
|
||||
{
|
||||
if(this.currentDescriptor == null)
|
||||
{
|
||||
this.currentDescriptor = descriptorService.getCurrentRepositoryDescriptor();
|
||||
}
|
||||
|
||||
return this.currentDescriptor;
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
Endpoint endpoint = new Endpoint(getBinding(), version);
|
||||
registry.registerDispatcher(endpoint, this);
|
||||
|
||||
try
|
||||
{
|
||||
// fake the CMIS servlet
|
||||
ServletConfig config = getServletConfig();
|
||||
this.servlet = getServlet();
|
||||
servlet.init(config);
|
||||
}
|
||||
catch(ServletException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to initialise CMIS servlet dispatcher", e);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Implement getBinding to provide the appropriate CMIS binding.
|
||||
*/
|
||||
protected abstract Binding getBinding();
|
||||
|
||||
/*
|
||||
* Implement getServlet to provide the appropriate servlet implementation.
|
||||
*/
|
||||
protected abstract HttpServlet getServlet();
|
||||
|
||||
protected Object getServletAttribute(String attrName)
|
||||
{
|
||||
if(attrName.equals(CmisRepositoryContextListener.SERVICES_FACTORY))
|
||||
{
|
||||
return cmisServiceFactory;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ServletConfig getServletConfig()
|
||||
{
|
||||
ServletConfig config = new CMISServletConfig();
|
||||
return config;
|
||||
}
|
||||
|
||||
protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req)
|
||||
{
|
||||
String serviceName = getServiceName();
|
||||
CMISHttpServletRequest httpReqWrapper = new CMISHttpServletRequest(req, serviceName, baseUrlGenerator,
|
||||
getBinding(), currentDescriptor, tenantAdminService);
|
||||
return httpReqWrapper;
|
||||
}
|
||||
|
||||
protected CMISHttpServletResponse getHttpResponse(WebScriptResponse res)
|
||||
{
|
||||
CMISHttpServletResponse httpResWrapper = new CMISHttpServletResponse(res, nonAttachContentTypes);
|
||||
|
||||
return httpResWrapper;
|
||||
}
|
||||
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
// wrap request & response
|
||||
CMISHttpServletResponse httpResWrapper = getHttpResponse(res);
|
||||
CMISHttpServletRequest httpReqWrapper = getHttpRequest(req);
|
||||
|
||||
servlet.service(httpReqWrapper, httpResWrapper);
|
||||
}
|
||||
catch(ServletException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fake a CMIS servlet config.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
private class CMISServletConfig implements ServletConfig
|
||||
{
|
||||
private List parameterNames = new ArrayList();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
CMISServletConfig()
|
||||
{
|
||||
parameterNames.add(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER);
|
||||
parameterNames.add(CmisAtomPubServlet.PARAM_CMIS_VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String arg0)
|
||||
{
|
||||
if(arg0.equals(CmisAtomPubServlet.PARAM_CALL_CONTEXT_HANDLER))
|
||||
{
|
||||
return PublicApiCallContextHandler.class.getName();
|
||||
}
|
||||
else if(arg0.equals(CmisAtomPubServlet.PARAM_CMIS_VERSION))
|
||||
{
|
||||
return (cmisVersion != null ? cmisVersion.value() : CmisVersion.CMIS_1_0.value());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getInitParameterNames()
|
||||
{
|
||||
final Iterator it = parameterNames.iterator();
|
||||
|
||||
Enumeration e = new Enumeration()
|
||||
{
|
||||
@Override
|
||||
public boolean hasMoreElements()
|
||||
{
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object nextElement()
|
||||
{
|
||||
return it.next();
|
||||
}
|
||||
};
|
||||
return e;
|
||||
}
|
||||
|
||||
// fake a servlet context. Note that getAttribute is the only method that the servlet uses,
|
||||
// hence the other methods are not implemented.
|
||||
@Override
|
||||
public ServletContext getServletContext()
|
||||
{
|
||||
return new ServletContext()
|
||||
{
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String arg0)
|
||||
{
|
||||
return getServletAttribute(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getAttributeNames()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletContext getContext(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getInitParameter(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getInitParameterNames()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInitParameter(String name, String value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMajorVersion()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMajorVersion()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMinorVersion()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestDispatcher getNamedDispatcher(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRealPath(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RequestDispatcher getRequestDispatcher(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String arg0) throws MalformedURLException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getResourceAsStream(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set getResourcePaths(String arg0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerInfo()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Servlet getServlet(String arg0) throws ServletException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletContextName()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, String className)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletRegistration getServletRegistration(String servletName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends ServletRegistration> getServletRegistrations()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, String className)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilterRegistration getFilterRegistration(String filterName)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ? extends FilterRegistration> getFilterRegistrations()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SessionCookieConfig getSessionCookieConfig()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(String className)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EventListener> void addListener(T t)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(Class<? extends EventListener> listenerClass)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JspConfigDescriptor getJspConfigDescriptor()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader getClassLoader()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareRoles(String... roleNames)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getServletNames()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration getServlets()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String arg0)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Exception arg0, String arg1)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(String arg0, Throwable arg1)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(String arg0)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(String arg0, Object arg1)
|
||||
{
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletName()
|
||||
{
|
||||
return "OpenCMIS";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.extensions.webscripts.AbstractWebScript;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
/**
|
||||
* An Alfresco web script that handles dispatch of OpenCMIS requests.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class CMISWebScript extends AbstractWebScript
|
||||
{
|
||||
private CMISDispatcherRegistry registry;
|
||||
|
||||
public void setRegistry(CMISDispatcherRegistry registry)
|
||||
{
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
|
||||
{
|
||||
CMISDispatcher dispatcher = registry.getDispatcher(req);
|
||||
if(dispatcher == null)
|
||||
{
|
||||
res.setStatus(404);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatcher.execute(req, res);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port
|
||||
* are overridden by a property from repository.properties or in an override file.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class DefaultBaseUrlGenerator extends AbstractBaseUrlGenerator
|
||||
{
|
||||
private boolean overrideServer;
|
||||
private String serverOverride;
|
||||
|
||||
public DefaultBaseUrlGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
public void setOverrideServer(boolean overrideServer)
|
||||
{
|
||||
this.overrideServer = overrideServer;
|
||||
}
|
||||
|
||||
public void setServerOverride(String serverOverride)
|
||||
{
|
||||
this.serverOverride = serverOverride;
|
||||
}
|
||||
|
||||
protected String getServerPath(HttpServletRequest request)
|
||||
{
|
||||
if(overrideServer)
|
||||
{
|
||||
return serverOverride;
|
||||
}
|
||||
else
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(request.getScheme());
|
||||
sb.append("://");
|
||||
sb.append(request.getServerName());
|
||||
sb.append(":");
|
||||
sb.append(request.getServerPort());
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
|
||||
/**
|
||||
* Default generator for OpenCMIS paths based on the repositoryId and binding.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class DefaultPathGenerator implements PathGenerator
|
||||
{
|
||||
public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding)
|
||||
{
|
||||
url.append(binding.toString());
|
||||
url.append("/");
|
||||
if(repositoryId != null)
|
||||
{
|
||||
url.append(repositoryId);
|
||||
}
|
||||
else
|
||||
{
|
||||
url.append(TenantUtil.DEFAULT_TENANT);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS path based on the repositoryId and binding.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public interface PathGenerator
|
||||
{
|
||||
public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding);
|
||||
}
|
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port
|
||||
* are overridden by any proxy http header parameters, if present.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class ProxyBaseUrlGenerator extends AbstractBaseUrlGenerator
|
||||
{
|
||||
public static final String FORWARDED_HOST_HEADER = "X-Forwarded-Host";
|
||||
public static final String FORWARDED_PROTO_HEADER = "X-Forwarded-Proto";
|
||||
public static final String HTTPS_SCHEME = "https";
|
||||
public static final String HTTP_SCHEME = "http";
|
||||
|
||||
@Override
|
||||
protected String getServerPath(HttpServletRequest request)
|
||||
{
|
||||
String scheme = request.getHeader(FORWARDED_PROTO_HEADER);
|
||||
String serverName;
|
||||
int serverPort;
|
||||
|
||||
if (!HTTP_SCHEME.equalsIgnoreCase(scheme) && !HTTPS_SCHEME.equalsIgnoreCase(scheme))
|
||||
{
|
||||
scheme = request.getScheme();
|
||||
}
|
||||
|
||||
serverName = request.getServerName();
|
||||
serverPort = request.getServerPort();
|
||||
|
||||
String host = request.getHeader(FORWARDED_HOST_HEADER);
|
||||
if ((host != null) && (host.length() > 0))
|
||||
{
|
||||
int index = host.indexOf(':');
|
||||
if (index < 0)
|
||||
{
|
||||
serverName = host;
|
||||
serverPort = getDefaultPort(scheme);
|
||||
}
|
||||
else
|
||||
{
|
||||
serverName = host.substring(0, index);
|
||||
try
|
||||
{
|
||||
serverPort = Integer.parseInt(host.substring(index + 1));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
serverPort = getDefaultPort(scheme);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(scheme);
|
||||
sb.append("://");
|
||||
sb.append(serverName);
|
||||
sb.append(":");
|
||||
sb.append(serverPort);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private int getDefaultPort(String scheme)
|
||||
{
|
||||
if (HTTPS_SCHEME.equalsIgnoreCase(scheme))
|
||||
{
|
||||
return 443;
|
||||
}
|
||||
|
||||
return 80;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.tenant.Network;
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.repo.tenant.TenantService;
|
||||
import org.alfresco.repo.tenant.TenantUtil;
|
||||
import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork;
|
||||
import org.alfresco.util.FileFilterMode;
|
||||
import org.alfresco.util.FileFilterMode.Client;
|
||||
import org.apache.chemistry.opencmis.commons.data.Acl;
|
||||
import org.apache.chemistry.opencmis.commons.data.ContentStream;
|
||||
import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
|
||||
import org.apache.chemistry.opencmis.commons.data.Properties;
|
||||
import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
|
||||
import org.apache.chemistry.opencmis.commons.enums.VersioningState;
|
||||
import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
|
||||
import org.apache.chemistry.opencmis.commons.impl.dataobjects.RepositoryInfoImpl;
|
||||
import org.apache.chemistry.opencmis.commons.spi.Holder;
|
||||
|
||||
/**
|
||||
* Override OpenCMIS service object - for public api
|
||||
*
|
||||
* @author sglover
|
||||
* @since PublicApi1.0
|
||||
*/
|
||||
public class PublicApiAlfrescoCmisService extends AlfrescoCmisServiceImpl
|
||||
{
|
||||
protected CMISConnector connector;
|
||||
protected TenantAdminService tenantAdminService;
|
||||
protected NetworksService networksService;
|
||||
|
||||
public PublicApiAlfrescoCmisService(CMISConnector connector, TenantAdminService tenantAdminService, NetworksService networksService)
|
||||
{
|
||||
super(connector);
|
||||
|
||||
this.connector = connector;
|
||||
this.networksService = networksService;
|
||||
this.tenantAdminService = tenantAdminService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String create(String repositoryId, Properties properties, String folderId,
|
||||
ContentStream contentStream, VersioningState versioningState,
|
||||
List<String> policies, ExtensionsData extension)
|
||||
{
|
||||
FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
return super.create(
|
||||
repositoryId,
|
||||
properties,
|
||||
folderId,
|
||||
contentStream,
|
||||
versioningState,
|
||||
policies,
|
||||
extension);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overridden to capture content upload for publishing to analytics service.
|
||||
*/
|
||||
@Override
|
||||
public String createDocument(String repositoryId, Properties properties, String folderId,
|
||||
ContentStream contentStream, VersioningState versioningState,
|
||||
List<String> policies, Acl addAces, Acl removeAces, ExtensionsData extension)
|
||||
{
|
||||
String newId = super.createDocument(
|
||||
repositoryId,
|
||||
properties,
|
||||
folderId,
|
||||
contentStream,
|
||||
versioningState,
|
||||
policies,
|
||||
addAces,
|
||||
removeAces,
|
||||
extension);
|
||||
return newId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overridden to capture content upload for publishing to analytics service.
|
||||
*/
|
||||
@Override
|
||||
public void setContentStream(String repositoryId, Holder<String> objectId,
|
||||
Boolean overwriteFlag, Holder<String> changeToken, ContentStream contentStream,
|
||||
ExtensionsData extension)
|
||||
{
|
||||
FileFilterMode.setClient(Client.cmis);
|
||||
try
|
||||
{
|
||||
super.setContentStream(repositoryId, objectId, overwriteFlag, changeToken, contentStream, extension);
|
||||
}
|
||||
finally
|
||||
{
|
||||
FileFilterMode.clearClient();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RepositoryInfo> getRepositoryInfos(ExtensionsData extension)
|
||||
{
|
||||
// for currently authenticated user
|
||||
PagingResults<Network> networks = networksService.getNetworks(new PagingRequest(0, Integer.MAX_VALUE));
|
||||
List<Network> page = networks.getPage();
|
||||
final List<RepositoryInfo> repoInfos = new ArrayList<RepositoryInfo>(page.size() + 1);
|
||||
for (Network network : page)
|
||||
{
|
||||
repoInfos.add(getRepositoryInfo(network));
|
||||
}
|
||||
return repoInfos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RepositoryInfo getRepositoryInfo(String repositoryId, ExtensionsData extension)
|
||||
{
|
||||
Network network = null;
|
||||
|
||||
try
|
||||
{
|
||||
checkRepositoryId(repositoryId);
|
||||
network = networksService.getNetwork(repositoryId);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
// ACE-2540: Avoid information leak. Same response if repository does not exist or if user is not a member
|
||||
throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!");
|
||||
}
|
||||
|
||||
return getRepositoryInfo(network);
|
||||
}
|
||||
|
||||
private RepositoryInfo getRepositoryInfo(final Network network)
|
||||
{
|
||||
final String networkId = network.getTenantDomain();
|
||||
final String tenantDomain = (networkId.equals(TenantUtil.SYSTEM_TENANT) || networkId.equals(TenantUtil.DEFAULT_TENANT)) ? TenantService.DEFAULT_DOMAIN : networkId;
|
||||
|
||||
return TenantUtil.runAsSystemTenant(new TenantRunAsWork<RepositoryInfo>()
|
||||
{
|
||||
public RepositoryInfo doWork()
|
||||
{
|
||||
RepositoryInfoImpl repoInfo = (RepositoryInfoImpl)connector.getRepositoryInfo(getContext().getCmisVersion());
|
||||
|
||||
repoInfo.setId(!networkId.equals("") ? networkId : TenantUtil.SYSTEM_TENANT);
|
||||
repoInfo.setName(tenantDomain);
|
||||
repoInfo.setDescription(tenantDomain);
|
||||
|
||||
return repoInfo;
|
||||
}
|
||||
}, tenantDomain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkRepositoryId(String repositoryId)
|
||||
{
|
||||
if(repositoryId.equals(TenantUtil.DEFAULT_TENANT) || repositoryId.equals(TenantUtil.SYSTEM_TENANT))
|
||||
{
|
||||
// TODO check for super admin
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tenantAdminService.existsTenant(repositoryId) || !tenantAdminService.isEnabledTenant(repositoryId))
|
||||
{
|
||||
throw new CmisObjectNotFoundException("Unknown repository '" + repositoryId + "'!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCall()
|
||||
{
|
||||
// NOTE: Don't invoke super beforeCall to exclude authentication which is already supported by
|
||||
// Web Script F/W
|
||||
//super.beforeCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCall()
|
||||
{
|
||||
// NOTE: Don't invoke super afterCall to exclude authentication which is already supported by
|
||||
// Web Script F/W
|
||||
//super.afterCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
super.close();
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import org.alfresco.repo.tenant.NetworksService;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
|
||||
/**
|
||||
* Override factory for OpenCMIS service objects - for public api
|
||||
*
|
||||
* @author steveglover
|
||||
* @author janv
|
||||
* @since PublicApi1.0
|
||||
*/
|
||||
public class PublicApiAlfrescoCmisServiceFactory extends AlfrescoCmisServiceFactory
|
||||
{
|
||||
private TenantAdminService tenantAdminService;
|
||||
private NetworksService networksService;
|
||||
|
||||
public void setNetworksService(NetworksService networksService)
|
||||
{
|
||||
this.networksService = networksService;
|
||||
}
|
||||
|
||||
public void setTenantAdminService(TenantAdminService tenantAdminService)
|
||||
{
|
||||
this.tenantAdminService = tenantAdminService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlfrescoCmisService getCmisServiceTarget(CMISConnector connector)
|
||||
{
|
||||
return new PublicApiAlfrescoCmisService(connector, tenantAdminService, networksService);
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Dispatches OpenCMIS requests to the OpenCMIS AtomPub servlet.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class PublicApiAtomPubCMISDispatcher extends AtomPubCMISDispatcher
|
||||
{
|
||||
@Override
|
||||
protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req)
|
||||
{
|
||||
String serviceName = getServiceName();
|
||||
CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName, baseUrlGenerator,
|
||||
getBinding(), getCurrentDescriptor(), tenantAdminService);
|
||||
return httpReqWrapper;
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Cloud-specific browser binding OpenCMIS dispatcher.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class PublicApiBrowserCMISDispatcher extends BrowserCMISDispatcher
|
||||
{
|
||||
@Override
|
||||
protected CMISHttpServletRequest getHttpRequest(WebScriptRequest req)
|
||||
{
|
||||
String serviceName = getServiceName();
|
||||
CMISHttpServletRequest httpReqWrapper = new PublicApiCMISHttpServletRequest(req, serviceName,
|
||||
baseUrlGenerator, getBinding(), getCurrentDescriptor(), tenantAdminService);
|
||||
return httpReqWrapper;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Wraps an OpenCMIS HttpServletRequest, mapping urls and adding servlet attributes specific to the Alfresco implementation of OpenCMIS.
|
||||
*/
|
||||
public class PublicApiCMISHttpServletRequest extends CMISHttpServletRequest
|
||||
{
|
||||
public PublicApiCMISHttpServletRequest(WebScriptRequest req, String serviceName, BaseUrlGenerator baseUrlGenerator,
|
||||
Binding binding, Descriptor currentDescriptor, TenantAdminService tenantAdminService)
|
||||
{
|
||||
super(req, serviceName, baseUrlGenerator, binding, currentDescriptor, tenantAdminService);
|
||||
}
|
||||
|
||||
protected void addAttributes()
|
||||
{
|
||||
super.addAttributes();
|
||||
|
||||
Match match = req.getServiceMatch();
|
||||
Map<String, String> templateVars = match.getTemplateVars();
|
||||
String apiScope = templateVars.get("apiScope");
|
||||
String apiVersion = templateVars.get("apiVersion");
|
||||
|
||||
if(apiScope != null)
|
||||
{
|
||||
httpReq.setAttribute("apiScope", apiScope);
|
||||
}
|
||||
|
||||
if(apiVersion != null)
|
||||
{
|
||||
httpReq.setAttribute("apiVersion", apiVersion);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.opencmis.CMISDispatcherRegistry.Binding;
|
||||
|
||||
/**
|
||||
* Cloud generator for OpenCMIS paths based on the repositoryId and binding.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class PublicApiPathGenerator implements PathGenerator
|
||||
{
|
||||
public void generatePath(HttpServletRequest req, StringBuilder url, String repositoryId, Binding binding)
|
||||
{
|
||||
url.append("{repositoryId}");
|
||||
url.append("/");
|
||||
|
||||
String scope = (String)req.getAttribute("apiScope");
|
||||
String serviceName = (String)req.getAttribute("serviceName");
|
||||
String apiVersion = (String)req.getAttribute("apiVersion");
|
||||
if(scope == null)
|
||||
{
|
||||
scope = "public";
|
||||
}
|
||||
url.append(scope);
|
||||
url.append("/");
|
||||
url.append(serviceName);
|
||||
url.append("/");
|
||||
url.append("versions");
|
||||
url.append("/");
|
||||
url.append(apiVersion);
|
||||
url.append("/");
|
||||
url.append(binding.toString());
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.opencmis;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.alfresco.repo.admin.SysAdminParams;
|
||||
|
||||
/**
|
||||
* Generates an OpenCMIS base url based on the request, repository id and binding. The url scheme, host and port
|
||||
* are overridden by sys admin parameters.
|
||||
*
|
||||
* @author steveglover
|
||||
*
|
||||
*/
|
||||
public class SysAdminParamsBaseUrlGenerator extends AbstractBaseUrlGenerator
|
||||
{
|
||||
private SysAdminParams sysAdminParams;
|
||||
|
||||
protected String getServerPath(HttpServletRequest request)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getServerScheme(request));
|
||||
sb.append("://");
|
||||
sb.append(getServerName(request));
|
||||
sb.append(":");
|
||||
sb.append(getServerPort(request));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String getServerScheme(HttpServletRequest request)
|
||||
{
|
||||
String scheme = sysAdminParams.getAlfrescoProtocol();
|
||||
if (scheme == null)
|
||||
{
|
||||
scheme = request.getScheme();
|
||||
}
|
||||
scheme = request.getScheme();
|
||||
return scheme;
|
||||
}
|
||||
|
||||
protected String getServerName(HttpServletRequest request)
|
||||
{
|
||||
String hostname = sysAdminParams.getAlfrescoHost();
|
||||
if (hostname == null)
|
||||
{
|
||||
hostname = request.getScheme();
|
||||
}
|
||||
hostname = request.getServerName();
|
||||
return hostname;
|
||||
}
|
||||
|
||||
protected int getServerPort(HttpServletRequest request)
|
||||
{
|
||||
Integer port = sysAdminParams.getAlfrescoPort();
|
||||
if (port == null)
|
||||
{
|
||||
port = request.getServerPort();
|
||||
}
|
||||
if (port == null)
|
||||
{
|
||||
port = request.getServerPort();
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
}
|
51
remote-api/src/main/java/org/alfresco/repo/SessionUser.java
Normal file
51
remote-api/src/main/java/org/alfresco/repo/SessionUser.java
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Contract implemented by any object that represents an Alfresco "user" that
|
||||
* can be persisted in an HTTP Session.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public interface SessionUser extends Serializable
|
||||
{
|
||||
/**
|
||||
* Return the user name
|
||||
*
|
||||
* @return user name
|
||||
*/
|
||||
String getUserName();
|
||||
|
||||
/**
|
||||
* Return the ticket
|
||||
*
|
||||
* @return ticket
|
||||
*/
|
||||
String getTicket();
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.imap.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.repo.imap.ImapService;
|
||||
import org.alfresco.repo.management.subsystems.ChildApplicationContextFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.extensions.webscripts.AbstractWebScript;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
/**
|
||||
* Shows the availability of the IMAP server via web script request.
|
||||
*/
|
||||
public class ServerStatusWebScript extends AbstractWebScript implements ApplicationContextAware
|
||||
{
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
|
||||
{
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException
|
||||
{
|
||||
ChildApplicationContextFactory subsystem = (ChildApplicationContextFactory)applicationContext.getBean("imap");
|
||||
|
||||
// note: getting property (rather than getting imapService bean to check isEnabled) does not cause subsystem startup (if stopped)
|
||||
// hence providing ability for subsystem to be disabled (whilst still supporting ability to check status and/or dynamically start via JMX)
|
||||
String isEnabled = (String)subsystem.getProperty("imap.server.enabled");
|
||||
|
||||
if (new Boolean(isEnabled).booleanValue())
|
||||
{
|
||||
res.getWriter().write("enabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
res.getWriter().write("disabled");
|
||||
}
|
||||
res.getWriter().flush();
|
||||
res.getWriter().close();
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.surf.policy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.node.NodeServicePolicies.BeforeDeleteNodePolicy;
|
||||
import org.alfresco.repo.policy.JavaBehaviour;
|
||||
import org.alfresco.repo.policy.PolicyComponent;
|
||||
import org.alfresco.repo.web.scripts.bean.ADMRemoteStore;
|
||||
import org.alfresco.service.cmr.model.FileInfo;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Delete Node Policy to remove surf-config files for a deleted user.
|
||||
*
|
||||
* @author Dmitry Velichkevich
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class SurfConfigCleaner extends ADMRemoteStore implements BeforeDeleteNodePolicy
|
||||
{
|
||||
private PolicyComponent policyComponent;
|
||||
|
||||
public void init()
|
||||
{
|
||||
this.policyComponent.bindClassBehaviour(
|
||||
BeforeDeleteNodePolicy.QNAME,
|
||||
ContentModel.TYPE_PERSON,
|
||||
new JavaBehaviour(this, BeforeDeleteNodePolicy.QNAME.getLocalName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeDeleteNode(NodeRef nodeRef)
|
||||
{
|
||||
final String userName = (String) nodeService.getProperty(nodeRef, ContentModel.PROP_USERNAME);
|
||||
final NodeRef componentsRef = getGlobalComponentsNodeRef();
|
||||
final NodeRef usersFolderRef = getGlobalUserFolderNodeRef();
|
||||
|
||||
// Remove the user Surf config folder, contains dynamic page definitions such as dashboard.xml
|
||||
// For example, qname path to user folder:
|
||||
// /app:company_home/st:sites/cm:surf-config/cm:pages/cm:user/cm:admin
|
||||
// ^^^^^ encoded username
|
||||
if (usersFolderRef != null)
|
||||
{
|
||||
NodeRef userFolderNodeRef = nodeService.getChildByName(usersFolderRef, ContentModel.ASSOC_CONTAINS, encodePath(userName));
|
||||
if (userFolderNodeRef != null)
|
||||
{
|
||||
// CLOUD-2053: Need to set as temporary to delete node instead of archiving.
|
||||
nodeService.addAspect(userFolderNodeRef, ContentModel.ASPECT_TEMPORARY, null);
|
||||
nodeService.deleteNode(userFolderNodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove each component Surf config file related to the user, such as the dashboard dashlet component references
|
||||
// For example, qname path to user component file:
|
||||
// /app:company_home/st:sites/cm:surf-config/cm:components/cm:page.component-1-1.user~admin~dashboard.xml
|
||||
// ^^^^^ encoded username
|
||||
if (componentsRef != null)
|
||||
{
|
||||
List<FileInfo> configNodes = getFileNodes(
|
||||
fileFolderService.getFileInfo(componentsRef),
|
||||
buildUserConfigSearchPattern(userName),
|
||||
true).getPage();
|
||||
|
||||
for (FileInfo fileInfo : configNodes)
|
||||
{
|
||||
// CLOUD-2053: Need to set as temporary to delete node instead of archiving.
|
||||
nodeService.addAspect(fileInfo.getNodeRef(), ContentModel.ASPECT_TEMPORARY, null);
|
||||
nodeService.deleteNode(fileInfo.getNodeRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPolicyComponent(PolicyComponent policyComponent)
|
||||
{
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
/**
|
||||
* AuthenticationListener implementations can receive notifications of successful and unsuccessful
|
||||
* authentication requests, made during web script, WebDav or Sharepoint requests.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public interface AuthenticationListener
|
||||
{
|
||||
/**
|
||||
* A user was successfully authenticated credentials.
|
||||
*/
|
||||
public void userAuthenticated(WebCredentials credentials);
|
||||
|
||||
/**
|
||||
* An authentication attempt, using credentials, failed with exception, ex.
|
||||
*/
|
||||
public void authenticationFailed(WebCredentials credentials, Exception ex);
|
||||
|
||||
/**
|
||||
* An authentication attempt, using credentials, failed.
|
||||
*/
|
||||
public void authenticationFailed(WebCredentials credentials);
|
||||
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
/**
|
||||
* {@link WebCredentials} holding username and the md5 hash of the password.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public class BasicAuthCredentials implements WebCredentials
|
||||
{
|
||||
private static final long serialVersionUID = 2626445241420904072L;
|
||||
|
||||
private String userName;
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public BasicAuthCredentials(String userName, String password)
|
||||
{
|
||||
this.userName = userName;
|
||||
this.password = DigestUtils.md5Hex(password);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.password == null) ? 0 : this.password.hashCode());
|
||||
result = prime * result + ((this.userName == null) ? 0 : this.userName.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) { return true; }
|
||||
if (obj == null) { return false; }
|
||||
if (getClass() != obj.getClass()) { return false; }
|
||||
BasicAuthCredentials other = (BasicAuthCredentials) obj;
|
||||
if (this.password == null)
|
||||
{
|
||||
if (other.password != null) { return false; }
|
||||
}
|
||||
else if (!this.password.equals(other.password)) { return false; }
|
||||
if (this.userName == null)
|
||||
{
|
||||
if (other.userName != null) { return false; }
|
||||
}
|
||||
else if (!this.userName.equals(other.userName)) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
|
||||
/**
|
||||
* {@link WebCredentials} representing a guest user.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public class GuestCredentials implements WebCredentials
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return getClass().equals(obj.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
import org.alfresco.jlan.server.auth.spnego.NegTokenInit;
|
||||
import org.alfresco.jlan.server.auth.spnego.NegTokenTarg;
|
||||
|
||||
/**
|
||||
* {@link WebCredentials} implementation for holding Kerberos credentials.
|
||||
*/
|
||||
public class KerberosCredentials implements WebCredentials
|
||||
{
|
||||
private static final long serialVersionUID = 4625258932647351551L;
|
||||
|
||||
private NegTokenInit negToken;
|
||||
private NegTokenTarg negTokenTarg;
|
||||
|
||||
public KerberosCredentials(NegTokenInit negToken, NegTokenTarg negTokenTarg)
|
||||
{
|
||||
this.negToken = negToken;
|
||||
this.negTokenTarg = negTokenTarg;
|
||||
}
|
||||
|
||||
public KerberosCredentials(NegTokenInit negToken)
|
||||
{
|
||||
this.negToken = negToken;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
|
||||
/**
|
||||
* {@link AuthenticationListener} that does nothing.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public class NoopAuthenticationListener implements AuthenticationListener
|
||||
{
|
||||
@Override
|
||||
public void userAuthenticated(WebCredentials credentials)
|
||||
{
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(WebCredentials credentials)
|
||||
{
|
||||
// Noop
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticationFailed(WebCredentials credentials, Exception ex)
|
||||
{
|
||||
// Noop
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
public interface TenantAuthentication
|
||||
{
|
||||
/**
|
||||
* Authenticate user against tenant
|
||||
*
|
||||
* @param username String
|
||||
* @param tenant String
|
||||
* @return true => authenticated, false => not authenticated
|
||||
*/
|
||||
boolean authenticateTenant(String username, String tenant);
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
|
||||
/**
|
||||
* {@link WebCredentials} class for holding Alfresco tickets.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public class TicketCredentials implements WebCredentials
|
||||
{
|
||||
private static final long serialVersionUID = -8255499275655719748L;
|
||||
|
||||
private String ticket;
|
||||
|
||||
public TicketCredentials(String ticket)
|
||||
{
|
||||
this.ticket = ticket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((this.ticket == null) ? 0 : this.ticket.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj) { return true; }
|
||||
if (obj == null) { return false; }
|
||||
if (getClass() != obj.getClass()) { return false; }
|
||||
TicketCredentials other = (TicketCredentials) obj;
|
||||
if (this.ticket == null)
|
||||
{
|
||||
if (other.ticket != null) { return false; }
|
||||
}
|
||||
else if (!this.ticket.equals(other.ticket)) { return false; }
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
|
||||
/**
|
||||
* {@link WebCredentials} where credentials are undetermined.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public class UnknownCredentials implements WebCredentials
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
return getClass().equals(obj.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.auth;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* WebScriptCredentials interface.
|
||||
*
|
||||
* Passed to {@link AuthenticationListener}s with credentials used in an authentication attempt.
|
||||
*
|
||||
* @author Alex Miller
|
||||
*/
|
||||
public interface WebCredentials extends Serializable
|
||||
{
|
||||
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.filter.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.WebApplicationContextUtils;
|
||||
|
||||
/**
|
||||
* An adapter from the servlet filter world into the Spring dependency injected world. Simply looks up a
|
||||
* {@link DependencyInjectedFilter} with a configured bean name and delegates the
|
||||
* {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} call to that. This allows us to swap in and out
|
||||
* different implementations for different 'hook points' in web.xml.
|
||||
*
|
||||
* @author dward
|
||||
*/
|
||||
public class BeanProxyFilter implements Filter
|
||||
{
|
||||
/**
|
||||
* Name of the init parameter that carries the proxied bean name
|
||||
*/
|
||||
private static final String INIT_PARAM_BEAN_NAME = "beanName";
|
||||
|
||||
private DependencyInjectedFilter filter;
|
||||
private ServletContext context;
|
||||
|
||||
/**
|
||||
* Initialize the filter.
|
||||
*
|
||||
* @param args
|
||||
* FilterConfig
|
||||
* @throws ServletException
|
||||
* the servlet exception
|
||||
* @exception ServletException
|
||||
*/
|
||||
public void init(FilterConfig args) throws ServletException
|
||||
{
|
||||
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(args.getServletContext());
|
||||
this.filter = (DependencyInjectedFilter)ctx.getBean(args.getInitParameter(INIT_PARAM_BEAN_NAME));
|
||||
this.context = args.getServletContext();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Filter#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
this.filter = null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
*/
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
this.filter.doFilter(this.context, request, response, chain);
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.filter.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
/**
|
||||
* A bean-like equivalent of a servlet filter, designed to be managed by a Spring container.
|
||||
*
|
||||
* @see BeanProxyFilter
|
||||
* @author dward
|
||||
*/
|
||||
public interface DependencyInjectedFilter
|
||||
{
|
||||
/**
|
||||
* The <code>doFilter</code> method of the Filter is called by the container each time a request/response pair is
|
||||
* passed through the chain due to a client request for a resource at the end of the chain. The FilterChain passed
|
||||
* in to this method allows the Filter to pass on the request and response to the next entity in the chain.
|
||||
* <p>
|
||||
* A typical implementation of this method would follow the following pattern:- <br>
|
||||
* 1. Examine the request<br>
|
||||
* 2. Optionally wrap the request object with a custom implementation to filter content or headers for input
|
||||
* filtering <br>
|
||||
* 3. Optionally wrap the response object with a custom implementation to filter content or headers for output
|
||||
* filtering <br>
|
||||
* 4. a) <strong>Either</strong> invoke the next entity in the chain using the FilterChain object (
|
||||
* <code>chain.doFilter()</code>), <br>
|
||||
* 4. b) <strong>or</strong> not pass on the request/response pair to the next entity in the filter chain to block
|
||||
* the request processing<br>
|
||||
* 5. Directly set headers on the response after invocation of the next entity in the filter chain.
|
||||
**/
|
||||
public void doFilter(ServletContext context, ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
|
||||
ServletException;
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.filter.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.alfresco.repo.management.subsystems.ActivateableBean;
|
||||
|
||||
/**
|
||||
* A Benign filter that does nothing more than invoke the filter chain. Allows strategic points of the filter chain to
|
||||
* be configured in and out according to the authentication subsystem in use.
|
||||
*
|
||||
* @author dward
|
||||
*/
|
||||
public class NullFilter implements DependencyInjectedFilter, ActivateableBean
|
||||
{
|
||||
private boolean isActive = true;
|
||||
|
||||
/**
|
||||
* Activates or deactivates the bean
|
||||
*
|
||||
* @param active
|
||||
* <code>true</code> if the bean is active and initialization should complete
|
||||
*/
|
||||
public void setActive(boolean active)
|
||||
{
|
||||
this.isActive = active;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.management.subsystems.ActivateableBean#isActive()
|
||||
*/
|
||||
public boolean isActive()
|
||||
{
|
||||
return this.isActive;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.filter.beans.DependencyInjectedFilter#doFilter(javax.servlet.ServletContext,
|
||||
* javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
|
||||
*/
|
||||
public void doFilter(ServletContext context, ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.filter.beans;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* A filter that will use the HttpSession (if it exists) as the monitor for a
|
||||
* synchronized block so that only one request per session is processed at any
|
||||
* time.
|
||||
*
|
||||
* Originally created to avoid having to make 200+ JSF session scoped beans thread
|
||||
* safe.
|
||||
*
|
||||
* @author Alan Davis
|
||||
* @deprecated 5.0 not exposed in web-client web.xml
|
||||
*/
|
||||
public class SessionSynchronizedFilter implements Filter
|
||||
{
|
||||
@Override
|
||||
public void init(FilterConfig arg0) throws ServletException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response,
|
||||
FilterChain chain) throws IOException, ServletException
|
||||
{
|
||||
HttpSession session = null;
|
||||
if (request instanceof HttpServletRequest)
|
||||
{
|
||||
session = ((HttpServletRequest)request).getSession(false);
|
||||
}
|
||||
if (session != null)
|
||||
{
|
||||
synchronized(session)
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.mozilla.javascript.ContextFactory;
|
||||
import org.mozilla.javascript.tools.debugger.Dim;
|
||||
import org.mozilla.javascript.tools.debugger.SwingGui;
|
||||
import org.springframework.extensions.webscripts.ScriptDebugger;
|
||||
|
||||
|
||||
/**
|
||||
* Alfresco implementation of Rhino JavaScript debugger
|
||||
*
|
||||
* Provides support for authenticated access to object inspection.
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class AlfrescoRhinoScriptDebugger extends ScriptDebugger
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(AlfrescoRhinoScriptDebugger.class);
|
||||
|
||||
// Logger
|
||||
private ContextFactory factory = null;
|
||||
private SwingGui gui = null;
|
||||
|
||||
|
||||
@Override
|
||||
protected void initDebugger()
|
||||
{
|
||||
dim = new AlfrescoDim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
activate();
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle()
|
||||
{
|
||||
return "Alfresco Repository JavaScript Debugger";
|
||||
}
|
||||
|
||||
|
||||
public static class AlfrescoDim extends Dim
|
||||
{
|
||||
/* (non-Javadoc)
|
||||
* @see org.mozilla.javascript.tools.debugger.Dim#objectToString(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public String objectToString(final Object arg0)
|
||||
{
|
||||
// execute command in context of currently selected user
|
||||
return AuthenticationUtil.runAs(new RunAsWork<String>()
|
||||
{
|
||||
@SuppressWarnings("synthetic-access")
|
||||
public String doWork() throws Exception
|
||||
{
|
||||
return AlfrescoDim.super.objectToString(arg0);
|
||||
}
|
||||
}, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2018 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServlet;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public class AlfrescoWebScriptServlet extends WebScriptServlet
|
||||
{
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
super.service(req, res);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.springframework.extensions.surf.util.Content;
|
||||
import org.springframework.extensions.webscripts.Description.FormatStyle;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.Runtime;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptRequest;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
public class BufferedRequest implements WrappingWebScriptRequest
|
||||
{
|
||||
private TempOutputStreamFactory streamFactory;
|
||||
private WebScriptRequest req;
|
||||
private TempOutputStream bufferStream;
|
||||
private InputStream contentStream;
|
||||
private BufferedReader contentReader;
|
||||
|
||||
public BufferedRequest(WebScriptRequest req, TempOutputStreamFactory streamFactory)
|
||||
{
|
||||
this.req = req;
|
||||
this.streamFactory = streamFactory;
|
||||
}
|
||||
|
||||
private TempOutputStream getBufferedBodyAsTempStream() throws IOException
|
||||
{
|
||||
if (bufferStream == null)
|
||||
{
|
||||
bufferStream = streamFactory.createOutputStream();
|
||||
|
||||
try
|
||||
{
|
||||
// Copy the stream
|
||||
FileCopyUtils.copy(req.getContent().getInputStream(), bufferStream);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
bufferStream.destroy();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return bufferStream;
|
||||
}
|
||||
|
||||
private InputStream bufferInputStream() throws IOException
|
||||
{
|
||||
if (contentReader != null)
|
||||
{
|
||||
throw new IllegalStateException("Reader in use");
|
||||
}
|
||||
if (contentStream == null)
|
||||
{
|
||||
contentStream = getBufferedBodyAsTempStream().getInputStream();
|
||||
}
|
||||
|
||||
return contentStream;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
if (contentStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
contentStream.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
contentStream = null;
|
||||
}
|
||||
if (contentReader != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
contentReader.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
contentReader = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
reset();
|
||||
if (bufferStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bufferStream.destroy();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
bufferStream = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WrappingWebScriptRequest#getNext()
|
||||
*/
|
||||
@Override
|
||||
public WebScriptRequest getNext()
|
||||
{
|
||||
return req;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#forceSuccessStatus()
|
||||
*/
|
||||
@Override
|
||||
public boolean forceSuccessStatus()
|
||||
{
|
||||
return req.forceSuccessStatus();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getAgent()
|
||||
*/
|
||||
@Override
|
||||
public String getAgent()
|
||||
{
|
||||
return req.getAgent();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getContent()
|
||||
*/
|
||||
@Override
|
||||
public Content getContent()
|
||||
{
|
||||
final Content wrapped = req.getContent();
|
||||
return new Content(){
|
||||
|
||||
@Override
|
||||
public String getContent() throws IOException
|
||||
{
|
||||
return wrapped.getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncoding()
|
||||
{
|
||||
return wrapped.getEncoding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimetype()
|
||||
{
|
||||
return wrapped.getMimetype();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSize()
|
||||
{
|
||||
return wrapped.getSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
if (BufferedRequest.this.contentReader != null)
|
||||
{
|
||||
throw new IllegalStateException("Reader in use");
|
||||
}
|
||||
if (BufferedRequest.this.contentStream == null)
|
||||
{
|
||||
try
|
||||
{
|
||||
BufferedRequest.this.contentStream = bufferInputStream();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return BufferedRequest.this.contentStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException
|
||||
{
|
||||
if (BufferedRequest.this.contentStream != null)
|
||||
{
|
||||
throw new IllegalStateException("Input Stream in use");
|
||||
}
|
||||
if (BufferedRequest.this.contentReader == null)
|
||||
{
|
||||
String encoding = wrapped.getEncoding();
|
||||
InputStream in = bufferInputStream();
|
||||
BufferedRequest.this.contentReader = new BufferedReader(new InputStreamReader(in, encoding == null ? "ISO-8859-1" : encoding));
|
||||
}
|
||||
return BufferedRequest.this.contentReader;
|
||||
}
|
||||
};
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getContentType()
|
||||
*/
|
||||
@Override
|
||||
public String getContentType()
|
||||
{
|
||||
return req.getContentType();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getContextPath()
|
||||
*/
|
||||
@Override
|
||||
public String getContextPath()
|
||||
{
|
||||
return req.getContextPath();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getExtensionPath()
|
||||
*/
|
||||
@Override
|
||||
public String getExtensionPath()
|
||||
{
|
||||
return req.getExtensionPath();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getFormat()
|
||||
*/
|
||||
@Override
|
||||
public String getFormat()
|
||||
{
|
||||
return req.getFormat();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getFormatStyle()
|
||||
*/
|
||||
@Override
|
||||
public FormatStyle getFormatStyle()
|
||||
{
|
||||
return req.getFormatStyle();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getHeader(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
return req.getHeader(name);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderNames()
|
||||
*/
|
||||
@Override
|
||||
public String[] getHeaderNames()
|
||||
{
|
||||
return req.getHeaderNames();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getHeaderValues(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String[] getHeaderValues(String name)
|
||||
{
|
||||
return req.getHeaderValues(name);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getJSONCallback()
|
||||
*/
|
||||
@Override
|
||||
public String getJSONCallback()
|
||||
{
|
||||
return req.getJSONCallback();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getParameter(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String getParameter(String name)
|
||||
{
|
||||
return req.getParameter(name);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterNames()
|
||||
*/
|
||||
@Override
|
||||
public String[] getParameterNames()
|
||||
{
|
||||
return req.getParameterNames();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getParameterValues(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public String[] getParameterValues(String name)
|
||||
{
|
||||
return req.getParameterValues(name);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getPathInfo()
|
||||
*/
|
||||
@Override
|
||||
public String getPathInfo()
|
||||
{
|
||||
return req.getPathInfo();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getQueryString()
|
||||
*/
|
||||
@Override
|
||||
public String getQueryString()
|
||||
{
|
||||
return req.getQueryString();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getRuntime()
|
||||
*/
|
||||
@Override
|
||||
public Runtime getRuntime()
|
||||
{
|
||||
return req.getRuntime();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getServerPath()
|
||||
*/
|
||||
@Override
|
||||
public String getServerPath()
|
||||
{
|
||||
return req.getServerPath();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceContextPath()
|
||||
*/
|
||||
@Override
|
||||
public String getServiceContextPath()
|
||||
{
|
||||
return req.getServiceContextPath();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getServiceMatch()
|
||||
*/
|
||||
@Override
|
||||
public Match getServiceMatch()
|
||||
{
|
||||
return req.getServiceMatch();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getServicePath()
|
||||
*/
|
||||
@Override
|
||||
public String getServicePath()
|
||||
{
|
||||
return req.getServicePath();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#getURL()
|
||||
*/
|
||||
@Override
|
||||
public String getURL()
|
||||
{
|
||||
return req.getURL();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#isGuest()
|
||||
*/
|
||||
@Override
|
||||
public boolean isGuest()
|
||||
{
|
||||
return req.isGuest();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptRequest#parseContent()
|
||||
*/
|
||||
@Override
|
||||
public Object parseContent()
|
||||
{
|
||||
return req.parseContent();
|
||||
}
|
||||
}
|
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.StringBuilderWriter;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Runtime;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
import org.springframework.extensions.webscripts.WrappingWebScriptResponse;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Transactional Buffered Response
|
||||
*/
|
||||
public class BufferedResponse implements WrappingWebScriptResponse
|
||||
{
|
||||
// Logger
|
||||
protected static final Log logger = LogFactory.getLog(BufferedResponse.class);
|
||||
|
||||
private TempOutputStreamFactory streamFactory;
|
||||
private WebScriptResponse res;
|
||||
private int bufferSize;
|
||||
private TempOutputStream outputStream = null;
|
||||
private StringBuilderWriter outputWriter = null;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param res WebScriptResponse
|
||||
* @param bufferSize int
|
||||
*/
|
||||
public BufferedResponse(WebScriptResponse res, int bufferSize, TempOutputStreamFactory streamFactory)
|
||||
{
|
||||
this.res = res;
|
||||
this.bufferSize = bufferSize;
|
||||
this.streamFactory = streamFactory;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WrappingWebScriptResponse#getNext()
|
||||
*/
|
||||
public WebScriptResponse getNext()
|
||||
{
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#addHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void addHeader(String name, String value)
|
||||
{
|
||||
res.addHeader(name, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#encodeScriptUrl(java.lang.String)
|
||||
*/
|
||||
public String encodeScriptUrl(String url)
|
||||
{
|
||||
return res.encodeScriptUrl(url);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#getEncodeScriptUrlFunction(java.lang.String)
|
||||
*/
|
||||
public String getEncodeScriptUrlFunction(String name)
|
||||
{
|
||||
return res.getEncodeScriptUrlFunction(name);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptResponse#encodeResourceUrl(java.lang.String)
|
||||
*/
|
||||
public String encodeResourceUrl(String url)
|
||||
{
|
||||
return res.encodeResourceUrl(url);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.WebScriptResponse#getEncodeResourceUrlFunction(java.lang.String)
|
||||
*/
|
||||
public String getEncodeResourceUrlFunction(String name)
|
||||
{
|
||||
return res.getEncodeResourceUrlFunction(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#getOutputStream()
|
||||
*/
|
||||
public OutputStream getOutputStream() throws IOException
|
||||
{
|
||||
if (outputStream == null)
|
||||
{
|
||||
if (outputWriter != null)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Already buffering output writer");
|
||||
}
|
||||
outputStream = streamFactory.createOutputStream();
|
||||
}
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#getRuntime()
|
||||
*/
|
||||
public Runtime getRuntime()
|
||||
{
|
||||
return res.getRuntime();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#getWriter()
|
||||
*/
|
||||
public Writer getWriter() throws IOException
|
||||
{
|
||||
if (outputWriter == null)
|
||||
{
|
||||
if (outputStream != null)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Already buffering output stream");
|
||||
}
|
||||
outputWriter = new StringBuilderWriter(bufferSize);
|
||||
}
|
||||
return outputWriter;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
if (outputStream != null)
|
||||
{
|
||||
outputStream = null;
|
||||
}
|
||||
else if (outputWriter != null)
|
||||
{
|
||||
outputWriter = null;
|
||||
}
|
||||
res.reset();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org./alfresco.web.scripts.WebScriptResponse#resetjava.lang.String)
|
||||
*/
|
||||
public void reset(String preserveHeadersPattern)
|
||||
{
|
||||
if (outputStream != null)
|
||||
{
|
||||
outputStream = null;
|
||||
}
|
||||
else if (outputWriter != null)
|
||||
{
|
||||
outputWriter = null;
|
||||
}
|
||||
res.reset(preserveHeadersPattern);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#setCache(org.alfresco.web.scripts.Cache)
|
||||
*/
|
||||
public void setCache(Cache cache)
|
||||
{
|
||||
res.setCache(cache);
|
||||
}
|
||||
|
||||
/*
|
||||
* (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#setContentEncoding(java.lang.String)
|
||||
*/
|
||||
public void setContentEncoding(String contentEncoding)
|
||||
{
|
||||
res.setContentEncoding(contentEncoding);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#setHeader(java.lang.String, java.lang.String)
|
||||
*/
|
||||
public void setHeader(String name, String value)
|
||||
{
|
||||
res.setHeader(name, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptResponse#setStatus(int)
|
||||
*/
|
||||
public void setStatus(int status)
|
||||
{
|
||||
res.setStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write buffered response to underlying response
|
||||
*/
|
||||
public void writeResponse()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled() && outputStream != null)
|
||||
{
|
||||
logger.debug("Writing Transactional response: size=" + outputStream.getLength());
|
||||
}
|
||||
|
||||
if (outputWriter != null)
|
||||
{
|
||||
outputWriter.flush();
|
||||
res.getWriter().write(outputWriter.toString());
|
||||
}
|
||||
else if (outputStream != null)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Writing Transactional response: size=" + outputStream.getLength());
|
||||
|
||||
try
|
||||
{
|
||||
outputStream.flush();
|
||||
FileCopyUtils.copy(outputStream.getInputStream(), res.getOutputStream());
|
||||
}
|
||||
finally
|
||||
{
|
||||
outputStream.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Failed to commit buffered response", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,427 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.alfresco.repo.content.MimetypeMap;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.Pair;
|
||||
import org.apache.commons.csv.CSVPrinter;
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CellStyle;
|
||||
import org.apache.poi.ss.usermodel.ClientAnchor;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
import org.apache.poi.ss.usermodel.Drawing;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.usermodel.Sheet;
|
||||
import org.apache.poi.ss.usermodel.Workbook;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Parent of Declarative Webscripts that generate Excel files,
|
||||
* usually based on some sort of dictionary model.
|
||||
*
|
||||
* @author Nick Burch
|
||||
*/
|
||||
public abstract class DeclarativeSpreadsheetWebScript extends DeclarativeWebScript
|
||||
{
|
||||
public static final String MODEL_CSV = "csv";
|
||||
public static final String MODEL_EXCEL = "excel";
|
||||
public static final String PARAM_REQ_DELIMITER = "delimiter";
|
||||
|
||||
private CSVFormat csvFormat;
|
||||
|
||||
protected DictionaryService dictionaryService;
|
||||
protected String filenameBase;
|
||||
|
||||
/**
|
||||
* @param dictionaryService the DictionaryService to set
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the resource for the webscript.
|
||||
*/
|
||||
protected abstract Object identifyResource(String format, WebScriptRequest req);
|
||||
|
||||
/**
|
||||
* If the format is requested as HTML, should an exception be raised,
|
||||
* or should an HTML version be called?
|
||||
*/
|
||||
protected abstract boolean allowHtmlFallback();
|
||||
|
||||
/**
|
||||
* Returns the QNames of the model properties to be output in
|
||||
* the header, and if they're required or not
|
||||
*/
|
||||
protected abstract List<Pair<QName, Boolean>> buildPropertiesForHeader(Object resource, String format, WebScriptRequest req);
|
||||
|
||||
/**
|
||||
* Populates the body of the Excel Workbook, once the header has been
|
||||
* output.
|
||||
* This is called if the format is .xls or .xlsx
|
||||
*/
|
||||
protected abstract void populateBody(Object resource, Workbook workbook, Sheet sheet, List<QName> properties)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Populates the body of the CSV file, once the header has been
|
||||
* output.
|
||||
* This is called if the format is .csv
|
||||
*/
|
||||
protected abstract void populateBody(Object resource, CSVPrinter csv, List<QName> properties)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* Set the CSVFormat
|
||||
*
|
||||
* @param csvFormat CSVFormat
|
||||
*/
|
||||
public void setCsvFormat(CSVFormat csvFormat)
|
||||
{
|
||||
this.csvFormat = csvFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CSVFormat. Returns {@link CSVFormat#EXCEL} if none was set.
|
||||
*
|
||||
* @return CSVFormat
|
||||
*/
|
||||
public CSVFormat getCsvFormat()
|
||||
{
|
||||
if (csvFormat == null)
|
||||
{
|
||||
return CSVFormat.EXCEL
|
||||
.withQuote('"')
|
||||
.withRecordSeparator("\n")
|
||||
.withFirstRecordAsHeader();
|
||||
}
|
||||
else
|
||||
{
|
||||
return csvFormat;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.extensions.webscripts.DeclarativeWebScript#executeImpl(org.springframework.extensions.webscripts.WebScriptRequest, org.springframework.extensions.webscripts.Status)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("success", Boolean.TRUE);
|
||||
|
||||
// What format are they after?
|
||||
String format = req.getFormat();
|
||||
if("csv".equals(format) || "xls".equals(format) ||
|
||||
"xlsx".equals(format) || "excel".equals(format))
|
||||
{
|
||||
// Identify the thing to process
|
||||
Object resource = identifyResource(format, req);
|
||||
|
||||
// Generate the spreadsheet
|
||||
try
|
||||
{
|
||||
generateSpreadsheet(resource, format, req, status, model);
|
||||
return model;
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST,
|
||||
"Unable to generate template file", e);
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, then it isn't a spreadsheet version
|
||||
if(allowHtmlFallback())
|
||||
{
|
||||
// There's some sort of help / upload form
|
||||
return model;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WebScriptException("Web Script format '" + format + "' is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the spreadsheet, based on the properties in the header
|
||||
* and a callback for the body.
|
||||
*/
|
||||
public void generateSpreadsheet(Object resource, String format, WebScriptRequest req,
|
||||
Status status, Map<String, Object> model) throws IOException
|
||||
{
|
||||
Pattern qnameMunger = Pattern.compile("([A-Z][a-z]+)([A-Z].*)");
|
||||
String delimiterParam = req.getParameter(PARAM_REQ_DELIMITER);
|
||||
CSVFormat reqCSVFormat = null;
|
||||
|
||||
if (delimiterParam != null && !delimiterParam.isEmpty())
|
||||
{
|
||||
reqCSVFormat = CSVFormat.EXCEL
|
||||
.withDelimiter(delimiterParam.charAt(0))
|
||||
.withQuote('"')
|
||||
.withRecordSeparator("\n")
|
||||
.withFirstRecordAsHeader();
|
||||
}
|
||||
|
||||
// Build up the details of the header
|
||||
List<Pair<QName, Boolean>> propertyDetails = buildPropertiesForHeader(resource, format, req);
|
||||
String[] headings = new String[propertyDetails.size()];
|
||||
String[] descriptions = new String[propertyDetails.size()];
|
||||
boolean[] required = new boolean[propertyDetails.size()];
|
||||
for(int i=0; i<headings.length; i++)
|
||||
{
|
||||
Pair<QName, Boolean> property = propertyDetails.get(i);
|
||||
if(property == null || property.getFirst() == null)
|
||||
{
|
||||
headings[i] = "";
|
||||
required[i] = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QName column = property.getFirst();
|
||||
required[i] = property.getSecond();
|
||||
|
||||
// Ask the dictionary service nicely for the details
|
||||
PropertyDefinition pd = dictionaryService.getProperty(column);
|
||||
if(pd != null && pd.getTitle(dictionaryService) != null)
|
||||
{
|
||||
// Use the friendly titles, which may even be localised!
|
||||
headings[i] = pd.getTitle(dictionaryService);
|
||||
descriptions[i] = pd.getDescription(dictionaryService);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing friendly found, try to munge the raw qname into
|
||||
// something we can show to a user...
|
||||
String raw = column.getLocalName();
|
||||
raw = raw.substring(0, 1).toUpperCase() + raw.substring(1);
|
||||
|
||||
Matcher m = qnameMunger.matcher(raw);
|
||||
if(m.matches())
|
||||
{
|
||||
headings[i] = m.group(1) + " " + m.group(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
headings[i] = raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build a list of just the properties
|
||||
List<QName> properties = new ArrayList<QName>(propertyDetails.size());
|
||||
for(Pair<QName,Boolean> p : propertyDetails)
|
||||
{
|
||||
QName qn = null;
|
||||
if(p != null)
|
||||
{
|
||||
qn = p.getFirst();
|
||||
}
|
||||
properties.add(qn);
|
||||
}
|
||||
|
||||
// Output
|
||||
if("csv".equals(format))
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
CSVPrinter csv = new CSVPrinter(sw, reqCSVFormat != null ? reqCSVFormat : getCsvFormat());
|
||||
csv.printRecord(headings);
|
||||
|
||||
populateBody(resource, csv, properties);
|
||||
|
||||
model.put(MODEL_CSV, sw.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
Workbook wb;
|
||||
if("xlsx".equals(format))
|
||||
{
|
||||
wb = new XSSFWorkbook();
|
||||
// TODO Properties
|
||||
}
|
||||
else
|
||||
{
|
||||
wb = new HSSFWorkbook();
|
||||
// TODO Properties
|
||||
}
|
||||
|
||||
// Add our header row
|
||||
Sheet sheet = wb.createSheet("Export");
|
||||
Row hr = sheet.createRow(0);
|
||||
sheet.createFreezePane(0, 1);
|
||||
|
||||
Font fb = wb.createFont();
|
||||
fb.setBold(true);
|
||||
Font fi = wb.createFont();
|
||||
fi.setBold(true);
|
||||
fi.setItalic(true);
|
||||
|
||||
CellStyle csReq = wb.createCellStyle();
|
||||
csReq.setFont(fb);
|
||||
CellStyle csOpt = wb.createCellStyle();
|
||||
csOpt.setFont(fi);
|
||||
|
||||
// Populate the header
|
||||
Drawing draw = null;
|
||||
for(int i=0; i<headings.length; i++)
|
||||
{
|
||||
Cell c = hr.createCell(i);
|
||||
c.setCellValue(headings[i]);
|
||||
|
||||
if(required[i])
|
||||
{
|
||||
c.setCellStyle(csReq);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.setCellStyle(csOpt);
|
||||
}
|
||||
|
||||
if(headings[i].length() == 0)
|
||||
{
|
||||
sheet.setColumnWidth(i, 3*250);
|
||||
}
|
||||
else
|
||||
{
|
||||
sheet.setColumnWidth(i, 18*250);
|
||||
}
|
||||
|
||||
if(descriptions[i] != null && descriptions[i].length() > 0)
|
||||
{
|
||||
// Add a description for it too
|
||||
if(draw == null)
|
||||
{
|
||||
draw = sheet.createDrawingPatriarch();
|
||||
}
|
||||
ClientAnchor ca = wb.getCreationHelper().createClientAnchor();
|
||||
ca.setCol1(c.getColumnIndex());
|
||||
ca.setCol2(c.getColumnIndex()+1);
|
||||
ca.setRow1(hr.getRowNum());
|
||||
ca.setRow2(hr.getRowNum()+2);
|
||||
|
||||
Comment cmt = draw.createCellComment(ca);
|
||||
cmt.setAuthor("");
|
||||
cmt.setString(wb.getCreationHelper().createRichTextString(descriptions[i]));
|
||||
cmt.setVisible(false);
|
||||
c.setCellComment(cmt);
|
||||
}
|
||||
}
|
||||
|
||||
// Have the contents populated
|
||||
populateBody(resource, wb, sheet, properties);
|
||||
|
||||
// Save it for the template
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
wb.write(baos);
|
||||
model.put(MODEL_EXCEL, baos.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> createTemplateParameters(WebScriptRequest req, WebScriptResponse res,
|
||||
Map<String, Object> customParams)
|
||||
{
|
||||
Map<String, Object> model = super.createTemplateParameters(req, res, customParams);
|
||||
// We sometimes need to monkey around to do the binary output...
|
||||
model.put("req", req);
|
||||
model.put("res", res);
|
||||
model.put("writeExcel", new WriteExcel(res, model, req.getFormat(), filenameBase));
|
||||
return model;
|
||||
}
|
||||
|
||||
public static class WriteExcel
|
||||
{
|
||||
private String format;
|
||||
private String filenameBase;
|
||||
private WebScriptResponse res;
|
||||
private Map<String, Object> model;
|
||||
private WriteExcel(WebScriptResponse res, Map<String, Object> model, String format, String filenameBase)
|
||||
{
|
||||
this.res = res;
|
||||
this.model = model;
|
||||
this.format = format;
|
||||
this.filenameBase = filenameBase;
|
||||
}
|
||||
public void write() throws IOException
|
||||
{
|
||||
String filename = filenameBase + "." + format;
|
||||
|
||||
// If it isn't a CSV, reset so we can send binary
|
||||
if(! "csv".equals(format))
|
||||
{
|
||||
res.reset();
|
||||
}
|
||||
|
||||
// Tell the browser it's a file download
|
||||
res.addHeader("Content-Disposition", "attachment; filename=" + filename);
|
||||
|
||||
// Now send that data
|
||||
if("csv".equals(format))
|
||||
{
|
||||
res.getWriter().append((String)model.get(MODEL_CSV));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the mimetype, as we've reset
|
||||
if("xlsx".equals(format))
|
||||
{
|
||||
res.setContentType(MimetypeMap.MIMETYPE_OPENXML_SPREADSHEET);
|
||||
} else {
|
||||
res.setContentType(MimetypeMap.MIMETYPE_EXCEL);
|
||||
}
|
||||
|
||||
// Send the raw excel bytes
|
||||
byte[] excel = (byte[])model.get(MODEL_EXCEL);
|
||||
res.getOutputStream().write(excel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.io.Writer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.dom4j.Element;
|
||||
|
||||
import org.springframework.extensions.config.ConfigImpl;
|
||||
|
||||
import org.springframework.extensions.config.ConfigSection;
|
||||
|
||||
import org.springframework.extensions.config.ConfigService;
|
||||
|
||||
import org.springframework.extensions.config.evaluator.Evaluator;
|
||||
|
||||
import org.springframework.extensions.config.xml.XMLConfigService;
|
||||
|
||||
import org.springframework.extensions.config.xml.elementreader.ConfigElementReader;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.BasicExtensionModule;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.ExtensibilityModel;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.HandlesExtensibility;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.WebScriptExtensibilityModuleHandler;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.impl.ExtensibilityModelImpl;
|
||||
|
||||
import org.springframework.extensions.surf.extensibility.impl.MarkupDirective;
|
||||
|
||||
import org.springframework.extensions.webscripts.Authenticator;
|
||||
|
||||
import org.springframework.extensions.webscripts.ExtendedScriptConfigModel;
|
||||
|
||||
import org.springframework.extensions.webscripts.ExtendedTemplateConfigModel;
|
||||
|
||||
import org.springframework.extensions.webscripts.ScriptConfigModel;
|
||||
|
||||
import org.springframework.extensions.webscripts.TemplateConfigModel;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptPropertyResourceBundle;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>A simple extensibility {@link org.springframework.extensions.webscripts.Container} for processing WebScripts. This extends the {@link RepositoryContainer} and
|
||||
|
||||
* implements the {@link HandlesExtensibility} interface to provide extensibility capabilities.</p>
|
||||
|
||||
*
|
||||
|
||||
* @author David Draper
|
||||
|
||||
*/
|
||||
|
||||
public class ExtensibilityContainer extends RepositoryContainer implements HandlesExtensibility
|
||||
|
||||
{
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ExtensibilityContainer.class);
|
||||
|
||||
|
||||
|
||||
public boolean isExtensibilitySuppressed()
|
||||
|
||||
{
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Opens a new {@link ExtensibilityModel}, defers execution to the extended {@link RepositoryContainer} and
|
||||
|
||||
* then closes the {@link ExtensibilityModel}.</p>
|
||||
|
||||
*/
|
||||
|
||||
@Override
|
||||
|
||||
public void executeScript(WebScriptRequest scriptReq,
|
||||
|
||||
WebScriptResponse scriptRes,
|
||||
|
||||
Authenticator auth) throws IOException
|
||||
|
||||
{
|
||||
|
||||
ExtensibilityModel extModel = this.openExtensibilityModel();
|
||||
|
||||
try
|
||||
|
||||
{
|
||||
|
||||
super.executeScript(scriptReq, scriptRes, auth);
|
||||
|
||||
}
|
||||
|
||||
finally
|
||||
|
||||
{
|
||||
|
||||
// It's only necessary to close the model if it's actually been used. Not all WebScripts will make use of the
|
||||
|
||||
// model. An example of this would be the StreamContent WebScript. It is important not to attempt to close
|
||||
|
||||
// an unused model since the WebScript executed may have already flushed the response if it has overridden
|
||||
|
||||
// the default .execute() method.
|
||||
|
||||
if (this.modelUsed.get())
|
||||
|
||||
{
|
||||
|
||||
try
|
||||
|
||||
{
|
||||
|
||||
this.closeExtensibilityModel(extModel, scriptRes.getWriter());
|
||||
|
||||
}
|
||||
|
||||
catch (IOException e)
|
||||
|
||||
{
|
||||
|
||||
logger.error("An error occurred getting the Writer when closing an ExtensibilityModel", e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>This keeps track of whether or not the {@link ExtensibilityModel} for the current thread has been used. The
|
||||
|
||||
* thread local value will only be set to <code>true</code> if the <code>getCurrentExtensibilityModel</code> method
|
||||
|
||||
* is called.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<Boolean> modelUsed = new ThreadLocal<Boolean>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>A {@link WebScriptExtensibilityModuleHandler} is required for retrieving information on what
|
||||
|
||||
* {@link BasicExtensionModule} instances have been configured and the extension files that need
|
||||
|
||||
* to be processed. This variable should be set thorugh the Spring application context configuration.</p>
|
||||
|
||||
*/
|
||||
|
||||
private WebScriptExtensibilityModuleHandler extensibilityModuleHandler = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Sets the {@link WebScriptExtensibilityModuleHandler} for this {@link org.springframework.extensions.webscripts.Container}.</p>
|
||||
|
||||
* @param extensibilityModuleHandler WebScriptExtensibilityModuleHandler
|
||||
|
||||
*/
|
||||
|
||||
public void setExtensibilityModuleHandler(WebScriptExtensibilityModuleHandler extensibilityModuleHandler)
|
||||
|
||||
{
|
||||
|
||||
this.extensibilityModuleHandler = extensibilityModuleHandler;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Maintains a list of all the {@link ExtensibilityModel} instances being used across all the
|
||||
|
||||
* available threads.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<ExtensibilityModel> extensibilityModel = new ThreadLocal<ExtensibilityModel>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Creates a new {@link ExtensibilityModel} and sets it on the current thread</p>
|
||||
|
||||
*/
|
||||
|
||||
public ExtensibilityModel openExtensibilityModel()
|
||||
|
||||
{
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
|
||||
{
|
||||
|
||||
logger.debug("Opening for thread: " + Thread.currentThread().getName());
|
||||
|
||||
}
|
||||
|
||||
this.extendedBundleCache.set(new HashMap<String, WebScriptPropertyResourceBundle>());
|
||||
|
||||
this.evaluatedModules.set(null);
|
||||
|
||||
this.fileBeingProcessed.set(null);
|
||||
|
||||
this.globalConfig.set(null);
|
||||
|
||||
this.sections.set(null);
|
||||
|
||||
this.sectionsByArea.set(null);
|
||||
|
||||
|
||||
|
||||
ExtensibilityModel model = new ExtensibilityModelImpl(null, this);
|
||||
|
||||
this.extensibilityModel.set(model);
|
||||
|
||||
this.modelUsed.set(Boolean.FALSE);
|
||||
|
||||
return model;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Flushes the {@link ExtensibilityModel} provided and sets its parent as the current {@link ExtensibilityModel}
|
||||
|
||||
* for the current thread.</p>
|
||||
|
||||
*/
|
||||
|
||||
public void closeExtensibilityModel(ExtensibilityModel model, Writer out)
|
||||
|
||||
{
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
|
||||
{
|
||||
|
||||
logger.debug("Closing for thread: " + Thread.currentThread().getName());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
model.flushModel(out);
|
||||
|
||||
this.modelUsed.set(Boolean.FALSE);
|
||||
|
||||
this.extensibilityModel.set(null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Returns the {@link ExtensibilityModel} for the current thread.</p>
|
||||
|
||||
*/
|
||||
|
||||
public ExtensibilityModel getCurrentExtensibilityModel()
|
||||
|
||||
{
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
|
||||
{
|
||||
|
||||
logger.debug("Getting current for thread: " + Thread.currentThread().getName());
|
||||
|
||||
}
|
||||
|
||||
this.modelUsed.set(Boolean.TRUE);
|
||||
|
||||
return this.extensibilityModel.get();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>This method is implemented to perform no action as it is not necessary for a standalone WebScript
|
||||
|
||||
* container to add dependencies for processing.</p>
|
||||
|
||||
*/
|
||||
|
||||
public void updateExtendingModuleDependencies(String pathBeingProcessed, Map<String, Object> model)
|
||||
|
||||
{
|
||||
|
||||
// NOT REQUIRED FOR STANDALONE WEBSCRIPT CONTAINER
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>A thread-safe cache of extended {@link ResourceBundle} instances for the current request.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<Map<String, WebScriptPropertyResourceBundle>> extendedBundleCache = new ThreadLocal<Map<String, WebScriptPropertyResourceBundle>>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Checks the cache to see if it has cached an extended bundle (that is a basic {@link ResourceBundle} that
|
||||
|
||||
* has had extension modules applied to it. Extended bundles can only be safely cached once per request as the modules
|
||||
|
||||
* applied can vary for each request.</p>
|
||||
|
||||
*
|
||||
|
||||
* @param webScriptId The id of the WebScript to retrieve the extended bundle for.
|
||||
|
||||
* @return A cached bundle or <code>null</code> if the bundle has not previously been cached.
|
||||
|
||||
*/
|
||||
|
||||
public ResourceBundle getCachedExtendedBundle(String webScriptId)
|
||||
|
||||
{
|
||||
|
||||
ResourceBundle cachedExtendedBundle = null;
|
||||
|
||||
Map<String, WebScriptPropertyResourceBundle> threadLocal = this.extendedBundleCache.get();
|
||||
|
||||
if (threadLocal != null)
|
||||
|
||||
{
|
||||
|
||||
cachedExtendedBundle = this.extendedBundleCache.get().get(webScriptId);
|
||||
|
||||
}
|
||||
|
||||
return cachedExtendedBundle;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Adds a new extended bundle to the cache. An extended bundle is a WebScript {@link ResourceBundle} that has had
|
||||
|
||||
* {@link ResourceBundle} instances merged into it from extension modules that have been applied. These can only be cached
|
||||
|
||||
* for the lifetime of the request as different modules may be applied to the same WebScript for different requests.</p>
|
||||
|
||||
*
|
||||
|
||||
* @param webScriptId The id of the WebScript to cache the extended bundle against.
|
||||
|
||||
* @param extensionBundle The extended bundle to cache.
|
||||
|
||||
*/
|
||||
|
||||
public void addExtensionBundleToCache(String webScriptId, WebScriptPropertyResourceBundle extensionBundle)
|
||||
|
||||
{
|
||||
|
||||
Map<String, WebScriptPropertyResourceBundle> threadLocal = this.extendedBundleCache.get();
|
||||
|
||||
if (threadLocal == null)
|
||||
|
||||
{
|
||||
|
||||
// This should never be the case because when a new model is opened this value should be reset
|
||||
|
||||
// but we will double-check to avoid the potential of NPEs...
|
||||
|
||||
threadLocal = new HashMap<String, WebScriptPropertyResourceBundle>();
|
||||
|
||||
this.extendedBundleCache.set(threadLocal);
|
||||
|
||||
}
|
||||
|
||||
threadLocal.put(webScriptId, extensionBundle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>A {@link ThreadLocal} reference to the file currently being processed in the model.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<String> fileBeingProcessed = new ThreadLocal<String>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Returns the path of the file currently being processed in the model by the current thread.
|
||||
|
||||
* This information is primarily provided for the purposes of generating debug information.</p>
|
||||
|
||||
*
|
||||
|
||||
* @return The path of the file currently being processed.
|
||||
|
||||
*/
|
||||
|
||||
public String getFileBeingProcessed()
|
||||
|
||||
{
|
||||
|
||||
return this.fileBeingProcessed.get();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Sets the path of the file currently being processed in the model by the current thread.
|
||||
|
||||
* This information should be collected to assist with providing debug information.</p>
|
||||
|
||||
* @param file The path of the file currently being processed.
|
||||
|
||||
*/
|
||||
|
||||
public void setFileBeingProcessed(String file)
|
||||
|
||||
{
|
||||
|
||||
this.fileBeingProcessed.set(file);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Retrieves an files for the evaluated modules that are extending the WebScript files being processed.</p>
|
||||
|
||||
*/
|
||||
|
||||
public List<String> getExtendingModuleFiles(String pathBeingProcessed)
|
||||
|
||||
{
|
||||
|
||||
List<String> extendingModuleFiles = new ArrayList<String>();
|
||||
|
||||
for (BasicExtensionModule module: this.getEvaluatedModules())
|
||||
|
||||
{
|
||||
|
||||
extendingModuleFiles.addAll(this.extensibilityModuleHandler.getExtendingModuleFiles(module, pathBeingProcessed));
|
||||
|
||||
}
|
||||
|
||||
return extendingModuleFiles;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>The list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable to
|
||||
|
||||
* this RequestContext. This is set to <code>null</code> when during instantiation and is only
|
||||
|
||||
* properly set the first time the <code>getEvaluatedModules</code> method is invoked. This ensures
|
||||
|
||||
* that module evaluation only occurs once per request.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<List<BasicExtensionModule>> evaluatedModules = new ThreadLocal<List<BasicExtensionModule>>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Retrieve the list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that have been evaluated as applicable
|
||||
|
||||
* for the current request. If this list has not yet been populated then use the {@link org.springframework.extensions.surf.extensibility.ExtensibilityModuleHandler}
|
||||
|
||||
* configured in the Spring application context to evaluate them.</p>
|
||||
|
||||
*
|
||||
|
||||
* @return A list of {@link org.springframework.extensions.surf.types.ExtensionModule} instances that are applicable to the current request.
|
||||
|
||||
*/
|
||||
|
||||
public List<BasicExtensionModule> getEvaluatedModules()
|
||||
|
||||
{
|
||||
|
||||
List<BasicExtensionModule> evaluatedModules = this.evaluatedModules.get();
|
||||
|
||||
if (evaluatedModules == null)
|
||||
|
||||
{
|
||||
|
||||
if (this.extensibilityModuleHandler == null)
|
||||
|
||||
{
|
||||
|
||||
if (logger.isErrorEnabled())
|
||||
|
||||
{
|
||||
|
||||
logger.error("No 'extensibilityModuleHandler' has been configured for this request context. Extensions cannot be processed");
|
||||
|
||||
}
|
||||
|
||||
evaluatedModules = new ArrayList<BasicExtensionModule>();
|
||||
|
||||
this.evaluatedModules.set(evaluatedModules);
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
{
|
||||
|
||||
evaluatedModules = this.extensibilityModuleHandler.getExtensionModules();
|
||||
|
||||
this.evaluatedModules.set(evaluatedModules);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return evaluatedModules;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>This is a local {@link ConfigImpl} instance that will only be used when extension modules are employed. It will
|
||||
|
||||
* initially be populated with the default "static" global configuration taken from the {@link ConfigService} associated
|
||||
|
||||
* with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include global configuration provided by extension modules that
|
||||
|
||||
* have been evaluated to be applied to the current request.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<ConfigImpl> globalConfig = new ThreadLocal<ConfigImpl>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>This map represents {@link ConfigSection} instances mapped by area. It will only be used when extension modules are
|
||||
|
||||
* employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated
|
||||
|
||||
* with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated
|
||||
|
||||
* to be applied to the current request.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<Map<String, List<ConfigSection>>> sectionsByArea = new ThreadLocal<Map<String,List<ConfigSection>>>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>A list of {@link ConfigSection} instances that are only applicable to the current request. It will only be used when extension modules are
|
||||
|
||||
* employed. It will initially be populated with the default "static" configuration taken from the {@link ConfigService} associated
|
||||
|
||||
* with this {@link org.springframework.extensions.surf.RequestContext} but then updated to include configuration provided by extension modules that have been evaluated
|
||||
|
||||
* to be applied to the current request.</p>
|
||||
|
||||
*/
|
||||
|
||||
private ThreadLocal<List<ConfigSection>> sections = new ThreadLocal<List<ConfigSection>>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Creates a new {@link ExtendedScriptConfigModel} instance using the local configuration generated for this request.
|
||||
|
||||
* If configuration for the request will be generated if it does not yet exist. It is likely that this method will be
|
||||
|
||||
* called multiple times within the context of a single request and although the configuration containers will always
|
||||
|
||||
* be the same a new {@link ExtendedScriptConfigModel} instance will always be created as the the supplied <code>xmlConfig</code>
|
||||
|
||||
* string could be different for each call (because each WebScript invoked in the request will supply different
|
||||
|
||||
* configuration.</p>
|
||||
|
||||
*/
|
||||
|
||||
public ScriptConfigModel getExtendedScriptConfigModel(String xmlConfig)
|
||||
|
||||
{
|
||||
|
||||
if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null)
|
||||
|
||||
{
|
||||
|
||||
this.getConfigExtensions();
|
||||
|
||||
}
|
||||
|
||||
return new ExtendedScriptConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Creates a new {@link TemplateConfigModel} instance using the local configuration generated for this request.
|
||||
|
||||
* If configuration for the request will be generated if it does not yet exist. It is likely that this method will be
|
||||
|
||||
* called multiple times within the context of a single request and although the configuration containers will always
|
||||
|
||||
* be the same a new {@link TemplateConfigModel} instance will always be created as the the supplied <code>xmlConfig</code>
|
||||
|
||||
* string could be different for each call (because each WebScript invoked in the request will supply different
|
||||
|
||||
* configuration.</p>
|
||||
|
||||
*/
|
||||
|
||||
public TemplateConfigModel getExtendedTemplateConfigModel(String xmlConfig)
|
||||
|
||||
{
|
||||
|
||||
if (this.globalConfig.get() == null && this.sectionsByArea.get() == null && this.sections.get() == null)
|
||||
|
||||
{
|
||||
|
||||
this.getConfigExtensions();
|
||||
|
||||
}
|
||||
|
||||
return new ExtendedTemplateConfigModel(getConfigService(), xmlConfig, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Creates and populates the request specific configuration container objects (<code>globalConfig</code>, <code>sectionsByArea</code> &
|
||||
|
||||
* <code>sections</code> with a combination of the default static configuration (taken from files accessed by the {@link ConfigService}) and
|
||||
|
||||
* dynamic configuration taken from extension modules evaluated for the current request. </p>
|
||||
|
||||
*/
|
||||
|
||||
private void getConfigExtensions()
|
||||
|
||||
{
|
||||
|
||||
// Extended configuration is only possible if config service is an XMLConfigService...
|
||||
|
||||
//
|
||||
|
||||
// ...also, it's only necessary to populate the configuration containers if they have not already been populated. This test should also
|
||||
|
||||
// be carried out by the two methods ("getExtendedTemplateConfigModel" & "getExtendedTemplateConfigModel") to prevent duplication
|
||||
|
||||
// of effort... but in case other methods attempt to access it we will make these additional tests.
|
||||
|
||||
if (getConfigService() instanceof XMLConfigService && this.globalConfig == null && this.sectionsByArea == null && this.sections == null)
|
||||
|
||||
{
|
||||
|
||||
// Cast the config service for ease of access
|
||||
|
||||
XMLConfigService xmlConfigService = (XMLConfigService) getConfigService();
|
||||
|
||||
|
||||
|
||||
// Get the current configuration from the ConfigService - we don't want to permanently pollute
|
||||
|
||||
// the standard configuration with additions from the modules...
|
||||
|
||||
this.globalConfig.set(new ConfigImpl((ConfigImpl)xmlConfigService.getGlobalConfig())); // Make a copy of the current global config
|
||||
|
||||
|
||||
|
||||
// Initialise these with the config service values...
|
||||
|
||||
this.sectionsByArea.set(new HashMap<String, List<ConfigSection>>(xmlConfigService.getSectionsByArea()));
|
||||
|
||||
this.sections.set(new ArrayList<ConfigSection>(xmlConfigService.getSections()));
|
||||
|
||||
|
||||
|
||||
// Check to see if there are any modules that we need to apply...
|
||||
|
||||
List<BasicExtensionModule> evaluatedModules = this.getEvaluatedModules();
|
||||
|
||||
if (evaluatedModules != null && !evaluatedModules.isEmpty())
|
||||
|
||||
{
|
||||
|
||||
for (BasicExtensionModule currModule: evaluatedModules)
|
||||
|
||||
{
|
||||
|
||||
for (Element currentConfigElement: currModule.getConfigurations())
|
||||
|
||||
{
|
||||
|
||||
// Set up containers for our request specific configuration - this will contain data taken from the evaluated modules...
|
||||
|
||||
Map<String, ConfigElementReader> parsedElementReaders = new HashMap<String, ConfigElementReader>();
|
||||
|
||||
Map<String, Evaluator> parsedEvaluators = new HashMap<String, Evaluator>();
|
||||
|
||||
List<ConfigSection> parsedConfigSections = new ArrayList<ConfigSection>();
|
||||
|
||||
|
||||
|
||||
// Parse and process the parses configuration...
|
||||
|
||||
String currentArea = xmlConfigService.parseFragment(currentConfigElement, parsedElementReaders, parsedEvaluators, parsedConfigSections);
|
||||
|
||||
for (Map.Entry<String, Evaluator> entry : parsedEvaluators.entrySet())
|
||||
|
||||
{
|
||||
|
||||
// add the evaluators to the config service
|
||||
|
||||
parsedEvaluators.put(entry.getKey(), entry.getValue());
|
||||
|
||||
}
|
||||
|
||||
for (Map.Entry<String, ConfigElementReader> entry : parsedElementReaders.entrySet())
|
||||
|
||||
{
|
||||
|
||||
// add the element readers to the config service
|
||||
|
||||
parsedElementReaders.put(entry.getKey(), entry.getValue());
|
||||
|
||||
}
|
||||
|
||||
for (ConfigSection section : parsedConfigSections)
|
||||
|
||||
{
|
||||
|
||||
// Update local configuration with our updated data...
|
||||
|
||||
xmlConfigService.addConfigSection(section, currentArea, this.globalConfig.get(), this.sectionsByArea.get(), this.sections.get());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* <p>Adds the <{@code}@markup> directive to the container which allows FreeMarker templates to be extended.</p>
|
||||
|
||||
*/
|
||||
|
||||
public void addExtensibilityDirectives(Map<String, Object> freeMarkerModel, ExtensibilityModel extModel)
|
||||
|
||||
{
|
||||
|
||||
MarkupDirective mud = new MarkupDirective("markup", extModel);
|
||||
|
||||
freeMarkerModel.put("markup", mud);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.alfresco.api.AlfrescoPublicApi;
|
||||
import org.alfresco.service.cmr.repository.FileTypeImageSize;
|
||||
|
||||
/**
|
||||
* Contains utility methods
|
||||
*
|
||||
* @author Roy Wetherall
|
||||
*/
|
||||
@AlfrescoPublicApi
|
||||
public class FileTypeImageUtils
|
||||
{
|
||||
private static final String IMAGE_PREFIX16 = "/images/filetypes/";
|
||||
private static final String IMAGE_PREFIX32 = "/images/filetypes32/";
|
||||
private static final String IMAGE_PREFIX64 = "/images/filetypes64/";
|
||||
private static final String IMAGE_POSTFIX_GIF = ".gif";
|
||||
private static final String IMAGE_POSTFIX_PNG = ".png";
|
||||
private static final String DEFAULT_FILE_IMAGE16 = IMAGE_PREFIX16 + "_default" + IMAGE_POSTFIX_GIF;
|
||||
private static final String DEFAULT_FILE_IMAGE32 = IMAGE_PREFIX32 + "_default" + IMAGE_POSTFIX_GIF;
|
||||
private static final String DEFAULT_FILE_IMAGE64 = IMAGE_PREFIX64 + "_default" + IMAGE_POSTFIX_PNG;
|
||||
|
||||
private static final Map<String, String> s_fileExtensionMap = new HashMap<String, String>(89, 1.0f);
|
||||
|
||||
/**
|
||||
* Return the image path to the filetype icon for the specified file name string
|
||||
*
|
||||
* @param sc ServletContext
|
||||
* @param name File name to build filetype icon path for
|
||||
* @param small True for the small 16x16 icon or false for the large 32x32
|
||||
*
|
||||
* @return the image path for the specified node type or the default icon if not found
|
||||
*/
|
||||
public static String getFileTypeImage(ServletContext sc, String name, boolean small)
|
||||
{
|
||||
return getFileTypeImage(sc, name, (small ? FileTypeImageSize.Small : FileTypeImageSize.Medium));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the image path to the filetype icon for the specified file name string
|
||||
*
|
||||
* @param sc ServletContext
|
||||
* @param name File name to build filetype icon path for
|
||||
* @param size Size of the icon to return
|
||||
*
|
||||
* @return the image path for the specified node type or the default icon if not found
|
||||
*/
|
||||
public static String getFileTypeImage(ServletContext sc, String name, FileTypeImageSize size)
|
||||
{
|
||||
String image = null;
|
||||
String defaultImage = null;
|
||||
switch (size)
|
||||
{
|
||||
case Small:
|
||||
defaultImage = DEFAULT_FILE_IMAGE16; break;
|
||||
case Medium:
|
||||
defaultImage = DEFAULT_FILE_IMAGE32; break;
|
||||
case Large:
|
||||
defaultImage = DEFAULT_FILE_IMAGE64; break;
|
||||
}
|
||||
|
||||
int extIndex = name.lastIndexOf('.');
|
||||
if (extIndex != -1 && name.length() > extIndex + 1)
|
||||
{
|
||||
String ext = name.substring(extIndex + 1).toLowerCase();
|
||||
String key = ext + ' ' + size.toString();
|
||||
|
||||
// found file extension for appropriate size image
|
||||
synchronized (s_fileExtensionMap)
|
||||
{
|
||||
image = s_fileExtensionMap.get(key);
|
||||
if (image == null)
|
||||
{
|
||||
// not found create for first time
|
||||
if (size != FileTypeImageSize.Large)
|
||||
{
|
||||
image = (size == FileTypeImageSize.Small ? IMAGE_PREFIX16 : IMAGE_PREFIX32) +
|
||||
ext + IMAGE_POSTFIX_GIF;
|
||||
}
|
||||
else
|
||||
{
|
||||
image = IMAGE_PREFIX64 + ext + IMAGE_POSTFIX_PNG;
|
||||
}
|
||||
|
||||
// does this image exist on the web-server?
|
||||
if (sc != null && sc.getResourceAsStream(image) != null)
|
||||
{
|
||||
// found the image for this extension - save it for later
|
||||
s_fileExtensionMap.put(key, image);
|
||||
}
|
||||
else if (sc == null)
|
||||
{
|
||||
// we have no ServerContext so return the default image but don't cache it
|
||||
image = defaultImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
// not found, save the default image for this extension instead
|
||||
s_fileExtensionMap.put(key, defaultImage);
|
||||
image = defaultImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (image != null ? image : defaultImage);
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.repo.cache.AbstractMTAsynchronouslyRefreshedCache;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.util.PropertyCheck;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.extensions.webscripts.Registry;
|
||||
|
||||
/**
|
||||
* Asynchronously refreshed cache for repository webscripts.
|
||||
* <p/>
|
||||
* This does not stop gratuitous calls to <i>refresh</i> but will ensure that, once an instance has been created,
|
||||
* a version of the registry is returned even if it is slighly out of date. This can be changed so that it waits
|
||||
* for reset but is probably not required.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 4.2.0
|
||||
*/
|
||||
public class RegistryAsynchronouslyRefreshedCache extends AbstractMTAsynchronouslyRefreshedCache<Registry> implements InitializingBean
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(RegistryAsynchronouslyRefreshedCache.class);
|
||||
|
||||
private ObjectFactory<Registry> registryFactory;
|
||||
private RetryingTransactionHelper retryingTransactionHelper;
|
||||
|
||||
/**
|
||||
* @param registryFactory factory for web script registries
|
||||
*/
|
||||
public void setRegistryFactory(ObjectFactory<Registry> registryFactory)
|
||||
{
|
||||
this.registryFactory = registryFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param retryingTransactionHelper the retryingTransactionHelper to set
|
||||
*/
|
||||
public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper)
|
||||
{
|
||||
this.retryingTransactionHelper = retryingTransactionHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Registry buildCache(final String tenantId)
|
||||
{
|
||||
return retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Registry>()
|
||||
{
|
||||
@Override
|
||||
public Registry execute() throws Throwable
|
||||
{
|
||||
return doBuildCache(tenantId);
|
||||
}
|
||||
}, true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is thread safe as per contract of {@link #buildCache(String)}.
|
||||
*/
|
||||
private Registry doBuildCache(String tenantId)
|
||||
{
|
||||
Registry registry = registryFactory.getObject();
|
||||
registry.reset();
|
||||
logger.info("Fetching web script registry for tenant " + tenantId);
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception
|
||||
{
|
||||
PropertyCheck.mandatory(this, "registryFactory", registryFactory);
|
||||
PropertyCheck.mandatory(this, "retryingTransactionHelper", retryingTransactionHelper);
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.extensions.webscripts.ClassPathStore;
|
||||
|
||||
import freemarker.cache.TemplateLoader;
|
||||
|
||||
/**
|
||||
* Extension of the SpringSurf ClassPathStore to ensure that the examination of
|
||||
* last modified dates on classpath bound resources does not cause a performance
|
||||
* degredation in REST heavy client applications.
|
||||
* <p>
|
||||
* In the repository, due to the possibility of Repository bound resources, all
|
||||
* WebScript search path lists have the "delay" set to either zero seconds (no delay)
|
||||
* or something close to that. This means that the FreeMarker template cache is
|
||||
* always or often requesting the last modified date of a classpath resource - and
|
||||
* the resources do not change. Note that the /extension classpath store still uses
|
||||
* the original ClassPathStore. Otherwise all stores can be refreshed as usual via
|
||||
* the Refresh WebScripts command.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class RepoClassPathStore extends ClassPathStore
|
||||
{
|
||||
@Override
|
||||
public TemplateLoader getTemplateLoader()
|
||||
{
|
||||
return new ClassPathTemplateLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified(String documentPath)
|
||||
throws IOException
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Path Store implementation of a Template Loader
|
||||
* <p>
|
||||
* Retrieves templates either from classes in the class path or classes inside of JAR files
|
||||
* within the class path
|
||||
* <p>
|
||||
* This implementation always returns a fixed last modified date of -1.
|
||||
*/
|
||||
private class ClassPathTemplateLoader extends ClassPathStore.ClassPathTemplateLoader
|
||||
{
|
||||
/**
|
||||
* @see freemarker.cache.TemplateLoader#getLastModified(java.lang.Object)
|
||||
*/
|
||||
public long getLastModified(Object templateSource)
|
||||
{
|
||||
return -1L;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.SocketException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.error.ExceptionStackUtil;
|
||||
import org.alfresco.repo.model.Repository;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport;
|
||||
import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.repo.transaction.TooBusyException;
|
||||
import org.alfresco.repo.web.scripts.bean.LoginPost;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.TemplateService;
|
||||
import org.alfresco.service.cmr.security.AuthorityService;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.extensions.webscripts.AbstractRuntimeContainer;
|
||||
import org.springframework.extensions.webscripts.Authenticator;
|
||||
import org.springframework.extensions.webscripts.Description;
|
||||
import org.springframework.extensions.webscripts.Description.RequiredAuthentication;
|
||||
import org.springframework.extensions.webscripts.Description.RequiredTransaction;
|
||||
import org.springframework.extensions.webscripts.Description.RequiredTransactionParameters;
|
||||
import org.springframework.extensions.webscripts.Description.TransactionCapability;
|
||||
import org.springframework.extensions.webscripts.ServerModel;
|
||||
import org.springframework.extensions.webscripts.WebScript;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.WebScriptResponse;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) container for Web Scripts
|
||||
*
|
||||
* @author steveglover
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryContainer extends AbstractRuntimeContainer
|
||||
{
|
||||
// Logger
|
||||
protected static final Log logger = LogFactory.getLog(RepositoryContainer.class);
|
||||
|
||||
/** Component Dependencies */
|
||||
private Repository repository;
|
||||
private RepositoryImageResolver imageResolver;
|
||||
private TransactionService transactionService;
|
||||
private RetryingTransactionHelper fallbackTransactionHelper;
|
||||
private AuthorityService authorityService;
|
||||
private DescriptorService descriptorService;
|
||||
|
||||
private boolean encryptTempFiles = false;
|
||||
private String tempDirectoryName = null;
|
||||
private int memoryThreshold = 4 * 1024 * 1024; // 4mb
|
||||
private long maxContentSize = (long) 4 * 1024 * 1024 * 1024; // 4gb
|
||||
private TempOutputStreamFactory streamFactory = null;
|
||||
private TempOutputStreamFactory responseStreamFactory = null;
|
||||
private String preserveHeadersPattern = null;
|
||||
|
||||
private Class<?>[] notPublicExceptions = new Class<?>[] {};
|
||||
private Class<?>[] publicExceptions = new Class<?>[] {};
|
||||
|
||||
/*
|
||||
* Shame init is already used (by TenantRepositoryContainer).
|
||||
*/
|
||||
public void setup()
|
||||
{
|
||||
File tempDirectory = TempFileProvider.getTempDir(tempDirectoryName);
|
||||
this.streamFactory = new TempOutputStreamFactory(tempDirectory, memoryThreshold, maxContentSize, encryptTempFiles, false);
|
||||
this.responseStreamFactory = new TempOutputStreamFactory(tempDirectory, memoryThreshold, maxContentSize, encryptTempFiles, true);
|
||||
}
|
||||
|
||||
public void setEncryptTempFiles(Boolean encryptTempFiles)
|
||||
{
|
||||
if(encryptTempFiles != null)
|
||||
{
|
||||
this.encryptTempFiles = encryptTempFiles.booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void setTempDirectoryName(String tempDirectoryName)
|
||||
{
|
||||
this.tempDirectoryName = tempDirectoryName;
|
||||
}
|
||||
|
||||
public void setMemoryThreshold(Integer memoryThreshold)
|
||||
{
|
||||
if(memoryThreshold != null)
|
||||
{
|
||||
this.memoryThreshold = memoryThreshold.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxContentSize(Long maxContentSize)
|
||||
{
|
||||
if(maxContentSize != null)
|
||||
{
|
||||
this.maxContentSize = maxContentSize.longValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPreserveHeadersPattern(String preserveHeadersPattern)
|
||||
{
|
||||
this.preserveHeadersPattern = preserveHeadersPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param repository Repository
|
||||
*/
|
||||
public void setRepository(Repository repository)
|
||||
{
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param imageResolver RepositoryImageResolver
|
||||
*/
|
||||
public void setRepositoryImageResolver(RepositoryImageResolver imageResolver)
|
||||
{
|
||||
this.imageResolver = imageResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transactionService TransactionService
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fallbackTransactionHelper an unlimited transaction helper used to generate error responses
|
||||
*/
|
||||
public void setFallbackTransactionHelper(RetryingTransactionHelper fallbackTransactionHelper)
|
||||
{
|
||||
this.fallbackTransactionHelper = fallbackTransactionHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param descriptorService DescriptorService
|
||||
*/
|
||||
public void setDescriptorService(DescriptorService descriptorService)
|
||||
{
|
||||
this.descriptorService = descriptorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param authorityService AuthorityService
|
||||
*/
|
||||
public void setAuthorityService(AuthorityService authorityService)
|
||||
{
|
||||
this.authorityService = authorityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptions which may contain information that cannot be displayed in UI
|
||||
*
|
||||
* @param notPublicExceptions - {@link Class}<?>[] instance which contains list of not public exceptions
|
||||
*/
|
||||
public void setNotPublicExceptions(List<Class<?>> notPublicExceptions)
|
||||
{
|
||||
this.notPublicExceptions = new Class<?>[] {};
|
||||
if((null != notPublicExceptions) && !notPublicExceptions.isEmpty())
|
||||
{
|
||||
this.notPublicExceptions = notPublicExceptions.toArray(this.notPublicExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?>[] getNotPublicExceptions()
|
||||
{
|
||||
return notPublicExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exceptions which may contain information that need to display in UI
|
||||
*
|
||||
* @param publicExceptions - {@link Class}<?>[] instance which contains list of public exceptions
|
||||
*/
|
||||
public void setPublicExceptions(List<Class<?>> publicExceptions)
|
||||
{
|
||||
this.publicExceptions = new Class<?>[] {};
|
||||
if((null != publicExceptions) && !publicExceptions.isEmpty())
|
||||
{
|
||||
this.publicExceptions = publicExceptions.toArray(this.publicExceptions);
|
||||
}
|
||||
}
|
||||
|
||||
public Class<?>[] getPublicExceptions()
|
||||
{
|
||||
return publicExceptions;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.Container#getDescription()
|
||||
*/
|
||||
public ServerModel getDescription()
|
||||
{
|
||||
return new RepositoryServerModel(descriptorService.getCurrentRepositoryDescriptor(), 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()
|
||||
{
|
||||
// Ensure we have a transaction - we might be generating the status template after the main transaction failed
|
||||
return fallbackTransactionHelper.doInTransaction(new RetryingTransactionCallback<Map<String, Object>>()
|
||||
{
|
||||
public Map<String, Object> execute() throws Throwable
|
||||
{
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
params.putAll(RepositoryContainer.super.getTemplateParameters());
|
||||
params.put(TemplateService.KEY_IMAGE_RESOLVER, imageResolver.getImageResolver());
|
||||
addRepoParameters(params);
|
||||
return params;
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Repository specific parameters
|
||||
*
|
||||
* @param params Map<String, Object>
|
||||
*/
|
||||
private void addRepoParameters(Map<String, Object> params)
|
||||
{
|
||||
if (AlfrescoTransactionSupport.getTransactionId() != null &&
|
||||
AuthenticationUtil.getFullAuthentication() != null)
|
||||
{
|
||||
NodeRef rootHome = repository.getRootHome();
|
||||
if (rootHome != null)
|
||||
{
|
||||
params.put("roothome", rootHome);
|
||||
}
|
||||
NodeRef companyHome = repository.getCompanyHome();
|
||||
if (companyHome != null)
|
||||
{
|
||||
params.put("companyhome", companyHome);
|
||||
}
|
||||
NodeRef person = repository.getFullyAuthenticatedPerson();
|
||||
if (person != null)
|
||||
{
|
||||
params.put("person", person);
|
||||
NodeRef userHome = repository.getUserHome(person);
|
||||
if (userHome != null)
|
||||
{
|
||||
params.put("userhome", userHome);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (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, final Authenticator auth)
|
||||
throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
executeScriptInternal(scriptReq, scriptRes, auth);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
Throwable hideCause = ExceptionStackUtil.getCause(e, notPublicExceptions);
|
||||
Throwable displayCause = ExceptionStackUtil.getCause(e, publicExceptions);
|
||||
if (displayCause == null && hideCause != null)
|
||||
{
|
||||
AlfrescoRuntimeException alf = null;
|
||||
if (e instanceof AlfrescoRuntimeException)
|
||||
{
|
||||
alf = (AlfrescoRuntimeException) e;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The message will not have a numerical identifier
|
||||
alf = new AlfrescoRuntimeException("WebScript execution failed", e);
|
||||
}
|
||||
String num = alf.getNumericalId();
|
||||
logger.error("Server error (" + num + ")", e);
|
||||
throw new RuntimeException("Server error (" + num + "). Details can be found in the server logs.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void executeScriptInternal(WebScriptRequest scriptReq, WebScriptResponse scriptRes, final Authenticator auth)
|
||||
throws IOException
|
||||
{
|
||||
final WebScript script = scriptReq.getServiceMatch().getWebScript();
|
||||
final Description desc = script.getDescription();
|
||||
final boolean debug = logger.isDebugEnabled();
|
||||
|
||||
// Escalate the webscript declared level of authentication to the container required authentication
|
||||
// eg. must be guest if MT is enabled unless credentials are empty
|
||||
RequiredAuthentication containerRequiredAuthentication = getRequiredAuthentication();
|
||||
final RequiredAuthentication required = (desc.getRequiredAuthentication().compareTo(containerRequiredAuthentication) < 0 && !auth.emptyCredentials() ? containerRequiredAuthentication : desc.getRequiredAuthentication());
|
||||
final boolean isGuest = scriptReq.isGuest();
|
||||
|
||||
if (required == RequiredAuthentication.none)
|
||||
{
|
||||
// TODO revisit - cleared here, in-lieu of WebClient clear
|
||||
//AuthenticationUtil.clearCurrentSecurityContext();
|
||||
|
||||
transactionedExecuteAs(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
|
||||
{
|
||||
try
|
||||
{
|
||||
AuthenticationUtil.pushAuthentication();
|
||||
|
||||
//
|
||||
// Determine if user already authenticated
|
||||
//
|
||||
if (debug)
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
logger.debug("Current authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
||||
logger.debug("Authentication required: " + required);
|
||||
logger.debug("Guest login requested: " + isGuest);
|
||||
}
|
||||
|
||||
//
|
||||
// Apply appropriate authentication to Web Script invocation
|
||||
//
|
||||
RetryingTransactionCallback<Boolean> authWork = new RetryingTransactionCallback<Boolean>()
|
||||
{
|
||||
public Boolean execute() throws Exception
|
||||
{
|
||||
if (auth == null || auth.authenticate(required, isGuest))
|
||||
{
|
||||
// The user will now have been authenticated, based on HTTP Auth, Ticket etc
|
||||
// Check that the user they authenticated as has appropriate access to the script
|
||||
|
||||
// Check to see if they supplied HTTP Auth or Ticket as guest, on a script that needs more
|
||||
if (required == RequiredAuthentication.user || required == RequiredAuthentication.admin)
|
||||
{
|
||||
String authenticatedUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
String runAsUser = AuthenticationUtil.getRunAsUser();
|
||||
|
||||
if ( (authenticatedUser == null) ||
|
||||
(authenticatedUser.equals(runAsUser) && authorityService.hasGuestAuthority()) ||
|
||||
(!authenticatedUser.equals(runAsUser) && authorityService.isGuestAuthority(authenticatedUser)) )
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires user authentication; however, a guest has attempted access.");
|
||||
}
|
||||
}
|
||||
|
||||
// Check to see if they're admin or system on an Admin only script
|
||||
if (required == RequiredAuthentication.admin && !(authorityService.hasAdminAuthority() || AuthenticationUtil.getFullyAuthenticatedUser().equals(AuthenticationUtil.getSystemUserName())))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script " + desc.getId() + " requires admin authentication; however, a non-admin has attempted access.");
|
||||
}
|
||||
|
||||
if (debug)
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
logger.debug("Authentication: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
boolean readOnly = transactionService.isReadOnly();
|
||||
boolean requiresNew = !readOnly && AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_READ_ONLY;
|
||||
if (transactionService.getRetryingTransactionHelper().doInTransaction(authWork, readOnly, requiresNew))
|
||||
{
|
||||
// Execute Web Script if authentication passed
|
||||
// The Web Script has its own txn management with potential runAs() user
|
||||
transactionedExecuteAs(script, scriptReq, scriptRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed for Web Script " + desc.getId());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
//
|
||||
// Reset authentication for current thread
|
||||
//
|
||||
AuthenticationUtil.popAuthentication();
|
||||
|
||||
if (debug)
|
||||
{
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
logger.debug("Authentication reset: " + (currentUser == null ? "unauthenticated" : "authenticated as " + currentUser));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script within required level of transaction
|
||||
*
|
||||
* @param script WebScript
|
||||
* @param scriptReq WebScriptRequest
|
||||
* @param scriptRes WebScriptResponse
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void transactionedExecute(final WebScript script, final WebScriptRequest scriptReq, final WebScriptResponse scriptRes)
|
||||
throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
final Description description = script.getDescription();
|
||||
if (description.getRequiredTransaction() == RequiredTransaction.none)
|
||||
{
|
||||
script.execute(scriptReq, scriptRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
final BufferedRequest bufferedReq;
|
||||
final BufferedResponse bufferedRes;
|
||||
RequiredTransactionParameters trxParams = description.getRequiredTransactionParameters();
|
||||
if (trxParams.getCapability() == TransactionCapability.readwrite)
|
||||
{
|
||||
if (trxParams.getBufferSize() > 0)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Creating Transactional Response for ReadWrite transaction; buffersize=" + trxParams.getBufferSize());
|
||||
|
||||
// create buffered request and response that allow transaction retrying
|
||||
bufferedReq = new BufferedRequest(scriptReq, streamFactory);
|
||||
bufferedRes = new BufferedResponse(scriptRes, trxParams.getBufferSize(), responseStreamFactory);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Transactional Response bypassed for ReadWrite - buffersize=0");
|
||||
bufferedReq = null;
|
||||
bufferedRes = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferedReq = null;
|
||||
bufferedRes = null;
|
||||
}
|
||||
|
||||
// encapsulate script within transaction
|
||||
RetryingTransactionCallback<Object> work = new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Begin retry transaction block: " + description.getRequiredTransaction() + ","
|
||||
+ description.getRequiredTransactionParameters().getCapability());
|
||||
|
||||
if (bufferedRes == null)
|
||||
{
|
||||
script.execute(scriptReq, scriptRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the request and response in case of a transaction retry
|
||||
bufferedReq.reset();
|
||||
// REPO-4388 don't reset specified headers
|
||||
bufferedRes.reset(preserveHeadersPattern);
|
||||
script.execute(bufferedReq, bufferedRes);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Transaction exception: " + description.getRequiredTransaction() + ": " + e.getMessage());
|
||||
// Note: user transaction shouldn't be null, but just in case inside this exception handler
|
||||
UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction();
|
||||
if (userTrx != null)
|
||||
{
|
||||
logger.debug("Transaction status: " + userTrx.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
UserTransaction userTrx = RetryingTransactionHelper.getActiveUserTransaction();
|
||||
if (userTrx != null)
|
||||
{
|
||||
if (userTrx.getStatus() != Status.STATUS_MARKED_ROLLBACK)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Marking web script transaction for rollback");
|
||||
try
|
||||
{
|
||||
userTrx.setRollbackOnly();
|
||||
}
|
||||
catch(Throwable re)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Caught and ignoring exception during marking for rollback: " + re.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-throw original exception for retry
|
||||
throw e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("End retry transaction block: " + description.getRequiredTransaction() + ","
|
||||
+ description.getRequiredTransactionParameters().getCapability());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
boolean readonly = description.getRequiredTransactionParameters().getCapability() == TransactionCapability.readonly;
|
||||
boolean requiresNew = description.getRequiredTransaction() == RequiredTransaction.requiresnew;
|
||||
|
||||
// log a warning if we detect a GET webscript being run in a readwrite transaction, GET calls should
|
||||
// NOT have any side effects so this scenario as a warning sign something maybe amiss, see ALF-10179.
|
||||
if (logger.isDebugEnabled() && !readonly && "GET".equalsIgnoreCase(description.getMethod()))
|
||||
{
|
||||
logger.debug("Webscript with URL '" + scriptReq.getURL() +
|
||||
"' is a GET request but it's descriptor has declared a readwrite transaction is required");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
RetryingTransactionHelper transactionHelper = transactionService.getRetryingTransactionHelper();
|
||||
if(script instanceof LoginPost)
|
||||
{
|
||||
//login script requires read-write transaction because of authorization intercepter
|
||||
transactionHelper.setForceWritable(true);
|
||||
}
|
||||
transactionHelper.doInTransaction(work, readonly, requiresNew);
|
||||
}
|
||||
catch (TooBusyException e)
|
||||
{
|
||||
// Map TooBusyException to a 503 status code
|
||||
throw new WebScriptException(HttpServletResponse.SC_SERVICE_UNAVAILABLE, e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Get rid of any temporary files
|
||||
if (bufferedReq != null)
|
||||
{
|
||||
bufferedReq.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure a response is always flushed after successful execution
|
||||
if (bufferedRes != null)
|
||||
{
|
||||
bufferedRes.writeResponse();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
Throwable socketException = ExceptionStackUtil.getCause(ioe, SocketException.class);
|
||||
Class<?> clientAbortException = null;
|
||||
try
|
||||
{
|
||||
clientAbortException = Class.forName("org.apache.catalina.connector.ClientAbortException");
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
// Note: if you need to look for more exceptions in the stack, then create a static array and pass it in
|
||||
if ((socketException != null && socketException.getMessage().contains("Broken pipe")) || (clientAbortException != null && ExceptionStackUtil.getCause(ioe, clientAbortException) != null))
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.warn("Client has cut off communication", ioe);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.info("Client has cut off communication");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw ioe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute script within required level of transaction as required effective user.
|
||||
*
|
||||
* @param script WebScript
|
||||
* @param scriptReq WebScriptRequest
|
||||
* @param scriptRes WebScriptResponse
|
||||
* @throws IOException
|
||||
*/
|
||||
private void transactionedExecuteAs(final WebScript script, final WebScriptRequest scriptReq,
|
||||
final WebScriptResponse scriptRes) throws IOException
|
||||
{
|
||||
String runAs = script.getDescription().getRunAs();
|
||||
if (runAs == null)
|
||||
{
|
||||
transactionedExecute(script, scriptReq, scriptRes);
|
||||
}
|
||||
else
|
||||
{
|
||||
RunAsWork<Object> work = new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
transactionedExecute(script, scriptReq, scriptRes);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
AuthenticationUtil.runAs(work, runAs);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#onApplicationEvent(org.springframework.context.ApplicationEvent)
|
||||
*/
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event)
|
||||
{
|
||||
if (event instanceof ContextRefreshedEvent)
|
||||
{
|
||||
ContextRefreshedEvent refreshEvent = (ContextRefreshedEvent)event;
|
||||
ApplicationContext refreshContext = refreshEvent.getApplicationContext();
|
||||
if (refreshContext != null && refreshContext.equals(applicationContext))
|
||||
{
|
||||
RunAsWork<Object> work = new RunAsWork<Object>()
|
||||
{
|
||||
public Object doWork() throws Exception
|
||||
{
|
||||
reset();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
AuthenticationUtil.runAs(work, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRequiredAuthentication()
|
||||
*/
|
||||
@Override
|
||||
public RequiredAuthentication getRequiredAuthentication()
|
||||
{
|
||||
if (AuthenticationUtil.isMtEnabled())
|
||||
{
|
||||
return RequiredAuthentication.guest; // user or guest (ie. at least guest)
|
||||
}
|
||||
|
||||
return RequiredAuthentication.none;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.RuntimeContainer#authenticate(org.alfresco.web.scripts.Authenticator, org.alfresco.web.scripts.Description.RequiredAuthentication)
|
||||
*/
|
||||
@Override
|
||||
public boolean authenticate(Authenticator auth, RequiredAuthentication required)
|
||||
{
|
||||
if (auth != null)
|
||||
{
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
|
||||
return auth.authenticate(required, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.AbstractRuntimeContainer#reset()
|
||||
*/
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
internalReset();
|
||||
return null;
|
||||
}
|
||||
}, true, false);
|
||||
}
|
||||
|
||||
private void internalReset()
|
||||
{
|
||||
super.reset();
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
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.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.web.context.ServletContextAware;
|
||||
|
||||
|
||||
/**
|
||||
* Web Scripts Image Resolver
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public void afterPropertiesSet()
|
||||
throws Exception
|
||||
{
|
||||
this.imageResolver = new TemplateImageResolver()
|
||||
{
|
||||
public String resolveImagePathForName(String filename, FileTypeImageSize size)
|
||||
{
|
||||
return FileTypeImageUtils.getFileTypeImage(servletContext, filename, size);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @return image resolver
|
||||
*/
|
||||
public TemplateImageResolver getImageResolver()
|
||||
{
|
||||
return this.imageResolver;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.jscript.ValueConverter;
|
||||
import org.alfresco.scripts.ScriptException;
|
||||
import org.alfresco.service.cmr.repository.ScriptLocation;
|
||||
import org.alfresco.service.cmr.repository.ScriptService;
|
||||
import org.springframework.extensions.webscripts.MultiScriptLoader;
|
||||
import org.springframework.extensions.webscripts.ScriptContent;
|
||||
import org.springframework.extensions.webscripts.ScriptLoader;
|
||||
import org.springframework.extensions.webscripts.ScriptProcessor;
|
||||
import org.springframework.extensions.webscripts.SearchPath;
|
||||
import org.springframework.extensions.webscripts.Store;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) Web Script Processor
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryScriptProcessor implements ScriptProcessor
|
||||
{
|
||||
// dependencies
|
||||
protected ScriptService scriptService;
|
||||
protected ScriptLoader scriptLoader;
|
||||
protected SearchPath searchPath;
|
||||
|
||||
// Javascript Converter
|
||||
private final ValueConverter valueConverter = new ValueConverter();
|
||||
|
||||
|
||||
/**
|
||||
* @param scriptService ScriptService
|
||||
*/
|
||||
public void setScriptService(ScriptService scriptService)
|
||||
{
|
||||
this.scriptService = scriptService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchPath SearchPath
|
||||
*/
|
||||
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#unwrapValue(java.lang.Object)
|
||||
*/
|
||||
public Object unwrapValue(Object value)
|
||||
{
|
||||
return valueConverter.convertValueForJava(value);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ScriptProcessor#reset()
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
init();
|
||||
this.scriptService.resetScriptProcessors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register script loader from each Web Script Store with Script Processor
|
||||
*/
|
||||
private void init()
|
||||
{
|
||||
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()]));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Script Location Facade
|
||||
*/
|
||||
private static class RepositoryScriptLocation implements ScriptLocation
|
||||
{
|
||||
private ScriptContent content;
|
||||
|
||||
private RepositoryScriptLocation(ScriptContent content)
|
||||
{
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getInputStream()
|
||||
*/
|
||||
public InputStream getInputStream()
|
||||
{
|
||||
return content.getInputStream();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getReader()
|
||||
*/
|
||||
public Reader getReader()
|
||||
{
|
||||
return content.getReader();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#isCachable()
|
||||
*/
|
||||
public boolean isCachable()
|
||||
{
|
||||
return content.isCachable();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#isSecure()
|
||||
*/
|
||||
public boolean isSecure()
|
||||
{
|
||||
return content.isSecure();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.repository.ScriptLocation#getPath()
|
||||
*/
|
||||
public String getPath()
|
||||
{
|
||||
return content.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return content.getPathDescription();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.springframework.extensions.webscripts.ScriptProcessor;
|
||||
import org.springframework.extensions.webscripts.ScriptProcessorFactory;
|
||||
|
||||
/**
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class RepositoryScriptProcessorFactory implements ScriptProcessorFactory
|
||||
{
|
||||
private ScriptProcessor scriptProcessor;
|
||||
|
||||
|
||||
/**
|
||||
* @param scriptProcessor the ScriptProcessor to set
|
||||
*/
|
||||
public void setScriptProcessor(ScriptProcessor scriptProcessor)
|
||||
{
|
||||
this.scriptProcessor = scriptProcessor;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.ScriptProcessorFactory#newInstance()
|
||||
*/
|
||||
public ScriptProcessor newInstance()
|
||||
{
|
||||
return scriptProcessor;
|
||||
}
|
||||
}
|
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.service.descriptor.Descriptor;
|
||||
import org.springframework.extensions.webscripts.ServerModel;
|
||||
|
||||
|
||||
/**
|
||||
* Script / Template Model representing Repository Server meta-data
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class RepositoryServerModel implements ServerModel
|
||||
{
|
||||
private Descriptor currentDescriptor;
|
||||
private Descriptor serverDescriptor;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param currentDescriptor Descriptor
|
||||
* @param serverDescriptor Descriptor
|
||||
*/
|
||||
/*package*/ RepositoryServerModel(Descriptor currentDescriptor, Descriptor serverDescriptor)
|
||||
{
|
||||
this.currentDescriptor = currentDescriptor;
|
||||
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#getId()
|
||||
*/
|
||||
public String getId()
|
||||
{
|
||||
return currentDescriptor.getId();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getName()
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return currentDescriptor.getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionMajor()
|
||||
*/
|
||||
public String getVersionMajor()
|
||||
{
|
||||
return currentDescriptor.getVersionMajor();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionMinor()
|
||||
*/
|
||||
public String getVersionMinor()
|
||||
{
|
||||
return currentDescriptor.getVersionMinor();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionRevision()
|
||||
*/
|
||||
public String getVersionRevision()
|
||||
{
|
||||
return currentDescriptor.getVersionRevision();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionLabel()
|
||||
*/
|
||||
public String getVersionLabel()
|
||||
{
|
||||
return currentDescriptor.getVersionLabel();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersionBuild()
|
||||
*/
|
||||
public String getVersionBuild()
|
||||
{
|
||||
return currentDescriptor.getVersionBuild();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.ServerModel#getVersion()
|
||||
*/
|
||||
public String getVersion()
|
||||
{
|
||||
return currentDescriptor.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 currentDescriptor.getSchema();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,261 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
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.processor.ProcessorExtension;
|
||||
import org.alfresco.repo.template.FreeMarkerProcessor;
|
||||
import org.alfresco.repo.template.QNameAwareObjectWrapper;
|
||||
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 org.springframework.extensions.surf.util.AbstractLifecycleBean;
|
||||
import org.springframework.extensions.webscripts.SearchPath;
|
||||
import org.springframework.extensions.webscripts.Store;
|
||||
import org.springframework.extensions.webscripts.TemplateProcessor;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
|
||||
import freemarker.cache.MultiTemplateLoader;
|
||||
import freemarker.cache.StrongCacheStorage;
|
||||
import freemarker.cache.TemplateLoader;
|
||||
import freemarker.core.TemplateClassResolver;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import freemarker.template.Version;
|
||||
|
||||
|
||||
/**
|
||||
* Repository (server-tier) Web Script Template Processor
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
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;
|
||||
private int updateDelay = 1;
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.template.FreeMarkerProcessor#setDefaultEncoding(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setDefaultEncoding(String defaultEncoding)
|
||||
{
|
||||
this.defaultEncoding = defaultEncoding;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.TemplateProcessor#getDefaultEncoding()
|
||||
*/
|
||||
public String getDefaultEncoding()
|
||||
{
|
||||
return this.defaultEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param updateDelay the time in seconds between checks on the modified date for cached templates
|
||||
*/
|
||||
public void setUpdateDelay(int updateDelay)
|
||||
{
|
||||
this.updateDelay = updateDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @param cacheSize not used anymore
|
||||
*/
|
||||
@Deprecated
|
||||
public void setCacheSize(int cacheSize)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param searchPath SearchPath
|
||||
*/
|
||||
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();
|
||||
}
|
||||
initConfig();
|
||||
}
|
||||
|
||||
/* (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 StrongCacheStorage());
|
||||
config.setTemplateUpdateDelay(updateDelay);
|
||||
|
||||
// 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");
|
||||
config.setIncompatibleImprovements(new Version(2, 3, 20));
|
||||
config.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
|
||||
|
||||
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)
|
||||
{
|
||||
initProcessorExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown(ApplicationEvent event)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.springframework.extensions.webscripts.TemplateProcessor;
|
||||
import org.springframework.extensions.webscripts.TemplateProcessorFactory;
|
||||
|
||||
/**
|
||||
* @author Kevin Roast
|
||||
*/
|
||||
public class RepositoryTemplateProcessorFactory implements TemplateProcessorFactory
|
||||
{
|
||||
private TemplateProcessor templateProcessor;
|
||||
|
||||
|
||||
/**
|
||||
* @param templateProcessor the TemplateProcessor to set
|
||||
*/
|
||||
public void setTemplateProcessor(TemplateProcessor templateProcessor)
|
||||
{
|
||||
this.templateProcessor = templateProcessor;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.extensions.webscripts.TemplateProcessorFactory#newInstance()
|
||||
*/
|
||||
public TemplateProcessor newInstance()
|
||||
{
|
||||
return templateProcessor;
|
||||
}
|
||||
}
|
@@ -0,0 +1,383 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.Key;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.CipherInputStream;
|
||||
import javax.crypto.CipherOutputStream;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
|
||||
import org.alfresco.repo.content.ContentLimitViolationException;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* An output stream implementation that keeps the data in memory if is less then
|
||||
* the specified <b>memoryThreshold</b> otherwise it writes it to a temp file.
|
||||
* <p/>
|
||||
*
|
||||
* Close the stream before any call to
|
||||
* {@link TempOutputStream}.getInputStream().
|
||||
* <p/>
|
||||
*
|
||||
* If <b>deleteTempFileOnClose</b> is false then use proper try-finally patterns
|
||||
* to ensure that the temp file is destroyed after it is no longer needed.
|
||||
*
|
||||
* <pre>
|
||||
* <code>try
|
||||
* {
|
||||
* StreamUtils.copy(new BufferedInputStream(new FileInputStream(file)), tempOutputStream);
|
||||
* tempOutputStream.close();
|
||||
* }
|
||||
* finally
|
||||
* {
|
||||
* tempOutputStream.destroy();
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
public class TempOutputStream extends OutputStream
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(TempOutputStream.class);
|
||||
|
||||
private static final int DEFAULT_MEMORY_THRESHOLD = 4 * 1024 * 1024; // 4mb
|
||||
private static final String ALGORITHM = "AES";
|
||||
private static final String MODE = "CTR";
|
||||
private static final String PADDING = "PKCS5Padding";
|
||||
private static final String TRANSFORMATION = ALGORITHM + '/' + MODE + '/' + PADDING;
|
||||
private static final int KEY_SIZE = 128;
|
||||
public static final String TEMP_FILE_PREFIX = "tempStreamFile-";
|
||||
|
||||
private final File tempDir;
|
||||
private final int memoryThreshold;
|
||||
private final long maxContentSize;
|
||||
private boolean encrypt;
|
||||
private boolean deleteTempFileOnClose;
|
||||
|
||||
private long length = 0;
|
||||
private OutputStream outputStream;
|
||||
private File tempFile;
|
||||
private TempByteArrayOutputStream tempStream;
|
||||
|
||||
private Key symKey;
|
||||
private byte[] iv;
|
||||
|
||||
/**
|
||||
* Creates a TempOutputStream.
|
||||
*
|
||||
* @param tempDir
|
||||
* the temporary directory, i.e. <code>isDir == true</code>, that
|
||||
* will be used as * parent directory for creating temp file backed
|
||||
* streams
|
||||
* @param memoryThreshold
|
||||
* the memory threshold in B
|
||||
* @param maxContentSize
|
||||
* the max content size in B
|
||||
* @param encrypt
|
||||
* true if temp files should be encrypted
|
||||
* @param deleteTempFileOnClose
|
||||
* true if temp files should be deleted on output stream close
|
||||
* (useful if we need to cache the content for further reads). If
|
||||
* this is false then we need to make sure we call
|
||||
* {@link TempOutputStream}.destroy to clean up properly.
|
||||
*/
|
||||
public TempOutputStream(File tempDir, int memoryThreshold, long maxContentSize, boolean encrypt, boolean deleteTempFileOnClose)
|
||||
{
|
||||
this.tempDir = tempDir;
|
||||
this.memoryThreshold = (memoryThreshold < 0) ? DEFAULT_MEMORY_THRESHOLD : memoryThreshold;
|
||||
this.maxContentSize = maxContentSize;
|
||||
this.encrypt = encrypt;
|
||||
this.deleteTempFileOnClose = deleteTempFileOnClose;
|
||||
|
||||
this.tempStream = new TempByteArrayOutputStream();
|
||||
this.outputStream = this.tempStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data as an InputStream
|
||||
*/
|
||||
public InputStream getInputStream() throws IOException
|
||||
{
|
||||
if (tempFile != null)
|
||||
{
|
||||
if (encrypt)
|
||||
{
|
||||
final Cipher cipher;
|
||||
try
|
||||
{
|
||||
cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
cipher.init(Cipher.DECRYPT_MODE, symKey, new IvParameterSpec(iv));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
destroy();
|
||||
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
logger.error("Cannot initialize decryption cipher", e);
|
||||
}
|
||||
|
||||
throw new IOException("Cannot initialize decryption cipher", e);
|
||||
}
|
||||
|
||||
return new BufferedInputStream(new CipherInputStream(new FileInputStream(tempFile), cipher));
|
||||
}
|
||||
return new BufferedInputStream(new FileInputStream(tempFile));
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ByteArrayInputStream(tempStream.getBuffer(), 0, tempStream.getCount());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException
|
||||
{
|
||||
update(1);
|
||||
outputStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
update(len);
|
||||
outputStream.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException
|
||||
{
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
close(deleteTempFileOnClose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the stream and removes the backing file (if present).
|
||||
* <p/>
|
||||
*
|
||||
* If <b>deleteTempFileOnClose</b> is false then use proper try-finally patterns
|
||||
* to ensure that the temp file is destroyed after it is no longer needed.
|
||||
*
|
||||
* <pre>
|
||||
* <code>try
|
||||
* {
|
||||
* StreamUtils.copy(new BufferedInputStream(new FileInputStream(file)), tempOutputStream);
|
||||
* tempOutputStream.close();
|
||||
* }
|
||||
* finally
|
||||
* {
|
||||
* tempOutputStream.destroy();
|
||||
* }
|
||||
* </code>
|
||||
* </pre>
|
||||
*/
|
||||
public void destroy() throws IOException
|
||||
{
|
||||
close(true);
|
||||
}
|
||||
|
||||
public long getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
private void closeOutputStream()
|
||||
{
|
||||
if (outputStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
outputStream.flush();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Flushing the output stream failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
outputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Closing the output stream failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteTempFile()
|
||||
{
|
||||
if (tempFile != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean isDeleted = tempFile.delete();
|
||||
if (!isDeleted)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Temp file could not be deleted: " + tempFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Deleted temp file: " + tempFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
tempFile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void close(boolean deleteTempFileOnClose)
|
||||
{
|
||||
closeOutputStream();
|
||||
|
||||
if (deleteTempFileOnClose)
|
||||
{
|
||||
deleteTempFile();
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedOutputStream createOutputStream(File file) throws IOException
|
||||
{
|
||||
BufferedOutputStream fileOutputStream;
|
||||
if (encrypt)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Generate a symmetric key
|
||||
final KeyGenerator keyGen = KeyGenerator.getInstance(ALGORITHM);
|
||||
keyGen.init(KEY_SIZE);
|
||||
symKey = keyGen.generateKey();
|
||||
|
||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, symKey);
|
||||
|
||||
iv = cipher.getIV();
|
||||
|
||||
fileOutputStream = new BufferedOutputStream(new CipherOutputStream(new FileOutputStream(file), cipher));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (logger.isErrorEnabled())
|
||||
{
|
||||
logger.error("Cannot initialize encryption cipher", e);
|
||||
}
|
||||
|
||||
throw new IOException("Cannot initialize encryption cipher", e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileOutputStream = new BufferedOutputStream(new FileOutputStream(file));
|
||||
}
|
||||
|
||||
return fileOutputStream;
|
||||
}
|
||||
|
||||
private void update(int len) throws IOException
|
||||
{
|
||||
if (maxContentSize > -1 && length + len > maxContentSize)
|
||||
{
|
||||
destroy();
|
||||
throw new ContentLimitViolationException("Content size violation, limit = " + maxContentSize);
|
||||
}
|
||||
|
||||
if (tempFile == null && (tempStream.getCount() + len) > memoryThreshold)
|
||||
{
|
||||
File file = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, ".bin", tempDir);
|
||||
|
||||
BufferedOutputStream fileOutputStream = createOutputStream(file);
|
||||
fileOutputStream.write(this.tempStream.getBuffer(), 0, this.tempStream.getCount());
|
||||
fileOutputStream.flush();
|
||||
|
||||
try
|
||||
{
|
||||
tempStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// Ignore exception
|
||||
}
|
||||
tempStream = null;
|
||||
|
||||
tempFile = file;
|
||||
outputStream = fileOutputStream;
|
||||
}
|
||||
|
||||
length += len;
|
||||
}
|
||||
|
||||
private static class TempByteArrayOutputStream extends ByteArrayOutputStream
|
||||
{
|
||||
/**
|
||||
* @return The internal buffer where data is stored
|
||||
*/
|
||||
public byte[] getBuffer()
|
||||
{
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of valid bytes in the buffer.
|
||||
*/
|
||||
public int getCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2019 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Factory for {@link TempOutputStream}
|
||||
*/
|
||||
public class TempOutputStreamFactory
|
||||
{
|
||||
/**
|
||||
* A temporary directory, i.e. <code>isDir == true</code>, that will be used as
|
||||
* parent directory for creating temp file backed streams.
|
||||
*/
|
||||
private final File tempDir;
|
||||
private int memoryThreshold;
|
||||
private long maxContentSize;
|
||||
private boolean encrypt;
|
||||
private boolean deleteTempFileOnClose;
|
||||
|
||||
/**
|
||||
* Creates a {@link TempOutputStream} factory.
|
||||
*
|
||||
* @param tempDir
|
||||
* the temporary directory, i.e. <code>isDir == true</code>, that
|
||||
* will be used as * parent directory for creating temp file backed
|
||||
* streams
|
||||
* @param memoryThreshold
|
||||
* the memory threshold in B
|
||||
* @param maxContentSize
|
||||
* the max content size in B
|
||||
* @param encrypt
|
||||
* true if temp files should be encrypted
|
||||
* @param deleteTempFileOnClose
|
||||
* true if temp files should be deleted on output stream close
|
||||
* (useful if we need to cache the content for further reads). If
|
||||
* this is false then we need to make sure we call
|
||||
* {@link TempOutputStream}.destroy to clean up properly.
|
||||
*/
|
||||
public TempOutputStreamFactory(File tempDir, int memoryThreshold, long maxContentSize, boolean encrypt, boolean deleteTempFileOnClose)
|
||||
{
|
||||
this.tempDir = tempDir;
|
||||
this.memoryThreshold = memoryThreshold;
|
||||
this.maxContentSize = maxContentSize;
|
||||
this.encrypt = encrypt;
|
||||
this.deleteTempFileOnClose = deleteTempFileOnClose;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TempOutputStream} object
|
||||
*/
|
||||
public TempOutputStream createOutputStream()
|
||||
{
|
||||
return new TempOutputStream(tempDir, memoryThreshold, maxContentSize, encrypt, deleteTempFileOnClose);
|
||||
}
|
||||
|
||||
public File getTempDir()
|
||||
{
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
public int getMemoryThreshold()
|
||||
{
|
||||
return memoryThreshold;
|
||||
}
|
||||
|
||||
public long getMaxContentSize()
|
||||
{
|
||||
return maxContentSize;
|
||||
}
|
||||
|
||||
public boolean isEncrypt()
|
||||
{
|
||||
return encrypt;
|
||||
}
|
||||
|
||||
public boolean isDeleteTempFileOnClose()
|
||||
{
|
||||
return deleteTempFileOnClose;
|
||||
}
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import org.alfresco.repo.cache.AsynchronouslyRefreshedCache;
|
||||
import org.alfresco.repo.tenant.TenantAdminService;
|
||||
import org.alfresco.repo.tenant.TenantDeployer;
|
||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Registry;
|
||||
|
||||
/**
|
||||
* Tenant-aware Repository (server-tier) container for Web Scripts
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class TenantRepositoryContainer extends RepositoryContainer implements TenantDeployer
|
||||
{
|
||||
// Logger
|
||||
protected static final Log logger = LogFactory.getLog(TenantRepositoryContainer.class);
|
||||
|
||||
/* Component Dependencies */
|
||||
protected TenantAdminService tenantAdminService;
|
||||
protected TransactionService transactionService;
|
||||
private AsynchronouslyRefreshedCache<Registry> registryCache;
|
||||
|
||||
/**
|
||||
* @param registryCache asynchronously maintained cache for script registries
|
||||
*/
|
||||
public void setWebScriptsRegistryCache(AsynchronouslyRefreshedCache<Registry> registryCache)
|
||||
{
|
||||
this.registryCache = registryCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tenantAdminService service to sort out tenant context
|
||||
*/
|
||||
public void setTenantAdminService(TenantAdminService tenantAdminService)
|
||||
{
|
||||
this.tenantAdminService = tenantAdminService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param transactionService service to give transactions when reading from the container
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
super.setTransactionService(transactionService);
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Registry getRegistry()
|
||||
{
|
||||
Registry registry = registryCache.get();
|
||||
boolean isUpToDate = registryCache.isUpToDate();
|
||||
if (!isUpToDate && logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Retrieved out of date web script registry for tenant " + tenantAdminService.getCurrentUserDomain());
|
||||
}
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnableTenant()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisableTenant()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
tenantAdminService.register(this);
|
||||
registryCache.refresh();
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
registryCache.refresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
transactionService.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Object>()
|
||||
{
|
||||
public Object execute() throws Exception
|
||||
{
|
||||
destroy();
|
||||
init();
|
||||
|
||||
return null;
|
||||
}
|
||||
}, true, false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServlet;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
|
||||
|
||||
|
||||
/**
|
||||
* Entry point for web scripts which can accept a tenant id in their servlet path
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class TenantWebScriptServlet extends WebScriptServlet
|
||||
{
|
||||
// public static final String SYSTEM_TENANT = "-system-";
|
||||
// public static final String DEFAULT_TENANT = "-default-";
|
||||
|
||||
private static final long serialVersionUID = 2954663814419046489L;
|
||||
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(TenantWebScriptServlet.class);
|
||||
|
||||
protected WebScriptServletRuntime getRuntime(HttpServletRequest req, HttpServletResponse res)
|
||||
{
|
||||
WebScriptServletRuntime runtime = new TenantWebScriptServletRuntime(container, authenticatorFactory, req, res, serverProperties);
|
||||
return runtime;
|
||||
}
|
||||
|
||||
/* (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 tenant request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : ""));
|
||||
|
||||
if (req.getCharacterEncoding() == null)
|
||||
{
|
||||
req.setCharacterEncoding("UTF-8");
|
||||
}
|
||||
|
||||
setLanguageFromRequestHeader(req);
|
||||
|
||||
try
|
||||
{
|
||||
WebScriptServletRuntime runtime = getRuntime(req, res);
|
||||
runtime.executeScript();
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
if(e.getMessage().contains("getOutputStream() has already been called for this response"))
|
||||
{
|
||||
if(logger.isDebugEnabled())
|
||||
{
|
||||
logger.warn("Client has cut off communication", e);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.warn("Client has cut off communication");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// clear threadlocal
|
||||
I18NUtil.setLocale(null);
|
||||
// clear authentication and tenant context
|
||||
AuthenticationUtil.clearCurrentSecurityContext();
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.extensions.config.ServerProperties;
|
||||
import org.springframework.extensions.surf.util.URLDecoder;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.Runtime;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest;
|
||||
|
||||
|
||||
/**
|
||||
* Web Script Request which can handle a tenant id in their servlet path
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class TenantWebScriptServletRequest extends WebScriptServletRequest
|
||||
{
|
||||
protected String tenant;
|
||||
protected String pathInfo;
|
||||
|
||||
protected void parse()
|
||||
{
|
||||
String realPathInfo = getRealPathInfo();
|
||||
|
||||
// remove tenant
|
||||
int idx = realPathInfo.indexOf('/', 1);
|
||||
tenant = realPathInfo.substring(1, idx == -1 ? realPathInfo.length() : idx);
|
||||
pathInfo = realPathInfo.substring(tenant.length() + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construction
|
||||
*
|
||||
* @param container Runtime
|
||||
* @param req HttpServletRequest
|
||||
* @param serviceMatch Match
|
||||
* @param serverProperties ServerProperties
|
||||
*/
|
||||
public TenantWebScriptServletRequest(Runtime container, HttpServletRequest req, Match serviceMatch, ServerProperties serverProperties)
|
||||
{
|
||||
super(container, req, serviceMatch, serverProperties);
|
||||
parse();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath()
|
||||
*/
|
||||
public String getServiceContextPath()
|
||||
{
|
||||
return getHttpServletRequest().getContextPath() + getHttpServletRequest().getServletPath() + "/" + tenant;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo()
|
||||
*/
|
||||
public String getPathInfo()
|
||||
{
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
public String getTenant()
|
||||
{
|
||||
return tenant;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo()
|
||||
*/
|
||||
protected String getRealPathInfo()
|
||||
{
|
||||
// NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat
|
||||
final String requestURI = getHttpServletRequest().getRequestURI();
|
||||
final String serviceContextPath = getHttpServletRequest().getContextPath() + getHttpServletRequest().getServletPath();
|
||||
String pathInfo;
|
||||
|
||||
if (serviceContextPath.length() > requestURI.length())
|
||||
{
|
||||
// NOTE: assume a redirect has taken place e.g. tomcat welcome-page
|
||||
// NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon
|
||||
pathInfo = getHttpServletRequest().getPathInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length()));
|
||||
}
|
||||
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.extensions.config.ServerProperties;
|
||||
import org.springframework.extensions.surf.util.URLDecoder;
|
||||
import org.springframework.extensions.webscripts.Match;
|
||||
import org.springframework.extensions.webscripts.RuntimeContainer;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory;
|
||||
import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime;
|
||||
|
||||
|
||||
/**
|
||||
* HTTP Servlet Web Script Runtime which can handle a tenant id in a web script path
|
||||
*
|
||||
* @author davidc
|
||||
*/
|
||||
public class TenantWebScriptServletRuntime extends WebScriptServletRuntime
|
||||
{
|
||||
public TenantWebScriptServletRuntime(RuntimeContainer container, ServletAuthenticatorFactory authFactory, HttpServletRequest req, HttpServletResponse res, ServerProperties serverProperties)
|
||||
{
|
||||
super(container, authFactory, req, res, serverProperties);
|
||||
}
|
||||
|
||||
/* (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
|
||||
final String requestURI = req.getRequestURI();
|
||||
final String serviceContextPath = req.getContextPath() + req.getServletPath();
|
||||
String pathInfo;
|
||||
|
||||
if (serviceContextPath.length() > requestURI.length())
|
||||
{
|
||||
// NOTE: assume a redirect has taken place e.g. tomcat welcome-page
|
||||
// NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon
|
||||
pathInfo = req.getPathInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length()));
|
||||
}
|
||||
|
||||
// ensure tenant is specified at beginning of path
|
||||
// NOTE: must contain at least root / and single character for tenant name
|
||||
if (pathInfo.length() < 2)
|
||||
{
|
||||
throw new WebScriptException("Missing tenant name in path: " + pathInfo);
|
||||
}
|
||||
// remove tenant
|
||||
int idx = pathInfo.indexOf('/', 1);
|
||||
pathInfo = pathInfo.substring(idx == -1 ? pathInfo.length() : idx);
|
||||
return pathInfo;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch)
|
||||
*/
|
||||
@Override
|
||||
protected WebScriptRequest createRequest(Match match)
|
||||
{
|
||||
// TODO: construct org.springframework.extensions.webscripts.servlet.WebScriptServletResponse when
|
||||
// org.alfresco.web.scripts.WebScriptServletResponse (deprecated) is removed
|
||||
servletReq = new TenantWebScriptServletRequest(this, req, match, serverProperties);
|
||||
return servletReq;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.WebScriptContainer#getName()
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return "TenantServletRuntime";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.alfresco.repo.nodelocator.CompanyHomeNodeLocator;
|
||||
import org.alfresco.repo.nodelocator.NodeLocatorService;
|
||||
import org.alfresco.repo.nodelocator.SharedHomeNodeLocator;
|
||||
import org.alfresco.repo.nodelocator.SitesHomeNodeLocator;
|
||||
import org.alfresco.repo.nodelocator.UserHomeNodeLocator;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.util.ISO8601DateFormat;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.extensions.surf.util.Content;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Smith
|
||||
* @since 4.0
|
||||
*
|
||||
*/
|
||||
public class WebScriptUtil
|
||||
{
|
||||
// General Keys
|
||||
public static final String DATA_KEY = "data";
|
||||
|
||||
// NodeRef Keys
|
||||
public static final String STORE_PROTOCOL = "store_protocol";
|
||||
public static final String STORE_ID = "store_id";
|
||||
public static final String NODE_ID = "node_id";
|
||||
|
||||
//Date/Calendar Keys
|
||||
public static final String DATE_TIME= "dateTime";
|
||||
public static final String FORMAT= "format";
|
||||
public static final String TIME_ZONE= "timeZone";
|
||||
public static final String ISO8601 = "ISO8601";
|
||||
|
||||
public static String getContent(WebScriptRequest request) throws IOException
|
||||
{
|
||||
Content content = request.getContent();
|
||||
return content.getContent();
|
||||
}
|
||||
|
||||
public static Map<String, Object> buildCalendarModel(Calendar calendar)
|
||||
{
|
||||
Map<String, Object> model = buildDateModel(calendar.getTime());
|
||||
model.put(TIME_ZONE, calendar.getTimeZone().getID());
|
||||
return model;
|
||||
}
|
||||
|
||||
public static Map<String, Object> buildDateModel(Date dateTime)
|
||||
{
|
||||
String dateStr = ISO8601DateFormat.format(dateTime);
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put(DATE_TIME, dateStr);
|
||||
model.put(FORMAT, ISO8601);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static Calendar getCalendar(JSONObject json) throws ParseException
|
||||
{
|
||||
Date date = getDate(json);
|
||||
if(date == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
String timeZone = json.optString(TIME_ZONE);
|
||||
if(timeZone != null)
|
||||
{
|
||||
TimeZone zone = TimeZone.getTimeZone(timeZone);
|
||||
calendar.setTimeZone(zone);
|
||||
}
|
||||
calendar.setTime(date);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public static Date getDate(JSONObject json) throws ParseException
|
||||
{
|
||||
if(json == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String dateTime = json.optString(DATE_TIME);
|
||||
if(dateTime == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
String format = json.optString(FORMAT);
|
||||
if(format!= null && ISO8601.equals(format) == false)
|
||||
{
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
|
||||
return dateFormat.parse(dateTime);
|
||||
}
|
||||
return ISO8601DateFormat.parse(dateTime);
|
||||
}
|
||||
|
||||
|
||||
public static Map<String, Object> createBaseModel(Map<String, Object> result)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put(DATA_KEY, result);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static Map<String, Object> createBaseModel(List<Map<String, Object>> results)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put(DATA_KEY, results);
|
||||
return model;
|
||||
}
|
||||
|
||||
public static NodeRef getNodeRef(Map<String, String> params)
|
||||
{
|
||||
String protocol = params.get(STORE_PROTOCOL);
|
||||
String storeId= params.get(STORE_ID);
|
||||
String nodeId= params.get(NODE_ID);
|
||||
if(protocol == null || storeId == null || nodeId==null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return new NodeRef(protocol, storeId, nodeId);
|
||||
}
|
||||
|
||||
|
||||
public static NodeRef resolveNodeReference(String reference, NodeLocatorService nodeLocatorService)
|
||||
{
|
||||
NodeRef nodeRef = null;
|
||||
switch (reference)
|
||||
{
|
||||
case "alfresco://company/home":
|
||||
nodeRef = nodeLocatorService.getNode(CompanyHomeNodeLocator.NAME, null, null);
|
||||
break;
|
||||
case "alfresco://user/home":
|
||||
nodeRef = nodeLocatorService.getNode(UserHomeNodeLocator.NAME, null, null);
|
||||
break;
|
||||
case "alfresco://company/shared":
|
||||
nodeRef = nodeLocatorService.getNode(SharedHomeNodeLocator.NAME, null, null);
|
||||
break;
|
||||
case "alfresco://sites/home":
|
||||
nodeRef = nodeLocatorService.getNode(SitesHomeNodeLocator.NAME, null, null);
|
||||
break;
|
||||
default:
|
||||
nodeRef = new NodeRef(reference);
|
||||
break;
|
||||
}
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import org.alfresco.repo.action.ActionImpl;
|
||||
import org.alfresco.repo.action.ActionTrackingServiceImpl;
|
||||
import org.alfresco.repo.action.RuntimeActionService;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.action.ActionStatus;
|
||||
import org.alfresco.service.cmr.action.ActionTrackingService;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public abstract class AbstractActionWebscript extends DeclarativeWebScript
|
||||
{
|
||||
protected NodeService nodeService;
|
||||
protected ActionService actionService;
|
||||
protected RuntimeActionService runtimeActionService;
|
||||
protected ActionTrackingService actionTrackingService;
|
||||
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setActionService(ActionService actionService)
|
||||
{
|
||||
this.actionService = actionService;
|
||||
}
|
||||
|
||||
public void setRuntimeActionService(RuntimeActionService runtimeActionService)
|
||||
{
|
||||
this.runtimeActionService = runtimeActionService;
|
||||
}
|
||||
|
||||
public void setActionTrackingService(ActionTrackingService actionTrackingService)
|
||||
{
|
||||
this.actionTrackingService = actionTrackingService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
RunningActionModelBuilder modelBuilder = new RunningActionModelBuilder(
|
||||
nodeService, actionService, actionTrackingService
|
||||
);
|
||||
return buildModel(modelBuilder, req, status, cache);
|
||||
}
|
||||
|
||||
protected abstract Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder,
|
||||
WebScriptRequest req,
|
||||
Status status, Cache cache
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Takes a running action ID, and returns an
|
||||
* ExecutionSummary object for it. Note - doesn't
|
||||
* check to see if the object exists in the
|
||||
* cache though!
|
||||
*/
|
||||
public static ExecutionSummary getSummaryFromKey(String key)
|
||||
{
|
||||
return WrappedActionTrackingService.getSummaryFromKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ExecutionSummary for the given action if it
|
||||
* is currently executing, or null if it isn't
|
||||
*/
|
||||
public static ExecutionSummary getSummaryFromAction(Action action)
|
||||
{
|
||||
// Is it running?
|
||||
if(action.getExecutionStatus() == ActionStatus.Running) {
|
||||
return WrappedActionTrackingService.buildExecutionSummary(action);
|
||||
}
|
||||
// Has it been given a execution id?
|
||||
// (eg has already finished, but this one was run)
|
||||
if( ((ActionImpl)action).getExecutionInstance() != -1 ) {
|
||||
return WrappedActionTrackingService.buildExecutionSummary(action);
|
||||
}
|
||||
// Not running, and hasn't run, we can't help
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the running action ID for the given
|
||||
* ExecutionSummary
|
||||
*/
|
||||
public static String getRunningId(ExecutionSummary summary)
|
||||
{
|
||||
return WrappedActionTrackingService.getRunningId(summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* So we can get at protected methods, which we need as
|
||||
* we use the same naming scheme as the cache in the
|
||||
* interests of simplicity.
|
||||
*/
|
||||
private static class WrappedActionTrackingService extends ActionTrackingServiceImpl
|
||||
{
|
||||
private static String getRunningId(ExecutionSummary summary)
|
||||
{
|
||||
return ActionTrackingServiceImpl.generateCacheKey(summary);
|
||||
}
|
||||
|
||||
protected static ExecutionSummary buildExecutionSummary(Action action)
|
||||
{
|
||||
return ActionTrackingServiceImpl.buildExecutionSummary(action);
|
||||
}
|
||||
|
||||
private static ExecutionSummary getSummaryFromKey(String key)
|
||||
{
|
||||
try {
|
||||
// Try to have the key turned into a summary for us
|
||||
return ActionTrackingServiceImpl.buildExecutionSummary(key);
|
||||
} catch(NoSuchElementException e) {
|
||||
// Wrong format
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public abstract class AbstractExecuteActionWebscript extends AbstractActionWebscript
|
||||
{
|
||||
protected Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder,
|
||||
WebScriptRequest req,
|
||||
Status status, Cache cache)
|
||||
{
|
||||
try {
|
||||
// Have the action to run be identified
|
||||
Action action = identifyAction(req, status, cache);
|
||||
if(action == null) {
|
||||
throw new WebScriptException(
|
||||
Status.STATUS_NOT_FOUND,
|
||||
"No Runnable Action found with the supplied details"
|
||||
);
|
||||
}
|
||||
|
||||
// Ask for it to be run in the background
|
||||
// It will be available to execute once the webscript finishes
|
||||
actionService.executeAction(
|
||||
action, null,
|
||||
false, true
|
||||
);
|
||||
|
||||
// Return the details if we can
|
||||
ExecutionSummary summary = getSummaryFromAction(action);
|
||||
if(summary == null) {
|
||||
throw new WebScriptException(
|
||||
Status.STATUS_EXPECTATION_FAILED,
|
||||
"Action failed to be added to the pending queue"
|
||||
);
|
||||
}
|
||||
|
||||
return modelBuilder.buildSimpleModel(summary);
|
||||
} catch(Exception e) {
|
||||
// Transaction broke
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Action identifyAction(
|
||||
WebScriptRequest req,
|
||||
Status status, Cache cache
|
||||
);
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.action.ExecutionDetails;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningActionDelete extends AbstractActionWebscript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder, WebScriptRequest req,
|
||||
Status status, Cache cache) {
|
||||
// Which action did they ask for?
|
||||
String actionTrackingId =
|
||||
req.getServiceMatch().getTemplateVars().get("action_tracking_id");
|
||||
|
||||
// Check it exists
|
||||
ExecutionSummary action =
|
||||
getSummaryFromKey(actionTrackingId);
|
||||
if(action == null) {
|
||||
throw new WebScriptException(
|
||||
Status.STATUS_NOT_FOUND,
|
||||
"No Running Action found with that tracking id"
|
||||
);
|
||||
}
|
||||
|
||||
ExecutionDetails details =
|
||||
actionTrackingService.getExecutionDetails(action);
|
||||
if(details == null) {
|
||||
throw new WebScriptException(
|
||||
Status.STATUS_NOT_FOUND,
|
||||
"No Running Action found with that tracking id"
|
||||
);
|
||||
}
|
||||
|
||||
// Request the cancel
|
||||
actionTrackingService.requestActionCancellation(action);
|
||||
|
||||
// Report it as having been cancelled
|
||||
status.setCode(Status.STATUS_NO_CONTENT);
|
||||
status.setMessage("Action cancellation requested");
|
||||
status.setRedirect(true);
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningActionGet extends AbstractActionWebscript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder, WebScriptRequest req,
|
||||
Status status, Cache cache) {
|
||||
// Which action did they ask for?
|
||||
String actionTrackingId =
|
||||
req.getServiceMatch().getTemplateVars().get("action_tracking_id");
|
||||
|
||||
ExecutionSummary action =
|
||||
getSummaryFromKey(actionTrackingId);
|
||||
|
||||
// Get the details, if we can
|
||||
Map<String,Object> model = modelBuilder.buildSimpleModel(action);
|
||||
|
||||
if(model == null) {
|
||||
throw new WebScriptException(
|
||||
Status.STATUS_NOT_FOUND,
|
||||
"No Running Action found with that tracking id"
|
||||
);
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.action.ActionService;
|
||||
import org.alfresco.service.cmr.action.ActionTrackingService;
|
||||
import org.alfresco.service.cmr.action.ExecutionDetails;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.util.ISO8601DateFormat;
|
||||
|
||||
/**
|
||||
* Builds up models for running actions
|
||||
*
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningActionModelBuilder
|
||||
{
|
||||
protected static final String MODEL_DATA_ITEM = "runningAction";
|
||||
protected static final String MODEL_DATA_LIST = "runningActions";
|
||||
|
||||
protected static final String ACTION_ID = "id";
|
||||
protected static final String ACTION_TYPE = "type";
|
||||
protected static final String ACTION_INSTANCE = "instance";
|
||||
protected static final String ACTION_NODE_REF = "nodeRef";
|
||||
protected static final String ACTION_STARTED_AT = "startedAt";
|
||||
protected static final String ACTION_RUNNING_ON = "runningOn";
|
||||
protected static final String ACTION_CANCEL_REQUESTED = "cancelRequested";
|
||||
protected static final String ACTION_KEY = "key";
|
||||
|
||||
|
||||
protected NodeService nodeService;
|
||||
protected ActionService actionService;
|
||||
protected ActionTrackingService actionTrackingService;
|
||||
|
||||
public RunningActionModelBuilder(NodeService nodeService, ActionService actionService,
|
||||
ActionTrackingService actionTrackingService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
this.actionService = actionService;
|
||||
this.actionTrackingService = actionTrackingService;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a model containing a single running action
|
||||
*/
|
||||
protected Map<String,Object> buildSimpleModel(ExecutionSummary summary)
|
||||
{
|
||||
Map<String, Object> ram = buildModel(summary);
|
||||
if(ram != null) {
|
||||
Map<String, Object> model = new HashMap<String,Object>();
|
||||
model.put(MODEL_DATA_ITEM, ram);
|
||||
return model;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a model containing a list of running actions for the given
|
||||
* list of Running Actions
|
||||
*/
|
||||
protected Map<String,Object> buildSimpleList(List<ExecutionSummary> runningActions)
|
||||
{
|
||||
List<Map<String,Object>> models = new ArrayList<Map<String,Object>>();
|
||||
|
||||
for(ExecutionSummary summary : runningActions) {
|
||||
Map<String, Object> ram = buildModel(summary);
|
||||
if(ram != null) {
|
||||
models.add(ram);
|
||||
}
|
||||
}
|
||||
|
||||
// Finish up
|
||||
Map<String, Object> model = new HashMap<String,Object>();
|
||||
model.put(MODEL_DATA_LIST, models);
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a model for a single action
|
||||
*/
|
||||
private Map<String,Object> buildModel(ExecutionSummary summary)
|
||||
{
|
||||
if(summary == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get the details, if we can
|
||||
ExecutionDetails details = actionTrackingService.getExecutionDetails(summary);
|
||||
|
||||
// Only record if still running - may have finished
|
||||
// between getting the list and now
|
||||
if(details != null) {
|
||||
Map<String, Object> ram = new HashMap<String,Object>();
|
||||
ram.put(ACTION_ID, summary.getActionId());
|
||||
ram.put(ACTION_TYPE, summary.getActionType());
|
||||
ram.put(ACTION_INSTANCE, summary.getExecutionInstance());
|
||||
ram.put(ACTION_KEY, AbstractActionWebscript.getRunningId(summary));
|
||||
|
||||
ram.put(ACTION_NODE_REF, details.getPersistedActionRef());
|
||||
ram.put(ACTION_RUNNING_ON, details.getRunningOn());
|
||||
ram.put(ACTION_CANCEL_REQUESTED, details.isCancelRequested());
|
||||
|
||||
if(details.getStartedAt() != null) {
|
||||
ram.put(ACTION_STARTED_AT, ISO8601DateFormat.format(details.getStartedAt()));
|
||||
} else {
|
||||
ram.put(ACTION_STARTED_AT, null);
|
||||
}
|
||||
|
||||
return ram;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningActionsGet extends AbstractActionWebscript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder, WebScriptRequest req,
|
||||
Status status, Cache cache) {
|
||||
List<ExecutionSummary> actions = null;
|
||||
|
||||
// Do they want all actions, or only certain ones?
|
||||
String type = req.getParameter("type");
|
||||
String nodeRef = req.getParameter("nodeRef");
|
||||
|
||||
if(type != null) {
|
||||
actions = actionTrackingService.getExecutingActions(type);
|
||||
} else if(nodeRef != null) {
|
||||
NodeRef actionNodeRef = new NodeRef(nodeRef);
|
||||
Action action = runtimeActionService.createAction(actionNodeRef);
|
||||
actions = actionTrackingService.getExecutingActions(action);
|
||||
} else {
|
||||
actions = actionTrackingService.getAllExecutingActions();
|
||||
}
|
||||
|
||||
// Build the model list
|
||||
return modelBuilder.buildSimpleList(actions);
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningActionsPost extends AbstractExecuteActionWebscript
|
||||
{
|
||||
@Override
|
||||
protected Action identifyAction(WebScriptRequest req, Status status,
|
||||
Cache cache) {
|
||||
// Which action did they ask for?
|
||||
String nodeRef = req.getParameter("nodeRef");
|
||||
if(nodeRef == null) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(new JSONTokener(req.getContent().getContent()));
|
||||
if(! json.has("nodeRef")) {
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not find required 'nodeRef' parameter");
|
||||
}
|
||||
nodeRef = json.getString("nodeRef");
|
||||
}
|
||||
catch (IOException iox)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not read content from request.", iox);
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not parse JSON from request.", je);
|
||||
}
|
||||
}
|
||||
|
||||
// Does it exist in the repo?
|
||||
NodeRef actionNodeRef = new NodeRef(nodeRef);
|
||||
if(! nodeService.exists(actionNodeRef)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Load the specified action
|
||||
Action action = runtimeActionService.createAction(actionNodeRef);
|
||||
return action;
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.replication.ReplicationDefinitionImpl;
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.action.ExecutionSummary;
|
||||
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||
import org.alfresco.service.cmr.replication.ReplicationService;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningReplicationActionsGet extends AbstractActionWebscript
|
||||
{
|
||||
private ReplicationService replicationService;
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> buildModel(
|
||||
RunningActionModelBuilder modelBuilder, WebScriptRequest req,
|
||||
Status status, Cache cache) {
|
||||
List<ExecutionSummary> actions = null;
|
||||
|
||||
// Do they want all replication actions, or only certain ones?
|
||||
String name = req.getParameter("name");
|
||||
|
||||
if(name != null) {
|
||||
// Try to find a replication definition with this name
|
||||
ReplicationDefinition rd = replicationService.loadReplicationDefinition(name);
|
||||
|
||||
// Look up what's running
|
||||
if(rd != null) {
|
||||
actions = actionTrackingService.getExecutingActions(rd);
|
||||
}
|
||||
} else {
|
||||
// All replication actions
|
||||
actions = actionTrackingService.getExecutingActions(
|
||||
ReplicationDefinitionImpl.EXECUTOR_NAME
|
||||
);
|
||||
}
|
||||
|
||||
// Build the model list
|
||||
return modelBuilder.buildSimpleList(actions);
|
||||
}
|
||||
|
||||
public void setReplicationService(ReplicationService replicationService)
|
||||
{
|
||||
this.replicationService = replicationService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.action;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.alfresco.service.cmr.action.Action;
|
||||
import org.alfresco.service.cmr.replication.ReplicationDefinition;
|
||||
import org.alfresco.service.cmr.replication.ReplicationService;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.json.JSONTokener;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Nick Burch
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RunningReplicationActionsPost extends AbstractExecuteActionWebscript
|
||||
{
|
||||
private ReplicationService replicationService;
|
||||
|
||||
@Override
|
||||
protected Action identifyAction(WebScriptRequest req, Status status,
|
||||
Cache cache) {
|
||||
// Which action did they ask for?
|
||||
String name = req.getParameter("name");
|
||||
if(name == null) {
|
||||
try {
|
||||
JSONObject json = new JSONObject(new JSONTokener(req.getContent().getContent()));
|
||||
if(! json.has("name")) {
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not find required 'name' parameter");
|
||||
}
|
||||
name = json.getString("name");
|
||||
}
|
||||
catch (IOException iox)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not read content from request.", iox);
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not parse JSON from request.", je);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the specified replication definition
|
||||
ReplicationDefinition replicationDefinition =
|
||||
replicationService.loadReplicationDefinition(name);
|
||||
return replicationDefinition;
|
||||
}
|
||||
|
||||
public void setReplicationService(ReplicationService replicationService)
|
||||
{
|
||||
this.replicationService = replicationService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.activities;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.SearchPath;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Java-backed WebScript to get a Template from a Template Store
|
||||
*/
|
||||
public class TemplateWebScript extends DeclarativeWebScript
|
||||
{
|
||||
// Logger
|
||||
protected static final Log logger = LogFactory.getLog(TemplateWebScript.class);
|
||||
|
||||
private SearchPath searchPath;
|
||||
|
||||
public void setSearchPath(SearchPath searchPath)
|
||||
{
|
||||
this.searchPath = searchPath;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.web.scripts.DeclarativeWebScript#executeImpl(org.alfresco.web.scripts.WebScriptRequest, org.alfresco.web.scripts.WebScriptResponse)
|
||||
*/
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// process extension
|
||||
String path = req.getExtensionPath(); // required
|
||||
|
||||
if ((path == null) || (path.length() == 0))
|
||||
{
|
||||
String msg = "Failed to getTemplate: missing {path}";
|
||||
logger.error(msg);
|
||||
throw new AlfrescoRuntimeException(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (path.endsWith(".ftl"))
|
||||
{
|
||||
try
|
||||
{
|
||||
InputStream is = searchPath.getDocument(path);
|
||||
if (is != null)
|
||||
{
|
||||
BufferedReader br = null;
|
||||
try
|
||||
{
|
||||
br = new BufferedReader(new InputStreamReader(is));
|
||||
String line = null;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while(((line = br.readLine()) !=null))
|
||||
{
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
model.put("template", sb.toString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (br != null) { br.close(); };
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ioe)
|
||||
{
|
||||
logger.error("Failed to getTemplate: " + ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.activities;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.SearchPath;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.Store;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Java-backed WebScript to get list of Activity Templates from a Template Store
|
||||
*/
|
||||
public class TemplatesWebScript extends DeclarativeWebScript
|
||||
{
|
||||
private SearchPath searchPath;
|
||||
|
||||
public void setSearchPath(SearchPath searchPath)
|
||||
{
|
||||
this.searchPath = searchPath;
|
||||
}
|
||||
|
||||
/* (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)
|
||||
{
|
||||
String path = "/";
|
||||
String templatePattern = "*.ftl";
|
||||
|
||||
// process extension
|
||||
String p = req.getExtensionPath(); // optional
|
||||
|
||||
if ((p != null) && (p.length() > 0))
|
||||
{
|
||||
int idx = p.lastIndexOf("/");
|
||||
if (idx != -1)
|
||||
{
|
||||
path = p.substring(0, idx);
|
||||
templatePattern = p.substring(idx+1) + ".ftl";
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> templatePaths = new HashSet<String>();
|
||||
for (Store apiStore : searchPath.getStores())
|
||||
{
|
||||
try
|
||||
{
|
||||
for (String templatePath : apiStore.getDocumentPaths(path, false, templatePattern))
|
||||
{
|
||||
templatePaths.add(templatePath);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new WebScriptException("Failed to search for templates from store " + apiStore, e);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
model.put("paths", templatePaths);
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.activities.feed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.util.JSONtoFmModel;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Java-backed WebScript to retrieve Activity Site Feed
|
||||
*/
|
||||
public class SiteFeedRetrieverWebScript extends DeclarativeWebScript
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(SiteFeedRetrieverWebScript.class);
|
||||
|
||||
private ActivityService activityService;
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
/* (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)
|
||||
{
|
||||
// retrieve requested format
|
||||
String format = req.getFormat();
|
||||
if (format == null || format.length() == 0)
|
||||
{
|
||||
format = getDescription().getDefaultFormat();
|
||||
}
|
||||
|
||||
String extensionPath = req.getExtensionPath();
|
||||
String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/");
|
||||
|
||||
String siteId = null;
|
||||
if (extParts.length == 1)
|
||||
{
|
||||
siteId = extParts[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected extension: " + extensionPath);
|
||||
}
|
||||
|
||||
// map feed collection format to feed entry format (if not the same), eg.
|
||||
// atomfeed -> atomentry
|
||||
// atom -> atomentry
|
||||
if (format.equals("atomfeed") || format.equals("atom"))
|
||||
{
|
||||
format = "atomentry";
|
||||
}
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
try
|
||||
{
|
||||
List<String> feedEntries = activityService.getSiteFeedEntries(siteId);
|
||||
|
||||
|
||||
if (format.equals(FeedTaskProcessor.FEED_FORMAT_JSON))
|
||||
{
|
||||
model.put("feedEntries", feedEntries);
|
||||
model.put("siteId", siteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Map<String, Object>> activityFeedModels = new ArrayList<Map<String, Object>>();
|
||||
try
|
||||
{
|
||||
for (String feedEntry : feedEntries)
|
||||
{
|
||||
activityFeedModels.add(JSONtoFmModel.convertJSONObjectToMap(feedEntry));
|
||||
}
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get user feed entries: " + je.getMessage());
|
||||
}
|
||||
|
||||
model.put("feedEntries", activityFeedModels);
|
||||
model.put("siteId", siteId);
|
||||
}
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
// implies that site either does not exist or is private (and current user is not admin or a member) - hence return 401 (unauthorised)
|
||||
String currentUser = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
status.setCode(Status.STATUS_UNAUTHORIZED);
|
||||
logger.warn("Unable to get site feed entries for '" + siteId + "' (site does not exist or is private) - currently logged in as '" + currentUser +"'");
|
||||
|
||||
model.put("feedEntries", null);
|
||||
model.put("siteId", "");
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.activities.feed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.query.PagingRequest;
|
||||
import org.alfresco.repo.activities.feed.FeedTaskProcessor;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||
import org.alfresco.service.cmr.activities.ActivityService;
|
||||
import org.alfresco.service.cmr.subscriptions.PagingFollowingResults;
|
||||
import org.alfresco.service.cmr.subscriptions.SubscriptionService;
|
||||
import org.alfresco.util.JSONtoFmModel;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.json.JSONException;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Java-backed WebScript to retrieve Activity User Feed
|
||||
*/
|
||||
public class UserFeedRetrieverWebScript extends DeclarativeWebScript
|
||||
{
|
||||
private static final Log logger = LogFactory.getLog(UserFeedRetrieverWebScript.class);
|
||||
|
||||
// URL request parameter names
|
||||
public static final String PARAM_SITE_ID = "s";
|
||||
public static final String PARAM_EXCLUDE_THIS_USER = "exclUser";
|
||||
public static final String PARAM_EXCLUDE_OTHER_USERS = "exclOthers";
|
||||
public static final String PARAM_ONLY_FOLLOWING = "following";
|
||||
public static final String PARAM_ACTIVITY_FILTER = "activityFilter";
|
||||
|
||||
private ActivityService activityService;
|
||||
private SubscriptionService subscriptionService;
|
||||
|
||||
private boolean userNamesAreCaseSensitive = false;
|
||||
|
||||
public void setActivityService(ActivityService activityService)
|
||||
{
|
||||
this.activityService = activityService;
|
||||
}
|
||||
|
||||
public void setSubscriptionService(SubscriptionService subscriptionService)
|
||||
{
|
||||
this.subscriptionService = subscriptionService;
|
||||
}
|
||||
|
||||
public void setUserNamesAreCaseSensitive(boolean userNamesAreCaseSensitive)
|
||||
{
|
||||
this.userNamesAreCaseSensitive = userNamesAreCaseSensitive;
|
||||
}
|
||||
|
||||
/* (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)
|
||||
{
|
||||
// retrieve requested format
|
||||
String format = req.getFormat();
|
||||
if (format == null || format.length() == 0)
|
||||
{
|
||||
format = getDescription().getDefaultFormat();
|
||||
}
|
||||
|
||||
// process extension
|
||||
String extensionPath = req.getExtensionPath();
|
||||
String[] extParts = extensionPath == null ? new String[1] : extensionPath.split("/");
|
||||
|
||||
String feedUserId = null;
|
||||
if (extParts.length == 1)
|
||||
{
|
||||
feedUserId = extParts[0];
|
||||
}
|
||||
else if (extParts.length > 1)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unexpected extension: " + extensionPath);
|
||||
}
|
||||
|
||||
// process arguments
|
||||
String siteId = req.getParameter(PARAM_SITE_ID); // optional
|
||||
String exclThisUserStr = req.getParameter(PARAM_EXCLUDE_THIS_USER); // optional
|
||||
String exclOtherUsersStr = req.getParameter(PARAM_EXCLUDE_OTHER_USERS); // optional
|
||||
String onlyFollowingStr = req.getParameter(PARAM_ONLY_FOLLOWING); // optional
|
||||
String activityFilterStr = req.getParameter(PARAM_ACTIVITY_FILTER); // optional
|
||||
|
||||
boolean exclThisUser = false;
|
||||
if ((exclThisUserStr != null) && (exclThisUserStr.equalsIgnoreCase("true") || exclThisUserStr.equalsIgnoreCase("t")))
|
||||
{
|
||||
exclThisUser = true;
|
||||
}
|
||||
|
||||
boolean exclOtherUsers = false;
|
||||
if ((exclOtherUsersStr != null) && (exclOtherUsersStr.equalsIgnoreCase("true") || exclOtherUsersStr.equalsIgnoreCase("t")))
|
||||
{
|
||||
exclOtherUsers = true;
|
||||
}
|
||||
|
||||
Set<String> userFilter = null;
|
||||
if ((onlyFollowingStr != null) && (onlyFollowingStr.equalsIgnoreCase("true") || onlyFollowingStr.equalsIgnoreCase("t")))
|
||||
{
|
||||
userFilter = new HashSet<String>();
|
||||
if (subscriptionService.isActive()) {
|
||||
PagingFollowingResults following = subscriptionService.getFollowing(AuthenticationUtil.getRunAsUser(), new PagingRequest(-1, null));
|
||||
if (following.getPage() != null)
|
||||
{
|
||||
for (String userName : following.getPage())
|
||||
{
|
||||
userFilter.add(this.userNamesAreCaseSensitive ? userName : userName.toLowerCase());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> activityFilter = null;
|
||||
if (activityFilterStr != null)
|
||||
{
|
||||
activityFilter = new HashSet<String>();
|
||||
String[] activities = activityFilterStr.split(",");
|
||||
for (String s : activities)
|
||||
{
|
||||
if (s.trim().length() > 0)
|
||||
{
|
||||
activityFilter.add(s.trim());
|
||||
}
|
||||
}
|
||||
if (activityFilter.size() == 0)
|
||||
{
|
||||
activityFilter = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ((feedUserId == null) || (feedUserId.length() == 0))
|
||||
{
|
||||
feedUserId = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
}
|
||||
|
||||
// map feed collection format to feed entry format (if not the same), eg.
|
||||
// atomfeed -> atomentry
|
||||
// atom -> atomentry
|
||||
if (format.equals("atomfeed") || format.equals("atom"))
|
||||
{
|
||||
format = "atomentry";
|
||||
}
|
||||
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
try
|
||||
{
|
||||
List<String> feedEntries = activityService.getUserFeedEntries(feedUserId, siteId, exclThisUser, exclOtherUsers, userFilter, activityFilter);
|
||||
|
||||
if (format.equals(FeedTaskProcessor.FEED_FORMAT_JSON))
|
||||
{
|
||||
model.put("feedEntries", feedEntries);
|
||||
model.put("siteId", siteId);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Map<String, Object>> activityFeedModels = new ArrayList<Map<String, Object>>();
|
||||
try
|
||||
{
|
||||
for (String feedEntry : feedEntries)
|
||||
{
|
||||
activityFeedModels.add(JSONtoFmModel.convertJSONObjectToMap(feedEntry));
|
||||
}
|
||||
}
|
||||
catch (JSONException je)
|
||||
{
|
||||
throw new AlfrescoRuntimeException("Unable to get user feed entries: " + je.getMessage());
|
||||
}
|
||||
|
||||
model.put("feedEntries", activityFeedModels);
|
||||
model.put("feedUserId", feedUserId);
|
||||
}
|
||||
}
|
||||
catch (AccessDeniedException ade)
|
||||
{
|
||||
status.setCode(Status.STATUS_UNAUTHORIZED);
|
||||
logger.warn("Unable to get user feed entries for '" + feedUserId + "' - currently logged in as '" + AuthenticationUtil.getFullyAuthenticatedUser() +"'");
|
||||
return null;
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.admin.RepoAdminService;
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
import org.alfresco.service.cmr.admin.RepoUsageStatus.RepoUsageLevel;
|
||||
import org.alfresco.service.descriptor.DescriptorService;
|
||||
import org.alfresco.service.license.LicenseDescriptor;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
|
||||
/**
|
||||
* Abstract implementation for scripts that access the {@link RepoAdminService}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public abstract class AbstractAdminWebScript extends DeclarativeWebScript
|
||||
{
|
||||
public static final String JSON_KEY_LAST_UPDATE = "lastUpdate";
|
||||
public static final String JSON_KEY_USERS = "users";
|
||||
public static final String JSON_KEY_DOCUMENTS = "documents";
|
||||
public static final String JSON_KEY_LICENSE_MODE = "licenseMode";
|
||||
public static final String JSON_KEY_READ_ONLY = "readOnly";
|
||||
public static final String JSON_KEY_UPDATED = "updated";
|
||||
public static final String JSON_KEY_LICENSE_VALID_UNTIL = "licenseValidUntil";
|
||||
public static final String JSON_KEY_LICENSE_HOLDER = "licenseHolder";
|
||||
public static final String JSON_KEY_LEVEL = "level";
|
||||
public static final String JSON_KEY_WARNINGS = "warnings";
|
||||
public static final String JSON_KEY_ERRORS = "errors";
|
||||
|
||||
/**
|
||||
* Logger that can be used by subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
protected RepoAdminService repoAdminService;
|
||||
protected DescriptorService descriptorService;
|
||||
|
||||
/**
|
||||
* @param repoAdminService the service that provides the functionality
|
||||
*/
|
||||
public void setRepoAdminService(RepoAdminService repoAdminService)
|
||||
{
|
||||
this.repoAdminService = repoAdminService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param descriptorService the service that provides the functionality
|
||||
*/
|
||||
public void setDescriptorService(DescriptorService descriptorService)
|
||||
{
|
||||
this.descriptorService = descriptorService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an I18N'd message for the given key or the key itself if not present
|
||||
*
|
||||
* @param args arguments to replace the variables in the message
|
||||
*/
|
||||
protected String getI18NMessage(String key, Object ... args)
|
||||
{
|
||||
return I18NUtil.getMessage(key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to assign JSON return variables based on the repository usage data.
|
||||
*/
|
||||
protected void putUsageInModel(
|
||||
Map<String, Object> model,
|
||||
RepoUsage repoUsage,
|
||||
boolean updated)
|
||||
{
|
||||
model.put(JSON_KEY_LAST_UPDATE, repoUsage.getLastUpdate());
|
||||
model.put(JSON_KEY_USERS, repoUsage.getUsers());
|
||||
model.put(JSON_KEY_DOCUMENTS, repoUsage.getDocuments());
|
||||
model.put(JSON_KEY_LICENSE_MODE, repoUsage.getLicenseMode());
|
||||
model.put(JSON_KEY_READ_ONLY, repoUsage.isReadOnly());
|
||||
model.put(JSON_KEY_LICENSE_VALID_UNTIL, repoUsage.getLicenseExpiryDate());
|
||||
model.put(JSON_KEY_UPDATED, updated);
|
||||
|
||||
// Add license holder
|
||||
LicenseDescriptor license = descriptorService.getLicenseDescriptor();
|
||||
if (license != null)
|
||||
{
|
||||
model.put(JSON_KEY_LICENSE_HOLDER, license.getHolderOrganisation());
|
||||
}
|
||||
|
||||
model.put(JSON_KEY_LEVEL, RepoUsageLevel.OK.ordinal());
|
||||
model.put(JSON_KEY_WARNINGS, Collections.emptyList());
|
||||
model.put(JSON_KEY_ERRORS, Collections.emptyList());
|
||||
}
|
||||
}
|
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import org.alfresco.repo.admin.BaseInterpreter;
|
||||
import org.alfresco.repo.processor.BaseProcessorExtension;
|
||||
|
||||
/**
|
||||
* Console Interpeter script extension - dynamically binds to the configured BaseInterpreter instance.
|
||||
* This avoids the need for a specific bean class per script interpreter.
|
||||
*
|
||||
* @see org.alfresco.repo.admin.BaseInterpreter
|
||||
* See script beans configured in 'web-scripts-application-context.xml'.
|
||||
*
|
||||
* @author Kevin Roast
|
||||
* @since 5.1
|
||||
*/
|
||||
public class DynamicInterpreterExtension extends BaseProcessorExtension
|
||||
{
|
||||
private BaseInterpreter interpreter;
|
||||
private long duration;
|
||||
private String result = "";
|
||||
private String command = "";
|
||||
|
||||
/**
|
||||
* Set the BaseInterpreter to use when executing commands and retrieving the command result.
|
||||
*
|
||||
* @param interpreter For example, repoAdminInterpreter
|
||||
*/
|
||||
public void setInterpreter(BaseInterpreter interpreter)
|
||||
{
|
||||
this.interpreter = interpreter;
|
||||
}
|
||||
|
||||
private BaseInterpreter getInterpreter()
|
||||
{
|
||||
return this.interpreter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Script execute command gateway.
|
||||
*
|
||||
* @param command string to execute
|
||||
*/
|
||||
public void executeCmd(String command)
|
||||
{
|
||||
this.command = command;
|
||||
this.interpretCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the command duration
|
||||
*/
|
||||
public long getDuration()
|
||||
{
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the command result
|
||||
*/
|
||||
public String getResult()
|
||||
{
|
||||
return this.result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the command last executed
|
||||
*/
|
||||
public String getCommand()
|
||||
{
|
||||
return this.command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interpret console command using the configured Interpreter
|
||||
*
|
||||
* @param command command
|
||||
*/
|
||||
private void interpretCommand(String command)
|
||||
{
|
||||
try
|
||||
{
|
||||
long startms = System.currentTimeMillis();
|
||||
this.result = getInterpreter().interpretCommand(command);
|
||||
this.duration = System.currentTimeMillis() - startms;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
StringWriter stackTrace = new StringWriter();
|
||||
e.printStackTrace(new PrintWriter(stackTrace));
|
||||
this.result = stackTrace.toString();
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* GET the repository {@link RepoUsage restrictions}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RepoRestrictionsGet extends AbstractAdminWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>(7);
|
||||
|
||||
RepoUsage restrictions = repoAdminService.getRestrictions();
|
||||
putUsageInModel(model, restrictions, false);
|
||||
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork;
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
import org.alfresco.service.cmr.admin.RepoUsageStatus;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* GET the repository {@link RepoUsage usage}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RepoUsageGet extends AbstractAdminWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(final WebScriptRequest req, final Status status, final Cache cache)
|
||||
{
|
||||
// Runas system to obtain the info
|
||||
RunAsWork<Map<String, Object>> runAs = new RunAsWork<Map<String,Object>>()
|
||||
{
|
||||
@Override
|
||||
public Map<String, Object> doWork() throws Exception
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>(7);
|
||||
|
||||
RepoUsageStatus usageStatus = repoAdminService.getUsageStatus();
|
||||
RepoUsage usage = usageStatus.getUsage();
|
||||
|
||||
putUsageInModel(
|
||||
model,
|
||||
usage,
|
||||
false);
|
||||
|
||||
// Add usage messages
|
||||
model.put(JSON_KEY_LEVEL, usageStatus.getLevel().ordinal());
|
||||
model.put(JSON_KEY_WARNINGS, usageStatus.getWarnings());
|
||||
model.put(JSON_KEY_ERRORS, usageStatus.getErrors());
|
||||
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
};
|
||||
return AuthenticationUtil.runAs(runAs, AuthenticationUtil.getSystemUserName());
|
||||
}
|
||||
}
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.admin;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.admin.RepoUsage;
|
||||
import org.alfresco.service.cmr.admin.RepoUsage.UsageType;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* GET the repository {@link RepoUsage usage}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public class RepoUsagePost extends AbstractAdminWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>(7);
|
||||
|
||||
boolean updated = repoAdminService.updateUsage(UsageType.USAGE_ALL);
|
||||
RepoUsage repoUsage = repoAdminService.getUsage();
|
||||
|
||||
putUsageInModel(model, repoUsage, updated);
|
||||
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.node.archive.ArchivedNodesCannedQueryBuilder;
|
||||
import org.alfresco.repo.node.archive.NodeArchiveService;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.ScriptPagingDetails;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is an abstract base class for the various webscript controllers in the
|
||||
* NodeArchiveService.
|
||||
*
|
||||
* @author Neil McErlean, Jamal Kaabi-Mofrad
|
||||
* @since 3.5
|
||||
*/
|
||||
public abstract class AbstractArchivedNodeWebScript extends DeclarativeWebScript
|
||||
{
|
||||
public static final String NAME = "name";
|
||||
public static final String TITLE = "title";
|
||||
public static final String DESCRIPTION = "description";
|
||||
public static final String NODEREF = "nodeRef";
|
||||
public static final String ARCHIVED_BY = "archivedBy";
|
||||
public static final String ARCHIVED_DATE = "archivedDate";
|
||||
public static final String DISPLAY_PATH = "displayPath";
|
||||
public static final String USER_NAME = "userName";
|
||||
public static final String FIRST_NAME = "firstName";
|
||||
public static final String LAST_NAME = "lastName";
|
||||
public static final String NODE_TYPE = "nodeType";
|
||||
public static final String DELETED_NODES = "deletedNodes";
|
||||
|
||||
public static final int DEFAULT_MAX_ITEMS_PER_PAGE = 50;
|
||||
|
||||
// Injected services
|
||||
protected ServiceRegistry serviceRegistry;
|
||||
protected NodeArchiveService nodeArchiveService;
|
||||
protected int maxSizeView = 1000;
|
||||
|
||||
/**
|
||||
* Sets the serviceRegistry instance
|
||||
*
|
||||
* @param serviceRegistry the serviceRegistry to set
|
||||
*/
|
||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
||||
{
|
||||
this.serviceRegistry = serviceRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nodeArchiveService instance
|
||||
*
|
||||
* @param nodeArchiveService the nodeArchiveService to set
|
||||
*/
|
||||
public void setNodeArchiveService(NodeArchiveService nodeArchiveService)
|
||||
{
|
||||
this.nodeArchiveService = nodeArchiveService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maxSizeView
|
||||
*
|
||||
* @param maxSizeView the maxSizeView
|
||||
*/
|
||||
public void setMaxSizeView(int maxSizeView)
|
||||
{
|
||||
this.maxSizeView = maxSizeView;
|
||||
}
|
||||
|
||||
protected StoreRef parseRequestForStoreRef(WebScriptRequest req)
|
||||
{
|
||||
// get the parameters that represent the StoreRef, we know they are present
|
||||
// otherwise this webscript would not have matched
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String storeType = templateVars.get("store_type");
|
||||
String storeId = templateVars.get("store_id");
|
||||
|
||||
// create the StoreRef and ensure it is valid
|
||||
StoreRef storeRef = new StoreRef(storeType, storeId);
|
||||
|
||||
return storeRef;
|
||||
}
|
||||
|
||||
protected NodeRef parseRequestForNodeRef(WebScriptRequest req)
|
||||
{
|
||||
// get the parameters that represent the NodeRef. They may not all be there
|
||||
// for all deletednodes webscripts.
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String storeType = templateVars.get("store_type");
|
||||
String storeId = templateVars.get("store_id");
|
||||
String id = templateVars.get("id");
|
||||
|
||||
if (id == null || id.trim().length() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new NodeRef(storeType, storeId, id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the named parameter as an integer, if the parameter is not present the default value is returned
|
||||
*
|
||||
* @param req The WebScript request
|
||||
* @param paramName The name of parameter to look for
|
||||
* @param defaultValue The default value that should be returned if parameter is not present in request or if it is not positive
|
||||
* @return The request parameter or default value
|
||||
*/
|
||||
protected int getIntParameter(WebScriptRequest req, String paramName, int defaultValue)
|
||||
{
|
||||
String paramString = req.getParameter(paramName);
|
||||
|
||||
if (paramString != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
int param = Integer.valueOf(paramString);
|
||||
|
||||
if (param >= 0)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* * This method gets all nodes from the archive which were originally
|
||||
* contained within the specified StoreRef.
|
||||
*
|
||||
* @param storeRef mandatory store ref
|
||||
* @param paging mandatory paging
|
||||
* @param filter optional filter
|
||||
*/
|
||||
protected PagingResults<NodeRef> getArchivedNodesFrom(StoreRef storeRef, ScriptPagingDetails paging, String filter)
|
||||
{
|
||||
NodeService nodeService = serviceRegistry.getNodeService();
|
||||
NodeRef archiveStoreRootNodeRef = nodeService.getStoreArchiveNode(storeRef);
|
||||
|
||||
// Create canned query
|
||||
ArchivedNodesCannedQueryBuilder queryBuilder = new ArchivedNodesCannedQueryBuilder.Builder(
|
||||
archiveStoreRootNodeRef, paging).filter(filter)
|
||||
.sortOrderAscending(false).build();
|
||||
|
||||
// Query the DB
|
||||
PagingResults<NodeRef> result = nodeArchiveService.listArchivedNodes(queryBuilder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void validatePermission(NodeRef nodeRef, String currentUser)
|
||||
{
|
||||
if (!nodeArchiveService.hasFullAccess(nodeRef))
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_FORBIDDEN, "You don't have permission to act on the node.");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.repo.node.archive.RestoreNodeReport;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the archivednode.put webscript.
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @since 3.5
|
||||
*/
|
||||
public class ArchivedNodePut extends AbstractArchivedNodeWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Current user
|
||||
String userID = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (userID == null)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script ["
|
||||
+ req.getServiceMatch().getWebScript().getDescription()
|
||||
+ "] requires user authentication.");
|
||||
}
|
||||
|
||||
NodeRef nodeRefToBeRestored = parseRequestForNodeRef(req);
|
||||
if (nodeRefToBeRestored == null)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "nodeRef not recognised. Could not restore.");
|
||||
}
|
||||
|
||||
// check if the current user has the permission to restore the node
|
||||
validatePermission(nodeRefToBeRestored, userID);
|
||||
|
||||
RestoreNodeReport report = nodeArchiveService.restoreArchivedNode(nodeRefToBeRestored);
|
||||
|
||||
// Handling of some error scenarios
|
||||
if (report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_INVALID_ARCHIVE_NODE))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_NOT_FOUND, "Unable to find archive node: " + nodeRefToBeRestored);
|
||||
}
|
||||
else if (report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_PERMISSION))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_FORBIDDEN, "Unable to restore archive node: " + nodeRefToBeRestored);
|
||||
}
|
||||
else if (report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_DUPLICATE_CHILD_NODE_NAME))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_CONFLICT, "Unable to restore archive node: " + nodeRefToBeRestored +". Duplicate child node name");
|
||||
}
|
||||
else if (report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_INVALID_PARENT) ||
|
||||
report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_INTEGRITY) ||
|
||||
report.getStatus().equals(RestoreNodeReport.RestoreStatus.FAILURE_OTHER))
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to restore archive node: " + nodeRefToBeRestored);
|
||||
}
|
||||
|
||||
model.put("restoreNodeReport", report);
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.security.AccessStatus;
|
||||
import org.alfresco.service.cmr.security.PermissionService;
|
||||
import org.alfresco.service.cmr.security.PersonService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.PathUtil;
|
||||
|
||||
/**
|
||||
* A simple POJO class for the state of an archived node. For easier passing to the FTL model.
|
||||
*
|
||||
* @author Neil McErlean
|
||||
* @since 3.5
|
||||
*/
|
||||
public class ArchivedNodeState
|
||||
{
|
||||
private NodeRef archivedNodeRef;
|
||||
private String archivedBy;
|
||||
private Date archivedDate;
|
||||
private String name;
|
||||
private String title;
|
||||
private String description;
|
||||
private String displayPath;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private String nodeType;
|
||||
private boolean isContentType;
|
||||
|
||||
/**
|
||||
* To prevent unauthorised construction.
|
||||
*/
|
||||
private ArchivedNodeState() { /* Intentionally empty*/ }
|
||||
|
||||
public static ArchivedNodeState create(NodeRef archivedNode, ServiceRegistry serviceRegistry)
|
||||
{
|
||||
ArchivedNodeState result = new ArchivedNodeState();
|
||||
|
||||
NodeService nodeService = serviceRegistry.getNodeService();
|
||||
Map<QName, Serializable> properties = nodeService.getProperties(archivedNode);
|
||||
|
||||
result.archivedNodeRef = archivedNode;
|
||||
result.archivedBy = (String) properties.get(ContentModel.PROP_ARCHIVED_BY);
|
||||
result.archivedDate = (Date) properties.get(ContentModel.PROP_ARCHIVED_DATE);
|
||||
result.name = (String) properties.get(ContentModel.PROP_NAME);
|
||||
result.title = (String) properties.get(ContentModel.PROP_TITLE);
|
||||
result.description = (String) properties.get(ContentModel.PROP_DESCRIPTION);
|
||||
QName type = nodeService.getType(archivedNode);
|
||||
result.isContentType = (type.equals(ContentModel.TYPE_CONTENT) || serviceRegistry.getDictionaryService().isSubClass(type, ContentModel.TYPE_CONTENT));
|
||||
result.nodeType = type.toPrefixString(serviceRegistry.getNamespaceService());
|
||||
|
||||
PersonService personService = serviceRegistry.getPersonService();
|
||||
if (result.archivedBy != null && personService.personExists(result.archivedBy))
|
||||
{
|
||||
NodeRef personNodeRef = personService.getPerson(result.archivedBy, false);
|
||||
Map<QName, Serializable> personProps = nodeService.getProperties(personNodeRef);
|
||||
|
||||
result.firstName = (String) personProps.get(ContentModel.PROP_FIRSTNAME);
|
||||
result.lastName = (String) personProps.get(ContentModel.PROP_LASTNAME);
|
||||
}
|
||||
|
||||
ChildAssociationRef originalParentAssoc = (ChildAssociationRef) properties.get(ContentModel.PROP_ARCHIVED_ORIGINAL_PARENT_ASSOC);
|
||||
|
||||
if (serviceRegistry.getPermissionService().hasPermission(originalParentAssoc.getParentRef(), PermissionService.READ).equals(AccessStatus.ALLOWED)
|
||||
&& nodeService.exists(originalParentAssoc.getParentRef()))
|
||||
{
|
||||
result.displayPath = PathUtil.getDisplayPath(nodeService.getPath(originalParentAssoc.getParentRef()), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.displayPath = "";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
return this.archivedNodeRef;
|
||||
}
|
||||
|
||||
public String getArchivedBy()
|
||||
{
|
||||
return this.archivedBy;
|
||||
}
|
||||
|
||||
public Date getArchivedDate()
|
||||
{
|
||||
return this.archivedDate;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public String getTitle()
|
||||
{
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public String getDescription()
|
||||
{
|
||||
return this.description;
|
||||
}
|
||||
|
||||
public String getDisplayPath()
|
||||
{
|
||||
return this.displayPath;
|
||||
}
|
||||
|
||||
public String getFirstName()
|
||||
{
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public String getLastName()
|
||||
{
|
||||
return this.lastName;
|
||||
}
|
||||
|
||||
public String getNodeType()
|
||||
{
|
||||
return this.nodeType;
|
||||
}
|
||||
|
||||
public boolean getIsContentType()
|
||||
{
|
||||
return this.isContentType;
|
||||
}
|
||||
}
|
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.ScriptPagingDetails;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the deletednodes.delete web script.
|
||||
*
|
||||
* @author Neil McErlean
|
||||
* @since 3.5
|
||||
*/
|
||||
public class ArchivedNodesDelete extends AbstractArchivedNodeWebScript
|
||||
{
|
||||
private static Log log = LogFactory.getLog(ArchivedNodesDelete.class);
|
||||
|
||||
public static final String PURGED_NODES = "purgedNodes";
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// Current user
|
||||
String userID = AuthenticationUtil.getFullyAuthenticatedUser();
|
||||
if (userID == null)
|
||||
{
|
||||
throw new WebScriptException(HttpServletResponse.SC_UNAUTHORIZED, "Web Script ["
|
||||
+ req.getServiceMatch().getWebScript().getDescription()
|
||||
+ "] requires user authentication.");
|
||||
}
|
||||
|
||||
StoreRef storeRef = parseRequestForStoreRef(req);
|
||||
NodeRef nodeRef = parseRequestForNodeRef(req);
|
||||
|
||||
List<NodeRef> nodesToBePurged = new ArrayList<NodeRef>();
|
||||
if (nodeRef != null)
|
||||
{
|
||||
// check if the current user has the permission to purge the node
|
||||
validatePermission(nodeRef, userID);
|
||||
|
||||
// If there is a specific NodeRef, then that is the only Node that should be purged.
|
||||
// In this case, the NodeRef points to the actual node to be purged i.e. the node in
|
||||
// the archive store.
|
||||
nodesToBePurged.add(nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// But if there is no specific NodeRef and instead there is only a StoreRef, then
|
||||
// all nodes which were originally in that StoreRef should be purged.
|
||||
// Create paging
|
||||
ScriptPagingDetails paging = new ScriptPagingDetails(maxSizeView, 0);
|
||||
PagingResults<NodeRef> result = getArchivedNodesFrom(storeRef, paging, null);
|
||||
nodesToBePurged.addAll(result.getPage());
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
{
|
||||
log.debug("Purging " + nodesToBePurged.size() + " nodes");
|
||||
}
|
||||
|
||||
// Now having identified the nodes to be purged, we simply have to do it.
|
||||
nodeArchiveService.purgeArchivedNodes(nodesToBePurged);
|
||||
|
||||
model.put(PURGED_NODES, nodesToBePurged);
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* This interface defines a filter for ArchivedNodes.
|
||||
*
|
||||
* @author Neil Mc Erlean
|
||||
* @since 3.5
|
||||
*/
|
||||
public interface ArchivedNodesFilter
|
||||
{
|
||||
/**
|
||||
* This method checks whether or not the specified {@link NodeRef} should be included,
|
||||
* as defined by the concrete filter implementation.
|
||||
* @param nodeRef the NodeRef to be checked for filtering.
|
||||
* @return <code>true</code> if the {@link NodeRef} is acceptable, else <code>false</code>.
|
||||
*/
|
||||
boolean accept(NodeRef nodeRef);
|
||||
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.query.PagingResults;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.util.ModelUtil;
|
||||
import org.alfresco.util.ScriptPagingDetails;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* This class is the controller for the archivednodes.get web script.
|
||||
*
|
||||
* @author Neil McErlean, Jamal Kaabi-Mofrad
|
||||
* @since 3.5
|
||||
*/
|
||||
public class ArchivedNodesGet extends AbstractArchivedNodeWebScript
|
||||
{
|
||||
private static final String MAX_ITEMS = "maxItems";
|
||||
private static final String SKIP_COUNT = "skipCount";
|
||||
private static final String NAME_FILTER = "nf";
|
||||
|
||||
List<ArchivedNodesFilter> nodeFilters = new ArrayList<ArchivedNodesFilter>();
|
||||
|
||||
/**
|
||||
* This method is used to inject {@link org.alfresco.repo.web.scripts.archive.ArchivedNodesFilter node filters} on this GET call.
|
||||
*
|
||||
*/
|
||||
public void setArchivedNodeFilters(List<ArchivedNodesFilter> nodeFilters)
|
||||
{
|
||||
this.nodeFilters = nodeFilters;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>();
|
||||
|
||||
// We want to get all nodes in the archive which were originally
|
||||
// contained in the following StoreRef.
|
||||
StoreRef storeRef = parseRequestForStoreRef(req);
|
||||
|
||||
// Create paging
|
||||
ScriptPagingDetails paging = new ScriptPagingDetails(getIntParameter(req, MAX_ITEMS, DEFAULT_MAX_ITEMS_PER_PAGE),
|
||||
getIntParameter(req, SKIP_COUNT, 0));
|
||||
|
||||
PagingResults<NodeRef> result = getArchivedNodesFrom(storeRef, paging, req.getParameter(NAME_FILTER));
|
||||
List<NodeRef> nodeRefs = result.getPage();
|
||||
|
||||
List<ArchivedNodeState> deletedNodes = new ArrayList<ArchivedNodeState>(nodeRefs.size());
|
||||
for (NodeRef archivedNode : nodeRefs)
|
||||
{
|
||||
ArchivedNodeState state = ArchivedNodeState.create(archivedNode, serviceRegistry);
|
||||
deletedNodes.add(state);
|
||||
}
|
||||
|
||||
// Now do the paging
|
||||
// ALF-19111. Note: Archived nodes CQ, supports Paging,
|
||||
// so no need to use the ModelUtil.page method to build the page again.
|
||||
model.put(DELETED_NODES, deletedNodes);
|
||||
// Because we haven't used ModelUtil.page method, we need to set the total items manually.
|
||||
paging.setTotalItems(deletedNodes.size());
|
||||
model.put("paging", ModelUtil.buildPaging(paging));
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.archive;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* This class is used to filter nodes based on node type.
|
||||
*
|
||||
* @author Neil McErlean
|
||||
* @since 3.5
|
||||
*/
|
||||
public class NodeTypeFilter implements ArchivedNodesFilter
|
||||
{
|
||||
private NodeService nodeService;
|
||||
private NamespaceService namespaceService;
|
||||
private List<QName> excludedTypes;
|
||||
|
||||
/**
|
||||
* This method sets the NamespaceService object.
|
||||
* @param namespaceService the namespaceService.
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method sets the NodeService object.
|
||||
* @param nodeService the node service.
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the List of node types to exclude. These node types should be in the
|
||||
* short form e.g. cm:myType.
|
||||
*
|
||||
* @param excludedTypesStg a List of node types which are to be excluded.
|
||||
*/
|
||||
public void setExcludedTypes(List<String> excludedTypesStg)
|
||||
{
|
||||
// Convert the Strings to QNames.
|
||||
this.excludedTypes = new ArrayList<QName>(excludedTypesStg.size());
|
||||
for (String s : excludedTypesStg)
|
||||
{
|
||||
QName typeQName = QName.createQName(s, namespaceService);
|
||||
this.excludedTypes.add(typeQName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.alfresco.repo.web.scripts.archive.ArchivedNodesFilter#accept(org.alfresco.service.cmr.repository.NodeRef)
|
||||
*/
|
||||
public boolean accept(NodeRef nodeRef)
|
||||
{
|
||||
boolean typeIsExcluded = this.excludedTypes.contains(nodeService.getType(nodeRef));
|
||||
return !typeIsExcluded;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.audit;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.audit.AuditService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.extensions.surf.util.I18NUtil;
|
||||
import org.springframework.extensions.webscripts.DeclarativeWebScript;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* Abstract implementation for scripts that access the {@link AuditService}.
|
||||
*
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public abstract class AbstractAuditWebScript extends DeclarativeWebScript
|
||||
{
|
||||
public static final String PARAM_APPLICATION = "application";
|
||||
public static final String PARAM_PATH="path";
|
||||
public static final String PARAM_ENABLE = "enable";
|
||||
public static final String PARAM_VALUE = "value";
|
||||
public static final String PARAM_VALUE_TYPE = "valueType";
|
||||
public static final String PARAM_FROM_TIME = "fromTime";
|
||||
public static final String PARAM_TO_TIME = "toTime";
|
||||
public static final String PARAM_FROM_ID = "fromId";
|
||||
public static final String PARAM_TO_ID = "toId";
|
||||
public static final String PARAM_USER = "user";
|
||||
public static final String PARAM_FORWARD = "forward";
|
||||
public static final String PARAM_LIMIT = "limit";
|
||||
public static final String PARAM_VERBOSE = "verbose";
|
||||
|
||||
public static final Long DEFAULT_FROM_TIME = null;
|
||||
public static final Long DEFAULT_TO_TIME = null;
|
||||
public static final Long DEFAULT_FROM_ID = null;
|
||||
public static final Long DEFAULT_TO_ID = null;
|
||||
public static final String DEFAULT_USER = null;
|
||||
public static final boolean DEFAULT_FORWARD = true;
|
||||
public static final int DEFAULT_LIMIT = 100;
|
||||
public static final boolean DEFAULT_VERBOSE = false;
|
||||
public static final boolean DEFAULT_ENABLE = false;
|
||||
|
||||
public static final String JSON_KEY_ENABLED = "enabled";
|
||||
public static final String JSON_KEY_APPLICATIONS = "applications";
|
||||
public static final String JSON_KEY_NAME = "name";
|
||||
public static final String JSON_KEY_PATH = "path";
|
||||
public static final String JSON_KEY_CLEARED = "cleared";
|
||||
public static final String JSON_KEY_DELETED = "deleted";
|
||||
|
||||
public static final String JSON_KEY_ENTRY_COUNT = "count";
|
||||
public static final String JSON_KEY_ENTRIES = "entries";
|
||||
public static final String JSON_KEY_ENTRY_ID = "id";
|
||||
public static final String JSON_KEY_ENTRY_APPLICATION = "application";
|
||||
public static final String JSON_KEY_ENTRY_USER = "user";
|
||||
public static final String JSON_KEY_ENTRY_TIME = "time";
|
||||
public static final String JSON_KEY_ENTRY_VALUES = "values";
|
||||
|
||||
/**
|
||||
* Logger that can be used by subclasses.
|
||||
*/
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
protected AuditService auditService;
|
||||
|
||||
/**
|
||||
* @param auditService the service that provides the actual data
|
||||
*/
|
||||
public void setAuditService(AuditService auditService)
|
||||
{
|
||||
this.auditService = auditService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an I18N'd message for the given key or the key itself if not present
|
||||
*
|
||||
* @param args arguments to replace the variables in the message
|
||||
*/
|
||||
protected String getI18NMessage(String key, Object ... args)
|
||||
{
|
||||
return I18NUtil.getMessage(key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the application name from the request.
|
||||
*
|
||||
* @return Returns the application name or <tt>null</tt> if not present
|
||||
*/
|
||||
protected final String getParamAppName(WebScriptRequest req)
|
||||
{
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String app = templateVars.get(PARAM_APPLICATION);
|
||||
if (app == null || app.length() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entry id from the request.
|
||||
*
|
||||
* @return Returns the id or <tt>null</tt> if not present
|
||||
*/
|
||||
protected Long getId(WebScriptRequest req)
|
||||
{
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String id = templateVars.get("id");
|
||||
if (id == null || id.length() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
return Long.parseLong(id);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path from the request.
|
||||
*
|
||||
* @return Returns the path or <tt>null</tt> if not present
|
||||
*/
|
||||
protected String getParamPath(WebScriptRequest req)
|
||||
{
|
||||
Map<String, String> templateVars = req.getServiceMatch().getTemplateVars();
|
||||
String paramPath = templateVars.get(PARAM_PATH);
|
||||
if (paramPath == null || paramPath.length() == 0)
|
||||
{
|
||||
paramPath = null;
|
||||
}
|
||||
else if (!paramPath.startsWith("/"))
|
||||
{
|
||||
// It won't ever, so we can expect to be here all the time
|
||||
paramPath = "/" + paramPath;
|
||||
}
|
||||
return paramPath;
|
||||
}
|
||||
|
||||
protected boolean getParamEnableDisable(WebScriptRequest req)
|
||||
{
|
||||
return getBooleanParam(req.getParameter(PARAM_ENABLE), DEFAULT_ENABLE);
|
||||
}
|
||||
|
||||
protected String getParamValue(WebScriptRequest req)
|
||||
{
|
||||
return req.getParameter(PARAM_VALUE);
|
||||
}
|
||||
|
||||
protected String getParamValueType(WebScriptRequest req)
|
||||
{
|
||||
return req.getParameter(PARAM_VALUE_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_FROM_TIME
|
||||
*/
|
||||
protected Long getParamFromTime(WebScriptRequest req)
|
||||
{
|
||||
return getLongParam(req.getParameter(PARAM_FROM_TIME), DEFAULT_FROM_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_TO_TIME
|
||||
*/
|
||||
protected Long getParamToTime(WebScriptRequest req)
|
||||
{
|
||||
return getLongParam(req.getParameter(PARAM_TO_TIME), DEFAULT_TO_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_FROM_ID
|
||||
*/
|
||||
protected Long getParamFromId(WebScriptRequest req)
|
||||
{
|
||||
return getLongParam(req.getParameter(PARAM_FROM_ID), DEFAULT_FROM_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_TO_ID
|
||||
*/
|
||||
protected Long getParamToId(WebScriptRequest req)
|
||||
{
|
||||
return getLongParam(req.getParameter(PARAM_TO_ID), DEFAULT_TO_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_USER
|
||||
*/
|
||||
protected String getParamUser(WebScriptRequest req)
|
||||
{
|
||||
return req.getParameter(PARAM_USER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_FORWARD
|
||||
*/
|
||||
protected boolean getParamForward(WebScriptRequest req)
|
||||
{
|
||||
return getBooleanParam(req.getParameter(PARAM_FORWARD), DEFAULT_FORWARD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_LIMIT
|
||||
*/
|
||||
protected int getParamLimit(WebScriptRequest req)
|
||||
{
|
||||
return getIntParam(req.getParameter(PARAM_LIMIT), DEFAULT_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #DEFAULT_VERBOSE
|
||||
*/
|
||||
protected boolean getParamVerbose(WebScriptRequest req)
|
||||
{
|
||||
return getBooleanParam(req.getParameter(PARAM_VERBOSE), DEFAULT_VERBOSE);
|
||||
}
|
||||
|
||||
private Long getLongParam(String paramStr, Long defaultVal)
|
||||
{
|
||||
if (paramStr == null)
|
||||
{
|
||||
// note: defaultVal can be null
|
||||
return defaultVal;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Long.parseLong(paramStr);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean getBooleanParam(String paramStr, boolean defaultVal)
|
||||
{
|
||||
if (paramStr == null)
|
||||
{
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
// note: will return false if paramStr does not equals "true" (ignoring case)
|
||||
return Boolean.parseBoolean(paramStr);
|
||||
}
|
||||
|
||||
private int getIntParam(String paramStr, int defaultVal)
|
||||
{
|
||||
if (paramStr == null)
|
||||
{
|
||||
return defaultVal;
|
||||
}
|
||||
try
|
||||
{
|
||||
return Integer.parseInt(paramStr);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* #%L
|
||||
* Alfresco Remote API
|
||||
* %%
|
||||
* Copyright (C) 2005 - 2016 Alfresco Software Limited
|
||||
* %%
|
||||
* This file is part of the Alfresco software.
|
||||
* If the software was purchased under a paid Alfresco license, the terms of
|
||||
* the paid license agreement will prevail. Otherwise, the software is
|
||||
* provided under the following open source license terms:
|
||||
*
|
||||
* Alfresco is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Alfresco 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||
* #L%
|
||||
*/
|
||||
package org.alfresco.repo.web.scripts.audit;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.audit.AuditService.AuditApplication;
|
||||
import org.springframework.extensions.webscripts.Cache;
|
||||
import org.springframework.extensions.webscripts.Status;
|
||||
import org.springframework.extensions.webscripts.WebScriptException;
|
||||
import org.springframework.extensions.webscripts.WebScriptRequest;
|
||||
|
||||
/**
|
||||
* @author Derek Hulley
|
||||
* @since 3.4
|
||||
*/
|
||||
public class AuditClearPost extends AbstractAuditWebScript
|
||||
{
|
||||
@Override
|
||||
protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache)
|
||||
{
|
||||
Map<String, Object> model = new HashMap<String, Object>(7);
|
||||
|
||||
String appName = getParamAppName(req);
|
||||
if (appName == null)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_BAD_REQUEST, "audit.err.app.notProvided");
|
||||
}
|
||||
AuditApplication app = auditService.getAuditApplications().get(appName);
|
||||
if (app == null)
|
||||
{
|
||||
throw new WebScriptException(Status.STATUS_NOT_FOUND, "audit.err.app.notFound", appName);
|
||||
}
|
||||
// Get from/to times
|
||||
Long fromTime = getParamFromTime(req); // might be null
|
||||
Long toTime = getParamToTime(req); // might be null
|
||||
|
||||
// Clear
|
||||
int cleared = auditService.clearAudit(appName, fromTime, toTime);
|
||||
|
||||
model.put(JSON_KEY_CLEARED, cleared);
|
||||
|
||||
// Done
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user