KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > webman > stager > SiteTransmitter


1 package webman.stager;
2
3 import org.apache.log4j.*;
4 import java.net.*;
5 import java.security.*;
6 import java.io.*;
7 import java.util.*;
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 javax.security.cert.X509Certificate;
11 import java.security.KeyStore JavaDoc;
12
13 /**
14  * Diese Klasse ist der sendende Teil des Stagers. Er muss über ein PropertyFile oder webman-Properties konfiguriert werden
15  * Der SiteTransmitter bestimmt die zu übertragenden Dateien, packt sie in ein Zip und übermittelt sie an den SiteReceiver
16  * Danach sendet er seine Liste der übertragenen Dateien und empfängt das Log des SiteReceivers
17  * Dieses wird zusammen mit den eigenen Ausgaben im Browser angezeigt
18  * Traten beim Stagen Fehler auf, so beendet sich der SiteTransmitter mit System.exit(-1), ansonsten System.exit(0)
19  * @see SiteReceiver
20  * @see ServerStarter
21  * @author $Author $
22  * @version $Revision: 1.56.2.2 $
23  */

24 public class SiteTransmitter extends Stager
25 {
26     /**Programm-Version gemäß CVS-Revision*/
27     public final String JavaDoc INTERNAL_VERSION = "1.59";
28     /**Log4J-Kategorie*/
29     private final static Category CAT = Category.getInstance(SiteTransmitter.class);
30     
31     /**Name der Webman-PropertyGruppe mit den Sitetransmitter-Properties*/
32     public final static String JavaDoc DEFAULT_BASE_PROPERTY_RESOURCE = "sitetransmitter";
33     /**Name des Standard-KeyStores für die SSL-Verschlüsselung*/
34     public final static String JavaDoc DEFAULT_KEYSTORE_FILE = "testkeys.sitetransmitter";
35     /**Standardpasswort für den KeyStore*/
36     public final static String JavaDoc DEFAULT_KEYSTORE_PASSWORD = "passphrase";
37     /**Standard-Port*/
38     public final static String JavaDoc DEFAULT_TARGET_PORT = "4242";
39     /**Standard-TimeOut für den Verbindungsaufbau zum SiteReceiver*/
40     public final static String JavaDoc DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS = "60";
41     /**Zeichenkette, die das Ende eines LogFiles kennzeichnet*/
42     public final static String JavaDoc LOG_END_TAG = "### THE END ###";
43     /**Maximales TimeOut für Verbindungsaufbau zum SiteReceiver*/
44     private final static int MAX_OPEN_TIMEOUT_SECONDS = 300;
45     /**Wie alt (in ms) kann ein Log maximal sein, damit es noch als aktuelles Log gilt*/
46     private final static int SHOW_LOG_TIMEOUT = 300000;
47     /**Pause zwischen 2 Versuchen, ein Socket zum SiteReceiver zu öffnen*/
48     private final static int OPEN_SOCKET_WAIT = 2000;
49     /**Wie lange (in ms) wird versucht ein Log anzuzeigen, dass noch nicht beendet ist*/
50     private final static int MAX_SHOW_TIME = 60000;
51     /**Pause (in ms) zwischen 2 Versuchen, das aktuelle Log einzulesen und anzuzeigen*/
52     private final static int SLEEP_TIME = 100;
53     /**Anzahl von Millisekunden je Sekunde*/
54     private final static int MILLIS_PER_SECOND = 1000;
55     /**Schreib-Puffergröße für das Socket bei der Übertragung der Site*/
56     private final static int BUFSIZE = 2048;
57     /**kleinst möglicher Port*/
58     private static final int MIN_PORT = 1024;
59     /**größt möglicher Port*/
60     private static final int MAX_PORT = 65535;
61     /**Anfangskapazität des Lesepuffers für das Anzeigen eines Logs*/
62     private static final int INITIAL_TEMP_LOG_BUFFER_CAPACITY = 100;
63     //private static final int PROGRESS_INDICATOR_DELAY = 2000;
64

65     /** Liste der PropertySets der anzustagenden Zielhosts */
66     private Vector propertySetList;
67     /**PropertySet, das gerade durchlaufen wird*/
68     private int currentPropertySet;
69     /**gibt an, ob das aktuell zu parsende PropertySet final ist (also vollständig sein muss)*/
70     private boolean isCurrentParsedPropertySetFinal;
71     /**die BaseProperties*/
72     private PropertySet baseProperties = null;
73     /**Verzeichnis, in dem sich die baseProperties befinden*/
74     private String JavaDoc confroot = null;
75     
76     /**Referenz auf den ServerStarter
77      @see ServerStarter*/

78     private ServerStarter starter = null;
79     /**Verwendetes SSLSocket*/
80     private SSLSocket clientSocket = null;
81     /**SocketFactory zum Ersttellen des SSLSocket*/
82     private SSLSocketFactory socketFactory = null;
83     /**die für die Übertragung gezippte Site*/
84     private File zippedSite = null;
85     /**stellt die Site zusammen und zippt sie
86     @see SitePacker*/

87     private SitePacker sitePacker;
88     /**merkt sich Fehler für ein Staging-Durchlauf*/
89     private boolean success;
90     /**fehler merkt sich Fehler während der gesamten (Multi-)Staging-Dauer*/
91     private boolean fehler;
92
93     /**die Ausgaben des SiteTransmitter gehen über dieses Socket an den aufrufenden Thread*/
94     private Socket outSocket = null;
95     /**wenn nur das Log gezeigt werden soll, müssen Properties nicht vollständig geparst werden*/
96     private boolean showLogOnly;
97     /**wenn ich auf mehrere Rechner stage ist es möglich, nur einmal zu packen und mehrfach zu transmitten*/
98     private boolean reuseZipfile = false;
99     /**true, wenn ich Properties über WebmanProperties einlese; false bei Benutzung von PropertyFiles*/
100     private boolean useDB = false;
101     /**Dummystring für JTest-kompatible Dummyanweisungen*/
102     private String JavaDoc fuckJTest = "Dummystring für JTest-kompatible Dummyanweisungen";
103     
104     /**
105      * Konstruiert neuen SiteTransmitter mit übergebenen Aurgumenten
106      * @param args ein Array mit folgenden Parametern: [[configuration=]<propertyFile>] [showlog=true] [port=<port>]
107      */

108     public static void main(String JavaDoc[] args)
109     {
110         (new SiteTransmitter()).startMain(args);
111     }
112     
113     /**
114      * Startet SiteTransmitter mit übergebenen Argumenten
115      * @param args ein Array mit folgenden Paramtern: [[configuration=]<propertyFile>] [showlog=true] [port=<port>]
116      */

117     private void startMain(String JavaDoc[] args)
118     {
119         try
120         {
121             CAT.debug("Am Anfang war der Beginn! (Wir starten um: " + new Date() + ")");
122             fehler = false;
123
124             // --------------------------------------------------------------------
125
// arguments and props
126
//
127
boolean useConfig = true, transferChangedOnly = false;
128             int openSocketTimeout, outPort = -1; // port the output goes to
129

130             outStream = System.out; //von mir zum Testen OHNE Sockets-Umgebung hinzugefügt
131
if ( args.length > 3 )
132             {
133                 printUsage();
134             }
135
136             /* Der ganze Aufwand des Propertylesens rührt von dem Bedürfnis her, auf mehrere Zielhosts zu stagen
137              * Dazu werden mehrere PropertySets verwandt, die aus den jeweiligen Propertyresourcen
138              * hergeleitet werden. Es gibt dabei ein BasePropertySet (das erste, das eingelesen wird), in dem
139              * alle übrigen referenziert sind (wenn es überhaupt noch weitere gibt)
140              * Zugleich dient dieses BasePropertySet als "Backup" für die anderen PropertySets in der Art, dass
141              * Properties, die in den einzelnen PropertySets nicht definiert wurden, auf den Wert gesetzt werden
142              * den sie im BasePropertySet haben. Ansonsten überschreiben sie die Werte des BasePropertySets.
143              * Für jede Ziel muss ein gültiges PropertySet vorhanden sein (jenes Ziel, für das kein gültiges
144              * PropertySet vorliegt, wird mit einer Fehlermeldung übersprungen), d.h. alle required Properties
145              * müssen definiert sein (entweder durch das jeweilige PropertySet oder in das BasePropertySet)
146              * und gesetzte Properties müssen wohlgeformt sein (also korrekte Werte ausweisen).
147              *
148              * Wurden in den BaseProperties keine weiteren TargetProperties referenziert, so werden
149              * die BaseProperties selbst als TargetProperties benutzt
150              */

151              
152             //Kommandozeilenparameter einlesen
153
try
154             {
155                 PropertySet arguments = new PropertySet(parseArguments(args));
156                 try
157                 {
158                     outPort = Integer.parseInt(arguments.get("port"));
159                 }
160                 catch (Exception JavaDoc e)
161                 {
162                     outPort = -1;
163                 }
164                 //allen Output auf den Port umleiten
165
if ( outPort > -1 )
166                 {
167                     try
168                     {
169                         outSocket = new Socket(InetAddress.getLocalHost(), outPort);
170                         outStream = new PrintStream(outSocket.getOutputStream(), true);
171                         System.setErr(outStream);
172                         System.setOut(outStream);
173                     }
174                     catch (Throwable JavaDoc t)
175                     {
176                         error("Wrong configuration of port",t);
177                         error("writing to stdout...");
178                     }
179                 }
180                                 
181                 // show log if requested
182
showLogOnly = "true".equals(arguments.get("showlog"));
183                 //wenn nur Log(s) gezeigt werden, müssen die alle auf eine HTML-Seite. Also nur EIN Header und EIN Footer (s.u.)!!
184
if ( showLogOnly )
185                 {
186                     printHeader("webman - Log(s) of last Transmission(s)");
187                 }//Der Rest kommt dann weiter unten in der while-Schleife....
188
else
189                 {//das gleiche gilt für die Ausgaben der verschiedenen Stagerdurchläufe
190
printHeader("webman - Transmission of Site(s)");
191                 }
192                 
193                 String JavaDoc baseResourceDescriptor = arguments.get("configuration");
194                 if ( baseResourceDescriptor == null ) //wenn kein PropertyFile angegeben wurde
195
{
196                     baseResourceDescriptor = arguments.get("propertyfile"); //rückwärtskompatibilität!
197
if ( baseResourceDescriptor == null )
198                     {
199                         //Datenbankzugriff
200
baseResourceDescriptor = DEFAULT_BASE_PROPERTY_RESOURCE;
201                         try
202                         { //nutze für DB die voll qualifizierten Klassennamen und nicht import-Anweisung oben, damit
203
//dies auch mit der datenbanklosen Variante für webman1.2 funktioniert (da es dort keine PropertyGruppen
204
//im eigentlichen Sinne gibt, kann ich die DB nicht benutzen. Außerdem gab es da noch ne andere Paketstruktur)
205
//(damit die nicht beim Starten des transmitters fehlende import-Klassen beanstandet)
206
com.teamkonzept.webman.db.TKWebmanDBManager.initConnection("/webmandb.ini", false);
207                             useDB = true;
208                             logAndPrint("<FONT color=white>Using WebMan-PropertyGroup " + baseResourceDescriptor + " as base property-resource.</FONT>");
209                         }
210                         catch (Throwable JavaDoc t)
211                         {
212                             error("Could not retrieve WebMan Properties due to error while accessing database: " + t.toString());
213                             error("Stopping SiteTransmitter.");
214                             System.exit(-1);
215                         }
216                     }
217                 }
218                 else
219                 {
220                     logAndPrint("<FONT color=white>Using file " + baseResourceDescriptor + " as base property-resource.</FONT>");
221                 }
222    
223                 propertySetList = new Vector();
224                 try
225                 {
226                     CAT.debug("PARSING baseProperties...");
227                     baseProperties = readProperties(baseResourceDescriptor);
228                 }
229                 catch (WrongConfigurationException w)
230                 {
231                     error("Wrong property configuration in base property-resource (" + baseResourceDescriptor + "): " + w.getMessage());
232                     error("SiteTransmitter stopped.");
233                     System.exit(-1);
234                 }
235       
236                 //Jetzt alle (eventuellen) weiteren Properties abklappern
237
Vector propertyResourceDescriptors = baseProperties.getPropertyGroup("TargetProperties");
238                 if ( propertyResourceDescriptors.size() > 0) //wenn mehrere PropertySet definiert wurden, dann werden die baseProperties selbst nicht abgearbeitet
239
{
240                     CAT.debug("PARSING TargetProperties...");
241                     String JavaDoc resourceDescriptor;
242                     for ( int i = 0; i < propertyResourceDescriptors.size(); i++ )
243                     {
244                         resourceDescriptor = (String JavaDoc)(propertyResourceDescriptors.elementAt(i));
245                         try
246                         {
247                             propertySetList.add(readProperties(resourceDescriptor));
248                         }
249                         catch (WrongConfigurationException w)
250                         {
251                             error("Wrong property configuration in property-resource " + resourceDescriptor,w);
252                             if ( i < propertyResourceDescriptors.size() - 1 ) //wenn noch weitere PropertyResourcen da sind
253
{
254                                 logAndPrint("omitting the respective target");
255                             }
256                         }
257                     }
258                     if ( propertySetList.size() == 0 ) //falls keine der speziellen PropertySets gültig ist
259
{
260                         error("No valid extended property-resource found. Using base property-resource (" + baseResourceDescriptor + ")");
261                         try //versuche BaseProperties als eigenständiges PropertySet zu verwenden
262
{
263                             //führe nochmal den Check durch (jetzt müssen die baseProperties ja vollständig und korrekt sein)
264
//und füge sie als einziges PropertySet in die Liste ein
265
propertySetList.add(parseProperties(baseProperties));
266                             ((PropertySet)propertySetList.lastElement()).set("ResourceDescriptor",baseResourceDescriptor);
267                         }
268                         catch (WrongConfigurationException w)
269                         {
270                             error("Wrong property configuration in base property-resource (" + baseResourceDescriptor + ")",w);
271                             print("SiteTransmitter stopped.");
272                             System.exit(-1);
273                         }
274                     }
275                 }
276                 else //wenn nur ein Propertyfile angegeben wurde (also die BaseProperties), so muss das abgearbeitet werden
277
{
278                     propertySetList.add(baseProperties);
279                     propertyResourceDescriptors.add(baseResourceDescriptor);
280                 }
281             }
282             catch (Exception JavaDoc e) //dürfte eigentlich nich passieren, aber man kann ja nie wissen...
283
{
284                 error("Unknown error while reading configuration",e);
285                 error("SiteTransmitter stopped.");
286                 System.exit(-1);
287             }
288             finally //uffräumen
289
{
290                 if ( useDB )
291                 {
292                     com.teamkonzept.webman.db.TKWebmanDBManager.deregister(false);
293                 }
294             }
295
296             // **************** *********************
297
// **************** J E T Z T G E H T ' S L O S *********************
298
// **************** *********************
299

300             currentPropertySet = 0;
301             while ( currentPropertySet < propertySetList.size() ) //solange noch targets abzuarbeiten sind
302
{
303                 success = true; //am Anfang ist noch Hoffnung: Alles wird gut
304
PropertySet props = (PropertySet)propertySetList.elementAt(currentPropertySet); //nehme mir nächsten Host vor; alle weiteren rücken nach
305

306                 CAT.info( "NEW STAGING PROCESS BEGINS FOR " + props.get("ResourceDescriptor"));
307                 // Logging beginnt hier (die obigen logAndPrint-Anweisungen printen nur, falls das log noch nicht existiert)
308
logAndPrint("<BR>============================================================================");
309                 
310                 if ( showLogOnly )
311                 {
312                     showLog(props.get("logFile"));
313                     //und zum nächsten log
314
currentPropertySet++;
315                     continue;
316                 }
317                 
318                 // ---------------------------------------------------------------------------
319
// start only if log is finished (if there is an END_TAG)
320
if ( !logFinished(props.get("logFile")) )
321                 {//hier werden erstmal im Zweifesfall auch alle aktiven Prozesse gezeigt, auch wenn
322
//jeder einzelne vielleicht ziemlich lange braucht. So ist das Verhalten aber wenigstens einheitlich
323
print("<B>There is an active process, showing log</B>");
324                     print("<FONT size=-1>(waiting not more than " + MAX_SHOW_TIME/MILLIS_PER_SECOND + " seconds for log continuation...)</FONT><BR>");
325                     showLog(props.get("logFile"));
326                     currentPropertySet++; //danach zum nächsten Log (sonst käme man ja in eine Endlosschleife)
327
continue;
328                 }
329                 
330                 switch (props.get("filesToTransmit").charAt(0))
331                 {
332                     case 'c': useConfig = true;
333                                 transferChangedOnly = true;
334                                 break;
335                     case 'a': useConfig = true;
336                                 transferChangedOnly = false;
337                                 break;
338                     case 'd': useConfig = false;
339                                 transferChangedOnly = false;
340                                 break;
341                     default: fuckJTest = "wurde vorher abgefangen verdammte scheiße noch mal!";
342                 }
343                 openSocketTimeout = MILLIS_PER_SECOND * Integer.parseInt(props.get("OpenSocketTimeoutSeconds"));
344             
345                 // starting output here
346
logfile = openLog(props.get("logFile"),props.get("appendLog").equals("true"));
347
348                 logAndPrint("<H2>Staging to target " + (currentPropertySet + 1) + " of " + propertySetList.size()
349                             + " (as defined in " + props.get("ResourceDescriptor") + ")</H2>");
350                 logAndPrint("<!------------------------------------------------------------------------------------------------------------------------------------->");
351                 logAndPrint("<B>WebMan SiteTransmitter started at " + new java.util.Date JavaDoc() + "</B>");
352                 logAndPrint("DocumentRoot: " + markAsFile(props.get("documentRoot")));
353                 logAndPrint("TargetCGI: " + props.get("targetCGI"));
354                 String JavaDoc targetCGIServer = ServerStarter.serverPart(props.get("targetCGI"));
355                 logAndPrint("<FONT color=white>Staging to " + targetCGIServer + "</FONT>");
356                 try
357                 {
358                     if ( !props.get("targetHost").equals(targetCGIServer) )
359                     {
360                         logAndPrint("<FONT color=white>But connecting to: " + InetAddress.getByName(props.get("targetHost")) + "</FONT>");
361                     }
362                     else
363                     {
364                         logAndPrint("Connecting to: " + InetAddress.getByName(props.get("targetHost")));
365                     }
366                 }
367                 catch (Exception JavaDoc e)
368                 {
369                     error("Lookup failed: TargetHost " + props.get("targetHost") + " is unknown!");
370                     closeLog();
371                     fehler = true;
372                     //und zum nächsten Target
373
currentPropertySet++;
374                     continue;
375                 }
376                 logAndPrint("TargetPort: " + props.get("targetPort"));
377                 
378                 if ( props.get("siteDocumentsConfig") != null )
379                 {
380                     logAndPrint("using SiteDocumentsConfiguration: " + markAsFile(props.get("siteDocumentsConfig")));
381                     if ( !useConfig )
382                     {
383                         logAndPrint("(but ignoring include and exclude rules)");
384                     }
385                 }
386                 else
387                 {
388                     logAndPrint("using TargetDir: " + markAsFile(props.get("TargetDir")));
389                 }
390
391                 logAndPrint("Storing list of site documents in " + markAsFile(props.get("siteDocumentsListing")));
392                 
393                 if ( transferChangedOnly )
394                 {
395                     logAndPrint("Transmitting changed files only");
396                 }
397                 else
398                 {
399                     logAndPrint("Transmitting all files");
400                 }
401                 
402                 if ( logfile == null )
403                 {
404                     error("Warning: couldn't open logfile " + markAsFile(props.get("logFile")));
405                 }
406                 else
407                 {
408                     if ( props.get("appendLog").equals("true") )
409                     {
410                         logAndPrint("Appending log to " + markAsFile(props.get("logFile")));
411                     }
412                     else
413                     {
414                         logAndPrint("Creating log in " + markAsFile(props.get("logFile")));
415                     }
416                 }
417  //*TEST ANFANG
418
CAT.debug("Staging begins...");
419                 // Methoden, die selbst keine Ausgabe erzeugen, werden über methodSucceed(String,String)
420
// abgewickelt, damit man weiß, was abgeht (z.B. "initializing ssl --- done")
421
// Methoden, die selbst Ausgaben erzeugen, werden über methodSucceed(String) abgewickelt, d.h.
422
// es wird an deren Ausgabe nur noch ein "--- done" oder "--- fail: ..." angehängt
423
// ssl initialisieren
424
if ( !methodSucceed(initSSL(), "initializing ssl")
425                 // Site zusammenstellen
426
|| !methodSucceed(assembleSite(props.get("documentRoot"),
427                                                  props.get("siteDocumentsConfig"),
428                                                  props.get("TargetDir"),
429                                                  props.get("siteDocumentsListing"),
430                                                  useConfig))
431                 // Site packen
432
|| !methodSucceed(packSite(props.get("tempDir"),transferChangedOnly))
433                 // SSL-Verbindung vorbereiten
434
|| !methodSucceed(prepareSSL(props.get("keyStore"),props.get("keyStorePassword"),
435                                               props.get("keyPassword"),props.get("trustStore")))
436                 // SSL-Verbindung öffnen
437
|| !methodSucceed(createConnection(props.get("targetCGI"), props.get("targetHost"),
438                                                      new Integer JavaDoc(props.get("targetPort")).intValue(),
439                                                      props.get("userName"), props.get("passWord"),
440                                                      props.get("proxyHost"), props.get("proxyPort"),
441                                                      openSocketTimeout, props.getReceiverProperties()) )
442                 // gepackte Site übertragen
443
|| !transmitSite(zippedSite)
444                 // SiteDocumentsListing übertragen
445
|| !methodSucceed(transmitSiteInfo(), "transmitting list of site documents")
446                 // Receiver-Log empfangen
447
|| !methodSucceed(receiveLog(),"receiving log of SiteReceiver") )
448                 {
449                     success = false;
450                 }
451    
452                 // Receiver-Ausgabe anzeigen
453
if ( starter != null )
454                 {
455                     if ( starter.gotReceiverOutput() )
456                     {
457                         logAndPrint("Starting output of SiteReceiver:");
458                         logAndPrint(" ");
459                         starter.startOutput();
460                         logAndPrint(" "); //Leerzeile
461
}
462                     CAT.debug("waiting for starter to end");
463                     synchronized ( starter.lock )
464                     {
465                         CAT.debug("ServerStarter ended");
466                     }
467                     if ( !starter.success )
468                     {
469                         success = false;
470                     }
471                 }
472
473                 // if everything is fine - save list of transmitted files
474
if ( success )
475                 {
476                     logAndPrint("<FONT color=#00cc00>Everything is fine, stored new list of site documents in: " + markAsFile(props.get("siteDocumentsListing")) + "</FONT>");
477                     try
478                     {
479                         sitePacker.saveToFile(props.get("siteDocumentsListing"));
480                     }
481                     catch (java.io.IOException JavaDoc e)
482                     {
483                         error("Warning: unable to store new list");
484                         logAndPrint(e.toString());
485                         error("next publication of changed files might be inaccurate");
486                         error("please transfer all files next time (set FilesToTransmit = a)");
487                     }
488                 }
489                 else
490                 {
491                     error("Something went wrong, please contact your system administrator.");
492                     //will noch auf die log4j-Logs hinweisen
493
Enumeration appenders = CAT.getRoot().getAllAppenders();
494                     Vector logNames = new Vector();
495                     Object JavaDoc appender = null;
496                     while ( appenders.hasMoreElements() )
497                     {
498                         appender = appenders.nextElement();
499                         if ( appender instanceof FileAppender )
500                         {
501                             logNames.add( ((FileAppender)appender).getFile() );
502                         }
503                     }
504                     if ( logNames.size() > 0 )
505                     {
506                         String JavaDoc hint = "He should also check the Log4J-Logfiles: ";
507                         for ( int i=0; i<logNames.size(); i++ )
508                         {
509                             hint += (String JavaDoc)logNames.elementAt(i);
510                             if ( i<logNames.size()-1 )
511                             {
512                                 hint += ", ";
513                             }
514                         }
515                         error(hint + ".");
516                     }
517                     fehler = true;
518                 }
519 //TEST ENDE */
520
// closing socket
521
if ( clientSocket != null )
522                 {
523                     try
524                     {
525                         clientSocket.close();
526                         CAT.debug("socket closed");
527                     }
528                     catch (Exception JavaDoc e)
529                     {
530                         CAT.warn("could not close socket to receiver",e);
531                         logAndPrint("warning: unable to close socket to receiver");
532                     }
533                 }
534                     
535                 logAndPrint("end of log");
536                 closeLog();
537                 try
538                 {
539                     if ( !reuseZipfile && (zippedSite != null) )
540                     {
541                         zippedSite.delete();
542                     }
543                 }
544                 catch (Exception JavaDoc e)
545                 {
546                     print("Note: zipfile could not be deleted - you can manually delete it.");
547                     CAT.error("zipfile could not be deleted: " + e);
548                 }
549                 currentPropertySet++; //auf zum nächsten Target (=PropertySet)
550
}//END WHILE
551
}
552         catch (Throwable JavaDoc t)
553         {
554             CAT.error("Unknown error occurred",t);
555         }
556         try
557         {
558             outSocket.close();
559         }
560         catch (Exception JavaDoc e)
561         {
562             CAT.warn("Could not close interprocess socket (STDOUT-Redirect)",e);
563         }
564         printFooter(); //Ende der Ausgabe ist hier!
565
System.exit(success && !fehler ? 0 : 1);
566     }
567     
568     /**
569      * liest Properties von der angegebenen ResourceDescriptor und gibt daraus resultierendes PropertySet zurück
570      * @param resourceDescriptor Name der Property-Resource (Property-Filename oder WebmanPropertyGroup-Name)
571      * @return gültiges PropertySet
572      * @throws WrongConfigurationException wenn die Auswertung der Properties einen Fehler ergab
573      */

574     private PropertySet readProperties(String JavaDoc resourceDescriptor) throws WrongConfigurationException
575     {
576         PropertySet source, result;
577         try
578         {
579             if ( useDB )
580             {
581                 source = new PropertySet(com.teamkonzept.lib.PropertyManager.getPropertyManager(resourceDescriptor));
582             }
583             else //PropertyFile
584
{
585                 if ( confroot == null )
586                 {//der baseResourceDescriptor ist entweder absolut oder relativ zum Klassenverzeichnis des Stagers
587
String JavaDoc classname = getClass().getName();
588                     String JavaDoc docroot = new File(getClass().getResource(classname.substring(classname.lastIndexOf(".") + 1) + ".class").getFile()).getParent();
589                     confroot = new File(getAbsoluteName(docroot,resourceDescriptor)).getParent();
590                     resourceDescriptor = getAbsoluteName(docroot,resourceDescriptor);
591                 }
592                 else
593                 {//alle übrigen Properties sind entweder absolut oder relativ zum Verzeichnis des baseResourceDescriptors
594
resourceDescriptor = getAbsoluteName(confroot,resourceDescriptor);
595                 }
596                 Properties p = new Properties();
597                 p.load(new FileInputStream(resourceDescriptor));
598                 source = new PropertySet(p);
599             }
600         }
601         catch (Exception JavaDoc e)
602         {
603             throw new WrongConfigurationException("Could not read property-resource \"" + resourceDescriptor + "\": " + e.toString());
604         }
605         result = parseProperties(source);
606         result.set("ResourceDescriptor",resourceDescriptor); //den Namen der Einfachheit halber gleich mitführen
607
return result;
608     }
609     
610     /**
611      * checkt die übergebenen Properties auf Konsistenz (und Vollständigkeit, wenn sie final sind)
612      * und erzeugt neues PropertySet, was ein Merge ist aus übergebenen und dem BasePropertySet (wenn vorhanden)
613      * @param source das neue PropertySet
614      * @return ein gültiges PropertySet als Merge von übergebenem und BasePropertySet
615      * @throws WrongConfigurationException wenn die Auswertung der Properties einen Fehler ergab
616      */

617     private PropertySet parseProperties(PropertySet source) throws WrongConfigurationException
618     {
619         //Konzept beim Propertyparsen:
620
//I.A. müssen alle Properties da sein. Über getProperty() wird eine Property abgefragt, wobei
621
//ihr Wert entweder aus dem gerade zu parsenden PropertySet geholt wird oder, wenn schon vorhanden
622
//aus den BaseProperties. Ist ein Wert nicht definiert, wird eine PropertyNotFoundException geworfen
623
//Entsprechend muss diese bei einer optionalen Property vor Ort abgefangen werden
624
//Einen Sonderfall stellen die baseProperties (beim ersten Parsen) dar, denn hier muss eigentlich
625
//gar kein Wert definiert sein, wenn noch extended Property-Resourcen vorhanden sind
626
//zwar wird bei einem fehlenden Wert von getProperty() an der Stelle keine Exception geworfen,
627
//doch dafür muss jeweils im Anschluss der zurückgegebene Wert auf null getestet werden, um bei
628
//der folgenden Verarbeitung keine NullpointerExceptions zu haben
629
//PropertySet() ist dabei schon so intelligent, Nullwerte einfach nicht einzutragen
630

631         PropertySet result = new PropertySet();
632         //als erstes werden einmal die baseProperties geparst. Wenn die erledigt sind, kommen nur noch die
633
//TargetProperties. Die müssen final sein
634
isCurrentParsedPropertySetFinal = true;
635         try
636         {
637             if ( baseProperties == null )
638             {//wenn gerade die BaseProperties zum ersten Mal geparst werden
639
CAT.debug("TargetPropertiesDescriptors...");
640                 Vector resourceDescriptors = source.getPropertyGroup("TargetProperties");
641                 if ( resourceDescriptors.size() > 0 )
642                 {
643                     for (int i=0; i<resourceDescriptors.size(); i++)
644                     {//TargetProperties werden in kanonischer Form dem aktuellen PropertySet hinzugefügt
645
result.set("TargetProperties" + i,(String JavaDoc)(resourceDescriptors.elementAt(i)));
646                     }
647                     //wenn targetProperties kommen, so brauchen baseProperties nicht vollständig (->final) sein
648
isCurrentParsedPropertySetFinal = false;
649                 }
650             }//werden targetProperties (oder baseProperties zum 2. Mal, d.h. es gibt keine gültigen TargetProperties
651
//-> muss baseProperties alleine verwenden) geparst, dann müssen die final sein
652

653             String JavaDoc temp = null; //für temporäre Propertyauswertung
654
File tempFile = null; // -""-
655

656             //LogFile parse ich als erstes, da im showLog-Modus das die einzig relevante Property ist
657
try
658             {
659                 temp = getProperty(source,"LogName");
660             }
661             catch (PropertyNotFoundException p)
662             {//Wenn LogName nicht da ist, kann es noch unter LogFile stehen. Wenn das aber auch fehlt, dann Fehler!
663
temp = getProperty(source,"logFile");
664             }
665             if ( temp != null )
666             {
667                 try
668                 {
669                     temp = getAbsoluteName(confroot,temp);
670                 }
671                 catch (IllegalArgumentException JavaDoc e)
672                 {
673                     if ( useDB )
674                     {
675                         throw new WrongConfigurationException("When using WebMan properties for "
676                         + "configuration, it is not possible to use a relative path "
677                         + "(\"" + temp + "\") for LogName. Specify an absolute path!");
678                     }
679                     else
680                     {
681                         throw e;
682                     }
683                 }
684                 try
685                 {
686                     temp = new File(temp).getCanonicalPath();
687                 }
688                 catch (IOException e)
689                 {
690                     CAT.warn("Could not form canonical path for " + temp);
691                 }
692             }
693             result.set("LogFile",temp);
694             CAT.debug("LogFile=" + temp);
695             //Zum Anzeigen des Logs reicht der jetzige Stand aus
696
if ( showLogOnly )
697             {
698                 return result;
699             }
700                     
701             temp = getProperty(source,"DocumentRoot");
702             if ( temp != null )
703             {
704                 if ( temp.endsWith(File.separator) )
705                 {
706                     temp = temp.substring(0,temp.length()-File.separator.length());
707                 }
708                 else if ( temp.endsWith("/") ) //in Java können Windowspfadnamen auch mit / gebildet werden
709
{
710                     temp = temp.substring(0,temp.length()-"/".length());
711                 }
712                 if ( !(new File(temp).exists()) )
713                 {
714                     throw new WrongConfigurationException("DocumentRoot " + temp + " doesn't exist.");
715                 }
716                 try
717                 {
718                     temp = new File(temp).getCanonicalPath();
719                 }
720                 catch (Exception JavaDoc e)
721                 {
722                     CAT.warn("Could not form canonical path for " + temp);
723                 }
724                 result.set("documentRoot",temp);
725             }
726             CAT.debug("DocumentRoot=" + result.get("documentRoot"));
727             
728             //AppendLog: diese Property ist optional
729
try
730             {
731                 temp = getProperty(source, "AppendLog");
732                 if ( temp != null && temp.toLowerCase().equals("yes") )
733                 {
734                     result.set("appendLog","true");
735                 }
736                 else
737                 {
738                     result.set("appendLog","false");
739                 }
740             }
741             catch (Exception JavaDoc e)
742             {
743                 result.set("appendLog","false");//default ist false
744
}
745             CAT.debug("AppendLog=" + result.get("AppendLog"));
746             
747             try
748             {//OpenSocketsTimeoutSeconds ist optional; default = 60
749
temp = getProperty(source,"OpenSocketTimeoutSeconds");
750                 //muss auf temp!= null checken, da hier keine Exception geowrfen wird, wenn isFinal=false ist
751
if ( temp != null && (Integer.parseInt(temp) < 1 || Integer.parseInt(temp) > MAX_OPEN_TIMEOUT_SECONDS) )
752                 {
753                     throw new WrongConfigurationException("OpenSocketTimeoutSeconds must be within 1.." + MAX_OPEN_TIMEOUT_SECONDS);
754                 }
755             }
756             catch ( PropertyNotFoundException p )
757             {
758                 temp = DEFAULT_OPEN_SOCKET_TIMEOUT_SECONDS;
759             }
760             result.set("OpenSocketTimeoutSeconds",temp);
761             CAT.debug("OpenSocketTimeoutSeconds=" + result.get("OpenSocketTimeoutSeconds"));
762             
763             temp = getProperty(source,"TargetCGI");
764             if ( temp != null ) //kann null sein, wenn ich TargetCGI erst in den TargetProperties spezifziere!
765
{
766                 //TargetCGI ist eine HTTP-URL
767
if ( !temp.startsWith("http://") )
768                 {
769                     temp = "http://" + temp;
770                 }
771                 result.set("TargetCGI",temp);
772             }
773             CAT.debug("TargetCGI=" + result.get("TargetCGI"));
774
775             // besondere Vererbungsregeln:
776
//1) Ist kein aktueller Host gesetzt, so wird er aus aktuellem/geerbten CGI berechnet,
777
// es sei denn, in den BaseProperties ist der Host EXPLIZIT gesetzt
778
//2) Ist ein aktueller Host gesetzt, so wird der IMMER dem (eventuell) vererbten vorgezogen
779
temp = source.get("TargetHost"); //hole mir aktuell gesetzten Host
780
if ( temp != null ) //alles klar, TargetHost wird aktuell explizit gesetzt
781
{
782                 //TargetHost ist nur ein Rechnername (ohne Protokoll!)
783
if ( temp.startsWith("http://") )
784                 {
785                     temp = temp.substring(7);
786                 }
787             }
788             else if ( baseProperties != null && baseProperties.get("TargetHost") != null )
789             {//wenn TargetHost in den baseProperties explizit gesetzt wurde, wird der verwendet
790
temp = baseProperties.get("TargetHost"); //ist da schon überprüft u. ins richtige Format gebracht worden
791
}
792             else //wenn Host weder aktuell noch in baseProperties explizit gesetzt wurde,
793
{ //dann wird er halt aus dem aktuellen/vererbten TargetCGI berechnet
794
temp = getProperty(source,"TargetCGI");
795                 //kann null sein, wenn ich grad baseProperties parse und da TargetCGI nich drin is
796
if ( temp != null && isCurrentParsedPropertySetFinal )
797                 {//wenn das currentParsedPropertySet final ist, dann muss ich den targetHost setzen
798
temp = ServerStarter.serverPart(temp);
799                 }
800                 else//wenn aber noch targetProperties kommen, so muss ich dort entscheiden, welches
801
{ //TargetCGI/TargetHost ich nehme; darf dann hier TargetHost nicht vorweg nehmen
802
temp = null;
803                 }
804             }
805             if ( temp != null ) //möchte keine null abspeichern
806
{
807                 result.set("TargetHost",temp); //geschafft
808
}
809             CAT.debug("TargetHost=" + result.get("TargetHost"));
810
811             try
812             {
813                 temp = getProperty(source,"TargetPort");
814                 if ( temp != null )
815                 {
816                     try
817                     {
818                         int port = Integer.parseInt(temp); //wirft Exception bei falschem Zahlenformat
819
if ( port < MIN_PORT || port > MAX_PORT )
820                         {
821                             throw new NumberFormatException JavaDoc();
822                         }
823                     }
824                     catch (NumberFormatException JavaDoc n)
825                     {
826                         throw new WrongConfigurationException("TargetPort must be within 1024...65535");
827                     }
828                 }
829                 else
830                 {
831                     temp = DEFAULT_TARGET_PORT;
832                 }
833                 result.set("TargetPort",temp);
834             }
835             catch (PropertyNotFoundException e)
836             {
837                 result.set("TargetPort",DEFAULT_TARGET_PORT);
838             }
839             CAT.debug("TargetPort=" + result.get("TargetPort"));
840             
841             //proxy-Einstellungen sind optional und bedeuten keinen Fehler -> wenn nicht vorhanden, dann = null!
842
try
843             {//es reicht schon, wenn eine Angabe von beiden fehlt -> dann brauch ich die andere auch nich
844
temp = getProperty(source,"ProxyHost"); //wenn der nicht vorhanden ist, springt er gleich raus
845
}
846             catch (PropertyNotFoundException e)
847             {
848                 temp = null;
849             }
850             if ( temp != null ) //falls ein proxyHost angegeben wurde, sollte der proxyPort auch stimmen
851
{
852                 try
853                 {
854                     int port = Integer.parseInt(getProperty(source,"proxyPort"));//wirft Exception bei falschem Zahlenformat und wenn Angabe fehlt
855
if ( port < 0 || port > MAX_PORT )
856                     {
857                         throw new NumberFormatException JavaDoc();
858                     }
859                     result.set("proxyHost",temp);
860                     result.set("proxyPort",getProperty(source,"ProxyPort"));
861                 }
862                 catch (NumberFormatException JavaDoc n)
863                 {
864                     throw new WrongConfigurationException("proxyPort must be within 0..." + MAX_PORT);
865                 }
866             }
867             CAT.debug("ProxyHost=" + result.get("ProxyHost"));
868             CAT.debug("ProxyPort=" + result.get("ProxyPort"));
869
870             temp = getProperty(source,"TempDir");
871             if ( temp != null )
872             {
873                 try
874                 {
875                     result.set("tempDir",getAbsoluteName(result.get("documentRoot"),temp));
876                 }
877                 catch (IllegalArgumentException JavaDoc e)
878                 {
879                     throw new WrongConfigurationException("when using a relative pathname for TempDir, DocumentRoot must be set as well.");
880                 }
881                 try
882                 {
883                     temp = new File(temp).getCanonicalPath();
884                 }
885                 catch (Exception JavaDoc e)
886                 {
887                     CAT.warn("Could not form canonical path for " + temp);
888                 }
889             }
890             CAT.debug("TempDir=" + result.get("TempDir"));
891
892             //KeyStore ist optional (nötig für ClientAuthentifizierung)
893
//Im Gegensatz zu anderen Pfadangaben werden diese im Klassenpfad des Stagers gesucht
894
try
895             {
896                 temp = getProperty(source,"KeyStore");
897                 if ( temp == null )
898                 {//beim Parsen der baseProperties kann temp == null sein, wenn noch targetProperties vorhanden sind
899
throw new PropertyNotFoundException("keyStore"); //dummy; möchte Catchblock-Code nicht doppeln
900
}
901                 else
902                 {
903                     result.set("keyStore",temp);
904                 }
905             }
906             catch (PropertyNotFoundException p)
907             {
908                 result.set("keyStore","");
909             }
910             CAT.debug("KeyStore=" + result.get("KeyStore"));
911             
912             try
913             {
914                 temp = getProperty(source,"TrustStore");
915                 if ( temp == null )
916                 {//beim Parsen der baseProperties kann temp == null sein, wenn noch targetProperties vorhanden sind
917
throw new PropertyNotFoundException("TrustStore"); //dummy, möchte nur den Code im Catchblock nicht doppeln
918
}
919                 result.set("trustStore",temp);
920             }
921             catch (PropertyNotFoundException p)
922             {
923                 result.set("trustStore",DEFAULT_KEYSTORE_FILE);
924             }
925             CAT.debug("TrustStore=" + result.get("TrustStore"));
926                        
927             //KeyPassword wird (wenn nicht vorhanden) immer nur vom ZUGEHÖRIGEN KeyStorePassword abgeleitet
928
//d.h. habe immer Paare von KeyPassword und KeyStoreKassword
929
temp = source.get("KeyStorePassword");
930             if ( temp != null )
931             {
932                 result.set("KeyStorePassword",temp);
933                 temp = source.get("KeyPassword");
934                 if ( temp != null )
935                 {
936                     result.set("KeyPassword",temp);
937                 }
938                 else
939                 {
940                     result.set("KeyPassword",result.get("KeyStorePassword"));
941                 }
942             }
943             else
944             {
945                 try
946                 {
947                     result.set("KeyStorePassword",getProperty(source,"KeyStorePassword"));
948                 }
949                 catch (PropertyNotFoundException p)
950                 {
951                     result.set("KeyStorePassword",DEFAULT_KEYSTORE_PASSWORD);
952                 }
953
954                 try
955                 {
956                     result.set("KeyPassword",getProperty(source,"KeyPassword"));
957                 }
958                 catch (PropertyNotFoundException p)
959                 {
960                     result.set("KeyPassword",result.get("KeyStorePassword"));
961                 }
962             }
963             CAT.debug("KeyStorePassword=" + result.get("KeyStorePassword"));
964             CAT.debug("KeyPassword=" + result.get("KeyPassword"));
965             
966             //Statt siteDocumentsConfig kann auch TargetDir angegeben werden -> dann gibt es keinen Dateifilter
967
//Sind beide Properties angegeben, hat SiteDocumentsConfig den Vorrang; eins muss mindestens angegeben sein
968
//Wird SiteDocumentsConfig in den TargetProperties durch TargetDir "überschrieben", so hat letzteres den Vorrang
969

970             //muss unterscheiden, ob sitedocumentsconfig aus base- oder targetproperties stammt
971
temp = source.get("SiteDocumentsConfig");
972             if ( temp != null )
973             {
974                 try
975                 {
976                     temp = getAbsoluteName(confroot,temp);
977                 }
978                 catch (IllegalArgumentException JavaDoc e)
979                 {
980                     if ( useDB )
981                     {
982                         throw new WrongConfigurationException("When using WebMan properties for "
983                         + "configuration, it is not possible to use a relative path "
984                         + "(\"" + temp + "\") for SiteDocumentsConfig. Specify an absolute path!");
985                     }
986                     else
987                     {
988                         throw e;
989                     }
990                 }
991                 try
992                 {
993                     temp = new File(temp).getCanonicalPath();
994                 }
995                 catch (Exception JavaDoc e)
996                 {
997                     CAT.warn("Could not form canonical path for " + temp);
998                 }
999                 tempFile = new File(temp);
1000                if ( !tempFile.exists() || !tempFile.canRead() )
1001                {
1002                    throw new WrongConfigurationException("Cannot find or read site documents configuration file " + temp);
1003                }
1004                result.set("SiteDocumentsConfig",temp);
1005            }
1006            else //wenn in aktuellen Properties sitedocConf nicht angegeben ist, muss es entweder
1007
{//in den baseproperties angegeben sein oder targetdir muss angegeben sein
1008
temp = source.get("TargetDir");
1009                if ( temp != null ) //bei aktuell nicht vorhandener sitedocconf wird targetdir gesetzt, wenn vorhanden
1010
{
1011                    result.set("TargetDir",temp);
1012                }
1013                else if ( isCurrentParsedPropertySetFinal )
1014                {
1015                    if ( baseProperties != null ) //wenn noch baseProperties existieren, dann muss ich noch fragen
1016
{//wenn aktuell nichts vorhanden ist, wird vererbt, wobei sitedocconf Vorrang hat
1017
if ( baseProperties.get("SiteDocumentsConfig") != null )
1018                        {//brauche hier nicht getAbsoluteName() ausführen, da der vorher schon gesetzt wurde (s.o.)
1019
result.set("SiteDocumentsConfig",baseProperties.get("SiteDocumentsConfig"));
1020                        }
1021                        else
1022                        {
1023                            if ( baseProperties.get("TargetDir") != null )
1024                            {
1025                                result.set("TargetDir",baseProperties.get("TargetDir"));
1026                            }
1027                            else //wenn keine der beiden Properties gesetzt ist, dann Fehler
1028
{
1029                                throw new WrongConfigurationException("TargetDir or SiteDocumentsConfig must be set");
1030                            }
1031                        }
1032                    }
1033                    else //wenn nirgendwo mehr was zu holen ist, dann Fehler
1034
{
1035                        throw new WrongConfigurationException("TargetDir or SiteDocumentsConfig must be set");
1036                    }
1037                }//wenn noch TargetProperties zu lesen sind, dann wird dort nach diesen Properties geschaut
1038
}
1039            CAT.debug("SiteDocumentsConfig=" + result.get("SiteDocumentsConfig"));
1040            CAT.debug("TargetDir=" + result.get("TargetDir"));
1041            
1042            temp = getProperty(source,"SiteDocumentsListing");
1043            if ( temp != null )
1044            {
1045                try
1046                {
1047                    temp = getAbsoluteName(confroot,temp);
1048                }
1049                catch (IllegalArgumentException JavaDoc e)
1050                {
1051                    if ( useDB )
1052                    {
1053                        throw new WrongConfigurationException("When using WebMan properties for "
1054                        + "configuration, it is not possible to use a relative path "
1055                        + "(\"" + temp + "\") for SiteDocumentsListing. Specify an absolute path!");
1056                    }
1057                    else
1058                    {
1059                        throw e;
1060                    }
1061                }
1062                try
1063                {
1064                    temp = new File(temp).getCanonicalPath();
1065                }
1066                catch (Exception JavaDoc e)
1067                {
1068                    CAT.warn("Could not form canonical path for " + temp);
1069                }
1070                tempFile = new File(temp);
1071                if ( !tempFile.exists() )
1072                {
1073                    throw new WrongConfigurationException("Cannot find SiteDocumentsListing " + temp);
1074                }
1075                if ( !tempFile.canWrite() || !tempFile.canRead() )
1076                {
1077                    throw new WrongConfigurationException("SiteDocumentsListing " + temp + " is not readable and writable.");
1078                }
1079                for (int i=0; i<propertySetList.size(); i++)
1080                {//jedes SiteDocumentListing muss verschieden sein von den anderen
1081
if ( temp.equals( ((PropertySet)propertySetList.elementAt(i)).get("siteDocumentsListing") ) )
1082                    {
1083                        throw new WrongConfigurationException("SiteDocumentsListing must be unique for each target! "
1084                        + "(filename " + temp + " is used in more than one property-resource (or inherited from base property-resource))") ;
1085                    }
1086                }
1087                result.set("SiteDocumentsListing",temp);
1088            }
1089            CAT.debug("SiteDocumentsListing=" + result.get("SiteDocumentsListing"));
1090         
1091            try
1092            {
1093                temp = getProperty(source, "TargetCGIPasswordProtected");
1094            }
1095            catch (PropertyNotFoundException p)
1096            {
1097                temp = null;
1098            }
1099            if ( temp != null)
1100            {
1101                if ( temp.toLowerCase().equals("yes") )
1102                {
1103                    result.set("userName",getProperty(source,"TargetCGIUserName"));
1104                    result.set("passWord",getProperty(source,"TargetCGIPassword"));
1105                    CAT.debug("TargetCGIUserName=" + result.get("userName"));
1106                    CAT.debug("TargetCGIPassword=" + result.get("passWord"));
1107                }
1108            }
1109
1110            temp = getProperty(source,"FilesToTransmit");
1111            if ( temp != null )
1112            {
1113                temp = temp.toLowerCase();
1114                if ( (temp.equals("c") || temp.equals("a") || temp.equals("d")) )
1115                {
1116                    result.set("FilesToTransmit",temp);
1117                }
1118                else
1119                {
1120                    throw new WrongConfigurationException("entry FilesToTransmit must be one of c, a or d");
1121                }
1122            }
1123            else
1124            {
1125                result.set("FilesToTransmit","a");
1126            }
1127            CAT.debug("FilesToTransmit=" + result.get("FilesToTransmit"));
1128            //--------------------------- receiver-properties abhandeln ---------------------------
1129

1130            //es gibt z.Z. nur 2 notwendig auf Senderseite zu setzende ReceiverProperties -> setze per Hand, nicht per Schleife
1131
//(dabei auch zu beachten: Sicherheitsaspekte (kann z.B. nicht tempDir oder logdir frei beliebig setzen, könnte sonst was auf ReceiverSeite löschen))
1132
try
1133            {
1134                result.set("ReceiverSiteDocumentsListing",getProperty(source,"ReceiverSiteDocumentsListing"));
1135            }
1136            catch (PropertyNotFoundException p)
1137            {//dummy; obiger Werte ist erstmal optional
1138
temp = null;
1139            }
1140            CAT.debug("ReceiverSiteDocumentsListing=" + result.get("ReceiverSiteDocumentsListing"));
1141            
1142            try
1143            {
1144                result.set("ReceiverLogFile",getProperty(source,"ReceiverLogFile"));
1145            }
1146            catch (PropertyNotFoundException p)
1147            {//dummy; obiger Werte ist erstmal optional
1148
temp = null;
1149            }
1150            CAT.debug("ReceiverLogFile=" + result.get("ReceiverLogFile"));
1151            //checke, ob siteDocumentsListings verschieden sind, falls auf denselben Host gestaged wird
1152
//(das ReceiverLog muss nicht unbedingt verschieden sein, auch wenn es im Nachhinein vielleicht praktisch wäre)
1153
if ( isCurrentParsedPropertySetFinal )
1154            {
1155                PropertySet props;
1156                //gehe alle bisherigen PropertySets durch
1157
for (int i=0; i<propertySetList.size(); i++)
1158                {
1159                    props = (PropertySet)propertySetList.elementAt(i);
1160                    //(nur) wenn ich auf selben Host stage, dürfen die SiteDocumentsListings nicht gleich sein
1161
if ( props.get("TargetHost").equals(result.get("TargetHost")) )
1162                    {
1163                        //der Wert MUSS immer gesetzt sein, sonst würde auf ReceiverSeite das Default
1164
//(oder der Wert aus den receiver.properties) genommen, der dann zufällig
1165
//gleich sein könnte mit einem der gesetzten Werte, was wieder zu dem Problem
1166
//führen würde, welches wir eigentlich zu verhindern suchen
1167
if ( props.get("ReceiverSiteDocumentsListing") == null )
1168                        {
1169                            throw new WrongConfigurationException("ReceiverSiteDocumentsListing must be set for EACH target for targets on the same host! ");
1170                        }
1171                        //wenn aktuell gültiges ReceiverSiteDocumentsListing gleich einem vorherigen, dann Fehler
1172
if ( result.get("ReceiverSiteDocumentsListing").equals(props.get("ReceiverSiteDocumentsListing")) )
1173                        {
1174                            throw new WrongConfigurationException("ReceiverSiteDocumentsListing must be unique for each target for targets on the same host! ");
1175                        }
1176                        try
1177                        {//wenn aktuell gültiges ReceiverLogFile gleich einem vorherigen, dann Warnung
1178
if ( result.get("ReceiverLogFile").equals(props.get("ReceiverLogFile")) )
1179                            {
1180                                throw new PropertyNotFoundException(null); //damit ich nachfolgende Fehlermeldung erzeugen kann:
1181
}
1182                        }
1183                        catch (PropertyNotFoundException p)
1184                        {
1185                            logAndPrint("Note: it is recommended to use distinct values for ReceiverLogFile when staging to multiple targets on the same host.");
1186                        }
1187                    }
1188                }
1189            }
1190            //eventuell sind noch Afterburner-Einstellungen vorhanden; die sind einfach abzuhandeln
1191
//ReceiverAfterburner wird entweder GANZ (mit Parametern) oder GAR NICHT vererbt!
1192
temp = source.get("ReceiverAfterBurner");
1193            if ( temp != null )
1194            {
1195                //wenn ReceiverAfterBurner leer überschrieben wurde, so soll er nicht ererbt werden
1196
//ergo sind wir dann an dieser Stelle fertig mit den Properties...
1197
if ( temp.equals("") )
1198                {
1199                    return result;
1200                }
1201                result.set("ReceiverAfterBurner",temp);
1202                temp = source.get("ReceiverAfterBurnerNoJava");
1203                if ( temp != null && temp.equals("yes") )
1204                {
1205                    result.set("ReceiverAfterBurnerNoJava","true");
1206                }
1207                Vector params = source.getPropertyGroup("ReceiverAfterBurnerParameter");
1208                for ( int i=0; i<params.size(); i++)
1209                {
1210                    result.set("ReceiverAfterBurnerParameter" + i,params.elementAt(i));
1211                }
1212            }
1213            else if (baseProperties != null )
1214            {
1215                temp = baseProperties.get("ReceiverAfterBurner");
1216                if ( temp != null )
1217                {
1218                    result.set("ReceiverAfterBurner",temp);
1219                    temp = source.get("ReceiverAfterBurnerNoJava");
1220                    if ( temp != null && temp.equals("yes") )
1221                    {
1222                        result.set("ReceiverAfterBurnerNoJava","true");
1223                    }
1224                    CAT.debug("ReceiverAfterBurnerParameter...");
1225                    //ich übernehme auch alle (potentiell) vorhandenen Parameter
1226
Vector params = baseProperties.getPropertyGroup("ReceiverAfterBurnerParameter");
1227                    for ( int i=0; i<params.size(); i++)
1228                    {
1229                        result.set("ReceiverAfterBurnerParameter" + i,params.elementAt(i));
1230                        CAT.debug("ReceiverAfterBurnerParameter" + i + "=" +
1231                                    result.get("ReceiverAfterBurnerParameter"+i));
1232                    }
1233                }
1234            }
1235            CAT.debug("ReceiverAfterBurner=" + result.get("ReceiverAfterBurner"));
1236            
1237            //SkipErrors: sobald Transmitter oder Receiver die auf yes setzen, ist diese Option eingeschaltet
1238
try
1239            {
1240                temp = getProperty(source,"ReceiverSkipErrors");
1241                if ( temp != null && temp.toLowerCase().equals("yes") )
1242                {
1243                    result.set("ReceiverSkipErrors","yes");
1244                }
1245            }
1246            catch (PropertyNotFoundException p)
1247            {
1248                temp = null;
1249            }
1250            CAT.debug("ReceiverSkipErrors=" + result.get("ReceiverSkipErrors"));
1251                    
1252            //Simulate: sobald Transmitter oder Receiver die auf yes setzen, ist diese Option eingeschaltet
1253
try
1254            {
1255                temp = getProperty(source,"ReceiverSimulate");
1256                if ( temp != null && temp.toLowerCase().equals("yes") )
1257                {
1258                    result.set("ReceiverSimulate","yes");
1259                }
1260            }
1261            catch (PropertyNotFoundException p)
1262            {
1263                temp = null;
1264            }
1265            CAT.debug("ReceiverSimulate=" + result.get("ReceiverSimulate"));
1266        }
1267        catch (Exception JavaDoc e) // oder was sonst so anfällt
1268
{
1269            if ( !(e instanceof WrongConfigurationException) )
1270            {//eine andere als ne WrongConfigurationException erstmal hübsch in eine eben solche "verpacken"!
1271
CAT.error("Unknown Exception: " + e.getMessage(),e); //printet auch den StackTrace
1272
throw new WrongConfigurationException(e.toString());
1273            }
1274            else
1275            {//sonst isses die oben geworfene WronConfigurationException -> einfach durchreichen
1276
throw (WrongConfigurationException)e;
1277            }
1278        }
1279        return result;
1280    }
1281         
1282    /**
1283     * holt sich Property aus gegebenem PropertySet oder, falls dort nich vorhanden, aus den baseProperties (wenn vorhanden)
1284     * @param p aktuell zu durchsuchendes PropertySet (->primäre Quelle)
1285     * @param key Name der zu findenden Property
1286     * @return Wert der gefundenen Property (null, wenn nicht vorhanden)
1287     * @throws PropertyNotFoundException wenn weder p noch baseProperties den gesuchten Wert enthielten
1288     */

1289    private String JavaDoc getProperty(PropertySet p, String JavaDoc key) throws PropertyNotFoundException
1290    {
1291        String JavaDoc s = p.get(key);
1292
1293        if ( s == null || s.equals("") )
1294        {
1295            if ( baseProperties != null ) //wenn die globalen Properties schon eingelesen wurden
1296
{//wenn dort der key auch keinen value hat und die aktuellen properties final sind -> fehler!
1297
s = baseProperties.get(key);
1298            }
1299        }
1300        if ( (s == null || s.equals("")) && isCurrentParsedPropertySetFinal )
1301        {
1302            throw new PropertyNotFoundException(key);
1303        }
1304        return s;
1305    }
1306        
1307    /**
1308     * Zerlegt einen ArgumentString (Kommandozeilenparameter) und bastelt daraus eine Hastable
1309     * Ausnahme: der Propertyfilename mit oder ohne "PropertyFile=" oder "Configuration=" angegeben werden
1310     *@param argStrings Argumente im Format name=value
1311     *@return Hashtable die Argumente mit name als Schlüssel und value als Werte
1312     */

1313    private Hashtable parseArguments(String JavaDoc[] argStrings)
1314    {
1315        Hashtable args = new Hashtable();
1316        int delimiter;
1317        String JavaDoc key,value;
1318        for (int i = 0; i<argStrings.length ; i++)
1319        {
1320            delimiter = argStrings[i].indexOf('=');
1321            if (delimiter > -1)
1322            {
1323                key = argStrings[i].substring(0,delimiter);
1324                value = argStrings[i].substring(delimiter+1);
1325                if (value.length() > 0)
1326                {
1327                    args.put(key,value);
1328                }
1329            }
1330            else
1331            {//PropertyFile kann auch ohne den key 'propertyfile=' angegeben werden
1332
args.put("configuration",argStrings[i]);
1333            }
1334        }
1335        return args;
1336    }
1337
1338    /**
1339     * Geht die ganze DocumentRoot durch und sammelt die zur Übertragung bestimmten Dateien
1340     * @param documentRoot die zu verwendende DocumentRoot
1341     * @param siteConfig Name der Datei, in der die Site-Konfiguration steht (z.B. sitedocuments.conf)
1342     * @param targetDir Name des Zielverzeichnisses auf dem Onlinerechner. Einer der beiden Parameter
1343     * siteConfig und siteConfig muss angegeben werden. Sind es beide, so wird nur siteConfig ausgewertet
1344     * @param siteDocumentsListing Name der Datei, in der die Liste der übertragenen Datein gespeichert ist/wird
1345     * @param useConfig wenn true, dann wird die siteConfig zur Auswahl der zu übertragenden Dateien ausgewertet
1346     * sonst werden alle Dateien unter der DocumentRoot übertragen
1347     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1348     */

1349    private String JavaDoc assembleSite(String JavaDoc documentRoot, String JavaDoc siteConfig, String JavaDoc targetDir, String JavaDoc siteDocumentsListing, boolean useConfig)
1350    {
1351        logAndPrint("<b>assembling site</b>");
1352        SiteDocumentsListing oldListing = null;
1353        try
1354        {
1355            oldListing = new SiteDocumentsListing(siteDocumentsListing);
1356        }
1357        catch ( IOException e)
1358        {
1359            logAndPrint("Found no old listing at " + siteDocumentsListing);
1360            CAT.debug("Found no old siteDocumentsListing: " + e.toString());
1361        }
1362        try
1363        {
1364            sitePacker = new SitePacker(documentRoot, siteConfig, targetDir, oldListing, useConfig);
1365        }
1366        catch ( IOException e)
1367        {
1368            return e.toString();
1369        }
1370        return null;
1371    }
1372
1373    /**
1374     * Kopiert alle zur Übertragung bestimmten Dateien in ein temporäres Directory und zippt diese
1375     * @param tempDir das temporäre Verzeichnis, in dem die Dateien gezippt werden
1376     * @param changedOnly wenn true, so werden nur alle seit dem letzten Staging geänderten (->Zeitstempel) Dateien übertragen
1377     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1378     */

1379    private String JavaDoc packSite(String JavaDoc tempDir, boolean changedOnly)
1380    {
1381        if ( reuseZipfile ) //wenn ich das alte Zipfile benutzen kann, brauch ich nich noch mal zu packen
1382
{
1383            return null;
1384        }
1385
1386        logAndPrint("<b>packing site</b>");
1387        //muss zwei freie Namen im tempDir finden (einen für das Sitekopieverzeichnis, einen für das Zip)
1388
File tempSite, zip;
1389        try
1390        {
1391            tempSite = File.createTempFile("webman_site","",new File(tempDir));
1392            tempSite.delete();
1393            CAT.info("Assembling site in temporary directory " + tempSite.getPath());
1394            zip = File.createTempFile("webman",".zip",new File(tempDir));
1395            zip.delete();
1396            CAT.info("Packing site into temporary file " + zip.getPath());
1397        }
1398        catch (IOException e)
1399        {
1400            CAT.debug("Unable to create temporary file in directory " + tempDir,e);
1401            return "Unable to create temporary file in " + tempDir + ": " + e.getMessage();
1402        }
1403        try
1404        {
1405            zippedSite = sitePacker.zipSite(zip.getAbsolutePath(),tempSite.getAbsolutePath(),changedOnly);
1406        }
1407        catch (IOException e)
1408        {
1409            return "Unable to zip site into file " + zip.getAbsolutePath() + NEWLINE + e.toString();
1410        }
1411        deleteFile(tempSite.getAbsolutePath());
1412        return null;
1413    }
1414
1415    /**
1416     * Übermittelt das SiteDocumentsListing
1417     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1418     */

1419    private String JavaDoc transmitSiteInfo()
1420    {
1421        CAT.debug("transmitting site info...");
1422        ObjectOutputStream oos = null;
1423        try
1424        {
1425            oos = new ObjectOutputStream(clientSocket.getOutputStream());
1426            oos.writeObject(sitePacker);
1427            oos.flush();
1428        }
1429        catch (IOException e)
1430        {
1431            return "unable to transmit site documents listing" + NEWLINE + e.toString();
1432        }
1433        return null;
1434    }
1435
1436    /**
1437     * Bereitet die SSL-Verbindung vor
1438     * @param keyStore Dateiname des KeyStores
1439     * @param keyStorePassword Passwort für Validierung des KeyStores
1440     * @param keyPassword Passwort für Zugriff auf (gewünschten) Schlüssel
1441     * @param trustStore Dateiname des TrustStores
1442     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1443     */

1444    private String JavaDoc prepareSSL(String JavaDoc keyStore, String JavaDoc keyStorePassword, String JavaDoc keyPassword, String JavaDoc trustStore)
1445    {
1446        logAndPrint("<b>preparing ssl connection</b>");
1447        try
1448        {
1449            /* Man könnte TrustStore auch über System.setProperty("javax.net.ssl.trustStore",trustStore);
1450             setzen, aber dann funzt die ClientAuthentication irgendwie nich... (obwohl das im JSSE-Example schon funzt) */

1451            com.sun.net.ssl.SSLContext ssl = com.sun.net.ssl.SSLContext.getInstance("SSL");
1452            KeyStore JavaDoc ks = KeyStore.getInstance("JKS");
1453            
1454            com.sun.net.ssl.TrustManagerFactory tmf = com.sun.net.ssl.TrustManagerFactory.getInstance("SunX509");
1455            ks.load(Stager.getResourceInputStream(this.getClass(),trustStore),null);
1456            tmf.init(ks);
1457            logAndPrint("using TrustStore " + markAsFile(trustStore) + " (for server authentication)");
1458            
1459            //KeyManager wird nur gebraucht für ClientAuthentifizierung
1460
com.sun.net.ssl.KeyManagerFactory kmf = null;
1461            if ( !keyStore.equals("") )
1462            {
1463                kmf = com.sun.net.ssl.KeyManagerFactory.getInstance("SunX509");
1464                ks.load(Stager.getResourceInputStream(this.getClass(),keyStore),keyStorePassword.toCharArray());
1465                kmf.init(ks, keyPassword.toCharArray());
1466                logAndPrint("using KeyStore " + markAsFile(keyStore) + " (for client authentication)");
1467            }
1468            
1469            ssl.init((kmf==null ? null : kmf.getKeyManagers()), tmf.getTrustManagers(), null);
1470            //wenn jetzt hier socketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault() stünde, würde das ganze nich richtig funktioneren!
1471
socketFactory = ssl.getSocketFactory();
1472        }
1473        catch (Exception JavaDoc e)
1474        {
1475            return "unable to create ssl socket factory: " + e;
1476        }
1477        return null;
1478    }
1479
1480    /**
1481     * Ruft SiteReceiver auf und stellt die SSL-Verbindung zum ihm her
1482     * @param receiverCGI URL des SiteReceiver-Startskripts
1483     * @param receiverHost Adresse des Rechners, zu dem die SSL-Verbindung aufgebaut wird
1484     * @param receiverPort Port auf dem die SSL-Verbindung aufgebaut wird
1485     * @param userName Benutzername für kennwortgeschützten Aufruf des receiverCGI (null, wenn kein Kennwortschutz)
1486     * @param passWord Passwort für kennwortgeschützten Aufruf des receiverCGI (null, wenn kein Kennwortschutz)
1487     * @param proxyHost Adresse des Proxys (null, wenn kein Proxy)
1488     * @param proxyPort Port des Proxys (null, wenn kein Proxy)
1489     * @param openSocketTimeout Zeit in ms die gewartet wird, bis der Versuch des Vebindungsaufbaus abgebrochen wird
1490     * @param receiverProperties die an den SiteReceiver zu übermittelnden ReceiverProperties
1491     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1492     */

1493    String JavaDoc createConnection(String JavaDoc receiverCGI, String JavaDoc receiverHost, int receiverPort,
1494                            String JavaDoc userName, String JavaDoc passWord, String JavaDoc proxyHost, String JavaDoc proxyPort,
1495                            int openSocketTimeout, Hashtable receiverProperties)
1496    {
1497        logAndPrint("<b>creating connection</b>");
1498        try
1499        {
1500            //Proxy berücksichtigen, falls vorhanden (sonst gibz keine Verbindung)
1501
if ( proxyHost != null && proxyPort != null)
1502            {
1503                System.setProperty("http.proxyHost",proxyHost);
1504                System.setProperty("http.proxyPort",proxyPort);
1505                logAndPrint("using HTTP-Proxy " + proxyHost + ":" + proxyPort);
1506            }
1507        }
1508        catch (Exception JavaDoc e)
1509        {
1510            logAndPrint("Could not set proxy parameters; connection may fail.");
1511        }
1512        
1513        starter = new ServerStarter(receiverCGI, this, userName, passWord, receiverProperties);
1514        starter.start();
1515               
1516        logAndPrint("Start opening socket at " + new java.util.Date JavaDoc());
1517        long start_time = System.currentTimeMillis();
1518        Exception JavaDoc exc = null;
1519        while ( System.currentTimeMillis() - start_time < (long)openSocketTimeout )
1520        {
1521            exc = null;
1522            if ( clientSocket != null && starter.isOK() )
1523            {//starter.isAlive-Abfrage damit nicht noch mal dieser if-zweig durchlaufen wird,
1524
//wenn starter schon gestoppt hat und "SiteReceiver stopped." ausgedruckt hat
1525
//(sieht blöd aus, wenn danach noch einmal "Socket not ready, trying again" kommt
1526
try
1527                {
1528                    // sometimes the firewall opens the socket but closes it
1529
// immediately cause the process on the online server
1530
// is not listening
1531
// readFromSocket returns null in that case
1532
String JavaDoc line = readFromSocket(clientSocket);
1533                    if ( line == null )
1534                    {
1535                        CAT.info("received null instead of ready at " + new java.util.Date JavaDoc());
1536                        logAndPrint("Socket not ready, trying again...");
1537                    }
1538                    else if ( line.indexOf("ready") == -1 )
1539                    {
1540                        return "SiteReceiver did not respond or authentication failed";
1541                    }
1542                    else
1543                    {
1544                        logAndPrint("Connected at " + new java.util.Date JavaDoc() + " on " + clientSocket);
1545                        break;
1546                    }
1547                }
1548                //Fange zuerst die allg. Exception ab, da Stager.readFromSocket immer eine allg. schmeißt,
1549
//auch wenn sie im "innern" eine SSL- oder SocketException ist -> verarbeite am besten alles hier
1550
catch (Exception JavaDoc e)
1551                {
1552                    if (e.getMessage() != null ) //kann auch null sein!
1553
{
1554                        if ( e.getMessage().indexOf("SocketException") > -1 )
1555                        {
1556                            error(e.getMessage());
1557                            if ( e.getMessage().indexOf("Connection aborted by peer: socket write error") > -1 )
1558                            {
1559                                logAndPrint("This error may arise from a failed SSL client authentication");
1560                                logAndPrint("See if SiteReceiver demands SSL client authentication and if so,"
1561                                + " check that KeyStore is specified for SiteTransmitter and that it containes the required certificate.");
1562                                //bei solch einem Fehler funzt die Connection nich -> kann aufhören
1563
return "unable to establish SSL connection";
1564                            }
1565                        }
1566                        else if ( e.getMessage().indexOf("SSLException") > -1 )
1567                        {
1568                            error(e.getMessage());
1569                            if ( e.getMessage().indexOf("untrusted server cert chain") > -1 )
1570                            {
1571                                logAndPrint("Check if the SiteReceiver has the appropriate certificate to authenticate to the SiteTransmitter and vice versa.");
1572                            }
1573                            else
1574                            {
1575                                logAndPrint("Check the SSL configuration!");
1576                            }
1577                            CAT.error("unable to read from socket",e);
1578                            //wenn ich einen SSL-Fehler erhalte, kommt mit Sicherheit keine Connection mehr zu Stande
1579
return "unable to establish SSL connection";
1580                        
1581                        }
1582                    }
1583                    CAT.warn("unable to read from socket",e);
1584                    CAT.info("trying again...");
1585                }
1586            }
1587            if ( ! starter.isOK() )
1588            {
1589                logAndPrint("Connector stopped at " + new java.util.Date JavaDoc());
1590                break;
1591            }
1592            try
1593            {
1594                Thread.sleep(OPEN_SOCKET_WAIT);
1595                clientSocket = (SSLSocket)socketFactory.
1596                                createSocket(InetAddress.getByName(receiverHost), receiverPort);
1597            }
1598            catch (Exception JavaDoc e)
1599            {
1600                exc = e;
1601            }
1602        }
1603        if ( exc != null )
1604        {
1605            logAndPrint("Stopped opening socket at " + new java.util.Date JavaDoc());
1606            return "unable to create ssl socket: " + exc;
1607        }
1608        if ( clientSocket == null )
1609        {
1610            return "socket closed at " + new java.util.Date JavaDoc();
1611        }
1612        try
1613        {
1614            clientSocket.setSoTimeout(0);
1615        }
1616        catch (Exception JavaDoc e)
1617        {
1618            logAndPrint("Stopped opening socket at " + new java.util.Date JavaDoc());
1619            return "unable to set timeout: " + e.toString();
1620        }
1621        if ( !starter.isOK() )
1622        {
1623            return "unable to create ssl socket.";
1624        }
1625        return null;
1626    }
1627    
1628    /**
1629     * Überträgt die Site über die SSL-Verbindung
1630     * @param zip die in ein Zipfile gepackte Site
1631     * @return true, wenn kein Fehler auftrat, andernfalls false
1632     */

1633    private boolean transmitSite(File zip)
1634    {
1635        // sende zipfile
1636
logAndPrint("<b>transmitting site</b>");
1637        try
1638        {
1639            long zipsize = zip.length();
1640            logAndPrint("Sending site (" + zipsize + " bytes)");
1641            logAndPrint("begin: " + (new Date()).toString() + " ");
1642            // sending size of zip
1643
printToSocket(clientSocket, "zip.size=" + zipsize);
1644            FileInputStream fin = new FileInputStream(zip);
1645            BufferedOutputStream out = new BufferedOutputStream(clientSocket.getOutputStream());
1646            
1647            byte[] buf = new byte[BUFSIZE];
1648            int read;
1649            while ( (read = fin.read(buf, 0, BUFSIZE)) != -1)
1650            {
1651                out.write(buf, 0, read);
1652            }
1653            out.flush();
1654            logAndPrint(" end: " + (new Date()).toString());
1655            logAndPrint("<b>... done</b><BR><BR>");
1656            fin.close();
1657            zip.delete();
1658        }
1659        catch (Exception JavaDoc e)
1660        {
1661            error("Unable to transmit zip file",e);
1662            return false;
1663        }
1664        return true;
1665    }
1666
1667    /**
1668     * Empfängt das log vom SiteReceiver
1669     * @return Mögliche Fehlermeldungen. Es wird null returnt, wenn kein Fehler auftrat.
1670     */

1671    private String JavaDoc receiveLog()
1672    {
1673        CAT.debug("receiving log...");
1674        BufferedReader in = null;
1675        String JavaDoc last = null, line = null;
1676        Vector log = new Vector();
1677        int lineCount = 0;
1678        
1679        try
1680        {
1681            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
1682            while ( (line = in.readLine()) != null )
1683            {
1684                lineCount++;
1685                if ( line.startsWith("abort") )
1686                {
1687                    starter.setLog(log);
1688                    throw new Exception JavaDoc("SiteReceiver aborted operation due to an error.");
1689                }
1690                last = line;
1691                log.add(line);
1692            }
1693            starter.setLog(log);
1694            if ( last == null || !last.startsWith("end") )
1695            {
1696                throw new Exception JavaDoc("SiteReveiver did not finish log transmission.");
1697            }
1698        }
1699        catch (Exception JavaDoc e)
1700        {
1701            return e.toString();
1702        }
1703        return null;
1704    }
1705
1706    /**
1707     * gibt eine kurze Hilfe zum Aufruf des SiteTransmitters aus
1708     */

1709    protected void printUsage()
1710    {
1711        print("Usage: SiteTransmitter [[configuration=]<propertyFile>] [showlog=true] [port=<port>]");
1712    }
1713   
1714    /**
1715     * löscht vollständig Dateien/Verzeichnisse
1716     * @param name Name der/des zu löschenden Datei/Verzeichnisses
1717     */

1718    protected void deleteFile(String JavaDoc name)
1719    {
1720        File f = new File(name);
1721        if ( f.exists() )
1722        {
1723            if ( f.isDirectory() )
1724            {
1725                String JavaDoc[] list = f.list();
1726                for ( int i = 0; i < list.length; i++ )
1727                {
1728                    deleteFile(name + File.separator + list[i]);
1729                }
1730            }
1731            f.delete();
1732        }
1733    }
1734    
1735    // ============ logging funktionen =================
1736
/**
1737     * gibt das Log aus und wartet dabei MAX_SHOW_TIME ms auf das Log-Ende (LOG_END_TAG)
1738     * @param filename Dateiname des Logfiles
1739     * @see SiteTransmitter#MAX_SHOW_TIME
1740     */

1741    protected void showLog(String JavaDoc filename)
1742    {
1743        CAT.info("showing log...");
1744        try
1745        {
1746            Vector tempLogBuffer = new Vector(INITIAL_TEMP_LOG_BUFFER_CAPACITY);
1747            boolean end_reached = false;
1748            boolean appendedLog = false; //zeigt an, ob mehr als ein log in einer Datei ist
1749
int skip = 0;
1750            File file = new File(filename);
1751            long startTime = System.currentTimeMillis();
1752            print("<H2>Showing Log (" + markAsFile(filename) + ")</H2>");
1753            while ( !end_reached && System.currentTimeMillis() - startTime < MAX_SHOW_TIME )
1754            {
1755                Thread.sleep(SLEEP_TIME);
1756                BufferedReader in = new BufferedReader(new FileReader(filename));
1757                // skipping some lines
1758
// for ( int i = 0; i < skip; i++)
1759
// {
1760
// in.readLine();
1761
// }
1762
String JavaDoc line = null;
1763                while ( (line = in.readLine()) != null )
1764                {
1765                    if ( line.indexOf(LOG_END_TAG) == -1 )
1766                    {
1767                        skip++;
1768                        tempLogBuffer.add(line);
1769                    }
1770                    else
1771                    {
1772                        line = in.readLine();
1773                        if ( line != null ) //falls noch ein weiteres log folgt
1774
{// -> logs wurden appended; will nur letztes betrachten
1775
appendedLog = true;
1776                            tempLogBuffer = new Vector(INITIAL_TEMP_LOG_BUFFER_CAPACITY);
1777                            skip++;
1778                            tempLogBuffer.add(line);
1779                        }
1780                        else //log ist zu Ende
1781
{
1782                            end_reached = true;
1783                            break;
1784                        }
1785                    }
1786                }
1787                //wenn ich nichts mehr lesen kann (->line==null) und offenbar nur ein log in der Datei ist
1788
//dann muss ich am Ende sein, auch wenn das End_Tag noch nicht erreicht wurde
1789
//das kann ja passieren, wenn sich der Stager irgendwie aufgehängt hat/nicht fertig wurde
1790
if ( !end_reached && !appendedLog )
1791                {
1792                    //dann geb ich erstmal schon das aus, was da ist, sonst muss man so lange warten
1793
while ( tempLogBuffer.size() > 0 )
1794                    {//entferne alle vorhandenen Strings, damit die nachher nicht nochmal angezeigt wird
1795
print((String JavaDoc)tempLogBuffer.remove(0) + NEWLINE);
1796                    }
1797                    //wenn das log schon alt ist bzw. schon MAX_SHOW_TIME lang angezeigt wurde, dann erkläre ich es für geschlossen
1798
if ( (System.currentTimeMillis() - file.lastModified() > SHOW_LOG_TIMEOUT)
1799                        || (System.currentTimeMillis() - startTime > MAX_SHOW_TIME) )
1800                     
1801                    {
1802                        tempLogBuffer.add(NEWLINE + NEWLINE + "...[log has not been properly finished]");
1803                        log("...[log has not been properly finished]");
1804                        closeLog();
1805                        end_reached = true;
1806                    }
1807                }
1808            }
1809            for ( int i=0; i<tempLogBuffer.size(); i++ )
1810            {
1811                print((String JavaDoc)tempLogBuffer.elementAt(i) + NEWLINE);
1812            }
1813        }
1814        catch (Exception JavaDoc e)
1815        {
1816            error("Error while reading logfile",e);
1817            if ( e instanceof FileNotFoundException )
1818            {
1819                print("Note: This may indicate that the referring staging process was not performed, maybe due to a wrong configuration. ");
1820            }
1821            fehler = true;
1822        }
1823    }
1824
1825    /**
1826     * Testet, ob das Log schon beendet wurde. Dabei gilt das Log als beendet,
1827     * wenn es in den letzten SHOW_LOG_TIMEOUT ms nicht verändert wurde
1828     * @param filename Dateiname des Logfiles
1829     * @return true, wenn das LogFile beendet (oder entsprechend "veraltet" ist, andernfalls false
1830     * @see SiteTransmitter#SHOW_LOG_TIMEOUT
1831     */

1832    protected boolean logFinished(String JavaDoc filename)
1833    {
1834        try
1835        {
1836            File f = new File(filename);
1837            if ( !f.exists() )
1838            {
1839                return true;
1840            }
1841            // wenn das log das letzte Mal vor mehr als SHOW_LOG_TIMEOUT angefasst wurde
1842
// dann gibt es einen inaktiven laufenden SiteTransmitter
1843
if ( System.currentTimeMillis() - f.lastModified() > SHOW_LOG_TIMEOUT )
1844            {
1845                return true;
1846            }
1847            BufferedReader in = new BufferedReader(new FileReader(f));
1848            String JavaDoc line = null,
1849            lastLine = null;
1850            // geh zur letzten Zeile
1851
while ((line = in.readLine()) != null)
1852            {
1853                lastLine = line;
1854            }
1855            return lastLine == null || lastLine.indexOf(LOG_END_TAG) > -1;
1856        }
1857        catch (Exception JavaDoc e)
1858        {
1859            print("Error while reading logfile: " + e);
1860            CAT.error("Error while reading logfile",e);
1861        }
1862        return true;
1863    }
1864
1865    /**
1866     * Schließt das Logfile, wobei das LOG_END_TAG ans Ende geschrieben wird
1867     */

1868    protected void closeLog()
1869    {
1870        log(LOG_END_TAG);
1871        super.closeLog();
1872    }
1873            
1874    // =============== html output ================
1875
/**
1876     * Schreibt den Seitenanfang für die HTML-Ausgabe
1877     * @param title der in der Titelleite des Browsers anzuzeigende Text
1878     */

1879    private void printHeader(String JavaDoc title)
1880    {
1881        print("<HTML><HEAD>"
1882                               + "<TITLE>" + title + "</TITLE>"
1883                               + "</HEAD><BODY BGCOLOR=#FFFFFF TEXT=#000000>"
1884                               + "<FONT FACE=Geneva, Arial, sans-serif>"
1885                               + "<H1>WebMan Stager: SiteTransmitter</H1>"
1886                               + "Java version: " + System.getProperty("java.version")
1887                               + ", Java vendor: " + System.getProperty("java.vendor")
1888                               + ", SiteTransmitter-Version: " + INTERNAL_VERSION + "<BR>");
1889    }
1890    
1891    /**
1892     * Schreibt das Seitenende für die HTML-Ausgabe
1893     */

1894    private void printFooter()
1895    {
1896        print("</FONT></FONT></BODY></HTML>");
1897    }
1898    
1899    /**
1900     * den RECEIVER_OUTPUT_MARKER (insbesondere dessen Leerzeichen) HTML-kompatibel umsetzen
1901     * @param str der umzusetzende Text
1902     * @see ServerStarter#RECEIVER_OUTPUT_MARKER
1903     * @return der umgesetzte Text
1904     */

1905    private String JavaDoc mapReceiverOutputMarker(String JavaDoc str)
1906    {
1907        String JavaDoc result = str;
1908        String JavaDoc tag="";
1909        if ( str.startsWith(starter.RECEIVER_OUTPUT_MARKER) )
1910        {
1911            result = str.substring(starter.RECEIVER_OUTPUT_MARKER.length());
1912            //falls string ein <h?>- oder <b>-Tag enthält, muss der receiver_output_marker dahinter!
1913
if ( result.trim().toLowerCase().startsWith("<h") || result.trim().toLowerCase().startsWith("<b") )
1914            {
1915                tag = result.substring(0,result.indexOf(">") + 1);
1916                result = result.substring(result.indexOf(">") + 1);
1917            }
1918            //nachdem merker abgeschnitten wurde, html-kompatibel wieder ansetzen
1919
for ( int i=0; i<starter.RECEIVER_OUTPUT_MARKER.length(); i++)
1920            {
1921                if ( starter.RECEIVER_OUTPUT_MARKER.charAt(i) == ' ' )
1922                {
1923                    result = "&nbsp;" + result;
1924                }
1925                else
1926                {
1927                    result = starter.RECEIVER_OUTPUT_MARKER.charAt(i) + result;
1928                }
1929            }
1930        }
1931        return tag + result;
1932    }
1933            
1934    /**
1935     * Schreibt eine Zeichenkette HTML-kompatibel in die (HTML-)Ausgabe
1936     * @param str der auszugebende Text
1937     */

1938    private void print(String JavaDoc str)
1939    {
1940        StringTokenizer tokens = new StringTokenizer(str,NEWLINE);
1941        while ( tokens.hasMoreElements() )
1942        {
1943            outStream.println(mapReceiverOutputMarker(tokens.nextToken()) + "<BR>");
1944        }
1945        outStream.flush();
1946    }
1947    
1948    /**
1949     * Schreibt eine Zeichenkette sowohl in die (HTML-)Ausgabe wie auch in das Logfile
1950     * @param line der auszugebene Text
1951     */

1952    protected void logAndPrint(String JavaDoc line)
1953    {
1954        print(line);
1955        log(line);
1956    }
1957}
1958
1959
1960/**
1961 * Liest eine URL (SiteReceiver-CGI oder asp) aus und startet damit den SiteReceiver
1962 * Die HTTP-Ausgabe wird hier empfangen, verarbeitet und ausgegeben
1963 * @author $Author: torsten $
1964 * @version $Revision: 1.56.2.2 $
1965 */

1966class ServerStarter extends Thread JavaDoc
1967{
1968    /**dient zur Synchronisation; wird von SiteTransmitter aus gecheckt*/
1969    Object JavaDoc lock = new Object JavaDoc();
1970    /**kennzeichnet fehlerfreie Abarbeitung; wird von SiteTransmitter aus gecheckt*/
1971    boolean success = true;
1972    
1973    /**Server-Adresse von aufzurufender URL*/
1974    private String JavaDoc server = null;
1975    /**Benutzername bei kennwortgeschützter URL*/
1976    private String JavaDoc user = null;
1977    /**Passwort bei kennwortgeschützter URL*/
1978    private String JavaDoc pass = null;
1979    /**liest die URL aus*/
1980    private BufferedReader in = null;
1981    /**speichert das Gelesene zwischen*/
1982    private Vector buffer = new Vector();
1983    /**die zu übermittelende ReceiverProperties*/
1984    private Hashtable receiverProperties;
1985    /**zeigt an, ob bereits begonnen wurde, das Gelesene im SiteTransmitter auszugeben*/
1986    private boolean outputStartet = false;
1987    /**Referenz auf den (aufrufenden) SiteTransmitter*/
1988    private SiteTransmitter caller = null;
1989    /**Dient der Abspeicherung des empfangenen SiteReceiver-Logs*/
1990    private Vector receiverLog = new Vector();
1991    /**Sobald der ServerStarter gestartet wurde, gibt ok an, ob er erfolgreich arbeitet/gearbeitet hat*/
1992    private boolean ok = true;//muss gleich true sein, da der SiteTransmitter kurz nach dem Start des ServerStarter
1993
//schon isOK() abfragt, aber da ist wohl die Threadinitialisierung noch nicht so weit, dass in run() "ok=true" erreicht wurde,
1994
//so dass ok noch false wäre und der SiteTransmitter alles abbricht!
1995

1996    /**Um in der (HTML-)Ausgabe den SiteReceiver-Output vom Rest zu unterscheiden*/
1997    public final static String JavaDoc RECEIVER_OUTPUT_MARKER = " > ";
1998    /**Log4J-Kategorie*/
1999    private final static Category CAT = Category.getInstance(ServerStarter.class);
2000
2001    /**
2002     * Konstruiert ServerStarter
2003     * @param server_url die aufzurufende URL
2004     * @param caller der aufrufende SiteTransmitter
2005     * @param userName Benutzername, falls server_url kennwortgeschützt ist (sonst null)
2006     * @param passWord Passwort, falls server_url kennwortgeschützt ist (sonst null)
2007     * @param receiverProperties die per ULR-Stringparamter an den SiteReceiver zu übermittelnden Properties
2008     */

2009    ServerStarter(String JavaDoc server_url, SiteTransmitter caller, String JavaDoc userName, String JavaDoc passWord, Hashtable receiverProperties)
2010    {
2011        server = server_url;
2012        this.caller = caller;
2013        this.user = userName;
2014        this.pass = passWord;
2015        this.receiverProperties = receiverProperties;
2016    }
2017
2018    /**
2019     * Eigentliche Ausführroutine des ServerStarter
2020     */

2021    public void run()
2022    {
2023        synchronized( lock )
2024        {
2025            boolean done = false; //noch bin ich nicht fertig ;)
2026
ok = true; //bin am arbeiten
2027
CAT.debug("running ServerStarter");
2028            String JavaDoc line;
2029            //falls receiver-properties definiert wurden, werden die als URLQueryString mitgeschickt
2030
if ( receiverProperties.size() > 0 )
2031            {
2032                Enumeration keys = receiverProperties.keys();
2033                server += "?";
2034                String JavaDoc key;
2035                while ( keys.hasMoreElements() )
2036                {
2037                    key = (String JavaDoc)keys.nextElement();
2038                    server += URLEncoder.encode(key.substring("Receiver".length())) + "="
2039                            + URLEncoder.encode((String JavaDoc)receiverProperties.get(key));
2040                    if ( keys.hasMoreElements() )
2041                    {
2042                        server += "&";
2043                    }
2044                }
2045                caller.logAndPrint("Submitting receiver properties: URL=" + server);
2046            }
2047            
2048            URL start_receiver = null;
2049            try
2050            {
2051                start_receiver = new URL(server);
2052            }
2053            catch (java.net.MalformedURLException JavaDoc e)
2054            {
2055                caller.error("Bad URL format: " + server);
2056                return;
2057            }
2058            HttpURLConnection uc = null;
2059            try
2060            {
2061                uc = (HttpURLConnection)start_receiver.openConnection();
2062            }
2063            catch (IOException e)
2064            {
2065                caller.error("Cannot open connection to: " + uc + ": " + e.toString());
2066            }
2067            try
2068            {
2069            // authentication
2070
if ( user != null && user.length() > 0 && pass != null )
2071                {
2072                    String JavaDoc userPassword = user + ":" + pass;
2073                    String JavaDoc encoding = new sun.misc.BASE64Encoder().encode (userPassword.getBytes());
2074                    uc.setRequestProperty ("Authorization", "Basic " + encoding);
2075                    caller.logAndPrint("prepared authentication - done");
2076                }
2077                boolean retry = false;
2078                do
2079                {
2080                    try
2081                    {
2082                        CAT.debug("run(): now getting InputStream");
2083                        long start = new Date().getTime();
2084                        in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
2085                        long end = new Date().getTime();
2086                        CAT.debug("run(): getting InputStream took " + (end - start) + " ms.");
2087                        retry = false; //wenn ich hier bin, ist die "fragile" Phase vorbei
2088
}
2089                    catch (NullPointerException JavaDoc n)
2090                    {
2091                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
2092                        n.printStackTrace(new PrintStream(baos));
2093                        if ( baos.toString().indexOf("sun.net.www.http.ChunkedInputStream.readChunkSize") > -1 )
2094                        {//diese Exception kommt öfters, hat aber offenbar nichts schlimmes zu bedeuten (JDK-Bug)
2095
//beim zweiten "Anlauf" sollte alles funktionieren
2096
CAT.warn("run(): NPE in readChunkSize() while getting InputStream from socket");
2097                            retry = true;
2098                        }
2099                        else
2100                        {
2101                            throw n;
2102                        }
2103                    }
2104                } while ( retry );
2105                CAT.debug("run(): got InputStream");
2106                //wenn InputStream erhalten, ist die nächste "fragile" Phase das Auslesen...
2107
int lineCount = 0;
2108                do
2109                {
2110                    try
2111                    {
2112                        while ( (line = in.readLine()) != null )
2113                        {
2114                            lineCount++;
2115                            if ( line.startsWith("abort") )
2116                            {
2117                            // receiver hat abgebrochen
2118
success = false;
2119                                caller.error("SiteReceiver has aborted");
2120                                break;
2121                            }
2122                            if ( line.equals("end of http output") )
2123                            {
2124                                CAT.info("run(): SiteReceiver has ended http output");
2125                                break;
2126                            }
2127                            if ( line.startsWith("end") )
2128                            {
2129                            // receiver is fertig
2130
caller.logAndPrint("SiteReceiver has ended");
2131                                break;
2132                            }
2133                            if ( buffer != null )
2134                            {
2135                                buffer.add(line);
2136                            }
2137                            else
2138                            {
2139                                caller.logAndPrint(line);
2140                            }
2141                        }
2142                        retry = false; //wenn ich hier bin, ist die "fragile" Phase vorbei
2143
CAT.debug("run(): read " + lineCount + " lines. leaving read-in-loop...");
2144                    }
2145                    catch (NullPointerException JavaDoc n)
2146                    {
2147                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
2148                        n.printStackTrace(new PrintStream(baos));
2149                        if ( baos.toString().indexOf("sun.net.www.http.ChunkedInputStream.readChunkSize") > -1 )
2150                        {//diese Exception kommt öfters, hat aber offenbar nichts schlimmes zu bedeuten (JDK-Bug)
2151
//beim zweiten "Anlauf" sollte alles funktionieren
2152
CAT.warn("run(): NPE in readChunkSize() while reading from socket in ServerStarter.run()");
2153                            retry = true;
2154                        }
2155                        else
2156                        {
2157                            throw n;
2158                        }
2159                    }
2160                } while ( retry );
2161                CAT.debug("run(): closing InputStream...");
2162                //wenn ich bis hier gekommen ist, is alles OK
2163
done = true;
2164                in.close();
2165            }
2166            catch (FileNotFoundException e)
2167            {
2168                //muss response über Header auslesen, da getResponseCode()/getResponseMessage nicht funzen!!
2169
String JavaDoc response = uc.getHeaderField(0);//erstes HeaderField enthält HTTP-Status
2170
response = response.substring(response.indexOf(" ") + 1);//den Teil "HTTP/1.1 " abschneiden
2171
if ( response.startsWith("404") )
2172                {
2173                    caller.error(server + " not found! Possibly the URL is misspelled (note that the filename part of an URL may be case sensitive.)");
2174                }
2175                else if ( response.startsWith("403") )
2176                {
2177                    caller.error(server + " is a forbidden URL. Check the web server/filesystem-permissions for this URL!");
2178                }
2179                else if ( response.startsWith("5") )
2180                {
2181                    caller.error(server + " generated an Internal Server Error.");
2182                    caller.error("This indicates a wrong CGI-processing, so you should check the cgi-file and related configuration files.");
2183                    caller.error("It is also possible that the cgi-file has not the proper permissions for reading/execution.");
2184                }
2185                else if ( response.startsWith("401") )
2186                {
2187                    caller.error("You're not authorized to call " + server);
2188                    caller.error("Check these properties: TargetCGIPasswordProtected, TargetCGIUser, TargetCGIPassword (for this URL)!");
2189                }
2190                else
2191                {
2192                    caller.error("Error while calling " + server + " - HTTP-Response: " + response);
2193                }
2194                CAT.error("run(): HTTP-Response: " + response);
2195                //mehr kann man leider nicht machen (z.B. errorStream auslesen -> der ist IMMER null!! (Java-Bug)
2196
}
2197            catch (java.net.UnknownHostException JavaDoc e)
2198            {
2199                caller.error("Server not found: " + serverPart(server));
2200                caller.error("Either the URL is misspelled, or the server is not online or reachable.");
2201            }
2202            catch ( ConnectException c )
2203            {
2204                caller.error("Couldn't connect to " + serverPart(server) + ".");
2205                caller.error("There is probably no web server running at this URL.");
2206                CAT.error("run(): " + c);
2207            }
2208            catch (Exception JavaDoc e)
2209            {
2210                caller.error("Unknown exception: " + e.toString());
2211                ByteArrayOutputStream baos = new ByteArrayOutputStream();
2212                e.printStackTrace(new PrintStream(baos));
2213                CAT.error("run(): " + baos.toString());
2214            }
2215            finally
2216            {
2217                ok = done;
2218            }
2219        }
2220    }
2221
2222    /**
2223     * entfernt "http://" und Dateipfad aus einer URL, so dass nur der Rechnername bleibt
2224     * @param url die zu bearbeitende URL
2225     * @return die bearbeitete URL
2226     */

2227    public static String JavaDoc serverPart(String JavaDoc url)
2228    {
2229        String JavaDoc result = url;
2230        if ( url.indexOf("//") > -1 )
2231        {//vorabfrage muss sein, da sonst indexOf("//") + 2 == 1 ist, falls "//" nicht vorhanden
2232
//->erstes Zeichen würde dann abgeschnitten, obwohl Anfang der Zeichenkette ja so bleiben kann
2233
result = url.substring(url.indexOf("//") + 2);
2234        }
2235        int ende1 = result.indexOf("/");
2236        if ( ende1 == -1 )
2237        {
2238            ende1 = result.length();
2239        }
2240        int ende2 = result.indexOf(":"); //falls eine Portnummer angegeben wurde
2241
if ( ende2 == -1 )
2242        {
2243            ende2 = result.length();
2244        }
2245        return result.substring(0,ende1 < ende2 ? ende1 : ende2);
2246    }
2247    
2248    /**
2249     * @return true, wenn der Thread noch arbeitet bzw. wenn er fehlerfrei gearbeitet hat
2250     */

2251    public boolean isOK()
2252    {
2253        return ok;
2254    }
2255    
2256    /**
2257     * Startet die SiteTransmitter-Ausgabe des vom URL-Aufruf Gelesenen (falls noch nicht gestartet)
2258     * @see SiteTransmitter#logAndPrint(String)
2259     */

2260    public void startOutput()
2261    {
2262        synchronized ( lock )
2263        {
2264            CAT.debug("startOutput()...");
2265            if ( outputStartet )
2266            {
2267                return;
2268            }
2269            outputStartet = true;
2270            if ( buffer != null )
2271            {
2272                for ( int i = 0; i < buffer.size(); i++ )
2273                {
2274                    caller.logAndPrint(RECEIVER_OUTPUT_MARKER + (String JavaDoc)buffer.get(i));
2275                }
2276                buffer = null;
2277            }
2278            // drucke Rest vom Log aus
2279
for ( int i = 0; i < receiverLog.size(); i++ )
2280            {
2281                caller.logAndPrint(RECEIVER_OUTPUT_MARKER + (String JavaDoc)receiverLog.get(i));
2282            }
2283        }
2284    }
2285
2286    /**
2287     * gibt an, ob schon etwas von der Ausgabe der aufgerufenen URL gelesen wurde
2288     * @return true, wenn schon Daten eingetroffen sind, ansonsten false
2289     */

2290    public boolean gotReceiverOutput()
2291    {
2292        return (buffer.size() > 0) || (receiverLog.size() > 0);
2293    }
2294    
2295    /**
2296     * Das eigene SiteReceiver-Log wird durch das übergebene ersetzt
2297     * @param log das neue Sitereceiver-Log
2298     */

2299    public void setLog(Vector log)
2300    {
2301        receiverLog = log;
2302    }
2303}
2304    
Popular Tags