[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Phpgroupware-cvs] sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyn
From: |
nomail |
Subject: |
[Phpgroupware-cvs] sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java, 1.2 |
Date: |
Wed, 9 Jun 2004 20:35:09 +0200 |
Update of /sync/sync4j/de/probusiness/pbgroupware/sync
Modified Files:
Branch:
PHPGwSyncStrategy.java
date: 2004/06/09 18:35:09; author: mkaemmerer; state: Exp; lines: +366 -28
Log Message:
- new sourceinfo and mimetype handling
=====================================================================
Index: sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java
diff -u sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java:1.1
sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java:1.2
--- sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java:1.1
Wed Apr 14 17:49:25 2004
+++ sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java Wed Jun
9 18:35:09 2004
@@ -10,6 +10,8 @@
import java.util.*;
import java.util.logging.*;
+import org.apache.xmlrpc.*;
+
import sync4j.framework.core.*;
import sync4j.framework.engine.*;
import sync4j.framework.engine.source.*;
@@ -26,15 +28,15 @@
public class PHPGwSyncStrategy extends Sync4jStrategy {
private static interface ConflictAction {
- public Sync4jOperationStatus handleConflict(
+ public Sync4jOperationStatus[] handleConflict(
final SyncOperationImpl op, final Principal
owner,
SyncItem a, SyncItem b,
final SyncSource source0, final SyncSource
source1
);
}
- private static final class AWinsCOnflictAction implements
ConflictAction {
- public Sync4jOperationStatus handleConflict(final
SyncOperationImpl op, final Principal owner,
+ private static final class AWinsConflictAction implements
ConflictAction {
+ public Sync4jOperationStatus[] handleConflict(final
SyncOperationImpl op, final Principal owner,
SyncItem a, SyncItem b,
final SyncSource source0, final SyncSource
source1) {
final ModificationCommand cmd = (ModificationCommand)
a.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
@@ -42,17 +44,81 @@
a = source1.setSyncItem(owner, b);
op.setSyncItemA(a);
op.setAOperation(true);
- return new Sync4jOperationStatusConflict(op,
source1, cmd, StatusCode.CONFLICT_RESOLVED_WITH_SERVER_DATA);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusConflict(op,
source1, cmd, StatusCode.CONFLICT_RESOLVED_WITH_SERVER_DATA)
+ };
} catch (SyncException e) {
log.severe("Error executing sync operation: " +
e.getMessage());
log.throwing(getClass().getName(),
"execSyncOperation", e);
- return new Sync4jOperationStatusError(op,
source1, cmd, e);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusError(op,
source1, cmd, e)
+ };
}
}
}
- private static final class BWinsCOnflictAction implements
ConflictAction {
- public Sync4jOperationStatus handleConflict(
+ private static final class DuplicateConflictAction implements
ConflictAction {
+ public Sync4jOperationStatus[] handleConflict(final
SyncOperationImpl op, final Principal owner,
+ SyncItem a, SyncItem b,
+ final SyncSource source0, final SyncSource
source1) {
+ final ModificationCommand cmd = (ModificationCommand)
a.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ final SyncItem buf = a;
+ // so for duplicate we first perform the same as if the
server would win:
+ final Set stats = new HashSet();
+ try {
+ a = source1.setSyncItem(owner, b);
+ op.setSyncItemA(a);
+ op.setAOperation(true);
+ stats.add(
+ new Sync4jOperationStatusConflict(op,
source1, cmd, StatusCode.CONFLICT_RESOLVED_WITH_SERVER_DATA)
+ );
+ } catch (SyncException e) {
+ log.severe("Error executing sync operation: " +
e.getMessage());
+ log.throwing(getClass().getName(),
"execSyncOperation", e);
+ stats.add(
+ new Sync4jOperationStatusError(op,
source1, cmd, e)
+ );
+ }
+ // then we take the other item, generating a new key
for it by prepending "duped" to its
+ // textual representation:
+ final SyncItemKey oldkey = buf.getKey();
+ final SyncItem newItem = new SyncItemImpl(source1,
"duped" + oldkey.getKeyAsString());
+ final SyncProperty dataprop = new SyncProperty(
+ SyncItem.PROPERTY_BINARY_CONTENT,
buf.getPropertyValue(SyncItem.PROPERTY_BINARY_CONTENT)
+ );
+ final SyncProperty timeprop = new SyncProperty(
+ SyncItem.PROPERTY_TIMESTAMP,
buf.getPropertyValue(SyncItem.PROPERTY_TIMESTAMP)
+ );
+ newItem.setProperty(dataprop);
+ newItem.setProperty(timeprop);
+ // then we put the new item into both of the sources
+ // I can only hope, that the state- and
item-assignement-handling is correct
+ try {
+ source0.setSyncItem(owner, newItem);
+ source1.setSyncItem(owner, newItem);
+ // INFO changed itemstate-behaviour here
+ // INFO comment out next three line if still
not working
+ // newItem.setState(SyncItemState.SYNCHRONIZED);
+ newItem.setState(SyncItemState.NEW);
+ op.setSyncItemB(newItem);
+ op.setBOperation(true);
+ stats.add(
+ new Sync4jOperationStatusConflict(op,
source0, cmd, StatusCode.CONFLICT_RESOLVED_WITH_DUPLICATE)
+ );
+ }
+ catch (final SyncException e) {
+ log.severe("Error executing sync operation: " +
e.getMessage());
+ log.throwing(getClass().getName(),
"execSyncOperation", e);
+ stats.add(
+ new Sync4jOperationStatusError(op,
source0, cmd, e)
+ );
+ }
+ return (Sync4jOperationStatus[]) stats.toArray(new
Sync4jOperationStatus[stats.size()]);
+ }
+ }
+
+ private static final class BWinsConflictAction implements
ConflictAction {
+ public Sync4jOperationStatus[] handleConflict(
final SyncOperationImpl op, final Principal
owner,
SyncItem a, SyncItem b,
final SyncSource source0, final SyncSource
source1) {
@@ -63,75 +129,226 @@
b = source0.setSyncItem(owner, a);
op.setSyncItemB(b);
op.setBOperation(true);
- return new Sync4jOperationStatusConflict(op,
source0, cmd, StatusCode.CONFLICT_RESOLVED_WITH_CLIENT_COMMAND_WINNING);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusConflict(op,
source0, cmd, StatusCode.CONFLICT_RESOLVED_WITH_CLIENT_COMMAND_WINNING)
+ };
} catch (SyncException e) {
log.severe("Error executing sync operation: " +
e.getMessage());
log.throwing(getClass().getName(),
"execSyncOperation", e);
- return new Sync4jOperationStatusError(op,
source0, cmd, e);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusError(op,
source0, cmd, e)
+ };
}
}
}
+ private static final class DoNothingConflictAction implements
ConflictAction {
+ public Sync4jOperationStatus[] handleConflict(final
SyncOperationImpl op, final Principal owner,
+ SyncItem a, SyncItem b,
+ final SyncSource source0, final SyncSource
source1) {
+ log.finest("starting to do nothing");
+ if (op.isBOperation()) {
+ // don't know why to use here the a-command,
but the original strategy
+ // does so and so do we now...
+ //ModificationCommand cmd =
(ModificationCommand) b.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ ModificationCommand cmd = (ModificationCommand)
a.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusOK(op,
source0, cmd)
+ };
+ }
+ else { // is op.isAOperation
+ ModificationCommand cmd = (ModificationCommand)
a.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ return new Sync4jOperationStatus[] {
+ new Sync4jOperationStatusOK(op,
source1, cmd)
+ };
+ }
+ }
+ }
+
private static final Map CONFLICT_ACTIONS;
static {
final Map m = new HashMap();
- m.put("serverwins", new AWinsCOnflictAction());
- m.put("clientwins", new BWinsCOnflictAction());
+ m.put("serverwins", new AWinsConflictAction());
+ m.put("clientwins", new BWinsConflictAction());
+ m.put("donothing", new DoNothingConflictAction());
+ m.put("duplicate", new DuplicateConflictAction());
CONFLICT_ACTIONS = Collections.unmodifiableMap(m);
}
protected static transient Logger log = Sync4jLogger.getLogger();
+ public static final String CONTENT_TYPE_KEY_TYPE = "contentType.type";
+ public static final String CONTENT_TYPE_KEY_VERSION =
"contentType.version";
+
/**
*
*/
public PHPGwSyncStrategy() {
super();
- // TODO Auto-generated constructor stub
}
/**
* @param syncSources
*/
- public PHPGwSyncStrategy(SyncSource[] syncSources) {
+ public PHPGwSyncStrategy(final SyncSource[] syncSources) {
super(syncSources);
- // TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see
sync4j.server.engine.Sync4jStrategy#execSyncOperation(sync4j.framework.engine.SyncOperationImpl)
*/
- protected SyncOperationStatus[] execSyncOperation(SyncOperationImpl
operation) {
- SyncItem syncItemA = operation.getSyncItemA();
- SyncItem syncItemB = operation.getSyncItemB();
- final Principal owner = operation.getOwner();
- final SyncSource[] sources = getSources();
+ protected SyncOperationStatus[] execSyncOperation(final
SyncOperationImpl operation) {
+ log.fine("start executing sync-op");
if (operation.getOperation() == SyncOperation.CONFLICT) {
+ SyncItem syncItemA = operation.getSyncItemA();
+ SyncItem syncItemB = operation.getSyncItemB();
+ final Principal owner = operation.getOwner();
+ final SyncSource[] sources = getSources();
+ log.fine("found conflict; preparing xml-rpc-call");
final Vector params = new Vector();
params.add(syncItemA.getKey().getKeyAsString());
- params.add(syncItemB.getKey().getKeyAsString());
+ final Object clientData =
syncItemA.getPropertyValue(SyncItem.PROPERTY_BINARY_CONTENT);
+ log.finer("found client-item; data is of type (" +
clientData.getClass().getName() + ")");
+ if (clientData instanceof String) {
+ params.add(clientData);
+ }
+ else if (clientData instanceof byte[]) {
+ params.add(new String(Base64.encode((byte[])
clientData)));
+ }
+ else {
+ params.add(clientData.toString());
+ }
+
Object ret = null;
try {
- ret = executeXMLRPC(owner, "handleConflict",
params);
+ log.fine("executing xml-rpc-call");
+ ret = executeXMLRPC(owner, sources[1],
"handleConflict", params);
+ log.fine("executed xml-rpc-call");
}
catch (final SyncSourceException e) {
- // TODO logging
+ log.severe("Error executing sync operation: " +
e.getMessage());
+ log.throwing(getClass().getName(),
"execSyncOperation", e);
+ final ModificationCommand cmd =
(ModificationCommand)
syncItemA.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ return new SyncOperationStatus[] {
+ new
Sync4jOperationStatusError(operation, sources[1], cmd, e)
+ };
}
if (ret != null) {
- final ConflictAction action = (ConflictAction)
CONFLICT_ACTIONS.get(ret);
+ log.fine("conflict-action returned; dispatch
handling (" + ret + ")");
+ final ConflictAction action = (ConflictAction)
CONFLICT_ACTIONS.get(ret.toString().toLowerCase());
if (action != null) {
- return new SyncOperationStatus[] {
-
action.handleConflict(operation, owner, syncItemA, syncItemB, sources[0],
sources[1])
- };
+ log.fine("conflict-action resolved;
action (" + action.getClass().getName() + ")");
+ return action.handleConflict(operation,
owner, syncItemA, syncItemB, sources[0], sources[1]);
}
}
}
return super.execSyncOperation(operation);
}
- private final Object executeXMLRPC(final Principal principal, final
String methodname, final Vector params) throws SyncSourceException {
- // prepend device_id to parameter-list
+ private static interface AB {
+ public SyncItem getSyncItem(SyncOperation op);
+ public void setSyncItem(SyncOperation op, SyncItem item);
+ }
+ private static final AB AB_AOP = new AB() {
+ public final SyncItem getSyncItem(final SyncOperation op) {
+ return op.getSyncItemB();
+ }
+ public final void setSyncItem(final SyncOperation op, final
SyncItem item) {
+ op.setSyncItemA(item);
+ }
+ };
+ private static final AB AB_BOP = new AB() {
+ public final SyncItem getSyncItem(final SyncOperation op) {
+ return op.getSyncItemA();
+ }
+ public final void setSyncItem(final SyncOperation op, final
SyncItem item) {
+ op.setSyncItemB(item);
+ }
+ };
+
+ private final Collection executeBulkSet(final Collection ops) {
+ // dividing in A- and B-operations and sorting by owner
+ final Map aops = new LinkedHashMap();
+ final Map bops = new LinkedHashMap();
+ for (final Iterator it = ops.iterator(); it.hasNext();) {
+ final SyncOperation op = (SyncOperation) it.next();
+ final Principal owner = op.getOwner();
+ final Map toPut;
+ if (op.isAOperation()) {
+ toPut = aops;
+ }
+ else {
+ toPut = bops;
+ }
+ Collection ownerops = (Collection) toPut.get(owner);
+ if (ownerops == null) {
+ ownerops = new LinkedHashSet();
+ toPut.put(owner, ownerops);
+ }
+ ownerops.add(op);
+ }
+ // preparing
+ final SyncSource[] sources = getSources();
+ final Collection status = new LinkedList();
+ // executing
+ executeBulkSet(aops, sources[1], status, AB_AOP);
+ executeBulkSet(bops, sources[0], status, AB_BOP);
+ return status;
+ }
+
+ /**
+ * @param operationsMap
+ * @param sources
+ * @param status
+ */
+ private void executeBulkSet(final Map operationsMap, final SyncSource
source, final Collection status, final AB ab) {
+ // handling A-operations
+ for (final Iterator it = operationsMap.entrySet().iterator();
it.hasNext();) {
+ final Map.Entry entry = (Map.Entry) it.next();
+ final Principal owner = (Principal) entry.getKey();
+ final Collection operations = (Collection)
entry.getValue();
+ final SyncItem[] bitems = new
SyncItem[operations.size()];
+ int i = 0;
+ for (final Iterator jt = operations.iterator();
jt.hasNext(); i++) {
+ final SyncOperation op = (SyncOperation)
jt.next();
+ bitems[i] = ab.getSyncItem(op);
+ }
+ SyncItem[] aitems = null;
+ try {
+ aitems = source.setSyncItems(owner, bitems);
+ }
+ catch (final SyncSourceException e) {
+ log.severe("Error executing sync operation: " +
e.getMessage());
+ log.throwing(getClass().getName(),
"execSyncOperation", e);
+ for (final Iterator jt = operations.iterator();
jt.hasNext(); i++) {
+ final SyncOperation op =
(SyncOperation) jt.next();
+ final SyncItem aitem = aitems[i];
+ final ModificationCommand cmd =
+ (ModificationCommand)
aitem.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ status.add(new
Sync4jOperationStatusError(op, source, cmd, e));
+ }
+ }
+ i = 0;
+ for (final Iterator jt = operations.iterator();
jt.hasNext(); i++) {
+ final SyncOperation op = (SyncOperation)
jt.next();
+ final SyncItem aitem = aitems[i];
+ final ModificationCommand cmd =
+ (ModificationCommand)
aitem.getPropertyValue(SyncItemHelper.PROPERTY_COMMAND);
+ ab.setSyncItem(op, aitem);
+ status.add(new Sync4jOperationStatusOK(op,
source, cmd));
+ }
+ }
+ }
+
+// private final Collection executeBulkDelete(final Collection ops) {
+// // TODO
+// return null;
+// }
+
+ private final Object executeXMLRPC(final Principal principal, final
SyncSource source, final String methodname, final Vector params) throws
SyncSourceException {
+ // prepend device_id and source-name to parameter-list
params.add(0, ((Sync4jPrincipal) principal).getId());
+ params.add(1, source.getName());
// prepare ipc-dispatch
final Vector fparams = new Vector();
fparams.add("sync." + methodname);
@@ -139,4 +356,125 @@
return
PHPGwSyncXMLRPCClient.getInstance().execute("phpgwapi.ipc_manager.execIPC",
fparams);
}
+ /* (non-Javadoc)
+ * @see
sync4j.server.engine.Sync4jStrategy#checkSyncOperation(java.security.Principal,
sync4j.framework.engine.SyncItem, sync4j.framework.engine.SyncItem)
+ */
+ protected SyncOperation checkSyncOperation(final Principal principal,
final SyncItem syncItemA, final SyncItem syncItemB) {
+ log.fine("intercepting sync-op");
+ SyncOperation op = super.checkSyncOperation(principal,
syncItemA, syncItemB);
+ log.fine("!!!!!: found sync-op -> " + op);
+ if (op instanceof SyncConflict) {
+ log.fine("found conflict (" + op + ")");
+ op = new PHPGwSyncConflict((SyncConflict) op,
principal);
+ log.fine("replaced conflict with: <" + op + ">");
+ }
+ return op;
+ }
+
+ private static final void publishSourceInfo(final Principal principal,
final SyncSource clsource) {
+ final SyncSourceInfo info = clsource.getInfo();
+ final ContentType[] supportedTypes = info.getSupportedTypes();
+ final int len = supportedTypes.length;
+ final Vector xrtypes = new Vector(len);
+ for (int i = 0; i < len; i++) {
+ final ContentType type = supportedTypes[i];
+ final Hashtable xrtype = new Hashtable();
+ xrtype.put(CONTENT_TYPE_KEY_TYPE, type.getType());
+ xrtype.put(CONTENT_TYPE_KEY_VERSION, type.getVersion());
+ xrtypes.add(xrtype);
+ }
+ if (xrtypes.isEmpty()) {
+ final ContentType type = info.getPreferredType();
+ final Hashtable xrtype = new Hashtable();
+ xrtype.put(CONTENT_TYPE_KEY_TYPE, type.getType());
+ xrtype.put(CONTENT_TYPE_KEY_VERSION, type.getVersion());
+ xrtypes.add(xrtype);
+ }
+
+
+ final Vector params = new Vector();
+ // prepend device_id to parameter-list
+ params.add(((Sync4jPrincipal) principal).getId());
+ params.add(xrtypes);
+ // prepare ipc-dispatch
+ final Vector fparams = new Vector();
+ fparams.add("sync.setSourceInfoSupportedTypes");
+ fparams.add(params);
+ try {
+
PHPGwSyncXMLRPCClient.getInstance().execute("phpgwapi.ipc_manager.execIPC",
fparams);
+ }
+ catch (final SyncSourceException e) {
+ log.throwing(PHPGwSyncStrategy.class.getName(), "error
publishing SyncSourceInfo.supportedTypes", e);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see
sync4j.framework.engine.SyncStrategy#prepareFastSync(sync4j.framework.engine.source.SyncSource[],
java.security.Principal, java.sql.Timestamp)
+ */
+ public SyncOperation[] prepareFastSync(final SyncSource[] sources,
final Principal principal, final java.sql.Timestamp since) throws SyncException
{
+ publishSourceInfo(principal, sources[0]);
+ return super.prepareFastSync(sources, principal, since);
+ }
+
+ /* (non-Javadoc)
+ * @see
sync4j.framework.engine.SyncStrategy#prepareSlowSync(sync4j.framework.engine.source.SyncSource[],
java.security.Principal)
+ */
+ public SyncOperation[] prepareSlowSync(final SyncSource[] sources,
final Principal principal) throws SyncException {
+ publishSourceInfo(principal, sources[0]);
+ return super.prepareSlowSync(sources, principal);
+ }
+
+ /* (non-Javadoc)
+ * @see
sync4j.framework.engine.SyncStrategy#sync(sync4j.framework.engine.SyncOperation[])
+ */
+ public SyncOperationStatus[] sync(final SyncOperation[] syncOperations)
{
+ final Logger log = Logger.getLogger(LOG_NAME);
+ log.info("Synchronizing...");
+ if ((syncOperations == null) || (syncOperations.length == 0)) {
+ return new SyncOperationStatus[0];
+ }
+
+ final Collection status = new ArrayList();
+
+ final Collection setOps = new LinkedList();
+// final Collection delOps = new LinkedList();
+ final Collection miscOps = new LinkedList();
+ final int len = syncOperations.length;
+ for (int i = 0; i < len; i++) {
+ final SyncOperation operation = syncOperations[i];
+ final Collection toAdd;
+ switch (operation.getOperation()) {
+ case SyncOperation.NEW:
+ case SyncOperation.UPDATE:
+ toAdd = setOps;
+ break;
+// case SyncOperation.DELETE:
+// toAdd = delOps;
+// break;
+ default:
+ toAdd = miscOps;
+ break;
+ }
+ toAdd.add(operation);
+ }
+ final SyncOperation[] syncOperations_2 =
+ (SyncOperation[]) miscOps.toArray(new
SyncOperation[miscOps.size()]);
+
+ status.addAll(executeBulkSet(setOps));
+// status.addAll(executeBulkDelete(delOps));
+
+ for (int i = 0; i < syncOperations_2.length; ++i) {
+ if (log.isLoggable(Level.FINE)) {
+ log.fine("Executing " + syncOperations_2[i]);
+ }
+ status.addAll(Arrays.asList(
+ execSyncOperation((SyncOperationImpl)
syncOperations_2[i])
+ ));
+ }
+ log.fine("Synchronization completed.");
+ if (log.isLoggable(Level.FINE)) {
+ log.fine("status: " + status);
+ }
+ return (SyncOperationStatus[]) status.toArray(new
SyncOperationStatus[status.size()]);
+ }
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Phpgroupware-cvs] sync/sync4j/de/probusiness/pbgroupware/sync/PHPGwSyncStrategy.java, 1.2,
nomail <=