Moved remote-api master into its own directory

This commit is contained in:
Chris Shields
2020-07-21 10:44:10 +01:00
parent f0485147b7
commit e0291f29eb
2274 changed files with 0 additions and 0 deletions

View 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
// ****

View 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.

View File

@@ -0,0 +1,2 @@
admin
admin

View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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();
}

View File

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

View File

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

View 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.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);
}

View File

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

View 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.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();
}
}

View File

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

View File

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

View File

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

View File

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

View 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.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();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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}&lt;?&gt;[] 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}&lt;?&gt;[] 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();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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