2.3.3. fejezet, Szerver válasz kódolási receptek
A szerver kimenetét megfelelően kódolni kell. Az UTF-8 karakter kódolás jó választás, mivel mindkét böngésző támogatja, és nemzetközi tartalomgenerálásra általánosan használható.
private void transferToOutput(Document content, HttpServletResponse response) throws IOException { ServletOutputStream out = response.getOutputStream(); if (content != null) { response.setCharacterEncoding("utf-8"); response.setContentType("text/xml"); config.getResourceContainer().writeLog("Begining of XML result transfer.", Level.INFO); if (generateDebugInfo) { ByteArrayOutputStream ostream = new ByteArrayOutputStream(); OutputStreamWriter sout = new OutputStreamWriter(ostream, "utf-8"); XMLTk.transfer(content, sout); content = null; ostream.writeTo(out); config.getResourceContainer().writeLog(ostream, Level.INFO); } else { OutputStreamWriter sout = new OutputStreamWriter(out, "utf-8"); XMLTk.transfer(content, sout); sout.flush(); content = null; } out.flush(); config.getResourceContainer().writeLog("End of XML result transfer.", Level.INFO); } out.close(); }
Multipart módon küldve többféle tartalom egybe fűzhető, habár az IE6 ezt a módszert nem támogatja.
public void transferToOutputMultipart(Document content, HttpServletResponse response) throws IOException { // multipart result generator (jquery.forms not supported) String BOUNDARY_STR = getBoundaryStr(); String BOUNDARY_START = "--" + BOUNDARY_STR; String BOUNDARY_END = BOUNDARY_START + "--"; response.setContentType("multipart/x-mixed-replace;boundary=\"" + BOUNDARY_STR + "\""); ServletOutputStream out = response.getOutputStream(); int partCount = 0; if (content != null) {//While cycle for each part out.println(BOUNDARY_START); response.setCharacterEncoding("utf-8"); out.println("Content-type: text/xml;charset=utf-8\n"); config.getResourceContainer().writeLog("Begining of Multipart "+partCount+". part XML result transfer.", Level.INFO); if (generateDebugInfo) { ByteArrayOutputStream ostream = new ByteArrayOutputStream(); OutputStreamWriter sout = new OutputStreamWriter(ostream, "utf-8"); XMLTk.transfer(content, sout); content = null; ostream.writeTo(out); config.getResourceContainer().writeLog(ostream, Level.INFO); } else { OutputStreamWriter sout = new OutputStreamWriter(out, "utf-8"); XMLTk.transfer(content, sout); content = null; sout.flush(); } out.flush(); config.getResourceContainer().writeLog("End of Multipart "+partCount+". part XML result transfer.", Level.INFO); partCount++; } // serviceCall.getMediaResultIterator(); if (partCount > 0) { out.println(BOUNDARY_END); out.flush(); } out.close(); }
Az elválasztó karaktereket MD5 algoritmussal előállítva elkerülhető a küldött tartalomba véletlenül bekerülő elválasztó karakterek multipart rész lezáróként történő félreértése.
public static String getMD5Sum(byte[] value) throws NoSuchAlgorithmException{ MessageDigest algorithm = MessageDigest.getInstance("MD5"); algorithm.reset(); algorithm.update(value); byte messageDigest[] = algorithm.digest(); StringBuffer hexString = new StringBuffer(); for (int i = 0; i < messageDigest.length; i++) { hexString.append(Integer.toHexString(0xFF & messageDigest[i])); } return hexString.toString(); }
Érdemes a value értékébe az aktuális dátumot betenni.
private String getBoundaryStr() { Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("Europa/Budapest")); String BOUNDARY_STR = null; long time = calendar.getTimeInMillis(); byte[] defaultBytes = Long.toHexString(time).getBytes(); try { BOUNDARY_STR = StrTk.getMD5Sum(defaultBytes); } catch (NoSuchAlgorithmException e) { BOUNDARY_STR = "0x34243285923167467324"; } return BOUNDARY_STR; }
UTF-8 XML dokumentum kiírása az OutputStream-re nem is olyan egyszerű. Fontos használni a PI_DISABLE_OUTPUT_ESCAPING feldolgozási utasítást, mivel máskülönben az adatbázisban tárolt speciális karakterek, mint például az & átalakul & formába, ami rossz eredményre vezethet a html tartalom előállításánál. Ez esetben korábban a szerkesztőmezőbe beírt & tartalmat újabb szerkesztéskor &amp;-ként láthatjuk viszont, és ez persze nem egyezik meg az előzőleg elmentett értékkel.
public static void transfer(Document content, OutputStreamWriter out) { try { Node root = content.getFirstChild(); if (root != null) { ProcessingInstruction pi = content.createProcessingInstruction(Result.PI_DISABLE_OUTPUT_ESCAPING, ""); root.getParentNode().insertBefore(pi, root); } Transformer serializer = TransformerFactory.newInstance().newTransformer(); serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); serializer.setOutputProperty(OutputKeys.INDENT, "yes"); serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8"); serializer.setOutputProperty(OutputKeys.METHOD, "xml"); DOMSource source = new DOMSource(content); StreamResult result = new StreamResult(out); serializer.transform(source, result); } catch (TransformerConfigurationException ex) { } catch (TransformerException ex) { }
StringBuffer tartalom összeállításánál érdemes HTML enkódolást alkalmazi az adatbázisból származó speciális karakterek átalakítására. Így elkerülhető a tartalom összeférhetetlensége az XML tagokkal.
public static boolean isXMLCompliant(char c) { int type = Character.getType(c); boolean result = Character.isLetterOrDigit(c) || Character.isWhitespace(c) || type == Character.DASH_PUNCTUATION || type == Character.START_PUNCTUATION || type == Character.END_PUNCTUATION || type == Character.CONNECTOR_PUNCTUATION || type == Character.MATH_SYMBOL || type == Character.OTHER_PUNCTUATION; return result && (c != '&') && (c != '<'); } public static String HTMLEnc(String s) { StringBuffer buff = new StringBuffer(); int len = (s == null ? -1 : s.length()); for (int i = 0; i < len; i++) { char c = s.charAt(i); if (isXMLCompliant(c)) buff.append(c); else buff.append("&#" + (int) c + ";"); } return buff.toString();
- A hozzászóláshoz be kell jelentkezni