/*
MacSyncMaster.java
Provides delta sync channel augmentation for the Mac Sync Channel.
Created: 23 February 2010
Module By: Jonathan Abbey, jonabbey@arlut.utexas.edu
-----------------------------------------------------------------------
Ganymede Directory Management System
Copyright (C) 1996-2012
The University of Texas at Austin
Ganymede is a registered trademark of The University of Texas at Austin
Contact information
Author Email: ganymede_author@arlut.utexas.edu
Email mailing list: ganymede@arlut.utexas.edu
US Mail:
Computer Science Division
Applied Research Laboratories
The University of Texas at Austin
PO Box 8029, Austin TX 78713-8029
Telephone: (512) 835-3200
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package arlut.csd.ganymede.gasharl;
import java.util.ArrayList;
import java.util.List;
import arlut.csd.ganymede.common.*;
import arlut.csd.ganymede.server.*;
/*------------------------------------------------------------------------------
class
MacSyncMaster
------------------------------------------------------------------------------*/
/**
* Provides delta sync channel augmentation for the Mac Sync Channel.
*/
public class MacSyncMaster implements SyncMaster {
private DBSession session;
/* -- */
public MacSyncMaster()
{
}
/**
* The augment() method optionally adds DBObject and DBField
* identifiers to the FieldBook book parameter if the SyncMaster
* decides that the additional DBObject/DBFields need to be written
* to a delta sync channel in response to the changes made to obj.
*/
public synchronized void augment(FieldBook book, DBEditObject obj)
{
this.session = obj.getDBSession();
try
{
switch (obj.getTypeID())
{
case SchemaConstants.UserBase:
includeUser(book, obj);
return;
case volumeSchema.BASE:
includeVolume(book, obj);
return;
case systemSchema.BASE:
includeSystem(book, obj);
return;
}
}
finally
{
this.session = null;
}
}
/**
* If a user is being modified, we need to make sure we link in
* the edit-in-place object definition for their auto.home.default
* map entry, the volume object, and the system object, so that
* the external mac sync channel scripting can resolve the nfs
* home directory.
*/
private void includeUser(FieldBook book, DBObject user)
{
if (!(user instanceof DBEditObject))
{
// if we're putting in a user as a non-edited context object
// for a host or volume redefinition, force the necessary
// fields to make sense of that.
includeUserFields(book, user);
}
List<Invid> mapEntries = (List<Invid>) user.getFieldValuesLocal(userSchema.VOLUMES);
for (Invid invid: mapEntries)
{
book.add(invid, mapEntrySchema.MAP);
book.add(invid, mapEntrySchema.VOLUME);
DBObject automounterMap = session.viewDBObject(invid);
Invid volumeInvid = (Invid) automounterMap.getFieldValueLocal(mapEntrySchema.VOLUME);
DBObject volumeObject = session.viewDBObject(volumeInvid);
Invid hostInvid = (Invid) volumeObject.getFieldValueLocal(volumeSchema.HOST);
book.add(volumeInvid, volumeSchema.HOST);
book.add(volumeInvid, volumeSchema.PATH);
book.add(hostInvid, systemSchema.SYSTEMNAME);
}
return;
}
/**
* If a volume is being modified, we need to scan to see if any
* users have that volume as a home directory in automounter, and
* if so we need to include those user objects and linked volume
* and system objects.
*/
private void includeVolume(FieldBook book, DBObject volume)
{
try
{
GanymedeSession gSession = session.getGSession();
String label = volume.getLabel();
String queryString = "select object from 'User' where 'Directory Volume'->('NFS Volume'->('Volume Label' == '" + label + "'))";
Query query = new GanyQueryTransmuter().transmuteQueryString(queryString);
List<Result> results = gSession.internalQuery(query);
for (Result result: results)
{
includeUser(book, session.viewDBObject(result.getInvid()));
}
}
catch (GanyParseException ex)
{
throw new RuntimeException(ex);
}
}
/**
* If a system is being modified such that its host name is being
* changed, we need to scan to see if any volumes are linked to
* that system, and if any users have their home directories on
* that volume, we need to include those user objects
*/
private void includeSystem(FieldBook book, DBObject system)
{
try
{
GanymedeSession gSession = session.getGSession();
String label = system.getLabel();
String queryString = "select object from 'User' where 'Directory Volume'->('NFS Volume'->('Host' == '" + label + "'))";
Query query = new GanyQueryTransmuter().transmuteQueryString(queryString);
List<Result> results = gSession.internalQuery(query);
for (Result result: results)
{
includeUser(book, session.viewDBObject(result.getInvid()));
}
}
catch (GanyParseException ex)
{
throw new RuntimeException(ex);
}
}
/**
* This method is called when includeVolume() or includeSystem()
* triggers the inclusion of a user.
*/
private void includeUserFields(FieldBook book, DBObject user)
{
Invid userInvid = user.getInvid();
if (book.has(userInvid))
{
// the user is already in the field book, we won't add
// anything
return;
}
book.add(userInvid, userSchema.USERNAME);
book.add(userInvid, userSchema.UID);
book.add(userInvid, userSchema.GUID);
book.add(userInvid, userSchema.VOLUMES);
}
}