Author: kwright
Date: Sat Sep 13 12:40:13 2014
New Revision: 1624731

URL: http://svn.apache.org/r1624731
Log:
Rework the Livelink connector.  Part of CONNECTORS-977.

Modified:
    
manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java

Modified: 
manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java
URL: 
http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java?rev=1624731&r1=1624730&r2=1624731&view=diff
==============================================================================
--- 
manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java
 (original)
+++ 
manifoldcf/trunk/connectors/livelink/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/livelink/LivelinkConnector.java
 Sat Sep 13 12:40:13 2014
@@ -96,11 +96,6 @@ public class LivelinkConnector extends o
   /** Deny access token for default authority */
   private final static String defaultAuthorityDenyToken = GLOBAL_DENY_TOKEN;
 
-  // Livelink does not have "deny" permissions, and there is no such thing as 
a document with no tokens, so it is safe to not have a local "deny" token.
-  // However, people feel that a suspenders-and-belt approach is called for, 
so this restriction has been added.
-  // Livelink tokens are numbers, "SYSTEM", or "GUEST", so they can't collide 
with the standard form.
-  private static final String denyToken = "DEAD_AUTHORITY";
-
   // A couple of very important points.
   // First, the canonical document identifier has the following form:
   // <D|F>[<volume_id>:]<object_id>
@@ -1086,31 +1081,25 @@ public class LivelinkConnector extends o
     return "";
   }
 
-
-  /** Get document versions given an array of document identifiers.
-  * This method is called for EVERY document that is considered. It is
-  * therefore important to perform as little work as possible here.
-  *@param documentIdentifiers is the array of local document identifiers, as 
understood by this connector.
-  *@param oldVersions is the corresponding array of version strings that have 
been saved for the document identifiers.
-  *   A null value indicates that this is a first-time fetch, while an empty 
string indicates that the previous document
-  *   had an empty version string.
-  *@param activities is the interface this method should use to perform 
whatever framework actions are desired.
-  *@param spec is the current document specification for the current job.  If 
there is a dependency on this
-  * specification, then the version string should include the pertinent data, 
so that reingestion will occur
-  * when the specification changes.  This is primarily useful for metadata.
+  /** Process a set of documents.
+  * This is the method that should cause each document to be fetched, 
processed, and the results either added
+  * to the queue of documents for the current job, and/or entered into the 
incremental ingestion manager.
+  * The document specification allows this class to filter what is done based 
on the job.
+  * The connector will be connected before this method can be called.
+  *@param documentIdentifiers is the set of document identifiers to process.
+  *@param statuses are the currently-stored document versions for each 
document in the set of document identifiers
+  * passed in above.
+  *@param activities is the interface this method should use to queue up new 
document references
+  * and ingest documents.
   *@param jobMode is an integer describing how the job is being run, whether 
continuous or once-only.
   *@param usesDefaultAuthority will be true only if the authority in use for 
these documents is the default one.
-  *@return the corresponding version strings, with null in the places where 
the document no longer exists.
-  * Empty version strings indicate that there is no versioning ability for the 
corresponding document, and the document
-  * will always be processed.
   */
   @Override
-  public String[] getDocumentVersions(String[] documentIdentifiers, String[] 
oldVersions, IVersionActivity activities,
-    DocumentSpecification spec, int jobMode, boolean usesDefaultAuthority)
+  public void processDocuments(String[] documentIdentifiers, IExistingVersions 
statuses, Specification spec,
+    IProcessActivity activities, int jobMode, boolean usesDefaultAuthority)
     throws ManifoldCFException, ServiceInterruption
   {
-    getSession();
-
+    
     // Initialize a "livelink context", to minimize the number of objects we 
have to fetch
     LivelinkContext llc = new LivelinkContext();
     
@@ -1189,22 +1178,23 @@ public class LivelinkConnector extends o
 
     // Prepare the specified metadata
     StringBuilder metadataString = null;
+    String[] specifiedMetadataAttributes = null;
     CategoryPathAccumulator catAccum = null;
     if (!includeAllMetadata)
     {
       metadataString = new StringBuilder();
       // Put into an array
-      String[] sortArray = new String[holder.size()];
+      specifiedMetadataAttributes = new String[holder.size()];
       i = 0;
       for (String attrName : holder)
       {
-        sortArray[i++] = attrName;
+        specifiedMetadataAttributes[i++] = attrName;
       }
 
       // Sort!
-      java.util.Arrays.sort(sortArray);
+      java.util.Arrays.sort(specifiedMetadataAttributes);
       // Build the metadata string piece now
-      packList(metadataString,sortArray,'+');
+      packList(metadataString,specifiedMetadataAttributes,'+');
     }
     else
       catAccum = new CategoryPathAccumulator(llc);
@@ -1215,23 +1205,24 @@ public class LivelinkConnector extends o
     if (pathAttributeName != null)
       
pathNameAttributeVersion.append("=").append(pathAttributeName).append(":").append(pathSeparator).append(":").append(matchMap);
 
-    // The version string includes the following:
-    // 1) The modify date for the document
-    // 2) The rights for the document, ordered (which can change without 
changing the ModifyDate field)
-    // 3) The requested metadata fields (category and attribute, ordered) for 
the document
-    //
-    // The document identifiers are object id's.
+    // Initialize the table of catid's.
+    // Keeping this around will allow us to benefit from batching of documents.
+    MetadataDescription desc = new MetadataDescription(llc);
+
+    // Build the node/path cache
+    SystemMetadataDescription sDesc = new SystemMetadataDescription(llc,spec);
 
-    String[] rval = new String[documentIdentifiers.length];
-    i = 0;
-    while (i < documentIdentifiers.length)
+    // Since the identifier indicates it is a directory, then queue up all the 
current children which pass the filter.
+    String filterString = buildFilterString(spec);
+
+    for (String documentIdentifier : documentIdentifiers)
     {
       // Since each livelink access is time-consuming, be sure that we abort 
if the job has gone inactive
       activities.checkJobStillActive();
 
       // Read the document or folder metadata, which includes the ModifyDate
-      String docID = documentIdentifiers[i];
-
+      String docID = documentIdentifier;
+      
       boolean isFolder = docID.startsWith("F");
 
       int colonPos = docID.indexOf(":",1);
@@ -1250,7 +1241,7 @@ public class LivelinkConnector extends o
         vol = new Integer(docID.substring(1,colonPos)).intValue();
       }
 
-      rval[i] = null;
+      getSession();
       ObjectInformation value = llc.getObjectInformation(vol,objID);
       if (value.exists())
       {
@@ -1265,88 +1256,191 @@ public class LivelinkConnector extends o
           {
             // We were able to get rights, so object still exists.
 
-            // I rearranged this on 11/7/2006 so that it would be more 
parseable, since
-            // we want to pull the transient information out of the version 
string where
-            // possible (so there is no mismatch between version checking and 
ingestion).
-
-            StringBuilder sb = new StringBuilder();
-
-            // On 1/17/2008 I changed the version generation code to NOT 
include metadata, view info, etc. for folders, since
-            // folders make absolutely no use of this info.
-            if (!isFolder)
+            // Changed folder versioning for MCF 2.0
+            if (isFolder)
+            {
+              // === Livelink folder ===
+              // I'm still not sure if Livelink folder modified dates are 
one-level or hierarchical.
+              // The code below assumes one-level only, so we always scan 
folders and there's no versioning
+              if (Logging.connectors.isDebugEnabled())
+                Logging.connectors.debug("Livelink: Processing folder 
"+Integer.toString(vol)+":"+Integer.toString(objID));
+
+              int sanityRetryCount = FAILURE_RETRY_COUNT;
+              while (true)
+              {
+                ListObjectsThread t = new 
ListObjectsThread(vol,objID,filterString);
+                try
+                {
+                  t.start();
+                  LLValue childrenDocs;
+                  try
+                  {
+                    childrenDocs = t.finishUp();
+                  }
+                  catch (ManifoldCFException e)
+                  {
+                    sanityRetryCount = assessRetry(sanityRetryCount,e);
+                    continue;
+                  }
+
+                  int size = 0;
+                  
+                  if (childrenDocs.isRecord())
+                    size = 1;
+                  if (childrenDocs.isTable())
+                    size = childrenDocs.size();
+
+                  // System.out.println("Total child count = 
"+Integer.toString(size));
+                  // Do the scan
+                  for (int j = 0; j < size; j++)
+                  {
+                    int childID = childrenDocs.toInteger(j, "ID");
+
+                    if (Logging.connectors.isDebugEnabled())
+                      Logging.connectors.debug("Livelink: Found a child of 
folder "+Integer.toString(vol)+":"+Integer.toString(objID)+" : 
ID="+Integer.toString(childID));
+
+                    int subtype = childrenDocs.toInteger(j, "SubType");
+                    boolean childIsFolder = (subtype == 
LAPI_DOCUMENTS.FOLDERSUBTYPE || subtype == LAPI_DOCUMENTS.PROJECTSUBTYPE ||
+                      subtype == LAPI_DOCUMENTS.COMPOUNDDOCUMENTSUBTYPE);
+
+                    // If it's a folder, we just let it through for now
+                    if (!childIsFolder && 
checkInclude(childrenDocs.toString(j,"Name") + "." + 
childrenDocs.toString(j,"FileType"), spec) == false)
+                    {
+                      if (Logging.connectors.isDebugEnabled())
+                        Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" was excluded by inclusion criteria");
+                      continue;
+                    }
+
+                    if (childIsFolder)
+                    {
+                      if (Logging.connectors.isDebugEnabled())
+                        Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" is a folder, project, or compound document; 
adding a reference");
+                      if (subtype == LAPI_DOCUMENTS.PROJECTSUBTYPE)
+                      {
+                        // If we pick up a project object, we need to describe 
the volume object (which
+                        // will be the root of all documents beneath)
+                        activities.addDocumentReference("F"+new 
Integer(childID).toString()+":"+new Integer(-childID).toString());
+                      }
+                      else
+                        activities.addDocumentReference("F"+new 
Integer(vol).toString()+":"+new Integer(childID).toString());
+                    }
+                    else
+                    {
+                      if (Logging.connectors.isDebugEnabled())
+                        Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" is a simple document; adding a reference");
+
+                      activities.addDocumentReference("D"+new 
Integer(vol).toString()+":"+new Integer(childID).toString());
+                    }
+
+                  }
+                  break;
+                }
+                catch (InterruptedException e)
+                {
+                  t.interrupt();
+                  throw new ManifoldCFException("Interrupted: 
"+e.getMessage(),e,ManifoldCFException.INTERRUPTED);
+                }
+                catch (RuntimeException e)
+                {
+                  sanityRetryCount = 
handleLivelinkRuntimeException(e,sanityRetryCount,true);
+                  continue;
+                }
+              }
+              if (Logging.connectors.isDebugEnabled())
+                Logging.connectors.debug("Livelink: Done processing folder 
"+Integer.toString(vol)+":"+Integer.toString(objID));
+            }
+            else
             {
+              // === Livelink document ===
+              
+              // The version string includes the following:
+              // 1) The modify date for the document
+              // 2) The rights for the document, ordered (which can change 
without changing the ModifyDate field)
+              // 3) The requested metadata fields (category and attribute, 
ordered) for the document
+              //
+              // The document identifiers are object id's.
+      
+              StringBuilder sb = new StringBuilder();
+
+              String[] categoryPaths;
               if (includeAllMetadata)
               {
                 // Find all the metadata associated with this object, and then
                 // find the set of category pathnames that correspond to it.
                 int[] catIDs = getObjectCategoryIDs(vol,objID);
-                String[] categoryPaths = 
catAccum.getCategoryPathsAttributeNames(catIDs);
+                categoryPaths = 
catAccum.getCategoryPathsAttributeNames(catIDs);
                 // Sort!
                 java.util.Arrays.sort(categoryPaths);
                 // Build the metadata string piece now
                 packList(sb,categoryPaths,'+');
               }
               else
+              {
+                categoryPaths = specifiedMetadataAttributes;
                 sb.append(metadataString);
-            }
-
-            String[] actualAcls;
-            String denyAcl;
-            if (acls != null && acls.length == 0)
-            {
-              // No forced acls.  Read the actual acls from livelink, as a set 
of rights.
-              // We need also to add in support for the special rights 
objects.  These are:
-              // -1: RIGHT_WORLD
-              // -2: RIGHT_SYSTEM
-              // -3: RIGHT_OWNER
-              // -4: RIGHT_GROUP
-              //
-              // RIGHT_WORLD means guest access.
-              // RIGHT_SYSTEM is "Public Access".
-              // RIGHT_OWNER is access by the owner of the object.
-              // RIGHT_GROUP is access by a member of the base group 
containing the owner
-              //
-              // These objects are returned by the GetObjectRights() call made 
above, and NOT
-              // returned by LLUser.ListObjects().  We have to figure out how 
to map these to
-              // things that are
-              // the equivalent of acls.
-
-              actualAcls = lookupTokens(rights, value);
-              java.util.Arrays.sort(actualAcls);
-              // If security is on, no deny acl is needed for the local 
authority, since the repository does not support "deny".  But this was added
-              // to be really really really sure.
-              denyAcl = denyToken;
+              }
+              
+              String[] actualAcls;
+              String[] denyAcls;
+              
+              String denyAcl;
+              if (acls != null && acls.length == 0)
+              {
+                // No forced acls.  Read the actual acls from livelink, as a 
set of rights.
+                // We need also to add in support for the special rights 
objects.  These are:
+                // -1: RIGHT_WORLD
+                // -2: RIGHT_SYSTEM
+                // -3: RIGHT_OWNER
+                // -4: RIGHT_GROUP
+                //
+                // RIGHT_WORLD means guest access.
+                // RIGHT_SYSTEM is "Public Access".
+                // RIGHT_OWNER is access by the owner of the object.
+                // RIGHT_GROUP is access by a member of the base group 
containing the owner
+                //
+                // These objects are returned by the GetObjectRights() call 
made above, and NOT
+                // returned by LLUser.ListObjects().  We have to figure out 
how to map these to
+                // things that are
+                // the equivalent of acls.
+
+                actualAcls = lookupTokens(rights, value);
+                java.util.Arrays.sort(actualAcls);
+                // If security is on, no deny acl is needed for the local 
authority, since the repository does not support "deny".  But this was added
+                // to be really really really sure.
+                denyAcl = defaultAuthorityDenyToken;
 
-            }
-            else if (acls != null && acls.length > 0)
-            {
-              // Forced acls
-              actualAcls = acls;
-              denyAcl = defaultAuthorityDenyToken;
-            }
-            else
-            {
-              // Security is OFF
-              actualAcls = acls;
-              denyAcl = null;
-            }
+              }
+              else if (acls != null && acls.length > 0)
+              {
+                // Forced acls
+                actualAcls = acls;
+                denyAcl = defaultAuthorityDenyToken;
+              }
+              else
+              {
+                // Security is OFF
+                actualAcls = acls;
+                denyAcl = null;
+              }
 
-            // Now encode the acls.  If null, we write a special value.
-            if (actualAcls == null)
-              sb.append('-');
-            else
-            {
-              sb.append('+');
-              packList(sb,actualAcls,'+');
-              // This was added on 4/21/2008 to support forced acls working 
with the global default authority.
-              pack(sb,denyAcl,'+');
-            }
+              // Now encode the acls.  If null, we write a special value.
+              if (actualAcls == null)
+              {
+                sb.append('-');
+                denyAcls = null;
+              }
+              else
+              {
+                sb.append('+');
+                packList(sb,actualAcls,'+');
+                // This was added on 4/21/2008 to support forced acls working 
with the global default authority.
+                pack(sb,denyAcl,'+');
+                denyAcls = new String[]{denyAcl};
+              }
 
-            // The date does not need to be parseable
-            sb.append(dt.toString());
+              // The date does not need to be parseable
+              sb.append(dt.toString());
 
-            if (!isFolder)
-            {
               // PathNameAttributeVersion comes completely from the spec, so 
we don't
               // have to worry about it changing.  No need, therefore, to 
parse it during
               // processDocuments.
@@ -1354,33 +1448,60 @@ public class LivelinkConnector extends o
 
               // Tack on ingestCgiPath, to insulate us against changes to the 
repository connection setup.  Added 9/7/07.
               sb.append("_").append(viewBasePath);
-            }
 
-            rval[i] = sb.toString();
-            if (Logging.connectors.isDebugEnabled())
-              Logging.connectors.debug("Livelink: Successfully calculated 
version string for object "+Integer.toString(vol)+":"+Integer.toString(objID)+" 
: '"+rval[i]+"'");
+              String versionString = sb.toString();
+              if (Logging.connectors.isDebugEnabled())
+                Logging.connectors.debug("Livelink: Successfully calculated 
version string for document 
"+Integer.toString(vol)+":"+Integer.toString(objID)+" : '"+versionString+"'");
+              
+              if 
(activities.checkDocumentNeedsReindexing(documentIdentifier,versionString))
+              {
+                // Index the document
+                if (Logging.connectors.isDebugEnabled())
+                  Logging.connectors.debug("Livelink: Processing document 
"+Integer.toString(vol)+":"+Integer.toString(objID));
+                if (checkIngest(llc,objID,spec))
+                {
+                  if (Logging.connectors.isDebugEnabled())
+                    Logging.connectors.debug("Livelink: Decided to ingest 
document "+Integer.toString(vol)+":"+Integer.toString(objID));
+
+                  // Grab the access tokens for this file from the version 
string, inside ingest method.
+                  
ingestFromLiveLink(llc,documentIdentifier,versionString,actualAcls,denyAcls,categoryPaths,activities,desc,sDesc);
+                }
+                else
+                {
+                  if (Logging.connectors.isDebugEnabled())
+                    Logging.connectors.debug("Livelink: Decided not to ingest 
document "+Integer.toString(vol)+":"+Integer.toString(objID)+" - Did not match 
ingestion criteria");
+                  activities.noDocument(documentIdentifier,versionString);
+                }
+                if (Logging.connectors.isDebugEnabled())
+                  Logging.connectors.debug("Livelink: Done processing document 
"+Integer.toString(vol)+":"+Integer.toString(objID));
+              }
+            }
           }
           else
           {
             if (Logging.connectors.isDebugEnabled())
               Logging.connectors.debug("Livelink: Could not get rights for 
object "+Integer.toString(vol)+":"+Integer.toString(objID)+" - deleting");
+            activities.deleteDocument(documentIdentifier);
+            continue;
           }
         }
         else
         {
           if (Logging.connectors.isDebugEnabled())
             Logging.connectors.debug("Livelink: Crawl user cannot see contents 
of object "+Integer.toString(vol)+":"+Integer.toString(objID)+" - deleting");
+          activities.deleteDocument(documentIdentifier);
+          continue;
         }
       }
       else
       {
         if (Logging.connectors.isDebugEnabled())
           Logging.connectors.debug("Livelink: Object 
"+Integer.toString(vol)+":"+Integer.toString(objID)+" has no information - 
deleting");
+        activities.deleteDocument(documentIdentifier);
+        continue;
       }
-      i++;
 
     }
-    return rval;
   }
 
   protected class ListObjectsThread extends Thread
@@ -1438,186 +1559,6 @@ public class LivelinkConnector extends o
     }
   }
 
-  /** Process a set of documents.
-  * This is the method that should cause each document to be fetched, 
processed, and the results either added
-  * to the queue of documents for the current job, and/or entered into the 
incremental ingestion manager.
-  * The document specification allows this class to filter what is done based 
on the job.
-  *@param documentIdentifiers is the set of document identifiers to process.
-  *@param activities is the interface this method should use to queue up new 
document references
-  * and ingest documents.
-  *@param spec is the document specification.
-  *@param scanOnly is an array corresponding to the document identifiers.  It 
is set to true to indicate when the processing
-  * should only find other references, and should not actually call the 
ingestion methods.
-  */
-  @Override
-  public void processDocuments(String[] documentIdentifiers, String[] 
versions, IProcessActivity activities, DocumentSpecification spec, boolean[] 
scanOnly)
-    throws ManifoldCFException, ServiceInterruption
-  {
-    getSession();
-
-    // Initialize livelink context
-    LivelinkContext llc = new LivelinkContext();
-    
-    // First, initialize the table of catid's.
-    // Keeping this around will allow us to benefit from batching of documents.
-    MetadataDescription desc = new MetadataDescription(llc);
-
-    // Build the node/path cache
-    SystemMetadataDescription sDesc = new SystemMetadataDescription(llc,spec);
-
-    int i = 0;
-    while (i < documentIdentifiers.length)
-    {
-      // Since each livelink access is time-consuming, be sure that we abort 
if the job has gone inactive
-      activities.checkJobStillActive();
-      
-      String documentIdentifier = documentIdentifiers[i];
-      String version = versions[i];
-      
-      boolean doScanOnly = scanOnly[i];
-
-      boolean isFolder = documentIdentifier.startsWith("F");
-      int colonPosition = documentIdentifier.indexOf(":",1);
-      int vol;
-      int objID;
-      if (colonPosition == -1)
-      {
-        vol = LLENTWK_VOL;
-        objID = new Integer(documentIdentifier.substring(1)).intValue();
-      }
-      else
-      {
-        vol = new 
Integer(documentIdentifier.substring(1,colonPosition)).intValue();
-        objID = new 
Integer(documentIdentifier.substring(colonPosition+1)).intValue();
-      }
-
-      if (isFolder)
-      {
-        // We don't know if LL will let us version folders properly, so ALWAYS 
process folders.
-        if (Logging.connectors.isDebugEnabled())
-          Logging.connectors.debug("Livelink: Processing folder 
"+Integer.toString(vol)+":"+Integer.toString(objID));
-
-        // Since the identifier indicates it is a directory, then queue up all 
the current children which pass the filter.
-        String filterString = buildFilterString(spec);
-
-        int sanityRetryCount = FAILURE_RETRY_COUNT;
-        while (true)
-        {
-          ListObjectsThread t = new ListObjectsThread(vol,objID,filterString);
-          try
-          {
-            t.start();
-            LLValue childrenDocs;
-            try
-            {
-              childrenDocs = t.finishUp();
-            }
-            catch (ManifoldCFException e)
-            {
-              sanityRetryCount = assessRetry(sanityRetryCount,e);
-              continue;
-            }
-
-            int size = 0;
-            
-            if (childrenDocs.isRecord())
-              size = 1;
-            if (childrenDocs.isTable())
-              size = childrenDocs.size();
-
-            // System.out.println("Total child count = 
"+Integer.toString(size));
-            // Do the scan
-            int j = 0;
-            while (j < size)
-            {
-              int childID = childrenDocs.toInteger(j, "ID");
-
-              if (Logging.connectors.isDebugEnabled())
-                Logging.connectors.debug("Livelink: Found a child of folder 
"+Integer.toString(vol)+":"+Integer.toString(objID)+" : 
ID="+Integer.toString(childID));
-
-              int subtype = childrenDocs.toInteger(j, "SubType");
-              boolean childIsFolder = (subtype == LAPI_DOCUMENTS.FOLDERSUBTYPE 
|| subtype == LAPI_DOCUMENTS.PROJECTSUBTYPE ||
-                subtype == LAPI_DOCUMENTS.COMPOUNDDOCUMENTSUBTYPE);
-
-              // If it's a folder, we just let it through for now
-              if (!childIsFolder && 
checkInclude(childrenDocs.toString(j,"Name") + "." + 
childrenDocs.toString(j,"FileType"), spec) == false)
-              {
-                if (Logging.connectors.isDebugEnabled())
-                  Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" was excluded by inclusion criteria");
-                j++;
-                continue;
-              }
-
-              if (childIsFolder)
-              {
-                if (Logging.connectors.isDebugEnabled())
-                  Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" is a folder, project, or compound document; 
adding a reference");
-                if (subtype == LAPI_DOCUMENTS.PROJECTSUBTYPE)
-                {
-                  // If we pick up a project object, we need to describe the 
volume object (which
-                  // will be the root of all documents beneath)
-                  activities.addDocumentReference("F"+new 
Integer(childID).toString()+":"+new Integer(-childID).toString());
-                }
-                else
-                  activities.addDocumentReference("F"+new 
Integer(vol).toString()+":"+new Integer(childID).toString());
-              }
-              else
-              {
-                if (Logging.connectors.isDebugEnabled())
-                  Logging.connectors.debug("Livelink: Child identifier 
"+Integer.toString(childID)+" is a simple document; adding a reference");
-
-                activities.addDocumentReference("D"+new 
Integer(vol).toString()+":"+new Integer(childID).toString());
-              }
-
-              j++;
-            }
-            break;
-          }
-          catch (InterruptedException e)
-          {
-            t.interrupt();
-            throw new ManifoldCFException("Interrupted: 
"+e.getMessage(),e,ManifoldCFException.INTERRUPTED);
-          }
-          catch (RuntimeException e)
-          {
-            sanityRetryCount = 
handleLivelinkRuntimeException(e,sanityRetryCount,true);
-            continue;
-          }
-        }
-        if (Logging.connectors.isDebugEnabled())
-          Logging.connectors.debug("Livelink: Done processing folder 
"+Integer.toString(vol)+":"+Integer.toString(objID));
-      }
-      else
-      {
-        // It's a known file, and we've already checked whether it's allowed 
or not (except any
-        // checks based on the file data)
-
-        if (doScanOnly == false)
-        {
-          if (Logging.connectors.isDebugEnabled())
-            Logging.connectors.debug("Livelink: Processing document 
"+Integer.toString(vol)+":"+Integer.toString(objID));
-          if (checkIngest(llc,objID,spec))
-          {
-            if (Logging.connectors.isDebugEnabled())
-              Logging.connectors.debug("Livelink: Decided to ingest document 
"+Integer.toString(vol)+":"+Integer.toString(objID));
-
-            // Grab the access tokens for this file from the version string, 
inside ingest method.
-            
ingestFromLiveLink(llc,documentIdentifiers[i],version,activities,desc,sDesc);
-          }
-          else
-          {
-            if (Logging.connectors.isDebugEnabled())
-              Logging.connectors.debug("Livelink: Decided not to ingest 
document "+Integer.toString(vol)+":"+Integer.toString(objID)+" - Did not match 
ingestion criteria");
-
-          }
-          if (Logging.connectors.isDebugEnabled())
-            Logging.connectors.debug("Livelink: Done processing document 
"+Integer.toString(vol)+":"+Integer.toString(objID));
-        }
-      }
-      i++;
-    }
-  }
-
   /** Get the maximum number of documents to amalgamate together into one 
batch, for this connector.
   *@return the maximum number. 0 indicates "unlimited".
   */
@@ -4267,6 +4208,8 @@ public class LivelinkConnector extends o
   */
   protected void ingestFromLiveLink(LivelinkContext llc,
     String documentIdentifier, String version,
+    String[] actualAcls, String[] denyAcls,
+    String[] categoryPaths,
     IProcessActivity activities,
     MetadataDescription desc, SystemMetadataDescription sDesc)
     throws ManifoldCFException, ServiceInterruption
@@ -4371,16 +4314,10 @@ public class LivelinkConnector extends o
             // Iterate over the metadata items.  These are organized by 
category
             // for speed of lookup.
 
-            // Unpack version string
-            int startPos = 0;
-
-            // Metadata items first
-            ArrayList metadataItems = new ArrayList();
-            startPos = unpackList(metadataItems,version,startPos,'+');
-            Iterator catIter = desc.getItems(metadataItems);
+            Iterator<MetadataItem> catIter = desc.getItems(categoryPaths);
             while (catIter.hasNext())
             {
-              MetadataItem item = (MetadataItem)catIter.next();
+              MetadataItem item = catIter.next();
               MetadataPathItem pathItem = item.getPathItem();
               if (pathItem != null)
               {
@@ -4390,10 +4327,10 @@ public class LivelinkConnector extends o
                 if (catVersion != null)
                 {
                   // Go through attributes now
-                  Iterator attrIter = item.getAttributeNames();
+                  Iterator<String> attrIter = item.getAttributeNames();
                   while (attrIter.hasNext())
                   {
-                    String attrName = (String)attrIter.next();
+                    String attrName = attrIter.next();
                     // Create a unique metadata name
                     String metadataName = pathItem.getCatName()+":"+attrName;
                     // Fetch the metadata and stuff it into the RepositoryData 
structure
@@ -4408,32 +4345,8 @@ public class LivelinkConnector extends o
               }
             }
 
-            // Unpack acls (conditionally)
-            if (startPos < version.length())
-            {
-              char x = version.charAt(startPos++);
-              if (x == '+')
-              {
-                ArrayList acls = new ArrayList();
-                startPos = unpackList(acls,version,startPos,'+');
-                // Turn into acls and add into description
-                String[] aclArray = new String[acls.size()];
-                int j = 0;
-                while (j < aclArray.length)
-                {
-                  aclArray[j] = (String)acls.get(j);
-                  j++;
-                }
-
-                StringBuilder denyBuffer = new StringBuilder();
-                startPos = unpack(denyBuffer,version,startPos,'+');
-                String denyAcl = denyBuffer.toString();
-                String[] denyAclArray = new String[1];
-                denyAclArray[0] = denyAcl;
-                
-                
rd.setSecurity(RepositoryDocument.SECURITY_TYPE_DOCUMENT,aclArray,denyAclArray);
-              }
-            }
+            if (actualAcls != null && denyAcls != null)
+              
rd.setSecurity(RepositoryDocument.SECURITY_TYPE_DOCUMENT,actualAcls,denyAcls);
 
             // Add the path metadata item into the mix, if enabled
             String pathAttributeName = sDesc.getPathAttributeName();
@@ -6708,7 +6621,7 @@ public class LivelinkConnector extends o
   *@param spec is the specification string.
   *@return the correct part of the filter string.  Empty string is returned if 
there is no filtering.
   */
-  protected static String buildFilterString(DocumentSpecification spec)
+  protected static String buildFilterString(Specification spec)
   {
     StringBuilder rval = new StringBuilder();
 
@@ -6758,7 +6671,7 @@ public class LivelinkConnector extends o
   *@param spec is the document specification.
   *@return the acls.
   */
-  protected static String[] getAcls(DocumentSpecification spec)
+  protected static String[] getAcls(Specification spec)
   {
     HashMap map = new HashMap();
     int i = 0;
@@ -6798,7 +6711,7 @@ public class LivelinkConnector extends o
   *@param documentSpecification is the specification.
   *@return true if it should be included.
   */
-  protected static boolean checkInclude(String filename, DocumentSpecification 
documentSpecification)
+  protected static boolean checkInclude(String filename, Specification 
documentSpecification)
     throws ManifoldCFException
   {
     // Scan includes to insure we match
@@ -6842,7 +6755,7 @@ public class LivelinkConnector extends o
   *@param objID is the file ID.
   *@param documentSpecification is the specification.
   */
-  protected boolean checkIngest(LivelinkContext llc, int objID, 
DocumentSpecification documentSpecification)
+  protected boolean checkIngest(LivelinkContext llc, int objID, Specification 
documentSpecification)
     throws ManifoldCFException
   {
     // Since the only exclusions at this point are not based on file contents, 
this is a no-op.
@@ -6988,7 +6901,7 @@ public class LivelinkConnector extends o
   protected static class MetadataItem
   {
     protected MetadataPathItem pathItem;
-    protected Map attributeNames = new HashMap();
+    protected Set<String> attributeNames = new HashSet<String>();
 
     /** Constructor.
     */
@@ -7001,7 +6914,7 @@ public class LivelinkConnector extends o
     */
     public void addAttribute(String attributeName)
     {
-      attributeNames.put(attributeName,attributeName);
+      attributeNames.add(attributeName);
     }
 
     /** Get the path object.
@@ -7015,9 +6928,9 @@ public class LivelinkConnector extends o
     /** Get an iterator over the attribute names.
     *@return the iterator.
     */
-    public Iterator getAttributeNames()
+    public Iterator<String> getAttributeNames()
     {
-      return attributeNames.keySet().iterator();
+      return attributeNames.iterator();
     }
 
   }
@@ -7043,7 +6956,7 @@ public class LivelinkConnector extends o
     protected MatchMap matchMap = new MatchMap();
 
     /** Constructor */
-    public SystemMetadataDescription(LivelinkContext llc, 
DocumentSpecification spec)
+    public SystemMetadataDescription(LivelinkContext llc, Specification spec)
       throws ManifoldCFException
     {
       this.llc = llc;
@@ -7172,7 +7085,7 @@ public class LivelinkConnector extends o
     protected final LivelinkContext llc;
     
     // This is a map of category name to category ID and attributes
-    protected Map categoryMap = new HashMap();
+    protected final Map<String,MetadataPathItem> categoryMap = new 
HashMap<String,MetadataPathItem>();
 
     /** Constructor.
     */
@@ -7184,21 +7097,19 @@ public class LivelinkConnector extends o
     /** Iterate over the metadata items represented by the specified chunk of 
version string.
     *@return an iterator over MetadataItem objects.
     */
-    public Iterator getItems(ArrayList metadataItems)
+    public Iterator<MetadataItem> getItems(String[] metadataItems)
       throws ManifoldCFException, ServiceInterruption
     {
       // This is the map that will be iterated over for a return value.
       // It gets built out of (hopefully cached) data from categoryMap.
-      HashMap newMap = new HashMap();
+      Map<String,MetadataItem> newMap = new HashMap<String,MetadataItem>();
 
       // Start at root
       ObjectInformation rootValue = null;
 
       // Walk through string and process each metadata element in turn.
-      int i = 0;
-      while (i < metadataItems.size())
+      for (String metadataSpec : metadataItems)
       {
-        String metadataSpec = (String)metadataItems.get(i++);
         StringBuilder categoryBuffer = new StringBuilder();
         StringBuilder attributeBuffer = new StringBuilder();
         unpackCategoryAttribute(categoryBuffer,attributeBuffer,metadataSpec);
@@ -7206,12 +7117,12 @@ public class LivelinkConnector extends o
         String attributeName = attributeBuffer.toString();
 
         // If there's already an entry for this category in the return map, 
use it
-        MetadataItem mi = (MetadataItem)newMap.get(category);
+        MetadataItem mi = newMap.get(category);
         if (mi == null)
         {
           // Now, look up the node information
           // Convert category to cat id.
-          MetadataPathItem item = (MetadataPathItem)categoryMap.get(category);
+          MetadataPathItem item = categoryMap.get(category);
           if (item == null)
           {
             RootValue rv = new RootValue(llc,category);


Reply via email to