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 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.replication.protocol;
028    
029    import java.io.Serializable;
030    import java.io.UnsupportedEncodingException;
031    import java.util.zip.DataFormatException;
032    
033    import org.opends.server.replication.common.ServerState;
034    import org.opends.server.types.DirectoryException;
035    import org.opends.server.types.DN;
036    
037    /**
038     * Message sent by a replication server to another replication server
039     * at Startup.
040     */
041    public class ReplServerStartMessage extends StartMessage implements
042        Serializable
043    {
044      private static final long serialVersionUID = -5871385537169856856L;
045    
046      private short serverId;
047      private String serverURL;
048      private String baseDn = null;
049      private int windowSize;
050      private ServerState serverState;
051    
052      /**
053       * Whether to continue using SSL to encrypt messages after the start
054       * messages have been exchanged.
055       */
056      private boolean sslEncryption;
057    
058    
059      /**
060       * Create a ReplServerStartMessage.
061       *
062       * @param serverId replication server id
063       * @param serverURL replication server URL
064       * @param baseDn base DN for which the ReplServerStartMessage is created.
065       * @param windowSize The window size.
066       * @param serverState our ServerState for this baseDn.
067       * @param protocolVersion The replication protocol version of the creator.
068       * @param generationId The generationId for this server.
069       * @param sslEncryption Whether to continue using SSL to encrypt messages
070       *                      after the start messages have been exchanged.
071       */
072      public ReplServerStartMessage(short serverId, String serverURL, DN baseDn,
073                                   int windowSize,
074                                   ServerState serverState,
075                                   short protocolVersion,
076                                   long generationId,
077                                   boolean sslEncryption)
078      {
079        super(protocolVersion, generationId);
080        this.serverId = serverId;
081        this.serverURL = serverURL;
082        if (baseDn != null)
083          this.baseDn = baseDn.toNormalizedString();
084        else
085          this.baseDn = null;
086        this.windowSize = windowSize;
087        this.serverState = serverState;
088        this.sslEncryption = sslEncryption;
089      }
090    
091      /**
092       * Creates a new ReplServerStartMessage by decoding the provided byte array.
093       * @param in A byte array containing the encoded information for the
094       *             ReplServerStartMessage
095       * @throws DataFormatException If the in does not contain a properly
096       *                             encoded ReplServerStartMessage.
097       */
098      public ReplServerStartMessage(byte[] in) throws DataFormatException
099      {
100        /* The ReplServerStartMessage is encoded in the form :
101         * <baseDn><ServerId><ServerUrl><windowsize><ServerState>
102         */
103        super(MSG_TYPE_REPL_SERVER_START, in);
104    
105        try
106        {
107          /* first bytes are the header */
108          int pos = headerLength;
109    
110          /* read the dn
111           * first calculate the length then construct the string
112           */
113          int length = getNextLength(in, pos);
114          baseDn = new String(in, pos, length, "UTF-8");
115          pos += length +1;
116    
117          /*
118           * read the ServerId
119           */
120          length = getNextLength(in, pos);
121          String serverIdString = new String(in, pos, length, "UTF-8");
122          serverId = Short.valueOf(serverIdString);
123          pos += length +1;
124    
125          /*
126           * read the ServerURL
127           */
128          length = getNextLength(in, pos);
129          serverURL = new String(in, pos, length, "UTF-8");
130          pos += length +1;
131    
132          /*
133           * read the window size
134           */
135          length = getNextLength(in, pos);
136          windowSize = Integer.valueOf(new String(in, pos, length, "UTF-8"));
137          pos += length +1;
138    
139          /*
140           * read the sslEncryption setting
141           */
142          length = getNextLength(in, pos);
143          sslEncryption = Boolean.valueOf(new String(in, pos, length, "UTF-8"));
144          pos += length +1;
145    
146          /*
147          * read the ServerState
148          */
149          serverState = new ServerState(in, pos, in.length-1);
150        } catch (UnsupportedEncodingException e)
151        {
152          throw new DataFormatException("UTF-8 is not supported by this jvm.");
153        }
154      }
155    
156      /**
157       * Get the Server Id.
158       * @return the server id
159       */
160      public short getServerId()
161      {
162        return this.serverId;
163      }
164    
165      /**
166       * Set the server URL.
167       * @return the server URL
168       */
169      public String getServerURL()
170      {
171        return this.serverURL;
172      }
173    
174      /**
175       * Get the base DN from this ReplServerStartMessage.
176       *
177       * @return the base DN from this ReplServerStartMessage.
178       */
179      public DN getBaseDn()
180      {
181        if (baseDn == null)
182          return null;
183        try
184        {
185          return DN.decode(baseDn);
186        } catch (DirectoryException e)
187        {
188          return null;
189        }
190      }
191    
192      /**
193       * Get the serverState.
194       * @return Returns the serverState.
195       */
196      public ServerState getServerState()
197      {
198        return this.serverState;
199      }
200    
201      /**
202       * {@inheritDoc}
203       */
204      @Override
205      public byte[] getBytes()
206      {
207        /* The ReplServerStartMessage is stored in the form :
208         * <operation type><basedn><serverid><serverURL><windowsize><serverState>
209         */
210        try {
211          byte[] byteDn = baseDn.getBytes("UTF-8");
212          byte[] byteServerId = String.valueOf(serverId).getBytes("UTF-8");
213          byte[] byteServerUrl = serverURL.getBytes("UTF-8");
214          byte[] byteServerState = serverState.getBytes();
215          byte[] byteWindowSize = String.valueOf(windowSize).getBytes("UTF-8");
216          byte[] byteSSLEncryption =
217                         String.valueOf(sslEncryption).getBytes("UTF-8");
218    
219          int length = byteDn.length + 1 + byteServerId.length + 1 +
220                       byteServerUrl.length + 1 + byteWindowSize.length + 1 +
221                       byteSSLEncryption.length + 1 +
222                       byteServerState.length + 1;
223    
224          /* encode the header in a byte[] large enough to also contain the mods */
225          byte resultByteArray[] = encodeHeader(MSG_TYPE_REPL_SERVER_START, length);
226          int pos = headerLength;
227    
228          /* put the baseDN and a terminating 0 */
229          pos = addByteArray(byteDn, resultByteArray, pos);
230    
231          /* put the ServerId */
232          pos = addByteArray(byteServerId, resultByteArray, pos);
233    
234          /* put the ServerURL */
235          pos = addByteArray(byteServerUrl, resultByteArray, pos);
236    
237          /* put the window size */
238          pos = addByteArray(byteWindowSize, resultByteArray, pos);
239    
240          /* put the SSL Encryption setting */
241          pos = addByteArray(byteSSLEncryption, resultByteArray, pos);
242    
243          /* put the ServerState */
244          pos = addByteArray(byteServerState, resultByteArray, pos);
245    
246          return resultByteArray;
247        }
248        catch (UnsupportedEncodingException e)
249        {
250          return null;
251        }
252      }
253    
254      /**
255       * get the window size for the server that created this message.
256       *
257       * @return The window size for the server that created this message.
258       */
259      public int getWindowSize()
260      {
261        return windowSize;
262      }
263    
264      /**
265       * Get the SSL encryption value for the server that created the
266       * message.
267       *
268       * @return The SSL encryption value for the server that created the
269       *         message.
270       */
271      public boolean getSSLEncryption()
272      {
273        return sslEncryption;
274      }
275    }