OpenMSPDBSyncListener.java

00001 /*
00002  * OpenMobileIS - a free Java(TM) Framework for mobile applications Java(TM)
00003  * Copyright (C) 2004-2006 Philippe Delrieu
00004  * All rights reserved.
00005  * Contact: pdelrieu@openmobileis.org
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00020  * USA
00021  *
00022  *  Author : Philippe Delrieu
00023  * 
00024  */
00025 package org.openmobileis.synchro.openmsp.client;
00026 
00027 import java.io.ByteArrayOutputStream;
00028 import java.io.OutputStreamWriter;
00029 
00030 import org.openmobileis.common.util.codec.GeneralCoder;
00031 import org.openmobileis.common.util.exception.DatabaseException;
00032 import org.openmobileis.common.util.exception.SynchroException;
00033 import org.openmobileis.common.util.log.LogManager;
00034 import org.openmobileis.synchro.client.SynchroDescriptor;
00035 import org.openmobileis.synchro.journal.JournalEntry;
00036 import org.openmobileis.synchro.journal.JournalManager;
00037 import org.openmobileis.synchro.openmsp.OpenMSPException;
00038 import org.openmobileis.synchro.openmsp.client.core.NumSyncManagerDB;
00039 import org.openmobileis.synchro.openmsp.client.db.ActionDB;
00040 import org.openmobileis.synchro.openmsp.client.db.DBImportFileCoder;
00041 import org.openmobileis.synchro.openmsp.client.db.ImportQueryManager;
00042 import org.openmobileis.synchro.openmsp.client.db.SyncActionDBManager;
00043 import org.openmobileis.synchro.openmsp.protocol.AbstractCommand;
00044 import org.openmobileis.synchro.openmsp.protocol.Command;
00045 import org.openmobileis.synchro.openmsp.protocol.ContainerMessage;
00046 import org.openmobileis.synchro.openmsp.protocol.DataItem;
00047 import org.openmobileis.synchro.openmsp.protocol.Element;
00048 import org.openmobileis.synchro.openmsp.protocol.Item;
00049 import org.openmobileis.synchro.openmsp.protocol.Message;
00050 import org.openmobileis.synchro.openmsp.protocol.RequestCommand;
00051 import org.openmobileis.synchro.openmsp.protocol.Result;
00052 import org.openmobileis.synchro.openmsp.protocol.Status;
00053 import org.openmobileis.synchro.security.auth.Credential;
00054 
00062 public abstract class OpenMSPDBSyncListener extends DefaultOpenMSPSyncListener  {
00063 
00064   private boolean syncGoOn = false;
00065   protected String installPath;
00066 
00070   public OpenMSPDBSyncListener() {
00071     super();
00072   }
00073 
00074   public void startSync(Credential cred, SynchroDescriptor synchrodescriptor) throws OpenMSPException {
00075     super.startSync(cred, synchrodescriptor);
00076     this.syncGoOn = true;
00077     installPath = synchrodescriptor.getSynchroConduit().getIntallPath();
00078   }
00079 
00080   /* (non-Javadoc)
00081    * @see org.openmobileis.synchro.openmsp.client.OpenMSPSyncListener#sendData(org.openmobileis.synchro.openmsp.protocol.Message)
00082    */
00083   public void sendData(Message message) throws OpenMSPException {
00084     if (!this.isSyncOK()) {
00085       return; // return if an error occurs during synchro.
00086     }
00087 
00088     if (!syncGoOn) { // synchronize data only for the first call.
00089     return;
00090     }
00091     syncGoOn = false;
00092     // construct Atomic Object action list and resolve conflicts
00093     ActionDB[] actionArray = SyncActionDBManager.getManager().getActionsForService(this.getSyncName());
00094      // genererate sync message.
00095     try {
00096 
00097       // add GET command to make synchro
00098       Command getCommand = new Command(Element.GET, this.getSyncName(), this.getSynchroTarget());
00099       long ns = NumSyncManagerDB.getManager().getSyncNumberForService(this.getSyncName());
00100       getCommand.setSourceSessionID(ns);
00101       Credential cred = this.getSyncroCredential();
00102       if (cred != null) {
00103         DefaultOpenMSPSyncListener.addCredentialToCommand(cred, getCommand);
00104       }
00105       ContainerMessage getContainer = new ContainerMessage(getCommand);
00106       Item newItem = new DataItem(
00107                   Element.ITEM
00108                   , ""
00109                   , ""
00110                   , null
00111                   , null
00112               );
00113       getContainer.add(newItem);
00114       message.add(getContainer); // add before sync container because GET command must be proceed before the SYNC command.
00115       
00116       //add sync command
00117       Command syncCommand = new Command(Element.SYNC, this.getSyncName(), this.getSynchroTarget());
00118       syncCommand.setSourceSessionID(ns);
00119       String commandMetadata = this.getSendCommandMetaData();
00120       if (commandMetadata != null)  {
00121         syncCommand.setMetaInformation(commandMetadata);
00122       }
00123       if (cred != null) {
00124         DefaultOpenMSPSyncListener.addCredentialToCommand(cred, syncCommand);
00125       }
00126       ContainerMessage syncContainer = new ContainerMessage(syncCommand);
00127 
00128       newItem = null;
00129       byte[] actionData = null;
00130       RequestCommand newCommand = null;
00131       ContainerMessage newContainer = null;
00132       for (int i=0; i<actionArray.length; i++) {
00133         if (actionArray[i].getActionType() == ActionDB.ADD_ACTION) { // ADD
00134           actionData = this.getSyncDataForAtomicObjectUID(actionArray[i].getActionObjectUID(), ActionDB.ADD_ACTION);
00135           if (actionData != null) {
00136             newCommand = new RequestCommand(Element.ADD);
00137             newCommand.setMetaInformation(new String(GeneralCoder.encodeBase64(actionArray[i].getActionObjectUID().getBytes())));
00138             newContainer = new ContainerMessage(newCommand);
00139             newItem = new DataItem(
00140                         Element.ITEM
00141                         , new String(GeneralCoder.encodeBase64(("AOUID:"+actionArray[i].getActionObjectUID()).getBytes()))
00142                         , new String(GeneralCoder.encodeBase64(actionData))
00143                         , null
00144                         , null
00145                     );
00146             newContainer.add(newItem);
00147             syncContainer.add(newContainer);
00148           }
00149         } else if (actionArray[i].getActionType() ==ActionDB.UPDATE_ACTION)  { // REPLACE
00150           actionData = this.getSyncDataForAtomicObjectUID(actionArray[i].getActionObjectUID(), ActionDB.UPDATE_ACTION);
00151           if (actionData != null) {
00152             String serverID = this.getServerUIDForAOUID(actionArray[i].getActionObjectUID());
00153             if (serverID != null) {
00154               newCommand = new RequestCommand(Element.REPLACE);
00155               newCommand.setMetaInformation(new String(GeneralCoder.encodeBase64(actionArray[i].getActionObjectUID().getBytes())));
00156               newContainer = new ContainerMessage(newCommand);
00157               newItem = new DataItem(
00158                           Element.ITEM
00159                           , new String(GeneralCoder.encodeBase64(("AOUID:"+serverID).getBytes()))
00160                           , new String(GeneralCoder.encodeBase64(actionData))
00161                           , null
00162                           , null
00163                       );
00164                newContainer.add(newItem);
00165               syncContainer.add(newContainer);
00166             }
00167           }
00168         } else if (actionArray[i].getActionType() ==ActionDB.DELETE_ACTION)  { // DELETE
00169           String serverID = this.getServerUIDForAOUID(actionArray[i].getActionObjectUID());
00170           if (serverID != null) {
00171             newCommand = new RequestCommand(Element.DELETE);
00172             newContainer = new ContainerMessage(newCommand);
00173             newCommand.setMetaInformation(new String(GeneralCoder.encodeBase64(actionArray[i].getActionObjectUID().getBytes())));
00174             newItem = new DataItem(
00175                         Element.ITEM
00176                         , new String(GeneralCoder.encodeBase64(("AOUID:"+serverID).getBytes()))
00177                         , ""
00178                         , null
00179                         , null
00180                     );
00181             newContainer.add(newItem);
00182             syncContainer.add(newContainer);
00183           }
00184         } // REMOVE action nothing done.
00185       }
00186       message.add(syncContainer);
00187     } catch (Throwable ex)  {
00188       this.setSynchroStatus(Status.STATUS_FAILED);
00189       LogManager.traceError(0, ex);
00190     }
00191 
00192   }
00193 
00194   /* (non-Javadoc)
00195    * @see org.openmobileis.synchro.openmsp.client.OpenMSPSyncListener#receiveMapCommand(org.openmobileis.synchro.openmsp.protocol.ContainerMessage, long)
00196    */
00197   public void receiveMapCommand(ContainerMessage mapContainer) throws OpenMSPException {
00198     mapContainer.resetCursor();
00199     try {
00200       while (mapContainer.hasMoreMessage()) {;
00201         Item map = (Item)mapContainer.nextMessage().getElement();
00202         String PDAUID = new String(GeneralCoder.decodeBase64(map.getTarget().getBytes()));
00203         String serverUID = new String(GeneralCoder.decodeBase64(map.getSource().getBytes()));
00204         this.notifyMAPofUID(PDAUID, serverUID);
00205       }
00206     } catch (java.io.IOException ex)  {
00207       this.setSynchroStatus(Status.STATUS_FAILED);
00208       LogManager.trace(new SynchroException(ex));
00209     }
00210   }
00211 
00212   /* (non-Javadoc)
00213    * @see org.openmobileis.synchro.openmsp.client.OpenMSPSyncListener#receiveResultCommand(org.openmobileis.synchro.openmsp.protocol.ContainerMessage, long)
00214    */
00215   public void receiveResultCommand(ContainerMessage resultContainer, ContainerMessage initialCommand) throws OpenMSPException {
00216     Result resultCommand = (Result)resultContainer.getElement(); //result
00217     try {
00218       long newSessionID = Long.parseLong(resultCommand.getMetaInformation());
00219       while (resultContainer.hasMoreMessage())  {
00220         DataItem item = (DataItem) resultContainer.nextMessage().getElement();
00221         String meta = item.getMetaInformation();
00222         String file = item.getData();
00223         if (meta.equals("ImportDataFile"))  {
00224           String importFileName = this.installPath+file;
00225           this.getImportQueryManager().importDataFile(importFileName);
00226         } else if (meta.equals("DatabaseFile"))  {
00227           String importFileName = this.installPath+file;
00228           this.importCompletSynchroDatabaseFile(importFileName);
00229         }
00230       }
00231       
00232       NumSyncManagerDB.getManager().saveSyncNumberForService(newSessionID, this.getSyncName());
00233     } catch (Throwable ex)  {
00234       throw new OpenMSPException(ex);
00235     }
00236   }
00237 
00238   /* (non-Javadoc)
00239    * @see org.openmobileis.synchro.openmsp.client.OpenMSPSyncListener#receiveStatusCommand(org.openmobileis.synchro.openmsp.protocol.Status, long)
00240    */
00241   public void receiveStatusCommand(Status statusCommande, ContainerMessage initialContenaire) throws OpenMSPException {
00242     try {
00243 //      int cmlRef = statusCommande.getCmdRef();
00244       int status = statusCommande.getStatus();
00245       if (initialContenaire != null)  {
00246         AbstractCommand command = (AbstractCommand)initialContenaire.getElement();
00247         this.manageReturnStatusLog(status, command.getElementType(), initialContenaire);
00248         if (status == Status.STATUS_OK)  {
00249           if ((command instanceof RequestCommand) && (command.getElementType() != Element.GET) && (command.getElementType() != Element.SYNC)) {
00250             String pdaID = new String(GeneralCoder.decodeBase64(((RequestCommand)command).getMetaInformation().getBytes()));
00251             if (pdaID != null)  {
00252               int actionType = ActionDB.UPDATE_ACTION;
00253               if (command.getElementType() == Element.DELETE) {
00254                 actionType = ActionDB.DELETE_ACTION;
00255                 this.removeServerUIDForAOUID(pdaID);
00256              }
00257              this.notifySyncDataDone(pdaID, actionType);
00258              SyncActionDBManager.getManager().deleteActionDB(this.getSyncName(), pdaID);
00259             }
00260           }
00261         } else if (status == Status.STATUS_NO_CONTENT) {
00262                 // do nothing first get return status. Not use.
00263         } else {
00264           //set sync in error
00265           this.notifySynchroFailure();
00266         }
00267       } 
00268     }catch (Exception ex) {
00269       this.setSynchroStatus(Status.STATUS_FAILED);
00270       LogManager.trace(new SynchroException(ex));      
00271     }
00272   }
00273 
00278   protected void manageReturnStatusLog(int statusCode, int cmlType, ContainerMessage container) {
00279     this.setSynchroStatus(statusCode);
00280     if (statusCode != Status.STATUS_OK) {
00281       String message = null;
00282       short journalEntryType = 0;
00283       if (cmlType == Element.ADD)  {
00284         journalEntryType = JournalEntry.ERROR_ADD;
00285         message = DefaultOpenMSPSyncListener.ADD_ERROR_MESSAGE;
00286       } else if (cmlType == Element.REPLACE)  {
00287         journalEntryType = JournalEntry.ERROR_REPLACE;
00288         message = DefaultOpenMSPSyncListener.UPDATE_ERROR_MESSAGE;
00289       } else if (cmlType == Element.DELETE)  {
00290         journalEntryType = JournalEntry.ERROR_DELETE;
00291         message = DefaultOpenMSPSyncListener.DELETE_ERROR_MESSAGE;
00292       } else if (cmlType == Element.ITEM)  {
00293         journalEntryType = JournalEntry.ERROR_SYNC;
00294         message = DefaultOpenMSPSyncListener.ITEM_ERROR_MESSAGE;
00295       } else if (cmlType == Element.SYNC)  {
00296         journalEntryType = JournalEntry.ERROR_SYNC_MOBILE;
00297         if (statusCode == Status.STATUS_UNAUTHORIZED) {
00298           message = DefaultOpenMSPSyncListener.SYNC_UNAUTHORIZED_MESSAGE;
00299         } else  {
00300           message = DefaultOpenMSPSyncListener.SYNC_ERROR_MESSAGE;
00301         }
00302       }
00303       if (message != null)  {
00304         JournalManager.getManager().saveJournalEntry(
00305 
00306            this.getSyncName()
00307 
00308           , journalEntryType
00309 
00310           , message
00311 
00312           , statusCode
00313 
00314         );
00315       }
00316     }
00317 
00318   }
00319 
00320   protected void receiveSyncItem( Credential cred, Item item , long newSyncNumber) {
00321   }
00322 
00328   protected byte[] getSyncDataForAtomicObjectUID(String pdaUID, int action) throws OpenMSPException {
00329     byte[] aoData = null;
00330     char[] charData = null;
00331     if (action == ActionDB.ADD_ACTION)  {
00332       String[] ret  = this.getDBDataForAdd(pdaUID);
00333       if (ret != null)  {
00334        charData = DBImportFileCoder.getCoder().encodeData(DBImportFileCoder.ADDAction, ret);
00335       } else  {
00336         //remove action because not use
00337         SyncActionDBManager.getManager().deleteActionDB(this.getSyncName(), pdaUID);
00338       }
00339     } else if (action == ActionDB.UPDATE_ACTION) {
00340       String[] ret  = this.getDBDataForReplace(pdaUID);
00341       if (ret != null)  {
00342         charData = DBImportFileCoder.getCoder().encodeData(DBImportFileCoder.REPLACEAction, ret);
00343       } else  {
00344         //remove action because not use
00345         SyncActionDBManager.getManager().deleteActionDB(this.getSyncName(), pdaUID);
00346       }
00347     }
00348     if (charData != null) {
00349       ByteArrayOutputStream out = new ByteArrayOutputStream();
00350       OutputStreamWriter writer = new OutputStreamWriter(out);
00351       try {
00352         writer.write(charData);
00353         writer.flush();
00354         writer.close();
00355         aoData = out.toByteArray();
00356       } catch (Exception ex)  {
00357         LogManager.trace(new SynchroException(ex));
00358       }
00359     }
00360     return aoData;
00361   }
00362   
00363   protected String getSendCommandMetaData()  throws OpenMSPException  {
00364     return null;
00365   }
00366 
00372   protected String getServerUIDForAOUID(String pdaUID)  {
00373     return pdaUID;
00374   }
00375   
00383   public void notifySyncDataDone(String pdaID, int actionType) throws OpenMSPException {
00384   }
00385 
00386   protected void notifyMAPofUID(String pdauid, String serveruid) throws OpenMSPException  {
00387     
00388   }
00389   
00395   protected void removeServerUIDForAOUID(String pdaUID) throws OpenMSPException {
00396   }
00397   
00403   protected void importCompletSynchroDatabaseFile(String importFile) throws DatabaseException {
00404   }
00405 
00410   protected abstract String[] getDBDataForAdd(String pdaUID) throws OpenMSPException;
00415   protected abstract String[] getDBDataForReplace(String pdaUID) throws OpenMSPException;
00416 
00420   protected abstract String getSynchroTarget();
00421 
00426   protected abstract Credential getSyncroCredential();
00427 
00431   protected abstract ImportQueryManager getImportQueryManager();
00432 
00433 }

Generated on Mon Dec 4 11:03:28 2006 for OpenMobileIS by  doxygen 1.5.1-p1