client/ftpd/src/se/lu/thep/coreftpd/webserver/ReadInputStreamSTDIN.java

Code
Comments
Other
Rev Date Author Line
741 10 Oct 06 olle 1 /*
1652 22 May 07 gregory 2  $Id$
741 10 Oct 06 olle 3
1916 31 Aug 07 jari 4  Copyright (C) 2006 Olle Mansson
1916 31 Aug 07 jari 5  Copyright (C) 2007 Gregory Vincic
741 10 Oct 06 olle 6
1652 22 May 07 gregory 7  This file is part of Proteios.
1652 22 May 07 gregory 8  Available at http://www.proteios.org/
741 10 Oct 06 olle 9
1652 22 May 07 gregory 10  Proteios is free software; you can redistribute it and/or modify it
1652 22 May 07 gregory 11  under the terms of the GNU General Public License as published by
1652 22 May 07 gregory 12  the Free Software Foundation; either version 2 of the License, or
1652 22 May 07 gregory 13  (at your option) any later version.
741 10 Oct 06 olle 14
1652 22 May 07 gregory 15  Proteios is distributed in the hope that it will be useful, but
1652 22 May 07 gregory 16  WITHOUT ANY WARRANTY; without even the implied warranty of
1652 22 May 07 gregory 17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1652 22 May 07 gregory 18  General Public License for more details.
741 10 Oct 06 olle 19
1652 22 May 07 gregory 20  You should have received a copy of the GNU General Public License
1652 22 May 07 gregory 21  along with this program; if not, write to the Free Software
1652 22 May 07 gregory 22  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1652 22 May 07 gregory 23  02111-1307, USA.
1652 22 May 07 gregory 24  */
741 10 Oct 06 olle 25
741 10 Oct 06 olle 26 //  Xerver Free Web Server
741 10 Oct 06 olle 27 //  Copyright (C) 2002-2005 Omid Rouhani
741 10 Oct 06 olle 28 //
741 10 Oct 06 olle 29 //
741 10 Oct 06 olle 30 //  This program is free software; you can redistribute it and/or
741 10 Oct 06 olle 31 //  modify it under the terms of the GNU General Public License
741 10 Oct 06 olle 32 //  as published by the Free Software Foundation; either version 2
741 10 Oct 06 olle 33 //  of the License, or (at your option) any later version.
741 10 Oct 06 olle 34 //
741 10 Oct 06 olle 35 //  This program is distributed in the hope that it will be useful,
741 10 Oct 06 olle 36 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
741 10 Oct 06 olle 37 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
741 10 Oct 06 olle 38 //  GNU General Public License for more details.
741 10 Oct 06 olle 39 //
741 10 Oct 06 olle 40 //  You should have received a copy of the GNU General Public License
741 10 Oct 06 olle 41 //  along with this program; if not, write to the Free Software
741 10 Oct 06 olle 42 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
741 10 Oct 06 olle 43 //
741 10 Oct 06 olle 44 //
741 10 Oct 06 olle 45 //  #############################################################
741 10 Oct 06 olle 46 //  ##  YOU CAN CONTACT THE AUTHOR (OMID ROUHANI) AT:          ##
741 10 Oct 06 olle 47 //  ##  HTTP://WWW.JAVASCRIPT.NU/XERVER/                       ##
741 10 Oct 06 olle 48 //  ##                                                         ##
741 10 Oct 06 olle 49 //  ##  IF YOUR SOFTWARE IS NOT RELEASED UNDER THE             ##
741 10 Oct 06 olle 50 //  ##  GNU GENERAL PUBLIC LICENSE (GPL),                      ##
741 10 Oct 06 olle 51 //  ##  PLEASE DO NOT COPY ANYTHING FROM THIS SOURCE CODE!!!   ##
741 10 Oct 06 olle 52 //  ##                                                         ##
741 10 Oct 06 olle 53 //  ##  FOR FULL LICENSE, PLEASE READ "XERVER LICENSE".        ##
741 10 Oct 06 olle 54 //  #############################################################
741 10 Oct 06 olle 55
1652 22 May 07 gregory 56 package se.lu.thep.coreftpd.webserver;
741 10 Oct 06 olle 57
791 23 Oct 06 olle 58 import se.lu.thep.coreftpd.common.DataInputStreamWithReadLine;
741 10 Oct 06 olle 59 import java.io.BufferedOutputStream;
741 10 Oct 06 olle 60 import java.io.OutputStream;
741 10 Oct 06 olle 61
741 10 Oct 06 olle 62 /**
1652 22 May 07 gregory 63  * 
1652 22 May 07 gregory 64  * <B>About this class:</B> <BR>
1652 22 May 07 gregory 65  * This class reads the POST data and sends it as STDIN to the script. <BR>
741 10 Oct 06 olle 66  * <BR>
1652 22 May 07 gregory 67  * 
1652 22 May 07 gregory 68  * <B>How to use:</B> <BR>
1652 22 May 07 gregory 69  * <CODE>(new ReadInputStreamSTDIN(DataInputStreamWithReadLine argDiswr,
1652 22 May 07 gregory 70  * OutputStream argOs)).start();</CODE> <BR>
741 10 Oct 06 olle 71  * <BR>
1652 22 May 07 gregory 72  * 
1652 22 May 07 gregory 73  * <B>More info:</B> <BR>
1652 22 May 07 gregory 74  * <CODE>argDiswr</CODE> = this is the <CODE>DataInputStreamWithReadLine</CODE>
1652 22 May 07 gregory 75  * containing the data the browser has sent us and that we still have not read
1652 22 May 07 gregory 76  * (=only the POST data is left in this stream) <BR>
1652 22 May 07 gregory 77  * <CODE>argOs</CODE> = Everything written to this will be sent to the script
1652 22 May 07 gregory 78  * (as STDIN). <BR>
741 10 Oct 06 olle 79  * <BR>
1652 22 May 07 gregory 80  * 
1652 22 May 07 gregory 81  * <B>IMPORTANT:</B> <CODE>argOs</CODE> is closed ("<CODE>argOs.close()</CODE>")
1652 22 May 07 gregory 82  * by <CODE>ReadInputStreamSTDIN</CODE>.
1652 22 May 07 gregory 83  * 
741 10 Oct 06 olle 84  * @author <a href="http://www.JavaScript.nu/xerver/" TARGET="_top">Omid Rouhani</a>
741 10 Oct 06 olle 85  * @version 1.0
741 10 Oct 06 olle 86  */
741 10 Oct 06 olle 87
1652 22 May 07 gregory 88 final public class ReadInputStreamSTDIN extends ReadInputStream {
741 10 Oct 06 olle 89   private DataInputStreamWithReadLine diswr;
1652 22 May 07 gregory 90
741 10 Oct 06 olle 91   private BufferedOutputStream bos;
1652 22 May 07 gregory 92
741 10 Oct 06 olle 93   RunScript rs_theRunScript;
741 10 Oct 06 olle 94
741 10 Oct 06 olle 95   /**
1652 22 May 07 gregory 96    * About the sleep time (TIME_TO_SLEEP): We want this to be short since this
1652 22 May 07 gregory 97    * is the minimum time the script has to wait until it gets new data.
1652 22 May 07 gregory 98    * However, if it is too short this will be like a while(true){}-loop which
1652 22 May 07 gregory 99    * will eat 100% CPU. So we balance these two factors against each other.
1652 22 May 07 gregory 100    */
1652 22 May 07 gregory 101   private final static int TIME_TO_SLEEP = 50; // See comments below
741 10 Oct 06 olle 102
1652 22 May 07 gregory 103   private final static int MAXIMUM_SLEEPS_IN_A_ROW = 100; // See comments
1652 22 May 07 gregory 104                               // below
741 10 Oct 06 olle 105
1652 22 May 07 gregory 106   public ReadInputStreamSTDIN() // now we can Extend ReadInputStreamSTDIN
1652 22 May 07 gregory 107                   // without problem
741 10 Oct 06 olle 108   {
741 10 Oct 06 olle 109   }
741 10 Oct 06 olle 110
1652 22 May 07 gregory 111   public ReadInputStreamSTDIN(DataInputStreamWithReadLine argDiswr,
1652 22 May 07 gregory 112       OutputStream argOs, RunScript argTheRunScript) {
1652 22 May 07 gregory 113     currentMode = INPUT_MODE;
1652 22 May 07 gregory 114     diswr = argDiswr;
1652 22 May 07 gregory 115     bos = new BufferedOutputStream(argOs);
1652 22 May 07 gregory 116     rs_theRunScript = argTheRunScript;
741 10 Oct 06 olle 117   }
741 10 Oct 06 olle 118
2386 14 Nov 07 gregory 119   @Override
1652 22 May 07 gregory 120   public void sendDataInputMode() {
1652 22 May 07 gregory 121     try {
1652 22 May 07 gregory 122       /**
1652 22 May 07 gregory 123        * About the algortihm: We see if we have data to read from "diswr".
1652 22 May 07 gregory 124        * If we have then we read that and send to script. If we don't have
1652 22 May 07 gregory 125        * any data we wait for TIME_TO_SLEEP milliseconds and look for new
1652 22 May 07 gregory 126        * data. However, if we never receive any new data (maybe all data
1652 22 May 07 gregory 127        * has been sent or there is a long network problem) then we only
1652 22 May 07 gregory 128        * repeat the procedure MAXIMUM_SLEEPS_IN_A_ROW times. After this we
1652 22 May 07 gregory 129        * just close the data stream.
1652 22 May 07 gregory 130        * 
1652 22 May 07 gregory 131        * However, everytime we get new data we reset the counter
1652 22 May 07 gregory 132        * (i_timesWeHaveSleept) so that we after this once again go one
1652 22 May 07 gregory 133        * sleeping a maximum of MAXIMUM_SLEEPS_IN_A_ROW times. So the total
1652 22 May 07 gregory 134        * number of sleeps (Thread.sleep()) can actually be inifinty (which
1652 22 May 07 gregory 135        * is what we want). This would occur if we had: get data, sleep,
1652 22 May 07 gregory 136        * get data, sleep etc. for ever.
1652 22 May 07 gregory 137        */
1652 22 May 07 gregory 138       int n;
1652 22 May 07 gregory 139       byte[] buffer = new byte[8192]; // I think 8192 is the largest
1652 22 May 07 gregory 140                       // buffer one of the
1652 22 May 07 gregory 141                       // XXXInputStreamXXX classes uses,
1652 22 May 07 gregory 142                       // so *maybe* it works faster if we
1652 22 May 07 gregory 143                       // read 8192 bytes each time. The
1652 22 May 07 gregory 144                       // value 8192 is showed when you for
1652 22 May 07 gregory 145                       // example check the value of
1652 22 May 07 gregory 146                       // ".available()" and you have more
1652 22 May 07 gregory 147                       // than 8192 bytes in the stream.
1652 22 May 07 gregory 148                       // ".available()" will still return
1652 22 May 07 gregory 149                       // 8192. (You can, however, still
1652 22 May 07 gregory 150                       // read more than 8192 bytes with
1652 22 May 07 gregory 151                       // for example
1652 22 May 07 gregory 152                       // "write(buffer,0,10240)"). Also,
1652 22 May 07 gregory 153                       // 8192 is 10'0000'0000'0000 binary
1652 22 May 07 gregory 154                       // and is the value of some
1652 22 May 07 gregory 155                       // constants, for example:
1652 22 May 07 gregory 156                       // java.util.prefs.Preference.MAX_VALUE_LENGTH,
1652 22 May 07 gregory 157                       // which is the "Maximum length of
1652 22 May 07 gregory 158                       // string allowed as a value".
1652 22 May 07 gregory 159       int i_timesWeHaveSleept = 0;
1652 22 May 07 gregory 160       while (i_timesWeHaveSleept < MAXIMUM_SLEEPS_IN_A_ROW) {
1652 22 May 07 gregory 161         while (diswr.available() > 0
1652 22 May 07 gregory 162             && (n = diswr.read(buffer, 0, 8192)) != -1)// (br.ready()
1652 22 May 07 gregory 163                                   // &&
1652 22 May 07 gregory 164                                   // (n=br.read(buffer))!=-1)
741 10 Oct 06 olle 165         {
1652 22 May 07 gregory 166           bos.write(buffer, 0, n);
1652 22 May 07 gregory 167           i_timesWeHaveSleept = 0; // Everytime we have got new
1652 22 May 07 gregory 168                         // data we reset the counter so
1652 22 May 07 gregory 169                         // that we after this once again
1652 22 May 07 gregory 170                         // go one waiting for a long
1652 22 May 07 gregory 171                         // time. Hence, as long as we
1652 22 May 07 gregory 172                         // once in a while get new data
1652 22 May 07 gregory 173                         // the time we wait
1652 22 May 07 gregory 174                         // (Thread.sleep()) can actually
1652 22 May 07 gregory 175                         // be inifinty. (hence: get
1652 22 May 07 gregory 176                         // data, sleep, get data, sleep
1652 22 May 07 gregory 177                         // etc. for ever; however, each
1652 22 May 07 gregory 178                         // sleep period is of course
1652 22 May 07 gregory 179                         // finite long)
741 10 Oct 06 olle 180         }
741 10 Oct 06 olle 181
1652 22 May 07 gregory 182         i_timesWeHaveSleept++;
1652 22 May 07 gregory 183         Thread.sleep(TIME_TO_SLEEP);
1652 22 May 07 gregory 184       }
741 10 Oct 06 olle 185
1652 22 May 07 gregory 186       bos.flush();
1652 22 May 07 gregory 187       bos.close();
1652 22 May 07 gregory 188
1652 22 May 07 gregory 189     } catch (Exception e) {
1652 22 May 07 gregory 190       exceptionOccured(e);
1652 22 May 07 gregory 191       if (b_showErrors)
1652 22 May 07 gregory 192         System.out
1652 22 May 07 gregory 193             .println("An error has occured @ sendDataInputMode:\n"
1652 22 May 07 gregory 194                 + e.getMessage());
1652 22 May 07 gregory 195     }
741 10 Oct 06 olle 196   }
741 10 Oct 06 olle 197
1652 22 May 07 gregory 198   private void exceptionOccured(Exception e) {
741 10 Oct 06 olle 199     rs_theRunScript.killProcess();
741 10 Oct 06 olle 200   }
741 10 Oct 06 olle 201 }