/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.framework.http;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.ApplicationContext;
import com.esri.gpt.framework.util.KmlUtil;
import com.esri.gpt.framework.util.Val;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
/**
* Character based handler for the content of an HTTP response body.
*/
public class CharacterHandler extends ContentHandler {
/** instance variables ====================================================== */
private Writer writer;
/** constructors ============================================================ */
/**
* Constructs with a supplied character writer.
* @param writer the character writer
*/
public CharacterHandler(Writer writer) {
super();
this.setWriter(writer);
}
/** properties ============================================================= */
/**
* Gets the writer to which the HTTP response is written.
* @return the character writer
*/
public Writer getWriter() {
return this.writer;
}
/**
* Sets the writer to which the HTTP response is written.
* @param writer the character writer
*/
private void setWriter(Writer writer) {
this.writer = writer;
}
/**
* Determines the character encoding associated with the HTTP response.
* @param request the HTTP request that was executed
* @return the encoding
*/
protected String determineEncoding(HttpClientRequest request) {
String encoding = request.getResponseInfo().getContentEncoding();
if ((encoding == null) || (encoding.length() == 0)) {
encoding = request.getResponseInfo().getDefaultEncoding();
}
if ((encoding == null) || (encoding.length() == 0)) {
encoding = "UTF-8";
}
return encoding;
}
/**
* Handle the content associated with an HTTP response body.
* @param request the HTTP request that was executed
* @param responseStream the stream associated with the HTTP response body
* @throws IOException if an exception occurs
*/
@Override
public void readResponse(HttpClientRequest request, InputStream responseStream)
throws IOException {
InputStreamReader ir = null;
String ct = request.getResponseInfo().getContentType();
boolean kmz = (ct != null) && (ct.toLowerCase().indexOf("application/vnd.google-earth.kmz") != -1);
if (kmz) {
ir = new InputStreamReader(KmlUtil.extractKmlStream(responseStream),this.determineEncoding(request));
long nChars = this.executeIO(ir,this.getWriter());
request.getResponseInfo().setCharactersRead(nChars);
} else {
// some sites do not return a response body charset encoding within the
// HTTP response header, for XML responses - peek for the XML encoding
boolean peekForXmlEncoding = false;
String encoding = request.getResponseInfo().getContentEncoding();
if ((encoding == null) || (encoding.length() == 0)) {
String lct = Val.chkStr(ct).toLowerCase();
if (lct.endsWith("/xml") || lct.endsWith("+xml")) {
StringAttributeMap params = ApplicationContext.getInstance().getConfiguration().getCatalogConfiguration().getParameters();
String param = params.getValue("HttpClientRequest.allowPeekForXmlEncoding");
peekForXmlEncoding = !Val.chkStr(param).equalsIgnoreCase("false");
}
}
if (!peekForXmlEncoding) {
ir = new InputStreamReader(responseStream,this.determineEncoding(request));
long nChars = this.executeIO(ir,this.getWriter());
request.getResponseInfo().setCharactersRead(nChars);
} else {
// peak for the encoding
ByteArrayHandler byteHandler = new ByteArrayHandler();
long nBytes = this.executeIO(responseStream,byteHandler.getOutputStream());
if (nBytes > 0) {
byte[] bytes = byteHandler.getContent();
String chars = new String(bytes,"UTF-8");
chars = Val.removeBOM(Val.chkStr(chars));
if (chars.startsWith("<?xml")) {
int nIdx1 = chars.indexOf(" encoding=");
int nIdx2 = chars.indexOf("?>");
if ((nIdx1 != -1) && (nIdx2 != -1) && (nIdx2 > nIdx1)) {
String tmp = Val.chkStr(chars.substring(nIdx1+10,nIdx2));
if (tmp.length() > 2) {
tmp = Val.chkStr(tmp.substring(1,tmp.length()-1));
if (tmp.length() > 0) {
try {
String encoding2 = tmp;
String chars2 = new String(bytes,encoding2);
chars = chars2;
} catch (IOException etmp) {}
}
}
}
}
this.getWriter().write(chars);
request.getResponseInfo().setCharactersRead(chars.length());
}
}
}
}
}