Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

CJDBCOutputStream.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2005 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Nicolas Modrzyk
00022  * Contributor(s): Emmanuel Cecchet.
00023  */
00024 
00025 package org.objectweb.cjdbc.common.stream;
00026 
00027 import java.io.BufferedOutputStream;
00028 import java.io.IOException;
00029 import java.io.ObjectOutputStream;
00030 import java.io.OutputStream;
00031 import java.io.StreamCorruptedException;
00032 import java.net.Socket;
00033 import java.util.ArrayList;
00034 
00035 /**
00036  * ObjectOutputStream to use between the controller and the driver.
00037  * 
00038  * @see org.objectweb.cjdbc.common.stream.CJDBCStream
00039  * @author <a href="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
00040  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00041  */
00042 public class CJDBCOutputStream
00043 {
00044   private ObjectOutputStream output;
00045   private long               bytesWritten;
00046   private Socket             socket;
00047   private boolean            useCompression                    = false;
00048   private long               speed                             = -1;
00049   private long               dateCreated;
00050   /**
00051    * ObjectOutputStream.writeUTF() encodes the String into binary however it
00052    * only works if the encoded UTF string is shorter in length that a short
00053    * (0xFFFFL). As every character is encoded in the worst case on 3 bytes, we
00054    * take this worst case value. If a String.length*3 > 0xFFFFL then we have to
00055    * go through the standard writeObject (or writeUnshared) method that will
00056    * call writeString() that will call in turn writeLongUTF(). Unfortunately,
00057    * writeString and writeLongUTF are not publicly accessible.
00058    */
00059   private static final long  MAXIMUM_STRING_LENGTH_IN_WRITEUTF = 0xFFFFL / 3;
00060 
00061   //private int unshared = 0;
00062 
00063   /**
00064    * Creates a new <code>CJDBCOutputStream</code> object for statistics on
00065    * sockets
00066    * 
00067    * @param socket socket to monitor
00068    * @throws IOException if an IO error occurs
00069    * @throws StreamCorruptedException if an error occurs
00070    */
00071   public CJDBCOutputStream(Socket socket) throws IOException,
00072       StreamCorruptedException
00073   {
00074     this(socket.getOutputStream());
00075     this.socket = socket;
00076   }
00077 
00078   /**
00079    * Creates a new CJDBCOutputStream from the given input stream.
00080    * 
00081    * @param out outputstream to wrap
00082    * @throws IOException if <code>new ObjectInputStream()</code> throws
00083    *           anException
00084    * @throws StreamCorruptedException same as above
00085    */
00086   public CJDBCOutputStream(OutputStream out) throws IOException,
00087       StreamCorruptedException
00088   {
00089     output = new ObjectOutputStream(new BufferedOutputStream(out));
00090     dateCreated = System.currentTimeMillis();
00091     bytesWritten = 0;
00092   }
00093 
00094   /**
00095    * @see java.io.ObjectOutputStream#flush()
00096    * @throws IOException if an error occurs
00097    */
00098   public void flush() throws IOException
00099   {
00100     output.flush();
00101   }
00102 
00103   /**
00104    * @see java.io.ObjectOutputStream#close()
00105    * @throws IOException if an error occurs
00106    */
00107   public void close() throws IOException
00108   {
00109     output.close();
00110   }
00111 
00112   /**
00113    * @see java.io.ObjectOutputStream#writeObject(java.lang.Object)
00114    * @param obj an Object to write to the stream
00115    * @throws IOException if an error occurs
00116    */
00117   public void writeObject(Object obj) throws IOException
00118   {
00119     if (useCompression)
00120     {
00121       byte[] bytes = CJDBCStream.compressObject(obj);
00122       bytesWritten += bytes.length + 4;
00123       // we are sending an integer on the pipe.
00124 
00125       output.writeInt(bytes.length);
00126       output.write(bytes);
00127     }
00128     else
00129     {
00130       if (obj == null)
00131       {
00132         output.writeInt(CJDBCStream.NULL);
00133         return;
00134       }
00135       else if (obj instanceof String)
00136       {
00137         String str = (String) obj;
00138         if (str.length() < MAXIMUM_STRING_LENGTH_IN_WRITEUTF)
00139         { // If the String can fit for a writeUTF call then use it else defaults
00140           // to writeUnshared (below) that will call the appropriate method to
00141           // send longer strings (not publicly available in the API).
00142           output.writeInt(CJDBCStream.STRING_OBJECT);
00143           output.writeUTF(str);
00144           return;
00145         }
00146       }
00147       else if (obj instanceof Integer)
00148       {
00149         output.writeInt(CJDBCStream.INTEGER_OBJECT);
00150         output.writeInt(((Integer) obj).intValue());
00151         return;
00152       }
00153       else if (obj instanceof Long)
00154       {
00155         output.writeInt(CJDBCStream.LONG_OBJECT);
00156         output.writeLong(((Long) obj).longValue());
00157         return;
00158       }
00159       else if (obj instanceof Boolean)
00160       {
00161         output.writeInt(CJDBCStream.BOOLEAN_OBJECT);
00162         output.writeBoolean(((Boolean) obj).booleanValue());
00163         return;
00164       }
00165 
00166       // Here we have an object for which we don't have special optimization and
00167       // that we will send as an object
00168       output.writeInt(CJDBCStream.OBJECT);
00169 
00170       // Use the unshared version to prevent the stream to keep references on
00171       // objects. This prevents objects sent through the channel from being
00172       // garbage collected and results in memory leaks.
00173       output.writeUnshared(obj);
00174 
00175       if (obj instanceof ArrayList)
00176       { // Reset the stream for shallow copies since unshared does not handle
00177         // them.
00178         output.flush();
00179         output.reset();
00180       }
00181     }
00182 
00183   }
00184 
00185   /**
00186    * @see java.io.ObjectOutputStream#writeUTF(java.lang.String)
00187    * @param string a String to write in UTF form to the stream
00188    * @throws IOException if an error occurs
00189    */
00190   public void writeUTF(String string) throws IOException
00191   {
00192     // Let writeObject handle this in case string is null
00193     this.writeObject(string);
00194     if (string != null)
00195       bytesWritten += string.length();
00196   }
00197 
00198   /**
00199    * @see java.io.ObjectOutputStream#writeInt(int)
00200    * @param value an int value to write to the stream
00201    * @throws IOException if an error occurs
00202    */
00203   public void writeInt(int value) throws IOException
00204   {
00205     bytesWritten += 4;
00206     output.writeInt(value);
00207   }
00208 
00209   /**
00210    * @see java.io.ObjectOutputStream#writeLong(long)
00211    * @param value a long value to write to the stream
00212    * @throws IOException if an error occurs
00213    */
00214   public void writeLong(long value) throws IOException
00215   {
00216     bytesWritten += 8;
00217     output.writeLong(value);
00218   }
00219 
00220   /**
00221    * @see java.io.ObjectOutputStream#writeBoolean(boolean)
00222    * @param value a boolean value to write to the stream
00223    * @throws IOException if an error occurs
00224    */
00225   public void writeBoolean(boolean value) throws IOException
00226   {
00227     bytesWritten += 1;
00228     output.writeBoolean(value);
00229   }
00230 
00231   /**
00232    * @return Returns the bytesWritten.
00233    */
00234   public long getBytesWritten()
00235   {
00236     return bytesWritten;
00237   }
00238 
00239   /**
00240    * @return Returns the socket.
00241    */
00242   public Socket getSocket()
00243   {
00244     return socket;
00245   }
00246 
00247   /**
00248    * @return Returns the dateCreated.
00249    */
00250   public long getDateCreated()
00251   {
00252     return dateCreated;
00253   }
00254 
00255   /**
00256    * @return Returns the useCompression.
00257    */
00258   public boolean getUseCompression()
00259   {
00260     return useCompression;
00261   }
00262 
00263   /**
00264    * @return Returns the speed.
00265    */
00266   public long getSpeed()
00267   {
00268     return speed;
00269   }
00270 }

Generated on Mon Apr 11 22:01:30 2005 for C-JDBC by  doxygen 1.3.9.1