/**
* Copyright 2014 The Apache Software Foundation.
*
* Licensed 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.gridfs;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.DBTCPConnector;
import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.manifoldcf.agents.interfaces.RepositoryDocument;
import org.apache.manifoldcf.agents.interfaces.ServiceInterruption;
import org.apache.manifoldcf.core.interfaces.ConfigParams;
import org.apache.manifoldcf.core.interfaces.Specification;
import org.apache.manifoldcf.core.interfaces.IHTTPOutput;
import org.apache.manifoldcf.core.interfaces.IPasswordMapperActivity;
import org.apache.manifoldcf.core.interfaces.IPostParameters;
import org.apache.manifoldcf.core.interfaces.IThreadContext;
import org.apache.manifoldcf.core.interfaces.ManifoldCFException;
import org.apache.manifoldcf.crawler.connectors.BaseRepositoryConnector;
import org.apache.manifoldcf.crawler.interfaces.IProcessActivity;
import org.apache.manifoldcf.crawler.interfaces.ISeedingActivity;
import org.apache.manifoldcf.crawler.interfaces.IExistingVersions;
import org.apache.manifoldcf.crawler.system.Logging;
import org.bson.types.ObjectId;
/**
*
* @author molgun
*/
public class GridFSRepositoryConnector extends BaseRepositoryConnector {
/**
* Activity name for the activity record.
*/
protected static final String ACTIVITY_FETCH = "fetch";
/**
* Server name for declaring bin name.
*/
protected static final String SERVER = "MongoDB - GridFS";
/**
* Session expiration milliseconds.
*/
protected static final long SESSION_EXPIRATION_MILLISECONDS = 30000L;
/**
* Endpoint username.
*/
protected String username = null;
/**
* Endpoint password.
*/
protected String password = null;
/**
* Endpoint host.
*/
protected String host = null;
/**
* Endpoint port.
*/
protected String port = null;
/**
* Endpoint db.
*/
protected String db = null;
/**
* Endpoint bucket.
*/
protected String bucket = null;
/**
* Endpoint url.
*/
protected String url = null;
/**
* Endpoint acl.
*/
protected String acl = null;
/**
* Endpoint denyAcl.
*/
protected String denyAcl = null;
/**
* MongoDB session.
*/
protected DB session = null;
/**
* Last session fetch time.
*/
protected long lastSessionFetch = -1L;
/**
* Forward to the javascript to check the configuration parameters.
*/
private static final String EDIT_CONFIG_HEADER_FORWARD = "editConfiguration.js";
/**
* Forward to the HTML template to view the configuration parameters.
*/
private static final String VIEW_CONFIG_FORWARD = "viewConfiguration.html";
/**
* Forward to the HTML template to edit the configuration parameters.
*/
private static final String EDIT_CONFIG_FORWARD_SERVER = "editConfiguration_Server.html";
/**
* GridFS server tab name.
*/
private static final String GRIDFS_SERVER_TAB_RESOURCE = "GridFSConnector.Server";
/**
* Tab name parameter for managing the view of the Web UI.
*/
private static final String TAB_NAME_PARAM = "TabName";
/**
* Constructer.
*/
public GridFSRepositoryConnector() {
super();
}
/**
* Tell the world what model this connector uses for addSeedDocuments().
* This must return a model value as specified above. The connector does not
* have to be connected for this method to be called.
*
* @return the model type value.
*/
@Override
public String[] getBinNames(String documentIdentifier) {
return new String[]{host};
}
/**
* Tell the world what model this connector uses for addSeedDocuments().
* This must return a model value as specified above. The connector does not
* have to be connected for this method to be called.
*
* @return the model type value.
*/
@Override
public int getConnectorModel() {
return super.getConnectorModel();
}
/**
* Return the list of activities that this connector supports (i.e. writes
* into the log). The connector does not have to be connected for this
* method to be called.
*
* @return the list.
*/
@Override
public String[] getActivitiesList() {
return new String[]{ACTIVITY_FETCH};
}
/**
* Connect.
*
* @param configParams is the set of configuration parameters, which in this
* case describe the root directory.
*/
@Override
public void connect(ConfigParams configParams) {
super.connect(configParams);
username = params.getParameter(GridFSConstants.USERNAME_PARAM);
password = params.getObfuscatedParameter(GridFSConstants.PASSWORD_PARAM);
host = params.getParameter(GridFSConstants.HOST_PARAM);
port = params.getParameter(GridFSConstants.PORT_PARAM);
db = params.getParameter(GridFSConstants.DB_PARAM);
bucket = params.getParameter(GridFSConstants.BUCKET_PARAM);
url = params.getParameter(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM);
acl = params.getParameter(GridFSConstants.ACL_RETURN_FIELD_NAME_PARAM);
denyAcl = params.getParameter(GridFSConstants.DENY_ACL_RETURN_FIELD_NAME_PARAM);
}
/**
* Test the connection. Returns a string describing the connection
* integrity.
*
* @return the connection's status as a displayable string.
* @throws org.apache.manifoldcf.core.interfaces.ManifoldCFException
*/
@Override
public String check() throws ManifoldCFException {
try {
getSession();
if (session != null) {
Mongo currentMongoSession = session.getMongo();
currentMongoSession.getConnector()
.getDBPortPool(currentMongoSession.getAddress())
.get()
.ensureOpen();
session.getMongo().close();
session = null;
return super.check();
}
return "Not connected.";
} catch (ManifoldCFException e) {
return e.getMessage();
} catch (IOException ex) {
return ex.getMessage();
}
}
/**
* Close the connection. Call this before discarding this instance of the
* repository connector.
*
* @throws org.apache.manifoldcf.core.interfaces.ManifoldCFException
*/
@Override
public void disconnect() throws ManifoldCFException {
if (session != null) {
try {
session.getMongo().close();
} catch (Exception e) {
Logging.connectors.error("GridFS: Error when trying to disconnect: " + e.getMessage());
throw new ManifoldCFException("GridFS: Error when trying to disconnect: " + e.getMessage(), e);
}
session = null;
lastSessionFetch = -1L;
username = null;
password = null;
host = null;
port = null;
db = null;
bucket = null;
url = null;
acl = null;
denyAcl = null;
}
}
/**
* This method is periodically called for all connectors that are connected
* but not in active use.
*
* @throws org.apache.manifoldcf.core.interfaces.ManifoldCFException
*/
@Override
public void poll() throws ManifoldCFException {
if (lastSessionFetch == -1L) {
return;
}
long currentTime = System.currentTimeMillis();
if (currentTime >= lastSessionFetch + SESSION_EXPIRATION_MILLISECONDS) {
if (session != null) {
session.getMongo().close();
session = null;
}
lastSessionFetch = -1L;
}
}
/**
* This method is called to assess whether to count this connector instance
* should actually be counted as being connected.
*
* @return true if the connector instance is actually connected.
*/
@Override
public boolean isConnected() {
if (session == null) {
return false;
}
Mongo currentMongoSession = session.getMongo();
DBTCPConnector currentTCPConnection = currentMongoSession.getConnector();
return currentTCPConnection.isOpen();
}
/**
* Get the maximum number of documents to amalgamate together into one
* batch, for this connector.
*
* @return the maximum number. 0 indicates "unlimited".
*/
@Override
public int getMaxDocumentRequest() {
return super.getMaxDocumentRequest();
}
/**
* Return the list of relationship types that this connector recognizes.
*
* @return the list.
*/
@Override
public String[] getRelationshipTypes() {
return super.getRelationshipTypes();
}
/** 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 lastSeedVersionString 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();
DBCollection fsFiles = session.getCollection(
bucket + GridFSConstants.COLLECTION_SEPERATOR + GridFSConstants.FILES_COLLECTION_NAME
);
DBCursor dnc = fsFiles.find();
while (dnc.hasNext()) {
DBObject dbo = dnc.next();
String _id = dbo.get("_id").toString();
activities.addSeedDocument(_id);
if (Logging.connectors.isDebugEnabled()) {
Logging.connectors.debug("GridFS: Document _id = " + _id + " added to queue");
}
}
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 {
for (String documentIdentifier : documentIdentifiers) {
String versionString;
GridFS gfs;
GridFSDBFile document;
getSession();
String _id = documentIdentifier;
gfs = new GridFS(session, bucket);
document = gfs.findOne(new ObjectId(_id));
if (document == null) {
activities.deleteDocument(documentIdentifier);
continue;
} else {
DBObject metadata = document.getMetaData();
versionString = document.getMD5() + "+" + metadata != null
? Integer.toString(metadata.hashCode())
: StringUtils.EMPTY;
}
if (versionString.length() == 0 || activities.checkDocumentNeedsReindexing(documentIdentifier, versionString)) {
long startTime = System.currentTimeMillis();
String errorCode = null;
String errorDesc = null;
String version = versionString;
try {
if (Logging.connectors.isDebugEnabled()) {
Logging.connectors.debug("GridFS: Processing document _id = " + _id);
}
DBObject metadata = document.getMetaData();
if (metadata == null) {
errorCode = "NULLMETADATA";
errorDesc = "Excluded because document had a null Metadata";
Logging.connectors.warn("GridFS: Document " + _id + " has a null metadata - skipping.");
activities.noDocument(_id, version);
continue;
}
String urlValue = document.getMetaData().get(this.url) == null
? StringUtils.EMPTY
: document.getMetaData().get(this.url).toString();
if (!StringUtils.isEmpty(urlValue)) {
boolean validURL;
try {
new java.net.URI(urlValue);
validURL = true;
} catch (java.net.URISyntaxException e) {
validURL = false;
}
if (validURL) {
long fileLenght = document.getLength();
Date createdDate = document.getUploadDate();
String fileName = document.getFilename();
String mimeType = document.getContentType();
if (!activities.checkURLIndexable(urlValue)) {
Logging.connectors.warn("GridFS: Document " + _id + " has a URL excluded by the output connector ('" + urlValue + "') - skipping.");
errorCode = activities.EXCLUDED_URL;
errorDesc = "Excluded because of URL (" + urlValue + ")";
activities.noDocument(_id, version);
continue;
}
if (!activities.checkLengthIndexable(fileLenght)) {
Logging.connectors.warn("GridFS: Document " + _id + " has a length excluded by the output connector (" + fileLenght + ") - skipping.");
errorCode = activities.EXCLUDED_LENGTH;
errorDesc = "Excluded because of length (" + fileLenght + ")";
activities.noDocument(_id, version);
continue;
}
if (!activities.checkMimeTypeIndexable(mimeType)) {
Logging.connectors.warn("GridFS: Document " + _id + " has a mime type excluded by the output connector ('" + mimeType + "') - skipping.");
errorCode = activities.EXCLUDED_MIMETYPE;
errorDesc = "Excluded because of mime type (" + mimeType + ")";
activities.noDocument(_id, version);
continue;
}
if (!activities.checkDateIndexable(createdDate)) {
Logging.connectors.warn("GridFS: Document " + _id + " has a date excluded by the output connector (" + createdDate + ") - skipping.");
errorCode = activities.EXCLUDED_DATE;
errorDesc = "Excluded because of date (" + createdDate + ")";
activities.noDocument(_id, version);
continue;
}
RepositoryDocument rd = new RepositoryDocument();
rd.setCreatedDate(createdDate);
rd.setModifiedDate(createdDate);
rd.setFileName(fileName);
rd.setMimeType(mimeType);
String[] aclsArray = null;
String[] denyAclsArray = null;
if (acl != null) {
try {
Object aclObject = document.getMetaData().get(acl);
if (aclObject != null) {
List<String> acls = (List<String>) aclObject;
aclsArray = (String[]) acls.toArray();
}
} catch (ClassCastException e) {
// This is bad because security will fail
Logging.connectors.warn("GridFS: Document " + _id + " metadata ACL field doesn't contain List<String> type.");
errorCode = "ACLTYPE";
errorDesc = "Allow ACL field doesn't contain List<String> type.";
throw new ManifoldCFException("Security decoding error: " + e.getMessage(), e);
}
}
if (denyAcl != null) {
try {
Object denyAclObject = document.getMetaData().get(denyAcl);
if (denyAclObject != null) {
List<String> denyAcls = (List<String>) denyAclObject;
denyAcls.add(GLOBAL_DENY_TOKEN);
denyAclsArray = (String[]) denyAcls.toArray();
}
} catch (ClassCastException e) {
// This is bad because security will fail
Logging.connectors.warn("GridFS: Document " + _id + " metadata DenyACL field doesn't contain List<String> type.");
errorCode = "ACLTYPE";
errorDesc = "Deny ACL field doesn't contain List<String> type.";
throw new ManifoldCFException("Security decoding error: " + e.getMessage(), e);
}
}
rd.setSecurity(RepositoryDocument.SECURITY_TYPE_DOCUMENT, aclsArray, denyAclsArray);
InputStream is = document.getInputStream();
try {
rd.setBinary(is, fileLenght);
try {
activities.ingestDocumentWithException(_id, version, urlValue, rd);
} catch (IOException e) {
handleIOException(e);
}
} finally {
try {
is.close();
} catch (IOException e) {
handleIOException(e);
}
}
gfs.getDB().getMongo().close();
session = null;
errorCode = "OK";
} else {
Logging.connectors.warn("GridFS: Document " + _id + " has a invalid URL: " + urlValue + " - skipping.");
errorCode = activities.BAD_URL;
errorDesc = "Excluded because document had illegal URL ('" + urlValue + "')";
activities.noDocument(_id, version);
}
} else {
Logging.connectors.warn("GridFS: Document " + _id + " has a null URL - skipping.");
errorCode = activities.NULL_URL;
errorDesc = "Excluded because document had a null URL.";
activities.noDocument(_id, version);
}
} finally {
if (errorCode != null) {
activities.recordActivity(startTime, ACTIVITY_FETCH, document.getLength(), _id, errorCode, errorDesc, null);
}
}
}
}
}
protected static void handleIOException(IOException e) throws ManifoldCFException, ServiceInterruption {
if (e instanceof InterruptedIOException) {
throw new ManifoldCFException(e.getMessage(), e, ManifoldCFException.INTERRUPTED);
} else {
throw new ManifoldCFException(e.getMessage(), e);
}
}
/**
* 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. The connector does not
* need to be connected for this method to be called.
*
* @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.
* @throws org.apache.manifoldcf.core.interfaces.ManifoldCFException
* @throws java.io.IOException
*/
@Override
public void outputConfigurationHeader(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters, List<String> tabsArray) throws ManifoldCFException, IOException {
tabsArray.add(Messages.getString(locale, GRIDFS_SERVER_TAB_RESOURCE));
Map<String, String> paramMap = new HashMap<String, String>();
fillInServerParameters(paramMap, out, parameters);
Messages.outputResourceWithVelocity(out, locale, EDIT_CONFIG_HEADER_FORWARD, paramMap, true);
}
/**
* 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 always
* "editconnection". The connector does not need to be connected for this
* method to be called.
*
* @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 {
Map<String, String> paramMap = new HashMap<String, String>();
paramMap.put(TAB_NAME_PARAM, tabName);
fillInServerParameters(paramMap, out, parameters);
Messages.outputResourceWithVelocity(out, locale, EDIT_CONFIG_FORWARD_SERVER, paramMap, true);
}
/**
* 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 always "editconnection". The connector does not
* need to be connected for this method to be called.
*
* @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 username = variableContext.getParameter(GridFSConstants.USERNAME_PARAM);
if (username != null) {
parameters.setParameter(GridFSConstants.USERNAME_PARAM, username);
}
String password = variableContext.getParameter(GridFSConstants.PASSWORD_PARAM);
if (password != null) {
parameters.setObfuscatedParameter(GridFSConstants.PASSWORD_PARAM, variableContext.mapKeyToPassword(password));
}
String db = variableContext.getParameter(GridFSConstants.DB_PARAM);
if (db != null) {
parameters.setParameter(GridFSConstants.DB_PARAM, db);
}
String bucket = variableContext.getParameter(GridFSConstants.BUCKET_PARAM);
if (bucket != null) {
parameters.setParameter(GridFSConstants.BUCKET_PARAM, bucket);
}
String port = variableContext.getParameter(GridFSConstants.PORT_PARAM);
if (port != null) {
parameters.setParameter(GridFSConstants.PORT_PARAM, port);
}
String host = variableContext.getParameter(GridFSConstants.HOST_PARAM);
if (host != null) {
parameters.setParameter(GridFSConstants.HOST_PARAM, host);
}
String url = variableContext.getParameter(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM);
if (url != null) {
parameters.setParameter(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM, url);
}
String acl = variableContext.getParameter(GridFSConstants.ACL_RETURN_FIELD_NAME_PARAM);
if (acl != null) {
parameters.setParameter(GridFSConstants.ACL_RETURN_FIELD_NAME_PARAM, acl);
}
String denyAcl = variableContext.getParameter(GridFSConstants.DENY_ACL_RETURN_FIELD_NAME_PARAM);
if (denyAcl != null) {
parameters.setParameter(GridFSConstants.DENY_ACL_RETURN_FIELD_NAME_PARAM, denyAcl);
}
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. The connector does not need to be connected for this
* method to be called.
*
* @param threadContext is the local thread context.
* @param out is the output to which any HTML should be sent.
* @param parameters are the configuration parameters, as they currently
* exist, for this connection being configured.
*/
@Override
public void viewConfiguration(IThreadContext threadContext, IHTTPOutput out, Locale locale, ConfigParams parameters) throws ManifoldCFException, IOException {
Map<String, String> paramMap = new HashMap<String, String>();
fillInServerParameters(paramMap, out, parameters);
Messages.outputResourceWithVelocity(out, locale, VIEW_CONFIG_FORWARD, paramMap, true);
}
/**
* Setup a session.
*
* @throws ManifoldCFException
*/
protected void getSession() throws ManifoldCFException {
if (session == null) {
if (StringUtils.isEmpty(db) || StringUtils.isEmpty(bucket)) {
throw new ManifoldCFException("GridFS: Database or bucket name cannot be empty.");
}
if (StringUtils.isEmpty(url)) {
throw new ManifoldCFException("GridFS: Metadata URL field cannot be empty.");
}
if (StringUtils.isEmpty(host) && StringUtils.isEmpty(port)) {
try {
session = new MongoClient().getDB(db);
} catch (UnknownHostException ex) {
throw new ManifoldCFException("GridFS: Default host is not found. Does mongod process run?" + ex.getMessage(), ex);
}
} else if (!StringUtils.isEmpty(host) && StringUtils.isEmpty(port)) {
try {
session = new MongoClient(host).getDB(db);
} catch (UnknownHostException ex) {
throw new ManifoldCFException("GridFS: Given host information is not valid or mongod process doesn't run" + ex.getMessage(), ex);
}
} else if (!StringUtils.isEmpty(host) && !StringUtils.isEmpty(port)) {
try {
int integerPort = Integer.parseInt(port);
session = new MongoClient(host, integerPort).getDB(db);
} catch (UnknownHostException ex) {
throw new ManifoldCFException("GridFS: Given information is not valid or mongod process doesn't run" + ex.getMessage(), ex);
} catch (NumberFormatException ex) {
throw new ManifoldCFException("GridFS: Given port is not valid number. " + ex.getMessage(), ex);
}
} else if (StringUtils.isEmpty(host) && !StringUtils.isEmpty(port)) {
try {
int integerPort = Integer.parseInt(port);
session = new MongoClient(host, integerPort).getDB(db);
} catch (UnknownHostException ex) {
throw new ManifoldCFException("GridFS: Given information is not valid or mongod process doesn't run" + ex.getMessage(), ex);
} catch (NumberFormatException ex) {
throw new ManifoldCFException("GridFS: Given port is not valid number. " + ex.getMessage(), ex);
}
}
if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
boolean auth = session.authenticate(username, password.toCharArray());
if (!auth) {
throw new ManifoldCFException("GridFS: Given database username and password doesn't match.");
}
}
lastSessionFetch = System.currentTimeMillis();
}
}
/**
* Fill in a Server tab configuration parameter map for calling a Velocity
* template.
*
* @param paramMap is the map to fill in
* @param parameters is the current set of configuration parameters
*/
public void fillInServerParameters(Map<String, String> paramMap, IPasswordMapperActivity mapper, ConfigParams parameters) {
String usernameParam = parameters.getParameter(GridFSConstants.USERNAME_PARAM);
paramMap.put(GridFSConstants.USERNAME_PARAM, usernameParam);
String passwordParam = parameters.getObfuscatedParameter(GridFSConstants.PASSWORD_PARAM);
if (passwordParam == null) {
passwordParam = StringUtils.EMPTY;
} else {
passwordParam = mapper.mapPasswordToKey(passwordParam);
}
paramMap.put(GridFSConstants.PASSWORD_PARAM, passwordParam);
String dbParam = parameters.getParameter(GridFSConstants.DB_PARAM);
if (StringUtils.isEmpty(dbParam)) {
dbParam = GridFSConstants.DEFAULT_DB_NAME;
}
paramMap.put(GridFSConstants.DB_PARAM, dbParam);
String bucketParam = parameters.getParameter(GridFSConstants.BUCKET_PARAM);
if (StringUtils.isEmpty(bucketParam)) {
bucketParam = GridFSConstants.DEFAULT_BUCKET_NAME;
}
paramMap.put(GridFSConstants.BUCKET_PARAM, bucketParam);
String hostParam = parameters.getParameter(GridFSConstants.HOST_PARAM);
paramMap.put(GridFSConstants.HOST_PARAM, hostParam);
String portParam = parameters.getParameter(GridFSConstants.PORT_PARAM);
paramMap.put(GridFSConstants.PORT_PARAM, portParam);
String urlParam = parameters.getParameter(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM);
paramMap.put(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM, urlParam);
String aclParam = parameters.getParameter(GridFSConstants.ACL_RETURN_FIELD_NAME_PARAM);
paramMap.put(GridFSConstants.ACL_RETURN_FIELD_NAME_PARAM, aclParam);
String denyAclParam = parameters.getParameter(GridFSConstants.DENY_ACL_RETURN_FIELD_NAME_PARAM);
paramMap.put(GridFSConstants.DENY_ACL_RETURN_FIELD_NAME_PARAM, denyAclParam);
}
/**
* Special column names, as far as document queries are concerned
*/
protected static HashMap documentKnownColumns;
static {
documentKnownColumns = new HashMap();
documentKnownColumns.put(GridFSConstants.DEFAULT_ID_FIELD_NAME, "");
documentKnownColumns.put(GridFSConstants.URL_RETURN_FIELD_NAME_PARAM, "");
}
/**
* Apply metadata to a repository document.
*
* @param rd is the repository document to apply the metadata to.
* @param metadataMap is the resultset row to use to get the metadata. All
* non-special columns from this row will be considered to be metadata.
*/
protected void applyMetadata(RepositoryDocument rd, DBObject metadataMap)
throws ManifoldCFException {
// Cycle through the document's fields
Iterator iter = metadataMap.keySet().iterator();
while (iter.hasNext()) {
String fieldName = (String) iter.next();
if (documentKnownColumns.get(fieldName) == null) {
// Consider this field to contain metadata.
// We can only accept non-binary metadata at this time.
Object metadata = metadataMap.get(fieldName);
if (!(metadata instanceof String)) {
throw new ManifoldCFException("Metadata field '" + fieldName + "' must be convertible to a string.");
}
rd.addField(fieldName, metadata.toString());
}
}
}
}