001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2007-2008 Sun Microsystems, Inc.
026     */
027    
028    package org.opends.server.replication.protocol;
029    
030    import java.io.ByteArrayOutputStream;
031    import java.io.IOException;
032    import java.io.UnsupportedEncodingException;
033    import java.util.ArrayList;
034    import java.util.List;
035    import java.util.zip.DataFormatException;
036    
037    /**
038     *
039     * This class defines a message that is sent by a replication server
040     * to the other replication servers in the topology containing the list
041     * of LDAP servers directly connected to it.
042     * A replication server sends a ReplServerInfoMessage when an LDAP
043     * server connects or disconnects.
044     *
045     * Exchanging these messages allows to have each replication server
046     * knowing the complete list of LDAP servers in the topology and
047     * their associated replication server and thus take the appropriate
048     * decision to route a message to an LDAP server.
049     *
050     */
051    public class ReplServerInfoMessage extends ReplicationMessage
052    {
053      private List<String> connectedServers = null;
054      private long generationId;
055    
056      /**
057       * Creates a new changelogInfo message from its encoded form.
058       *
059       * @param in The byte array containing the encoded form of the message.
060       * @throws java.util.zip.DataFormatException If the byte array does not
061       * contain a valid encoded form of the message.
062       */
063      public ReplServerInfoMessage(byte[] in) throws DataFormatException
064      {
065        try
066        {
067          /* first byte is the type */
068          if (in.length < 1 || in[0] != MSG_TYPE_REPL_SERVER_INFO)
069            throw new DataFormatException(
070            "Input is not a valid " + this.getClass().getCanonicalName());
071    
072          int pos = 1;
073    
074          /* read the generationId */
075          int length = getNextLength(in, pos);
076          generationId = Long.valueOf(new String(in, pos, length,
077              "UTF-8"));
078          pos += length +1;
079    
080          /* read the connected servers */
081          connectedServers = new ArrayList<String>();
082          while (pos < in.length)
083          {
084            /*
085             * Read the next server ID
086             * first calculate the length then construct the string
087             */
088            length = getNextLength(in, pos);
089            connectedServers.add(new String(in, pos, length, "UTF-8"));
090            pos += length +1;
091          }
092        } catch (UnsupportedEncodingException e)
093        {
094          throw new DataFormatException("UTF-8 is not supported by this jvm.");
095        }
096      }
097    
098    
099      /**
100       * Creates a new ReplServerInfo message from a list of the currently
101       * connected servers.
102       *
103       * @param connectedServers The list of currently connected servers ID.
104       * @param generationId     The generationId currently associated with this
105       *                         domain.
106       */
107      public ReplServerInfoMessage(List<String> connectedServers,
108          long generationId)
109      {
110        this.connectedServers = connectedServers;
111        this.generationId = generationId;
112      }
113    
114      /**
115       * {@inheritDoc}
116       */
117      @Override
118      public byte[] getBytes()
119      {
120        try
121        {
122          ByteArrayOutputStream oStream = new ByteArrayOutputStream();
123    
124          /* Put the message type */
125          oStream.write(MSG_TYPE_REPL_SERVER_INFO);
126    
127          // Put the generationId
128          oStream.write(String.valueOf(generationId).getBytes("UTF-8"));
129          oStream.write(0);
130    
131          // Put the servers
132          if (connectedServers.size() >= 1)
133          {
134            for (String server : connectedServers)
135            {
136              byte[] byteServerURL = server.getBytes("UTF-8");
137              oStream.write(byteServerURL);
138              oStream.write(0);
139            }
140          }
141    
142          return oStream.toByteArray();
143        }
144        catch (IOException e)
145        {
146          // never happens
147          return null;
148        }
149      }
150    
151      /**
152       * Get the list of servers currently connected to the Changelog server
153       * that generated this message.
154       *
155       * @return A collection of the servers currently connected to the Changelog
156       *         server that generated this message.
157       */
158      public List<String> getConnectedServers()
159      {
160        return connectedServers;
161      }
162    
163      /**
164       * Get the generationId from this message.
165       * @return The generationId.
166       */
167      public long getGenerationId()
168      {
169        return generationId;
170      }
171    
172      /**
173       * {@inheritDoc}
174       */
175      @Override
176      public String toString()
177      {
178        String csrvs = "";
179        for (String s : connectedServers)
180        {
181          csrvs += s + "/";
182        }
183        return ("ReplServerInfoMessage: genId=" + getGenerationId() +
184                " Connected peers:" + csrvs);
185      }
186    
187    }