You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2018/08/11 09:41:00 UTC
svn commit: r1837851 [1/2] - in /manifoldcf/trunk: ./
connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/
connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/
connectors/nuxeo/conn...
Author: kwright
Date: Sat Aug 11 09:41:00 2018
New Revision: 1837851
URL: http://svn.apache.org/viewvc?rev=1837851&view=rev
Log:
Hook up forbidden checks for connectors, and fix numerous locale and encoding issues.
Modified:
manifoldcf/trunk/build.xml
manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
manifoldcf/trunk/connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/EmailConnector.java
manifoldcf/trunk/connectors/nuxeo/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/nuxeo/NuxeoRepositoryConnector.java
manifoldcf/trunk/connectors/nuxeo/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/nuxeo/model/NuxeoDocumentHelper.java
manifoldcf/trunk/connectors/slack/connector/src/main/java/org/apache/manifoldcf/crawler/notifications/slack/SlackSession.java
manifoldcf/trunk/connectors/tika/connector/src/main/java/org/apache/manifoldcf/agents/transformation/tika/TikaParser.java
manifoldcf/trunk/connectors/tikaservice/connector/src/main/java/org/apache/manifoldcf/agents/transformation/tikaservice/TikaExtractor.java
Modified: manifoldcf/trunk/build.xml
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/build.xml?rev=1837851&r1=1837850&r2=1837851&view=diff
==============================================================================
--- manifoldcf/trunk/build.xml (original)
+++ manifoldcf/trunk/build.xml Sat Aug 11 09:41:00 2018
@@ -2942,13 +2942,22 @@ Use Apache Forrest version forrest-0.9-d
<fileset dir="dist/connector-common-lib">
<include name="**/*.jar"/>
</fileset>
+ <fileset dir="dist/connector-lib">
+ <include name="**/*.jar"/>
+ </fileset>
+ <fileset dir="dist/connector-lib-proprietary">
+ <include name="**/*.jar"/>
+ </fileset>
<fileset dir="dist/test-lib">
<include name="**/*.jar"/>
</fileset>
</classpath>
<bundledsignatures name="jdk-unsafe"/>
<bundledsignatures name="jdk-non-portable"/>
- <fileset dir="framework/build">
+ <fileset dir="framework">
+ <include name="**/*.class"/>
+ </fileset>
+ <fileset dir="connectors">
<include name="**/*.class"/>
</fileset>
</forbiddenapis>
Modified: manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java?rev=1837851&r1=1837850&r2=1837851&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java (original)
+++ manifoldcf/trunk/connectors/cmis/connector/src/main/java/org/apache/manifoldcf/agents/output/cmisoutput/CmisOutputConnector.java Sat Aug 11 09:41:00 2018
@@ -37,6 +37,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.TimeZone;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
@@ -86,1042 +87,1042 @@ import org.apache.manifoldcf.crawler.sys
*/
public class CmisOutputConnector extends BaseOutputConnector {
- protected final static String ACTIVITY_READ = "read document";
- protected static final String RELATIONSHIP_CHILD = "child";
+ protected final static String ACTIVITY_READ = "read document";
+ protected static final String RELATIONSHIP_CHILD = "child";
- // Tab name properties
+ // Tab name properties
- private static final String CMIS_SERVER_TAB_PROPERTY = "CmisOutputConnector.Server";
+ private static final String CMIS_SERVER_TAB_PROPERTY = "CmisOutputConnector.Server";
- // Template names
+ // Template names
- /** Forward to the javascript to check the configuration parameters */
- private static final String EDIT_CONFIG_HEADER_FORWARD = "editConfiguration.js";
-
- /** Server tab template */
- private static final String EDIT_CONFIG_FORWARD_SERVER = "editConfiguration_Server.html";
-
- /** Forward to the HTML template to view the configuration parameters */
- private static final String VIEW_CONFIG_FORWARD = "viewConfiguration.html";
-
- /**
- * CMIS Session handle
- */
- Session session = null;
-
- protected String username = null;
- protected String password = null;
-
- /** Endpoint protocol */
- protected String protocol = null;
-
- /** Endpoint server name */
- protected String server = null;
-
- /** Endpoint port */
- protected String port = null;
-
- /** Endpoint context path of the Alfresco webapp */
- protected String path = null;
-
- protected String repositoryId = null;
- protected String binding = null;
-
- /** Target folder for the drop zone */
- protected String cmisQuery = null;
-
- /** Flag for creating the new tree structure using timestamp**/
- protected String createTimestampTree = Boolean.FALSE.toString();
-
- protected SessionFactory factory = SessionFactoryImpl.newInstance();
- protected Map<String, String> parameters = new HashMap<String, String>();
-
- protected static final long timeToRelease = 300000L;
- protected long lastSessionFetch = -1L;
-
- protected Folder parentDropZoneFolder = null;
-
- /** Save activity */
- protected final static String ACTIVITY_INJECTION = "Injection";
-
- /** Delete activity */
- protected final static String ACTIVITY_DELETE = "Delete";
-
- private static final String CMIS_PROPERTY_PREFIX = "cmis:";
-
- /** Document accepted */
- private final static int DOCUMENT_STATUS_ACCEPTED = 0;
-
- private static final String DOCUMENT_STATUS_ACCEPTED_DESC = "Injection OK - ";
-
- private static final String DOCUMENT_STATUS_REJECTED_DESC = "Injection KO - ";
-
- /** Document permanently rejected */
- private final static int DOCUMENT_STATUS_REJECTED = 1;
-
- /** Document remove accepted */
- private final static String DOCUMENT_DELETION_STATUS_ACCEPTED = "Remove request accepted";
-
- /** Document remove permanently rejected */
- private final static String DOCUMENT_DELETION_STATUS_REJECTED = "Remove request rejected";
-
- private static final String CONTENT_PATH_PARAM = "contentPath";
-
- /**
- * Constructor
- */
- public CmisOutputConnector() {
- super();
- }
-
- /**
- * Return the list of activities that this connector supports (i.e. writes
- * into the log).
- *
- * @return the list.
- */
- @Override
- public String[] getActivitiesList() {
- return new String[] { ACTIVITY_INJECTION, ACTIVITY_DELETE };
- }
-
- protected class GetSessionThread extends Thread {
- protected Throwable exception = null;
-
- public GetSessionThread() {
- super();
- setDaemon(true);
- }
-
- public void run() {
- try {
- // Create a session
- parameters.clear();
-
- // user credentials
- parameters.put(SessionParameter.USER, username);
- parameters.put(SessionParameter.PASSWORD, password);
-
- String endpoint = protocol + "://" + server + ":" + port + path;
-
- // connection settings
- if (CmisOutputConfig.BINDING_ATOM_VALUE.equals(binding)) {
- // AtomPub protocol
- parameters.put(SessionParameter.ATOMPUB_URL, endpoint);
- parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
- } else if (CmisOutputConfig.BINDING_WS_VALUE.equals(binding)) {
- // Web Services - SOAP - protocol
- parameters.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value());
- parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, endpoint + "/ACLService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, endpoint + "/DiscoveryService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, endpoint + "/MultiFilingService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, endpoint + "/NavigationService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, endpoint + "/ObjectService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, endpoint + "/PolicyService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, endpoint + "/RelationshipService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, endpoint + "/RepositoryService?wsdl");
- parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, endpoint + "/VersioningService?wsdl");
- }
- // create session
- if (StringUtils.isEmpty(repositoryId)) {
-
- // get a session from the first CMIS repository exposed by
- // the endpoint
- List<Repository> repos = null;
- try {
- repos = factory.getRepositories(parameters);
- session = repos.get(0).createSession();
- } catch (Exception e) {
- Logging.connectors.error(
- "CMIS: Error during getting CMIS repositories. Please check the endpoint parameters: " + e.getMessage(),
- e);
- this.exception = e;
- }
-
- } else {
-
- // get a session from the repository specified in the
- // configuration with its own ID
- parameters.put(SessionParameter.REPOSITORY_ID, repositoryId);
-
- try {
- session = factory.createSession(parameters);
- } catch (Exception e) {
- Logging.connectors
- .error("CMIS: Error during the creation of the new session. Please check the endpoint parameters: "
- + e.getMessage(), e);
- this.exception = e;
- }
-
- }
-
- } catch (Throwable e) {
- this.exception = e;
- }
- }
-
- public Throwable getException() {
- return exception;
- }
- }
-
- protected class CheckConnectionThread extends Thread {
- protected Throwable exception = null;
-
- public CheckConnectionThread() {
- super();
- setDaemon(true);
- }
-
- public void run() {
- try {
- session.getRepositoryInfo();
- } catch (Throwable e) {
- Logging.connectors.warn("CMIS: Error checking repository: " + e.getMessage(), e);
- this.exception = e;
- }
- }
-
- public Throwable getException() {
- return exception;
- }
-
- }
-
- protected class DestroySessionThread extends Thread {
- protected Throwable exception = null;
-
- public DestroySessionThread() {
- super();
- setDaemon(true);
- }
-
- public void run() {
- try {
- session = null;
- } catch (Throwable e) {
- this.exception = e;
- }
- }
-
- public Throwable getException() {
- return exception;
- }
-
- }
-
- /**
- * Close the connection. Call this before discarding the connection.
- */
- @Override
- public void disconnect() throws ManifoldCFException {
- if (session != null) {
- DestroySessionThread t = new DestroySessionThread();
- try {
- t.start();
- t.join();
- Throwable thr = t.getException();
- if (thr != null) {
- if (thr instanceof RemoteException)
- throw (RemoteException) thr;
- else
- throw (Error) thr;
- }
- session = null;
- lastSessionFetch = -1L;
- } catch (InterruptedException e) {
- t.interrupt();
- throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } catch (RemoteException e) {
- Throwable e2 = e.getCause();
- if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
- throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
- session = null;
- lastSessionFetch = -1L;
- // Treat this as a transient problem
- Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
- }
-
- }
-
- username = null;
- password = null;
- protocol = null;
- server = null;
- port = null;
- path = null;
- binding = null;
- repositoryId = null;
- cmisQuery = null;
- createTimestampTree = Boolean.FALSE.toString();
-
- }
-
- /**
- * This method create a new CMIS session for a CMIS repository, if the
- * repositoryId is not provided in the configuration, the connector will
- * retrieve all the repositories exposed for this endpoint the it will start
- * to use the first one.
- *
- * @param configParameters
- * is the set of configuration parameters, which in this case
- * describe the target appliance, basic auth configuration, etc.
- * (This formerly came out of the ini file.)
- */
- @Override
- public void connect(ConfigParams configParams) {
- super.connect(configParams);
- username = params.getParameter(CmisOutputConfig.USERNAME_PARAM);
- password = params.getParameter(CmisOutputConfig.PASSWORD_PARAM);
- protocol = params.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
- server = params.getParameter(CmisOutputConfig.SERVER_PARAM);
- port = params.getParameter(CmisOutputConfig.PORT_PARAM);
- path = params.getParameter(CmisOutputConfig.PATH_PARAM);
-
- binding = params.getParameter(CmisOutputConfig.BINDING_PARAM);
- cmisQuery = params.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
- createTimestampTree = params.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
-
- if (StringUtils.isNotEmpty(params.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM))) {
- repositoryId = params.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
- }
-
- }
-
- /**
- * Test the connection. Returns a string describing the connection integrity.
- *
- * @return the connection's status as a displayable string.
- */
- @Override
- public String check() throws ManifoldCFException {
- try {
- checkConnection();
- return super.check();
- } catch (ServiceInterruption e) {
- return "Connection temporarily failed: " + e.getMessage();
- } catch (ManifoldCFException e) {
- return "Connection failed: " + e.getMessage();
- }
- }
-
- /** Set up a session */
- protected void getSession() throws ManifoldCFException, ServiceInterruption {
- if (session == null) {
- // Check for parameter validity
-
- if (StringUtils.isEmpty(binding))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.BINDING_PARAM + " required but not set");
-
- if (StringUtils.isEmpty(username))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.USERNAME_PARAM + " required but not set");
-
- if (Logging.connectors.isDebugEnabled())
- Logging.connectors.debug("CMIS: Username = '" + username + "'");
-
- if (StringUtils.isEmpty(password))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.PASSWORD_PARAM + " required but not set");
-
- Logging.connectors.debug("CMIS: Password exists");
-
- if (StringUtils.isEmpty(protocol))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.PROTOCOL_PARAM + " required but not set");
-
- if (StringUtils.isEmpty(server))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.SERVER_PARAM + " required but not set");
-
- if (StringUtils.isEmpty(port))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.PORT_PARAM + " required but not set");
-
- if (StringUtils.isEmpty(path))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.PATH_PARAM + " required but not set");
-
- if (StringUtils.isEmpty(cmisQuery))
- throw new ManifoldCFException("Parameter " + CmisOutputConfig.CMIS_QUERY_PARAM + " required but not set");
-
- long currentTime;
- GetSessionThread t = new GetSessionThread();
- try {
- t.start();
- t.join();
- Throwable thr = t.getException();
- if (thr != null) {
- if (thr instanceof java.net.MalformedURLException)
- throw (java.net.MalformedURLException) thr;
- else if (thr instanceof NotBoundException)
- throw (NotBoundException) thr;
- else if (thr instanceof RemoteException)
- throw (RemoteException) thr;
- else if (thr instanceof CmisConnectionException)
- throw new ManifoldCFException("CMIS: Error during getting a new session: " + thr.getMessage(), thr);
- else if (thr instanceof CmisPermissionDeniedException)
- throw new ManifoldCFException("CMIS: Wrong credentials during getting a new session: " + thr.getMessage(),
- thr);
- else
- throw (Error) thr;
- }
- } catch (InterruptedException e) {
- t.interrupt();
- throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } catch (java.net.MalformedURLException e) {
- throw new ManifoldCFException(e.getMessage(), e);
- } catch (NotBoundException e) {
- // Transient problem: Server not available at the moment.
- Logging.connectors.warn("CMIS: Server not up at the moment: " + e.getMessage(), e);
- currentTime = System.currentTimeMillis();
- throw new ServiceInterruption(e.getMessage(), currentTime + 60000L);
- } catch (RemoteException e) {
- Throwable e2 = e.getCause();
- if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
- throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
- // Treat this as a transient problem
- Logging.connectors.warn("CMIS: Transient remote exception creating session: " + e.getMessage(), e);
- currentTime = System.currentTimeMillis();
- throw new ServiceInterruption(e.getMessage(), currentTime + 60000L);
- }
-
- }
-
- lastSessionFetch = System.currentTimeMillis();
- }
-
- /**
- * Release the session, if it's time.
- */
- protected void releaseCheck() throws ManifoldCFException {
- if (lastSessionFetch == -1L)
- return;
-
- long currentTime = System.currentTimeMillis();
- if (currentTime >= lastSessionFetch + timeToRelease) {
- DestroySessionThread t = new DestroySessionThread();
- try {
- t.start();
- t.join();
- Throwable thr = t.getException();
- if (thr != null) {
- if (thr instanceof RemoteException)
- throw (RemoteException) thr;
- else
- throw (Error) thr;
- }
- session = null;
- lastSessionFetch = -1L;
- } catch (InterruptedException e) {
- t.interrupt();
- throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } catch (RemoteException e) {
- Throwable e2 = e.getCause();
- if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
- throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
- session = null;
- lastSessionFetch = -1L;
- // Treat this as a transient problem
- Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
- }
-
- }
- }
-
- protected void checkConnection() throws ManifoldCFException, ServiceInterruption {
- while (true) {
- boolean noSession = (session == null);
- getSession();
- long currentTime;
- CheckConnectionThread t = new CheckConnectionThread();
- try {
- t.start();
- t.join();
- Throwable thr = t.getException();
- if (thr != null) {
- if (thr instanceof RemoteException)
- throw (RemoteException) thr;
- else if (thr instanceof CmisConnectionException)
- throw new ManifoldCFException("CMIS: Error during checking connection: " + thr.getMessage(), thr);
- else
- throw (Error) thr;
- }
- return;
- } catch (InterruptedException e) {
- t.interrupt();
- throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } catch (RemoteException e) {
- Throwable e2 = e.getCause();
- if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
- throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
- if (noSession) {
- currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Transient error connecting to filenet service: " + e.getMessage(),
- currentTime + 60000L);
- }
- session = null;
- lastSessionFetch = -1L;
- continue;
- }
- }
- }
-
- /**
- * This method is periodically called for all connectors that are connected
- * but not in active use.
- */
- @Override
- public void poll() throws ManifoldCFException {
- if (lastSessionFetch == -1L)
- return;
-
- long currentTime = System.currentTimeMillis();
- if (currentTime >= lastSessionFetch + timeToRelease) {
- DestroySessionThread t = new DestroySessionThread();
- try {
- t.start();
- t.join();
- Throwable thr = t.getException();
- if (thr != null) {
- if (thr instanceof RemoteException)
- throw (RemoteException) thr;
- else
- throw (Error) thr;
- }
- session = null;
- lastSessionFetch = -1L;
- } catch (InterruptedException e) {
- t.interrupt();
- throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } catch (RemoteException e) {
- Throwable e2 = e.getCause();
- if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
- throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
- session = null;
- lastSessionFetch = -1L;
- // Treat this as a transient problem
- Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
- }
-
- }
- }
-
- /**
- * This method is called to assess whether to count this connector instance
- * should actually be counted as being connected.
- *
- * @return true if the connector instance is actually connected.
- */
- @Override
- public boolean isConnected() {
- return session != null;
- }
-
- /**
- * Read the content of a resource, replace the variable ${PARAMNAME} with the
- * value and copy it to the out.
- *
- * @param resName
- * @param out
- * @throws ManifoldCFException
- */
- private static void outputResource(String resName, IHTTPOutput out, Locale locale, Map<String, String> paramMap)
- throws ManifoldCFException {
- Messages.outputResourceWithVelocity(out, locale, resName, paramMap, true);
- }
-
- /**
- * Fill in a Server tab configuration parameter map for calling a Velocity
- * template.
- *
- * @param newMap
- * is the map to fill in
- * @param parameters
- * is the current set of configuration parameters
- */
- private static void fillInServerConfigurationMap(Map<String, String> newMap, IPasswordMapperActivity mapper,
- ConfigParams parameters) {
- String username = parameters.getParameter(CmisOutputConfig.USERNAME_PARAM);
- String password = parameters.getParameter(CmisOutputConfig.PASSWORD_PARAM);
- String protocol = parameters.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
- String server = parameters.getParameter(CmisOutputConfig.SERVER_PARAM);
- String port = parameters.getParameter(CmisOutputConfig.PORT_PARAM);
- String path = parameters.getParameter(CmisOutputConfig.PATH_PARAM);
- String repositoryId = parameters.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
- String binding = parameters.getParameter(CmisOutputConfig.BINDING_PARAM);
- String cmisQuery = parameters.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
- String createTimestampTree = parameters.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
-
- if (username == null)
- username = StringUtils.EMPTY;
- if (password == null)
- password = StringUtils.EMPTY;
- else
- password = mapper.mapPasswordToKey(password);
- if (protocol == null)
- protocol = CmisOutputConfig.PROTOCOL_DEFAULT_VALUE;
- if (server == null)
- server = CmisOutputConfig.SERVER_DEFAULT_VALUE;
- if (port == null)
- port = CmisOutputConfig.PORT_DEFAULT_VALUE;
- if (path == null)
- path = CmisOutputConfig.PATH_DEFAULT_VALUE;
- if (repositoryId == null)
- repositoryId = StringUtils.EMPTY;
- if (binding == null)
- binding = CmisOutputConfig.BINDING_ATOM_VALUE;
- if (cmisQuery == null)
- cmisQuery = CmisOutputConfig.CMIS_QUERY_DEFAULT_VALUE;
- if(createTimestampTree == null)
- createTimestampTree = CmisOutputConfig.CREATE_TIMESTAMP_TREE_DEFAULT_VALUE;
-
- newMap.put(CmisOutputConfig.USERNAME_PARAM, username);
- newMap.put(CmisOutputConfig.PASSWORD_PARAM, password);
- newMap.put(CmisOutputConfig.PROTOCOL_PARAM, protocol);
- newMap.put(CmisOutputConfig.SERVER_PARAM, server);
- newMap.put(CmisOutputConfig.PORT_PARAM, port);
- newMap.put(CmisOutputConfig.PATH_PARAM, path);
- newMap.put(CmisOutputConfig.REPOSITORY_ID_PARAM, repositoryId);
- newMap.put(CmisOutputConfig.BINDING_PARAM, binding);
- newMap.put(CmisOutputConfig.CMIS_QUERY_PARAM, cmisQuery);
- newMap.put(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM, createTimestampTree);
- }
-
- /**
- * View configuration. This method is called in the body section of the
- * connector's view configuration page. Its purpose is to present the
- * connection information to the user. The coder can presume that the HTML
- * that is output from this configuration will be within appropriate
- * <html> and <body> tags.
- *
- * @param threadContext
- * is the local thread context.
- * @param out
- * is the output to which any HTML should be sent.
- * @param parameters
- * are the configuration parameters, as they currently exist, for
- * this connection being configured.
- */
- @Override
- public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters)
- throws ManifoldCFException, IOException {
- Map<String, String> paramMap = new HashMap<String, String>();
-
- // Fill in map from each tab
- fillInServerConfigurationMap(paramMap, out, parameters);
-
- outputResource(VIEW_CONFIG_FORWARD, out, locale, paramMap);
- }
-
- /**
- *
- * Output the configuration header section. This method is called in the head
- * section of the connector's configuration page. Its purpose is to add the
- * required tabs to the list, and to output any javascript methods that might
- * be needed by the configuration editing HTML.
- *
- * @param threadContext
- * is the local thread context.
- * @param out
- * is the output to which any HTML should be sent.
- * @param parameters
- * are the configuration parameters, as they currently exist, for
- * this connection being configured.
- * @param tabsArray
- * is an array of tab names. Add to this array any tab names that are
- * specific to the connector.
- */
- @Override
- public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out, Locale locale,
- ConfigParams parameters, List<String> tabsArray) throws ManifoldCFException, IOException {
- // Add the Server tab
- tabsArray.add(Messages.getString(locale, CMIS_SERVER_TAB_PROPERTY));
- // Map the parameters
- Map<String, String> paramMap = new HashMap<String, String>();
-
- // Fill in the parameters from each tab
- fillInServerConfigurationMap(paramMap, out, parameters);
-
- // Output the Javascript - only one Velocity template for all tabs
- outputResource(EDIT_CONFIG_HEADER_FORWARD, out, locale, paramMap);
- }
-
- @Override
- public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, Locale locale,
- ConfigParams parameters, String tabName) throws ManifoldCFException, IOException {
-
- // Call the Velocity templates for each tab
-
- // Server tab
- Map<String, String> paramMap = new HashMap<String, String>();
- // Set the tab name
- paramMap.put("TabName", tabName);
- // Fill in the parameters
- fillInServerConfigurationMap(paramMap, out, parameters);
- outputResource(EDIT_CONFIG_FORWARD_SERVER, out, locale, paramMap);
-
- }
-
- /**
- * Process a configuration post. This method is called at the start of the
- * connector's configuration page, whenever there is a possibility that form
- * data for a connection has been posted. Its purpose is to gather form
- * information and modify the configuration parameters accordingly. The name
- * of the posted form is "editconnection".
- *
- * @param threadContext
- * is the local thread context.
- * @param variableContext
- * is the set of variables available from the post, including binary
- * file post information.
- * @param parameters
- * are the configuration parameters, as they currently exist, for
- * this connection being configured.
- * @return null if all is well, or a string error message if there is an error
- * that should prevent saving of the connection (and cause a
- * redirection to an error page).
- */
- @Override
- public String processConfigurationPost(IThreadContext threadContext, IPostParameters variableContext,
- ConfigParams parameters) throws ManifoldCFException {
-
- String binding = variableContext.getParameter(CmisOutputConfig.BINDING_PARAM);
- if (binding != null)
- parameters.setParameter(CmisOutputConfig.BINDING_PARAM, binding);
-
- String username = variableContext.getParameter(CmisOutputConfig.USERNAME_PARAM);
- if (username != null)
- parameters.setParameter(CmisOutputConfig.USERNAME_PARAM, username);
-
- String password = variableContext.getParameter(CmisOutputConfig.PASSWORD_PARAM);
- if (password != null)
- parameters.setParameter(CmisOutputConfig.PASSWORD_PARAM, variableContext.mapKeyToPassword(password));
-
- String protocol = variableContext.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
- if (protocol != null) {
- parameters.setParameter(CmisOutputConfig.PROTOCOL_PARAM, protocol);
- }
-
- String server = variableContext.getParameter(CmisOutputConfig.SERVER_PARAM);
- if (server != null && !StringUtils.contains(server, '/')) {
- parameters.setParameter(CmisOutputConfig.SERVER_PARAM, server);
- }
-
- String port = variableContext.getParameter(CmisOutputConfig.PORT_PARAM);
- if (port != null) {
- try {
- Integer.parseInt(port);
- parameters.setParameter(CmisOutputConfig.PORT_PARAM, port);
- } catch (NumberFormatException e) {
-
- }
- }
-
- String path = variableContext.getParameter(CmisOutputConfig.PATH_PARAM);
- if (path != null) {
- parameters.setParameter(CmisOutputConfig.PATH_PARAM, path);
- }
-
- String cmisQuery = variableContext.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
- if (cmisQuery != null) {
- parameters.setParameter(CmisOutputConfig.CMIS_QUERY_PARAM, cmisQuery);
- }
-
- String createTimestampTree = variableContext.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
- if (createTimestampTree != null) {
- parameters.setParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM, createTimestampTree);
- }
-
- String repositoryId = variableContext.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
- if (repositoryId != null) {
- parameters.setParameter(CmisOutputConfig.REPOSITORY_ID_PARAM, repositoryId);
- }
-
- return null;
- }
-
- protected static void handleIOException(IOException e, String context)
- throws ManifoldCFException, ServiceInterruption {
- if (e instanceof InterruptedIOException) {
- throw new ManifoldCFException(e.getMessage(), e, ManifoldCFException.INTERRUPTED);
- } else {
- Logging.connectors.warn("CMIS: IOException " + context + ": " + e.getMessage(), e);
- throw new ManifoldCFException(e.getMessage(), e);
- }
- }
-
- /**
- * Check if the target drop zone is a CMIS folder
- *
- * @return
- */
- private boolean isDropZoneFolder(String cmisQuery) {
- boolean isDropZoneFolder = false;
-
- // Get the drop zone folder
- ItemIterable<QueryResult> dropZoneItemIterable = session.query(cmisQuery, false);
- Iterator<QueryResult> dropZoneIterator = dropZoneItemIterable.iterator();
- String baseTypeId = null;
- while (dropZoneIterator.hasNext()) {
- QueryResult dropZoneResult = (QueryResult) dropZoneIterator.next();
-
- // check if it is a base folder content type
- baseTypeId = dropZoneResult.getPropertyByQueryName(PropertyIds.BASE_TYPE_ID).getFirstValue().toString();
- if (StringUtils.isNotEmpty(baseTypeId) && StringUtils.equals(baseTypeId, EnumBaseObjectTypeIds.CMIS_FOLDER.value())) {
- String objectId = dropZoneResult.getPropertyValueById(PropertyIds.OBJECT_ID);
- parentDropZoneFolder = (Folder) session.getObject(objectId);
- isDropZoneFolder = true;
- }
- }
- return isDropZoneFolder;
- }
-
- private boolean isSourceRepoCmisCompliant(RepositoryDocument document) {
- Iterator<String> fields = document.getFields();
- while (fields.hasNext()) {
- String fieldName = (String) fields.next();
- if (StringUtils.startsWith(fieldName, CMIS_PROPERTY_PREFIX)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public int addOrReplaceDocumentWithException(String documentURI, VersionContext pipelineDescription,
- RepositoryDocument document, String authorityNameString, IOutputAddActivity activities)
- throws ManifoldCFException, ServiceInterruption, IOException {
-
- getSession();
-
- boolean isDropZoneFolder = isDropZoneFolder(cmisQuery);
- long startTime = System.currentTimeMillis();
- String resultDescription = StringUtils.EMPTY;
- Folder leafParent = null;
- String fileName = StringUtils.EMPTY;
- InputStream inputStream = null;
- ContentStream contentStream = null;
- // properties
- // (minimal set: name and object type id)
- Map<String, Object> properties = new HashMap<String, Object>();
- Long binaryLength = null;
- String mimeType = StringUtils.EMPTY;
- try {
- if (isDropZoneFolder) {
-
- // Creation of the new Repository Node
- fileName = document.getFileName();
- Date creationDate = document.getCreatedDate();
- Date lastModificationDate = document.getModifiedDate();
- String objectId = StringUtils.EMPTY;
- mimeType = document.getMimeType();
- binaryLength = document.getBinaryLength();
-
- //check if the repository connector includes the content path
- String primaryPath = StringUtils.EMPTY;
- List<String> sourcePath = document.getSourcePath();
- if(sourcePath != null && !sourcePath.isEmpty()) {
- primaryPath = sourcePath.get(0);
- }
-
-
-
- //if the source is CMIS Repository Connector we override the objectId for synchronizing with removeDocument method
- if(isSourceRepoCmisCompliant(document)) {
- String[] cmisObjectIdArray = (String[]) document.getField(PropertyIds.OBJECT_ID);
- if(cmisObjectIdArray!=null && cmisObjectIdArray.length>0) {
- objectId = cmisObjectIdArray[0];
- }
-
- //Mapping all the CMIS properties ...
- /*
- Iterator<String> fields = document.getFields();
- while (fields.hasNext()) {
- String field = (String) fields.next();
- if(!StringUtils.equals(field, "cm:lastThumbnailModification")
- || !StringUtils.equals(field, "cmis:secondaryObjectTypeIds")) {
- String[] valuesArray = (String[]) document.getField(field);
- properties.put(field,valuesArray);
- }
- }
- */
- }
-
- //Agnostic metadata
- properties.put(PropertyIds.OBJECT_TYPE_ID, EnumBaseObjectTypeIds.CMIS_DOCUMENT.value());
- properties.put(PropertyIds.NAME, fileName);
- properties.put(PropertyIds.CREATION_DATE, creationDate);
- properties.put(PropertyIds.LAST_MODIFICATION_DATE, lastModificationDate);
-
- //check objectId
- if(StringUtils.isNotEmpty(objectId)){
- ObjectId objId = new ObjectIdImpl(objectId);
- properties.put(PropertyIds.OBJECT_ID, objId);
- }
-
- // Content Stream
- inputStream = document.getBinaryStream();
- contentStream = new ContentStreamImpl(fileName, BigInteger.valueOf(binaryLength), mimeType,
- inputStream);
-
- // create a major version
- leafParent = getOrCreateLeafParent(parentDropZoneFolder, creationDate, Boolean.valueOf(createTimestampTree), primaryPath);
- leafParent.createDocument(properties, contentStream, VersioningState.NONE);
- resultDescription = DOCUMENT_STATUS_ACCEPTED_DESC;
- return DOCUMENT_STATUS_ACCEPTED;
-
- } else {
- resultDescription = DOCUMENT_STATUS_REJECTED_DESC;
- return DOCUMENT_STATUS_REJECTED;
- }
-
- } catch (CmisContentAlreadyExistsException | CmisNameConstraintViolationException e) {
-
- //updating the existing content
- if(leafParent != null) {
- String documentFullPath = leafParent.getPath() + CmisOutputConnectorUtils.SLASH + fileName;
- String newFileName = fileName+System.currentTimeMillis();
-
- Document currentContent = (Document) session.getObjectByPath(documentFullPath);
- currentContent.updateProperties(properties);
- contentStream = new ContentStreamImpl(newFileName, BigInteger.valueOf(binaryLength), mimeType, inputStream);
- currentContent.setContentStream(contentStream, true);
-
- Logging.connectors.warn(
- "CMIS: Document already exists - Updating: " + documentFullPath);
- }
-
- resultDescription = DOCUMENT_STATUS_ACCEPTED_DESC;
- return DOCUMENT_STATUS_ACCEPTED;
-
- } catch (Exception e) {
- resultDescription = DOCUMENT_STATUS_REJECTED_DESC;
- throw new ManifoldCFException(e.getMessage(), e);
-
- } finally {
-
- if(inputStream != null) {
- inputStream.close();
- }
-
- activities.recordActivity(startTime, ACTIVITY_INJECTION, document.getBinaryLength(), documentURI, resultDescription,
- resultDescription);
- }
-
- }
-
- /**
- * Check and create the leaf folder dedicate to inject the content
- * @param folder: this is the root folder where starts the tree
- * @param creationDate: this is the creation date of the current content
- * @param createTimestampTree: this is the flag checked in the ManifoldCF configuration panel
- * @return the target folder created using the creationDate related to the injected content
- */
- private Folder getOrCreateLeafParent(Folder folder, Date creationDate, boolean createTimestampTree, String primaryPath) {
- Folder leafParent = folder;
- if (createTimestampTree) {
- GregorianCalendar calendar = new GregorianCalendar();
- calendar.setTime(creationDate);
- String year = String.valueOf(calendar.get(GregorianCalendar.YEAR));
- String month = String.valueOf((calendar.get(GregorianCalendar.MONTH)+1));
- String day = String.valueOf(calendar.get(GregorianCalendar.DAY_OF_MONTH));
-
- //Check and create all the new folders
- Folder yearFolder = createFolderIfNotExist(leafParent, year);
- Folder monthFolder = createFolderIfNotExist(yearFolder, month);
- Folder dayFolder = createFolderIfNotExist(monthFolder, day);
-
- leafParent = dayFolder;
-
- } else if(StringUtils.isNotEmpty(primaryPath)) {
- String[] primaryPathArray = StringUtils.split(primaryPath, CmisOutputConnectorUtils.SLASH);
- leafParent = folder;
- for (int i = 0; i < primaryPathArray.length - 1; i++) {
- String pathSegment = primaryPathArray[i];
- Folder pathSegmentFolder = createFolderIfNotExist(leafParent, pathSegment);
- leafParent = pathSegmentFolder;
- }
- }
- return leafParent;
- }
-
- /**
- * Create a new CMIS folder as a child node of leafParent
- * @param leafParent
- * @param folderName
- * @return the current CMIS folder if exists otherwise it will return a new one
- */
- private Folder createFolderIfNotExist(Folder leafParent, String folderName) {
- Folder folder = null;
- try {
- folder = (Folder) session.getObjectByPath(leafParent.getPath() + CmisOutputConnectorUtils.SLASH + folderName);
- } catch (CmisObjectNotFoundException onfe) {
- Map<String, Object> props = new HashMap<String, Object>();
- props.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
- props.put(PropertyIds.NAME, folderName);
- folder = leafParent.createFolder(props);
-
- String folderId = folder.getId();
- String folderPath = folder.getPath();
- Logging.connectors.info(
- "CMIS: Created a new folder - id: " + folderId +
- " | Path: " + folderPath);
- }
- return folder;
- }
-
-
- /**
- * Encoding process to retrieve the contentPath parameter from the documentURI.
- * The contentPath parameter can be passed from any repository connector that is currently supporting the content migration capability.
- * @param documentURI
- * @return contentPath
- * @throws URISyntaxException
- * @throws UnsupportedEncodingException
- */
- private String getContentPath(String documentURI) throws URISyntaxException, UnsupportedEncodingException {
- String contentPath = StringUtils.EMPTY;
- String documentURIWithFixedEncoding = StringUtils.replace(documentURI, " ", "%20");
- List<NameValuePair> params = URLEncodedUtils.parse(new URI(documentURIWithFixedEncoding), StandardCharsets.UTF_8);
- Iterator<NameValuePair> paramsIterator = params.iterator();
- while (paramsIterator.hasNext()) {
- NameValuePair param = (NameValuePair) paramsIterator.next();
- if(StringUtils.equals(CONTENT_PATH_PARAM, param.getName())){
- contentPath = param.getValue();
- }
- }
- return contentPath;
- }
-
- @Override
- public void removeDocument(String documentURI, String outputDescription, IOutputRemoveActivity activities)
- throws ManifoldCFException, ServiceInterruption {
- getSession();
- long startTime = System.currentTimeMillis();
- String result = StringUtils.EMPTY;
- boolean isDropZoneFolder = isDropZoneFolder(cmisQuery);
-
- //append the prefix for the relative path in the target repo
- try {
- if(isDropZoneFolder
- && parentDropZoneFolder != null
- && StringUtils.isNotEmpty(documentURI)) {
- String parentDropZonePath = parentDropZoneFolder.getPath();
-
- String contentPath = getContentPath(documentURI);
- String fullDocumentURIinTargetRepo = parentDropZonePath + contentPath;
-
- if(session.existsPath(fullDocumentURIinTargetRepo)) {
- session.deleteByPath(fullDocumentURIinTargetRepo);
- result = DOCUMENT_DELETION_STATUS_ACCEPTED;
- } else {
- result = DOCUMENT_DELETION_STATUS_REJECTED;
- }
- } else {
- result = DOCUMENT_DELETION_STATUS_REJECTED;
- }
- } catch (Exception e) {
- result = DOCUMENT_DELETION_STATUS_REJECTED;
- throw new ManifoldCFException(e.getMessage(), e);
- } finally {
- activities.recordActivity(startTime, ACTIVITY_DELETE, null, documentURI, null, result);
- }
- }
-
-
+ /** Forward to the javascript to check the configuration parameters */
+ private static final String EDIT_CONFIG_HEADER_FORWARD = "editConfiguration.js";
+
+ /** Server tab template */
+ private static final String EDIT_CONFIG_FORWARD_SERVER = "editConfiguration_Server.html";
+
+ /** Forward to the HTML template to view the configuration parameters */
+ private static final String VIEW_CONFIG_FORWARD = "viewConfiguration.html";
+
+ /**
+ * CMIS Session handle
+ */
+ Session session = null;
+
+ protected String username = null;
+ protected String password = null;
+
+ /** Endpoint protocol */
+ protected String protocol = null;
+
+ /** Endpoint server name */
+ protected String server = null;
+
+ /** Endpoint port */
+ protected String port = null;
+
+ /** Endpoint context path of the Alfresco webapp */
+ protected String path = null;
+
+ protected String repositoryId = null;
+ protected String binding = null;
+
+ /** Target folder for the drop zone */
+ protected String cmisQuery = null;
+
+ /** Flag for creating the new tree structure using timestamp**/
+ protected String createTimestampTree = Boolean.FALSE.toString();
+
+ protected SessionFactory factory = SessionFactoryImpl.newInstance();
+ protected Map<String, String> parameters = new HashMap<String, String>();
+
+ protected static final long timeToRelease = 300000L;
+ protected long lastSessionFetch = -1L;
+
+ protected Folder parentDropZoneFolder = null;
+
+ /** Save activity */
+ protected final static String ACTIVITY_INJECTION = "Injection";
+
+ /** Delete activity */
+ protected final static String ACTIVITY_DELETE = "Delete";
+
+ private static final String CMIS_PROPERTY_PREFIX = "cmis:";
+
+ /** Document accepted */
+ private final static int DOCUMENT_STATUS_ACCEPTED = 0;
+
+ private static final String DOCUMENT_STATUS_ACCEPTED_DESC = "Injection OK - ";
+
+ private static final String DOCUMENT_STATUS_REJECTED_DESC = "Injection KO - ";
+
+ /** Document permanently rejected */
+ private final static int DOCUMENT_STATUS_REJECTED = 1;
+
+ /** Document remove accepted */
+ private final static String DOCUMENT_DELETION_STATUS_ACCEPTED = "Remove request accepted";
+
+ /** Document remove permanently rejected */
+ private final static String DOCUMENT_DELETION_STATUS_REJECTED = "Remove request rejected";
+
+ private static final String CONTENT_PATH_PARAM = "contentPath";
+
+ /**
+ * Constructor
+ */
+ public CmisOutputConnector() {
+ super();
+ }
+
+ /**
+ * Return the list of activities that this connector supports (i.e. writes
+ * into the log).
+ *
+ * @return the list.
+ */
+ @Override
+ public String[] getActivitiesList() {
+ return new String[] { ACTIVITY_INJECTION, ACTIVITY_DELETE };
+ }
+
+ protected class GetSessionThread extends Thread {
+ protected Throwable exception = null;
+
+ public GetSessionThread() {
+ super();
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ // Create a session
+ parameters.clear();
+
+ // user credentials
+ parameters.put(SessionParameter.USER, username);
+ parameters.put(SessionParameter.PASSWORD, password);
+
+ String endpoint = protocol + "://" + server + ":" + port + path;
+
+ // connection settings
+ if (CmisOutputConfig.BINDING_ATOM_VALUE.equals(binding)) {
+ // AtomPub protocol
+ parameters.put(SessionParameter.ATOMPUB_URL, endpoint);
+ parameters.put(SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
+ } else if (CmisOutputConfig.BINDING_WS_VALUE.equals(binding)) {
+ // Web Services - SOAP - protocol
+ parameters.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value());
+ parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, endpoint + "/ACLService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, endpoint + "/DiscoveryService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, endpoint + "/MultiFilingService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, endpoint + "/NavigationService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, endpoint + "/ObjectService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, endpoint + "/PolicyService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, endpoint + "/RelationshipService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, endpoint + "/RepositoryService?wsdl");
+ parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, endpoint + "/VersioningService?wsdl");
+ }
+ // create session
+ if (StringUtils.isEmpty(repositoryId)) {
+
+ // get a session from the first CMIS repository exposed by
+ // the endpoint
+ List<Repository> repos = null;
+ try {
+ repos = factory.getRepositories(parameters);
+ session = repos.get(0).createSession();
+ } catch (Exception e) {
+ Logging.connectors.error(
+ "CMIS: Error during getting CMIS repositories. Please check the endpoint parameters: " + e.getMessage(),
+ e);
+ this.exception = e;
+ }
+
+ } else {
+
+ // get a session from the repository specified in the
+ // configuration with its own ID
+ parameters.put(SessionParameter.REPOSITORY_ID, repositoryId);
+
+ try {
+ session = factory.createSession(parameters);
+ } catch (Exception e) {
+ Logging.connectors
+ .error("CMIS: Error during the creation of the new session. Please check the endpoint parameters: "
+ + e.getMessage(), e);
+ this.exception = e;
+ }
+
+ }
+
+ } catch (Throwable e) {
+ this.exception = e;
+ }
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+ }
+
+ protected class CheckConnectionThread extends Thread {
+ protected Throwable exception = null;
+
+ public CheckConnectionThread() {
+ super();
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ session.getRepositoryInfo();
+ } catch (Throwable e) {
+ Logging.connectors.warn("CMIS: Error checking repository: " + e.getMessage(), e);
+ this.exception = e;
+ }
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+
+ }
+
+ protected class DestroySessionThread extends Thread {
+ protected Throwable exception = null;
+
+ public DestroySessionThread() {
+ super();
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ session = null;
+ } catch (Throwable e) {
+ this.exception = e;
+ }
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+
+ }
+
+ /**
+ * Close the connection. Call this before discarding the connection.
+ */
+ @Override
+ public void disconnect() throws ManifoldCFException {
+ if (session != null) {
+ DestroySessionThread t = new DestroySessionThread();
+ try {
+ t.start();
+ t.join();
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof RemoteException)
+ throw (RemoteException) thr;
+ else
+ throw (Error) thr;
+ }
+ session = null;
+ lastSessionFetch = -1L;
+ } catch (InterruptedException e) {
+ t.interrupt();
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } catch (RemoteException e) {
+ Throwable e2 = e.getCause();
+ if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
+ throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
+ session = null;
+ lastSessionFetch = -1L;
+ // Treat this as a transient problem
+ Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
+ }
+
+ }
+
+ username = null;
+ password = null;
+ protocol = null;
+ server = null;
+ port = null;
+ path = null;
+ binding = null;
+ repositoryId = null;
+ cmisQuery = null;
+ createTimestampTree = Boolean.FALSE.toString();
+
+ }
+
+ /**
+ * This method create a new CMIS session for a CMIS repository, if the
+ * repositoryId is not provided in the configuration, the connector will
+ * retrieve all the repositories exposed for this endpoint the it will start
+ * to use the first one.
+ *
+ * @param configParameters
+ * is the set of configuration parameters, which in this case
+ * describe the target appliance, basic auth configuration, etc.
+ * (This formerly came out of the ini file.)
+ */
+ @Override
+ public void connect(ConfigParams configParams) {
+ super.connect(configParams);
+ username = params.getParameter(CmisOutputConfig.USERNAME_PARAM);
+ password = params.getParameter(CmisOutputConfig.PASSWORD_PARAM);
+ protocol = params.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
+ server = params.getParameter(CmisOutputConfig.SERVER_PARAM);
+ port = params.getParameter(CmisOutputConfig.PORT_PARAM);
+ path = params.getParameter(CmisOutputConfig.PATH_PARAM);
+
+ binding = params.getParameter(CmisOutputConfig.BINDING_PARAM);
+ cmisQuery = params.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
+ createTimestampTree = params.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
+
+ if (StringUtils.isNotEmpty(params.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM))) {
+ repositoryId = params.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
+ }
+
+ }
+
+ /**
+ * Test the connection. Returns a string describing the connection integrity.
+ *
+ * @return the connection's status as a displayable string.
+ */
+ @Override
+ public String check() throws ManifoldCFException {
+ try {
+ checkConnection();
+ return super.check();
+ } catch (ServiceInterruption e) {
+ return "Connection temporarily failed: " + e.getMessage();
+ } catch (ManifoldCFException e) {
+ return "Connection failed: " + e.getMessage();
+ }
+ }
+
+ /** Set up a session */
+ protected void getSession() throws ManifoldCFException, ServiceInterruption {
+ if (session == null) {
+ // Check for parameter validity
+
+ if (StringUtils.isEmpty(binding))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.BINDING_PARAM + " required but not set");
+
+ if (StringUtils.isEmpty(username))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.USERNAME_PARAM + " required but not set");
+
+ if (Logging.connectors.isDebugEnabled())
+ Logging.connectors.debug("CMIS: Username = '" + username + "'");
+
+ if (StringUtils.isEmpty(password))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.PASSWORD_PARAM + " required but not set");
+
+ Logging.connectors.debug("CMIS: Password exists");
+
+ if (StringUtils.isEmpty(protocol))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.PROTOCOL_PARAM + " required but not set");
+
+ if (StringUtils.isEmpty(server))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.SERVER_PARAM + " required but not set");
+
+ if (StringUtils.isEmpty(port))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.PORT_PARAM + " required but not set");
+
+ if (StringUtils.isEmpty(path))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.PATH_PARAM + " required but not set");
+
+ if (StringUtils.isEmpty(cmisQuery))
+ throw new ManifoldCFException("Parameter " + CmisOutputConfig.CMIS_QUERY_PARAM + " required but not set");
+
+ long currentTime;
+ GetSessionThread t = new GetSessionThread();
+ try {
+ t.start();
+ t.join();
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof java.net.MalformedURLException)
+ throw (java.net.MalformedURLException) thr;
+ else if (thr instanceof NotBoundException)
+ throw (NotBoundException) thr;
+ else if (thr instanceof RemoteException)
+ throw (RemoteException) thr;
+ else if (thr instanceof CmisConnectionException)
+ throw new ManifoldCFException("CMIS: Error during getting a new session: " + thr.getMessage(), thr);
+ else if (thr instanceof CmisPermissionDeniedException)
+ throw new ManifoldCFException("CMIS: Wrong credentials during getting a new session: " + thr.getMessage(),
+ thr);
+ else
+ throw (Error) thr;
+ }
+ } catch (InterruptedException e) {
+ t.interrupt();
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } catch (java.net.MalformedURLException e) {
+ throw new ManifoldCFException(e.getMessage(), e);
+ } catch (NotBoundException e) {
+ // Transient problem: Server not available at the moment.
+ Logging.connectors.warn("CMIS: Server not up at the moment: " + e.getMessage(), e);
+ currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption(e.getMessage(), currentTime + 60000L);
+ } catch (RemoteException e) {
+ Throwable e2 = e.getCause();
+ if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
+ throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
+ // Treat this as a transient problem
+ Logging.connectors.warn("CMIS: Transient remote exception creating session: " + e.getMessage(), e);
+ currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption(e.getMessage(), currentTime + 60000L);
+ }
+
+ }
+
+ lastSessionFetch = System.currentTimeMillis();
+ }
+
+ /**
+ * Release the session, if it's time.
+ */
+ protected void releaseCheck() throws ManifoldCFException {
+ if (lastSessionFetch == -1L)
+ return;
+
+ long currentTime = System.currentTimeMillis();
+ if (currentTime >= lastSessionFetch + timeToRelease) {
+ DestroySessionThread t = new DestroySessionThread();
+ try {
+ t.start();
+ t.join();
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof RemoteException)
+ throw (RemoteException) thr;
+ else
+ throw (Error) thr;
+ }
+ session = null;
+ lastSessionFetch = -1L;
+ } catch (InterruptedException e) {
+ t.interrupt();
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } catch (RemoteException e) {
+ Throwable e2 = e.getCause();
+ if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
+ throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
+ session = null;
+ lastSessionFetch = -1L;
+ // Treat this as a transient problem
+ Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
+ }
+
+ }
+ }
+
+ protected void checkConnection() throws ManifoldCFException, ServiceInterruption {
+ while (true) {
+ boolean noSession = (session == null);
+ getSession();
+ long currentTime;
+ CheckConnectionThread t = new CheckConnectionThread();
+ try {
+ t.start();
+ t.join();
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof RemoteException)
+ throw (RemoteException) thr;
+ else if (thr instanceof CmisConnectionException)
+ throw new ManifoldCFException("CMIS: Error during checking connection: " + thr.getMessage(), thr);
+ else
+ throw (Error) thr;
+ }
+ return;
+ } catch (InterruptedException e) {
+ t.interrupt();
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } catch (RemoteException e) {
+ Throwable e2 = e.getCause();
+ if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
+ throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
+ if (noSession) {
+ currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption("Transient error connecting to filenet service: " + e.getMessage(),
+ currentTime + 60000L);
+ }
+ session = null;
+ lastSessionFetch = -1L;
+ continue;
+ }
+ }
+ }
+
+ /**
+ * This method is periodically called for all connectors that are connected
+ * but not in active use.
+ */
+ @Override
+ public void poll() throws ManifoldCFException {
+ if (lastSessionFetch == -1L)
+ return;
+
+ long currentTime = System.currentTimeMillis();
+ if (currentTime >= lastSessionFetch + timeToRelease) {
+ DestroySessionThread t = new DestroySessionThread();
+ try {
+ t.start();
+ t.join();
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof RemoteException)
+ throw (RemoteException) thr;
+ else
+ throw (Error) thr;
+ }
+ session = null;
+ lastSessionFetch = -1L;
+ } catch (InterruptedException e) {
+ t.interrupt();
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } catch (RemoteException e) {
+ Throwable e2 = e.getCause();
+ if (e2 instanceof InterruptedException || e2 instanceof InterruptedIOException)
+ throw new ManifoldCFException(e2.getMessage(), e2, ManifoldCFException.INTERRUPTED);
+ session = null;
+ lastSessionFetch = -1L;
+ // Treat this as a transient problem
+ Logging.connectors.warn("CMIS: Transient remote exception closing session: " + e.getMessage(), e);
+ }
+
+ }
+ }
+
+ /**
+ * This method is called to assess whether to count this connector instance
+ * should actually be counted as being connected.
+ *
+ * @return true if the connector instance is actually connected.
+ */
+ @Override
+ public boolean isConnected() {
+ return session != null;
+ }
+
+ /**
+ * Read the content of a resource, replace the variable ${PARAMNAME} with the
+ * value and copy it to the out.
+ *
+ * @param resName
+ * @param out
+ * @throws ManifoldCFException
+ */
+ private static void outputResource(String resName, IHTTPOutput out, Locale locale, Map<String, String> paramMap)
+ throws ManifoldCFException {
+ Messages.outputResourceWithVelocity(out, locale, resName, paramMap, true);
+ }
+
+ /**
+ * Fill in a Server tab configuration parameter map for calling a Velocity
+ * template.
+ *
+ * @param newMap
+ * is the map to fill in
+ * @param parameters
+ * is the current set of configuration parameters
+ */
+ private static void fillInServerConfigurationMap(Map<String, String> newMap, IPasswordMapperActivity mapper,
+ ConfigParams parameters) {
+ String username = parameters.getParameter(CmisOutputConfig.USERNAME_PARAM);
+ String password = parameters.getParameter(CmisOutputConfig.PASSWORD_PARAM);
+ String protocol = parameters.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
+ String server = parameters.getParameter(CmisOutputConfig.SERVER_PARAM);
+ String port = parameters.getParameter(CmisOutputConfig.PORT_PARAM);
+ String path = parameters.getParameter(CmisOutputConfig.PATH_PARAM);
+ String repositoryId = parameters.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
+ String binding = parameters.getParameter(CmisOutputConfig.BINDING_PARAM);
+ String cmisQuery = parameters.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
+ String createTimestampTree = parameters.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
+
+ if (username == null)
+ username = StringUtils.EMPTY;
+ if (password == null)
+ password = StringUtils.EMPTY;
+ else
+ password = mapper.mapPasswordToKey(password);
+ if (protocol == null)
+ protocol = CmisOutputConfig.PROTOCOL_DEFAULT_VALUE;
+ if (server == null)
+ server = CmisOutputConfig.SERVER_DEFAULT_VALUE;
+ if (port == null)
+ port = CmisOutputConfig.PORT_DEFAULT_VALUE;
+ if (path == null)
+ path = CmisOutputConfig.PATH_DEFAULT_VALUE;
+ if (repositoryId == null)
+ repositoryId = StringUtils.EMPTY;
+ if (binding == null)
+ binding = CmisOutputConfig.BINDING_ATOM_VALUE;
+ if (cmisQuery == null)
+ cmisQuery = CmisOutputConfig.CMIS_QUERY_DEFAULT_VALUE;
+ if(createTimestampTree == null)
+ createTimestampTree = CmisOutputConfig.CREATE_TIMESTAMP_TREE_DEFAULT_VALUE;
+
+ newMap.put(CmisOutputConfig.USERNAME_PARAM, username);
+ newMap.put(CmisOutputConfig.PASSWORD_PARAM, password);
+ newMap.put(CmisOutputConfig.PROTOCOL_PARAM, protocol);
+ newMap.put(CmisOutputConfig.SERVER_PARAM, server);
+ newMap.put(CmisOutputConfig.PORT_PARAM, port);
+ newMap.put(CmisOutputConfig.PATH_PARAM, path);
+ newMap.put(CmisOutputConfig.REPOSITORY_ID_PARAM, repositoryId);
+ newMap.put(CmisOutputConfig.BINDING_PARAM, binding);
+ newMap.put(CmisOutputConfig.CMIS_QUERY_PARAM, cmisQuery);
+ newMap.put(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM, createTimestampTree);
+ }
+
+ /**
+ * View configuration. This method is called in the body section of the
+ * connector's view configuration page. Its purpose is to present the
+ * connection information to the user. The coder can presume that the HTML
+ * that is output from this configuration will be within appropriate
+ * <html> and <body> tags.
+ *
+ * @param threadContext
+ * is the local thread context.
+ * @param out
+ * is the output to which any HTML should be sent.
+ * @param parameters
+ * are the configuration parameters, as they currently exist, for
+ * this connection being configured.
+ */
+ @Override
+ public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters)
+ throws ManifoldCFException, IOException {
+ Map<String, String> paramMap = new HashMap<String, String>();
+
+ // Fill in map from each tab
+ fillInServerConfigurationMap(paramMap, out, parameters);
+
+ outputResource(VIEW_CONFIG_FORWARD, out, locale, paramMap);
+ }
+
+ /**
+ *
+ * Output the configuration header section. This method is called in the head
+ * section of the connector's configuration page. Its purpose is to add the
+ * required tabs to the list, and to output any javascript methods that might
+ * be needed by the configuration editing HTML.
+ *
+ * @param threadContext
+ * is the local thread context.
+ * @param out
+ * is the output to which any HTML should be sent.
+ * @param parameters
+ * are the configuration parameters, as they currently exist, for
+ * this connection being configured.
+ * @param tabsArray
+ * is an array of tab names. Add to this array any tab names that are
+ * specific to the connector.
+ */
+ @Override
+ public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out, Locale locale,
+ ConfigParams parameters, List<String> tabsArray) throws ManifoldCFException, IOException {
+ // Add the Server tab
+ tabsArray.add(Messages.getString(locale, CMIS_SERVER_TAB_PROPERTY));
+ // Map the parameters
+ Map<String, String> paramMap = new HashMap<String, String>();
+
+ // Fill in the parameters from each tab
+ fillInServerConfigurationMap(paramMap, out, parameters);
+
+ // Output the Javascript - only one Velocity template for all tabs
+ outputResource(EDIT_CONFIG_HEADER_FORWARD, out, locale, paramMap);
+ }
+
+ @Override
+ public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, Locale locale,
+ ConfigParams parameters, String tabName) throws ManifoldCFException, IOException {
+
+ // Call the Velocity templates for each tab
+
+ // Server tab
+ Map<String, String> paramMap = new HashMap<String, String>();
+ // Set the tab name
+ paramMap.put("TabName", tabName);
+ // Fill in the parameters
+ fillInServerConfigurationMap(paramMap, out, parameters);
+ outputResource(EDIT_CONFIG_FORWARD_SERVER, out, locale, paramMap);
+
+ }
+
+ /**
+ * Process a configuration post. This method is called at the start of the
+ * connector's configuration page, whenever there is a possibility that form
+ * data for a connection has been posted. Its purpose is to gather form
+ * information and modify the configuration parameters accordingly. The name
+ * of the posted form is "editconnection".
+ *
+ * @param threadContext
+ * is the local thread context.
+ * @param variableContext
+ * is the set of variables available from the post, including binary
+ * file post information.
+ * @param parameters
+ * are the configuration parameters, as they currently exist, for
+ * this connection being configured.
+ * @return null if all is well, or a string error message if there is an error
+ * that should prevent saving of the connection (and cause a
+ * redirection to an error page).
+ */
+ @Override
+ public String processConfigurationPost(IThreadContext threadContext, IPostParameters variableContext,
+ ConfigParams parameters) throws ManifoldCFException {
+
+ String binding = variableContext.getParameter(CmisOutputConfig.BINDING_PARAM);
+ if (binding != null)
+ parameters.setParameter(CmisOutputConfig.BINDING_PARAM, binding);
+
+ String username = variableContext.getParameter(CmisOutputConfig.USERNAME_PARAM);
+ if (username != null)
+ parameters.setParameter(CmisOutputConfig.USERNAME_PARAM, username);
+
+ String password = variableContext.getParameter(CmisOutputConfig.PASSWORD_PARAM);
+ if (password != null)
+ parameters.setParameter(CmisOutputConfig.PASSWORD_PARAM, variableContext.mapKeyToPassword(password));
+
+ String protocol = variableContext.getParameter(CmisOutputConfig.PROTOCOL_PARAM);
+ if (protocol != null) {
+ parameters.setParameter(CmisOutputConfig.PROTOCOL_PARAM, protocol);
+ }
+
+ String server = variableContext.getParameter(CmisOutputConfig.SERVER_PARAM);
+ if (server != null && !StringUtils.contains(server, '/')) {
+ parameters.setParameter(CmisOutputConfig.SERVER_PARAM, server);
+ }
+
+ String port = variableContext.getParameter(CmisOutputConfig.PORT_PARAM);
+ if (port != null) {
+ try {
+ Integer.parseInt(port);
+ parameters.setParameter(CmisOutputConfig.PORT_PARAM, port);
+ } catch (NumberFormatException e) {
+
+ }
+ }
+
+ String path = variableContext.getParameter(CmisOutputConfig.PATH_PARAM);
+ if (path != null) {
+ parameters.setParameter(CmisOutputConfig.PATH_PARAM, path);
+ }
+
+ String cmisQuery = variableContext.getParameter(CmisOutputConfig.CMIS_QUERY_PARAM);
+ if (cmisQuery != null) {
+ parameters.setParameter(CmisOutputConfig.CMIS_QUERY_PARAM, cmisQuery);
+ }
+
+ String createTimestampTree = variableContext.getParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM);
+ if (createTimestampTree != null) {
+ parameters.setParameter(CmisOutputConfig.CREATE_TIMESTAMP_TREE_PARAM, createTimestampTree);
+ }
+
+ String repositoryId = variableContext.getParameter(CmisOutputConfig.REPOSITORY_ID_PARAM);
+ if (repositoryId != null) {
+ parameters.setParameter(CmisOutputConfig.REPOSITORY_ID_PARAM, repositoryId);
+ }
+
+ return null;
+ }
+
+ protected static void handleIOException(IOException e, String context)
+ throws ManifoldCFException, ServiceInterruption {
+ if (e instanceof InterruptedIOException) {
+ throw new ManifoldCFException(e.getMessage(), e, ManifoldCFException.INTERRUPTED);
+ } else {
+ Logging.connectors.warn("CMIS: IOException " + context + ": " + e.getMessage(), e);
+ throw new ManifoldCFException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Check if the target drop zone is a CMIS folder
+ *
+ * @return
+ */
+ private boolean isDropZoneFolder(String cmisQuery) {
+ boolean isDropZoneFolder = false;
+
+ // Get the drop zone folder
+ ItemIterable<QueryResult> dropZoneItemIterable = session.query(cmisQuery, false);
+ Iterator<QueryResult> dropZoneIterator = dropZoneItemIterable.iterator();
+ String baseTypeId = null;
+ while (dropZoneIterator.hasNext()) {
+ QueryResult dropZoneResult = (QueryResult) dropZoneIterator.next();
+
+ // check if it is a base folder content type
+ baseTypeId = dropZoneResult.getPropertyByQueryName(PropertyIds.BASE_TYPE_ID).getFirstValue().toString();
+ if (StringUtils.isNotEmpty(baseTypeId) && StringUtils.equals(baseTypeId, EnumBaseObjectTypeIds.CMIS_FOLDER.value())) {
+ String objectId = dropZoneResult.getPropertyValueById(PropertyIds.OBJECT_ID);
+ parentDropZoneFolder = (Folder) session.getObject(objectId);
+ isDropZoneFolder = true;
+ }
+ }
+ return isDropZoneFolder;
+ }
+
+ private boolean isSourceRepoCmisCompliant(RepositoryDocument document) {
+ Iterator<String> fields = document.getFields();
+ while (fields.hasNext()) {
+ String fieldName = (String) fields.next();
+ if (StringUtils.startsWith(fieldName, CMIS_PROPERTY_PREFIX)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int addOrReplaceDocumentWithException(String documentURI, VersionContext pipelineDescription,
+ RepositoryDocument document, String authorityNameString, IOutputAddActivity activities)
+ throws ManifoldCFException, ServiceInterruption, IOException {
+
+ getSession();
+
+ boolean isDropZoneFolder = isDropZoneFolder(cmisQuery);
+ long startTime = System.currentTimeMillis();
+ String resultDescription = StringUtils.EMPTY;
+ Folder leafParent = null;
+ String fileName = StringUtils.EMPTY;
+ InputStream inputStream = null;
+ ContentStream contentStream = null;
+ // properties
+ // (minimal set: name and object type id)
+ Map<String, Object> properties = new HashMap<String, Object>();
+ Long binaryLength = null;
+ String mimeType = StringUtils.EMPTY;
+ try {
+ if (isDropZoneFolder) {
+
+ // Creation of the new Repository Node
+ fileName = document.getFileName();
+ Date creationDate = document.getCreatedDate();
+ Date lastModificationDate = document.getModifiedDate();
+ String objectId = StringUtils.EMPTY;
+ mimeType = document.getMimeType();
+ binaryLength = document.getBinaryLength();
+
+ //check if the repository connector includes the content path
+ String primaryPath = StringUtils.EMPTY;
+ List<String> sourcePath = document.getSourcePath();
+ if(sourcePath != null && !sourcePath.isEmpty()) {
+ primaryPath = sourcePath.get(0);
+ }
+
+
+
+ //if the source is CMIS Repository Connector we override the objectId for synchronizing with removeDocument method
+ if(isSourceRepoCmisCompliant(document)) {
+ String[] cmisObjectIdArray = (String[]) document.getField(PropertyIds.OBJECT_ID);
+ if(cmisObjectIdArray!=null && cmisObjectIdArray.length>0) {
+ objectId = cmisObjectIdArray[0];
+ }
+
+ //Mapping all the CMIS properties ...
+ /*
+ Iterator<String> fields = document.getFields();
+ while (fields.hasNext()) {
+ String field = (String) fields.next();
+ if(!StringUtils.equals(field, "cm:lastThumbnailModification")
+ || !StringUtils.equals(field, "cmis:secondaryObjectTypeIds")) {
+ String[] valuesArray = (String[]) document.getField(field);
+ properties.put(field,valuesArray);
+ }
+ }
+ */
+ }
+
+ //Agnostic metadata
+ properties.put(PropertyIds.OBJECT_TYPE_ID, EnumBaseObjectTypeIds.CMIS_DOCUMENT.value());
+ properties.put(PropertyIds.NAME, fileName);
+ properties.put(PropertyIds.CREATION_DATE, creationDate);
+ properties.put(PropertyIds.LAST_MODIFICATION_DATE, lastModificationDate);
+
+ //check objectId
+ if(StringUtils.isNotEmpty(objectId)){
+ ObjectId objId = new ObjectIdImpl(objectId);
+ properties.put(PropertyIds.OBJECT_ID, objId);
+ }
+
+ // Content Stream
+ inputStream = document.getBinaryStream();
+ contentStream = new ContentStreamImpl(fileName, BigInteger.valueOf(binaryLength), mimeType,
+ inputStream);
+
+ // create a major version
+ leafParent = getOrCreateLeafParent(parentDropZoneFolder, creationDate, Boolean.valueOf(createTimestampTree), primaryPath);
+ leafParent.createDocument(properties, contentStream, VersioningState.NONE);
+ resultDescription = DOCUMENT_STATUS_ACCEPTED_DESC;
+ return DOCUMENT_STATUS_ACCEPTED;
+
+ } else {
+ resultDescription = DOCUMENT_STATUS_REJECTED_DESC;
+ return DOCUMENT_STATUS_REJECTED;
+ }
+
+ } catch (CmisContentAlreadyExistsException | CmisNameConstraintViolationException e) {
+
+ //updating the existing content
+ if(leafParent != null) {
+ String documentFullPath = leafParent.getPath() + CmisOutputConnectorUtils.SLASH + fileName;
+ String newFileName = fileName+System.currentTimeMillis();
+
+ Document currentContent = (Document) session.getObjectByPath(documentFullPath);
+ currentContent.updateProperties(properties);
+ contentStream = new ContentStreamImpl(newFileName, BigInteger.valueOf(binaryLength), mimeType, inputStream);
+ currentContent.setContentStream(contentStream, true);
+
+ Logging.connectors.warn(
+ "CMIS: Document already exists - Updating: " + documentFullPath);
+ }
+
+ resultDescription = DOCUMENT_STATUS_ACCEPTED_DESC;
+ return DOCUMENT_STATUS_ACCEPTED;
+
+ } catch (Exception e) {
+ resultDescription = DOCUMENT_STATUS_REJECTED_DESC;
+ throw new ManifoldCFException(e.getMessage(), e);
+
+ } finally {
+
+ if(inputStream != null) {
+ inputStream.close();
+ }
+
+ activities.recordActivity(startTime, ACTIVITY_INJECTION, document.getBinaryLength(), documentURI, resultDescription,
+ resultDescription);
+ }
+
+ }
+
+ /**
+ * Check and create the leaf folder dedicate to inject the content
+ * @param folder: this is the root folder where starts the tree
+ * @param creationDate: this is the creation date of the current content
+ * @param createTimestampTree: this is the flag checked in the ManifoldCF configuration panel
+ * @return the target folder created using the creationDate related to the injected content
+ */
+ private Folder getOrCreateLeafParent(Folder folder, Date creationDate, boolean createTimestampTree, String primaryPath) {
+ Folder leafParent = folder;
+ if (createTimestampTree) {
+ GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"), Locale.ROOT);
+ calendar.setTime(creationDate);
+ String year = String.valueOf(calendar.get(GregorianCalendar.YEAR));
+ String month = String.valueOf((calendar.get(GregorianCalendar.MONTH)+1));
+ String day = String.valueOf(calendar.get(GregorianCalendar.DAY_OF_MONTH));
+
+ //Check and create all the new folders
+ Folder yearFolder = createFolderIfNotExist(leafParent, year);
+ Folder monthFolder = createFolderIfNotExist(yearFolder, month);
+ Folder dayFolder = createFolderIfNotExist(monthFolder, day);
+
+ leafParent = dayFolder;
+
+ } else if(StringUtils.isNotEmpty(primaryPath)) {
+ String[] primaryPathArray = StringUtils.split(primaryPath, CmisOutputConnectorUtils.SLASH);
+ leafParent = folder;
+ for (int i = 0; i < primaryPathArray.length - 1; i++) {
+ String pathSegment = primaryPathArray[i];
+ Folder pathSegmentFolder = createFolderIfNotExist(leafParent, pathSegment);
+ leafParent = pathSegmentFolder;
+ }
+ }
+ return leafParent;
+ }
+
+ /**
+ * Create a new CMIS folder as a child node of leafParent
+ * @param leafParent
+ * @param folderName
+ * @return the current CMIS folder if exists otherwise it will return a new one
+ */
+ private Folder createFolderIfNotExist(Folder leafParent, String folderName) {
+ Folder folder = null;
+ try {
+ folder = (Folder) session.getObjectByPath(leafParent.getPath() + CmisOutputConnectorUtils.SLASH + folderName);
+ } catch (CmisObjectNotFoundException onfe) {
+ Map<String, Object> props = new HashMap<String, Object>();
+ props.put(PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
+ props.put(PropertyIds.NAME, folderName);
+ folder = leafParent.createFolder(props);
+
+ String folderId = folder.getId();
+ String folderPath = folder.getPath();
+ Logging.connectors.info(
+ "CMIS: Created a new folder - id: " + folderId +
+ " | Path: " + folderPath);
+ }
+ return folder;
+ }
+
+
+ /**
+ * Encoding process to retrieve the contentPath parameter from the documentURI.
+ * The contentPath parameter can be passed from any repository connector that is currently supporting the content migration capability.
+ * @param documentURI
+ * @return contentPath
+ * @throws URISyntaxException
+ * @throws UnsupportedEncodingException
+ */
+ private String getContentPath(String documentURI) throws URISyntaxException, UnsupportedEncodingException {
+ String contentPath = StringUtils.EMPTY;
+ String documentURIWithFixedEncoding = StringUtils.replace(documentURI, " ", "%20");
+ List<NameValuePair> params = URLEncodedUtils.parse(new URI(documentURIWithFixedEncoding), StandardCharsets.UTF_8);
+ Iterator<NameValuePair> paramsIterator = params.iterator();
+ while (paramsIterator.hasNext()) {
+ NameValuePair param = (NameValuePair) paramsIterator.next();
+ if(StringUtils.equals(CONTENT_PATH_PARAM, param.getName())){
+ contentPath = param.getValue();
+ }
+ }
+ return contentPath;
+ }
+
+ @Override
+ public void removeDocument(String documentURI, String outputDescription, IOutputRemoveActivity activities)
+ throws ManifoldCFException, ServiceInterruption {
+ getSession();
+ long startTime = System.currentTimeMillis();
+ String result = StringUtils.EMPTY;
+ boolean isDropZoneFolder = isDropZoneFolder(cmisQuery);
+
+ //append the prefix for the relative path in the target repo
+ try {
+ if(isDropZoneFolder
+ && parentDropZoneFolder != null
+ && StringUtils.isNotEmpty(documentURI)) {
+ String parentDropZonePath = parentDropZoneFolder.getPath();
+
+ String contentPath = getContentPath(documentURI);
+ String fullDocumentURIinTargetRepo = parentDropZonePath + contentPath;
+
+ if(session.existsPath(fullDocumentURIinTargetRepo)) {
+ session.deleteByPath(fullDocumentURIinTargetRepo);
+ result = DOCUMENT_DELETION_STATUS_ACCEPTED;
+ } else {
+ result = DOCUMENT_DELETION_STATUS_REJECTED;
+ }
+ } else {
+ result = DOCUMENT_DELETION_STATUS_REJECTED;
+ }
+ } catch (Exception e) {
+ result = DOCUMENT_DELETION_STATUS_REJECTED;
+ throw new ManifoldCFException(e.getMessage(), e);
+ } finally {
+ activities.recordActivity(startTime, ACTIVITY_DELETE, null, documentURI, null, result);
+ }
+ }
+
+
}
\ No newline at end of file
Modified: manifoldcf/trunk/connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/EmailConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/EmailConnector.java?rev=1837851&r1=1837850&r2=1837851&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/EmailConnector.java (original)
+++ manifoldcf/trunk/connectors/email/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/email/EmailConnector.java Sat Aug 11 09:41:00 2018
@@ -373,7 +373,7 @@ public class EmailConnector extends org.
}
if (comparisonTerm != null) {
- SimpleDateFormat date = new SimpleDateFormat(EmailConfig.EMAIL_FILTERING_DATE_FORMAT);
+ SimpleDateFormat date = new SimpleDateFormat(EmailConfig.EMAIL_FILTERING_DATE_FORMAT, Locale.ROOT);
try {
searchClause = new ReceivedDateTerm(comparisonTerm, date.parse(findParameterValue));
} catch (ParseException e) {