List of usage examples for java.io OutputStreamWriter write
public void write(int c) throws IOException
From source file:com.techventus.server.voice.Voice.java
/** * Mark a Conversation with a known Message ID as unread. * * @param msgID the msg id//from w w w . j a va 2 s .c o m * @return the string * @throws IOException Signals that an I/O exception has occurred. */ public String markUnRead(String msgID) throws IOException { String out = ""; StringBuffer calldata = new StringBuffer(); // POST /voice/inbox/mark/ // messages=[messageID] // &read=0 // &_rnr_se=[pull from page] calldata.append("messages="); calldata.append(URLEncoder.encode(msgID, enc)); calldata.append("&read=0"); calldata.append("&_rnr_se="); calldata.append(URLEncoder.encode(rnrSEE, enc)); URL callURL = new URL("https://www.google.com/voice/b/0/inbox/mark"); URLConnection callconn = callURL.openConnection(); callconn.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken); callconn.setRequestProperty("User-agent", USER_AGENT); callconn.setDoOutput(true); OutputStreamWriter callwr = new OutputStreamWriter(callconn.getOutputStream()); callwr.write(calldata.toString()); callwr.flush(); BufferedReader callrd = new BufferedReader(new InputStreamReader(callconn.getInputStream())); String line; while ((line = callrd.readLine()) != null) { out += line + "\n\r"; } callwr.close(); callrd.close(); if (out.equals("")) { throw new IOException("No Response Data Received."); } return out; }
From source file:com.techventus.server.voice.Voice.java
/** * Delete message./* w w w. jav a 2 s . c o m*/ * * @param msgID the msg id * @return the string * @throws IOException Signals that an I/O exception has occurred. */ public String deleteMessage(String msgID) throws IOException { String out = ""; StringBuffer calldata = new StringBuffer(); // POST /voice/inbox/deleteMessages/ // messages=[messageID] // &trash=1 // &_rnr_se=[pull from page] calldata.append("messages="); calldata.append(URLEncoder.encode(msgID, enc)); calldata.append("&trash=1"); calldata.append("&_rnr_se="); calldata.append(URLEncoder.encode(rnrSEE, enc)); URL callURL = new URL("https://www.google.com/voice/b/0/inbox/deleteMessages/"); URLConnection callconn = callURL.openConnection(); callconn.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken); callconn.setRequestProperty("User-agent", USER_AGENT); callconn.setDoOutput(true); OutputStreamWriter callwr = new OutputStreamWriter(callconn.getOutputStream()); callwr.write(calldata.toString()); callwr.flush(); BufferedReader callrd = new BufferedReader(new InputStreamReader(callconn.getInputStream())); String line; while ((line = callrd.readLine()) != null) { out += line + "\n\r"; } callwr.close(); callrd.close(); if (out.equals("")) { throw new IOException("No Response Data Received."); } return out; }
From source file:com.techventus.server.voice.Voice.java
/** * Place a call.//from www.jav a 2 s .co m * * @param originNumber * the origin number * @param destinationNumber * the destination number * @param phoneType * the phone type, this is a number such as 1,2,7 formatted as a String * @return the raw response string received from Google Voice. * @throws IOException * Signals that an I/O exception has occurred. */ public String call(String originNumber, String destinationNumber, String phoneType) throws IOException { String out = ""; StringBuffer calldata = new StringBuffer(); // POST /voice/call/connect/ // outgoingNumber=[number to call] // &forwardingNumber=[forwarding number] // &subscriberNumber=undefined // &phoneType=[phone type from google] // &remember=0 // &_rnr_se=[pull from page] calldata.append("outgoingNumber="); calldata.append(URLEncoder.encode(destinationNumber, enc)); calldata.append("&forwardingNumber="); calldata.append(URLEncoder.encode(originNumber, enc)); calldata.append("&subscriberNumber=undefined"); calldata.append("&phoneType="); calldata.append(URLEncoder.encode(phoneType, enc)); calldata.append("&remember=0"); calldata.append("&_rnr_se="); calldata.append(URLEncoder.encode(rnrSEE, enc)); URL callURL = new URL("https://www.google.com/voice/b/0/call/connect/"); URLConnection callconn = callURL.openConnection(); callconn.setRequestProperty("Authorization", "GoogleLogin auth=" + authToken); callconn.setRequestProperty("User-agent", USER_AGENT); callconn.setDoOutput(true); OutputStreamWriter callwr = new OutputStreamWriter(callconn.getOutputStream()); callwr.write(calldata.toString()); callwr.flush(); BufferedReader callrd = new BufferedReader(new InputStreamReader(callconn.getInputStream())); String line; while ((line = callrd.readLine()) != null) { out += line + "\n\r"; } callwr.close(); callrd.close(); if (out.equals("")) { throw new IOException("No Response Data Received."); } return out; }
From source file:com.techventus.server.voice.Voice.java
/** * Use this login method to login - use captchaAnswer to answer a captcha challenge * @param pCaptchaAnswer (optional) String entered by the user as an answer to a CAPTCHA challenge. - null to make a normal login attempt * @param pCaptchaToken (optional) token which matches the response/url from the captcha challenge * @throws IOException if login encounters a connection error *//* w w w.j a v a2 s . c o m*/ public void login(String pCaptchaAnswer, String pCaptchaToken) throws IOException { String data = URLEncoder.encode("accountType", enc) + "=" + URLEncoder.encode(account_type, enc); data += "&" + URLEncoder.encode("Email", enc) + "=" + URLEncoder.encode(user, enc); data += "&" + URLEncoder.encode("Passwd", enc) + "=" + URLEncoder.encode(pass, enc); data += "&" + URLEncoder.encode("service", enc) + "=" + URLEncoder.encode(SERVICE, enc); data += "&" + URLEncoder.encode("source", enc) + "=" + URLEncoder.encode(source, enc); if (pCaptchaAnswer != null && pCaptchaToken != null) { data += "&" + URLEncoder.encode("logintoken", enc) + "=" + URLEncoder.encode(pCaptchaToken, enc); data += "&" + URLEncoder.encode("logincaptcha", enc) + "=" + URLEncoder.encode(pCaptchaAnswer, enc); } // Send data URL url = new URL(loginURLString); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("User-agent", USER_AGENT); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write(data); wr.flush(); // Get the response conn.connect(); int responseCode = conn.getResponseCode(); if (PRINT_TO_CONSOLE) System.out.println(loginURLString + " - " + conn.getResponseMessage()); InputStream is; if (responseCode == 200) { is = conn.getInputStream(); } else { is = conn.getErrorStream(); } InputStreamReader isr = new InputStreamReader(is); BufferedReader rd = new BufferedReader(isr); String line; String completelineDebug = ""; /* * A failure response contains an error code and a URL to an error page that can be displayed to the user. * If the error code is a CAPTCHA challenge, the response also includes a URL to a CAPTCHA image and a special * token. Your application should be able to solicit an answer from the user and then retry the login request. * To display the CAPTCHA image to the user, prefix the CaptchaUrl value with "http://www.google.com/accounts/", * for example: " http://www.google.com/accounts/Captcha?ctoken=HiteT4b0Bk5Xg18_AcVoP6-yFkHPibe7O9EqxeiI7lUSN". */ String lErrorString = "Unknown Connection Error."; // ex: Error=CaptchaRequired // String AuthToken = null; while ((line = rd.readLine()) != null) { completelineDebug += line + "\n"; if (line.contains("Auth=")) { this.authToken = line.split("=", 2)[1].trim(); if (PRINT_TO_CONSOLE) { System.out.println("Logged in to Google - Auth token received"); } } else if (line.contains("Error=")) { lErrorString = line.split("=", 2)[1].trim(); //error = getErrorEnumByCode(lErrorString); error = ERROR_CODE.valueOf(lErrorString); if (PRINT_TO_CONSOLE) System.out.println("Login error - " + lErrorString); } if (line.contains("CaptchaToken=")) { captchaToken = line.split("=", 2)[1].trim(); } if (line.contains("CaptchaUrl=")) { captchaUrl = "http://www.google.com/accounts/" + line.split("=", 2)[1].trim(); } if (line.contains("Url=")) { captchaUrl2 = line.split("=", 2)[1].trim(); } } wr.close(); rd.close(); // if (PRINT_TO_CONSOLE){ // System.out.println(completelineDebug); // } if (this.authToken == null) { AuthenticationException.throwProperException(error, captchaToken, captchaUrl); } String response = this.getRawPhonesInfo(); int phoneIndex = response.indexOf("gc-user-number-value\">"); this.phoneNumber = response.substring(phoneIndex + 22, phoneIndex + 36); this.phoneNumber = this.phoneNumber.replaceAll("[^a-zA-Z0-9]", ""); if (this.phoneNumber.indexOf("+") == -1) { this.phoneNumber = "+1" + this.phoneNumber; } }
From source file:com.cloud.bridge.service.EC2RestServlet.java
/** * Send out an error response according to Amazon convention. *//*from ww w .j a va 2 s . c o m*/ private void faultResponse(HttpServletResponse response, String errorCode, String errorMessage) { try { OutputStreamWriter out = new OutputStreamWriter(response.getOutputStream()); response.setContentType("text/xml; charset=UTF-8"); out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); out.write("<Response><Errors><Error><Code>"); out.write(errorCode); out.write("</Code><Message>"); out.write(errorMessage); out.write("</Message></Error></Errors><RequestID>"); out.write(UUID.randomUUID().toString()); out.write("</RequestID></Response>"); out.flush(); out.close(); } catch (IOException e) { logger.error("Unexpected exception " + e.getMessage(), e); } }
From source file:study.tdcc.act.MainCalendar.java
/** * XML?????/*w w w .ja va2 s .com*/ * * @param strUrl * @param strXml * @param strMethod (PUT,DELETE) * @return InputStream ???InputStream */ public InputStream httpPostXml(String strUrl, String strXml, String strMethod) { Log.d("DEBUG", "MainCalendar httpPostXml Start"); blHttpSucceeded = false; try { while (strUrl != null) { URL urlObj = new URL(strUrl); //URL????? HttpURLConnection httpURLCObj = (HttpURLConnection) urlObj.openConnection(); //?POST? httpURLCObj.setRequestMethod("POST"); //GData-Version? httpURLCObj.setRequestProperty(GDATA_VERSION_TAG, GDATA_VERSION); if (strMethod != null) { //POST??????If-Match:*?X-HTTP-Method-Override httpURLCObj.setRequestProperty("If-Match", "*"); httpURLCObj.setRequestProperty("X-HTTP-Method-Override", strMethod); } // httpURLCObj.setDoOutput(true); //Content-Type??XML httpURLCObj.setRequestProperty("Content-Type", CONTENT_TYPE_AA); // httpURLCObj.setUseCaches(false); //OutputStreamWriter??XML?? OutputStreamWriter outputStreamWriter = new OutputStreamWriter(httpURLCObj.getOutputStream(), "UTF-8"); outputStreamWriter.write(strXml); outputStreamWriter.close(); //HTTP?? intResponseCode = 0; intResponseCode = httpURLCObj.getResponseCode(); strUrl = null; Log.d("DEBUG", "MainCalendar httpPostXml HttpResponseCode : " + intResponseCode); if (intResponseCode == HttpURLConnection.HTTP_OK || intResponseCode == HttpURLConnection.HTTP_CREATED) { //??OK???CREATED????? blHttpSucceeded = true; Log.d("DEBUG", "MainCalendar httpPostXml End(1)"); //?InputStream?? return httpURLCObj.getInputStream(); } else if (intResponseCode == HttpURLConnection.HTTP_MOVED_TEMP) { //??MOVED_TEMP????????? //?Location????URL????(?while? Map<String, List<String>> mResponseHeaders = httpURLCObj.getHeaderFields(); if (mResponseHeaders.containsKey("Location")) { strUrl = mResponseHeaders.get("Location").get(0); } else if (mResponseHeaders.containsKey("location")) { strUrl = mResponseHeaders.get("location").get(0); } } else { //??OK???CREATED???MOVED_TEMP?? blHttpSucceeded = false; Log.d("DEBUG", "MainCalendar httpPostXml End(2) ??OK,CREATED,MOVED_TEMP??"); } } } catch (Exception e) { Log.e("ERROR", "MainCalendar httpPostXml ERROR", e); } Log.d("DEBUG", "MainCalendar httpPostXml End(3)"); return null; }
From source file:cz.cas.lib.proarc.common.export.mets.structure.MetsElementVisitor.java
/** * Saves the mets document into a file//from w w w . ja va 2s .c o m * * @param mets * @param outputFile * @throws MetsExportException */ private void saveMets(Mets mets, File outputFile, IMetsElement metsElement) throws MetsExportException { String fileMd5Name; try { addFileGrpToMets(fileGrpMap); addStructLink(); try { JAXBContext jaxbContext = JAXBContext.newInstance(Mets.class, OaiDcType.class, ModsDefinition.class); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8"); // marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, // "http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema.xsd http://www.loc.gov/METS/ http://www.loc.gov/standards/mets/mets.xsd http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/mods.xsd http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd"); marshaller.marshal(mets, outputFile); MessageDigest md; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new MetsExportException("Unable to create MD5 hash", false, e); } md.reset(); InputStream is; try { is = new FileInputStream(outputFile); } catch (FileNotFoundException e) { throw new MetsExportException("Unable to open file:" + outputFile.getAbsolutePath(), false, e); } byte[] bytes = new byte[2048]; int numBytes; long totalBytes = 0; try { while ((numBytes = is.read(bytes)) != -1) { totalBytes = totalBytes + numBytes; md.update(bytes, 0, numBytes); } } catch (IOException e) { throw new MetsExportException("Unable to generate MD5 hash", false, e); } byte[] digest = md.digest(); String result = new String(Hex.encodeHex(digest)); metsElement.getMetsContext().getFileList() .add(new FileMD5Info("." + File.separator + outputFile.getName(), result, totalBytes)); fileMd5Name = "MD5_" + MetsUtils.removeNonAlpabetChars(metsElement.getMetsContext().getPackageID()) + ".md5"; File fileMd5 = new File(metsElement.getMetsContext().getOutputPath() + File.separator + metsElement.getMetsContext().getPackageID() + File.separator + fileMd5Name); OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileMd5)); for (FileMD5Info info : metsElement.getMetsContext().getFileList()) { osw.write(info.getMd5() + " " + info.getFileName() + "\n"); } osw.close(); is.close(); // calculate md5 for md5file - it's inserted into info.xml is = new FileInputStream(fileMd5); FileMD5Info md5InfoMd5File = MetsUtils.getDigest(is); is.close(); metsElement.getMetsContext().getFileList() .add(new FileMD5Info("." + File.separator + fileMd5Name, null, fileMd5.length())); MetsUtils.saveInfoFile(metsElement.getMetsContext().getOutputPath(), metsElement.getMetsContext(), md5InfoMd5File.getMd5(), fileMd5Name, outputFile); } catch (Exception ex) { throw new MetsExportException(metsElement.getOriginalPid(), "Unable to save mets file:" + outputFile.getAbsolutePath(), false, ex); } List<String> validationErrors; try { validationErrors = MetsUtils.validateAgainstXSD(outputFile, Mets.class.getResourceAsStream("mets.xsd")); } catch (Exception ex) { throw new MetsExportException("Error while validation document:" + outputFile, false, ex); } if (validationErrors.size() > 0) { MetsExportException metsException = new MetsExportException("Invalid mets file:" + outputFile, false, null); metsException.getExceptions().get(0).setValidationErrors(validationErrors); for (String error : validationErrors) { LOG.fine(error); } throw metsException; } LOG.log(Level.FINE, "Element validated:" + metsElement.getOriginalPid() + "(" + metsElement.getElementType() + ")"); } finally { JhoveUtility.destroyConfigFiles(metsElement.getMetsContext().getJhoveContext()); } metsElement.getMetsContext().getGeneratedPSP().add(metsElement.getMetsContext().getPackageID()); }
From source file:edu.unc.lib.dl.admin.controller.RESTProxyController.java
@RequestMapping(value = { "/services/rest", "/services/rest/*", "/services/rest/**/*" }) public final void proxyAjaxCall(HttpServletRequest request, HttpServletResponse response) throws IOException { log.debug("Prepending service url " + this.servicesUrl + " to " + request.getRequestURI()); String url = request.getRequestURI().replaceFirst(".*/services/rest/?", this.servicesUrl); if (request.getQueryString() != null) url = url + "?" + request.getQueryString(); OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream()); HttpClient client = new HttpClient(); HttpMethod method = null;//w w w. ja v a 2s .c o m try { log.debug("Proxying ajax request to services REST api via " + request.getMethod()); // Split this according to the type of request if (request.getMethod().equals("GET")) { method = new GetMethod(url); } else if (request.getMethod().equals("POST")) { method = new PostMethod(url); // Set any eventual parameters that came with our original // request (POST params, for instance) Enumeration<String> paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) { String paramName = paramNames.nextElement(); ((PostMethod) method).setParameter(paramName, request.getParameter(paramName)); } } else { throw new NotImplementedException("This proxy only supports GET and POST methods."); } // Forward the user's groups along with the request method.addRequestHeader(HttpClientUtil.SHIBBOLETH_GROUPS_HEADER, GroupsThreadStore.getGroupString()); method.addRequestHeader("On-Behalf-Of", GroupsThreadStore.getUsername()); // Execute the method client.executeMethod(method); // Set the content type, as it comes from the server Header[] headers = method.getResponseHeaders(); for (Header header : headers) { if ("Content-Type".equalsIgnoreCase(header.getName())) { response.setContentType(header.getValue()); } } try (InputStream responseStream = method.getResponseBodyAsStream()) { int b; while ((b = responseStream.read()) != -1) { response.getOutputStream().write(b); } } response.getOutputStream().flush(); } catch (HttpException e) { writer.write(e.toString()); throw e; } catch (IOException e) { e.printStackTrace(); writer.write(e.toString()); throw e; } finally { if (method != null) method.releaseConnection(); } }
From source file:geotheme.servlet.wms.java
/** * @see HttpServlet#service(HttpServletRequest req, HttpServletResponse res) *//* w ww .ja v a 2 s. c o m*/ protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { OutputStreamWriter wr = null; InputStream in = null; OutputStream out = null; //req.setCharacterEncoding("UTF-8"); try { Map<String, Object> reqMap = new HashMap<String, Object>(); Enumeration<?> en = req.getParameterNames(); String key = new String(); /** * Converting all Map Keys into Upper Case **/ while (en.hasMoreElements()) { key = (String) en.nextElement(); reqMap.put(key.toUpperCase(), req.getParameter(key)); } wmsParamBean wmsBean = new wmsParamBean(); BeanUtils.populate(wmsBean, reqMap); HttpSession session = req.getSession(true); /** * Reading the saved SLD **/ String sessionName = wmsBean.getLAYER(); if (sessionName.length() < 1) sessionName = wmsBean.getLAYERS(); if (session.getAttribute(sessionName) != null) { wmsBean.setSLD_BODY((String) session.getAttribute(sessionName)); wmsBean.setSLD(""); wmsBean.setSTYLES(""); } if (wmsBean.getREQUEST().compareToIgnoreCase("GetPDFGraphic") == 0) { /** * Generate PDF Request */ generatePDF pdf = new generatePDF(this.pdfURL, this.pdfLayers); ByteArrayOutputStream baos = pdf.createPDFFromImage(wmsBean, this.geoserverURL); res.addHeader("Content-Type", "application/force-download"); res.addHeader("Content-Disposition", "attachment; filename=\"MapOutput.pdf\""); res.getOutputStream().write(baos.toByteArray()); } else { /** * Generating Map from GeoServer **/ URL geoURL = new URL(this.geoserverURL); URLConnection geoConn = geoURL.openConnection(); geoConn.setDoOutput(true); wr = new OutputStreamWriter(geoConn.getOutputStream(), "UTF-8"); wr.write(wmsBean.getURL_PARAM()); wr.flush(); in = geoConn.getInputStream(); out = res.getOutputStream(); res.setContentType(wmsBean.getFORMAT()); int b; while ((b = in.read()) != -1) { out.write(b); } } } catch (Exception e) { //e.printStackTrace(); } finally { if (out != null) { out.flush(); out.close(); } if (in != null) { in.close(); } if (wr != null) { wr.close(); } } }
From source file:net.jotel.ws.client.WebSocketClient.java
private void handshake() throws IOException { OutputStreamWriter writer = new OutputStreamWriter(outputStream, Charset.forName("UTF8")); // Once a connection to the server has been established (including a // connection via a proxy or over a TLS-encrypted tunnel), the client // MUST send an opening handshake to the server. The handshake consists // of an HTTP upgrade request, along with a list of required and // optional headers. The requirements for this handshake are as // follows.//from www . ja v a 2 s . co m // 1. The handshake MUST be a valid HTTP request as specified by // [RFC2616]. // 2. The Method of the request MUST be GET and the HTTP version // MUST be at least 1.1. log.debug("Upgrade request"); // 3. The request MUST contain a "Request-URI" as part of the GET // method. This MUST match the /resource name/ Section 3 (a // relative URI), or be an absolute URI that, when parsed, has a // matching /resource name/ as well as matching /host/, /port/, and // appropriate scheme (ws or wss). writer.write("GET "); writer.write(resourceName); writer.write(" HTTP/1.1\r\n"); // 4. The request MUST contain a "Host" header whose value is equal to // /host/. writer.write(HOST_HEADER); writer.write(": "); writer.write(host); writer.write(CRLF); // 5. The request MUST contain an "Upgrade" header whose value is // equal to "websocket". writer.write(UPGRADE_HEADER); writer.write(": websocket\r\n"); // 6. The request MUST contain a "Connection" header whose value MUST // include the "Upgrade" token. writer.write(CONNECTION_HEADER); writer.write(": Upgrade\r\n"); // 7. The request MUST include a header with the name "Sec-WebSocket- // Key". The value of this header MUST be a nonce consisting of a // randomly selected 16-byte value that has been base64-encoded // [RFC3548]. The nonce MUST be selected randomly for each // connection. SecWebSocketKey key = generateSecWebSocketKey(); writer.write(SEC_WEB_SOCKET_KEY_HEADER); writer.write(": "); writer.write(key.getKey()); writer.write(CRLF); // 8. The request MUST include a header with the name "Sec-WebSocket- // Origin" if the request is coming from a browser client. If the // connection is from a non-browser client, the request MAY include // this header if the semantics of that client match the use-case // described here for browser clients. The value of this header // MUST be the ASCII serialization of origin of the context in // which the code establishing the connection is running, and MUST // be lower-case. The value MUST NOT contain letters in the range // U+0041 to U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL // LETTER Z) [I-D.ietf-websec-origin]. The ABNF is as defined in // Section 6.1 of [I-D.ietf-websec-origin]. writer.write(ORIGIN_HEADER); writer.write(": "); writer.write(origin); writer.write(CRLF); // 9. The request MUST include a header with the name "Sec-WebSocket- // Version". The value of this header MUST be 8. writer.write(SEC_WEB_SOCKET_VERSION_HEADER); writer.write(": 8\r\n"); // 10. The request MAY include a header with the name "Sec-WebSocket- // Protocol". If present, this value indicates the subprotocol(s) // the client wishes to speak, ordered by preference. The elements // that comprise this value MUST be non-empty strings with // characters in the range U+0021 to U+007E not including separator // characters as defined in [RFC2616], and MUST all be unique // strings. The ABNF for the value of this header is 1#token, // where the definitions of constructs and rules are as given in // [RFC2616]. // if (!StringUtils.isBlank(protocol)) { writer.write(SEC_WEB_SOCKET_PROTOCOL_HEADER); writer.write(": "); writer.write(protocol); writer.write(CRLF); } // 11. The request MAY include a header with the name "Sec-WebSocket- // Extensions". If present, this value indicates the protocol- // level extension(s) the client wishes to speak. The // interpretation and format of this header is described in // Section 9.1. // TODO // 12. The request MAY include headers associated with sending cookies, // as defined by the appropriate specifications // [I-D.ietf-httpstate-cookie]. These headers are referred to as // _Headers to Send Appropriate Cookies_. // // TODO // extra headers for (Map.Entry<String, String> entry : extraHeaders.entrySet()) { writer.write(entry.getKey()); writer.write(": "); writer.write(entry.getValue()); writer.write(CRLF); } writer.write(CRLF); writer.flush(); // Once the client's opening handshake has been sent, the client MUST // wait for a response from the server before sending any further data. String code = readStatusCode(inputStream); log.debug("Server response code {}", code); // The client MUST validate the server's response as follows: // 1. If the status code received from the server is not 101, the // client handles the response per HTTP procedures. Otherwise, // proceed as follows. if (!"101".equals(code)) { throw new WebSocketException("Invalid handshake response"); } Map<String, List<String>> fieldMap = readFields(inputStream); String value; // 2. If the response lacks an "Upgrade" header or the "Upgrade" header // contains a value that is not an ASCII case-insensitive match for // the value "websocket", the client MUST _Fail the WebSocket // Connection _. value = getFieldValue(fieldMap, "upgrade"); if (!"WebSocket".equalsIgnoreCase(value)) { throw new WebSocketException("Expected WebSocket as Updgrade field value!"); } // 3. If the response lacks a "Connection" header or the "Connection" // header contains a value that is not an ASCII case-insensitive // match for the value "Upgrade", the client MUST _Fail the // WebSocket Connection_. value = getFieldValue(fieldMap, "connection"); if (!UPGRADE_HEADER.equalsIgnoreCase(value)) { throw new WebSocketException("Expected Upgrade as Connection field value!"); } // 4. If the response lacks a "Sec-WebSocket-Accept" header or the // "Sec-WebSocket-Accept" contains a value other than the base64- // encoded SHA-1 of the concatenation of the "Sec-WebSocket-Key" (as // a string, not base64-decoded) with the string "258EAFA5-E914- // 47DA-95CA-C5AB0DC85B11", the client MUST _Fail the WebSocket // Connection_ value = getFieldValue(fieldMap, "sec-websocket-accept"); if (!key.isServerKeyValid(value)) { throw new WebSocketException("Server key doesn't match an expected response"); } // 5. If the response includes a "Sec-WebSocket-Extensions" header, and // this header indicates the use of an extension that was not // present in the client' handshake (the server has indicated an // extension not requested by the client), the client MUST _Fail the // WebSocket Connection_. (The parsing of this header to determine // which extensions are requested is discussed in Section 9.1.) value = getFieldValue(fieldMap, "sec-websocket-extensions"); if (!StringUtils.isEmpty(value)) { throw new WebSocketException("The server has indicated an extension not request by the client!"); } if (fieldMap.containsKey("")) { throw new WebSocketException("Empty field name found in field list!"); } // If the server's response is validated as provided for above, it is // said that _The WebSocket Connection is Established_ and that the // WebSocket Connection is in the OPEN state. The _Extensions In Use_ // is defined to be a (possibly empty) string, the value of which is // equal to the value of the |Sec-WebSocket-Extensions| header supplied // by the server's handshake, or the null value if that header was not // present in the server's handshake. The _Subprotocol In Use_ is // defined to be the value of the |Sec-WebSocket-Protocol| header in the // server's handshake, or the null value if that header was not present // in the server's handshake. Additionally, if any headers in the // server's handshake indicate that cookies should be set (as defined by // [I-D.ietf-httpstate-cookie]), these cookies are referred to as // _Cookies Set During the Server's Opening Handshake_. }