001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.net.imap;
019
020 import java.io.IOException;
021 import java.util.regex.Matcher;
022 import java.util.regex.Pattern;
023
024 import org.apache.commons.net.MalformedServerReplyException;
025
026 /**
027 * IMAPReply stores IMAP reply code constants.
028 */
029
030 public final class IMAPReply
031 {
032 /** The reply code indicating success of an operation. */
033 public static final int OK = 0;
034
035 /** The reply code indicating failure of an operation. */
036 public static final int NO = 1;
037
038 /** The reply code indicating command rejection. */
039 public static final int BAD = 2;
040
041 /** The reply code indicating command continuation. */
042 public static final int CONT = 3;
043
044 /** The IMAP reply String indicating success of an operation. */
045 private static final String IMAP_OK = "OK";
046
047 /** The IMAP reply String indicating failure of an operation. */
048 private static final String IMAP_NO = "NO";
049
050 /** The IMAP reply String indicating command rejection. */
051 private static final String IMAP_BAD = "BAD";
052
053 // Start of line for untagged replies
054 private static final String IMAP_UNTAGGED_PREFIX = "* ";
055
056 // Start of line for continuation replies
057 private static final String IMAP_CONTINUATION_PREFIX = "+";
058
059 // Cannot be instantiated.
060 private IMAPReply()
061 {}
062
063 /**
064 * Checks if the reply line is untagged - e.g. "* OK ..."
065 * @param line to be checked
066 * @return {@code true} if the line is untagged
067 */
068 public static boolean isUntagged(String line) {
069 return line.startsWith(IMAP_UNTAGGED_PREFIX);
070 }
071
072 /**
073 * Checks if the reply line is a continuation, i.e. starts with "+"
074 * @param line the line to be checked
075 * @return {@code true} if the line is untagged
076 */
077 public static boolean isContinuation(String line) {
078 return line.startsWith(IMAP_CONTINUATION_PREFIX);
079 }
080
081 private static final String TAGGED_RESPONSE = "^\\w+ (\\S+).*"; // TODO perhaps be less strict on tag match?
082 // tag cannot contain: + ( ) { SP CTL % * " \ ]
083 private static final Pattern TAGGED_PATTERN = Pattern.compile(TAGGED_RESPONSE);
084
085 /**
086 * Intepret the String reply code - OK, NO, BAD - in a tagged response as a integer.
087 *
088 * @param line the tagged line to be checked
089 * @return {@link #OK} or {@link #NO} or {@link #BAD}
090 * @throws IOException if the input has an unexpected format
091 */
092 public static int getReplyCode(String line) throws IOException {
093 return getReplyCode(line, TAGGED_PATTERN);
094 }
095
096 private static final String UNTAGGED_RESPONSE = "^\\* (\\S+).*";
097 private static final Pattern UNTAGGED_PATTERN = Pattern.compile(UNTAGGED_RESPONSE);
098
099 /**
100 * Intepret the String reply code - OK, NO, BAD - in an untagged response as a integer.
101 *
102 * @param line the untagged line to be checked
103 * @return {@link #OK} or {@link #NO} or {@link #BAD}
104 * @throws IOException if the input has an unexpected format
105 */
106 public static int getUntaggedReplyCode(String line) throws IOException {
107 return getReplyCode(line, UNTAGGED_PATTERN);
108 }
109
110 // Helper method to process both tagged and untagged replies.
111 private static int getReplyCode(String line, Pattern pattern) throws IOException{
112 if (isContinuation(line)) {
113 return CONT;
114 }
115 Matcher m = pattern.matcher(line);
116 if (m.matches()) {
117 String code = m.group(1);
118 if (code.equals(IMAP_OK)) {
119 return OK;
120 }
121 if (code.equals(IMAP_BAD)) {
122 return BAD;
123 }
124 if (code.equals(IMAP_NO)) {
125 return NO;
126 }
127 }
128 throw new MalformedServerReplyException(
129 "Received unexpected IMAP protocol response from server: '" + line + "'.");
130 }
131
132 /**
133 * Checks whether the reply code indicates success or not
134 *
135 * @param replyCode the code to check
136 * @return {@code true} if the code equals {@link #OK}
137 */
138 public static boolean isSuccess(int replyCode) {
139 return replyCode == OK;
140 }
141 /**
142 * Checks if the reply line is a continuation, i.e. starts with "+"
143 * @param replyCode the code to be checked
144 * @return {@code true} if the response was a continuation
145 */
146 public static boolean isContinuation(int replyCode) {
147 return replyCode == CONT;
148 }
149
150 }
151
152 /* kate: indent-width 4; replace-tabs on; */