Android Open Source - couchdroid Couch Replication Task






From Project

Back to project page couchdroid.

License

The source code is released under:

Apache License

If you think the Android project couchdroid listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
 * Copyright (c) 2011 Cummings Engineering Consultants, Inc. 
 * //from   w  w  w.  j a v a  2s  . c  o  m
 * Licensed 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 census.couchdroid;

import java.net.InetAddress;
import java.net.URL;

import org.json.JSONException;
import org.json.JSONObject;

import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;

/**
 * This class encapsulates the data for a replication task running on a couch server 
 * (as returned from the query to "_active_tasks")
 * 
 * Note: The "equals()" method is overidden for this class in order to easily compare two tasks. However the
 * "hashCode()" method was not overidden, so this class should not be used inside hash tables.
 * 
 * @author anthony.payne
 *
 */
public class CouchReplicationTask extends CouchTask {
    
    /**
     * Logging instance for this class.
     */
    //static Log log = LogFactory.getLog(Document.class);
    
    /** Used to identify a running task as a replication task */
    public static final String TASK_TYPE = "Replication";
    
    /** Used to parse the string holding the task details */
    private static final String DELIMITER = " ";
    
    /** JSON key for the source field */
    private static final String SOURCE_KEY = "source";
    /** JSON key for the target field */
    private static final String TARGET_KEY = "target";
    /** JSON key for the create_target field */
    private static final String CREATE_TARGET_KEY = "create_target";
    /** JSON key for the continuous field */
    private static final String CONTINUOUS_KEY = "continuous";
    /** JSON key for the cancel field */
    private static final String CANCEL_KEY = "cancel";
    
    /** Source (DB) of the replication */
    private ReplicationTarget source;
    
    /** Target (DB) of the replication */
    private ReplicationTarget destination;
    
    /** Flag indicating if this is to be a continuous replication or not */
    private boolean continuous;
    /** Flag indicating if the target (DB) should be created if it does not exist */
    private boolean createTarget;
    /** Flag indicating if this task is to be canceled or not */
    private boolean cancel;
    
    /**
     * Creates a replication task from the task details returned from a DB query about running tasks.
     * 
     * @param task Task details
     * @param status Status of task
     * @param pid PID of task
     */
    public CouchReplicationTask(final String task, final String status, final String pid) {
        super(TASK_TYPE, task, status, pid);
        
        source = null;
        destination = null;
        continuous = false;
        createTarget = false;
        cancel = false;
    }
    
    /**
     * Creates a replication task between the source and destination.
     * 
     * @param source Source for the replication 
     * @param destination Target for the replication
     */
    public CouchReplicationTask(ReplicationTarget source, ReplicationTarget destination) {
        super(TASK_TYPE, null, null, null);
        
        this.source = source;
        this.destination = destination;
    }

    /**
     * Initializes the fields based on the data in the "task" string.
     * @return
     */
    public boolean loadDetailsFromTask() {
        if(task == null) {
            return false;
        }
        
        String[] parts = task.split(DELIMITER);
        
        if(parts.length < 4) {
            //log.error("Unable to parse replication task: " + task);
            return false;
        }
        
        // [0] - Task ID
        // [1] - source URL
        // [2] - "->"
        // [3] - destination URL
        
        source = ReplicationTarget.fromUrl(parts[1]);
        destination = ReplicationTarget.fromUrl(parts[3]);
        
        if(source == null || destination == null) {
            //log.error("Unable to extract source and destination details from replication task: " + task);
            return false;
        }
        return true;
    }

    /**
     * @return the source
     */
    public ReplicationTarget getSource() {
        return source;
    }

    /**
     * @return the destination
     */
    public ReplicationTarget getDestination() {
        return destination;
    }

    /**
     * @return the continuous
     */
    public boolean isContinuous() {
        return continuous;
    }
    
    /**
     * @return The JSON object representing this replication task. Null is returned upon failure.
     */
    public JSONObject getCreateRequest() {
        final JSONObject object = new JSONObject();
        final String source = this.source.buildUrl();
        final String destination = this.destination.buildUrl();
        if(source == null || destination == null) {
            //log.error("Unable to build source or destination URL");
            return null;
        }
        try {
            object.put(SOURCE_KEY, source);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            object.put(TARGET_KEY, destination);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        if(createTarget) {
            try {
                object.put(CREATE_TARGET_KEY, Boolean.TRUE);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        if(continuous) {
            try {
                object.put(CONTINUOUS_KEY, Boolean.TRUE);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        if(cancel) {
            try {
                object.put(CANCEL_KEY, Boolean.TRUE);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        return object;
    }

    /**
     * sets the continuous flag. 
     */
    public void setContinuous() {
        continuous = true;
    }

    /**
     * Sets the create target flag 
     */
    public void setCreateTarget() {
        createTarget = true;
    }

    /**
     * Sets the cancel flag
     */
    public void setCancel() {
        cancel = true;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if(obj instanceof CouchReplicationTask) {
            final CouchReplicationTask other = (CouchReplicationTask) obj;
            if(source.equals(other.source) && destination.equals(other.destination)) {
                return true;
            }
        }
        return false;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        throw new RuntimeException("hashCode() is not supported yet.");
    }
    
    /**
     * Simple class for encapsulating the details about a source or destination of a replication task.
     * 
     * Note: The "equals()" method is overidden for this class in order to easily compare two targets. However the
     * "hashCode()" method was not overidden, so this class should not be used inside hash tables.
     * 
     * @author anthony.payne
     *
     */
    public static class ReplicationTarget {
        private final static String FULL_URL_PREFIX = "http";
        private final static String PATH_SEPARATOR = "/";
        private final static int PORT_NOT_USED = -1;
        
        /** The item in the database being replicated (could be a DB or a document) */
        private String replicatedEntity;
        
        /** The server */
        private String server;
        
        /** The Couch port */
        private int port;
        
        /** Indicates if this target is remote (true) or local (false) */
        private boolean isRemote;
        
        private ReplicationTarget() {
            
        }

        /**
         * Constructor used for local targets
         * @param replicatedEntry
         */
        public ReplicationTarget(final String replicatedEntry) {
            this(replicatedEntry, null, PORT_NOT_USED);
        }
        
        /**
         * Constructor used to specify the server and port along with the entity being replicated.
         * @param replicatedEntry
         * @param server
         * @param port
         */
        public ReplicationTarget(final String replicatedEntry, final String server, final int port) {
            this.replicatedEntity = replicatedEntry;
            this.server = server;
            this.port = port;
            isRemote = (server != null);
        }
        
        /**
         * Builds the URL for this replication source or destination
         * @return String holding the URL
         */
        public String buildUrl() {
            final StringBuffer buffer = new StringBuffer();
            
            if(isRemote == false) {
                buffer.append(replicatedEntity);
            } else {
                buffer.append(FULL_URL_PREFIX + "://" + server + ":" + port + "/" + replicatedEntity);              
            }
            
            return buffer.toString();
        }
        
        /**
         * Constructs a ReplicationTarget given a URL
         * @param url URL from a replication task
         * @return The replication target instance if successful; null if not
         */
        static private ReplicationTarget fromUrl(final String url) {
            if(url.startsWith(FULL_URL_PREFIX) == false) {
                final ReplicationTarget target = new ReplicationTarget();
                target.isRemote = false;
                target.port = PORT_NOT_USED;
                target.replicatedEntity = url;
                target.server = null;
                return target;
            }
            
            try {
                final URL asUrl = new URL(url);
                final ReplicationTarget target = new ReplicationTarget();
                target.server = asUrl.getHost();
                target.port = asUrl.getPort();
                target.replicatedEntity = asUrl.getPath();
                
                if(target.replicatedEntity.startsWith(PATH_SEPARATOR)) {
                    target.replicatedEntity = target.replicatedEntity.substring(PATH_SEPARATOR.length());
                }
                if(target.replicatedEntity.endsWith(PATH_SEPARATOR)) {
                    target.replicatedEntity = target.replicatedEntity.substring(0, target.replicatedEntity.length() - 
                            PATH_SEPARATOR.length());
                }
                
                target.isRemote = false;
                
                if(target.server != null) {
                    final InetAddress tempAddress = InetAddress.getByName(target.server);
                    target.isRemote = !(tempAddress.isLoopbackAddress());
                }
                
                //log.debug(target.toString());
                
                return target;
            } catch(final Exception e) {
                //log.debug("Failed to create target due to exception, " + e);
            }
            return null;
        }


        /* (non-Javadoc)
         * @see java.lang.Object#toString()
         */
        @Override
        public String toString() {
            StringBuffer buffer = new StringBuffer();
            buffer.append("Host: ");
            if(server != null) {
                buffer.append(server + ", ");
            } else {
                buffer.append("Not set, ");
            }
            buffer.append("Port = " + port + ", ");
            buffer.append("Path = " + replicatedEntity + ", isRemote = " + isRemote);
            return buffer.toString();
        }


        /**
         * @return the replicatedEntity
         */
        public String getReplicatedEntity() {
            return replicatedEntity;
        }


        /**
         * @return the sourceDatabaseServer
         */
        public String getServer() {
            return server;
        }


        /**
         * @return the sourceDatabasePort
         */
        public int getPort() {
            return port;
        }


        /**
         * @return the isRemote
         */
        public boolean isRemote() {
            return isRemote;
        }

        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if(obj instanceof ReplicationTarget) {
                final ReplicationTarget other = (ReplicationTarget) obj;
                
                if(((replicatedEntity == null && other.replicatedEntity == null) || 
                        replicatedEntity.equals(other.replicatedEntity)) && 
                        ((server == null && other.server == null) || server.equals(other.server)) &&
                        port == other.port) {
                    return true;
                }
            }
            return false;
        }
        
        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            throw new RuntimeException("hashCode() is not supported yet.");
        }
    }
}




Java Source Code List

census.couchdroid.CouchAdHocView.java
census.couchdroid.CouchDatabase.java
census.couchdroid.CouchDocument.java
census.couchdroid.CouchReplicationTask.java
census.couchdroid.CouchResponse.java
census.couchdroid.CouchSession.java
census.couchdroid.CouchTask.java
census.couchdroid.CouchUpdate.java
census.couchdroid.CouchViewResults.java
census.couchdroid.CouchView.java