/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2003 - 2007 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package com.funambol.syncclient.spds;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.microedition.io.HttpConnection;
import javax.microedition.io.Connector;
import com.funambol.syncclient.util.StaticDataHelper;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.RadioInfo;
/**
* Rapresents a HTTP client implementation
*
*/
public final class SyncMLClientImpl {
private static final String PROP_MICROEDITION_CONFIGURATION = "microedition.configuration";
private static final String PROP_CONTENT_LANGUAGE = "Content-Language";
private static final String PROP_CONTENT_LENGTH = "Content-Length";
private static final String PROP_CONTENT_TYPE = "Content-Type";
private static final String PROP_MICROEDITION_LOCALE = "microedition.locale";
private static final String PROP_MICROEDITION_PROFILES = "microedition.profiles";
private static final String PROP_USER_AGENT = "User-Agent";
private final String requestURL;
/**
*
* @param requestURL must be non-null
*
*/
public SyncMLClientImpl(final String requestURL) throws IOException
{
if (requestURL == null)
{
throw new NullPointerException("request URL parameter is null");
}
this.requestURL = requestURL;
}
/**
*
* @param request HTTP request
* @return HTTP response
*/
public String sendMessage(final String request) throws Exception,
IOException,
NetworkException {
StaticDataHelper.log("*************************************************");
HttpConnection httpCon = null;
DataInputStream inputStream = null;
DataOutputStream outputStream = null;
int rc = 0;
StringBuffer b = null;
byte[] data = null;
synchronized (this) {
boolean signal = true;
if ((RadioInfo.getState() != RadioInfo.STATE_ON) ||
(RadioInfo.getSignalLevel() == RadioInfo.LEVEL_NO_COVERAGE)) {
signal = false;
}
if (!signal) {
throw new NetworkException();
}
try {
StaticDataHelper sdh = new StaticDataHelper();
byte[] dataToSend = request.getBytes();//the SyncML message to send in byte form
// ----------------------------------------------------------------------------------------------------------
String sessionId = SyncManagerImpl.session_id;
StaticDataHelper.log("### Opening the connection nr. " + ++(SyncManagerImpl.c) + " in session " + sessionId);
httpCon = (HttpConnection)Connector.open(requestURL + ";deviceside=true");//'true' direct TCP, 'false' proxy TCP (MDS)
String url = httpCon.getURL();
String jsessionid;
String jsessionidParam = "jsessionid=";
String devicesideParam = ";deviceside=";
//StaticDataHelper.log("[DEBUG] URL: " + url);
int startIndex = url.indexOf(jsessionidParam) + jsessionidParam.length();
int endIndex = url.indexOf(devicesideParam);
//StaticDataHelper.log("[DEBUG] startIndex: " + startIndex);
//StaticDataHelper.log("[DEBUG] endIndex: " + endIndex);
if (url.indexOf(jsessionidParam) != -1 && endIndex != -1) {
jsessionid = url.substring(startIndex, endIndex);
} else {
jsessionid = "jsessionid from server not yet available";
}
StaticDataHelper.log("### Connection nr. " + SyncManagerImpl.c + " in session " + sessionId + " [" + jsessionid + "] opened");
// --------------------------------------------------------------------------------------------------------------------------------------
httpCon.setRequestMethod(HttpConnection.POST);
httpCon.setRequestProperty (PROP_USER_AGENT,
"BlackBerry/" + sdh.getOS());
httpCon.setRequestProperty (PROP_CONTENT_LENGTH,
String.valueOf(dataToSend.length));
httpCon.setRequestProperty (PROP_CONTENT_TYPE,
"application/vnd.syncml+xml");
String locale = System.getProperty(PROP_MICROEDITION_LOCALE);
if (locale != null) {
httpCon.setRequestProperty(PROP_CONTENT_LANGUAGE, locale);
}
outputStream = httpCon.openDataOutputStream();
outputStream.write(dataToSend);
outputStream.flush();
inputStream = httpCon.openDataInputStream();
int size = (int)httpCon.getLength();//in an HTTP connection it has to be the value of the
//'content-length' header field. When not known, -1
b = new StringBuffer(size >= 0 ? (int)size : 4096);
if (size != -1) {
// Read content-Length bytes, or until max is reached.
int ch = 0;
for (int i = 0; i < size; i++) {
if ((ch = inputStream.read()) != -1) {
b.append((char)ch);
}
}
} else {
// Read til the connection is closed, or til max is reached.
// (Typical HTTP/1.0 script generated output)
int ch = 0;
size = 0;
while ((ch = inputStream.read()) != -1) {
b.append((char)ch);
}
}
data = b.toString().getBytes();
}//end try
catch (Exception e) {
StaticDataHelper.log(">>> Exception in SyncMLClientImpl.sendMessage(request): " + e.toString());
throw e;
}
finally {
if (inputStream != null) {
inputStream.close();
inputStream = null;
}
if (outputStream != null) {
outputStream.close();
outputStream = null;
}
if (httpCon != null) {
// ----------------------------------------------------------------------------------------------------
String url = httpCon.getURL();
String sessionId = SyncManagerImpl.session_id;
String jsessionid;
String jsessionidParam = "jsessionid=";
String devicesideParam = ";deviceside=";
//StaticDataHelper.log("[DEBUG] URL: " + url);
int startIndex = url.indexOf(jsessionidParam) + jsessionidParam.length();
int endIndex = url.indexOf(devicesideParam);
//StaticDataHelper.log("[DEBUG] startIndex: " + startIndex);
//StaticDataHelper.log("[DEBUG] endIndex: " + endIndex);
if (url.indexOf(jsessionidParam) != -1 && endIndex != -1) {
jsessionid = url.substring(startIndex, endIndex);
} else {
jsessionid = "jsessionid from server not yet available";
}
StaticDataHelper.log("### Closing connection nr. " + SyncManagerImpl.c + " for session " + sessionId + " [" + jsessionid + "]");
httpCon.close();
StaticDataHelper.log("### Connection nr. " + SyncManagerImpl.c + " closed");
// ----------------------------------------------------------------------------------------------------
httpCon = null;
}
}
}//end synchronized
return new String(data);
}//end sendMessage
}