/** * Copyright (C) 2003-2007 Funambol * * This program is free software; you can redistribute it and/or modify * it under the terms of the Honest Public License. * * 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 * Honest Public License for more details. * * You should have received a copy of the Honest Public License * along with this program; if not, write to Funambol, * 643 Bair Island Road, Suite 305 - Redwood City, CA 94063, USA */ package br.com.prognus.psync.synclet; import java.util.*; import com.funambol.framework.core.*; import com.funambol.framework.core.Map; import com.funambol.framework.engine.pipeline.*; import com.funambol.framework.logging.FunambolLogger; import com.funambol.framework.logging.FunambolLoggerFactory; import com.funambol.framework.protocol.ProtocolUtil; /** * This class changes the input message client source URI with a correspondent * server source URI * * This is done in order to allow any client to sync with different source URI * using the same SyncSource. For example into phone is possible to write * ./contact or only contact to synchorized with the same contact SyncSource. * * @version $Id: ChangeSourceUriSynclet.java,v 1.5 2007-02-15 10:23:46 luigiafassina Exp $ */ public class ChangeSourceUriSynclet implements InputMessageProcessor, OutputMessageProcessor { // --------------------------------------------------------------- Constants private static final String SYNCLET_NAME = ChangeSourceUriSynclet.class.getName(); private static final String PROPERTY_SOURCENAME_CHANGED = "funambol.foundation.changesourcename.SOURCENAME_CHANGED"; // ------------------------------------------------------------ Private data private static final FunambolLogger log = FunambolLoggerFactory.getLogger("engine.pipeline"); private HashMap sourceNameMapping = null; // ---------------------------------------------------------- Public methods /** * Process input message and set MessageProcessingContext property. * * @param processingContext the message processing context * @param message the message to be processed * @throws Sync4jException */ public void preProcessMessage(MessageProcessingContext processingContext, SyncML message ) throws Sync4jException { if (log.isTraceEnabled()) { log.trace(SYNCLET_NAME + ".preProcessMessage(...)"); } HashMap sourceReplacedMap = (HashMap)processingContext.getSessionProperty( PROPERTY_SOURCENAME_CHANGED); if (sourceReplacedMap == null) { sourceReplacedMap = new HashMap(); processingContext.setSessionProperty(PROPERTY_SOURCENAME_CHANGED, sourceReplacedMap ); } // // Store and change the source uri into commands // manageInputAlert (message, sourceReplacedMap); manageInputStatus(message, sourceReplacedMap); manageInputSync (message, sourceReplacedMap); manageInputMap (message, sourceReplacedMap); } /** * Process and manipulate the output message. * * @param processingContext the message processing context * @param message the message to be processed * @throws Sync4jException */ public void postProcessMessage(MessageProcessingContext processingContext, SyncML message) throws Sync4jException { if (log.isTraceEnabled()) { log.trace(SYNCLET_NAME + ".postProcessMessage(...)"); } HashMap sourceReplacedMap = (HashMap)processingContext.getSessionProperty( PROPERTY_SOURCENAME_CHANGED); if (!sourceReplacedMap.isEmpty()) { // // Replace original source uri into commands // manageOutputStatus (message, sourceReplacedMap); manageOutputResults(message, sourceReplacedMap); manageOutputAlert (message, sourceReplacedMap); manageOutputSync (message, sourceReplacedMap); } } /** * Set the hashmap with sources name's to change * * @param map */ public void setSourceNameMapping(HashMap map) { this.sourceNameMapping = map; } /** * Get the hashmap with sources name's to change * * @return the map */ public HashMap getSourceNameMapping() { return this.sourceNameMapping; } // --------------------------------------------------------- Private Methods /** * Store and change Target URI into Alert commands * * @param message the client message * @param sourceReplacedMap the HashMap in which store uri to replace */ private void manageInputAlert(SyncML message, HashMap sourceReplacedMap) { if (log.isTraceEnabled()) { log.trace("Change TargetURI into input Alert commands"); } SyncBody syncBody = message.getSyncBody(); AbstractCommand[] allClientCommands = (AbstractCommand[])syncBody.getCommands().toArray( new AbstractCommand[0]); ArrayList alertList = ProtocolUtil.filterCommands(allClientCommands, Alert.class); Iterator itAlertList = alertList.iterator(); Alert alert = null; ArrayList items = null; Iterator itItem = null; Item item = null; Target target = null; String targetUri = null; while (itAlertList.hasNext()) { alert = (Alert)itAlertList.next(); items = alert.getItems(); itItem = items.iterator(); while (itItem.hasNext()) { item = (Item)itItem.next(); target = item.getTarget(); if (target != null) { targetUri = target.getLocURI(); if (log.isTraceEnabled()) { log.trace("original targetUri: " + targetUri); } if (sourceNameMapping.containsKey(targetUri)) { String targetNew = (String)sourceNameMapping.get(targetUri); if (log.isTraceEnabled()) { log.trace("new targetUri: " + targetNew); } target.setLocURI(targetNew); sourceReplacedMap.put(targetNew, targetUri); } } } } } /** * Store and change SourceRef into Status commmads * * @param message the client message * @param sourceReplacedMap the HashMap in which store uri to replace */ private void manageInputStatus(SyncML message, HashMap sourceReplacedMap) { if (log.isTraceEnabled()) { log.trace("Change SourceRef into input Status commands"); } SyncBody syncBody = message.getSyncBody(); AbstractCommand[] allClientCommands = (AbstractCommand[])syncBody.getCommands().toArray( new AbstractCommand[0]); ArrayList statusList = ProtocolUtil.filterCommands(allClientCommands, Status.class); Iterator itStatusList = statusList.iterator(); Status status = null; while (itStatusList.hasNext()) { status = (Status)itStatusList.next(); SourceRef[] srefs = (SourceRef[])status.getSourceRef().toArray(new SourceRef[0]); int s = srefs.length; for(int i=0;i 0) { if (items[0] instanceof DevInfItem) { DevInfItem item = (DevInfItem) items[0]; ArrayList dss = item.getDevInfData().getDevInf().getDataStores(); int s = dss.size(); for (int i = 0; i < s; i++) { DataStore ds = (DataStore) dss.get(i); String sourceRef = ds.getSourceRef().getValue(); if (sourceReplacedMap.containsKey(sourceRef)) { ds.getSourceRef().setValue((String) sourceReplacedMap. get(sourceRef)); } } } } } /** * Replace Source into Sync commands * * @param message the client message * @param sourceReplacedMap the HashMap with the uri to replace */ private void manageOutputSync(SyncML message, HashMap sourceReplacedMap) { if (log.isTraceEnabled()) { log.trace("Replace Source into output Sync commands"); } SyncBody syncBody = message.getSyncBody(); AbstractCommand[] allServerCommands = (AbstractCommand[])syncBody.getCommands().toArray( new AbstractCommand[0]); ArrayList syncList = ProtocolUtil.filterCommands(allServerCommands, Sync.class); Iterator itSyncList = syncList.iterator(); Sync sync = null; Source source = null; String sourceUri = null; while (itSyncList.hasNext()) { sync = (Sync) itSyncList.next(); source = sync.getSource(); if (source != null) { sourceUri = source.getLocURI(); if (sourceReplacedMap.containsKey(sourceUri)) { // // Here we have to create a new Source object because // the Sync can contain the same Source used in the // engine/sessionHandler to handle the Database. // If here we change the source object of the sync commands we // change also the source of the database because it's // the same object!!. // // Source newSource = new Source( (String) sourceReplacedMap.get(sourceUri), source.getLocName() ); sync.setSource(newSource); } } } } }