| /** |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.manifoldcf.crawler.connectors.sharedrive; |
| |
| import jcifs.ACE; |
| import jcifs.smb.NtlmPasswordAuthenticator; |
| import jcifs.smb.SmbException; |
| import jcifs.smb.SmbFile; |
| import jcifs.smb.SmbFileFilter; |
| import jcifs.context.SingletonContext; |
| import org.apache.manifoldcf.agents.interfaces.RepositoryDocument; |
| import org.apache.manifoldcf.agents.interfaces.ServiceInterruption; |
| import org.apache.manifoldcf.connectorcommon.extmimemap.ExtensionMimeMap; |
| import org.apache.manifoldcf.connectorcommon.interfaces.IKeystoreManager; |
| import org.apache.manifoldcf.connectorcommon.interfaces.KeystoreManagerFactory; |
| import org.apache.manifoldcf.core.common.DateParser; |
| import org.apache.manifoldcf.core.interfaces.ConfigParams; |
| import org.apache.manifoldcf.core.interfaces.Configuration; |
| import org.apache.manifoldcf.core.interfaces.ConfigurationNode; |
| import org.apache.manifoldcf.core.interfaces.IHTTPOutput; |
| import org.apache.manifoldcf.core.interfaces.IPostParameters; |
| import org.apache.manifoldcf.core.interfaces.IThreadContext; |
| import org.apache.manifoldcf.core.interfaces.LockManagerFactory; |
| import org.apache.manifoldcf.core.interfaces.ManifoldCFException; |
| import org.apache.manifoldcf.core.interfaces.Specification; |
| import org.apache.manifoldcf.core.interfaces.SpecificationNode; |
| import org.apache.manifoldcf.core.util.URLEncoder; |
| import org.apache.manifoldcf.crawler.interfaces.IExistingVersions; |
| import org.apache.manifoldcf.crawler.interfaces.IFingerprintActivity; |
| import org.apache.manifoldcf.crawler.interfaces.IProcessActivity; |
| import org.apache.manifoldcf.crawler.interfaces.ISeedingActivity; |
| import org.apache.manifoldcf.crawler.system.Logging; |
| import org.apache.manifoldcf.crawler.system.ManifoldCF; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InterruptedIOException; |
| import java.net.MalformedURLException; |
| import java.net.UnknownHostException; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| |
| /** This is the "repository connector" for a smb/cifs shared drive file system. It's a relative of the share crawler, and should have |
| * comparable basic functionality. |
| */ |
| public class SharedDriveConnector extends org.apache.manifoldcf.crawler.connectors.BaseRepositoryConnector |
| { |
| public static final String _rcsid = "@(#)$Id: SharedDriveConnector.java 996524 2010-09-13 13:38:01Z kwright $"; |
| |
| // Activities we log |
| public final static String ACTIVITY_ACCESS = "access"; |
| |
| // These are the share connector nodes and attributes in the document specification |
| public static final String NODE_STARTPOINT = "startpoint"; |
| public static final String NODE_INCLUDE = "include"; |
| public static final String NODE_EXCLUDE = "exclude"; |
| public static final String NODE_PATHNAMEATTRIBUTE = "pathnameattribute"; |
| public static final String NODE_PATHMAP = "pathmap"; |
| public static final String NODE_FILEMAP = "filemap"; |
| public static final String NODE_URIMAP = "urimap"; |
| public static final String NODE_SHAREACCESS = "shareaccess"; |
| public static final String NODE_SHARESECURITY = "sharesecurity"; |
| public static final String NODE_PARENTFOLDERACCESS = "parentfolderaccess"; |
| public static final String NODE_PARENTFOLDERSECURITY = "parentfoldersecurity"; |
| public static final String NODE_MAXLENGTH = "maxlength"; |
| public static final String NODE_ACCESS = "access"; |
| public static final String NODE_SECURITY = "security"; |
| public static final String ATTRIBUTE_PATH = "path"; |
| public static final String ATTRIBUTE_TYPE = "type"; |
| public static final String ATTRIBUTE_INDEXABLE = "indexable"; |
| public static final String ATTRIBUTE_FILESPEC = "filespec"; |
| public static final String ATTRIBUTE_VALUE = "value"; |
| public static final String ATTRIBUTE_TOKEN = "token"; |
| public static final String ATTRIBUTE_MATCH = "match"; |
| public static final String ATTRIBUTE_REPLACE = "replace"; |
| public static final String VALUE_DIRECTORY = "directory"; |
| public static final String VALUE_FILE = "file"; |
| |
| // Properties this connector needs (that can only be configured once) |
| public final static String PROPERTY_JCIFS_USE_NTLM_V1 = "org.apache.manifoldcf.crawler.connectors.jcifs.usentlmv1"; |
| |
| // Static initialization of various system properties. This hopefully takes place |
| // before jcifs is loaded. |
| static |
| { |
| if (System.getProperty("jcifs.resolveOrder") == null) { |
| System.setProperty("jcifs.resolveOrder","LMHOSTS,DNS,WINS"); |
| } |
| if (System.getProperty("jcifs.smb.client.soTimeout") == null) { |
| System.setProperty("jcifs.smb.client.soTimeout","150000"); |
| } |
| if (System.getProperty("jcifs.smb.client.responseTimeout") == null) { |
| System.setProperty("jcifs.smb.client.responseTimeout","120000"); |
| } |
| if (System.getProperty("jcifs.smb.client.minVersion") == null) { |
| System.setProperty("jcifs.smb.client.minVersion","SMB1"); |
| } |
| if (System.getProperty("jcifs.smb.client.maxVersion") == null) { |
| System.setProperty("jcifs.smb.client.maxVersion","SMB210"); |
| } |
| if (System.getProperty("jcifs.traceResources") == null) { |
| System.setProperty("jcifs.traceResources","true"); |
| } |
| if (System.getProperty("jcifs.smb.client.ipcSigningEnforced") == null) { |
| System.setProperty("jcifs.smb.client.ipcSigningEnforced","true"); |
| } |
| // Don't change these!! |
| System.setProperty("jcifs.smb.client.listCount","20"); |
| System.setProperty("jcifs.smb.client.dfs.strictView","true"); |
| } |
| |
| private String smbconnectionPath = null; |
| private String server = null; |
| private String domain = null; |
| private String username = null; |
| private String password = null; |
| private boolean useSIDs = true; |
| private String binName = null; |
| |
| private NtlmPasswordAuthenticator pa; |
| |
| /** Deny access token for default authority */ |
| private final static String defaultAuthorityDenyToken = GLOBAL_DENY_TOKEN; |
| |
| /** Constructor. |
| */ |
| public SharedDriveConnector() |
| { |
| } |
| |
| /** Set thread context. |
| * Use the opportunity to set the system properties we'll need. |
| */ |
| @Override |
| public void setThreadContext(IThreadContext threadContext) |
| throws ManifoldCFException |
| { |
| super.setThreadContext(threadContext); |
| // We need to know whether to operate in NTLMv2 mode, or in NTLM mode. We do this before jcifs called the first time. |
| boolean useV1 = LockManagerFactory.getBooleanProperty(threadContext, PROPERTY_JCIFS_USE_NTLM_V1, false); |
| if (!useV1) |
| { |
| System.setProperty("jcifs.smb.lmCompatibility","3"); |
| System.setProperty("jcifs.smb.client.useExtendedSecurity","true"); |
| } |
| else |
| { |
| System.setProperty("jcifs.smb.lmCompatibility","0"); |
| System.setProperty("jcifs.smb.client.useExtendedSecurity","false"); |
| } |
| } |
| |
| /** Establish a "session". In the case of the jcifs connector, this just builds the appropriate smbconnectionPath string, and does the necessary checks. */ |
| protected void getSession() |
| throws ManifoldCFException |
| { |
| if (smbconnectionPath == null) |
| { |
| |
| // Get the server |
| if (server == null || server.length() == 0) |
| throw new ManifoldCFException("Missing parameter '"+SharedDriveParameters.server+"'"); |
| |
| // make the smb connection to the server |
| String authenticationString; |
| if (domain == null || domain.length() == 0) |
| domain = null; |
| |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("Connecting to: " + "smb://" + ((domain==null)?"":domain)+";"+username+":<password>@" + server + "/"); |
| |
| try |
| { |
| // use NtlmPasswordAuthentication so that we can reuse credential for DFS support |
| pa = new NtlmPasswordAuthenticator(domain,username,password); |
| SmbFile smbconnection = new SmbFile("smb://" + server + "/",SingletonContext.getInstance().withCredentials(pa)); |
| smbconnectionPath = getFileCanonicalPath(smbconnection); |
| } |
| catch (MalformedURLException e) |
| { |
| Logging.connectors.error("Unable to access SMB/CIFS share: "+"smb://" + ((domain==null)?"":domain)+";"+username+":<password>@"+ server + "/\n" + e); |
| throw new ManifoldCFException("Unable to access SMB/CIFS share: "+server, e, ManifoldCFException.REPOSITORY_CONNECTION_ERROR); |
| } |
| } |
| } |
| |
| /** 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_ACCESS}; |
| } |
| |
| /** Close the connection. Call this before discarding the repository connector. |
| */ |
| @Override |
| public void disconnect() |
| throws ManifoldCFException |
| { |
| server = null; |
| domain = null; |
| username = null; |
| password = null; |
| pa = null; |
| smbconnectionPath = null; |
| binName = null; |
| super.disconnect(); |
| } |
| |
| /** Connect. |
| *@param configParameters is the set of configuration parameters, which |
| * in this case describe the root directory. |
| */ |
| @Override |
| public void connect(ConfigParams configParameters) |
| { |
| super.connect(configParameters); |
| |
| // Get the server |
| server = configParameters.getParameter(SharedDriveParameters.server); |
| domain = configParameters.getParameter(SharedDriveParameters.domain); |
| username = configParameters.getParameter(SharedDriveParameters.username); |
| if (username == null) |
| username = ""; |
| password = configParameters.getObfuscatedParameter(SharedDriveParameters.password); |
| if (password == null) |
| password = ""; |
| String useSIDsString = configParameters.getParameter(SharedDriveParameters.useSIDs); |
| if (useSIDsString == null) |
| useSIDsString = "true"; |
| useSIDs = "true".equals(useSIDsString); |
| |
| |
| String configBinName = configParameters.getParameter(SharedDriveParameters.binName); |
| |
| binName = (configBinName == null || configBinName.length() == 0) ? server : configBinName; |
| |
| if (binName.length() > 255) // trim the bin name to fit in the database |
| binName = binName.substring(0, 255); |
| |
| // Rejigger the username/domain to be sure we PASS in a domain and we do not include the domain attached to the user! |
| // (This became essential at jcifs 1.3.0) |
| int index = username.indexOf("@"); |
| if (index != -1) |
| { |
| // Strip off the domain from the user |
| String userDomain = username.substring(index+1); |
| if (domain == null || domain.length() == 0) |
| domain = userDomain; |
| username = username.substring(0,index); |
| } |
| index = username.indexOf("\\"); |
| if (index != -1) |
| { |
| String userDomain = username.substring(0,index); |
| if (domain == null || domain.length() == 0) |
| domain = userDomain; |
| username = username.substring(index+1); |
| } |
| } |
| |
| /** Get the bin name string for a document identifier. The bin name describes the queue to which the |
| * document will be assigned for throttling purposes. Throttling controls the rate at which items in a |
| * given queue are fetched; it does not say anything about the overall fetch rate, which may operate on |
| * multiple queues or bins. |
| * For example, if you implement a web crawler, a good choice of bin name would be the server name, since |
| * that is likely to correspond to a real resource that will need real throttle protection. |
| *@param documentIdentifier is the document identifier. |
| *@return the bin name. |
| */ |
| @Override |
| public String[] getBinNames(String documentIdentifier) |
| { |
| return new String[]{binName}; |
| } |
| |
| /** |
| * Convert a document identifier to a URI. The URI is the URI that will be |
| * the unique key from the search index, and will be presented to the user |
| * as part of the search results. |
| * |
| * @param documentIdentifier |
| * is the document identifier. |
| * @return the document uri. |
| */ |
| protected static String convertToURI(String documentIdentifier, MatchMap fileMap, MatchMap uriMap) |
| throws ManifoldCFException |
| { |
| // |
| // Note well: This MUST be a legal URI!! |
| // e.g. |
| // smb://10.33.65.1/Test Folder/PPT Docs/Dearman_University of Texas 20030220.ppt |
| // file:////10.33.65.1/Test Folder/PPT Docs/Dearman_University of Texas 20030220.ppt |
| |
| String serverPath = documentIdentifier.substring("smb://".length()); |
| |
| // The first mapping converts one server path to another. |
| // If not present, we leave the original path alone. |
| serverPath = fileMap.translate(serverPath); |
| |
| // The second mapping, if present, creates a URI, using certain rules. If not present, the old standard IRI conversion is done. |
| if (uriMap.getMatchCount() != 0) |
| { |
| // URI translation. |
| // First step is to perform utf-8 translation and %-encoding. |
| |
| byte[] byteArray = serverPath.getBytes(StandardCharsets.UTF_8); |
| StringBuilder output = new StringBuilder(); |
| int i = 0; |
| while (i < byteArray.length) |
| { |
| int x = ((int)byteArray[i++]) & 0xff; |
| if (x >= 0x80 || (x >= 0 && x <= ' ') || x == ':' || x == '?' || x == '^' || x == '{' || x == '}' || |
| x == '%' || x == '#' || x == '`' || x == ';' || x == '@' || x == '&' || x == '=' || x == '+' || |
| x == '$' || x == ',') |
| { |
| output.append('%'); |
| String hexValue = Integer.toHexString((int)x).toUpperCase(Locale.ROOT); |
| if (hexValue.length() == 1) |
| output.append('0'); |
| output.append(hexValue); |
| } |
| else |
| output.append((char)x); |
| } |
| |
| // Second step is to perform the mapping. This strips off the server name and glues on the protocol and web server name, most likely. |
| return uriMap.translate(output.toString()); |
| } |
| else |
| { |
| // Convert to a URI that begins with file://///. This used to be done according to the following IE7 specification: |
| // http://blogs.msdn.com/ie/archive/2006/12/06/file-uris-in-windows.aspx |
| // However, two factors required change. First, IE8 decided to no longer adhere to the same specification as IE7. |
| // Second, the ingestion API does not (and will never) accept anything other than a well-formed URI. Thus, file |
| // specifications are ingested in a canonical form (which happens to be pretty much what this connector used prior to |
| // 3.9.0), and the various clients are responsible for converting that form into something the browser will accept. |
| |
| StringBuilder output = new StringBuilder(); |
| |
| int i = 0; |
| while (i < serverPath.length()) |
| { |
| int pos = serverPath.indexOf("/",i); |
| if (pos == -1) |
| pos = serverPath.length(); |
| String piece = serverPath.substring(i,pos); |
| // Note well. This does *not* %-encode some characters such as '#', which are legal in URI's but have special meanings! |
| String replacePiece = URLEncoder.encode(piece); |
| // Convert the +'s back to %20's |
| int j = 0; |
| while (j < replacePiece.length()) |
| { |
| int plusPos = replacePiece.indexOf("+",j); |
| if (plusPos == -1) |
| plusPos = replacePiece.length(); |
| output.append(replacePiece.substring(j,plusPos)); |
| if (plusPos < replacePiece.length()) |
| { |
| output.append("%20"); |
| plusPos++; |
| } |
| j = plusPos; |
| } |
| |
| if (pos < serverPath.length()) |
| { |
| output.append("/"); |
| pos++; |
| } |
| i = pos; |
| } |
| return "file://///"+output.toString(); |
| } |
| } |
| |
| /** Request arbitrary connector information. |
| * This method is called directly from the API in order to allow API users to perform any one of several connector-specific |
| * queries. |
| *@param output is the response object, to be filled in by this method. |
| *@param command is the command, which is taken directly from the API request. |
| *@return true if the resource is found, false if not. In either case, output may be filled in. |
| */ |
| @Override |
| public boolean requestInfo(Configuration output, String command) |
| throws ManifoldCFException |
| { |
| if (command.startsWith("folders/")) |
| { |
| String parentFolder = command.substring("folders/".length()); |
| try |
| { |
| String[] folders = getChildFolderNames(parentFolder); |
| int i = 0; |
| while (i < folders.length) |
| { |
| String folder = folders[i++]; |
| ConfigurationNode node = new ConfigurationNode("folder"); |
| node.setValue(folder); |
| output.addChild(output.getChildCount(),node); |
| } |
| } |
| catch (ManifoldCFException e) |
| { |
| ManifoldCF.createErrorNode(output,e); |
| } |
| } |
| else if (command.startsWith("folder/")) |
| { |
| String folder = command.substring("folder/".length()); |
| try |
| { |
| String canonicalFolder = validateFolderName(folder); |
| if (canonicalFolder != null) |
| { |
| ConfigurationNode node = new ConfigurationNode("folder"); |
| node.setValue(canonicalFolder); |
| output.addChild(output.getChildCount(),node); |
| } |
| } |
| catch (ManifoldCFException e) |
| { |
| ManifoldCF.createErrorNode(output,e); |
| } |
| } |
| else |
| return super.requestInfo(output,command); |
| return true; |
| } |
| |
| |
| /** Queue "seed" documents. Seed documents are the starting places for crawling activity. Documents |
| * are seeded when this method calls appropriate methods in the passed in ISeedingActivity object. |
| * |
| * This method can choose to find repository changes that happen only during the specified time interval. |
| * The seeds recorded by this method will be viewed by the framework based on what the |
| * getConnectorModel() method returns. |
| * |
| * It is not a big problem if the connector chooses to create more seeds than are |
| * strictly necessary; it is merely a question of overall work required. |
| * |
| * The end time and seeding version string passed to this method may be interpreted for greatest efficiency. |
| * For continuous crawling jobs, this method will |
| * be called once, when the job starts, and at various periodic intervals as the job executes. |
| * |
| * When a job's specification is changed, the framework automatically resets the seeding version string to null. The |
| * seeding version string may also be set to null on each job run, depending on the connector model returned by |
| * getConnectorModel(). |
| * |
| * Note that it is always ok to send MORE documents rather than less to this method. |
| * The connector will be connected before this method can be called. |
| *@param activities is the interface this method should use to perform whatever framework actions are desired. |
| *@param spec is a document specification (that comes from the job). |
| *@param seedTime is the end of the time range of documents to consider, exclusive. |
| *@param lastSeedVersion is the last seeding version string for this job, or null if the job has no previous seeding version string. |
| *@param jobMode is an integer describing how the job is being run, whether continuous or once-only. |
| *@return an updated seeding version string, to be stored with the job. |
| */ |
| @Override |
| public String addSeedDocuments(ISeedingActivity activities, Specification spec, |
| String lastSeedVersion, long seedTime, int jobMode) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| getSession(); |
| try |
| { |
| for (int i = 0; i < spec.getChildCount(); i++) |
| { |
| SpecificationNode n = spec.getChild(i); |
| if (n.getType().equals(NODE_STARTPOINT)) |
| { |
| // The id returned MUST be in canonical form!!! |
| String seed = mapToIdentifier(n.getAttributeValue(ATTRIBUTE_PATH)); |
| if (Logging.connectors.isDebugEnabled()) |
| { |
| Logging.connectors.debug("Seed = '"+seed+"'"); |
| } |
| activities.addSeedDocument(seed); |
| } |
| } |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("Could not get a canonical path: "+e.getMessage(),e); |
| } |
| catch (UnknownHostException e) |
| { |
| throw new ManifoldCFException("Could not get a canonical path: "+e.getMessage(),e); |
| } |
| return ""; |
| } |
| |
| /** 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. |
| */ |
| @Override |
| public void processDocuments(String[] documentIdentifiers, IExistingVersions statuses, Specification spec, |
| IProcessActivity activities, int jobMode, boolean usesDefaultAuthority) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| // Read the forced acls. A null return indicates that security is disabled!!! |
| // A zero-length return indicates that the native acls should be used. |
| // All of this is germane to how we ingest the document, so we need to note it in |
| // the version string completely. |
| String[] acls = getForcedAcls(spec); |
| String[] shareAcls = getForcedShareAcls(spec); |
| String[] parentFolderAcls = getForcedParentFolderAcls(spec); |
| |
| String pathAttributeName = null; |
| MatchMap matchMap = new MatchMap(); |
| MatchMap fileMap = new MatchMap(); |
| MatchMap uriMap = new MatchMap(); |
| |
| int i = 0; |
| while (i < spec.getChildCount()) |
| { |
| SpecificationNode n = spec.getChild(i++); |
| if (n.getType().equals(NODE_PATHNAMEATTRIBUTE)) |
| pathAttributeName = n.getAttributeValue(ATTRIBUTE_VALUE); |
| else if (n.getType().equals(NODE_PATHMAP)) |
| { |
| // Path mapping info also needs to be looked at, because it affects what is |
| // ingested. |
| String pathMatch = n.getAttributeValue(ATTRIBUTE_MATCH); |
| String pathReplace = n.getAttributeValue(ATTRIBUTE_REPLACE); |
| matchMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| else if (n.getType().equals(NODE_FILEMAP)) |
| { |
| String pathMatch = n.getAttributeValue(ATTRIBUTE_MATCH); |
| String pathReplace = n.getAttributeValue(ATTRIBUTE_REPLACE); |
| fileMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| else if (n.getType().equals(NODE_URIMAP)) |
| { |
| String pathMatch = n.getAttributeValue(ATTRIBUTE_MATCH); |
| String pathReplace = n.getAttributeValue(ATTRIBUTE_REPLACE); |
| uriMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| |
| for (String documentIdentifier : documentIdentifiers) |
| { |
| getSession(); |
| |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Processing '"+documentIdentifier+"'"); |
| |
| String versionString; |
| SmbFile file; |
| |
| String ingestionURI = null; |
| String pathAttributeValue = null; |
| |
| String[] shareAllow = null; |
| String[] shareDeny = null; |
| boolean shareSecurityOn = false; |
| |
| String[] parentAllow = null; |
| String[] parentDeny = null; |
| boolean parentSecurityOn = false; |
| |
| String[] documentAllow = null; |
| String[] documentDeny = null; |
| boolean documentSecurityOn = false; |
| |
| // Common info we really need to fetch only once |
| long fileLength = 0L; |
| long lastModified = 0L; |
| boolean fileExists = false; |
| boolean fileIsDirectory = false; |
| |
| try |
| { |
| file = new SmbFile(documentIdentifier,SingletonContext.getInstance().withCredentials(pa)); |
| fileExists = fileExists(file); |
| |
| // File has to exist AND have a non-null canonical path to be readable. If the canonical path is |
| // null, it means that the windows permissions are not right and directory/file is not readable!!! |
| String newPath = getFileCanonicalPath(file); |
| // We MUST check the specification here, otherwise a recrawl may not delete what it's supposed to! |
| if (fileExists && newPath != null) |
| { |
| fileIsDirectory = fileIsDirectory(file); |
| if (checkInclude(fileIsDirectory,newPath,spec)) |
| { |
| if (fileIsDirectory) |
| { |
| // Hmm, this is not correct; version string should be empty for windows directories, since |
| // they are not hierarchical in modified date propagation. |
| // It's a directory. The version ID will be the |
| // last modified date. |
| //long lastModified = fileLastModified(file); |
| //versionString = new Long(lastModified).toString(); |
| versionString = ""; |
| |
| } |
| else |
| { |
| fileLength = fileLength(file); |
| if (checkIncludeFile(fileLength,newPath,spec,activities)) |
| { |
| // It's a file of acceptable length. |
| // The ability to get ACLs, list files, and an inputstream under DFS all work now. |
| // The SmbFile for parentFolder acls. |
| SmbFile parentFolder = new SmbFile(file.getParent(),SingletonContext.getInstance().withCredentials(pa)); |
| |
| // Compute the security information |
| String[] modelArray = new String[0]; |
| |
| List<String> allowList = new ArrayList<String>(); |
| List<String> denyList = new ArrayList<String>(); |
| shareSecurityOn = getFileShareSecuritySet(allowList, denyList, file, shareAcls); |
| shareAllow = allowList.toArray(modelArray); |
| shareDeny = denyList.toArray(modelArray); |
| |
| allowList.clear(); |
| denyList.clear(); |
| parentSecurityOn = getFileSecuritySet(allowList, denyList, parentFolder, parentFolderAcls); |
| parentAllow = allowList.toArray(modelArray); |
| parentDeny = denyList.toArray(modelArray); |
| |
| allowList.clear(); |
| denyList.clear(); |
| documentSecurityOn = getFileSecuritySet(allowList, denyList, file, acls); |
| documentAllow = allowList.toArray(modelArray); |
| documentDeny = denyList.toArray(modelArray); |
| |
| // This is stuff we need for computing the version string AND for indexing |
| lastModified = fileLastModified(file); |
| |
| // The format of this string changed on 11/8/2006 to be comformant with the standard way |
| // acls and metadata descriptions are being stuffed into the version string across connectors. |
| |
| // The format of this string changed again on 7/3/2009 to permit the ingestion uri/iri to be included. |
| // This was to support filename/uri mapping functionality. |
| |
| StringBuilder sb = new StringBuilder(); |
| |
| addSecuritySet(sb,shareSecurityOn,shareAllow,shareDeny); |
| addSecuritySet(sb,parentSecurityOn,parentAllow,parentDeny); |
| addSecuritySet(sb,documentSecurityOn,documentAllow,documentDeny); |
| |
| // Include the path attribute name and value in the parseable area. |
| if (pathAttributeName != null) |
| { |
| sb.append('+'); |
| pack(sb,pathAttributeName,'+'); |
| // Calculate path string; we'll include that wholesale in the version |
| pathAttributeValue = documentIdentifier; |
| // 3/13/2008 |
| // In looking at what comes into the path metadata attribute by default, and cogitating a bit, I've concluded that |
| // the smb:// and the server/domain name at the start of the path are just plain old noise, and should be stripped. |
| // This changes a behavior that has been around for a while, so there is a risk, but a quick back-and-forth with the |
| // SE's leads me to believe that this is safe. |
| |
| if (pathAttributeValue.startsWith("smb://")) |
| { |
| int index = pathAttributeValue.indexOf("/","smb://".length()); |
| if (index == -1) |
| index = pathAttributeValue.length(); |
| pathAttributeValue = pathAttributeValue.substring(index); |
| } |
| // Now, translate |
| pathAttributeValue = matchMap.translate(pathAttributeValue); |
| pack(sb,pathAttributeValue,'+'); |
| } |
| else |
| sb.append('-'); |
| |
| // Calculate the ingestion IRI/URI, and include that in the parseable area. |
| ingestionURI = convertToURI(documentIdentifier,fileMap,uriMap); |
| pack(sb,ingestionURI,'+'); |
| |
| // The stuff from here on down is non-parseable. |
| sb.append(new Long(lastModified).toString()).append(":") |
| .append(new Long(fileLength).toString()); |
| // Also include the specification-based answer for the question of whether fingerprinting is |
| // going to be done. Although we may not consider this to truly be "version" information, the |
| // specification does affect whether anything is ingested or not, so it really is. The alternative |
| // is to fingerprint right here, in the version part of the world, but that's got a performance |
| // downside, because it means that we'd have to suck over pretty much everything just to determine |
| // what we wanted to ingest. |
| boolean ifIndexable = wouldFileBeIncluded(newPath,spec,true); |
| boolean ifNotIndexable = wouldFileBeIncluded(newPath,spec,false); |
| if (ifIndexable == ifNotIndexable) |
| sb.append("I"); |
| else |
| sb.append(ifIndexable?"Y":"N"); |
| versionString = sb.toString(); |
| } |
| else |
| { |
| activities.deleteDocument(documentIdentifier); |
| continue; |
| } |
| } |
| } |
| else |
| { |
| activities.deleteDocument(documentIdentifier); |
| continue; |
| } |
| } |
| else |
| { |
| activities.deleteDocument(documentIdentifier); |
| continue; |
| } |
| } |
| catch (jcifs.smb.SmbAuthException e) |
| { |
| Logging.connectors.warn("JCIFS: Authorization exception reading version information for "+documentIdentifier+" - skipping"); |
| if(e.getMessage().equals("Logon failure: unknown user name or bad password.")) |
| throw new ManifoldCFException( "SmbAuthException thrown: " + e.getMessage(), e ); |
| else { |
| activities.deleteDocument(documentIdentifier ); |
| continue; |
| } |
| } |
| catch (MalformedURLException mue) |
| { |
| Logging.connectors.error("JCIFS: MalformedURLException thrown: "+mue.getMessage(),mue); |
| throw new ManifoldCFException("MalformedURLException thrown: "+mue.getMessage(),mue); |
| } |
| catch (SmbException se) |
| { |
| processSMBException(se,documentIdentifier,"getting document version","fetching share security"); |
| activities.deleteDocument(documentIdentifier); |
| continue; |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| long currentTime = System.currentTimeMillis(); |
| Logging.connectors.warn("JCIFS: Socket timeout reading version information for document "+documentIdentifier+": "+e.getMessage(),e); |
| throw new ServiceInterruption("Timeout or other service interruption: "+e.getMessage(),e,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| catch (InterruptedIOException e) |
| { |
| throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED); |
| } |
| catch (IOException e) |
| { |
| long currentTime = System.currentTimeMillis(); |
| Logging.connectors.warn("JCIFS: I/O error reading version information for document "+documentIdentifier+": "+e.getMessage(),e); |
| throw new ServiceInterruption("Timeout or other service interruption: "+e.getMessage(),e,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| |
| if (versionString.length() == 0 || activities.checkDocumentNeedsReindexing(documentIdentifier,versionString)) |
| { |
| String errorCode = null; |
| String errorDesc = null; |
| Long fileLengthLong = null; |
| long startFetchTime = System.currentTimeMillis(); |
| try |
| { |
| byte[] transferBuffer = null; |
| |
| try |
| { |
| |
| if (fileExists) |
| { |
| if (fileIsDirectory) |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: '"+documentIdentifier+"' is a directory"); |
| |
| // Queue up stuff for directory |
| // DFS special support no longer needed, because JCifs now does the right thing. |
| |
| // This is the string we replace in the child canonical paths. |
| // String matchPrefix = ""; |
| // This is what we replace it with, to get back to a DFS path. |
| // String matchReplace = ""; |
| |
| // DFS resolved. |
| |
| // Use a filter to actually do the work here. This prevents large arrays from being |
| // created when there are big directories. |
| ProcessDocumentsFilter filter = new ProcessDocumentsFilter(activities,spec); |
| fileListFiles(file,filter); |
| filter.checkAndThrow(); |
| } |
| else |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: '"+documentIdentifier+"' is a file"); |
| |
| // We've already avoided queuing documents that we |
| // don't want, based on file specifications. |
| // We still need to check based on file data. |
| |
| // DFS support is now implicit in JCifs. |
| |
| String fileName = getFileCanonicalPath(file); |
| if (fileName != null && !file.isHidden()) |
| { |
| String uri = ingestionURI; |
| String fileNameString = file.getName(); |
| Date lastModifiedDate = new Date(lastModified); |
| Date creationDate = new Date(file.createTime()); |
| Long originalLength = new Long(fileLength); |
| String contentType = mapExtensionToMimeType(fileNameString); |
| |
| if (!activities.checkURLIndexable(uri)) |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because output connector cannot accept URL ('"+uri+"')"); |
| errorCode = activities.EXCLUDED_URL; |
| errorDesc = "Rejected due to URL ('"+uri+"')"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| |
| if (!activities.checkMimeTypeIndexable(contentType)) |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because output connector cannot accept content type ('"+contentType+"')"); |
| errorCode = activities.EXCLUDED_MIMETYPE; |
| errorDesc = "Rejected due to mime type ("+contentType+")"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| |
| if (!activities.checkDateIndexable(lastModifiedDate)) |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because output connector cannot accept date ("+lastModifiedDate+")"); |
| errorCode = activities.EXCLUDED_DATE; |
| errorDesc = "Rejected due to date ("+lastModifiedDate+")"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| |
| // Initialize repository document with common stuff, and find the URI |
| RepositoryDocument rd = new RepositoryDocument(); |
| |
| //If using the lastAccess patched/Google version of jcifs then this can be uncommented |
| //Date lastAccessDate = new Date(file.lastAccess()); |
| Integer attributes = file.getAttributes(); |
| String shareName = file.getShare(); |
| |
| rd.setFileName(fileNameString); |
| rd.setOriginalSize(originalLength); |
| |
| if (contentType != null) |
| rd.setMimeType(contentType); |
| rd.addField("lastModified", lastModifiedDate.toString()); |
| rd.addField("fileLastModified",DateParser.formatISO8601Date(lastModifiedDate)); |
| rd.setModifiedDate(lastModifiedDate); |
| |
| // Add extra obtainable fields to the field map |
| rd.addField("createdOn", creationDate.toString()); |
| rd.addField("fileCreatedOn",DateParser.formatISO8601Date(creationDate)); |
| rd.setCreatedDate(creationDate); |
| |
| //rd.addField("lastAccess", lastModifiedDate.toString()); |
| rd.addField("attributes", Integer.toString(attributes)); |
| rd.addField("shareName", shareName); |
| |
| setDocumentSecurity(rd,shareAllow,shareDeny,parentAllow,parentDeny,documentAllow,documentDeny); |
| setPathMetadata(rd,pathAttributeName,pathAttributeValue); |
| |
| // manipulate path to include the DFS alias, not the literal path |
| // String newPath = matchPrefix + fileName.substring(matchReplace.length()); |
| String newPath = fileName; |
| if (checkNeedFileData(newPath, spec)) |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Local file data needed for '"+documentIdentifier+"'"); |
| |
| // Create a temporary file, and use that for the check and then the ingest |
| File tempFile = File.createTempFile("_sdc_",null); |
| try |
| { |
| FileOutputStream os = new FileOutputStream(tempFile); |
| try |
| { |
| |
| // Now, make a local copy so we can fingerprint |
| InputStream inputStream = getFileInputStream(file); |
| try |
| { |
| // Copy! |
| if (transferBuffer == null) |
| transferBuffer = new byte[65536]; |
| while (true) |
| { |
| int amt = inputStream.read(transferBuffer,0,transferBuffer.length); |
| if (amt == -1) |
| break; |
| os.write(transferBuffer,0,amt); |
| } |
| } |
| finally |
| { |
| inputStream.close(); |
| } |
| } |
| finally |
| { |
| os.close(); |
| } |
| |
| if (checkIngest(tempFile, newPath, spec, activities)) |
| { |
| // Not needed; fetched earlier: long fileLength = tempFile.length(); |
| if (!activities.checkLengthIndexable(fileLength)) |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because output connector cannot accept length ("+fileLength+")"); |
| errorCode = activities.EXCLUDED_LENGTH; |
| errorDesc = "Rejected due to length ("+fileLength+")"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Decided to ingest '"+documentIdentifier+"'"); |
| // OK, do ingestion itself! |
| InputStream inputStream = new FileInputStream(tempFile); |
| try |
| { |
| rd.setBinary(inputStream, fileLength); |
| |
| activities.ingestDocumentWithException(documentIdentifier, versionString, uri, rd); |
| errorCode = "OK"; |
| fileLengthLong = new Long(fileLength); |
| } |
| finally |
| { |
| inputStream.close(); |
| } |
| |
| } |
| else |
| { |
| // We must actively remove the document here, because the getDocumentVersions() |
| // method has no way of signalling this, since it does not do the fingerprinting. |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Decided to remove '"+documentIdentifier+"'"); |
| activities.noDocument(documentIdentifier, versionString); |
| errorCode = "NOWORKNEEDED"; |
| errorDesc = "No indexing needed for document at this time"; |
| } |
| } |
| finally |
| { |
| tempFile.delete(); |
| } |
| } |
| else |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Local file data not needed for '"+documentIdentifier+"'"); |
| |
| // Not needed; fetched earlier: long fileLength = fileLength(file); |
| if (!activities.checkLengthIndexable(fileLength)) |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because output connector cannot accept length ("+fileLength+")"); |
| errorCode = activities.EXCLUDED_LENGTH; |
| errorDesc = "Rejected because of length ("+fileLength+")"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| |
| // Presume that since the file was queued that it fulfilled the needed criteria. |
| // Go off and ingest the fast way. |
| |
| // Ingest the document. |
| InputStream inputStream = getFileInputStream(file); |
| try |
| { |
| rd.setBinary(inputStream, fileLength); |
| |
| activities.ingestDocumentWithException(documentIdentifier, versionString, uri, rd); |
| errorCode = "OK"; |
| fileLengthLong = new Long(fileLength); |
| } |
| finally |
| { |
| inputStream.close(); |
| } |
| } |
| } |
| else |
| { |
| Logging.connectors.debug("JCIFS: Skipping file because canonical path is null, or because file is hidden"); |
| errorCode = "NULLORHIDDEN"; |
| errorDesc = "Null canonical path or hidden file"; |
| activities.noDocument(documentIdentifier,versionString); |
| continue; |
| } |
| } |
| } |
| } |
| catch (MalformedURLException mue) |
| { |
| Logging.connectors.error("MalformedURLException tossed: "+mue.getMessage(),mue); |
| errorCode = mue.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Malformed URL: "+mue.getMessage(); |
| throw new ManifoldCFException("MalformedURLException tossed: "+mue.getMessage(),mue); |
| } |
| catch (jcifs.smb.SmbAuthException e) |
| { |
| Logging.connectors.warn("JCIFS: Authorization exception reading document/directory "+documentIdentifier+" - skipping"); |
| errorCode = e.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Authorization: "+e.getMessage(); |
| if(e.getMessage().equals("Logon failure: unknown user name or bad password.")) |
| throw new ManifoldCFException( "SmbAuthException thrown: " + e.getMessage(), e ); |
| else { |
| activities.noDocument(documentIdentifier, versionString); |
| continue; |
| } |
| } |
| catch (SmbException se) |
| { |
| // At least some of these are transport errors, and should be treated as service |
| // interruptions. |
| long currentTime = System.currentTimeMillis(); |
| Throwable cause = se.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw new ManifoldCFException(te.getRootCause().getMessage(),te.getRootCause(),ManifoldCFException.INTERRUPTED); |
| |
| Logging.connectors.warn("JCIFS: Timeout processing document/directory "+documentIdentifier+": retrying...",se); |
| errorCode = cause.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Transport: "+cause.getMessage(); |
| throw new ServiceInterruption("Timeout or other service interruption: "+cause.getMessage(),cause,currentTime + 300000L, |
| currentTime + 12 * 60 * 60000L,-1,false); |
| } |
| if (se.getMessage().toLowerCase(Locale.ROOT).indexOf("reset by peer") != -1 || |
| se.getMessage().toLowerCase(Locale.ROOT).indexOf("busy") != -1 || |
| se.getMessage().toLowerCase(Locale.ROOT).indexOf("file in use") != -1 || |
| se.getMessage().toLowerCase(Locale.ROOT).indexOf("is being used") != -1 || |
| se.getMessage().indexOf("0xC0000054") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Busy' response when processing document/directory for "+documentIdentifier+": retrying...",se); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Busy: "+se.getMessage(); |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("handle is invalid") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Handle is invalid' response when processing document/directory for "+documentIdentifier+": retrying...",se); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Expiration: "+se.getMessage(); |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("parameter is incorrect") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Parameter is incorrect' response when processing document/directory for "+documentIdentifier+": retrying...",se); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Expiration: "+se.getMessage(); |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("no longer available") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'No longer available' response when processing document/directory for "+documentIdentifier+": retrying...",se); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Expiration: "+se.getMessage(); |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("cannot find") != -1 || se.getMessage().indexOf("cannot be found") != -1) |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Skipping document/directory "+documentIdentifier+" because it cannot be found"); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Not found: "+se.getMessage(); |
| activities.noDocument(documentIdentifier, versionString); |
| } |
| else if (se.getMessage().indexOf("0xC0000205") != -1) |
| { |
| Logging.connectors.warn("JCIFS: Out of resources exception reading document/directory "+documentIdentifier+" - skipping"); |
| // We call the delete even if it's a directory; this is harmless and it cleans up the jobqueue row. |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Resources: "+se.getMessage(); |
| activities.noDocument(documentIdentifier, versionString); |
| } |
| else if (se.getMessage().indexOf("is denied") != -1) |
| { |
| Logging.connectors.warn("JCIFS: Access exception reading document/directory "+documentIdentifier+" - skipping"); |
| // We call the delete even if it's a directory; this is harmless and it cleans up the jobqueue row. |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Authorization: "+se.getMessage(); |
| activities.noDocument(documentIdentifier, versionString); |
| } |
| else |
| { |
| Logging.connectors.error("JCIFS: SmbException tossed processing "+documentIdentifier,se); |
| errorCode = se.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = "Unknown: "+se.getMessage(); |
| throw new ServiceInterruption("Unknown SMBException thrown: "+se.getMessage(),se,currentTime + 3 * 60 * 60000L, |
| -1L,1,true); |
| } |
| } |
| catch (IOException e) |
| { |
| errorCode = e.getClass().getSimpleName().toUpperCase(Locale.ROOT); |
| errorDesc = e.getMessage(); |
| handleIOException(documentIdentifier,e); |
| } |
| } |
| catch (ManifoldCFException e) |
| { |
| if (e.getErrorCode() == ManifoldCFException.INTERRUPTED) |
| errorCode = null; |
| throw e; |
| } |
| finally |
| { |
| if (errorCode != null) |
| activities.recordActivity(new Long(startFetchTime),ACTIVITY_ACCESS, |
| fileLengthLong,documentIdentifier,errorCode,errorDesc,null); |
| } |
| |
| } |
| } |
| } |
| |
| protected static void handleIOException(String documentIdentifier, IOException e) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| if (e instanceof java.net.SocketTimeoutException) |
| { |
| long currentTime = System.currentTimeMillis(); |
| Logging.connectors.warn("JCIFS: Socket timeout processing "+documentIdentifier+": "+e.getMessage(),e); |
| throw new ServiceInterruption("Timeout or other service interruption: "+e.getMessage(),e,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (e instanceof InterruptedIOException) |
| { |
| throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED); |
| } |
| else |
| { |
| long currentTime = System.currentTimeMillis(); |
| Logging.connectors.warn("JCIFS: IO error processing "+documentIdentifier+": "+e.getMessage(),e); |
| throw new ServiceInterruption("Timeout or other service interruption: "+e.getMessage(),e,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| } |
| |
| /** Map an extension to a mime type */ |
| protected static String mapExtensionToMimeType(String fileName) |
| { |
| int slashIndex = fileName.lastIndexOf("/"); |
| if (slashIndex != -1) |
| fileName = fileName.substring(slashIndex+1); |
| int dotIndex = fileName.lastIndexOf("."); |
| if (dotIndex == -1) |
| return null; |
| return ExtensionMimeMap.mapToMimeType(fileName.substring(dotIndex+1).toLowerCase(java.util.Locale.ROOT)); |
| } |
| |
| protected static void addSecuritySet(StringBuilder description, |
| boolean enabled, String[] allowTokens, String[] denyTokens) |
| { |
| if (enabled) |
| { |
| description.append("+"); |
| java.util.Arrays.sort(allowTokens); |
| java.util.Arrays.sort(denyTokens); |
| // Stuff the acls into the description string. |
| packList(description,allowTokens,'+'); |
| packList(description,denyTokens,'+'); |
| } |
| else |
| description.append("-"); |
| |
| } |
| |
| protected boolean getFileSecuritySet(List<String> allowList, List<String> denyList, SmbFile file, String[] forced) |
| throws ManifoldCFException, IOException |
| { |
| if (forced != null) |
| { |
| if (forced.length == 0) |
| { |
| convertACEs(allowList,denyList,getFileSecurity(file, useSIDs)); |
| } |
| else |
| { |
| for (String forcedToken : forced) |
| { |
| allowList.add(forcedToken); |
| } |
| denyList.add(defaultAuthorityDenyToken); |
| } |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| protected boolean getFileShareSecuritySet(List<String> allowList, List<String> denyList, SmbFile file, String[] forced) |
| throws ManifoldCFException, IOException |
| { |
| if (forced != null) |
| { |
| if (forced.length == 0) |
| { |
| convertACEs(allowList,denyList,getFileShareSecurity(file, useSIDs)); |
| } |
| else |
| { |
| for (String forcedToken : forced) |
| { |
| allowList.add(forcedToken); |
| } |
| denyList.add(defaultAuthorityDenyToken); |
| } |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| protected void convertACEs(List<String> allowList, List<String> denyList, ACE[] aces) |
| { |
| if (aces == null) |
| { |
| // "Public" share: S-1-1-0 |
| allowList.add("S-1-1-0"); |
| denyList.add(defaultAuthorityDenyToken); |
| } |
| else |
| { |
| denyList.add(defaultAuthorityDenyToken); |
| for (ACE ace : aces) |
| { |
| if ((ace.getAccessMask() & ACE.FILE_READ_DATA) != 0) |
| { |
| if (ace.isAllow()) |
| allowList.add(useSIDs ? ace.getSID().toString() : ace.getSID().getAccountName()); |
| else |
| denyList.add(useSIDs ? ace.getSID().toString() : ace.getSID().getAccountName()); |
| } |
| } |
| } |
| } |
| |
| |
| protected static void processSMBException(SmbException se, String documentIdentifier, String activity, String operation) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| // At least some of these are transport errors, and should be treated as service |
| // interruptions. |
| long currentTime = System.currentTimeMillis(); |
| Throwable cause = se.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw new ManifoldCFException(te.getRootCause().getMessage(),te.getRootCause(),ManifoldCFException.INTERRUPTED); |
| Logging.connectors.warn("JCIFS: Timeout "+activity+" for "+documentIdentifier+": retrying...",se); |
| // Transport exceptions no longer abort when they give up, so we can't get notified that there is a problem. |
| |
| throw new ServiceInterruption("Timeout or other service interruption: "+cause.getMessage(),cause,currentTime + 300000L, |
| currentTime + 12 * 60 * 60000L,-1,false); |
| } |
| if (se.getMessage().indexOf("busy") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Busy' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // Busy exceptions just skip the document and keep going |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("0xC0000054") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Busy' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // Busy exceptions just skip the document and keep going |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("handle is invalid") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Handle is invalid' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // Invalid handle errors treated like "busy" |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("parameter is incorrect") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'Parameter is incorrect' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // Invalid handle errors treated like "busy" |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("no longer available") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'No longer available' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // No longer available == busy |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if(se.getMessage().indexOf("No process is on the other end of the pipe") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'No process is on the other end of the pipe' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // 'No process is on the other end of the pipe' skip the document and keep going |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().toLowerCase(Locale.ROOT).indexOf("busy") != -1 || |
| se.getMessage().toLowerCase(Locale.ROOT).indexOf("file in use") != -1 || |
| se.getMessage().toLowerCase(Locale.ROOT).indexOf("is being used") != -1) |
| { |
| Logging.connectors.warn("JCIFS: 'File in Use' response when "+activity+" for "+documentIdentifier+": retrying...",se); |
| // 'File in Use' skip the document and keep going |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 300000L, |
| currentTime + 3 * 60 * 60000L,-1,false); |
| } |
| else if (se.getMessage().indexOf("cannot find") != -1 || se.getMessage().indexOf("cannot be found") != -1) |
| { |
| return; |
| } |
| else if (se.getMessage().indexOf("is denied") != -1) |
| { |
| Logging.connectors.warn("JCIFS: Access exception when "+activity+" for "+documentIdentifier+" - skipping"); |
| return; |
| } |
| else if (se.getMessage().indexOf("Incorrect function") != -1) |
| { |
| Logging.connectors.error("JCIFS: Server does not support a required operation ("+operation+"?) for "+documentIdentifier); |
| throw new ManifoldCFException("Server does not support a required operation ("+operation+", possibly?) accessing document "+documentIdentifier,se); |
| } |
| else |
| { |
| Logging.connectors.error("Unrecognized SmbException thrown "+activity+" for "+documentIdentifier,se); |
| throw new ServiceInterruption("Timeout or other service interruption: "+se.getMessage(),se,currentTime + 3 * 60 * 60000L, |
| -1,1,true); |
| } |
| } |
| |
| protected static void setDocumentSecurity(RepositoryDocument rd, |
| String[] shareAllow, String[] shareDeny, |
| String[] parentAllow, String[] parentDeny, |
| String[] allow, String[] deny) |
| { |
| // set share acls |
| if (shareAllow.length > 0 || shareDeny.length > 0) |
| rd.setSecurity(RepositoryDocument.SECURITY_TYPE_SHARE,shareAllow,shareDeny); |
| // set parent folder acls |
| if (parentAllow.length > 0 || parentDeny.length > 0) |
| rd.setSecurity(RepositoryDocument.SECURITY_TYPE_PARENT,parentAllow,parentDeny); |
| // set native file acls |
| if (allow.length > 0 || deny.length > 0) |
| rd.setSecurity(RepositoryDocument.SECURITY_TYPE_DOCUMENT,allow,deny); |
| } |
| |
| protected static void setPathMetadata(RepositoryDocument rd, String pathAttributeName, String pathAttributeValue) |
| throws ManifoldCFException |
| { |
| if (pathAttributeName != null && pathAttributeValue != null) { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Path attribute name is '"+pathAttributeName+"'"); |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Path attribute value is '"+pathAttributeValue+"'"); |
| rd.addField(pathAttributeName,pathAttributeValue); |
| } |
| else |
| Logging.connectors.debug("JCIFS: Path attribute name is null"); |
| } |
| |
| /** Check status of connection. |
| */ |
| @Override |
| |
| public String check() |
| throws ManifoldCFException |
| { |
| getSession(); |
| String serverURI = smbconnectionPath; |
| SmbFile server = null; |
| try |
| { |
| server = new SmbFile(serverURI,SingletonContext.getInstance().withCredentials(pa)); |
| } |
| catch (MalformedURLException e1) |
| { |
| return "Malformed URL: '"+serverURI+"': "+e1.getMessage(); |
| } |
| try |
| { |
| // check to make sure it's a server or a folder |
| int type = getFileType(server); |
| if (type==SmbFile.TYPE_SERVER || type==SmbFile.TYPE_SHARE |
| || type==SmbFile.TYPE_FILESYSTEM) |
| { |
| try |
| { |
| server.connect(); |
| if (!server.exists()) |
| return "Server or path does not exist"; |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| return "Timeout connecting to server: "+e.getMessage(); |
| } |
| catch (InterruptedIOException e) |
| { |
| throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED); |
| } |
| catch (IOException e) |
| { |
| return "Couldn't connect to server: "+e.getMessage(); |
| } |
| return super.check(); |
| } |
| else |
| return "URI is not a server URI: '"+serverURI+"'"; |
| } |
| catch (SmbException e) |
| { |
| return "Could not connect: "+e.getMessage(); |
| } |
| } |
| |
| // Protected methods |
| |
| /** Check if a file's stats are OK for inclusion. |
| */ |
| protected static boolean checkIncludeFile(long fileLength, String fileName, Specification documentSpecification, IFingerprintActivity activities) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| // If it's a file, make sure the maximum length is not exceeded |
| if (!activities.checkLengthIndexable(fileLength) || |
| !activities.checkMimeTypeIndexable(mapExtensionToMimeType(fileName))) |
| return false; |
| long maxFileLength = Long.MAX_VALUE; |
| for (int i = 0; i < documentSpecification.getChildCount(); i++) |
| { |
| SpecificationNode sn = documentSpecification.getChild(i); |
| if (sn.getType().equals(NODE_MAXLENGTH)) |
| { |
| try |
| { |
| String value = sn.getAttributeValue(ATTRIBUTE_VALUE); |
| if (value != null && value.length() > 0) |
| maxFileLength = new Long(value).longValue(); |
| } |
| catch (NumberFormatException e) |
| { |
| throw new ManifoldCFException("Bad number: "+e.getMessage(),e); |
| } |
| } |
| } |
| if (fileLength > maxFileLength) |
| return false; |
| return true; |
| } |
| |
| |
| /** Check if a file or directory should be included, given a document specification. |
| *@param isDirectory is true if the file is a directory. |
| *@param fileName is the canonical file name. |
| *@param documentSpecification is the specification. |
| *@return true if it should be included. |
| */ |
| protected boolean checkInclude(boolean isDirectory, String fileName, Specification documentSpecification) |
| throws ManifoldCFException |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: In checkInclude for '"+fileName+"'"); |
| |
| // This method does not attempt to do any fingerprinting. Instead, it will opt to include any |
| // file that may depend on fingerprinting, and exclude everything else. The actual setup for |
| // the fingerprinting test is in checkNeedFileData(), while the actual code that determines in vs. |
| // out using the file data is in checkIngest(). |
| try |
| { |
| String pathPart; |
| String filePart; |
| if (isDirectory) |
| { |
| |
| pathPart = fileName; |
| filePart = null; |
| } |
| else |
| { |
| int lastSlash = fileName.lastIndexOf("/"); |
| if (lastSlash == -1) |
| { |
| pathPart = ""; |
| filePart = fileName; |
| } |
| else |
| { |
| // Pathpart has to include the slash |
| pathPart = fileName.substring(0,lastSlash+1); |
| filePart = fileName.substring(lastSlash+1); |
| } |
| } |
| |
| int i; |
| |
| // Scan until we match a startpoint |
| i = 0; |
| while (i < documentSpecification.getChildCount()) |
| { |
| SpecificationNode sn = documentSpecification.getChild(i++); |
| if (sn.getType().equals(NODE_STARTPOINT)) |
| { |
| // Prepend the server URL to the path, since that's what pathpart will have. |
| String path = mapToIdentifier(sn.getAttributeValue(ATTRIBUTE_PATH)); |
| |
| // Compare with filename |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Matching startpoint '"+path+"' against actual '"+pathPart+"'"); |
| int matchEnd = matchSubPath(path,pathPart); |
| if (matchEnd == -1) |
| { |
| Logging.connectors.debug("JCIFS: No match"); |
| continue; |
| } |
| |
| Logging.connectors.debug("JCIFS: Startpoint found!"); |
| |
| // If this is the root, it's always included. |
| if (matchEnd == fileName.length()) |
| { |
| Logging.connectors.debug("JCIFS: Startpoint: always included"); |
| return true; |
| } |
| |
| // matchEnd is the start of the rest of the path (after the match) in fileName. |
| // We need to walk through the rules and see whether it's in or out. |
| int j = 0; |
| while (j < sn.getChildCount()) |
| { |
| SpecificationNode node = sn.getChild(j++); |
| String flavor = node.getType(); |
| if (flavor.equals(NODE_INCLUDE) || flavor.equals(NODE_EXCLUDE)) |
| { |
| String type = node.getAttributeValue(ATTRIBUTE_TYPE); |
| if (type == null) |
| type = ""; |
| String indexable = node.getAttributeValue(ATTRIBUTE_INDEXABLE); |
| if (indexable == null) |
| indexable = ""; |
| String match = node.getAttributeValue(ATTRIBUTE_FILESPEC); |
| |
| // Check if there's a match against the filespec |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Checking '"+match+"' against '"+fileName.substring(matchEnd-1)+"'"); |
| boolean isMatch = checkMatch(fileName,matchEnd-1,match); |
| boolean isKnown = true; |
| |
| // Check the directory/file criteria |
| if (isMatch) |
| { |
| Logging.connectors.debug("JCIFS: Match found."); |
| isMatch = type.length() == 0 || |
| (type.equals(VALUE_DIRECTORY) && isDirectory) || |
| (type.equals(VALUE_FILE) && !isDirectory); |
| } |
| else |
| Logging.connectors.debug("JCIFS: No match!"); |
| |
| // Check the indexable criteria |
| if (isMatch) |
| { |
| if (indexable.length() != 0) |
| { |
| // Directories are never considered indexable. |
| // But if this is not a directory, things become ambiguous. |
| boolean isIndexable; |
| if (isDirectory) |
| { |
| isIndexable = false; |
| isMatch = (indexable.equals("yes") && isIndexable) || |
| (indexable.equals("no") && !isIndexable); |
| } |
| else |
| isKnown = false; |
| |
| } |
| } |
| |
| if (isKnown) |
| { |
| if (isMatch) |
| { |
| if (flavor.equals(NODE_INCLUDE)) |
| return true; |
| else |
| return false; |
| } |
| } |
| else |
| { |
| // Not known |
| // What we do depends on whether this is an include rule or an exclude one. |
| // We want to err on the side of inclusion, which means for include rules |
| // we return true, and for exclude rules we simply continue. |
| if (flavor.equals(NODE_INCLUDE)) |
| return true; |
| // Continue |
| } |
| } |
| } |
| |
| } |
| } |
| return false; |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| catch (UnknownHostException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| finally |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Leaving checkInclude for '"+fileName+"'"); |
| } |
| |
| } |
| |
| /** Pretend that a file is either indexable or not, and return whether or not it would be ingested. |
| * This is only ever called for files. |
| *@param fileName is the canonical file name. |
| *@param documentSpecification is the specification. |
| *@param pretendIndexable should be set to true if the document's contents would be fingerprinted as "indexable", |
| * or false otherwise. |
| *@return true if the file would be ingested given the parameters. |
| */ |
| protected boolean wouldFileBeIncluded(String fileName, Specification documentSpecification, |
| boolean pretendIndexable) |
| throws ManifoldCFException |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: In wouldFileBeIncluded for '"+fileName+"', pretendIndexable="+(pretendIndexable?"true":"false")); |
| |
| // This file was flagged as needing file data. However, that doesn't tell us *for what* we need it. |
| // So we need to redo the decision tree, but this time do everything completely. |
| |
| try |
| { |
| String pathPart; |
| String filePart; |
| boolean isDirectory = false; |
| |
| int lastSlash = fileName.lastIndexOf("/"); |
| if (lastSlash == -1) |
| { |
| pathPart = ""; |
| filePart = fileName; |
| } |
| else |
| { |
| pathPart = fileName.substring(0,lastSlash+1); |
| filePart = fileName.substring(lastSlash+1); |
| } |
| |
| // Scan until we match a startpoint |
| int i = 0; |
| while (i < documentSpecification.getChildCount()) |
| { |
| SpecificationNode sn = documentSpecification.getChild(i++); |
| if (sn.getType().equals(NODE_STARTPOINT)) |
| { |
| // Prepend the server URL to the path, since that's what pathpart will have. |
| String path = mapToIdentifier(sn.getAttributeValue(ATTRIBUTE_PATH)); |
| |
| // Compare with filename |
| int matchEnd = matchSubPath(path,pathPart); |
| if (matchEnd == -1) |
| { |
| continue; |
| } |
| |
| // matchEnd is the start of the rest of the path (after the match) in fileName. |
| // We need to walk through the rules and see whether it's in or out. |
| int j = 0; |
| while (j < sn.getChildCount()) |
| { |
| SpecificationNode node = sn.getChild(j++); |
| String flavor = node.getType(); |
| if (flavor.equals(NODE_INCLUDE) || flavor.equals(NODE_EXCLUDE)) |
| { |
| String type = node.getAttributeValue(ATTRIBUTE_TYPE); |
| if (type == null) |
| type = ""; |
| String indexable = node.getAttributeValue(ATTRIBUTE_INDEXABLE); |
| if (indexable == null) |
| indexable = ""; |
| String match = node.getAttributeValue(ATTRIBUTE_FILESPEC); |
| |
| // Check if there's a match against the filespec |
| boolean isMatch = checkMatch(fileName,matchEnd-1,match); |
| |
| // Check the directory/file criteria |
| if (isMatch) |
| { |
| isMatch = type.length() == 0 || |
| (type.equals(VALUE_DIRECTORY) && isDirectory) || |
| (type.equals(VALUE_FILE) && !isDirectory); |
| } |
| |
| // Check the indexable criteria |
| if (isMatch) |
| { |
| if (indexable.length() != 0) |
| { |
| // Directories are never considered indexable. |
| // But if this is not a directory, things become ambiguous. |
| boolean isIndexable; |
| if (isDirectory) |
| isIndexable = false; |
| else |
| { |
| // Evaluate the parts of being indexable that are based on the filename, mime type, and url |
| isIndexable = pretendIndexable; |
| } |
| |
| isMatch = (indexable.equals("yes") && isIndexable) || |
| (indexable.equals("no") && !isIndexable); |
| |
| |
| } |
| } |
| |
| if (isMatch) |
| { |
| if (flavor.equals(NODE_INCLUDE)) |
| return true; |
| else |
| return false; |
| } |
| } |
| } |
| |
| } |
| } |
| return false; |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| catch (UnknownHostException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| finally |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Leaving wouldFileBeIncluded for '"+fileName+"'"); |
| } |
| } |
| |
| /** Check to see whether we need the contents of the file for anything. We do this by assuming that |
| * the file is indexable, and assuming that it's not, and seeing if the same thing would happen. |
| *@param fileName is the name of the file. |
| *@param documentSpecification is the document specification. |
| *@return true if the file needs to be fingerprinted. |
| */ |
| protected boolean checkNeedFileData(String fileName, Specification documentSpecification) |
| throws ManifoldCFException |
| { |
| return wouldFileBeIncluded(fileName,documentSpecification,true) != wouldFileBeIncluded(fileName,documentSpecification,false); |
| } |
| |
| /** Check if a file should be ingested, given a document specification and a local copy of the |
| * file. It is presumed that only files that passed checkInclude() and were also flagged as needing |
| * file data by checkNeedFileData() will be checked by this method. |
| *@param localFile is the file. |
| *@param fileName is the JCIFS file name. |
| *@param documentSpecification is the specification. |
| *@param activities are the activities available to determine indexability. |
| *@return true if the file should be ingested. |
| */ |
| protected boolean checkIngest(File localFile, String fileName, Specification documentSpecification, IFingerprintActivity activities) |
| throws ManifoldCFException, ServiceInterruption |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: In checkIngest for '"+fileName+"'"); |
| |
| // This file was flagged as needing file data. However, that doesn't tell us *for what* we need it. |
| // So we need to redo the decision tree, but this time do everything completely. |
| |
| try |
| { |
| String pathPart; |
| String filePart; |
| boolean isDirectory = false; |
| |
| int lastSlash = fileName.lastIndexOf("/"); |
| if (lastSlash == -1) |
| { |
| pathPart = ""; |
| filePart = fileName; |
| } |
| else |
| { |
| pathPart = fileName.substring(0,lastSlash+1); |
| filePart = fileName.substring(lastSlash+1); |
| } |
| |
| // Scan until we match a startpoint |
| int i = 0; |
| while (i < documentSpecification.getChildCount()) |
| { |
| SpecificationNode sn = documentSpecification.getChild(i++); |
| if (sn.getType().equals(NODE_STARTPOINT)) |
| { |
| // Prepend the server URL to the path, since that's what pathpart will have. |
| String path = mapToIdentifier(sn.getAttributeValue(ATTRIBUTE_PATH)); |
| |
| // Compare with filename |
| int matchEnd = matchSubPath(path,pathPart); |
| if (matchEnd == -1) |
| { |
| continue; |
| } |
| |
| // matchEnd is the start of the rest of the path (after the match) in fileName. |
| // We need to walk through the rules and see whether it's in or out. |
| int j = 0; |
| while (j < sn.getChildCount()) |
| { |
| SpecificationNode node = sn.getChild(j++); |
| String flavor = node.getType(); |
| if (flavor.equals(NODE_INCLUDE) || flavor.equals(NODE_EXCLUDE)) |
| { |
| String type = node.getAttributeValue(ATTRIBUTE_TYPE); |
| if (type == null) |
| type = ""; |
| String indexable = node.getAttributeValue(ATTRIBUTE_INDEXABLE); |
| if (indexable == null) |
| indexable = ""; |
| String match = node.getAttributeValue(ATTRIBUTE_FILESPEC); |
| |
| // Check if there's a match against the filespec |
| boolean isMatch = checkMatch(fileName,matchEnd-1,match); |
| |
| // Check the directory/file criteria |
| if (isMatch) |
| { |
| isMatch = type.length() == 0 || |
| (type.equals(VALUE_DIRECTORY) && isDirectory) || |
| (type.equals(VALUE_FILE) && !isDirectory); |
| } |
| |
| // Check the indexable criteria |
| if (isMatch) |
| { |
| if (indexable.length() != 0) |
| { |
| // Directories are never considered indexable. |
| // But if this is not a directory, things become ambiguous. |
| boolean isIndexable; |
| if (isDirectory) |
| isIndexable = false; |
| else |
| { |
| isIndexable = activities.checkDocumentIndexable(localFile); |
| } |
| |
| isMatch = (indexable.equals("yes") && isIndexable) || |
| (indexable.equals("no") && !isIndexable); |
| |
| |
| } |
| } |
| |
| if (isMatch) |
| { |
| if (flavor.equals(NODE_INCLUDE)) |
| return true; |
| else |
| return false; |
| } |
| } |
| } |
| |
| } |
| } |
| return false; |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| catch (UnknownHostException e) |
| { |
| throw new ManifoldCFException("Couldn't map to canonical path: "+e.getMessage(),e); |
| } |
| finally |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Leaving checkIngest for '"+fileName+"'"); |
| } |
| |
| } |
| |
| /** Match a sub-path. The sub-path must match the complete starting part of the full path, in a path |
| * sense. The returned value should point into the file name beyond the end of the matched path, or |
| * be -1 if there is no match. |
| *@param subPath is the sub path. |
| *@param fullPath is the full path. |
| *@return the index of the start of the remaining part of the full path, or -1. |
| */ |
| protected static int matchSubPath(String subPath, String fullPath) |
| { |
| if (subPath.length() > fullPath.length()) |
| return -1; |
| if (fullPath.startsWith(subPath) == false) |
| return -1; |
| int rval = subPath.length(); |
| if (fullPath.length() == rval) |
| return rval; |
| char x = fullPath.charAt(rval); |
| if (x == File.separatorChar) |
| rval++; |
| return rval; |
| } |
| |
| /** Check a match between two strings with wildcards. |
| *@param sourceMatch is the expanded string (no wildcards) |
| *@param sourceIndex is the starting point in the expanded string. |
| *@param match is the wildcard-based string. |
| *@return true if there is a match. |
| */ |
| protected static boolean checkMatch(String sourceMatch, int sourceIndex, String match) |
| { |
| // Note: The java regex stuff looks pretty heavyweight for this purpose. |
| // I've opted to try and do a simple recursive version myself, which is not compiled. |
| // Basically, the match proceeds by recursive descent through the string, so that all *'s cause |
| // recursion. |
| boolean caseSensitive = false; |
| |
| return processCheck(caseSensitive, sourceMatch, sourceIndex, match, 0); |
| } |
| |
| /** Recursive worker method for checkMatch. Returns 'true' if there is a path that consumes both |
| * strings in their entirety in a matched way. |
| *@param caseSensitive is true if file names are case sensitive. |
| *@param sourceMatch is the source string (w/o wildcards) |
| *@param sourceIndex is the current point in the source string. |
| *@param match is the match string (w/wildcards) |
| *@param matchIndex is the current point in the match string. |
| *@return true if there is a match. |
| */ |
| protected static boolean processCheck(boolean caseSensitive, String sourceMatch, int sourceIndex, |
| String match, int matchIndex) |
| { |
| // Logging.connectors.debug("Matching '"+sourceMatch+"' position "+Integer.toString(sourceIndex)+ |
| // " against '"+match+"' position "+Integer.toString(matchIndex)); |
| |
| // Match up through the next * we encounter |
| while (true) |
| { |
| // If we've reached the end, it's a match. |
| if (sourceMatch.length() == sourceIndex && match.length() == matchIndex) |
| return true; |
| // If one has reached the end but the other hasn't, no match |
| if (match.length() == matchIndex) |
| return false; |
| if (sourceMatch.length() == sourceIndex) |
| { |
| if (match.charAt(matchIndex) != '*') |
| return false; |
| matchIndex++; |
| continue; |
| } |
| char x = sourceMatch.charAt(sourceIndex); |
| char y = match.charAt(matchIndex); |
| if (!caseSensitive) |
| { |
| if (x >= 'A' && x <= 'Z') |
| x -= 'A'-'a'; |
| if (y >= 'A' && y <= 'Z') |
| y -= 'A'-'a'; |
| } |
| if (y == '*') |
| { |
| // Wildcard! |
| // We will recurse at this point. |
| // Basically, we want to combine the results for leaving the "*" in the match string |
| // at this point and advancing the source index, with skipping the "*" and leaving the source |
| // string alone. |
| return processCheck(caseSensitive,sourceMatch,sourceIndex+1,match,matchIndex) || |
| processCheck(caseSensitive,sourceMatch,sourceIndex,match,matchIndex+1); |
| } |
| if (y == '?' || x == y) |
| { |
| sourceIndex++; |
| matchIndex++; |
| } |
| else |
| return false; |
| } |
| } |
| |
| /** Grab forced acl out of document specification. |
| *@param spec is the document specification. |
| *@return the acls. |
| */ |
| protected static String[] getForcedAcls(Specification spec) |
| { |
| HashMap map = new HashMap(); |
| int i = 0; |
| boolean securityOn = true; |
| while (i < spec.getChildCount()) |
| { |
| SpecificationNode sn = spec.getChild(i++); |
| if (sn.getType().equals(NODE_ACCESS)) |
| { |
| String token = sn.getAttributeValue(ATTRIBUTE_TOKEN); |
| map.put(token,token); |
| } |
| else if (sn.getType().equals(NODE_SECURITY)) |
| { |
| String value = sn.getAttributeValue(ATTRIBUTE_VALUE); |
| if (value.equals("on")) |
| securityOn = true; |
| else if (value.equals("off")) |
| securityOn = false; |
| } |
| } |
| if (!securityOn) |
| return null; |
| |
| String[] rval = new String[map.size()]; |
| Iterator iter = map.keySet().iterator(); |
| i = 0; |
| while (iter.hasNext()) |
| { |
| rval[i++] = (String)iter.next(); |
| } |
| return rval; |
| } |
| |
| /** Grab forced share acls out of document specification. |
| *@param spec is the document specification. |
| *@return the acls. |
| */ |
| protected static String[] getForcedShareAcls(Specification spec) |
| { |
| HashMap map = new HashMap(); |
| int i = 0; |
| boolean securityOn = true; |
| while (i < spec.getChildCount()) |
| { |
| SpecificationNode sn = spec.getChild(i++); |
| if (sn.getType().equals(NODE_SHAREACCESS)) |
| { |
| String token = sn.getAttributeValue(ATTRIBUTE_TOKEN); |
| map.put(token,token); |
| } |
| else if (sn.getType().equals(NODE_SHARESECURITY)) |
| { |
| String value = sn.getAttributeValue(ATTRIBUTE_VALUE); |
| if (value.equals("on")) |
| securityOn = true; |
| else if (value.equals("off")) |
| securityOn = false; |
| } |
| } |
| if (!securityOn) |
| return null; |
| String[] rval = new String[map.size()]; |
| Iterator iter = map.keySet().iterator(); |
| i = 0; |
| while (iter.hasNext()) |
| { |
| rval[i++] = (String)iter.next(); |
| } |
| return rval; |
| } |
| |
| /** Grab forced parent folder acls out of document specification. |
| *@param spec is the document specification. |
| *@return the acls. |
| */ |
| protected static String[] getForcedParentFolderAcls(Specification spec) |
| { |
| HashMap map = new HashMap(); |
| int i = 0; |
| boolean securityOn = false; |
| while (i < spec.getChildCount()) |
| { |
| SpecificationNode sn = spec.getChild(i++); |
| if (sn.getType().equals(NODE_PARENTFOLDERACCESS)) |
| { |
| String token = sn.getAttributeValue(ATTRIBUTE_TOKEN); |
| map.put(token,token); |
| } |
| else if (sn.getType().equals(NODE_PARENTFOLDERSECURITY)) |
| { |
| String value = sn.getAttributeValue(ATTRIBUTE_VALUE); |
| if (value.equals("on")) |
| securityOn = true; |
| else if (value.equals("off")) |
| securityOn = false; |
| } |
| } |
| if (!securityOn) |
| return null; |
| String[] rval = new String[map.size()]; |
| Iterator iter = map.keySet().iterator(); |
| i = 0; |
| while (iter.hasNext()) |
| { |
| rval[i++] = (String)iter.next(); |
| } |
| return rval; |
| } |
| |
| /** Map a "path" specification to a full identifier. |
| */ |
| protected String mapToIdentifier(String path) |
| throws MalformedURLException, UnknownHostException |
| { |
| String smburi = smbconnectionPath; |
| String uri = smburi + path + "/"; |
| return getFileCanonicalPath(new SmbFile(uri,SingletonContext.getInstance().withCredentials(pa))); |
| } |
| |
| // These methods allow me to experiment with cluster-mandated error handling on an entirely local level. They correspond to individual SMBFile methods. |
| |
| /** Get canonical path */ |
| protected static String getFileCanonicalPath(SmbFile file) |
| { |
| return file.getCanonicalPath(); |
| } |
| |
| /** Check for file/directory existence */ |
| protected static boolean fileExists(SmbFile file) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.exists(); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while checking if file exists: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Check if file is a directory */ |
| protected static boolean fileIsDirectory(SmbFile file) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.isDirectory(); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while seeing if file is a directory: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get last modified date for file */ |
| protected static long fileLastModified(SmbFile file) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.lastModified(); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting file last-modified date: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get file length */ |
| protected static long fileLength(SmbFile file) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.length(); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting file length: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** List files */ |
| protected static SmbFile[] fileListFiles(SmbFile file, SmbFileFilter filter) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.listFiles(filter); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| if (e.getMessage().equals("0x8000002D")) { |
| // Symlink |
| Logging.connectors.warn("JCIFS: Symlink detected: "+file); |
| return new SmbFile[0]; |
| } |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while listing files: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get input stream for file */ |
| protected static InputStream getFileInputStream(SmbFile file) |
| throws IOException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| IOException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.getInputStream(); |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| throw e; |
| } |
| catch (InterruptedIOException e) |
| { |
| throw e; |
| } |
| catch (IOException e) |
| { |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting file input stream: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentIOExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get file security */ |
| protected static ACE[] getFileSecurity(SmbFile file, boolean useSIDs) |
| throws IOException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| IOException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.getSecurity(!useSIDs); |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| throw e; |
| } |
| catch (InterruptedIOException e) |
| { |
| throw e; |
| } |
| catch (IOException e) |
| { |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting file security: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentIOExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get share security */ |
| protected static ACE[] getFileShareSecurity(SmbFile file, boolean useSIDs) |
| throws IOException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| IOException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.getShareSecurity(!useSIDs); |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| throw e; |
| } |
| catch (InterruptedIOException e) |
| { |
| throw e; |
| } |
| catch (IOException e) |
| { |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting share security: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentIOExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Get file type */ |
| protected static int getFileType(SmbFile file) |
| throws SmbException |
| { |
| int totalTries = 0; |
| int retriesRemaining = 3; |
| SmbException currentException = null; |
| while (retriesRemaining > 0 && totalTries < 5) |
| { |
| retriesRemaining--; |
| totalTries++; |
| try |
| { |
| return file.getType(); |
| } |
| catch (SmbException e) |
| { |
| // If it's an interruption, throw it right away. |
| Throwable cause = e.getRootCause(); |
| if (cause != null && (cause instanceof jcifs.util.transport.TransportException)) |
| { |
| // See if it's an interruption |
| jcifs.util.transport.TransportException te = (jcifs.util.transport.TransportException)cause; |
| if (te.getRootCause() != null && te.getRootCause() instanceof java.lang.InterruptedException) |
| throw e; |
| } |
| |
| Logging.connectors.warn("JCIFS: Possibly transient exception detected on attempt "+Integer.toString(totalTries)+" while getting file type: "+e.getMessage(),e); |
| if (currentException != null) |
| { |
| // Compare exceptions. If they differ, reset the retry count. |
| if (!equivalentSmbExceptions(currentException,e)) |
| retriesRemaining = 3; |
| } |
| currentException = e; |
| } |
| } |
| throw currentException; |
| } |
| |
| /** Check if two SmbExceptions are equivalent */ |
| protected static boolean equivalentSmbExceptions(SmbException e1, SmbException e2) |
| { |
| // The thing we want to compare is the message. This is a little risky in that if there are (for example) object addresses in the message, the comparison will always fail. |
| // However, I don't think we expect any such thing in this case. |
| String e1m = e1.getMessage(); |
| String e2m = e2.getMessage(); |
| if (e1m == null) |
| e1m = ""; |
| if (e2m == null) |
| e2m = ""; |
| return e1m.equals(e2m); |
| } |
| |
| /** Check if two IOExceptions are equivalent */ |
| protected static boolean equivalentIOExceptions(IOException e1, IOException e2) |
| { |
| // The thing we want to compare is the message. This is a little risky in that if there are (for example) object addresses in the message, the comparison will always fail. |
| // However, I don't think we expect any such thing in this case. |
| String e1m = e1.getMessage(); |
| String e2m = e2.getMessage(); |
| if (e1m == null) |
| e1m = ""; |
| if (e2m == null) |
| e2m = ""; |
| return e1m.equals(e2m); |
| } |
| |
| // UI support methods. |
| // |
| // These support methods come in two varieties. The first bunch is involved in setting up connection configuration information. The second bunch |
| // is involved in presenting and editing document specification information for a job. The two kinds of methods are accordingly treated differently, |
| // in that the first bunch cannot assume that the current connector object is connected, while the second bunch can. That is why the first bunch |
| // receives a thread context argument for all UI methods, while the second bunch does not need one (since it has already been applied via the connect() |
| // method, above). |
| |
| /** 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 |
| { |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.Server")); |
| out.print( |
| "<script type=\"text/javascript\">\n"+ |
| "<!--\n"+ |
| "function checkConfigForSave()\n"+ |
| "{\n"+ |
| " if (editconnection.server.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.NeedAServerName") + "\");\n"+ |
| " SelectTab(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.Server2") + "\");\n"+ |
| " editconnection.server.focus();\n"+ |
| " return false;\n"+ |
| " }\n"+ |
| "\n"+ |
| " if (editconnection.server.value.indexOf(\"/\") != -1)\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.ServerNameCannotIncludePathInformation") + "\");\n"+ |
| " SelectTab(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.Server2") + "\");\n"+ |
| " editconnection.server.focus();\n"+ |
| " return false;\n"+ |
| " }\n"+ |
| " \n"+ |
| " if (editconnection.username.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.NeedAUserName") + "\");\n"+ |
| " SelectTab(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.Server2") + "\");\n"+ |
| " editconnection.username.focus();\n"+ |
| " return false;\n"+ |
| " }\n"+ |
| "\n"+ |
| " return true;\n"+ |
| "}\n"+ |
| "\n"+ |
| "//-->\n"+ |
| "</script>\n" |
| ); |
| } |
| |
| /** Output the configuration body section. |
| * This method is called in the body section of the connector's configuration page. Its purpose is to present the required form elements for editing. |
| * The coder can presume that the HTML that is output from this configuration will be within appropriate <html>, <body>, and <form> tags. The name of the |
| * form is "editconnection". |
| *@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 tabName is the current tab name. |
| */ |
| @Override |
| public void outputConfigurationBody(IThreadContext threadContext, IHTTPOutput out, |
| Locale locale, ConfigParams parameters, String tabName) |
| throws ManifoldCFException, IOException |
| { |
| String server = parameters.getParameter(SharedDriveParameters.server); |
| if (server==null) server = ""; |
| String domain = parameters.getParameter(SharedDriveParameters.domain); |
| if (domain==null) domain = ""; |
| String username = parameters.getParameter(SharedDriveParameters.username); |
| if (username==null) username = ""; |
| String password = parameters.getObfuscatedParameter(SharedDriveParameters.password); |
| if (password==null) |
| password = ""; |
| else |
| password = out.mapPasswordToKey(password); |
| String resolvesids = parameters.getParameter(SharedDriveParameters.useSIDs); |
| if (resolvesids==null) resolvesids = "true"; |
| String binName = parameters.getParameter(SharedDriveParameters.binName); |
| if (binName == null) binName = ""; |
| |
| // "Server" tab |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.Server"))) |
| { |
| out.print( |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.Server3") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"text\" size=\"32\" name=\"server\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(server)+"\"/></td>\n"+ |
| " </tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.AuthenticationDomain") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"text\" size=\"32\" name=\"domain\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(domain)+"\"/></td>\n"+ |
| " </tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.UserName") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"text\" size=\"32\" name=\"username\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(username)+"\"/></td>\n"+ |
| " </tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.Password") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"password\" size=\"32\" name=\"password\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(password)+"\"/></td>\n"+ |
| " </tr>\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.UseSIDSForSecurity") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"hidden\" name=\"resolvesidspresent\" value=\"true\"/><input type=\"checkbox\" value=\"true\" name=\"resolvesids\" "+("true".equals(resolvesids)?"checked=\"true\"":"")+"/></td>\n"+ |
| " </tr>\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.BinName") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"text\" size=\"32\" name=\"binname\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(binName)+"\"/></td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\"server\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(server)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\"domain\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(domain)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\"username\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(username)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\"password\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(password)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\"resolvesidspresent\" value=\"true\"/>\n"+ |
| "<input type=\"hidden\" name=\"resolvesids\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(resolvesids)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\"binname\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(binName)+"\"/>\n" |
| ); |
| } |
| } |
| |
| /** 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, |
| Locale locale, ConfigParams parameters) |
| throws ManifoldCFException |
| { |
| String server = variableContext.getParameter("server"); |
| if (server != null) |
| parameters.setParameter(SharedDriveParameters.server,server); |
| |
| String domain = variableContext.getParameter("domain"); |
| if (domain != null) |
| parameters.setParameter(SharedDriveParameters.domain,domain); |
| |
| String username = variableContext.getParameter("username"); |
| if (username != null) |
| parameters.setParameter(SharedDriveParameters.username,username); |
| |
| String password = variableContext.getParameter("password"); |
| if (password != null) |
| parameters.setObfuscatedParameter(SharedDriveParameters.password,variableContext.mapKeyToPassword(password)); |
| |
| String resolvesidspresent = variableContext.getParameter("resolvesidspresent"); |
| if (resolvesidspresent != null) |
| { |
| parameters.setParameter(SharedDriveParameters.useSIDs,"false"); |
| String resolvesids = variableContext.getParameter("resolvesids"); |
| if (resolvesids != null) |
| parameters.setParameter(SharedDriveParameters.useSIDs, resolvesids); |
| } |
| String binName = variableContext.getParameter("binname"); |
| if (binName != null) |
| parameters.setParameter(SharedDriveParameters.binName, binName); |
| |
| return null; |
| } |
| |
| /** 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 |
| { |
| out.print( |
| "<table class=\"displaytable\">\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\" colspan=\"1\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.Parameters") + "</nobr></td>\n"+ |
| " <td class=\"value\" colspan=\"3\">\n" |
| ); |
| Iterator iter = parameters.listParameters(); |
| while (iter.hasNext()) |
| { |
| String param = (String)iter.next(); |
| String value = parameters.getParameter(param); |
| if (param.length() >= "password".length() && param.substring(param.length()-"password".length()).equalsIgnoreCase("password")) |
| { |
| out.print( |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(param)+"=********</nobr><br/>\n" |
| ); |
| } |
| else if (param.length() >="keystore".length() && param.substring(param.length()-"keystore".length()).equalsIgnoreCase("keystore")) |
| { |
| IKeystoreManager kmanager = KeystoreManagerFactory.make("",value); |
| out.print( |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(param)+"=<"+Integer.toString(kmanager.getContents().length)+ Messages.getBodyString(locale,"SharedDriveConnector.certificate") + "></nobr><br/>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(param)+"="+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(value)+"</nobr><br/>\n" |
| ); |
| } |
| } |
| out.print( |
| " </td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| |
| /** Output the specification header section. |
| * This method is called in the head section of a job page which has selected a repository connection of the |
| * current type. Its purpose is to add the required tabs to the list, and to output any javascript methods |
| * that might be needed by the job editing HTML. |
| * The connector will be connected before this method can be called. |
| *@param out is the output to which any HTML should be sent. |
| *@param locale is the locale the output is preferred to be in. |
| *@param ds is the current document specification for this job. |
| *@param connectionSequenceNumber is the unique number of this connection within the job. |
| *@param tabsArray is an array of tab names. Add to this array any tab names that are specific to the connector. |
| */ |
| @Override |
| public void outputSpecificationHeader(IHTTPOutput out, Locale locale, Specification ds, |
| int connectionSequenceNumber, List<String> tabsArray) |
| throws ManifoldCFException, IOException |
| { |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.Paths")); |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.Security")); |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.Metadata")); |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.ContentLength")); |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.FileMapping")); |
| tabsArray.add(Messages.getString(locale,"SharedDriveConnector.URLMapping")); |
| String seqPrefix = "s"+connectionSequenceNumber+"_"; |
| |
| out.print( |
| "<script type=\"text/javascript\">\n"+ |
| "//<!--\n"+ |
| "\n"+ |
| "function "+seqPrefix+"checkSpecification()\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"specmaxlength.value != \"\" && !isInteger(editjob."+seqPrefix+"specmaxlength.value))\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.NeedAValidNumberForMaximumDocumentLength") + "\");\n"+ |
| " editjob."+seqPrefix+"specmaxlength.focus();\n"+ |
| " return false;\n"+ |
| " }\n"+ |
| " return true;\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecOp(n, opValue, anchorvalue)\n"+ |
| "{\n"+ |
| " eval(\"editjob.\"+n+\".value = \\\"\"+opValue+\"\\\"\");\n"+ |
| " postFormSetAnchor(anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddToPath(anchorvalue)\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"pathaddon.value == \"\" && editjob."+seqPrefix+"pathtypein.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.SelectAFolderOrTypeInAPathFirst") + "\");\n"+ |
| " editjob."+seqPrefix+"pathaddon.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " if (editjob."+seqPrefix+"pathaddon.value != \"\" && editjob."+seqPrefix+"pathtypein.value != \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.EitherSelectAFolderORTypeInAPath") + "\");\n"+ |
| " editjob."+seqPrefix+"pathaddon.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"pathop\",\"AddToPath\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddSpec(suffix,anchorvalue)\n"+ |
| "{\n"+ |
| " if (eval(\"editjob."+seqPrefix+"specfile\"+suffix+\".value\") == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.EnterAFileSpecificationFirst") + "\");\n"+ |
| " eval(\"editjob."+seqPrefix+"specfile\"+suffix+\".focus()\");\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"pathop\"+suffix,\"Add\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecInsertSpec(postfix,anchorvalue)\n"+ |
| "{\n"+ |
| " if (eval(\"editjob."+seqPrefix+"specfile_i\"+postfix+\".value\") == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.EnterAFileSpecificationFirst") + "\");\n"+ |
| " eval(\"editjob."+seqPrefix+"specfile_i\"+postfix+\".focus()\");\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"specop\"+postfix,\"Insert Here\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddToken(anchorvalue)\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"spectoken.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.NullAccessTokensNotAllowed") + "\");\n"+ |
| " editjob."+seqPrefix+"spectoken.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"accessop\",\"Add\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddMapping(anchorvalue)\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"specmatch.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringCannotBeEmpty") + "\");\n"+ |
| " editjob."+seqPrefix+"specmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " if (!isRegularExpression(editjob."+seqPrefix+"specmatch.value))\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringMustBeValidRegularExpression") + "\");\n"+ |
| " editjob."+seqPrefix+"specmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"specmappingop\",\"Add\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddFMap(anchorvalue)\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"specfmapmatch.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringCannotBeEmpty") + "\");\n"+ |
| " editjob."+seqPrefix+"specfmapmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " if (!isRegularExpression(editjob."+seqPrefix+"specfmapmatch.value))\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringMustBeValidRegularExpression") + "\");\n"+ |
| " editjob."+seqPrefix+"specfmapmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"specfmapop\",\"Add\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "function "+seqPrefix+"SpecAddUMap(anchorvalue)\n"+ |
| "{\n"+ |
| " if (editjob."+seqPrefix+"specumapmatch.value == \"\")\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringCannotBeEmpty") + "\");\n"+ |
| " editjob."+seqPrefix+"specumapmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " if (!isRegularExpression(editjob."+seqPrefix+"specumapmatch.value))\n"+ |
| " {\n"+ |
| " alert(\"" + Messages.getBodyJavascriptString(locale,"SharedDriveConnector.MatchStringMustBeValidRegularExpression") + "\");\n"+ |
| " editjob."+seqPrefix+"specumapmatch.focus();\n"+ |
| " return;\n"+ |
| " }\n"+ |
| " "+seqPrefix+"SpecOp(\""+seqPrefix+"specumapop\",\"Add\",anchorvalue);\n"+ |
| "}\n"+ |
| "\n"+ |
| "//-->\n"+ |
| "</script>\n" |
| ); |
| } |
| |
| /** Output the specification body section. |
| * This method is called in the body section of a job page which has selected a repository connection of the |
| * current type. Its purpose is to present the required form elements for editing. |
| * The coder can presume that the HTML that is output from this configuration will be within appropriate |
| * <html>, <body>, and <form> tags. The name of the form is always "editjob". |
| * The connector will be connected before this method can be called. |
| *@param out is the output to which any HTML should be sent. |
| *@param locale is the locale the output is preferred to be in. |
| *@param ds is the current document specification for this job. |
| *@param connectionSequenceNumber is the unique number of this connection within the job. |
| *@param actualSequenceNumber is the connection within the job that has currently been selected. |
| *@param tabName is the current tab name. (actualSequenceNumber, tabName) form a unique tuple within |
| * the job. |
| */ |
| @Override |
| public void outputSpecificationBody(IHTTPOutput out, Locale locale, Specification ds, |
| int connectionSequenceNumber, int actualSequenceNumber, String tabName) |
| throws ManifoldCFException, IOException |
| { |
| String seqPrefix = "s"+connectionSequenceNumber+"_"; |
| |
| int i; |
| int k; |
| |
| // "Content Length" tab |
| i = 0; |
| String maxLength = null; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_MAXLENGTH)) |
| maxLength = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| } |
| if (maxLength == null) |
| maxLength = ""; |
| |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.ContentLength")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.MaximumDocumentLength") + "</nobr></td>\n"+ |
| " <td class=\"value\"><input type=\"text\" name=\""+seqPrefix+"specmaxlength\" size=\"10\" value=\""+maxLength+"\"/></td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specmaxlength\" value=\""+maxLength+"\"/>\n" |
| ); |
| } |
| |
| // Check for Paths tab |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.Paths")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n" |
| ); |
| // Now, loop through paths. There will be a row in the current table for each one. |
| // The row will contain a delete button on the left. On the right will be the startpoint itself at the top, |
| // and underneath it the table where the filter criteria are edited. |
| i = 0; |
| k = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT)) |
| { |
| String pathDescription = "_"+Integer.toString(k); |
| String pathOpName = seqPrefix+"pathop"+pathDescription; |
| String startPath = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <a name=\""+seqPrefix+"path_"+Integer.toString(k)+"\">\n"+ |
| " <input type=\"button\" value=\"Delete\" alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeletePath")+Integer.toString(k)+"\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+pathOpName+"\",\"Delete\",\""+seqPrefix+"path_"+Integer.toString(k)+"\")'/>\n"+ |
| " </a> \n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <table class=\"displaytable\">\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specpath"+pathDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH))+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+pathOpName+"\" value=\"\"/>\n"+ |
| " <nobr>"+((startPath.length() == 0)?"(root)":org.apache.manifoldcf.ui.util.Encoder.bodyEscape(startPath))+"</nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"boxcell\">\n"+ |
| " <table class=\"displaytable\">\n" |
| ); |
| // Now go through the include/exclude children of this node, and display one line per node, followed |
| // an "add" line. |
| int j = 0; |
| while (j < sn.getChildCount()) |
| { |
| SpecificationNode excludeNode = sn.getChild(j); |
| String instanceDescription = "_"+Integer.toString(k)+"_"+Integer.toString(j); |
| String instanceOpName = seqPrefix + "specop" + instanceDescription; |
| |
| String nodeFlavor = excludeNode.getType(); |
| String nodeType = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE); |
| if (nodeType == null) |
| nodeType = ""; |
| String filespec = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC); |
| String indexable = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE); |
| if (indexable == null) |
| indexable = ""; |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"button\" value=\"Insert\" onClick='Javascript:"+seqPrefix+"SpecInsertSpec(\""+instanceDescription+"\",\""+seqPrefix+"filespec_"+Integer.toString(k)+"_"+Integer.toString(j+1)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.InsertNewMatchForPath")+Integer.toString(k)+" before position #"+Integer.toString(j)+"\"/>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <select name=\""+seqPrefix+"specfl_i"+instanceDescription+"\">\n"+ |
| " <option value=\"include\">" + Messages.getBodyString(locale,"SharedDriveConnector.Include") + "</option>\n"+ |
| " <option value=\"exclude\">" + Messages.getBodyString(locale,"SharedDriveConnector.Exclude") + "</option>\n"+ |
| " </select> \n"+ |
| " <select name=\""+seqPrefix+"spectin_i"+instanceDescription+"\">\n"+ |
| " <option value=\"\" selected=\"selected\">" + Messages.getBodyString(locale,"SharedDriveConnector.AnyFileOrDirectory") + "</option>\n"+ |
| " <option value=\"file\">" + Messages.getBodyString(locale,"SharedDriveConnector.files") + "</option>\n"+ |
| " <option value=\"indexable-file\">" + Messages.getBodyString(locale,"SharedDriveConnector.indexableFiles") + "</option>\n"+ |
| " <option value=\"unindexable-file\">" + Messages.getBodyString(locale,"SharedDriveConnector.unindexableFiles") + "</option>\n"+ |
| " <option value=\"directory\">" + Messages.getBodyString(locale,"SharedDriveConnector.directorys") + "</option>\n"+ |
| " </select> " + Messages.getBodyString(locale,"SharedDriveConnector.matching") + " \n"+ |
| " <input type=\"text\" size=\"20\" name=\""+seqPrefix+"specfile_i"+instanceDescription+"\" value=\"\"/>\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| "\n"+ |
| " </tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <a name=\""+seqPrefix+"filespec_"+Integer.toString(k)+"_"+Integer.toString(j)+"\">\n"+ |
| " <input type=\"button\" value=\"Delete\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+instanceOpName+"\",\"Delete\",\""+seqPrefix+"filespec_"+Integer.toString(k)+"_"+Integer.toString(j)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeletePath")+Integer.toString(k)+Messages.getAttributeString(locale,"SharedDriveConnector.matchSpec")+Integer.toString(j)+"\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <input type=\"hidden\" name=\""+instanceOpName+"\" value=\"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specfl"+instanceDescription+"\" value=\""+nodeFlavor+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specty"+instanceDescription+"\" value=\""+nodeType+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specin"+instanceDescription+"\" value=\""+indexable+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specfile"+instanceDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(filespec)+"\"/>\n"+ |
| " "+Integer.toString(j+1)+". "+(nodeFlavor.equals("include")?"Include":"")+""+(nodeFlavor.equals("exclude")?"Exclude":"")+""+(indexable.equals("yes")?" indexable":"")+""+(indexable.equals("no")?" un-indexable":"")+""+(nodeType.equals("file")?" file(s)":"")+""+(nodeType.equals("directory")?" directory(s)":"")+""+(nodeType.equals("")?" file(s) or directory(s)":"")+" matching "+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(filespec)+"\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| j++; |
| } |
| if (j == 0) |
| { |
| out.print( |
| " <tr><td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoRulesDefined") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specchildcount"+pathDescription+"\" value=\""+Integer.toString(j)+"\"/>\n"+ |
| " <a name=\""+seqPrefix+"filespec_"+Integer.toString(k)+"_"+Integer.toString(j)+"\">\n"+ |
| " <input type=\"button\" value=\"Add\" onClick='Javascript:"+seqPrefix+"SpecAddSpec(\""+pathDescription+"\",\""+seqPrefix+"filespec_"+Integer.toString(k)+"_"+Integer.toString(j+1)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.AddNewMatchForPath")+Integer.toString(k)+"\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <select name=\""+seqPrefix+"specfl"+pathDescription+"\">\n"+ |
| " <option value=\"include\">" + Messages.getBodyString(locale,"SharedDriveConnector.Include") + "</option>\n"+ |
| " <option value=\"exclude\">" + Messages.getBodyString(locale,"SharedDriveConnector.Exclude") + "</option>\n"+ |
| " </select> \n"+ |
| " <select name=\""+seqPrefix+"spectin"+pathDescription+"\">\n"+ |
| " <option value=\"\">" + Messages.getBodyString(locale,"SharedDriveConnector.AnyFileOrDirectory") + "</option>\n"+ |
| " <option value=\"file\">" + Messages.getBodyString(locale,"SharedDriveConnector.files") + "</option>\n"+ |
| " <option value=\"indexable-file\">" + Messages.getBodyString(locale,"SharedDriveConnector.indexableFiles") + "</option>\n"+ |
| " <option value=\"unindexable-file\">" + Messages.getBodyString(locale,"SharedDriveConnector.unindexableFiles") + "</option>\n"+ |
| " <option value=\"directory\">" + Messages.getBodyString(locale,"SharedDriveConnector.directorys") + "</option>\n"+ |
| " </select> " + Messages.getBodyString(locale,"SharedDriveConnector.matching") + " \n"+ |
| " <input type=\"text\" size=\"20\" name=\""+seqPrefix+"specfile"+pathDescription+"\" value=\"\"/>\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| " </table>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| " </table>\n"+ |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| k++; |
| } |
| } |
| if (k == 0) |
| { |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoStartingPointsDefined") + "</td>\n"+ |
| " </tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\" colspan=\"2\">\n"+ |
| " <nobr>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"pathcount\" value=\""+Integer.toString(k)+"\"/>\n"+ |
| " <a name=\""+seqPrefix+"path_"+Integer.toString(k)+"\">\n" |
| ); |
| |
| String pathSoFar = (String)currentContext.get(seqPrefix+"specpath"); |
| if (pathSoFar == null) |
| pathSoFar = ""; |
| |
| // Grab next folder/project list |
| try |
| { |
| String[] childList; |
| childList = getChildFolderNames(pathSoFar); |
| if (childList == null) |
| { |
| // Illegal path - set it back |
| pathSoFar = ""; |
| childList = getChildFolderNames(""); |
| if (childList == null) |
| throw new ManifoldCFException("Can't find any children for root folder"); |
| } |
| out.print( |
| " <input type=\"hidden\" name=\""+seqPrefix+"specpath\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(pathSoFar)+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"pathop\" value=\"\"/>\n"+ |
| " <input type=\"button\" value=\"Add\" alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddPath") + "\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+seqPrefix+"pathop\",\"Add\",\""+seqPrefix+"path_"+Integer.toString(k+1)+"\")'/>\n"+ |
| " "+((pathSoFar.length()==0)?"(root)":org.apache.manifoldcf.ui.util.Encoder.bodyEscape(pathSoFar))+"\n" |
| ); |
| if (pathSoFar.length() > 0) |
| { |
| out.print( |
| " <input type=\"button\" value=\"-\" alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.RemoveFromPath") + "\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+seqPrefix+"pathop\",\"Up\",\""+seqPrefix+"path_"+Integer.toString(k)+"\")'/>\n" |
| ); |
| } |
| if (childList.length > 0) |
| { |
| out.print( |
| " <nobr>\n"+ |
| " <input type=\"button\" value=\"+\" alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddPath") + "\" onClick='Javascript:"+seqPrefix+"SpecAddToPath(\""+seqPrefix+"path_"+Integer.toString(k)+"\")'/> \n"+ |
| " <select name=\""+seqPrefix+"pathaddon\">\n"+ |
| " <option value=\"\" selected=\"selected\">" + Messages.getBodyString(locale,"SharedDriveConnector.PickAFolder") + "</option>\n" |
| ); |
| int j = 0; |
| while (j < childList.length) |
| { |
| String folder = org.apache.manifoldcf.ui.util.Encoder.attributeEscape(childList[j]); |
| out.print( |
| " <option value=\""+folder+"\">"+folder+"</option>\n" |
| ); |
| j++; |
| } |
| out.print( |
| " </select>" + Messages.getBodyString(locale,"SharedDriveConnector.orTypeAPath") + |
| " <input type=\"text\" name=\""+seqPrefix+"pathtypein\" size=\"16\" value=\"\"/>\n"+ |
| " </nobr>\n" |
| ); |
| } |
| } |
| catch (ManifoldCFException e) |
| { |
| e.printStackTrace(); |
| out.println(org.apache.manifoldcf.ui.util.Encoder.bodyEscape(e.getMessage())); |
| } |
| out.print( |
| " </a>\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| // Generate hiddens for the pathspec tab |
| i = 0; |
| k = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT)) |
| { |
| String pathDescription = "_"+Integer.toString(k); |
| String startPath = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH); |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specpath"+pathDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(startPath)+"\"/>\n" |
| ); |
| // Now go through the include/exclude children of this node. |
| int j = 0; |
| while (j < sn.getChildCount()) |
| { |
| SpecificationNode excludeNode = sn.getChild(j); |
| String instanceDescription = "_"+Integer.toString(k)+"_"+Integer.toString(j); |
| |
| String nodeFlavor = excludeNode.getType(); |
| String nodeType = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE); |
| if (nodeType == null) |
| nodeType = ""; |
| String filespec = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC); |
| String indexable = excludeNode.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE); |
| if (indexable == null) |
| indexable = ""; |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfl"+instanceDescription+"\" value=\""+nodeFlavor+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specty"+instanceDescription+"\" value=\""+nodeType+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specin"+instanceDescription+"\" value=\""+indexable+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfile"+instanceDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(filespec)+"\"/>\n" |
| ); |
| j++; |
| } |
| k++; |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specchildcount"+pathDescription+"\" value=\""+Integer.toString(j)+"\"/>\n" |
| ); |
| } |
| } |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"pathcount\" value=\""+Integer.toString(k)+"\"/>\n" |
| ); |
| } |
| |
| |
| // Security tab |
| |
| // Find whether security is on or off |
| i = 0; |
| boolean securityOn = true; |
| boolean shareSecurityOn = true; |
| boolean parentFolderSecurityOn = false; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| securityOn = false; |
| else if (securityValue.equals("on")) |
| securityOn = true; |
| } |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SHARESECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| shareSecurityOn = false; |
| else if (securityValue.equals("on")) |
| shareSecurityOn = true; |
| } |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PARENTFOLDERSECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| parentFolderSecurityOn = false; |
| else if (securityValue.equals("on")) |
| parentFolderSecurityOn = true; |
| } |
| } |
| |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.Security")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.FileSecurity") + "</nobr></td>\n"+ |
| " <td colspan=\"3\" class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specsecurity\" value=\"on\" "+(securityOn?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Enabled") + " \n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specsecurity\" value=\"off\" "+((securityOn==false)?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Disabled") + "\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n" |
| ); |
| // Finally, go through forced ACL |
| i = 0; |
| k = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS)) |
| { |
| String accessDescription = "_"+Integer.toString(k); |
| String accessOpName = seqPrefix+"accessop"+accessDescription; |
| String token = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TOKEN); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"description\" colspan=\"1\">\n"+ |
| " <input type=\"hidden\" name=\""+accessOpName+"\" value=\"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"spectoken"+accessDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(token)+"\"/>\n"+ |
| " <a name=\""+seqPrefix+"token_"+Integer.toString(k)+"\">\n"+ |
| " <input type=\"button\" value=\"Delete\" alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeleteToken")+Integer.toString(k)+"\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+accessOpName+"\",\"Delete\",\""+seqPrefix+"token_"+Integer.toString(k)+"\")'/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\" colspan=\"3\">\n"+ |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(token)+"</nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| k++; |
| } |
| } |
| if (k == 0) |
| { |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"message\" colspan=\"4\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoFileAccessTokensPresent") + "</td>\n"+ |
| " </tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\" colspan=\"1\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"tokencount\" value=\""+Integer.toString(k)+"\"/>\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"accessop\" value=\"\"/>\n"+ |
| " <a name=\""+seqPrefix+"token_"+Integer.toString(k)+"\">\n"+ |
| " <input type=\"button\" value=\"Add\" alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddToken") + "\" onClick='Javascript:"+seqPrefix+"SpecAddToken(\""+seqPrefix+"token_"+Integer.toString(k+1)+"\")'/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\" colspan=\"3\">\n"+ |
| " <nobr><input type=\"text\" size=\"30\" name=\""+seqPrefix+"spectoken\" value=\"\"/></nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.ShareSecurity") + "</nobr></td>\n"+ |
| " <td colspan=\"3\" class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specsharesecurity\" value=\"on\" "+(shareSecurityOn?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Enabled") + " \n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specsharesecurity\" value=\"off\" "+((shareSecurityOn==false)?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Disabled") + "\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.ParentFolderSecurity") + "</nobr></td>\n"+ |
| " <td colspan=\"3\" class=\"value\">\n"+ |
| " <nobr>\n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specparentfoldersecurity\" value=\"on\" "+(parentFolderSecurityOn?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Enabled") + " \n"+ |
| " <input type=\"radio\" name=\""+seqPrefix+"specparentfoldersecurity\" value=\"off\" "+((parentFolderSecurityOn==false)?"checked=\"true\"":"")+" />" + Messages.getBodyString(locale,"SharedDriveConnector.Disabled") + "\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specsecurity\" value=\""+(securityOn?"on":"off")+"\"/>\n" |
| ); |
| // Finally, go through forced ACL |
| i = 0; |
| k = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS)) |
| { |
| String accessDescription = "_"+Integer.toString(k); |
| String token = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TOKEN); |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"spectoken"+accessDescription+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(token)+"\"/>\n" |
| ); |
| k++; |
| } |
| } |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"tokencount\" value=\""+Integer.toString(k)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specsharesecurity\" value=\""+(shareSecurityOn?"on":"off")+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specparentfoldersecurity\" value=\""+(parentFolderSecurityOn?"on":"off")+"\"/>\n" |
| ); |
| } |
| |
| |
| |
| // Metadata tab |
| |
| // Find the path-value metadata attribute name |
| // Find the path-value mapping data |
| i = 0; |
| String pathNameAttribute = ""; |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap matchMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHNAMEATTRIBUTE)) |
| { |
| pathNameAttribute = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| } |
| else if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| matchMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.Metadata")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specmappingcount\" value=\""+Integer.toString(matchMap.getMatchCount())+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specmappingop\" value=\"\"/>\n"+ |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\" colspan=\"1\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.PathAttributeName") + "</nobr></td>\n"+ |
| " <td class=\"value\" colspan=\"3\">\n"+ |
| " <input type=\"text\" name=\""+seqPrefix+"specpathnameattribute\" size=\"20\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(pathNameAttribute)+"\"/>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n" |
| ); |
| i = 0; |
| while (i < matchMap.getMatchCount()) |
| { |
| String matchString = matchMap.getMatchString(i); |
| String replaceString = matchMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specmappingop_"+Integer.toString(i)+"\" value=\"\"/>\n"+ |
| " <a name=\""+seqPrefix+"mapping_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+seqPrefix+"specmappingop_"+Integer.toString(i)+"\",\"Delete\",\""+seqPrefix+"mapping_"+Integer.toString(i)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeleteMapping")+Integer.toString(i)+"\" value=\"Delete\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\"><input type=\"hidden\" name=\""+seqPrefix+"specmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"</td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><input type=\"hidden\" name=\""+seqPrefix+"specreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"</td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| if (i == 0) |
| { |
| out.print( |
| " <tr><td colspan=\"4\" class=\"message\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoMappingsSpecified") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <a name=\""+seqPrefix+"mapping_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecAddMapping(\""+seqPrefix+"mapping_"+Integer.toString(i+1)+"\")' alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddToMappings") + "\" value=\"Add\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.MatchRegexp") + "<input type=\"text\" name=\""+seqPrefix+"specmatch\" size=\"32\" value=\"\"/></nobr></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.ReplaceString") + "<input type=\"text\" name=\""+seqPrefix+"specreplace\" size=\"32\" value=\"\"/></nobr></td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specpathnameattribute\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(pathNameAttribute)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specmappingcount\" value=\""+Integer.toString(matchMap.getMatchCount())+"\"/>\n" |
| ); |
| i = 0; |
| while (i < matchMap.getMatchCount()) |
| { |
| String matchString = matchMap.getMatchString(i); |
| String replaceString = matchMap.getReplaceString(i); |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>\n" |
| ); |
| i++; |
| } |
| } |
| |
| // File and URL Mapping tabs |
| |
| // Find the filename mapping data |
| // Find the URL mapping data |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap fileMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap uriMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_FILEMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| fileMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| else if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_URIMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| uriMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.FileMapping")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfmapcount\" value=\""+Integer.toString(fileMap.getMatchCount())+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfmapop\" value=\"\"/>\n"+ |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n" |
| ); |
| i = 0; |
| while (i < fileMap.getMatchCount()) |
| { |
| String matchString = fileMap.getMatchString(i); |
| String replaceString = fileMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specfmapop_"+Integer.toString(i)+"\" value=\"\"/>\n"+ |
| " <a name=\""+seqPrefix+"fmap_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+seqPrefix+"specfmapop_"+Integer.toString(i)+"\",\"Delete\",\""+seqPrefix+"fmap_"+Integer.toString(i)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeleteFileMapping")+Integer.toString(i)+"\" value=\"Delete\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\"><input type=\"hidden\" name=\""+seqPrefix+"specfmapmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"</td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><input type=\"hidden\" name=\""+seqPrefix+"specfmapreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"</td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| if (i == 0) |
| { |
| out.print( |
| " <tr><td colspan=\"4\" class=\"message\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoFileMappingsSpecified") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <a name=\""+seqPrefix+"fmap_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecAddFMap(\""+seqPrefix+"fmap_"+Integer.toString(i+1)+"\")' alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddToFileMappings") + "\" value=\"Add\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">" + Messages.getBodyString(locale,"SharedDriveConnector.MatchRegexp") + "<input type=\"text\" name=\""+seqPrefix+"specfmapmatch\" size=\"32\" value=\"\"/></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\">" + Messages.getBodyString(locale,"SharedDriveConnector.ReplaceString") + "<input type=\"text\" name=\""+seqPrefix+"specfmapreplace\" size=\"32\" value=\"\"/></td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfmapcount\" value=\""+Integer.toString(fileMap.getMatchCount())+"\"/>\n" |
| ); |
| i = 0; |
| while (i < fileMap.getMatchCount()) |
| { |
| String matchString = fileMap.getMatchString(i); |
| String replaceString = fileMap.getReplaceString(i); |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfmapmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specfmapreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>\n" |
| ); |
| i++; |
| } |
| } |
| |
| if (tabName.equals(Messages.getString(locale,"SharedDriveConnector.URLMapping")) && connectionSequenceNumber == actualSequenceNumber) |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specumapcount\" value=\""+Integer.toString(uriMap.getMatchCount())+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specumapop\" value=\"\"/>\n"+ |
| "<table class=\"displaytable\">\n"+ |
| " <tr><td class=\"separator\" colspan=\"4\"><hr/></td></tr>\n" |
| ); |
| i = 0; |
| while (i < uriMap.getMatchCount()) |
| { |
| String matchString = uriMap.getMatchString(i); |
| String replaceString = uriMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specumapop_"+Integer.toString(i)+"\" value=\"\"/>\n"+ |
| " <a name=\""+seqPrefix+"umap_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecOp(\""+seqPrefix+"specumapop_"+Integer.toString(i)+"\",\"Delete\",\""+seqPrefix+"umap_"+Integer.toString(i)+"\")' alt=\""+Messages.getAttributeString(locale,"SharedDriveConnector.DeleteUrlMapping")+Integer.toString(i)+"\" value=\"Delete\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specumapmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>\n"+ |
| " "+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <input type=\"hidden\" name=\""+seqPrefix+"specumapreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>\n"+ |
| " "+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"\n"+ |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| if (i == 0) |
| { |
| out.print( |
| " <tr><td colspan=\"4\" class=\"message\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoURLMappingsSpecifiedWillProduceAFileIRI") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"lightseparator\" colspan=\"4\"><hr/></td></tr>\n"+ |
| " \n"+ |
| " <tr>\n"+ |
| " <td class=\"value\">\n"+ |
| " <a name=\""+seqPrefix+"umap_"+Integer.toString(i)+"\">\n"+ |
| " <input type=\"button\" onClick='Javascript:"+seqPrefix+"SpecAddUMap(\""+seqPrefix+"umap_"+Integer.toString(i+1)+"\")' alt=\"" + Messages.getAttributeString(locale,"SharedDriveConnector.AddToURLMappings") + "\" value=\"Add\"/>\n"+ |
| " </a>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">" + Messages.getBodyString(locale,"SharedDriveConnector.MatchRegexp") + "<input type=\"text\" name=\""+seqPrefix+"specumapmatch\" size=\"32\" value=\"\"/></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\">" + Messages.getBodyString(locale,"SharedDriveConnector.ReplaceString") + "<input type=\"text\" name=\""+seqPrefix+"specumapreplace\" size=\"32\" value=\"\"/></td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specumapcount\" value=\""+Integer.toString(uriMap.getMatchCount())+"\"/>\n" |
| ); |
| i = 0; |
| while (i < uriMap.getMatchCount()) |
| { |
| String matchString = uriMap.getMatchString(i); |
| String replaceString = uriMap.getReplaceString(i); |
| out.print( |
| "<input type=\"hidden\" name=\""+seqPrefix+"specumapmatch_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(matchString)+"\"/>\n"+ |
| "<input type=\"hidden\" name=\""+seqPrefix+"specumapreplace_"+Integer.toString(i)+"\" value=\""+org.apache.manifoldcf.ui.util.Encoder.attributeEscape(replaceString)+"\"/>\n" |
| ); |
| i++; |
| } |
| } |
| } |
| |
| /** Process a specification post. |
| * This method is called at the start of job's edit or view 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 |
| * document specification accordingly. The name of the posted form is always "editjob". |
| * The connector will be connected before this method can be called. |
| *@param variableContext contains the post data, including binary file-upload information. |
| *@param locale is the locale the output is preferred to be in. |
| *@param ds is the current document specification for this job. |
| *@param connectionSequenceNumber is the unique number of this connection within the job. |
| *@return null if all is well, or a string error message if there is an error that should prevent saving of |
| * the job (and cause a redirection to an error page). |
| */ |
| @Override |
| public String processSpecificationPost(IPostParameters variableContext, Locale locale, Specification ds, |
| int connectionSequenceNumber) |
| throws ManifoldCFException |
| { |
| String seqPrefix = "s"+connectionSequenceNumber+"_"; |
| |
| String x = variableContext.getParameter(seqPrefix+"pathcount"); |
| if (x != null) |
| { |
| // Delete all path specs first |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| // Find out how many children were sent |
| int pathCount = Integer.parseInt(x); |
| // Gather up these |
| i = 0; |
| while (i < pathCount) |
| { |
| String pathDescription = "_"+Integer.toString(i); |
| String pathOpName = seqPrefix+"pathop"+pathDescription; |
| x = variableContext.getParameter(pathOpName); |
| if (x != null && x.equals("Delete")) |
| { |
| // Skip to the next |
| i++; |
| continue; |
| } |
| // Path inserts won't happen until the very end |
| String path = variableContext.getParameter(seqPrefix+"specpath"+pathDescription); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH,path); |
| |
| // Now, get the number of children |
| String y = variableContext.getParameter(seqPrefix+"specchildcount"+pathDescription); |
| int childCount = Integer.parseInt(y); |
| int j = 0; |
| int w = 0; |
| while (j < childCount) |
| { |
| String instanceDescription = "_"+Integer.toString(i)+"_"+Integer.toString(j); |
| // Look for an insert or a delete at this point |
| String instanceOp = seqPrefix+"specop"+instanceDescription; |
| String z = variableContext.getParameter(instanceOp); |
| String flavor; |
| String type; |
| String indexable; |
| String match; |
| SpecificationNode sn; |
| if (z != null && z.equals("Delete")) |
| { |
| // Process the deletion as we gather |
| j++; |
| continue; |
| } |
| if (z != null && z.equals("Insert Here")) |
| { |
| // Process the insertion as we gather. |
| flavor = variableContext.getParameter(seqPrefix+"specfl_i"+instanceDescription); |
| indexable = ""; |
| type = ""; |
| String xxx = variableContext.getParameter(seqPrefix+"spectin_i"+instanceDescription); |
| if (xxx.equals("file") || xxx.equals("directory")) |
| type = xxx; |
| else if (xxx.equals("indexable-file")) |
| { |
| indexable = "yes"; |
| type = "file"; |
| } |
| else if (xxx.equals("unindexable-file")) |
| { |
| indexable = "no"; |
| type = "file"; |
| } |
| |
| match = variableContext.getParameter(seqPrefix+"specfile_i"+instanceDescription); |
| sn = new SpecificationNode(flavor); |
| if (type != null && type.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE,type); |
| if (indexable != null && indexable.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE,indexable); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC,match); |
| node.addChild(w++,sn); |
| } |
| flavor = variableContext.getParameter(seqPrefix+"specfl"+instanceDescription); |
| type = variableContext.getParameter(seqPrefix+"specty"+instanceDescription); |
| match = variableContext.getParameter(seqPrefix+"specfile"+instanceDescription); |
| indexable = variableContext.getParameter(seqPrefix+"specin"+instanceDescription); |
| sn = new SpecificationNode(flavor); |
| if (type != null && type.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE,type); |
| if (indexable != null && indexable.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE,indexable); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC,match); |
| node.addChild(w++,sn); |
| j++; |
| } |
| if (x != null && x.equals("Add")) |
| { |
| // Process adds to the end of the rules in-line |
| String match = variableContext.getParameter(seqPrefix+"specfile"+pathDescription); |
| String indexable = ""; |
| String type = ""; |
| String xxx = variableContext.getParameter(seqPrefix+"spectin"+pathDescription); |
| if (xxx.equals("file") || xxx.equals("directory")) |
| type = xxx; |
| else if (xxx.equals("indexable-file")) |
| { |
| indexable = "yes"; |
| type = "file"; |
| } |
| else if (xxx.equals("unindexable-file")) |
| { |
| indexable = "no"; |
| type = "file"; |
| } |
| |
| String flavor = variableContext.getParameter(seqPrefix+"specfl"+pathDescription); |
| SpecificationNode sn = new SpecificationNode(flavor); |
| if (type != null && type.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE,type); |
| if (indexable != null && indexable.length() > 0) |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE,indexable); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC,match); |
| node.addChild(w,sn); |
| } |
| |
| ds.addChild(ds.getChildCount(),node); |
| i++; |
| } |
| |
| // See if there's a global add operation |
| String op = variableContext.getParameter(seqPrefix+"pathop"); |
| if (op != null && op.equals("Add")) |
| { |
| String path = variableContext.getParameter(seqPrefix+"specpath"); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH,path); |
| ds.addChild(ds.getChildCount(),node); |
| |
| // Now add in the defaults; these will be "include all directories" and "include all indexable files". |
| SpecificationNode sn = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_INCLUDE); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE,"file"); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE,"yes"); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC,"*"); |
| node.addChild(node.getChildCount(),sn); |
| sn = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_INCLUDE); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE,"directory"); |
| sn.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC,"*"); |
| node.addChild(node.getChildCount(),sn); |
| } |
| else if (op != null && op.equals("Up")) |
| { |
| // Strip off end |
| String path = variableContext.getParameter(seqPrefix+"specpath"); |
| int k = path.lastIndexOf("/"); |
| if (k == -1) |
| path = ""; |
| else |
| path = path.substring(0,k); |
| currentContext.save(seqPrefix+"specpath",path); |
| } |
| else if (op != null && op.equals("AddToPath")) |
| { |
| String path = variableContext.getParameter(seqPrefix+"specpath"); |
| String addon = variableContext.getParameter(seqPrefix+"pathaddon"); |
| String typein = variableContext.getParameter(seqPrefix+"pathtypein"); |
| if (addon != null && addon.length() > 0) |
| { |
| if (path.length() == 0) |
| path = addon; |
| else |
| path += "/" + addon; |
| } |
| else if (typein != null && typein.length() > 0) |
| { |
| String trialPath = path; |
| if (trialPath.length() == 0) |
| trialPath = typein; |
| else |
| trialPath += "/" + typein; |
| // Validate trial path |
| try |
| { |
| trialPath = validateFolderName(trialPath); |
| if (trialPath != null) |
| path = trialPath; |
| } |
| catch (ManifoldCFException e) |
| { |
| // Effectively, this just means we can't add a typein to the path right now. |
| } |
| } |
| currentContext.save(seqPrefix+"specpath",path); |
| } |
| } |
| |
| x = variableContext.getParameter(seqPrefix+"specmaxlength"); |
| if (x != null) |
| { |
| // Delete max length entry |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_MAXLENGTH)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| if (x.length() > 0) |
| { |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_MAXLENGTH); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE,x); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| |
| x = variableContext.getParameter(seqPrefix+"specsecurity"); |
| if (x != null) |
| { |
| // Delete all security entries first |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SECURITY)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SECURITY); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE,x); |
| ds.addChild(ds.getChildCount(),node); |
| |
| } |
| |
| x = variableContext.getParameter(seqPrefix+"tokencount"); |
| if (x != null) |
| { |
| // Delete all file specs first |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| int accessCount = Integer.parseInt(x); |
| i = 0; |
| while (i < accessCount) |
| { |
| String accessDescription = "_"+Integer.toString(i); |
| String accessOpName = seqPrefix+"accessop"+accessDescription; |
| x = variableContext.getParameter(accessOpName); |
| if (x != null && x.equals("Delete")) |
| { |
| // Next row |
| i++; |
| continue; |
| } |
| // Get the stuff we need |
| String accessSpec = variableContext.getParameter(seqPrefix+"spectoken"+accessDescription); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TOKEN,accessSpec); |
| ds.addChild(ds.getChildCount(),node); |
| i++; |
| } |
| |
| String op = variableContext.getParameter(seqPrefix+"accessop"); |
| if (op != null && op.equals("Add")) |
| { |
| String accessspec = variableContext.getParameter(seqPrefix+"spectoken"); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TOKEN,accessspec); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| |
| x = variableContext.getParameter(seqPrefix+"specsharesecurity"); |
| if (x != null) |
| { |
| // Delete all security entries first |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SHARESECURITY)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SHARESECURITY); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE,x); |
| ds.addChild(ds.getChildCount(),node); |
| |
| } |
| |
| x = variableContext.getParameter(seqPrefix+"specparentfoldersecurity"); |
| if (x != null) |
| { |
| // Delete all security entries first |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PARENTFOLDERSECURITY)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PARENTFOLDERSECURITY); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE,x); |
| ds.addChild(ds.getChildCount(),node); |
| |
| } |
| |
| String xc = variableContext.getParameter(seqPrefix+"specpathnameattribute"); |
| if (xc != null) |
| { |
| // Delete old one |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHNAMEATTRIBUTE)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| if (xc.length() > 0) |
| { |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHNAMEATTRIBUTE); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE,xc); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| |
| xc = variableContext.getParameter(seqPrefix+"specmappingcount"); |
| if (xc != null) |
| { |
| // Delete old spec |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHMAP)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| // Now, go through the data and assemble a new list. |
| int mappingCount = Integer.parseInt(xc); |
| |
| // Gather up these |
| i = 0; |
| while (i < mappingCount) |
| { |
| String pathDescription = "_"+Integer.toString(i); |
| String pathOpName = seqPrefix+"specmappingop"+pathDescription; |
| xc = variableContext.getParameter(pathOpName); |
| if (xc != null && xc.equals("Delete")) |
| { |
| // Skip to the next |
| i++; |
| continue; |
| } |
| // Inserts won't happen until the very end |
| String match = variableContext.getParameter(seqPrefix+"specmatch"+pathDescription); |
| String replace = variableContext.getParameter(seqPrefix+"specreplace"+pathDescription); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| i++; |
| } |
| |
| // Check for add |
| xc = variableContext.getParameter(seqPrefix+"specmappingop"); |
| if (xc != null && xc.equals("Add")) |
| { |
| String match = variableContext.getParameter(seqPrefix+"specmatch"); |
| String replace = variableContext.getParameter(seqPrefix+"specreplace"); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| |
| xc = variableContext.getParameter(seqPrefix+"specfmapcount"); |
| if (xc != null) |
| { |
| // Delete old spec |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_FILEMAP)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| // Now, go through the data and assemble a new list. |
| int mappingCount = Integer.parseInt(xc); |
| |
| // Gather up these |
| i = 0; |
| while (i < mappingCount) |
| { |
| String pathDescription = "_"+Integer.toString(i); |
| String pathOpName = seqPrefix+"specfmapop"+pathDescription; |
| xc = variableContext.getParameter(pathOpName); |
| if (xc != null && xc.equals("Delete")) |
| { |
| // Skip to the next |
| i++; |
| continue; |
| } |
| // Inserts won't happen until the very end |
| String match = variableContext.getParameter(seqPrefix+"specfmapmatch"+pathDescription); |
| String replace = variableContext.getParameter(seqPrefix+"specfmapreplace"+pathDescription); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_FILEMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| i++; |
| } |
| |
| // Check for add |
| xc = variableContext.getParameter(seqPrefix+"specfmapop"); |
| if (xc != null && xc.equals("Add")) |
| { |
| String match = variableContext.getParameter(seqPrefix+"specfmapmatch"); |
| String replace = variableContext.getParameter(seqPrefix+"specfmapreplace"); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_FILEMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| |
| xc = variableContext.getParameter(seqPrefix+"specumapcount"); |
| if (xc != null) |
| { |
| // Delete old spec |
| int i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_URIMAP)) |
| ds.removeChild(i); |
| else |
| i++; |
| } |
| |
| // Now, go through the data and assemble a new list. |
| int mappingCount = Integer.parseInt(xc); |
| |
| // Gather up these |
| i = 0; |
| while (i < mappingCount) |
| { |
| String pathDescription = "_"+Integer.toString(i); |
| String pathOpName = seqPrefix+"specumapop"+pathDescription; |
| xc = variableContext.getParameter(pathOpName); |
| if (xc != null && xc.equals("Delete")) |
| { |
| // Skip to the next |
| i++; |
| continue; |
| } |
| // Inserts won't happen until the very end |
| String match = variableContext.getParameter(seqPrefix+"specumapmatch"+pathDescription); |
| String replace = variableContext.getParameter(seqPrefix+"specumapreplace"+pathDescription); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_URIMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| i++; |
| } |
| |
| // Check for add |
| xc = variableContext.getParameter(seqPrefix+"specumapop"); |
| if (xc != null && xc.equals("Add")) |
| { |
| String match = variableContext.getParameter(seqPrefix+"specumapmatch"); |
| String replace = variableContext.getParameter(seqPrefix+"specumapreplace"); |
| SpecificationNode node = new SpecificationNode(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_URIMAP); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH,match); |
| node.setAttribute(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE,replace); |
| ds.addChild(ds.getChildCount(),node); |
| } |
| } |
| return null; |
| } |
| |
| /** View specification. |
| * This method is called in the body section of a job's view page. Its purpose is to present the document |
| * specification 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. |
| * The connector will be connected before this method can be called. |
| *@param out is the output to which any HTML should be sent. |
| *@param locale is the locale the output is preferred to be in. |
| *@param ds is the current document specification for this job. |
| *@param connectionSequenceNumber is the unique number of this connection within the job. |
| */ |
| @Override |
| public void viewSpecification(IHTTPOutput out, Locale locale, Specification ds, |
| int connectionSequenceNumber) |
| throws ManifoldCFException, IOException |
| { |
| out.print( |
| "<table class=\"displaytable\">\n" |
| ); |
| int i = 0; |
| boolean seenAny = false; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode spn = ds.getChild(i++); |
| if (spn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_STARTPOINT)) |
| { |
| if (seenAny == false) |
| { |
| seenAny = true; |
| } |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"description\">\n"+ |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(spn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_PATH))+":"+"</nobr>\n"+ |
| " </td>\n"+ |
| " <td class=\"value\">\n" |
| ); |
| int j = 0; |
| while (j < spn.getChildCount()) |
| { |
| SpecificationNode sn = spn.getChild(j++); |
| // This is "include" or "exclude" |
| String nodeFlavor = sn.getType(); |
| // This is the file/directory name match |
| String filespec = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_FILESPEC); |
| // This has a value of null, "", "file", or "directory". |
| String nodeType = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TYPE); |
| if (nodeType == null) |
| nodeType = ""; |
| // This has a value of null, "", "yes", or "no". |
| String ingestableFlag = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_INDEXABLE); |
| if (ingestableFlag == null) |
| ingestableFlag = ""; |
| out.print( |
| " <nobr>\n"+ |
| " "+Integer.toString(j)+".\n"+ |
| " "+(nodeFlavor.equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_INCLUDE)?"Include":"")+"\n"+ |
| " "+(nodeFlavor.equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_EXCLUDE)?"Exclude":"")+"\n"+ |
| " "+(ingestableFlag.equals("yes")?" indexable":"")+"\n"+ |
| " "+(ingestableFlag.equals("no")?" un-indexable":"")+"\n"+ |
| " "+(nodeType.equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.VALUE_FILE)?" file(s)":"")+"\n"+ |
| " "+(nodeType.equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.VALUE_DIRECTORY)?" directory(s)":"")+"\n"+ |
| " "+(nodeType.equals("")?" file(s) or directory(s)":"")+" matching \n"+ |
| " "+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(filespec)+"\n"+ |
| " </nobr>\n"+ |
| " <br/>\n" |
| ); |
| } |
| out.print( |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| } |
| } |
| if (seenAny == false) |
| { |
| out.print( |
| " <tr><td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoDocumentsSpecified") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| "\n" |
| ); |
| // Find whether security is on or off |
| i = 0; |
| boolean securityOn = true; |
| boolean shareSecurityOn = true; |
| boolean parentFolderSecurityOn = false; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| securityOn = false; |
| else if (securityValue.equals("on")) |
| securityOn = true; |
| } |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_SHARESECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| shareSecurityOn = false; |
| else if (securityValue.equals("on")) |
| shareSecurityOn = true; |
| } |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PARENTFOLDERSECURITY)) |
| { |
| String securityValue = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| if (securityValue.equals("off")) |
| parentFolderSecurityOn = false; |
| else if (securityValue.equals("on")) |
| parentFolderSecurityOn = true; |
| } |
| } |
| out.print( |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.FileSecurity") + "</nobr></td>\n"+ |
| " <td class=\"value\"><nobr>"+(securityOn?Messages.getBodyString(locale,"SharedDriveConnector.Enabled"):Messages.getBodyString(locale,"SharedDriveConnector.Disabled"))+"</nobr></td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n" |
| ); |
| // Go through looking for access tokens |
| seenAny = false; |
| i = 0; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_ACCESS)) |
| { |
| if (seenAny == false) |
| { |
| out.print( |
| " <tr><td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.FileAccessTokens") + "</nobr></td>\n"+ |
| " <td class=\"value\">\n" |
| ); |
| seenAny = true; |
| } |
| String token = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_TOKEN); |
| out.print( |
| " <nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(token)+"</nobr><br/>\n" |
| ); |
| } |
| } |
| |
| if (seenAny) |
| { |
| out.print( |
| " </td>\n"+ |
| " </tr>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <tr><td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoFileAccessTokensSpecified") + "</td></tr>\n" |
| ); |
| } |
| out.print( |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " \n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.ShareSecurity") + "</nobr></td>\n"+ |
| " <td class=\"value\"><nobr>"+(shareSecurityOn?Messages.getBodyString(locale,"SharedDriveConnector.Enabled"):Messages.getBodyString(locale,"SharedDriveConnector.Disabled"))+"</nobr></td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| " \n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.ParentFolderSecurity") + "</nobr></td>\n"+ |
| " <td class=\"value\"><nobr>"+(parentFolderSecurityOn?Messages.getBodyString(locale,"SharedDriveConnector.Enabled"):Messages.getBodyString(locale,"SharedDriveConnector.Disabled"))+"</nobr></td>\n"+ |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n" |
| ); |
| // Find the path-name metadata attribute name |
| i = 0; |
| String pathNameAttribute = ""; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHNAMEATTRIBUTE)) |
| { |
| pathNameAttribute = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| } |
| } |
| out.print( |
| " <tr>\n" |
| ); |
| if (pathNameAttribute.length() > 0) |
| { |
| out.print( |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.PathNameMetadataAttribute") + "</nobr></td>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(pathNameAttribute)+"</nobr></td>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoPathNameMetadataAttributeSpecified") + "</td>\n" |
| ); |
| } |
| out.print( |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| "\n" |
| ); |
| |
| // Find the path-value mapping data |
| i = 0; |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap matchMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_PATHMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| matchMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| if (matchMap.getMatchCount() > 0) |
| { |
| out.print( |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.PathValueMapping") + "</nobr></td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <table class=\"displaytable\">\n" |
| ); |
| i = 0; |
| while (i < matchMap.getMatchCount()) |
| { |
| String matchString = matchMap.getMatchString(i); |
| String replaceString = matchMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"</nobr></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"</nobr></td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| out.print( |
| " </table>\n"+ |
| " </td>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoMappingsSpecified") + "</td>\n" |
| ); |
| } |
| out.print( |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n" |
| ); |
| // Find the file name mapping data |
| i = 0; |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap fileMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_FILEMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| fileMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| if (fileMap.getMatchCount() > 0) |
| { |
| out.print( |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.FileNameMapping") + "</nobr></td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <table class=\"displaytable\">\n" |
| ); |
| i = 0; |
| while (i < fileMap.getMatchCount()) |
| { |
| String matchString = fileMap.getMatchString(i); |
| String replaceString = fileMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"</nobr></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"</nobr></td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| out.print( |
| " </table>\n"+ |
| " </td>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoFileNameMappingsSpecified") + "</td>\n" |
| ); |
| } |
| out.print( |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n" |
| ); |
| |
| // Find the url mapping data |
| i = 0; |
| org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap uriMap = new org.apache.manifoldcf.crawler.connectors.sharedrive.MatchMap(); |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_URIMAP)) |
| { |
| String pathMatch = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_MATCH); |
| String pathReplace = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_REPLACE); |
| uriMap.appendMatchPair(pathMatch,pathReplace); |
| } |
| } |
| if (uriMap.getMatchCount() > 0) |
| { |
| out.print( |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.URLMappingColon") + "</nobr></td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <table class=\"displaytable\">\n" |
| ); |
| i = 0; |
| while (i < uriMap.getMatchCount()) |
| { |
| String matchString = uriMap.getMatchString(i); |
| String replaceString = uriMap.getReplaceString(i); |
| out.print( |
| " <tr>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(matchString)+"</nobr></td>\n"+ |
| " <td class=\"value\">==></td>\n"+ |
| " <td class=\"value\"><nobr>"+org.apache.manifoldcf.ui.util.Encoder.bodyEscape(replaceString)+"</nobr></td>\n"+ |
| " </tr>\n" |
| ); |
| i++; |
| } |
| out.print( |
| " </table>\n"+ |
| " </td>\n" |
| ); |
| } |
| else |
| { |
| out.print( |
| " <td class=\"message\" colspan=\"2\">" + Messages.getBodyString(locale,"SharedDriveConnector.NoURLMappingsSpecifiedWillProduceAFileIRI") + "</td>\n" |
| ); |
| } |
| out.print( |
| " </tr>\n"+ |
| "\n"+ |
| " <tr><td class=\"separator\" colspan=\"2\"><hr/></td></tr>\n"+ |
| "\n"+ |
| " <tr>\n"+ |
| " <td class=\"description\"><nobr>" + Messages.getBodyString(locale,"SharedDriveConnector.MaximumDocumentLength") + "</nobr></td>\n"+ |
| " <td class=\"value\">\n"+ |
| " <nobr>\n" |
| ); |
| // Find the path-value mapping data |
| i = 0; |
| String maxLength = null; |
| while (i < ds.getChildCount()) |
| { |
| SpecificationNode sn = ds.getChild(i++); |
| if (sn.getType().equals(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.NODE_MAXLENGTH)) |
| { |
| maxLength = sn.getAttributeValue(org.apache.manifoldcf.crawler.connectors.sharedrive.SharedDriveConnector.ATTRIBUTE_VALUE); |
| } |
| } |
| if (maxLength == null || maxLength.length() == 0) |
| maxLength = "Unlimited"; |
| out.print( |
| " "+maxLength+"\n"+ |
| " </nobr>\n"+ |
| " </td>\n"+ |
| " </tr>\n"+ |
| "</table>\n" |
| ); |
| } |
| |
| /* The following are additional methods used by the UI */ |
| |
| /** |
| * given a server uri, return all shares |
| * |
| * @param serverURI - |
| * @return an array of SmbFile |
| */ |
| public SmbFile[] getShareNames(String serverURI) |
| throws ManifoldCFException |
| { |
| getSession(); |
| SmbFile server = null; |
| try |
| { |
| server = new SmbFile(serverURI,SingletonContext.getInstance().withCredentials(pa)); |
| } |
| catch (MalformedURLException e1) |
| { |
| throw new ManifoldCFException("MalformedURLException tossed",e1); |
| } |
| SmbFile[] shares = null; |
| try |
| { |
| // check to make sure it's a server |
| if (getFileType(server)==SmbFile.TYPE_SERVER) |
| { |
| shares = fileListFiles(server,new ShareFilter()); |
| } |
| } |
| catch (SmbException e) |
| { |
| throw new ManifoldCFException("SmbException tossed: "+e.getMessage(),e); |
| } |
| return shares; |
| } |
| |
| /** |
| * Given a folder path, determine if the folder is in fact legal and accessible (and is a folder). |
| * @param folder is the relative folder from the network root |
| * @return the canonical folder name if valid, or null if not. |
| * @throws ManifoldCFException |
| */ |
| public String validateFolderName(String folder) throws ManifoldCFException |
| { |
| getSession(); |
| //create new connection by appending to the old connection |
| String smburi = smbconnectionPath; |
| String uri = smburi; |
| if (folder.length() > 0) { |
| uri = smburi + folder + "/"; |
| } |
| |
| SmbFile currentDirectory = null; |
| try |
| { |
| currentDirectory = new SmbFile(uri,SingletonContext.getInstance().withCredentials(pa)); |
| } |
| catch (MalformedURLException e1) |
| { |
| throw new ManifoldCFException("validateFolderName: Can't get parent file: " + uri,e1); |
| } |
| |
| try |
| { |
| currentDirectory.connect(); |
| if (fileIsDirectory(currentDirectory) == false) |
| return null; |
| String newCanonicalPath = currentDirectory.getCanonicalPath(); |
| String rval = newCanonicalPath.substring(smburi.length()); |
| if (rval.endsWith("/")) |
| rval = rval.substring(0,rval.length()-1); |
| return rval; |
| } |
| catch (SmbException se) |
| { |
| try |
| { |
| processSMBException(se, folder, "checking folder", "getting canonical path"); |
| return null; |
| } |
| catch (ServiceInterruption si) |
| { |
| throw new ManifoldCFException("Service interruption: "+si.getMessage(),si); |
| } |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("MalformedURLException tossed: "+e.getMessage(),e); |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| throw new ManifoldCFException("IOException tossed: "+e.getMessage(),e); |
| } |
| catch (InterruptedIOException e) |
| { |
| throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED); |
| } |
| catch (IOException e) |
| { |
| throw new ManifoldCFException("IOException tossed: "+e.getMessage(),e); |
| } |
| |
| } |
| |
| /** |
| * given a smb uri, return all children directories |
| * |
| * @param folder is the relative folder from the network root |
| * @return array of child folder names |
| * @throws ManifoldCFException |
| */ |
| public String[] getChildFolderNames(String folder) throws ManifoldCFException |
| { |
| getSession(); |
| //create new connection by appending to the old connection |
| String smburi = smbconnectionPath; |
| String uri = smburi; |
| if (folder.length() > 0) { |
| uri = smburi + folder + "/"; |
| } |
| |
| SmbFile currentDirectory = null; |
| try |
| { |
| currentDirectory = new SmbFile(uri,SingletonContext.getInstance().withCredentials(pa)); |
| } |
| catch (MalformedURLException e1) |
| { |
| throw new ManifoldCFException("getChildFolderNames: Can't get parent file: " + uri,e1); |
| } |
| |
| // add DFS support |
| SmbFile[] children = null; |
| try |
| { |
| currentDirectory.connect(); |
| children = currentDirectory.listFiles(new DirectoryFilter()); |
| } |
| catch (SmbException se) |
| { |
| try |
| { |
| processSMBException(se, folder, "getting child folder names", "listing files"); |
| children = new SmbFile[0]; |
| } |
| catch (ServiceInterruption si) |
| { |
| throw new ManifoldCFException("Service interruption: "+si.getMessage(),si); |
| } |
| } |
| catch (MalformedURLException e) |
| { |
| throw new ManifoldCFException("MalformedURLException tossed: "+e.getMessage(),e); |
| } |
| catch (java.net.SocketTimeoutException e) |
| { |
| throw new ManifoldCFException("IOException tossed: "+e.getMessage(),e); |
| } |
| catch (InterruptedIOException e) |
| { |
| throw new ManifoldCFException("Interrupted: "+e.getMessage(),e,ManifoldCFException.INTERRUPTED); |
| } |
| catch (IOException e) |
| { |
| throw new ManifoldCFException("IOException tossed: "+e.getMessage(),e); |
| } |
| |
| // populate a String array |
| String[] directories = new String[children.length]; |
| for (int i=0;i < children.length;i++){ |
| String directoryName = children[i].getName(); |
| // strip the trailing slash |
| directoryName = directoryName.replaceAll("/",""); |
| directories[i] = directoryName; |
| } |
| |
| java.util.Arrays.sort(directories); |
| return directories; |
| } |
| |
| /** |
| * inner class which returns only shares. used by listfiles(SmbFileFilter) |
| * |
| * @author James Maupin |
| */ |
| |
| class ShareFilter implements SmbFileFilter |
| { |
| /* (non-Javadoc) |
| * @see jcifs.smb.SmbFileFilter#accept(jcifs.smb.SmbFile) |
| */ |
| public boolean accept(SmbFile arg0) throws SmbException |
| { |
| if (getFileType(arg0)==SmbFile.TYPE_SHARE){ |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| /** |
| * inner class which returns only directories. used by listfiles(SmbFileFilter) |
| * |
| * @author James Maupin |
| */ |
| |
| class DirectoryFilter implements SmbFileFilter |
| { |
| /* (non-Javadoc) |
| * @see jcifs.smb.SmbFileFilter#accept(jcifs.smb.SmbFile) |
| */ |
| public boolean accept(SmbFile arg0) throws SmbException { |
| int type = getFileType(arg0); |
| if (type==SmbFile.TYPE_SHARE || (type==SmbFile.TYPE_FILESYSTEM && fileIsDirectory(arg0))){ |
| return true; |
| } else { |
| return false; |
| } |
| } |
| } |
| |
| /** This is the filter class that actually receives the files in batches. We do it this way |
| * so that the client won't run out of memory loading a huge directory. |
| */ |
| protected class ProcessDocumentsFilter implements SmbFileFilter |
| { |
| |
| /** This is the activities object, where matching references will be logged */ |
| protected final IProcessActivity activities; |
| /** Document specification */ |
| protected final Specification spec; |
| /** Exceptions that we saw. These are saved here so that they can be rethrown when done */ |
| protected ManifoldCFException lcfException = null; |
| protected ServiceInterruption serviceInterruption = null; |
| |
| /** Constructor */ |
| public ProcessDocumentsFilter(IProcessActivity activities, Specification spec) |
| { |
| this.activities = activities; |
| this.spec = spec; |
| } |
| |
| /** Decide if we accept the file. This is where we will actually do the work. */ |
| public boolean accept(SmbFile f) throws SmbException |
| { |
| if (lcfException != null || serviceInterruption != null) |
| return false; |
| |
| try |
| { |
| int type = f.getType(); |
| if (type != SmbFile.TYPE_SERVER && type != SmbFile.TYPE_FILESYSTEM && type != SmbFile.TYPE_SHARE) |
| return false; |
| String canonicalPath = getFileCanonicalPath(f); |
| if (canonicalPath != null) |
| { |
| // manipulate path to include the DFS alias, not the literal path |
| // String newPath = matchPrefix + canonicalPath.substring(matchReplace.length()); |
| String newPath = canonicalPath; |
| |
| // Check against the current specification. This is a nicety to avoid queuing |
| // documents that we will immediately turn around and remove. However, if this |
| // check was not here, everything should still function, provided the getDocumentVersions() |
| // method does the right thing. |
| boolean fileIsDirectory = fileIsDirectory(f); |
| if (checkInclude(fileIsDirectory, newPath, spec)) |
| { |
| if (fileIsDirectory) |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Recorded path is '" + newPath + "' and is included."); |
| activities.addDocumentReference(newPath); |
| } |
| else |
| { |
| long fileLength = fileLength(f); |
| if (checkIncludeFile(fileLength, newPath, spec, activities)) |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Recorded path is '" + newPath + "' and is included."); |
| activities.addDocumentReference(newPath); |
| } |
| else |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Recorded path '"+newPath+"' is excluded!"); |
| } |
| } |
| } |
| else |
| { |
| if (Logging.connectors.isDebugEnabled()) |
| Logging.connectors.debug("JCIFS: Recorded path '"+newPath+"' is excluded!"); |
| } |
| } |
| else |
| Logging.connectors.debug("JCIFS: Excluding a child file because canonical path is null"); |
| |
| |
| return false; |
| } |
| catch (ManifoldCFException e) |
| { |
| if (lcfException == null) |
| lcfException = e; |
| return false; |
| } |
| catch (ServiceInterruption e) |
| { |
| if (serviceInterruption == null) |
| serviceInterruption = e; |
| return false; |
| } |
| } |
| |
| /** Check for exception, and throw if there is one */ |
| public void checkAndThrow() |
| throws ServiceInterruption, ManifoldCFException |
| { |
| if (lcfException != null) |
| throw lcfException; |
| if (serviceInterruption != null) |
| throw serviceInterruption; |
| } |
| } |
| |
| } |