/* $Id$ */
/**
* 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.jobs;
import org.apache.manifoldcf.core.interfaces.*;
import org.apache.manifoldcf.agents.interfaces.*;
import org.apache.manifoldcf.crawler.interfaces.*;
import java.util.*;
/** This class manages the "jobnotifications" table, which contains the ordered list of notification
* connections and their specification data.
*
* <br><br>
* <b>jobnotifications</b>
* <table border="1" cellpadding="3" cellspacing="0">
* <tr class="TableHeadingColor">
* <th>Field</th><th>Type</th><th>Description </th>
* <tr><td>ownerid</td><td>BIGINT</td><td>Reference:jobs.id</td></tr>
* <tr><td>ordinal</td><td>BIGINT</td><td></td></tr>
* <tr><td>notificationname</td><td>VARCHAR(32)</td><td></td></tr>
* <tr><td>connectiondesc</td><td>VARCHAR(255)</td><td></td></tr>
* <tr><td>connectionspec</td><td>LONGTEXT</td><td></td></tr>
* </table>
* <br><br>
*
*/
public class NotificationManager extends org.apache.manifoldcf.core.database.BaseTable
{
public static final String _rcsid = "@(#)$Id$";
// Schema
public final static String ownerIDField = "ownerid";
public final static String ordinalField = "ordinal";
public final static String notificationNameField = "notificationname";
public final static String connectionDescriptionField = "connectiondesc";
public final static String connectionSpecField = "connectionspec";
/** Constructor.
*@param threadContext is the thread context.
*@param database is the database instance.
*/
public NotificationManager(IThreadContext threadContext, IDBInterface database)
throws ManifoldCFException
{
super(database,"jobnotifications");
}
/** Install or upgrade.
*@param ownerTable is the name of the table that owns this one.
*@param owningTablePrimaryKey is the primary key of the owning table.
*/
public void install(String ownerTable, String owningTablePrimaryKey,
String notificationTableName, String notificationTableNameField)
throws ManifoldCFException
{
// Standard practice: Outer loop to support upgrades
while (true)
{
Map existing = getTableSchema(null,null);
if (existing == null)
{
HashMap map = new HashMap();
map.put(ownerIDField,new ColumnDescription("BIGINT",false,false,ownerTable,owningTablePrimaryKey,false));
map.put(ordinalField,new ColumnDescription("BIGINT",false,false,null,null,false));
map.put(notificationNameField,new ColumnDescription("VARCHAR(32)",false,true,notificationTableName,notificationTableNameField,false));
map.put(connectionDescriptionField,new ColumnDescription("VARCHAR(255)",false,true,null,null,false));
map.put(connectionSpecField,new ColumnDescription("LONGTEXT",false,true,null,null,false));
performCreate(map,null);
}
else
{
// Upgrade code goes here, if needed.
}
// Index management
IndexDescription ownerIndex = new IndexDescription(false,new String[]{ownerIDField});
IndexDescription notificationNameIndex = new IndexDescription(false,new String[]{notificationNameField});
// Get rid of indexes that shouldn't be there
Map indexes = getTableIndexes(null,null);
Iterator iter = indexes.keySet().iterator();
while (iter.hasNext())
{
String indexName = (String)iter.next();
IndexDescription id = (IndexDescription)indexes.get(indexName);
if (ownerIndex != null && id.equals(ownerIndex))
ownerIndex = null;
else if (notificationNameIndex != null && id.equals(notificationNameIndex))
notificationNameIndex = null;
else if (indexName.indexOf("_pkey") == -1)
// This index shouldn't be here; drop it
performRemoveIndex(indexName);
}
// Add the ones we didn't find
if (ownerIndex != null)
performAddIndex(null,ownerIndex);
if (notificationNameIndex != null)
performAddIndex(null,notificationNameIndex);
break;
}
}
/** Uninstall.
*/
public void deinstall()
throws ManifoldCFException
{
performDrop(null);
}
/** Build a query clause matching a set of notification connection names.
*/
public void buildNotificationQueryClause(StringBuilder query, ArrayList params,
String parentIDField, List<String> connectionNames)
{
query.append("SELECT 'x' FROM ").append(getTableName()).append(" WHERE ");
query.append(buildConjunctionClause(params,new ClauseDescription[]{
new JoinClause(parentIDField,ownerIDField),
new MultiClause(notificationNameField,connectionNames)}));
}
/** Get all the notification connection names for a job.
*@param ownerID is the job ID.
*@return the set of connection names.
*/
public String[] getNotificationConnectionNames(Long ownerID)
throws ManifoldCFException
{
ArrayList newList = new ArrayList();
StringBuilder query = new StringBuilder("SELECT ");
query.append(notificationNameField).append(" FROM ").append(getTableName()).append(" WHERE ");
query.append(buildConjunctionClause(newList,new ClauseDescription[]{
new UnitaryClause(ownerIDField,ownerID)}));
IResultSet set = performQuery(query.toString(),newList,null,null);
String[] rval = new String[set.getRowCount()];
for (int i = 0; i < set.getRowCount(); i++)
{
IResultRow row = set.getRow(i);
rval[i] = (String)row.getValue(notificationNameField);
}
return rval;
}
/** Fill in a set of notifications corresponding to a set of owner id's.
*@param returnValues is a map keyed by ownerID, with value of JobDescription.
*@param ownerIDList is the list of owner id's.
*@param ownerIDParams is the corresponding set of owner id parameters.
*/
public void getRows(Map<Long,JobDescription> returnValues, String ownerIDList, ArrayList ownerIDParams)
throws ManifoldCFException
{
IResultSet set = performQuery("SELECT * FROM "+getTableName()+" WHERE "+ownerIDField+" IN ("+ownerIDList+") ORDER BY "+ordinalField+" ASC",ownerIDParams,
null,null);
for (int i = 0; i < set.getRowCount(); i++)
{
IResultRow row = set.getRow(i);
Long ownerID = (Long)row.getValue(ownerIDField);
String notificationName = (String)row.getValue(notificationNameField);
String notificationDesc = (String)row.getValue(connectionDescriptionField);
String notificationSpec = (String)row.getValue(connectionSpecField);
JobDescription jd = returnValues.get(ownerID);
jd.addNotification(notificationName,notificationDesc).fromXML(notificationSpec);
}
}
/** Compare rows in job description with what's currently in the database.
*@param ownerID is the owning identifier.
*@param job is a job description.
*/
public boolean compareRows(Long ownerID, IJobDescription job)
throws ManifoldCFException
{
ArrayList params = new ArrayList();
String query = buildConjunctionClause(params,new ClauseDescription[]{
new UnitaryClause(ownerIDField,ownerID)});
IResultSet set = performQuery("SELECT * FROM "+getTableName()+" WHERE "+
query+" ORDER BY "+ordinalField+" ASC",params,null,null);
if (set.getRowCount() != job.countNotifications())
return false;
for (int i = 0; i < set.getRowCount(); i++)
{
IResultRow row = set.getRow(i);
String notificationConnectionName = (String)row.getValue(notificationNameField);
String spec = (String)row.getValue(connectionSpecField);
if (spec == null)
spec = "";
if (!job.getNotificationConnectionName(i).equals(notificationConnectionName))
return false;
if (!job.getNotificationSpecification(i).toXML().equals(spec))
return false;
}
return true;
}
/** Write a pipeline list into the database.
*@param ownerID is the owning identifier.
*@param job is the job description that is the source of the pipeline.
*/
public void writeRows(Long ownerID, IJobDescription job)
throws ManifoldCFException
{
beginTransaction();
try
{
HashMap map = new HashMap();
for (int i = 0; i < job.countNotifications(); i++)
{
String notificationConnectionName = job.getNotificationConnectionName(i);
String notificationDescription = job.getNotificationDescription(i);
Specification os = job.getNotificationSpecification(i);
map.clear();
map.put(ownerIDField,ownerID);
map.put(ordinalField,new Long((long)i));
map.put(notificationNameField,notificationConnectionName);
if (notificationDescription != null && notificationDescription.length() > 0)
map.put(connectionDescriptionField,notificationDescription);
map.put(connectionSpecField,os.toXML());
performInsert(map,null);
}
}
catch (ManifoldCFException e)
{
signalRollback();
throw e;
}
catch (Error e)
{
signalRollback();
throw e;
}
finally
{
endTransaction();
}
}
/** Delete rows.
*@param ownerID is the owner whose rows to delete.
*/
public void deleteRows(Long ownerID)
throws ManifoldCFException
{
ArrayList list = new ArrayList();
String query = buildConjunctionClause(list,new ClauseDescription[]{
new UnitaryClause(ownerIDField,ownerID)});
performDelete("WHERE "+query,list,null);
}
}