1 package de.tivsource.lib.jcyradm;
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.io.PrintStream;
9 import java.math.BigDecimal;
10 import java.net.Socket;
11 import java.util.HashMap;
12 import java.util.Locale;
13 import java.util.Map;
14 import java.util.Properties;
15 import java.util.ResourceBundle;
16 import java.util.regex.Pattern;
17
18 import javax.net.ssl.SSLSocket;
19 import javax.net.ssl.SSLSocketFactory;
20
21 import org.apache.log4j.Logger;
22
23 import de.tivsource.lib.jcyradm.exception.AuthenticationFailure;
24 import de.tivsource.lib.jcyradm.exception.MailboxExists;
25 import de.tivsource.lib.jcyradm.exception.NoLogMessagesFile;
26 import de.tivsource.lib.jcyradm.exception.NoMailbox;
27 import de.tivsource.lib.jcyradm.exception.NoPropertiesFile;
28 import de.tivsource.lib.jcyradm.exception.NoQuota;
29 import de.tivsource.lib.jcyradm.exception.NoServerAnswerFile;
30 import de.tivsource.lib.jcyradm.exception.NoServerResponse;
31 import de.tivsource.lib.jcyradm.exception.NoServerStream;
32 import de.tivsource.lib.jcyradm.exception.NoValidMailboxName;
33 import de.tivsource.lib.jcyradm.exception.QuotaNotInitialized;
34 import de.tivsource.lib.jcyradm.exception.UnexpectedExtraArguments;
35 import de.tivsource.lib.jcyradm.exception.UnexpectedServerAnswer;
36
37 /**
38 * JCyrAdm ist eine Libary die dazu dient eine Verbindung mit einem
39 * Cyrus-Imap-Server herzustellen und um dann Verwaltungsoperationen
40 * auszuführen (createMailbox, removeMailbox, etc. ).
41 *
42 * @author Marc Michele
43 *
44 */
45 public class JCyrAdm {
46
47 /**
48 * Statischer Logger der Klasse JCyrAdm, zur Zeit gibt es Meldungen vom
49 * Type INFO, TRACE und DEBUG.
50 */
51 private static final Logger LOGGER = Logger.getLogger(JCyrAdm.class);
52
53 /**
54 * Der Standard Imap-Port.
55 */
56 private static final int DEFAULT_IMAP_PORT = 143;
57
58 /**
59 * Der Standard Imap-SSL-Port.
60 */
61 private static final int DEFAULT_IMAP_SSL_PORT = 993;
62
63 /**
64 * Die Standard Properties Datei.
65 */
66 private static final String DEFAULT_PROPERTIES_FILE = "jcyradm.properties";
67
68 /**
69 * Cyrus Imap-Host zu dem die Verbindung aufgebaut werden soll.
70 */
71 private String host = "localhost";
72
73 /**
74 * Port auf dem der Cyrus Server lauscht.
75 */
76 private Integer port;
77
78 /**
79 * Default ACL.
80 */
81 private String allacl = "lrswipcda";
82
83 /**
84 * Administrator mit dem die Verbindung aufgebaut werden soll.
85 */
86 private String administrator;
87
88 /**
89 * Passwort des Administrators.
90 */
91 private String password;
92
93 /**
94 * Belegter Speicherplatz der Mailbox.
95 */
96 private BigDecimal used;
97
98
99 /**
100 * Zugeordneter Speicherplatz der Mailbox.
101 */
102 private BigDecimal quota;
103
104 /**
105 * Prozentuale Belegung der Mailbox.
106 */
107 private BigDecimal load;
108
109 /**
110 * Willkommens-Nachricht des Servers.
111 */
112 private String welcomeMsg;
113
114 /**
115 * SSL-Socket-Verbindungs-Objekt.
116 */
117 private SSLSocket sslRequestSocket;
118
119 /**
120 * Socket-Verbindungs-Objekt.
121 */
122 private Socket requestSocket;
123
124 /**
125 * Der Stream mit dem zu Server geschrieben wird.
126 */
127 private PrintStream out;
128
129 /**
130 * Der Stream mit dem vom Server gelesen wird.
131 */
132 private BufferedReader in;
133
134 /**
135 * Map mit den ACLs der aktuellen Mailbox (User/ACL).
136 */
137 private Map<String, String> acls;
138
139 /**
140 * Map mit den Rückgabewerten des ID Kommandos.
141 */
142 private Map<String, String> idMap = new HashMap<String, String>();
143
144 /**
145 * Property Datei in der die Einstellungen gespeichert werden.
146 */
147 private Properties props;
148
149 /**
150 * Datei mit den erwarteten Server-Anworten.
151 */
152 private ResourceBundle serverAnswers;
153
154 /**
155 * Datei mit den Log-Nachrichten.
156 */
157 private ResourceBundle logMessages;
158
159 /**
160 * Standard Konstruktor der Klasse JCyrAdm, dabei wird die interne
161 * Properties-Datei benutzt.
162 *
163 * @throws NoPropertiesFile - Ausnahme wenn die Properties-Datei nicht
164 * gefunden wird.
165 * @throws NoServerAnswerFile
166 * @throws NoLogMessagesFile
167 */
168 public JCyrAdm() throws NoPropertiesFile, NoServerAnswerFile,
169 NoLogMessagesFile {
170 super();
171 LOGGER.debug("Aktuelle Sprache: " + Locale.getDefault().getLanguage());
172 props = new Properties();
173
174 try {
175 LOGGER.debug("Lade Standard Properties Datei.");
176 InputStream inputStream = getClass().getClassLoader()
177 .getResourceAsStream(DEFAULT_PROPERTIES_FILE);
178 props.load(inputStream);
179 inputStream.close();
180 } catch (Exception e1) {
181 throw new NoPropertiesFile();
182 }
183
184 try {
185 LOGGER.debug("Lade Server Antworten Datei.");
186 serverAnswers = ResourceBundle.getBundle("server");
187 } catch (Exception e2) {
188 throw new NoServerAnswerFile();
189 }
190
191 try {
192 LOGGER.debug("Lade Log-Nachrichten Datei.");
193 logMessages = ResourceBundle.getBundle("logging");
194 } catch (Exception e3) {
195 throw new NoLogMessagesFile();
196 }
197
198 } // Ende JCyrAdm()
199
200 /**
201 * Konstruktor der Klasse JCyrAdm, es muss eine Properties-Datei angegeben
202 * werden.
203 *
204 * @param properties - Properties-Datei
205 * @throws NoPropertiesFile - Ausnahme wenn die Properties-Datei nicht
206 * gefunden wird.
207 * @throws NoServerAnswerFile
208 * @throws NoLogMessagesFile
209 */
210 public JCyrAdm(String properties) throws NoPropertiesFile,
211 NoServerAnswerFile, NoLogMessagesFile {
212 super();
213 LOGGER.debug("Aktuelle Sprache: " + Locale.getDefault().getLanguage());
214 props = new Properties();
215
216 try {
217 LOGGER.debug("Lade Properties Datei.");
218 InputStream inputStream = new FileInputStream(properties);
219 props.load(inputStream);
220 inputStream.close();
221 } catch (Exception e1) {
222 throw new NoPropertiesFile();
223 }
224
225 try {
226 LOGGER.debug("Lade Server Antworten Datei.");
227 serverAnswers = ResourceBundle.getBundle("server");
228 } catch (Exception e2) {
229 throw new NoServerAnswerFile();
230 }
231
232 try {
233 LOGGER.debug("Lade Log-Nachrichten Datei.");
234 logMessages = ResourceBundle.getBundle("logging");
235 } catch (Exception e3) {
236 throw new NoLogMessagesFile();
237 }
238
239 }// Ende JCyrAdm(String properties)
240
241 /**
242 * Methode um eine Verbindung zum Server aufzubauen, es muss der Parameter
243 * "ssl" gesetzt werden. Wenn TRUE übergeben wird dann wird eine
244 * SSL-Verbindung zum angebenen Port aufgebaut.
245 *
246 * @param ssl - Boolean mit dem zwischen SSL und Plain umgeschaltet wird.
247 * @throws IOException - Unbekannter Host oder Unmöglich den Stream zu
248 * öffnen
249 */
250 public final void connect(final Boolean ssl) throws IOException {
251 LOGGER.debug(logMessages.getString("logger.trace.connect"));
252 if (ssl) {
253 LOGGER.trace("öffne Verschlüsselte Verbindung");
254 if (isNull(port)) {
255 port = DEFAULT_IMAP_SSL_PORT;
256 }
257 SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
258 .getDefault();
259 sslRequestSocket = (SSLSocket) factory.createSocket(host, port);
260 out = new PrintStream(sslRequestSocket.getOutputStream());
261 out.flush();
262 in = new BufferedReader(new InputStreamReader(
263 sslRequestSocket.getInputStream()));
264 } else {
265 LOGGER.trace("öffne Ungesicherte Verbindung");
266 if (isNull(port)) {
267 port = DEFAULT_IMAP_PORT;
268 }
269 requestSocket = new Socket(host, port);
270 out = new PrintStream(requestSocket.getOutputStream());
271 out.flush();
272 in = new BufferedReader(new InputStreamReader(
273 requestSocket.getInputStream()));
274
275 }
276 welcomeMsg = in.readLine();
277 LOGGER.debug("Server >| " + welcomeMsg);
278 } // Ende connect()
279
280 /**
281 * Methode um die Verbindung zum Server zu trennen.
282 *
283 * @throws IOException - wenn der Stream schon geschlossen ist oder
284 * Verbindung abgelaufen ist.
285 */
286 public final void disconnect() throws IOException {
287 LOGGER.trace(logMessages.getString("logger.trace.disconnect"));
288 if (sslRequestSocket != null) {
289 LOGGER.trace("schließe Verschlüsselte Verbindung");
290 sslRequestSocket.close();
291 } else {
292 LOGGER.trace("schließe Ungesicherte Verbindung");
293 requestSocket.close();
294 }
295 } // disconnect()
296
297 /**
298 * Unfertige Methode !!!! Diese Methode muss dringent überarbeitet werden.
299 * Holt die Capability und setzt die Default-ACLs. .
300 *
301 * @throws IOException - InputStream/OutputStream geschlossen oder nicht
302 * vorhanden
303 */
304 public final void capability() throws IOException {
305 LOGGER.trace("capability() aufgerufen.");
306 sendCommand(". capability");
307 String line = in.readLine();
308 LOGGER.debug("Server >| " + line);
309 //System.out.println("Server >| " + line);
310 line = in.readLine();
311 LOGGER.debug("Server >| " + line);
312 //System.out.println("Server >| " + line);
313
314 // // TODO Hier mus noch die Acl Abfrage hin ist jetzt von Hand gesetzt
315 allacl = "lrswipkxtecda";
316 }
317
318 /**
319 * Mit dieser Methode wird der Administrationsbenutzer am Server
320 * angemeldet.
321 *
322 * @throws NoServerResponse - Keine Antwort vom Server erhalten.
323 * @throws UnexpectedServerAnswer - Unerwartete Antwort vom Server.
324 * @throws AuthenticationFailure
325 */
326 public final void login() throws NoServerResponse, UnexpectedServerAnswer, AuthenticationFailure {
327 LOGGER.trace("login() aufgerufen.");
328 sendCommand(". login \"" + administrator + "\" \"" + password + "\"");
329 try {
330 // Lese Antwort vom Server
331 String line = in.readLine();
332 LOGGER.debug("Server >| " + line);
333
334 // Wenn User oder Passwort falsch
335 if(serverAnswers.getString("server.answer.login.failed")
336 .contentEquals(new StringBuffer(line))) {
337 LOGGER.error("Fehler >| " + line);
338 throw new AuthenticationFailure();
339 }
340 // Wenn Benutzer erfolgreich angemeldet wurde
341 else if(Pattern.matches(serverAnswers.getString("server.answer.login"), line)) {
342 LOGGER.info("Authen >| " + line);
343 }
344 // In allen anderen Fällen
345 else {
346 System.out.println(serverAnswers.getString("server.answer.login"));
347 LOGGER.error("Fehler >| " + line);
348 throw new UnexpectedServerAnswer();
349 }
350
351 } catch (IOException e) {
352 throw new NoServerResponse();
353 }
354 }// Ende login()
355
356 /**
357 * Mit dieser Methode meldet man sich vom Server ab, es werden auch alle
358 * Streams geschlossen.
359 *
360 * @throws NoServerResponse - Keine Antwort vom Server.
361 * @throws NoServerStream - Kein Stream vom Server vorhanden.
362 * @throws UnexpectedServerAnswer - Unerwartete Server Antwort erhalten.
363 */
364 public final void logout() throws NoServerResponse, NoServerStream, UnexpectedServerAnswer {
365 LOGGER.trace("logout() aufgerufen.");
366
367 // Sende Logout Nachricht
368 sendCommand(". logout");
369
370 try {
371 // Werte erste Server Antwort aus
372 String line = in.readLine();
373 LOGGER.debug("Server >| " + line);
374 if(!serverAnswers.getString("server.answer.logout")
375 .contentEquals(new StringBuffer(line))) {
376 LOGGER.error("Fehler >| " + line);
377 throw new UnexpectedServerAnswer();
378 }
379 } catch (IOException e) {
380 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
381 throw new NoServerResponse();
382 }
383
384 try {
385 // Werte zweite Server Antwort aus
386 String line = in.readLine();
387 LOGGER.debug("Server >| " + line);
388 if(!serverAnswers.getString("server.answer.ok")
389 .contentEquals(new StringBuffer(line))) {
390 LOGGER.error("Fehler >| " + line);
391 throw new UnexpectedServerAnswer();
392 }
393 } catch (IOException e) {
394 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
395 throw new NoServerResponse();
396 }
397
398 try {
399 // Schließe InputStream
400 in.close();
401 } catch (IOException e) {
402 LOGGER.error("Fehler >| Keine Stream vom Server vorhanden");
403 throw new NoServerStream();
404 }
405 // Schließe OutputStream
406 out.close();
407 }// Ende logout()
408
409 /**
410 * Mit dieser Methode können die ACLs einer bestimmten Mailbox abgefragt
411 * werden.
412 *
413 * @param mailbox - Die Mailbox für die die ACLs abgefragt werden sollen
414 * @throws NoValidMailboxName - // TODO Dokumentation
415 * @throws NoServerResponse
416 * @throws UnexpectedServerAnswer
417 */
418 public final void acl(final String mailbox) throws NoValidMailboxName,
419 NoServerResponse, UnexpectedServerAnswer {
420 /*
421 * Prüfen ob der übergebene Mailboxname gültig ist.
422 */
423 if (!isValid(mailbox)) {
424 LOGGER.error("Fehler >| Ungültiger Mailboxname");
425 throw new NoValidMailboxName();
426 }
427
428 /*
429 * Kommando absetzen.
430 */
431 sendCommand(". getacl \"user." + mailbox + "\"");
432
433 /*
434 * Erste Antwortzeile einlesen.
435 */
436 try {
437 String line = in.readLine();
438 LOGGER.debug("Server >| " + line);
439
440 if(!Pattern.matches(serverAnswers.getString("server.answer.acl"), line)) {
441 LOGGER.error("Fehler >| " + line);
442 throw new UnexpectedServerAnswer();
443 }
444
445 acls = new HashMap<String, String>();
446 String keys[] = line.split(" ");
447 for(int i=0; i < keys.length; i++) {
448 if(i > 2) {
449 if(i % 2 == 1) {
450 acls.put(keys[i], keys[i+1]);
451 }
452 }
453 }
454
455 } catch (IOException e) {
456 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
457 throw new NoServerResponse();
458 }
459
460 /*
461 * Zweite Antwortzeile einlesen.
462 */
463 try {
464 String line = in.readLine();
465 LOGGER.debug("Server >| " + line);
466 if(!serverAnswers.getString("server.answer.ok")
467 .contentEquals(new StringBuffer(line))) {
468 LOGGER.error("Fehler >| " + line);
469 throw new UnexpectedServerAnswer();
470 }
471 } catch (IOException e) {
472 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
473 throw new NoServerResponse();
474 }
475 }// Ende acl(String)
476
477 /**
478 * Mit dieser Methode können für eine bestimmte Mailbox, Rechte für einen
479 * bestimmten Benutzer gesetzt werden.
480 *
481 * @param mailbox - Die Mailbox für die die Rechte gesetzt werden sollen.
482 * @param user - Benutzer für die die Rechte gelten sollen.
483 * @param acl - Rechte die für den Benutzer gelten sollen.
484 * @throws NoValidMailboxName -
485 * @throws NoServerResponse
486 * @throws UnexpectedServerAnswer
487 */
488 public final void setAcl(final String mailbox, final String user,
489 final String acl) throws NoValidMailboxName, NoServerResponse, UnexpectedServerAnswer {
490 /*
491 * Prüfen ob der übergebene Mailboxname gültig ist.
492 */
493 if (!isValid(mailbox)) {
494 LOGGER.error("Fehler >| Ungültiger Mailboxname");
495 throw new NoValidMailboxName();
496 }
497
498 /*
499 * Kommando absetzen.
500 */
501 sendCommand(". setacl \"user." + mailbox + "\" \"" + user + "\" " + acl);
502
503 /*
504 * Einlesen der Antwortzeile.
505 */
506 try {
507 String line = in.readLine();
508 LOGGER.debug("Server >| " + line);
509 if(!serverAnswers.getString("server.answer.ok")
510 .contentEquals(new StringBuffer(line))) {
511 LOGGER.error("Fehler >| " + line);
512 throw new UnexpectedServerAnswer();
513 }
514 } catch (IOException e) {
515 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
516 throw new NoServerResponse();
517 }
518 }// Ende setAcl(String, String, String)
519
520
521 /**
522 * Mit dieser Methode können die Rechte einer Mailbox die für einen
523 * bestimmten Benutzer existieren gelöscht werden.
524 *
525 * @param mailbox - Mailbox für die die Rechte gelöscht werden sollen.
526 * @param user - Benutzer für den die Rechte gelöscht werden sollen.
527 * @throws NoValidMailboxName - // TODO Dokumentation.
528 * @throws NoServerResponse
529 * @throws UnexpectedServerAnswer
530 */
531 public final void deleteAcl(final String mailbox, final String user)
532 throws NoValidMailboxName, NoServerResponse, UnexpectedServerAnswer {
533 /*
534 * Prüfen ob der übergebene Mailboxname gültig ist.
535 */
536 if (!isValid(mailbox)) {
537 LOGGER.error("Fehler >| Ungültiger Mailboxname");
538 throw new NoValidMailboxName();
539 }
540
541 /*
542 * Kommando absetzen.
543 */
544 sendCommand(". deleteacl \"user." + mailbox + "\" \"" + user + "\"");
545
546 /*
547 * Antwortzeile auswerten.
548 */
549 try {
550 String line = in.readLine();
551 LOGGER.debug("Server >| " + line);
552 if(!serverAnswers.getString("server.answer.ok")
553 .contentEquals(new StringBuffer(line))) {
554 LOGGER.error("Fehler >| " + line);
555 throw new UnexpectedServerAnswer();
556 }
557 } catch (IOException e) {
558 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
559 throw new NoServerResponse();
560 }
561
562 }// Ende deleteAcl(String, String)
563
564 /**
565 * Methode zum berechnen der Quota der aktuellen Mailbox, die Werte können
566 * über die entsprechenden Methoden abgerufen werden.
567 *
568 * @param mailbox - Mailbox für die die Quota berechnet werden soll.
569 * @throws IOException - InputStream/OutputStream geschlossen oder nicht
570 * vorhanden
571 * @throws NoMailbox - TODO doku
572 * @throws NoQuota - TODO doku
573 * @throws UnexpectedExtraArguments - TODO doku
574 * @throws NoServerResponse - TODO doku
575 * @throws NoValidMailboxName - TODO doku
576 */
577 public final void quota(final String mailbox) throws IOException,
578 NoMailbox, NoQuota, UnexpectedExtraArguments, NoServerResponse,
579 NoValidMailboxName {
580
581 /*
582 * Prüfen ob der übergebene Mailboxname gültig ist.
583 */
584 if (!isValid(mailbox)) {
585 LOGGER.error("Fehler >| Ungültiger Mailboxname");
586 throw new NoValidMailboxName();
587 }
588
589 /*
590 * Absenden des Befehls und auslesen der ersten Ergebniszeile.
591 */
592 sendCommand(". getquota \"user." + mailbox + "\"");
593 String line = in.readLine();
594 LOGGER.debug("Server >| " + line);
595
596 /*
597 * Prüfen ob der Server eine Antwort geschickt hat.
598 */
599 if (isNull(line)) {
600 LOGGER.warn("Kein Antwort vom Server.");
601 throw new NoServerResponse();
602 }
603
604 /*
605 * Wird geworfen wenn es die Mailbox nicht gibt.
606 */
607 if (line.startsWith(". NO Mailbox")) {
608 LOGGER.warn("Mailbox existiert nicht.");
609 throw new NoMailbox();
610 }
611
612 /*
613 * Wird geworfen wenn keine Quota gesetzt worden ist .
614 */
615 if (line.startsWith(". NO Quota root does not exist")) {
616 LOGGER.warn("Es wurde bis jetzt noch keine Quota gesetzt.");
617 throw new NoQuota();
618 }
619
620 /*
621 * Wird geworfen wenn der Methode unbekannte Parameter oder Zeichen
622 * übergeben wurden.
623 */
624 if (line.startsWith(". BAD Unexpected extra arguments to Getquota")) {
625 LOGGER.warn("Es wurden weiter Argumente dem Befehl hinzugefügt.");
626 throw new UnexpectedExtraArguments();
627 }
628
629 /*
630 * Wenn keine Quota exsistiert bzw. die Antwort nicht "* QUOTA enthält
631 * dann wird eine Exception geworfen.
632 */
633 if (!line.startsWith("* QUOTA")) {
634 LOGGER.warn("In der Server-Anwort war keine Quota enthalten.");
635 // TODO Exception hier hin.
636 }
637
638 /*
639 * Setzen der Index Elemente.
640 */
641 int start = line.lastIndexOf("(");
642 int end = line.lastIndexOf(")");
643
644 /*
645 * Zerlegen des Ergebnisses und schreiben der Quota und des
646 * Benutzten Platzes in die Variablen.
647 */
648 String[] storage = line.substring(start + 1, end).split(" ");
649 used = new BigDecimal(storage[1]);
650 quota = new BigDecimal(storage[2]);
651 LOGGER.debug(line.substring(start + 1, end));
652
653
654 /*
655 * Errechnen der Load und befüllung der entsprechenden Variable.
656 */
657 load = used.multiply(new BigDecimal("100")).divide(quota, 2,
658 BigDecimal.ROUND_UP);
659
660 /*
661 * Auslesen der zweiten Antwortzeile
662 */
663 line = in.readLine();
664 LOGGER.debug("Server >| " + line);
665
666 /*
667 * Prüfen ob der Server eine Antwort geschickt hat.
668 */
669 if (isNull(line)) {
670 LOGGER.warn("Kein Antwort vom Server.");
671 throw new NoServerResponse();
672 }
673
674 /*
675 * Exceptions je nach Antwortzeile.
676 */
677 if (!line.startsWith(". OK")) {
678 LOGGER.warn(
679 "Der letzte Befehl wurde nicht erfolgreich ausgeführt."
680 );
681 // TODO hier mus noch eine Exception hin
682 }
683
684 }// Ende quota(String mailbox)
685
686 /**
687 * Methode zum setzten der Quota einer Mailbox.
688 *
689 * @param mailbox - Hier. // TODO Doku hier
690 * @param quotaToSet - Hier. // TODO Doku hier
691 * @throws IOException - TODO doku
692 * @throws NoValidMailboxName -
693 */
694 public final void setQuota(final String mailbox,
695 final BigDecimal quotaToSet)
696 throws IOException, NoValidMailboxName {
697 /*
698 * Prüfen ob der übergebene Mailboxname gültig ist.
699 */
700 if (!isValid(mailbox)) {
701 LOGGER.warn("Ungültiger Mailboxname");
702 throw new NoValidMailboxName();
703 }
704
705 /*
706 * Sende Kommando.
707 */
708 sendCommand((new StringBuilder())
709 .append(". setquota \"")
710 .append("user.")
711 .append(mailbox)
712 .append("\" (STORAGE ")
713 .append(quotaToSet)
714 .append(")").toString());
715
716 String line = in.readLine();
717 LOGGER.debug("Server >| " + line);
718 //System.out.println("Server >| " + line);
719
720 // ". setquota \"$mb_name\" (STORAGE $quota)"
721 // // TODO hier mus code hin
722 }// Ende setQuota()
723
724 /**
725 * Methode zum erstellen einer Mailbox mit dem Namen "mailbox".
726 *
727 * @param mailbox - String mit dem Namen der Mailbox (i.e.
728 * "mailboxname" ohne [user.])
729 * @throws IOException - InputStream/OutputStream geschlossen oder nicht
730 * vorhanden
731 * @throws MailboxExists - Die Mailbox die erstellt werden soll exsistiert
732 * bereits.
733 * @throws NoServerResponse - //TODO Dokumentation
734 * @throws NoValidMailboxName - //TODO Dokumentation
735 */
736 public final void createMailBox(final String mailbox) throws IOException,
737 MailboxExists, NoServerResponse, NoValidMailboxName {
738 /*
739 * Prüfen ob der übergebene Mailboxname gültig ist.
740 */
741 System.out.println(mailbox);
742 if (!isValid(mailbox)) {
743
744 LOGGER.warn("Ungültiger Mailboxname");
745 throw new NoValidMailboxName();
746 }
747
748 /*
749 * Kommando absetzen.
750 */
751 sendCommand((new StringBuilder())
752 .append(". create \"")
753 .append("user.")
754 .append(mailbox)
755 .append("\"")
756 .toString());
757
758 /*
759 * Antwortzeile auslesen.
760 */
761 String line = in.readLine();
762 LOGGER.debug("Server >| " + line);
763
764 /*
765 * Prüfen ob es eine Serverantwort gibt.
766 */
767 if (isNull(line)) {
768 LOGGER.warn("Keine Antwort vom Server.");
769 throw new NoServerResponse();
770 }
771
772 /*
773 * Wirft Exception wenn es die Mailbox bereits gibt.
774 */
775 if (line.startsWith(". NO Mailbox already exists")) {
776 LOGGER.warn("Die Mailbox existiert schon.");
777 throw new MailboxExists();
778 }
779 }// Ende createMailBox()
780
781 /**
782 * Hier. // TODO Doku hier
783 *
784 * @param mailbox - Hier. // TODO Doku hier
785 * @throws IOException - InputStream/OutputStream geschlossen oder nicht
786 * vorhanden
787 * @throws NoValidMailboxName -
788 */
789 public final void deleteMailBox(final String mailbox) throws IOException,
790 NoValidMailboxName {
791 /*
792 * Prüfen ob der übergebene Mailboxname gültig ist.
793 */
794 if (!isValid(mailbox)) {
795 LOGGER.warn("Ungültiger Mailboxname");
796 throw new NoValidMailboxName();
797 }
798
799 /*
800 * Setzen der Rechte für den Administrationsbenutzer
801 */
802 try {
803 setAcl(mailbox, administrator, allacl);
804 } catch (NoServerResponse e) {
805 // TODO Auto-generated catch block
806 e.printStackTrace();
807 } catch (UnexpectedServerAnswer e) {
808 // TODO Auto-generated catch block
809 e.printStackTrace();
810 }
811
812 sendCommand(". delete \"user." + mailbox + "\"");
813 String line = in.readLine();
814 LOGGER.debug("Server >| " + line);
815 //System.out.println("Server >| " + line);
816 }// Ende deleteMailBox()
817
818 /**
819 * Methode zum setzen des Hostnamen oder der IP-Adresse des Servers mit dem
820 * eine Verbindung aufgebaut werden soll. Falls der Host nicht gesetzt ist
821 * wird localhost als hostname benutzt.
822 *
823 * @param hostname - Der Name oder die IP-Adresse des Servers zu dem eine
824 * Verbindung aufgebaut werden soll.
825 */
826 public final void setHost(final String hostname) {
827 this.host = hostname;
828 }// Ende setHost()
829
830 /**
831 * Methode um die Port-Nummer des Server zu verändern, normalerweise nicht
832 * nötig, wenn der Server auf den Standard-Ports betrieben wird.
833 *
834 * @param portNumber - Port-Nummer die für die Verbindung zum Server
835 * benutzt werden soll.
836 */
837 public final void setPort(final Integer portNumber) {
838 this.port = portNumber;
839 }// Ende setPort()
840
841 /**
842 * Hier. // TODO Doku hier
843 *
844 * @param set - Hier. // TODO Doku hier
845 */
846 public final void setAdministrator(final String set) {
847 this.administrator = set;
848 }// Ende setAdministrator()
849
850 /**
851 * Hier. // TODO Doku hier
852 *
853 * @param set - Hier. // TODO Doku hier
854 */
855 public final void setPassword(final String set) {
856 this.password = set;
857 }// Ende setPasswort()
858
859 /**
860 * Liefert die Version des Server mit dem gerade eine Verbindung aufgebaut
861 * ist.
862 *
863 * @return String - Cyrus Version
864 * @throws IOException - InputStream/OutputStream geschlossen oder nicht
865 * vorhanden
866 */
867 public final String version() throws IOException {
868 sendCommand(". id NIL");
869 String line = in.readLine();
870 LOGGER.debug("Server >| " + line);
871
872 if (isNull(line)) {
873 // TODO Hier kommt noch Exception
874 LOGGER.warn("Keine Server Antwort.");
875 }
876
877 int start = line.indexOf("(");
878 int end = line.lastIndexOf(")");
879
880 String[] storage = line.substring(start + 1, end).split("\" \"");
881
882 for (int i = 0; i < storage.length; i++) {
883 idMap.put(storage[i], storage[i + 1]);
884 i++;
885 }
886
887 line = in.readLine();
888 LOGGER.debug("Server >| " + line);
889 //System.out.println("Server >| " + line);
890
891 return idMap.get("version").split(" ")[0];
892 }// Ende version()
893
894 /**
895 * Mit Hilfe dieser Methode kann man sich die Wilkommensnachricht des Server
896 * abfragen, die nach dem aufruf der Methode connect(Boolean ssl) empfangen
897 * wurde.
898 *
899 * @return String - Willkommensnachricht des Servers.
900 */
901 public final String getWelcomeMsg() {
902 return welcomeMsg;
903 }// Ende getWelcomeMsg()
904
905 /**
906 * TODO Doku
907 * @return
908 */
909 public Map<String, String> getAcls() {
910 return acls;
911 }// Ende getAcls;
912
913 /**
914 * Bevor die Methode getUsed() aufgerufen werden kann, muss die Methode
915 * quota(String mailbox) aufgrufen werden. Die Methode getUsed() liefert
916 * dann den benutzen Teil der Quota der Mailbox.
917 *
918 * @return BigDecimal - Benutzer Teil der Quota der Mailbox die mit der
919 * Methode quota(String mailbox) übergeben wurde.
920 * @throws QuotaNotInitialized - TODO doku
921 */
922 public final BigDecimal getUsed() throws QuotaNotInitialized {
923 if (isNull(used)) {
924 throw new QuotaNotInitialized();
925 }
926 return used;
927 }// Ende getUsed()
928
929 /**
930 * Bevor die Methode getQuota() aufgerufen werden kann, muss die Methode
931 * quota(String mailbox) aufgrufen werden. Die Methode getQuota() liefert
932 * dann die aktuelle Quota der Mailbox.
933 *
934 * @return BigDecimal - Quota der Mailbox die mit der Methode quota(String
935 * mailbox) übergeben wurde.
936 * @throws QuotaNotInitialized - TODO doku
937 */
938 public final BigDecimal getQuota() throws QuotaNotInitialized {
939 if (isNull(used)) {
940 throw new QuotaNotInitialized();
941 }
942 return quota;
943 }// Ende getQuota()
944
945 /**
946 * Bevor die Methode getLoad() aufgerufen werden kann, muss die Methode
947 * quota(String mailbox) aufgrufen werden. Die Methode getLoad() liefert
948 * dann die aktuelle Load der Mailbox.
949 *
950 * @return BigDecimal - Load der Mailbox die mit der Methode quota(String
951 * mailbox) übergeben wurde.
952 * @throws QuotaNotInitialized - TODO doku
953 */
954 public final BigDecimal getLoad() throws QuotaNotInitialized {
955 if (isNull(used)) {
956 throw new QuotaNotInitialized();
957 }
958 return load;
959 }// Ende getLoad()
960
961 /**
962 * Hilfs-Methode um ein Kommando an den Server zu senden.
963 *
964 * @param command - Kommando das an den Server gesendet werden soll.
965 */
966 private void sendCommand(final String command) {
967 out.println(command);
968 out.flush();
969 LOGGER.debug("Client >| " + command);
970 }// Ende sendCommand()
971
972 /**
973 * Hilfs-Methode die prüft ob ein Object Null ist.
974 *
975 * @param isNull - Objekt das getestet werden soll.
976 * @return Boolean - Wahrheitswert: True wenn das Objekt Null ist.
977 */
978 private Boolean isNull(final Object isNull) {
979 return isNull != null ? false : true;
980 }// Ende isNull()
981
982 /**
983 * Hilfs-Methode die testet ob ein String ein gültiger String im Sinne
984 * einer Cyrus Mailbox ist.
985 *
986 * @param mbString - String der als Mailbox übergeben wurde.
987 * @return Boolean - Wenn gültig dann True.
988 */
989 private Boolean isValid(final String mbString) {
990 return Pattern.matches("[a-zA-Z_]*", mbString)? true : false;
991 }
992
993 /**
994 * Hilfs-Methode die dazu dient den String einer zu einem bestimmtem
995 * Schlüssel aus der Eigenschaftsdatei zu holen.
996 *
997 * @param text - Schlüssel unter dem der String abgelegt ist.
998 * @return String - Der enthaltente String zum angegebenen Schlüssel oder
999 * wenn der Schlüssel nicht gefunden wurde der übergebene String.
1000 */
1001 @Deprecated
1002 private String getText(String text) {
1003 if ((props != null) && (props.getProperty(text) != null)) {
1004 return props.getProperty(text);
1005 }
1006 return text;
1007 }// Ende getText()
1008
1009
1010 }// Ende class