| 1 | /**************************************************************** |
| 2 | ??*??Licensed??to??the??Apache??Software??Foundation??(ASF)??under??one??????* |
| 3 | ??*??or??more??contributor??license??agreements.????See??the??NOTICE??file??* |
| 4 | ??*??distributed??with??this??work??for??additional??information????????????????* |
| 5 | ??*??regarding??copyright??ownership.????The??ASF??licenses??this??file??????* |
| 6 | ??*??to??you??under??the??Apache??License,??Version??2.0??(the????????????????????????* |
| 7 | ??*??"License");??you??may??not??use??this??file??except??in??compliance??????* |
| 8 | ??*??with??the??License.????You??may??obtain??a??copy??of??the??License??at??????* |
| 9 | ??*????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????* |
| 10 | ??*??????http://www.apache.org/licenses/LICENSE-2.0??????????????????????????????????* |
| 11 | ??*????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????* |
| 12 | ??*??Unless??required??by??applicable??law??or??agreed??to??in??writing,??????* |
| 13 | ??*??software??distributed??under??the??License??is??distributed??on??an????* |
| 14 | ??*??"AS??IS"??BASIS,??WITHOUT??WARRANTIES??OR??CONDITIONS??OF??ANY??????????????* |
| 15 | ??*??KIND,??either??express??or??implied.????See??the??License??for??the????????* |
| 16 | ??*??specific??language??governing??permissions??and??limitations????????????* |
| 17 | ??*??under??the??License.??????????????????????????????????????????????????????????????????????????????????????* |
| 18 | ??****************************************************************/ |
| 19 | ?? |
| 20 | package??org.apache.james.mpt; |
| 21 | ?? |
| 22 | import??java.nio.ByteBuffer; |
| 23 | import??java.nio.channels.SocketChannel; |
| 24 | import??java.nio.charset.Charset; |
| 25 | ?? |
| 26 | final??class??ExternalSession??implements??Session??{ |
| 27 | ?? |
| 28 | ????????/**??Number??of??milliseconds??to??sleep??after??empty??read??*/ |
| 29 | ????????private??static??final??int??SHORT_WAIT_FOR_INPUT??=??10; |
| 30 | ?? |
| 31 | ????????private??static??final??byte[]??CRLF??=??{??'\r',??'\n'??}; |
| 32 | ?? |
| 33 | ????????private??final??SocketChannel??socket; |
| 34 | ?? |
| 35 | ????????private??final??Monitor??monitor; |
| 36 | ?? |
| 37 | ????????private??final??ByteBuffer??readBuffer; |
| 38 | ?? |
| 39 | ????????private??final??Charset??ascii; |
| 40 | ?? |
| 41 | ????????private??final??ByteBuffer??lineEndBuffer; |
| 42 | ?? |
| 43 | ????????private??boolean??first??=??true; |
| 44 | ?? |
| 45 | ????????private??final??String??shabang; |
| 46 | ???????? |
| 47 | ????????public??ExternalSession(final??SocketChannel??socket,??final??Monitor??monitor,??String??shabang)??{ |
| 48 | ????????????????this(socket,??monitor,??shabang,??false); |
| 49 | ????????} |
| 50 | ?? |
| 51 | ????????public??ExternalSession(final??SocketChannel??socket,??final??Monitor??monitor,??String??shabang,??boolean??debug)??{ |
| 52 | ????????????????super(); |
| 53 | ????????????????this.socket??=??socket; |
| 54 | ????????????????this.monitor??=??monitor; |
| 55 | ????????????????readBuffer??=??ByteBuffer.allocateDirect(2048); |
| 56 | ????????????????ascii??=??Charset.forName("US-ASCII"); |
| 57 | ????????????????lineEndBuffer??=??ByteBuffer.wrap(CRLF); |
| 58 | ????????????????this.shabang??=??shabang; |
| 59 | ????????} |
| 60 | ?? |
| 61 | ????????public??String??readLine()??throws??Exception??{ |
| 62 | ????????????????StringBuffer??buffer??=??new??StringBuffer(); |
| 63 | ????????????????readlineInto(buffer); |
| 64 | ????????????????final??String??result; |
| 65 | ????????????????if??(first??&&??shabang??!=??null)??{ |
| 66 | ????????????????????????//??fake??shabang |
| 67 | ????????????????????????monitor.note("<-"??+??buffer.toString()); |
| 68 | ????????????????????????result??=??shabang; |
| 69 | ????????????????????????first??=??false; |
| 70 | ????????????????}??else??{ |
| 71 | ????????????????????????result??=??buffer.toString(); |
| 72 | ????????????????????????monitor.note("<-"??+??result); |
| 73 | ????????????????} |
| 74 | ????????????????return??result; |
| 75 | ????????} |
| 76 | ?? |
| 77 | ????????private??void??readlineInto(StringBuffer??buffer)??throws??Exception??{ |
| 78 | ????????????????monitor.debug("[Reading??line]"); |
| 79 | ????????????????readBuffer.flip(); |
| 80 | ????????????????while??(oneFromLine(buffer)) |
| 81 | ????????????????????????; |
| 82 | //????????????May??have??partial??read |
| 83 | ????????????????readBuffer.compact(); |
| 84 | ????????????????monitor.debug("[Done]"); |
| 85 | ????????} |
| 86 | ?? |
| 87 | ????????private??boolean??oneFromLine(StringBuffer??buffer)??throws??Exception??{ |
| 88 | ????????????????final??boolean??result; |
| 89 | ????????????????if??(readBuffer.hasRemaining())??{ |
| 90 | ????????????????????????char??next??=??(char)??readBuffer.get(); |
| 91 | ????????????????????????if??(next??==??'\n')??{ |
| 92 | ????????????????????????????????monitor.debug("[LF]"); |
| 93 | //????????????????????????????Reached??end??of??the??line |
| 94 | ????????????????????????????????result??=??false; |
| 95 | ????????????????????????}??else??if??(next??==??'\r')??{ |
| 96 | //????????????????????????????CRLF??line??endings??so??drop |
| 97 | ????????????????????????????????monitor.debug("[CR]"); |
| 98 | ????????????????????????????????result??=??true; |
| 99 | ????????????????????????}??else??{ |
| 100 | //????????????????????????????Load??buffer |
| 101 | ????????????????????????????????monitor.debug(next); |
| 102 | ????????????????????????????????buffer.append(next); |
| 103 | ????????????????????????????????result??=??true; |
| 104 | ????????????????????????} |
| 105 | ????????????????}??else??{ |
| 106 | ????????????????????????monitor.debug("[Reading??into??buffer]"); |
| 107 | ????????????????????????readBuffer.clear(); |
| 108 | ????????????????????????while??(socket.read(readBuffer)??==??0)??{ |
| 109 | //????????????????????????????No??response??yet |
| 110 | //????????????????????????????Wait??a??little??while |
| 111 | ????????????????????????????????Thread.sleep(SHORT_WAIT_FOR_INPUT); |
| 112 | ????????????????????????} |
| 113 | //????????????????????Reset??for??transfer??into??string??buffer |
| 114 | ????????????????????????readBuffer.flip(); |
| 115 | ????????????????????????monitor.debug("[Done]"); |
| 116 | ????????????????????????result??=??true; |
| 117 | ????????????????} |
| 118 | ????????????????return??result; |
| 119 | ????????} |
| 120 | ?? |
| 121 | ????????public??void??start()??throws??Exception??{ |
| 122 | ????????????????while??(!socket.finishConnect())??{ |
| 123 | ????????????????????????monitor.note("connecting..."); |
| 124 | ????????????????????????Thread.sleep(10); |
| 125 | ????????????????} |
| 126 | ????????} |
| 127 | ?? |
| 128 | ????????public??void??stop()??throws??Exception??{ |
| 129 | ????????????????monitor.note("closing"); |
| 130 | ????????????????socket.close(); |
| 131 | ????????} |
| 132 | ?? |
| 133 | ????????public??void??writeLine(String??line)??throws??Exception??{ |
| 134 | ????????????????monitor.note("->??"??+??line); |
| 135 | ????????????????monitor.debug("[Writing??line]"); |
| 136 | ????????????????ByteBuffer??writeBuffer??=??ascii.encode(line); |
| 137 | ????????????????while??(writeBuffer.hasRemaining())??{ |
| 138 | ????????????????????????socket.write(writeBuffer); |
| 139 | ????????????????} |
| 140 | ????????????????lineEndBuffer.rewind(); |
| 141 | ????????????????while??(lineEndBuffer.hasRemaining())??{ |
| 142 | ????????????????????????socket.write(lineEndBuffer); |
| 143 | ????????????????} |
| 144 | ????????????????monitor.debug("[Done]"); |
| 145 | ????????} |
| 146 | ?? |
| 147 | ????????/** |
| 148 | ??????????*??Constructs??a??<code>String</code>??with??all??attributes |
| 149 | ??????????*??in??name??=??value??format. |
| 150 | ??????????* |
| 151 | ??????????*??@return??a??<code>String</code>??representation?? |
| 152 | ??????????*??of??this??object. |
| 153 | ??????????*/ |
| 154 | ????????public??String??toString() |
| 155 | ????????{ |
| 156 | ????????????????final??String??TAB??=??"??"; |
| 157 | ???????????????? |
| 158 | ????????????????String??result??=????"External??(??" |
| 159 | ????????????????????????+??"socket??=??"??+??this.socket??+??TAB |
| 160 | ????????????????????????+??"monitor??=??"??+??this.monitor??+??TAB |
| 161 | ????????????????????????+??"readBuffer??=??"??+??this.readBuffer??+??TAB |
| 162 | ????????????????????????+??"ascii??=??"??+??this.ascii??+??TAB |
| 163 | ????????????????????????+??"lineEndBuffer??=??"??+??this.lineEndBuffer??+??TAB |
| 164 | ????????????????????????+??"first??=??"??+??this.first??+??TAB |
| 165 | ????????????????????????+??"shabang??=??"??+??this.shabang??+??TAB |
| 166 | ????????????????????????+??"??)"; |
| 167 | ???????? |
| 168 | ????????????????return??result; |
| 169 | ????????} |
| 170 | ???????? |
| 171 | ???????? |
| 172 | } |