KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > webman > stager > SiteReceiver


1 package webman.stager;
2
3 import java.net.*;
4 import java.security.*;
5 import java.io.*;
6 import java.util.*;
7 import java.lang.reflect.*;
8 import javax.net.ssl.*;
9 //import com.sun.net.ssl.*; //wird explizit bei den jeweiligen Klassen vorgesetzt, da ab jdk1.4 die einzelnen Klassen (z.B. SSLContext) auch aus javax.net.ssl stammen können -> kurze Schreibweise ist mehrdeutig
10
import com.ringlord.archive.*;
11 import org.apache.log4j.*;
12
13 /**
14  * Empfangsteil des Stagers
15  * Aufruf: siehe main()
16  * @author $Author: torsten $
17  * @version $Revision: 1.44.2.3 $
18  */

19 public class SiteReceiver extends Stager
20 {
21     /**Log4J-Category*/
22     private final static Category CAT = Category.getInstance(SiteReceiver.class);
23     
24     /**interner Versionszähler, orientiert sich an CVS-Revision*/
25     public final String JavaDoc INTERNAL_VERSION = "1.49";
26     
27     /**Standardname für das gespeicherte SiteDocumentsListing*/
28     public final static String JavaDoc DEFAULT_SITE_LISTING_NAME = "sitereceiver.doclist";
29     /**Standardname für das Logfile*/
30     public final static String JavaDoc DEFAULT_LOGFILE_NAME = "sitereceiver.log";
31     /**Standardname des SSL-Schlüsselspeichers*/
32     public final static String JavaDoc DEFAULT_KEYSTORE_FILE = "testkeys.sitereceiver";
33     /**Standardpasswort zum Zugriff auf den SSL-Schlüsselspeicher*/
34     public final static String JavaDoc DEFAULT_KEYSTORE_PASSWORD = "passphrase";
35     /**Standardport*/
36     public final static String JavaDoc DEFAULT_RECEIVER_PORT = "4242";
37     /**Standardtimeout für das Öffnen des Serversockets*/
38     public final static String JavaDoc DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS = "60";
39     /**maximales Timeout für das Öffnen des Serversockets*/
40     public final static int MAX_OPEN_TIMEOUT_SECONDS = 300;
41     /**Millisekunden pro Sekunde*/
42     private final static int MILLIS_PER_SECOND = 1000;
43     /**Puffergröße beim Empfangen der Site*/
44     private final static int RECEIVE_SITE_BUFSIZE = 2048;
45     /**in diesem Intervall schaut der Server nach, ob eine Verbindung eingegangen ist*/
46     private final static int SLEEP_TIME = 1000;
47     /**kleinster erlaubter Port*/
48     private final static int MIN_PORT = 1024;
49     /**größter erlaubter Port*/
50     private final static int MAX_PORT = 65535;
51     /**Puffer für das Entpacken der Site*/
52     private final static int ZIP_BUFSIZE = 16384;
53     //private final static int PROGRESS_INDICATOR_DELAY = 2000;
54

55     /**die Properties aus der Konfigurationsdatei*/
56     private PropertySet properties;
57     /**die Properties aus dem URL-Querystring*/
58     private PropertySet queryStringProperties = null;
59     /**Socket nach Verbindungserstellung; ist nicht private, da von ClientConnector drauf zugegriffen wird*/
60     SSLSocket clientSocket = null;
61     /**Socket zum Herstellen der Verbindung*/
62     private SSLServerSocket serverSocket = null;
63     /**SocketFactory für das SSLSocket*/
64     private SSLServerSocketFactory serverSocketFactory = null;
65     /**Größe der gepackten Site; fasst max. ca. 2 Gigabyte*/
66     private int zipSize;
67     /**das vom SiteTransmitter gesendete SiteDocumentsListing*/
68     private SiteDocumentsListing sendSiteListing = null;
69     /**das beim letzten Mal vom SiteReceiver gespeicherte SiteDocumentsListing*/
70     private SiteDocumentsListing oldListing = null;
71     /**das im jetzigen Durchlauf vom SiteReceiver gespeicherte SiteDocumentsListing*/
72     private SiteDocumentsListing newListing = null;
73     /**speichert die Logeinträge zwischen*/
74     private Vector vLog = new Vector();
75     /**zeigt an, ob das Logzwischenspeichern schon begonnen hat*/
76     private boolean vLogStarted = false;
77     /** es soll nur ein SiteReceiver gleichzeitig laufen */
78     private static boolean instanceRunning = false;
79     /**zählt die akutalisierten Dateien*/
80     private int updatedFiles = 0;
81     /**zählt die aktualisierten Verzeichnisse*/
82     private int updatedDirs = 0;
83     /**JTest-Dummy*/
84     private String JavaDoc fuckJTest;
85     
86     /**
87      * Startet neuen SiteReceiver, falls nicht schon einer läuft
88      * @param args <remoteIP> <propertyFile> [<urlQueryString>]
89      */

90     public static void main(String JavaDoc[] args)
91     {
92         if ( instanceRunning )
93         {
94             System.exit(1);
95         }
96         else
97         {
98             instanceRunning = true;
99             new SiteReceiver(args);
100         }
101     }
102     
103     /**
104      * Konstruiert SiteReceiver
105      * @param args <remoteIP> <propertyFile> [<urlQueryString>]
106      */

107     private SiteReceiver(String JavaDoc[] args)
108     {
109         outStream = System.out; //Work-around für Jtest (wenn man statisch inititalisiert, erkennt jtest system.out!!
110
String JavaDoc propertyFile, remoteIP;
111         remoteIP = "127.0.0.1"; //Dummy
112
// parse arguments
113
CAT.info("WebMan SiteReceiver starting at " + new java.util.Date JavaDoc());
114         try
115         {
116             // parse properties
117
remoteIP = args[0];
118             propertyFile = args[1];
119             if ( args.length > 2 ) //optional kommt noch ein URL-QueryString rüber
120
{
121                 CAT.debug("PARSING properties from urlString...");
122                 queryStringProperties = new PropertySet(parseQueryString(args[2]));
123             }
124             else
125             {
126                 queryStringProperties = null;
127             }
128             //kommt erst nach parseQueryString, da in readProperties queryStringProperties abgefragt wird
129
CAT.debug("PARSING properties from file...");
130             properties = readProperties(propertyFile);
131         }
132         catch (Exception JavaDoc e)
133         {
134             error("Error in configuration: ",e);
135             error("SiteReceiver stopped.");
136             printUsage();
137             System.exit(-1);
138         }
139
140         // open log
141
logfile = openLog(properties.get("logFile"),properties.get("appendLog").equals("true"));
142         if ( logfile == null )
143         {
144             error("Could not open logfile " + properties.get("logFile"));
145             error("SiteReceiver stopped.");
146             System.exit(-1);
147         }
148         logAndPrint("<h2>WebMan Stager: SiteReceiver</h2>");
149         logAndPrint("<B>started at " + new java.util.Date JavaDoc() + "</B>");
150         logAndPrint("Java version: " + System.getProperty("java.version") + ", Java vendor: "
151                     + System.getProperty("java.vendor") + ", SiteReceiver-Version: " + INTERNAL_VERSION);
152         try
153         {
154            logAndPrint("Remote host: " + InetAddress.getByName(remoteIP));
155         }
156         catch( Exception JavaDoc e)
157         {
158             logAndPrint("Remote host: " + remoteIP + " (unknown host)");
159         }
160         // testing ip of client
161
if ( !transferAllowedFrom(remoteIP,properties.get("SenderIP")) )
162         {
163            error("Request denied because IP " + remoteIP + " is not allowed");
164            error("SiteReceiver stopped.");
165            System.exit(-1);
166         }
167         logAndPrint("ReceiverPort: " + properties.get("ReceiverPort"));
168         logAndPrint("TempDir: " + markAsFile(properties.get("tempDir")));
169         if ( properties.get("appendLog").equals("true") )
170         {
171             logAndPrint("Appending log to " + markAsFile(properties.get("logFile")));
172         }
173         else
174         {
175             logAndPrint("Creating log in " + markAsFile(properties.get("logFile")));
176         }
177         try
178         {
179             logAndPrint("Using site documents listing " + markAsFile(properties.get("siteDocumentsListing")));
180             oldListing = new SiteDocumentsListing(properties.get("siteDocumentsListing"));
181         }
182         catch ( IOException e)
183         {
184             logAndPrint("Found no old listing at " + markAsFile(properties.get("siteDocumentsListing")));
185         }
186         try
187         {
188             logAndPrint("ReceiverHost: " + (properties.get("ReceiverHost").equals("localhost")
189                                             ? InetAddress.getLocalHost()
190                                             : InetAddress.getByName(properties.get("ReceiverHost"))));
191         }
192         catch (java.net.UnknownHostException JavaDoc e)
193         {
194             error("Server IP is unknown",e);
195         }
196         if ( properties.get("Simulate").equals("true") )
197         {
198             logAndPrint(" ");
199             logAndPrint("<B> --- Entering Simulation Mode: No files are changed (except logfile and temporary directory). --- </B>");
200             logAndPrint(" ");
201         }
202         try
203         {
204  //*BEGIN TEST
205
boolean success = true;
206             int openSocketTimeout = MILLIS_PER_SECOND * Integer.parseInt(properties.get("OpenSocketTimeoutSeconds"));
207             try
208             {
209                 // methoden, die selbst keine Ausgabe erzeugen, werden über methodSucceed(String,String)
210
// abgewickelt, damit man weiß, was abgeht (z.B. "initializing ssl --- done")
211
// methoden, die selbst Ausgaben erzeugen, werden über methodSucceed(String) abgewickelt, d.h.
212
// es wird an deren Ausgabe nur noch ein "--- done" oder "--- fail: ..." angehängt
213

214                 // try to init ssl
215
if ( !methodSucceed(initSSL(), "initializing ssl")
216                 // preparing ssl connection
217
|| !methodSucceed(prepareSSL(properties.get("keyStore"), properties.get("keyStorePassword"),
218                                                 properties.get("keyPassword"),properties.get("trustStore")))
219                 // creating temp dir
220
|| !methodSucceed(createTempDir(properties.get("tempDir")), "creating temp dir")
221                 // opening ssl socket
222
|| !methodSucceed(createConnection(properties.get("ReceiverHost"),
223                                                      Integer.parseInt(properties.get("ReceiverPort")),openSocketTimeout,
224                                                      !properties.get("trustStore").equals("")))
225                 // receiving zip size
226
|| !methodSucceed(receiveFileSize(), "receiving file size")
227                 // receiving site
228
|| !methodSucceed(receiveSite(properties.get("archiveName")))
229                 // receiving siteinfo
230
|| !methodSucceed(receiveSiteInfo(), "receiving site info")
231                 // unpacking site
232
|| !methodSucceed(extractSite(properties.get("tempDir"),properties.get("archiveName"),
233                                                 properties.get("SkipErrors").equals("true"),
234                                                 properties.get("Simulate").equals("true")) )
235                   )
236                 {
237                     success = false;
238                 }
239             }
240             // catch unknow exception
241
catch (Exception JavaDoc e)
242             {
243                 error("Unknown exception: ",e);
244                 success = false;
245             }
246             //AfterBurner
247
if ( properties.get("AfterBurner") != null )
248             {
249                 String JavaDoc afterBurner = properties.get("AfterBurner");
250                 Vector params = properties.getPropertyGroup("AfterBurnerParameter");
251                 //direkter Cast von Object[] nach String[] klappt leider nicht (weiß nich wieso)
252
String JavaDoc[] strParams = new String JavaDoc[params.size()];
253                 String JavaDoc paramString = "";
254                 for ( int i=0; i<params.size(); i++ )
255                 {
256                     strParams[i] = (String JavaDoc)params.elementAt(i);
257                     paramString += strParams[i] + " ";
258                 }
259                 logAndPrint("<B>running AfterBurner</B>");
260                 boolean noJava = properties.get("AfterBurnerNoJava").equals("true");
261                 logAndPrint((noJava ? "" : "java ") + afterBurner + " " + "<I>" + paramString + "</I>");
262                 if ( !doAfterBurner(afterBurner,strParams,noJava) )
263                 {
264                     success = false;
265                     CAT.warn("AfterBurner failed");
266                 }
267                 else
268                 {
269                     logAndPrint("<B>... done</B>");
270                 }
271             }
272             // transmitting log
273
if ( clientSocket == null )
274             {
275                 logAndPrint("skipping log transmission (no socket available)");
276             }
277             else if ( !methodSucceed(transmitLog(success),"transmitting log") )
278             {
279                 success = false;
280             }
281             if ( !success )
282             {
283                 //will noch auf die log4j-Logs hinweisen
284
Enumeration appenders = CAT.getRoot().getAllAppenders();
285                 Vector logNames = new Vector();
286                 Object JavaDoc appender;
287                 while ( appenders.hasMoreElements() )
288                 {
289                     appender = appenders.nextElement();
290                     if ( appender instanceof FileAppender )
291                     {
292                         logNames.add( ((FileAppender)appender).getFile() );
293                     }
294                 }
295                 if ( logNames.size() > 0 )
296                 {
297                     String JavaDoc hint = "Something went wrong. You should check the Log4J-Logfiles: ";
298                     for ( int i=0; i<logNames.size(); i++ )
299                     {
300                         hint += (String JavaDoc)logNames.elementAt(i);
301                         if ( i<logNames.size()-1 )
302                         {
303                             hint += ", ";
304                         }
305                     }
306                     error(hint + ".");
307                 }
308                 logAndPrint("abort");
309                 System.exit(-1);
310             }
311 // TEST ENDE */
312
logAndPrint("WebMan SiteReceiver finished at " + new java.util.Date JavaDoc());
313         }
314         
315         finally
316         {
317             try
318             {
319                 clientSocket.close();
320                 serverSocket.close();
321                 closeLog();
322             }
323             catch (Exception JavaDoc e)
324             {
325                 fuckJTest = "wen interessiert's?";
326             }
327         }
328         // a must be for stopping the accept() method in thread
329
System.exit(0);
330     }
331
332     /**
333      * Zerlegt den URL-QueryString in seine Bestandteile
334      * @param query QueryString der Aufruf-URL
335      * @return Hastable mit allen erkannten key-value-Paaren
336      */

337     private Hashtable parseQueryString(String JavaDoc query)
338     {
339         Hashtable result = new Hashtable();
340         String JavaDoc pair, key, value;
341         int delimiter;
342
343         StringTokenizer tokenizer = new StringTokenizer(query,"&");
344         while ( tokenizer.hasMoreTokens() )
345         {
346             pair = tokenizer.nextToken();
347             delimiter = pair.indexOf('=');
348             if (delimiter > -1)
349             {
350                 key = pair.substring(0,delimiter);
351                 value = pair.substring(delimiter+1);
352                 if (value.length() > 0)
353                 {//gleich noch die URL-Kodierung rückgängig machen
354
try
355                     {
356                         result.put(URLDecoder.decode(key),URLDecoder.decode(value));
357                     }
358                     catch (Exception JavaDoc e)
359                     {
360                         fuckJTest="was immer hier auch schief gehen könnte.";
361                     }
362                 }
363             }
364         }
365         return result;
366     }
367     
368     /**
369      * liest Properties von der angegebenen ResourceDescriptor und gibt daraus resultierndes PropertySet zurück
370      * @param propertyFile Name des Property-Filename
371      * @return gültiges PropertySet
372      * @throws WrongConfigurationException wenn beim Parsen der Properties ein Fehler auftrat
373      */

374     private PropertySet readProperties(String JavaDoc propertyFile) throws WrongConfigurationException
375     {
376         //Behandle erstemal den Fall PropertyFile
377
Properties p = new Properties();
378         // ---> anzudenken: Propertymanager, um sowohl PropertyFiles als auch webman-Properties zu benutzen!
379
//Problem: Die DB ist vom Stager aus schwer anzusprechen; somit fällt der PropertyManager auch flach
380
try
381         {
382             p.load(new FileInputStream(propertyFile));
383         }
384         catch (Exception JavaDoc e)
385         {
386             throw new WrongConfigurationException("Could not read property file \"" + propertyFile + "\": " + e.toString());
387         }
388         PropertySet source = new PropertySet(p); //temporär, um diese und die globalen properties zusammenzuführen
389
return parseProperties(source);
390     }
391         
392     /**
393      * checkt die übergebenen Properties auf Fehlerfreiheit und Vollständigkeit und erzeugt neues PropertySet
394      * @param source das zu checkende PropertySet
395      * @return ein gültiges PropertySet
396      * @throws WrongConfigurationException wenn beim Parsen der Properties ein Fehler auftrat
397      */

398     private PropertySet parseProperties(PropertySet source) throws WrongConfigurationException
399     {
400         PropertySet result = new PropertySet();
401         try
402         {
403             String JavaDoc temp = null; //für temporäre Propertyauswertung
404
File tempFile = null; // -""-
405

406             result.set("logDir",new File(getProperty(source,"logDir")).getCanonicalPath());
407             CAT.debug("LogDir=" + result.get("logDir"));
408             tempFile = new File(result.get("logDir"));
409             if ( !tempFile.exists() )
410             {
411                 throw new WrongConfigurationException("LogDir " + tempFile.getPath() + " doesn't exist.");
412             }
413             else if ( !tempFile.canWrite() )
414             {
415                 throw new WrongConfigurationException("Cannot write to LogDir " + tempFile.getPath());
416             }
417             
418             //logname kann auch vom sender aus gesetzt werden (über URLQueryString)
419
if ( queryStringProperties != null && queryStringProperties.get("LogFile") != null )
420             {
421                 temp = queryStringProperties.get("LogFile");
422             }
423             else
424             {
425                 try
426                 {
427                     temp = getProperty(source,"LogFile");
428                 }
429                 catch ( PropertyNotFoundException p )
430                 {
431                     temp = DEFAULT_LOGFILE_NAME;
432                 }
433             }
434             result.set("logFile",getAbsoluteName(result.get("logDir"),temp));
435             CAT.debug("logFile=" + result.get("logFile"));
436                                   
437             //sitelisting kann auch vom sender aus gesetzt werden (über URLQueryString)
438
if ( queryStringProperties != null && queryStringProperties.get("siteDocumentsListing") != null )
439             {
440                 temp = queryStringProperties.get("siteDocumentsListing");
441             }
442             else
443             {
444                 try
445                 {
446                     temp = getProperty(source,"siteDocumentsListing");
447                 }
448                 catch ( PropertyNotFoundException p )
449                 {
450                     temp = DEFAULT_SITE_LISTING_NAME;
451                 }
452             }
453             result.set("siteDocumentsListing",getAbsoluteName(result.get("logDir"),temp));
454             CAT.debug("siteDocumentsListing=" + result.get("siteDocumentsListing"));
455             
456             //skipErrors kann auch vom sender aus gesetzt werden (über URLQueryString)
457
result.set("SkipErrors","false");
458             //diese Property kann vom Receiver und vom Transmitter aus gesetzt werden; sobald sie bei einem
459
//von beiden "yes" ist, wird sie auf true gesetzt
460
if ( queryStringProperties != null && queryStringProperties.get("SkipErrors") != null )
461             {
462                 if ( queryStringProperties.get("SkipErrors").equals("yes") )
463                 {
464                     result.set("SkipErrors","true");
465                 }
466             }
467             else
468             {
469                 temp = source.get("SkipErrors");
470                 if ( temp != null && temp.toLowerCase().equals("yes") )
471                 {
472                     result.set("SkipErrors","true");
473                 }
474             }
475             CAT.debug("SkipErrors=" + result.get("SkipErrors"));
476             
477             //schlussendlich noch die Simulations-Property (zeigt an, ob das Staging nur simuliert werden soll)
478
result.set("Simulate","false");
479             //diese Property kann vom Receiver und vom Transmitter aus gesetzt werden; sobald sie bei einem
480
//von beiden "yes" ist, wird sie auf true gesetzt
481
if ( queryStringProperties != null && queryStringProperties.get("Simulate") != null )
482             {
483                 if ( queryStringProperties.get("Simulate").equals("yes") )
484                 {
485                     result.set("Simulate","true");
486                 }
487             }
488             else
489             {
490                 temp = source.get("Simulate");
491                 if ( temp != null && temp.toLowerCase().equals("yes") )
492                 {
493                     result.set("Simulate","true");
494                 }
495             }
496             CAT.debug("Simulate=" + result.get("Simulate"));
497             
498             //Nun die "normalen" Properties
499
temp = new File(getProperty(source,"TempDir")).getCanonicalPath();
500             tempFile = new File(temp);
501             if ( !tempFile.exists() )
502             {
503                 throw new WrongConfigurationException("TempDir " + temp + " doesn't exist.");
504             }
505             if ( !tempFile.isDirectory() || !tempFile.canRead() || !tempFile.canWrite() )
506             {
507                 throw new WrongConfigurationException("TempDir " + temp + " is not a readable/writeable directory.");
508             }
509             //Lege in tempdir ein eigenes Unterverzeichnis zum Entpacken der Site an
510
try
511             { //und checke auch gleich, ob ich tempZip erzeugen kann
512
tempFile = File.createTempFile("webman_received",".zip",new File(temp));
513                 tempFile.delete();
514                 result.set("archiveName",tempFile.getPath());
515                 CAT.debug("ArchiveName=" + result.get("archiveName"));
516                 
517                 tempFile = File.createTempFile("webman_site","",new File(temp));
518                 tempFile.delete();
519
520                 //brauche tempDir mit abschließendem /
521
temp = tempFile.getPath();
522                 if ( !temp.endsWith(File.separator) && !temp.endsWith("/") )
523                 {//In Java können Windows-Pfadnamen auch mit / gebildet werden
524
temp += File.separator;
525                 }
526                 result.set("tempDir",temp);
527                 CAT.debug("TempDir=" + result.get("TempDir"));
528             }
529             catch (IOException e)
530             {
531                 throw new WrongConfigurationException("Cannot create temporary files in TempDir " + temp + ".");
532             }
533             
534             try
535             {
536                 temp = getProperty(source, "AppendLog");
537                 if ( temp.toLowerCase().equals("yes") )
538                 {
539                     result.set("appendLog","true");
540                 }
541                 else
542                 {
543                     result.set("appendLog","false");
544                 }
545             }
546             catch (Exception JavaDoc e)
547             {
548                 result.set("appendLog","false");//default ist false
549
}
550             CAT.debug("AppendLog=" + result.get("AppendLog"));
551                       
552             try
553             {
554                 result.set("keyStore",getProperty(source,"KeyStore"));
555             }
556             catch (PropertyNotFoundException p)
557             {
558                 result.set("keyStore",DEFAULT_KEYSTORE_FILE);
559             }
560             CAT.debug("keyStore=" + result.get("keyStore"));
561             
562             try
563             {
564                 result.set("KeyStorePassword",getProperty(source,"KeyStorePassword"));
565             }
566             catch (PropertyNotFoundException p)
567             {
568                 result.set("KeyStorePassword",DEFAULT_KEYSTORE_PASSWORD);
569             }
570             CAT.debug("KeyStorePassword=" + result.get("KeyStorePassword"));
571             
572             try
573             {
574                 result.set("KeyPassword",getProperty(source,"KeyPassword"));
575             }
576             catch (PropertyNotFoundException p)
577             {
578                 result.set("KeyPassword",result.get("KeyStorePassword"));
579             }
580             CAT.debug("KeyPassword=" + result.get("KeyPassword"));
581                         
582             //brauche truststore nur, wenn ich ClientAuthentifizierung durchführen möchte!
583
try
584             {
585                 result.set("trustStore",getProperty(source,"TrustStore"));
586             }
587             catch (PropertyNotFoundException p)
588             {
589                 result.set("trustStore","");
590             }
591             CAT.debug("trustStore=" + result.get("trustStore"));
592                          
593             try
594             {
595                 int port = Integer.parseInt(getProperty(source,"ReceiverPort")); //wirft Exception bei falschem Zahlenformat
596
if ( port < MIN_PORT || port > MAX_PORT )
597                 {
598                     throw new NumberFormatException JavaDoc();
599                 }
600                 result.set("ReceiverPort",String.valueOf(port));
601             }
602             catch (NumberFormatException JavaDoc n)
603             {
604                 throw new WrongConfigurationException("ReceiverPort must be within 1024...65535");
605             }
606             catch (PropertyNotFoundException p)
607             {
608                 result.set("ReceiverPort",DEFAULT_RECEIVER_PORT);
609             }
610             CAT.debug("ReceiverPort=" + result.get("ReceiverPort"));
611                         
612             result.set("SenderIP",getProperty(source, "SenderIP"));
613             CAT.debug("SenderIP=" + result.get("SenderIP"));
614             
615             try
616             {//OpenSocketsTimeoutSeconds ist optional; default = 60
617
temp = getProperty(source,"OpenSocketTimeoutSeconds");
618                 //muss auf temp!= null checken, da hier keine Exception geowrfen wird, wenn isFinal=false ist
619
if ( temp != null && (Integer.parseInt(temp) < 1 || Integer.parseInt(temp) > MAX_OPEN_TIMEOUT_SECONDS) )
620                 {
621                     throw new WrongConfigurationException("OpenSocketTimeoutSeconds must be within 1.." + MAX_OPEN_TIMEOUT_SECONDS);
622                 }
623             }
624             catch ( PropertyNotFoundException p )
625             {
626                 temp = DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS;
627             }
628             result.set("OpenSocketTimeoutSeconds",temp);
629             CAT.debug("OpenSocketTimeoutSeconds=" + result.get("OpenSocketTimeoutSeconds"));
630                         
631             try
632             {
633                 result.set("ReceiverHost",getProperty(source,"ReceiverHost"));
634             }
635             catch (Exception JavaDoc e)
636             {//kein Problem, benutzen localhost
637
result.set("ReceiverHost","localhost");
638             }
639             CAT.debug("ReceiverHost=" + result.get("ReceiverHost"));
640                         
641             //eventuell noch AfterBurner-Einstellungen
642
//AfterBurner kann NUR vom sender aus gesetzt werden (über URLQueryString)
643
if ( queryStringProperties != null && queryStringProperties.get("AfterBurner") != null )
644             {
645                 result.set("AfterBurner",queryStringProperties.get("AfterBurner"));
646                 CAT.debug("AfterBurner=" + result.get("AfterBurner"));
647                 temp = queryStringProperties.get("AfterBurnerNoJava");
648                 if ( temp != null && temp.equals("true") )
649                 {
650                     result.set("AfterBurnerNoJava","true");
651                 }
652                 else
653                 {
654                     result.set("AfterBurnerNoJava","false");
655                 }
656                 CAT.debug("AfterBurnerNoJava=" + result.get("AfterBurnerNoJava"));
657                 Vector params = queryStringProperties.getPropertyGroup("AfterBurnerParameter");
658                 for ( int i=0; i<params.size(); i++)
659                 {
660                     result.set("AfterBurnerParameter" + i,params.elementAt(i));
661                 }
662             }
663         }
664         catch (PropertyNotFoundException p)
665         {
666             throw new WrongConfigurationException(p);
667         }
668         catch (Exception JavaDoc e) //oder was sonst so anfällt
669
{
670             if ( !(e instanceof WrongConfigurationException) )
671             {//eine andere als ne WrongConfigurationException erstmal hübsch in eine eben solche "verpacken"!
672
CAT.error("Unknown Exception: " + e.getMessage(),e); //printet auch den StackTrace
673
throw new WrongConfigurationException(e.toString());
674             }
675             else
676             {//sonst isses die oben geworfene WronConfigurationException -> einfach durchreichen
677
throw (WrongConfigurationException)e;
678             }
679         }
680         return result;
681     }
682     
683     /**
684      * bereitet die SSL-Verbindung vor (initialisiert die SSLServerSocketFactory)
685      * @param keyStore Dateiname des SSL-Schlüsselspeichers
686      * @param keyStorePassword Zugriffspasswort für den SSL-Schlüsselspeicher
687      * @param keyPassword Passwort für den zu benutzenden SSL-Schlüssel
688      * @param trustStore Dateiname des SSL-Zertifikatspeichers (optional)
689      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
690      */

691     private String JavaDoc prepareSSL(String JavaDoc keyStore, String JavaDoc keyStorePassword, String JavaDoc keyPassword, String JavaDoc trustStore)
692     {
693         logAndPrint("<b>preparing ssl connection</b>");
694         try
695         {
696             /*
697             Man könnte TrustStore auch über System.setProperty("javax.net.ssl.trustStore",trustStore);
698             setzen, aber dann funzt die ClientAuthentication irgendwie nich... (obwohl das im JSSE-Example schon funzt)
699             */

700             
701             KeyStore ks = KeyStore.getInstance("JKS");
702             
703             com.sun.net.ssl.TrustManagerFactory tmf = null;
704             //brauche TrustStore nur zur ClientAuthentifizierung
705
if ( !trustStore.equals("") )
706             {
707                 tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509");
708                 ks.load(Stager.getResourceInputStream(this.getClass(),trustStore),null);
709                 tmf.init(ks);
710                 logAndPrint("using TrustStore " + markAsFile(trustStore) + " (for client authentication)");
711             }
712             
713             com.sun.net.ssl.SSLContext ssl = com.sun.net.ssl.SSLContext.getInstance("SSL");
714             
715             com.sun.net.ssl.KeyManagerFactory kmf = com.sun.net.ssl.KeyManagerFactory.getInstance("SunX509");
716             ks.load(Stager.getResourceInputStream(this.getClass(),keyStore),keyStorePassword.toCharArray());
717             logAndPrint("using KeyStore " + markAsFile(keyStore) + " (for server authentication)");
718                     
719             kmf.init(ks, keyPassword.toCharArray());
720             ssl.init(kmf.getKeyManagers(), (tmf==null ? null : tmf.getTrustManagers()), null);
721             serverSocketFactory = ssl.getServerSocketFactory();
722         }
723         catch (Exception JavaDoc e)
724         {
725             return "unable to create ssl socket factory: " + e;
726         }
727         return null;
728     }
729
730     /**
731      * @param ipaddress IPAdresse, an der das ServerSocket geöffnet werden soll
732      * @param receiverPort Port, auf dem das ServerSocket geöffnet werden soll
733      * @param timeOut wieviele Millisekunden soll auf die Verbindung gewartet werden
734      * @param useClientAuth wenn true, dann wird vom Client eine Authentifizierung über SSL-Zertifikat verlangt
735      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
736      */

737     private String JavaDoc createConnection(String JavaDoc ipaddress, int receiverPort, int timeOut, boolean useClientAuth)
738     {
739         try
740         {
741             logAndPrint("<b>creating server socket</b>");
742             serverSocket = (SSLServerSocket)serverSocketFactory.createServerSocket(
743                             receiverPort, 1, //1 = number of connections
744
ipaddress.equals("localhost") ? InetAddress.getLocalHost()
745                                                           : InetAddress.getByName(ipaddress));
746             //darf nicht getByName("localhost") statt getLocalHost() benutzen, da letzteres die
747
//äußere (also wirklich interessante) IP liefert. Wenn ich localhost oder 127.0.0.1
748
//benutze, funzt die ganze SSL-Chose nich!!
749
if ( useClientAuth )
750             {
751                 logAndPrint("demanding SSL client authentication");
752                 serverSocket.setNeedClientAuth(useClientAuth);
753             }
754             CAT.debug("createConnection(): serverSocket created");
755         }
756         catch (Exception JavaDoc e)
757         {
758             return "unable to create server socket: " + e;
759         }
760         logAndPrint("starting ClientConnector...");
761         // waiting for client to connect
762
ClientConnector acceptor = new ClientConnector(this,serverSocket);
763         logAndPrint("opened server socket at " + new java.util.Date JavaDoc());
764         acceptor.start();
765         long start_time = System.currentTimeMillis();
766         try
767         {
768             while ( System.currentTimeMillis() - start_time < timeOut && clientSocket == null )
769             {
770                 Thread.sleep(SLEEP_TIME);
771             }
772         }
773         catch (Exception JavaDoc e)
774         {
775             return "server interrupted: " + e;
776         }
777         if ( clientSocket == null )
778         {
779             try
780             {
781                 serverSocket.close();
782                 logAndPrint("closed server socket at " + new java.util.Date JavaDoc());
783             }
784             catch (Exception JavaDoc e)
785             {
786                 return "connection from client failed - time out, but cannot close server socket: " + e;
787             }
788             return "connection from client failed - time out";
789         }
790         // testing sender ip address
791
if ( !transferAllowedFrom(clientSocket.getInetAddress().getHostAddress(),properties.get("SenderIP")))
792         {
793             try
794             {
795                 printToSocket(clientSocket, "request denied");
796             }
797             catch (Exception JavaDoc e)
798             {
799                 CAT.warn("request denied because ip " + clientSocket.getInetAddress() + " not allowed");
800             }
801             return "request denied";
802         }
803         try
804         {
805             printToSocket(clientSocket, "ready");
806         }
807         catch (Exception JavaDoc e)
808         {
809             return e.toString();
810         }
811         try
812         {
813             clientSocket.setSoTimeout(0);
814         }
815         catch (Exception JavaDoc e)
816         {
817             return e.toString();
818         }
819         logAndPrint("end of http output");//nötig, damit cgi-Aufruf als fertig gilt, wodurch verhindert wird, dass
820
//der ServerStarter bei getInputStream() blockt (der wartet nämlich sonst bis zum Ende vom SiteReceiver)
821
vLogStarted = true;
822         return null;
823     }
824     
825     /**
826      * liest die Dateigröße des zu empfangenden Zipfiles
827      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
828      */

829     private String JavaDoc receiveFileSize()
830     {
831     // receiving size of zip
832
String JavaDoc line;
833         try
834         {
835             line = readFromSocket(clientSocket);
836         }
837         catch (Exception JavaDoc e)
838         {
839             return "unable to read from socket: " + e.toString();
840         }
841         if ( line == null )
842         {
843             return "received null instead of zip-size";
844         }
845         if ( !line.startsWith("zip.size=") )
846         {
847             return "wrong format: " + markAsFile(line) + " - expected " + markAsFile("zip.size=[0-9]+");
848         }
849         line = line.substring(9, line.length());
850         try
851         {
852             zipSize = Integer.parseInt(line);
853         }
854         catch (Exception JavaDoc e)
855         {
856             return "wrong format: " + markAsFile(line) + e + " - expected " + markAsFile("zip.size=[0-9]+");
857         }
858         return null;
859     }
860
861     /**
862      * legt ein temporäres Verzeichnis zum Entpacken der empfangenen Site an
863      * @param tempDir Name des anzulegenden temp. Verzeichisses
864      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
865      */

866     private String JavaDoc createTempDir(String JavaDoc tempDir)
867     {
868         // creating tempdir
869
File tmp = new File(tempDir);
870         int fileCount = 0;
871         if ( tmp.exists() )
872         {
873             if ( !tmp.isDirectory() )
874             {
875                 return("could not create temporary directory " + markAsFile(tempDir) + " - file of same name does exist");
876             }
877             logAndPrint("Deleting files in temporary dir: " + tempDir);
878             String JavaDoc[] list = tmp.list();
879             for ( int i = 0; i < list.length; i++ )
880             {
881                 fileCount += deleteFile(tempDir + File.separator + list[i]);
882             }
883             CAT.info(fileCount + " files/dirs deleted in temporary dir " + tempDir);
884         }
885         else if ( !tmp.mkdirs() )
886         {
887             return "could not create temporary directory " + markAsFile(tempDir);
888         }
889         return null;
890     }
891     
892     /**
893      * empfängt die gepackte Site und speichert sie als Zipfile ab
894      * @param archiveName Dateiname, unter dem das Zipfile abgelegt wird
895      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
896      */

897     private String JavaDoc receiveSite(String JavaDoc archiveName)
898     {
899         logAndPrint("<b>receiving site</b>");
900         try
901         {
902             FileOutputStream fout = new FileOutputStream(archiveName);
903             BufferedInputStream in = new BufferedInputStream(clientSocket.getInputStream());
904             byte[] buf = new byte[RECEIVE_SITE_BUFSIZE];
905             int to_read = zipSize; //fasst max. ca. 2 Gigabyte -> sollte reichen
906
int read;
907     
908             logAndPrint("start receiving site: " + (new Date()).toString() + " ");
909             logAndPrint("wait until " + zipSize + " bytes are received...");
910             while ( to_read > 0 )
911             {
912                 if ( to_read < RECEIVE_SITE_BUFSIZE )
913                 {
914                     read = in.read(buf, 0, to_read);
915                 }
916                 else
917                 {
918                     read = in.read(buf, 0, RECEIVE_SITE_BUFSIZE);
919                 }
920                 fout.write(buf, 0, read);
921                 to_read -= read;
922             }
923             logAndPrint("finish receiving site: " + (new Date()).toString());
924             fout.flush();
925             fout.close();
926         }
927         catch (Exception JavaDoc e)
928         {
929             return "unable to receive zip file: " + e;
930         }
931         return null;
932     }
933
934     /**
935      * empfängt das SiteDocumentsListing vom SiteTransmitter
936      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
937      */

938     private String JavaDoc receiveSiteInfo()
939     {
940         try
941         {
942             InputStream in = clientSocket.getInputStream();
943             ObjectInputStream ois = new ObjectInputStream(in);
944             sendSiteListing = (SiteDocumentsListing)ois.readObject();
945         }
946         catch (Exception JavaDoc e)
947         {
948             return "unable to receive site info: " + e.toString();
949         }
950         return null;
951     }
952
953     /**
954      * entpackt die empfangene Site erst in ein temporäres Verzeichniss und aktualisiert dann damit die bestehende Site
955      * @param tempDir Name des temporären Verzeichnisses
956      * @param archiveName das zu entpackende Zipfile
957      * @param skipErrors wenn true, bricht das update nicht beim ersten Fehler ab sondern versucht weiter zu machen
958      * @param simulate wenn true, wird das Update nur simuliert (es werden keine Änderungen am Dateisystem vorgenommen)
959      * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
960      */

961     private String JavaDoc extractSite(String JavaDoc tempDir, String JavaDoc archiveName, boolean skipErrors, boolean simulate)
962     {
963         try
964         {
965             logAndPrint("<b>updating site</b>");
966             String JavaDoc fs = File.separator;
967             if ( new File(archiveName).length() == 0 )
968             {
969                 logAndPrint("Nothing to extract (empty or non existent zip file).");
970             }
971             else try
972             {
973                 Archive archive = new ArchiveFactory().open(archiveName);
974                 if ( archive == null )
975                 {
976                     return archiveName + " is not a recognized collection of files. Aborting zip-extraction.";
977                 }
978                 Enumeration names = archive.getNames();
979                 if ( names != null )
980                 {
981                     StringBuffer JavaDoc tBuf = new StringBuffer JavaDoc();
982                     int fileCount = 0;
983                     final byte[] buf = new byte[ZIP_BUFSIZE];
984                     // we divide the loops to avoid a comparison on each
985
// iteration
986
while ( names.hasMoreElements() )
987                     {
988                         String JavaDoc name = (String JavaDoc)names.nextElement();
989                         fileCount++;
990                         System.out.print( tBuf.toString() );
991                         System.out.flush();
992                         //tempDir hat beim Properties-Einlesen schon ein abschließenden FS erhalten
993
File file = new File(tempDir + name);
994                         File parent = file.getParentFile();
995                         if ( parent != null )
996                         {
997                             parent.mkdirs(); //return offenbar auch false, wenn directories erfolgreich erstellt wurden
998
}
999                         CAT.debug("extractSite(): creating file " + tempDir + name);
1000                        try
1001                        {
1002                            BufferedInputStream input = new BufferedInputStream(archive.getInputStream(name));
1003                            BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(file));
1004                            int total = 0;
1005                            int inBuffer;
1006                            while( (inBuffer = input.read(buf)) > -1 )
1007                            {
1008                                output.write( buf, 0, inBuffer );
1009                                total += inBuffer;
1010                            }
1011                            input.close();
1012                            output.close(); //!!
1013
}
1014                        catch(IOException e)
1015                        {
1016                            CAT.error("extractSite(): error reading/writing file " + name + "from zip",e);
1017                        }
1018                    }
1019                    logAndPrint(fileCount + " files extracted.");
1020                }
1021            }
1022            catch (Exception JavaDoc e)
1023            {
1024                CAT.error("extractSite(): error extracting zip " + archiveName,e);
1025                return "unable to extract zip file: " + e;
1026                //geht noch zu finally, wo das tempDir gelöscht wird
1027
}
1028            deleteFile(archiveName);
1029            CAT.debug("extractSite(): zip deleted.");
1030            
1031            //egal, ob was entpackt wurde oder nicht, die neue SiteStruktur muss geupdated werden!
1032

1033            //wandle empfangenes SiteListing in neues um
1034
newListing = new SiteDocumentsListing();
1035            String JavaDoc[] dirs = sendSiteListing.getDirectories();
1036            for ( int i = 0; i < dirs.length; i++ )
1037            {
1038                String JavaDoc[] files = sendSiteListing.getDocumentNames(dirs[i]);
1039                for ( int k = 0; k < files.length; k++ )
1040                {
1041                    String JavaDoc target = sendSiteListing.getTargetDir(dirs[i], files[k]);
1042                    //CAT.debug("adding doc " + dirs[i] + "/" + files[k] + " to new listing as " + target + "/" + files[k]);
1043
newListing.addDocument(target, files[k], -1, -1, null);
1044                }
1045            }
1046            //kopiere Dateien in ihr Zielverzeichnis
1047
logAndPrint("<BR>updating documents...<BR>");
1048            if ( skipErrors )
1049            {
1050                logAndPrint("<BR>(skipping possible errors)<BR>");
1051            }
1052            if ( !updateSite(tempDir, ".",skipErrors,simulate) )
1053            {
1054                if ( !skipErrors )
1055                {
1056                    throw new Exception JavaDoc("stopped updating documents at first error");
1057                }
1058                else
1059                {
1060                    error("Errors occured while updating documents. Since the option SkipErrors was set, "
1061                    + "the SiteReceiver updated as much as possible and is trying to continue operation."
1062                    + " Note that, however, the consistency of the site cannot be garanteed, "
1063                    + "nor the correct behaviour of the following operations.");
1064                }
1065            }
1066            logAndPrint("");
1067            logAndPrint("updated " + updatedFiles + " files in " + updatedDirs + " directories.");
1068            logAndPrint("");
1069            //falls ein altes SiteListing existiert, muss die Site erst aufgeräumt werden
1070
if ( oldListing != null )
1071            {
1072                logAndPrint("deleting files and directories that no longer belong to the site...");
1073                int fileCounter, totalFiles = 0, totalDirs = 0; //zum Zählen der gelöschten Dateien
1074
String JavaDoc canonicalDir;
1075                //nicht mehr vorhandene Dokumente löschen
1076
dirs = oldListing.getDirectories();
1077                for ( int i = 0; i < dirs.length; i++ )
1078                {
1079                    fileCounter = 0;
1080                    canonicalDir = dirs[i];
1081                    try
1082                    {
1083                        canonicalDir = new File(dirs[i]).getCanonicalPath();
1084                    }
1085                    catch (Exception JavaDoc e)
1086                    {
1087                        CAT.debug("extractSite(): Couldn't form canonical path for " + dirs[i]);
1088                    }
1089                    //für die folgende Methode muss unbedingt dirs[i] übergeben werden und nicht canonicalDir,
1090
//sonst kommt es innerhalb dieser Methode zu einer NullPointerException (das Pfad-Format muss
1091
//offenbar genau übereinstimmen)
1092
String JavaDoc[] docs = oldListing.getNoMoreExistingDocuments(dirs[i], newListing);
1093                    for ( int k=0; k<docs.length; k++ )
1094                    {
1095                        if ( !simulate )
1096                        {
1097                            if ( (new File(dirs[i] + fs + docs[k])).delete() )
1098                            {
1099                                CAT.info("deleted " + canonicalDir + fs + docs[k]);
1100                                fileCounter++;
1101                            }
1102                        }
1103                        else
1104                        {
1105                            fileCounter++;//bei einer Simulation wird einfach davon ausgegangen, dass das Löschen klappte
1106
}
1107                    }
1108                    if ( fileCounter > 0 )
1109                    {
1110                        logAndPrint("deleted " + fileCounter + " document(s) in " + canonicalDir);
1111                        totalDirs++;
1112                    }
1113                    totalFiles += fileCounter;
1114                }
1115                logAndPrint("");
1116                logAndPrint("deleted " + totalFiles + " files in " + totalDirs + " directories.");
1117                logAndPrint("");
1118                totalDirs = 0;
1119                //nicht mehr vorhandene Verzeichnisse löschen
1120
dirs = oldListing.getNoMoreExistingDirectories(newListing);
1121                for ( int i=0; i<dirs.length; i++ )
1122                {
1123                    File dir = new File(dirs[i]);
1124                    try
1125                    {
1126                        dir = dir.getCanonicalFile();
1127                    }
1128                    catch (IOException e)
1129                    {
1130                        CAT.debug("extractSite(): Couldn't form canonical path for " + dir.getPath());
1131                    }
1132                    if ( dir.exists() )
1133                    {
1134                        if ( dir.list().length == 0 )
1135                        {
1136                            if ( !simulate )
1137                            {
1138                                if ( dir.delete() )
1139                                {
1140                                    totalDirs++;
1141                                    logAndPrint("deleted directory " + dir.getPath());
1142                                }
1143                            }
1144                            else
1145                            {
1146                                totalDirs++;
1147                                logAndPrint("deleted directory " + dir.getPath());
1148                            }
1149                        }
1150                        else
1151                        {
1152                            logAndPrint("could not delete directory " + dir.getPath() + " because it was not empty.");
1153                        }
1154                    }
1155                }
1156                logAndPrint("");
1157                logAndPrint("deleted " + totalDirs + " directories.");
1158                logAndPrint("");
1159            }
1160            // storing new document list
1161
try
1162            {
1163                if ( !simulate )
1164                {
1165                    newListing.saveToFile(properties.get("siteDocumentsListing"));
1166                }
1167                logAndPrint("Saved new document list");
1168            }
1169            catch (IOException e)
1170            {
1171                error("Unable to save new document list: ",e);
1172            }
1173        }
1174        catch (Exception JavaDoc e)
1175        {
1176            e.printStackTrace(new PrintWriter(logfile));
1177            return e.toString();
1178            //geht noch zu finally, wo das tempDir gelöscht wird
1179
}
1180        finally
1181        {
1182            // deleting temp
1183
logAndPrint("Deleting temporary dir " + tempDir);
1184            deleteFile(tempDir);
1185        }
1186        //hier kommt er nur an, wenn alles glatt lief; wenn vorher ein return "fehler" oder eine
1187
//exception auftaucht, geht er in den finally-Block und verlässt schon dort die Methode!
1188
//(wo der entsprechende return-Value durchgereicht wird)
1189
return null;
1190    }
1191    
1192    /**
1193     * klappert rekursiv alle Dateien/Verzeichnisse der empfangenen und entpackten Site ab
1194     * und aktualisiert entsprechend die bestehende Site
1195     * @param tempDir temporäres Verzeichnis, in dem die empfangene Site erstmal entpackt wurde
1196     * @param subdir abzuarbeitendes Unterverzeichnis in diesem temporären Verzeichnis
1197     * @param skipErrors wenn true, bricht das update nicht beim ersten Fehler ab sondern versucht weiter zu machen
1198     * @param simulate wenn true, wird das Update nur simuliert (es werden keine Änderungen am Dateisystem vorgenommen)
1199     * @throws Exception wenn was schwerwiegendes schiefgeht
1200     * @return true wenn alles glatt ging
1201     */

1202    boolean updateSite(String JavaDoc tempDir, String JavaDoc subdir, boolean skipErrors, boolean simulate) throws Exception JavaDoc
1203    {
1204        boolean success = true;
1205        int fileCounter = 0;
1206        String JavaDoc target = null;
1207        String JavaDoc FS = File.separator;
1208        String JavaDoc[] list = (new File(tempDir + FS + subdir)).list();
1209        try
1210        {
1211            for ( int i = 0; i < list.length; i++ )
1212            {
1213                String JavaDoc filename = list[i];
1214                File file = new File(tempDir + FS + subdir + FS + filename);
1215                try
1216                {
1217                    file = file.getCanonicalFile();
1218                }
1219                catch (IOException e)
1220                {
1221                    CAT.debug("updateSite(): Couldn't form canonical path for " + file.getPath());
1222                }
1223                CAT.debug("file " + file.getPath());
1224                // subdirs abarbeiten
1225
if ( file.isDirectory() )
1226                {
1227                    success = updateSite(tempDir, subdir + FS + filename, skipErrors, simulate);
1228                    if ( !success && !skipErrors )
1229                    {
1230                        return false;
1231                    }
1232                }
1233                else
1234                {
1235                    target = sendSiteListing.getTargetDir(subdir, filename);
1236                    if ( target == null )
1237                    {
1238                        error("found " + subdir + FS + filename + " in " + tempDir + ", but not in sent siteDocumentsListing!");
1239                        if ( skipErrors )
1240                        {
1241                            success = false;
1242                            continue; //auf zur nächsten Datei
1243
}
1244                        else
1245                        {
1246                            return false;
1247                        }
1248      
1249                    }
1250                    //Zielverzeichnis erstellen, falls es noch nicht existiert
1251
File targetDir = new File(target);
1252                    try
1253                    {
1254                        targetDir = targetDir.getCanonicalFile();
1255                    }
1256                    catch (IOException e)
1257                    {
1258                        CAT.debug("updateSite(): Couldn't form canonical path for " + targetDir.getPath());
1259                    }
1260                    target = targetDir.getPath(); //sollte funktionieren
1261
CAT.debug(" ...target dir is " + target);
1262                    if ( targetDir.exists() )
1263                    {
1264                        if ( !targetDir.isDirectory() )
1265                        {
1266                            error("failed to create directory " + markAsFile(target) + ": a file with that name exists");
1267                            error("failed to create document " + target + FS + filename);
1268                            if ( skipErrors )
1269                            {
1270                                error("Skipping further attempts to write to this \"directory\".");
1271                                return false; //wieder nach oben
1272
}
1273                            else
1274                            {
1275                                return false;
1276                            }
1277                        }
1278                    }
1279                    else
1280                    {
1281                        try
1282                        {
1283                            if ( !targetDir.mkdirs() ) //Muss das auch simuliert werden??
1284
{
1285                                error("failed to create directory " + markAsFile(target));
1286                                //suche mögliche Gründe
1287
String JavaDoc dir = new String JavaDoc(target);
1288                                boolean foundParentDir = false;
1289                                int index = dir.length();
1290                                while ( (index = dir.lastIndexOf(FS, index - 1)) >= 0 && !foundParentDir )
1291                                {
1292                                    dir = dir.substring(0, index + 1);
1293                                    File fDir = new File(dir);
1294                                    if ( fDir.exists() )
1295                                    {
1296                                        foundParentDir = true;
1297                                        error("nearest existing parent directory is: " + markAsFile(dir));
1298                                        if ( fDir.canRead() )
1299                                        {
1300                                            CAT.info("directory is readable");
1301                                        }
1302                                        else
1303                                        {
1304                                            error("directory is not readable");
1305                                        }
1306                                        if ( fDir.canWrite() )
1307                                        {
1308                                            CAT.info("directory is writeable");
1309                                        }
1310                                        else
1311                                        {
1312                                            error(markAsFile(dir) + " is not a writable directory. "
1313                                                    + "Skipping further attempts to write to " + markAsFile(target) + ".");
1314                                            return false; //wieder nach oben
1315
}
1316                                        //Verzeichnis ist möglicherweise nicht accessible (chmod a-x):
1317
//das krieg ich raus durch das Anlegen einer leeren temporären Datei
1318
try
1319                                        {
1320                                            File temp = File.createTempFile("SRU",".tmp",fDir);
1321                                            temp.delete();
1322                                        }
1323                                        catch (Exception JavaDoc dummy)
1324                                        {
1325                                            error(markAsFile(dir) + " is no accessible directory. "
1326                                                + "Skipping further attempts to write to " + markAsFile(target) + ".");
1327                                            return false; //wieder nach oben
1328
}
1329                                    }
1330                                }
1331                                if ( !foundParentDir )
1332                                {
1333                                    CAT.warn("found no parent directory");
1334                                }
1335                                error("failed to create document " + markAsFile(target + FS + filename));
1336                                if ( skipErrors )
1337                                {
1338                                    success = false;
1339                                    continue; //auf zur nächsten Datei
1340
}
1341                                else
1342                                {
1343                                    return false;
1344                                }
1345                            }
1346                        }
1347                        catch (Exception JavaDoc e)
1348                        {
1349                            error("failed to create directory " + markAsFile(target),e);
1350                            error("failed to create document " + markAsFile(target + FS + filename));
1351                            if ( skipErrors )
1352                            {
1353                                if ( e.toString().toLowerCase().indexOf("no space") > -1 ||
1354                                     ( e.toString().toLowerCase().indexOf("kein ") > -1
1355                                       && e.toString().toLowerCase().indexOf("platz ") > -1 )
1356                                   )
1357                                {//in einem solchen Fall geht garnix mehr
1358
throw e;
1359                                }
1360                                else
1361                                {
1362                                    success = false;
1363                                    continue; //auf zur nächsten Datei
1364
}
1365                            }
1366                            else
1367                            {
1368                                return false;
1369                            }
1370                        }
1371                    }
1372                    // now copy file
1373
String JavaDoc source = tempDir + FS + subdir + FS + filename;
1374                    try
1375                    {
1376                        source = new File(source).getCanonicalPath();
1377                    }
1378                    catch (IOException e)
1379                    {
1380                        CAT.debug("updateSite(): Couldn't form canonical path for " + source);
1381                    }
1382                    String JavaDoc dest = target + FS + filename;
1383                    try
1384                    {
1385                        dest = new File(dest).getCanonicalPath();
1386                    }
1387                    catch (IOException e)
1388                    {
1389                        CAT.debug("updateSite(): Couldn't form canonical path for " + dest);
1390                    }
1391                    File fSource = new File(source);
1392                    if ( !fSource.exists() )
1393                    {
1394                        error("failed to create document " + markAsFile(dest) + ": source file " + markAsFile(source) + " does not exist.");
1395                        if ( skipErrors )
1396                        {
1397                            success = false;
1398                            continue; //auf zur nächsten Datei
1399
}
1400                        else
1401                        {
1402                            return false;
1403                        }
1404                    }
1405                    try
1406                    {
1407                        //vorher war hier fSource.renameTo(new File(dest)), aber das klappte zumindest auf
1408
//pallas nicht (Permission denied - Exception), Ursache unklar. Deswegen dieser work-around
1409
if ( !simulate )
1410                        {
1411                            SitePacker.copyFile(fSource,new File(dest));
1412                        }
1413                        if ( simulate || fSource.delete() )
1414                        {
1415                            CAT.info("moved document from " + source + " to " + target);
1416                        }
1417                        else
1418                        {
1419                            CAT.info("copied but could not delete document " + source);
1420                        }
1421                        fileCounter++;
1422                    }
1423                    catch (Exception JavaDoc e)
1424                    {
1425                        error("failed to copy document from " + source + " to " + markAsFile(dest),e);
1426                        if ( skipErrors )
1427                        {
1428                            if ( e.toString().indexOf("denied") > -1 || e.toString().indexOf("verweigert") > -1)
1429                            {
1430                                //falls die Fehlerursache mangelnde Schreibrechte im umgebenden Verzeichnis waren,
1431
//sollten weitere Versuche, in dieses Verzeichnis zu schreiben, unterbleiben
1432
File dir = new File(dest).getParentFile();
1433                                if ( !dir.exists() || !dir.isDirectory() || !dir.canWrite() )
1434                                {
1435                                    error(markAsFile(dir.getName()) + " is not a writable directory. "
1436                                            + "Skipping further attempts to write to this directory.");
1437                                    return false; //wieder nach oben
1438
}
1439                                else
1440                                { //Verzeichnis ist möglicherweise nicht accessible (chmod a-x):
1441
//das krieg ich raus durch das Anlegen einer leeren temporären Datei
1442
try
1443                                    {
1444                                        File temp = File.createTempFile("SRU",".tmp",dir);
1445                                        temp.delete();
1446                                    }
1447                                    catch (Exception JavaDoc dummy)
1448                                    {
1449                                        error(markAsFile(dir.getName()) + " is no accessible directory. "
1450                                            + "Skipping further attempts to write to this directory.");
1451                                        return false; //wieder nach oben
1452
}
1453                                }
1454                            }
1455                            else if ( e.toString().toLowerCase().indexOf("no space") > -1 ||
1456                                      ( e.toString().toLowerCase().indexOf("kein ") > -1
1457                                        && e.toString().toLowerCase().indexOf("platz ") > -1 )
1458                                    )
1459                            {//in einem solchen Fall geht garnix mehr
1460
throw e;
1461                            }
1462                            success = false;
1463                            continue; //auf zur nächsten Datei
1464
}
1465                        else
1466                        {
1467                            return false;
1468                        }
1469                    }
1470                }
1471            }
1472        }
1473        catch (Exception JavaDoc e)
1474        {
1475            //fuckJTest = "Dummy";
1476
e.printStackTrace(new PrintWriter(logfile));
1477        }
1478        finally
1479        {
1480            if ( target != null )
1481            {
1482                logAndPrint("moved " + fileCounter + " file(s) to " + target);
1483                updatedFiles += fileCounter;
1484                updatedDirs++;
1485            }
1486        }
1487        return success;
1488    }
1489
1490    /**
1491     * Überträgt das Logfile an den SiteTransmitter.
1492     * Trat im bisherigen Programmablauf ein Fehler auf, wird statt dessen ein "abort" gesendet
1493     * @param success zeigt an, ob der bisherige Programmablauf fehlerfrei war.
1494     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1495     */

1496    private String JavaDoc transmitLog(boolean success)
1497    {
1498        PrintWriter out = null;
1499        int lineCount = 0;
1500        try
1501        {
1502            out = new PrintWriter(clientSocket.getOutputStream());
1503            int size = vLog.size();
1504            for ( int i = 0; i < size; i++ )
1505            {
1506                out.println((String JavaDoc)vLog.get(i));
1507                lineCount++;
1508            }
1509            if ( !success )
1510            {
1511                out.println("abort");
1512            }
1513            out.println("end");
1514            out.flush();
1515        }
1516        catch (Exception JavaDoc e)
1517        {
1518            return e.toString();
1519        }
1520        finally
1521        {
1522            CAT.debug("transmitted " + lineCount + " log lines.");
1523        }
1524        return null;
1525    }
1526    
1527    
1528    //=================== end main =======================
1529

1530    /**
1531     * prüft, ob die Verbindung von einer erlaubten IP-Adresse kommt
1532     * @param ip die zu überprüfende IP-Adresse
1533     * @param allowedIP die erlaubte(n) IP-Adresse(n) (optional mit * als Wildcard)
1534     * @return true, wenn die IP-Adresse erlaub ist
1535     */

1536    private boolean transferAllowedFrom(String JavaDoc ip, String JavaDoc allowedIP)
1537    {
1538        CAT.debug("transferAllowedFrom(): ip=" + ip + " allowedIP=" + allowedIP);
1539        if ( allowedIP.indexOf("*") > -1 ) //wildcards beachten
1540
{//geh davon aus, dass die wildcards "rechtsbündig" sind
1541
int pos = allowedIP.indexOf("*") - 1;
1542            if ( pos == -1 || ip.substring(0,pos).equals(allowedIP.substring(0,pos)) )
1543            {
1544                return true;
1545            }
1546            return false;
1547        }
1548        return (ip.indexOf(allowedIP) > -1 );
1549    }
1550
1551    /**
1552     * gibt die Aufrufsyntax aus
1553     */

1554    private void printUsage()
1555    {
1556        outStream.println("usage: java SiteReceiver &lt;remoteIP&gt; &lt;propertyFileName&gt; [&lt;url-encoded properties&gt;]");
1557    }
1558
1559    /**
1560     * löscht Dateien bzw. Verzeichnisse (mit Unterverzeichnissen) vollständig
1561     * @param name Datei- bzw. Verzeichnisname
1562     * @return Anzahl gelöschter Dateien/Verzeichnisse
1563     */

1564    private int deleteFile(String JavaDoc name)
1565    {
1566        File f = new File(name);
1567        int fileCount = 0;
1568        if ( f.exists() )
1569        {
1570        // clear directory first
1571
if ( f.isDirectory() )
1572            {
1573                String JavaDoc[] list = f.list();
1574                for ( int i = 0; i < list.length; i++ )
1575                {
1576                    fileCount += deleteFile(name + File.separator + list[i]);
1577                }
1578            }
1579            // delete file
1580
if ( f.delete() )
1581            {
1582                fileCount++;
1583            }
1584        }
1585        return fileCount;
1586    }
1587    
1588    /**
1589     * Ausgeben einer Log-4J-Debugmeldung
1590     * @param p Meldungspriorität
1591     * @param s Meldungstext
1592     */

1593    static void CAT(Priority p, String JavaDoc s)
1594    {
1595        CAT.log(p,s);
1596    }
1597    
1598    /**
1599     * gibt eine Message aus und loggt sie
1600     * @param message auszugebende Logmessage
1601     */

1602    protected void logAndPrint(String JavaDoc message)
1603    {
1604        if ( vLogStarted )
1605        {
1606            logAndKeep(message);
1607        }
1608        else
1609        {
1610            print(message);
1611            log(message);
1612        }
1613    }
1614
1615    /**
1616     * gibt eine Message aus, wobei Zeilenumbrüche in "<BR>"s gewandelt werden
1617     * @param s auszugebende Message
1618     */

1619    private void print(String JavaDoc s)
1620    {
1621        int i = s.indexOf(NEWLINE);
1622        while ( i > -1 )
1623        {
1624            outStream.println(s.substring(0,i) + "<BR>");
1625            s = s.substring(i+1,s.length());
1626            i = s.indexOf(NEWLINE);
1627        }
1628        if ( s.length() > 0 )
1629        {
1630            outStream.println(s);
1631        }
1632        outStream.flush();
1633    }
1634    
1635    /**
1636     * speichert eine Message im Log
1637     * @param message zu speichernde und zu loggende Message
1638     */

1639    private void logAndKeep(String JavaDoc message)
1640    {
1641        vLog.add(message);
1642        log(message);
1643    }
1644
1645    /**
1646     * gibt eine Property aus einem Propertyset zurück
1647     * @param source das zu durchsuchende PropertySet
1648     * @param key Name der gesuchten Property
1649     * @return Wert der gesuchten Property
1650     * @throws PropertyNotFoundException wenn die gesuchte Property nicht gefunden wurde
1651     */

1652    private String JavaDoc getProperty(PropertySet source, String JavaDoc key) throws PropertyNotFoundException
1653    {
1654        String JavaDoc result = source.get(key);
1655
1656        if ( result == null || result.equals("") ) //wenn wert gar nicht vorhanden
1657
{
1658            throw new PropertyNotFoundException(key);
1659        }
1660        return result;
1661    }
1662    
1663    /**
1664     * führt den Afterburner aus
1665     * @param afterBurner Name der zu startenden Javaklasse
1666     * @param strArgs Parameter für die zu startende Javaklasse
1667     * @param noJava wenn true, wird das Programm nicht als JavaKlasse gestartet
1668     * @return true, wenn kein Fehler beim Starten des Afterburners auftrat, sonst false
1669     */

1670    private boolean doAfterBurner(String JavaDoc afterBurner, String JavaDoc[] strArgs, boolean noJava)
1671    {
1672        try
1673        {
1674            String JavaDoc[] newArgs;
1675            int offset;
1676            //erst das Kommando konstruieren
1677
if ( noJava )
1678            {
1679                offset = 1;
1680                newArgs = new String JavaDoc[strArgs.length + offset];
1681                newArgs[0] = afterBurner;
1682            }
1683            else
1684            { //ParameterArray ist besser als alles in einen CommandoString zu schreiben, da nur so die
1685
//originale Parameterzuordnung erhalten bleibt (sonst wird ein Parameter, der ein
1686
//Leerzeichen enthält, zu zwei Parametern aufgesplittet!)
1687
offset = 4;
1688                newArgs = new String JavaDoc[strArgs.length + 4];
1689                newArgs[0] = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
1690                newArgs[1] = "-classpath";
1691                newArgs[2] = System.getProperty("java.class.path");
1692                newArgs[3] = afterBurner;
1693            }
1694            //Jetzt die restlichen Parameter ranhängen
1695
for ( int x=0; x<strArgs.length; x++ )
1696            {
1697                newArgs[x+offset] = strArgs[x];
1698            }
1699            //Jetzt geht's los
1700
Process JavaDoc proc = Runtime.getRuntime().exec(newArgs);
1701            BufferedReader inReader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
1702            BufferedReader errReader = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
1703            String JavaDoc line;
1704            while ((line = inReader.readLine()) != null)
1705            {
1706                logAndPrint(line);
1707            }
1708            //falls was in den errStream geschrieben wurde, muss ich das auch noch auslesen
1709
String JavaDoc errors = "";
1710            while ((line = errReader.readLine()) != null)
1711            {
1712                errors += line;
1713            }
1714            if ( !errors.equals("") )
1715            {
1716                throw new Exception JavaDoc(errors);
1717            }
1718            return true;
1719        }
1720        catch (Throwable JavaDoc t)
1721        {
1722            error("Error during afterburning: ",t);
1723            return false;
1724        }
1725    }
1726 }
1727
1728
1729/**
1730 * Thread, der die Verbindung vom Client entgegennimmt
1731 * (-> wenn ein TimeOut statt findet, kann der Thread gestoppt werden)
1732 * wenn ein Fehler beim Verbindungsaufbau auftritt, wird der ganze SiteReceiver beendet *
1733 * @author $Author: torsten $
1734 * @version $Revision: 1.44.2.3 $
1735 */

1736class ClientConnector extends Thread JavaDoc
1737{
1738    /**ServerSocket, das die Verbindung entgegennehmen soll*/
1739    private SSLServerSocket server;
1740    /**SiteReceiver, dem das clientSocket nach zustande gekommener Verbindung übergeben wird*/
1741    private SiteReceiver siteReceiver;
1742
1743    /**
1744     * konstruiert ClientConnector
1745     * @param receiver SiteReceiver, dem das clientSocket nach zustande gekommener Verbindung übergeben wird
1746     * @param socket ServerSocket, das die Verbindung entgegennehmen soll
1747     */

1748    ClientConnector(SiteReceiver receiver, SSLServerSocket socket)
1749    {
1750        server = socket;
1751        siteReceiver = receiver;
1752    }
1753
1754    /**
1755     * startet den Thread
1756     */

1757    public void run()
1758    {
1759        try
1760        {
1761            siteReceiver.clientSocket = (SSLSocket)server.accept();
1762            SiteReceiver.CAT(Priority.DEBUG,"ClientConnector: connection accepted");
1763        }
1764        catch (Exception JavaDoc e)
1765        {
1766            siteReceiver.error("Connection from client failed: ",e);
1767            siteReceiver.closeLog();
1768            System.exit(1);
1769        }
1770    }
1771}
Popular Tags