Java tutorial
/* * This software code is (c) 2010 T-Mobile USA, Inc. All Rights Reserved. * * Unauthorized redistribution or further use of this material is * prohibited without the express permission of T-Mobile USA, Inc. and * will be prosecuted to the fullest extent of the law. * * Removal or modification of these Terms and Conditions from the source * or binary code of this software is prohibited. In the event that * redistribution of the source or binary code for this software is * approved by T-Mobile USA, Inc., these Terms and Conditions and the * above copyright notice must be reproduced in their entirety and in all * circumstances. * * No name or trademarks of T-Mobile USA, Inc., or of its parent company, * Deutsche Telekom AG or any Deutsche Telekom or T-Mobile entity, may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" AND "WITH ALL FAULTS" BASIS * AND WITHOUT WARRANTIES OF ANY KIND. ALL EXPRESS OR IMPLIED * CONDITIONS, REPRESENTATIONS OR WARRANTIES, INCLUDING ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT CONCERNING THIS SOFTWARE, ITS SOURCE OR BINARY CODE * OR ANY DERIVATIVES THEREOF ARE HEREBY EXCLUDED. T-MOBILE USA, INC. * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE * OR ITS DERIVATIVES. IN NO EVENT WILL T-MOBILE USA, INC. OR ITS * LICENSORS BE LIABLE FOR LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT * OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF T-MOBILE USA, * INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * THESE TERMS AND CONDITIONS APPLY SOLELY AND EXCLUSIVELY TO THE USE, * MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE, ITS SOURCE OR BINARY * CODE OR ANY DERIVATIVES THEREOF, AND ARE SEPARATE FROM ANY WRITTEN * WARRANTY THAT MAY BE PROVIDED WITH A DEVICE YOU PURCHASE FROM T-MOBILE * USA, INC., AND TO THE EXTENT PERMITTED BY LAW. */ package javax.microedition.ims.core.xdm; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.conn.scheme.Scheme; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.SocketTimeoutException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; //import android.os.SystemProperties; import javax.microedition.ims.DefaultStackContext; import javax.microedition.ims.StackHelper; import javax.microedition.ims.common.IMSMessage; import javax.microedition.ims.common.Logger; import javax.microedition.ims.common.RepetitiousTaskManager; import javax.microedition.ims.common.Shutdownable; import javax.microedition.ims.config.Configuration; import javax.microedition.ims.core.AkaException; import javax.microedition.ims.core.IMSStack; import javax.microedition.ims.core.IMSStackException; import javax.microedition.ims.core.StackContext; import javax.microedition.ims.core.auth.AKAAuthProviderMockImpl; import javax.microedition.ims.core.auth.AuthUtil; import javax.microedition.ims.core.auth.DigestUtils; import javax.microedition.ims.core.connection.ConnState; import javax.microedition.ims.core.connection.ConnectionDataProvider; import javax.microedition.ims.core.connection.ConnectionDataProviderConfigVsDnsImpl; import javax.microedition.ims.core.env.DefaultScheduledService; import javax.microedition.ims.core.env.EnvironmentDefaultImpl; import javax.microedition.ims.core.messagerouter.MessageRouterComposite; import javax.microedition.ims.core.messagerouter.MessageRouterMSRP; import javax.microedition.ims.core.messagerouter.MessageRouterSIP; import javax.microedition.ims.core.registry.DefaultStackRegistry; import javax.microedition.ims.core.sipservice.AbstractService; import javax.microedition.ims.core.transaction.TransactionManager; import javax.microedition.ims.core.xdm.data.DocumentBean; import javax.microedition.ims.core.xdm.data.DocumentDataBean; import javax.microedition.ims.dns.DNSResolverDNSJavaImpl; //import javax.microedition.ims.entrypoint.MockStackRegistryHelper; //import javax.microedition.ims.entrypoint.config.MockConfBuilderRegistry; import javax.microedition.ims.messages.parser.message.ChallengeParser; import javax.microedition.ims.messages.wrappers.sip.AuthenticationChallenge; import javax.microedition.ims.transport.messagerouter.Router; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; /** * User: Pavel Laboda (pavel.laboda@gmail.com) Date: 19.4.2010 Time: 17.30.11 */ public class XDMServiceImpl extends AbstractService implements XDMService, Shutdownable { private static final String TAG = "XDMServiceImpl"; private static final String DIGEST_TEMPLATE = "Digest username=\"#uname\", realm=\"#realm\", nonce=\"#nonce\", uri=\"#uri\", response=\"#responce\", opaque=\"#opaque\", qop=#qop, nc=#nc, cnonce=\"#cnonce\""; private static final String DIGEST = "Digest username=\"sip:movial11@dummy.com\", realm=\"dummy.com\", nonce=\"905af2e3e13a653da86bd3d32c820689\", uri=\"/services/resource-lists/users/sip:movial11@dummy.com\", response=\"ae5a6e2877402d6f8991818efaa05aa0\", opaque=\"21b11c1ec137d891c338a8c65c940ec3\", qop=auth, nc=00000003, cnonce=\"14d3e1cd6398960c\""; private static final String WRONG_DIGEST = "Digest username=\"sip:movial11@dummy.com\", realm=\"dummy.com\", nonce=\"05af2e3e13a653da86bd3d32c820689\", uri=\"/services/resource-lists/users/sip:movial11@dummy.com\", response=\"ae5a6e2877402d6f8991818efaa05aa0\", opaque=\"21b11c1ec137d891c338a8c65c940ec3\", qop=auth, nc=00000003, cnonce=\"14d3e1cd6398960c\""; private static final String DIGEST2 = "Digest username=\"sip:movial11@dummy.com\", realm=\"dummy.com\", nonce=\"403f83140fbf864a9110a29258e5dea7\", uri=\"/services/org.openmobilealliance.xcap-directory/users/sip%3Amovial11%40dummy.com/directory.xml\", response=\"20452a026e0da8e8db71b8d5e7a429e2\", opaque=\"b3addfe60e740417d60d2059b1aa43c6\", qop=auth, nc=00000005, cnonce=\"d776de233ae90908\""; private static final String URL_STR = "http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial11@dummy.com/index"; // http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial11@dummy.com/index/~~/resource-lists/list/entry[@uri="tel:19728881041"] private static final String documentListXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + "<xcap-directory xmlns=\"urn:oma:xml:xdm:xcap-directory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n" + " <folder auid=\"org.openmobilealliance.group-usage-list\"/>\n" + " <folder auid=\"simservs.ngn.etsi.org\"/>\n" + " <folder auid=\"resource-lists\">\n" + " <entry uri=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip%3Amovial11%40dummy.com/index\" etag=\"W/'437-1271417541984'\" last-modified=\"2010-04-16T13:32:21.000+02:00\" size=\"437\"/>\n" + " </folder>\n" + " <folder auid=\"org.openmobilealliance.USER-profile\"/>\n" + " <folder auid=\"pidf-manipulation\"/>\n" + " <folder auid=\"pres-rules\"/>\n" + " <folder auid=\"rls-services\">\n" + " <entry uri=\"http://siptest.dummy.com:8080/services/rls-services/users/sip%3Amovial11%40dummy.com/index\" etag=\"W/'435-1261478532956'\" last-modified=\"2009-12-22T11:42:12.000+01:00\" size=\"435\"/>\n" + " </folder>\n" + " <folder auid=\"org.openmobilealliance.pres-rules\"/>\n" + " <folder auid=\"org.openmobilealliance.pres-content\"/>\n" + " <folder auid=\"org.openmobilealliance.access-rules\"/>\n" + " <folder auid=\"org.openmobilealliance.groups\"/>\n" + "</xcap-directory>"; private final DocumentBuilder db; private final AtomicReference<AuthenticationChallenge> lastChallenge = new AtomicReference<AuthenticationChallenge>( null); private static final String LIST_NODE_NAME = "list"; private static final String DEFAULT_CHARSET = "UTF-8"; private static final String CHARSET_NAME = DEFAULT_CHARSET; private static final int BUFF_SIZE = 10 * 1024; private static class HttpClientHolder { private static HttpClient httpClient = createHttpClient(); private static HttpClient createHttpClient() { /* * HttpParams parameters = new BasicHttpParams(); SchemeRegistry * schemeRegistry = new SchemeRegistry(); //SSLSocketFactory * sslSocketFactory = SSLSocketFactory.getSocketFactory(); * LayeredSocketFactory sslSocketFactory = new * EasySSLSocketFactory(); * //sslSocketFactory.setHostnameVerifier(SSLSocketFactory * .ALLOW_ALL_HOSTNAME_VERIFIER); schemeRegistry.register(new * Scheme("https", sslSocketFactory, 443)); ClientConnectionManager * manager = new ThreadSafeClientConnManager(parameters, * schemeRegistry); HttpClient httpClient = new * DefaultHttpClient(manager, parameters); */ HttpParams httpParamters = new BasicHttpParams(); int timeoutConnection = 3000; HttpConnectionParams.setConnectionTimeout(httpParamters, timeoutConnection); int timeoutSocket = 5000; HttpConnectionParams.setSoTimeout(httpParamters, timeoutSocket); final HttpClient httpClient = new DefaultHttpClient(httpParamters); try { prepareHttpClient(httpClient); } catch (InstantiationException e) { Logger.log(TAG, e.getMessage()); } return httpClient; } private static void prepareHttpClient(HttpClient httpClient) throws InstantiationException { javax.net.ssl.SSLSocketFactory nativeSslSocketFactory; try { SSLContext sc = SSLContext.getInstance("TLS"); sc.init(null, new TrustManager[] { new FakeX509TrustManager() }, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(nativeSslSocketFactory = sc.getSocketFactory()); // SSLCertificateSocketFactory sslCertificateSocketFactory = new // SSLCertificateSocketFactory(500); // HttpsURLConnection.setDefaultSSLSocketFactory(sslCertificateSocketFactory); } catch (NoSuchAlgorithmException e) { Logger.log(TAG, e.getMessage()); throw new InstantiationException(e.getMessage()); } catch (KeyManagementException e) { Logger.log(TAG, e.getMessage()); throw new InstantiationException(e.getMessage()); } EasySSLSocketFactory sslSocketFactory = new EasySSLSocketFactory(nativeSslSocketFactory); sslSocketFactory.setHostnameVerifier(new AcceptAllHostnameVerifier()); Scheme httpsShema = new Scheme("https", sslSocketFactory, 443); httpClient.getConnectionManager().getSchemeRegistry().register(httpsShema); } } public XDMServiceImpl(StackContext stackContext, TransactionManager transactionManager) throws IMSStackException { super(stackContext, transactionManager); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { db = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new IMSStackException(e); } } public XDMResponse sendXCAPRequest(final XDMRequest request) throws XCAPException, SAXException { Logger.log("XCAP REQUEST", "------------------------------ Request Begin ------------------------------"); Logger.log("XCAP REQUEST", "METHOD: " + request.getMethod()); Logger.log("XCAP REQUEST", "URI: " + request.getURI()); Logger.log("XCAP REQUEST", "HEADERS: " + request.getHeaders()); Logger.log("XCAP REQUEST", "TYPE: " + request.getEntityType()); Logger.log("XCAP REQUEST", "ID: " + request.getIMSEntityId()); Logger.log("XCAP REQUEST", "BODY: " + request.getBody()); Logger.log("XCAP REQUEST", "------------------------------ Request End ------------------------------"); // final String content = "content goes here"; // final String etag = "etag goes here"; // final String mimeType = "mime type goes here"; XDMResponse retValue = null; final HttpClient httpclient = HttpClientHolder.httpClient; HttpResponse response = null; try { // prepare and send first request HttpRequestBase httpRequest = createHttpRequest(request); prepareUrlConnection(request, httpRequest, lastChallenge.get()); // HttpURLConnection urlConnection = (HttpURLConnection) // url.openConnection(); /* * System.out.println("AllowUserInteraction = " + * urlConnection.getAllowUserInteraction()); * System.out.println("DoInput = " + urlConnection.getDoInput()); * System.out.println("DoOutput = " + urlConnection.getDoOutput()); * System.out.println("DefaultUseCaches = " + * urlConnection.getDefaultUseCaches()); * System.out.println("InstanceFollowRedirects = " + * urlConnection.getInstanceFollowRedirects()); * System.out.println("UseCaches = " + * urlConnection.getUseCaches()); * System.out.println("DefaultAllowUserInteraction = " + * HttpURLConnection.getDefaultAllowUserInteraction()); * urlConnection.setDoInput(true); urlConnection.setDoOutput(true); * urlConnection.setAllowUserInteraction(true); * URLConnection.setDefaultAllowUserInteraction(true); */ printRequest(httpRequest); response = httpclient.execute(httpRequest); printResponse(response); // if (urlConnection.getResponseCode() == 401) {//this line causes // additional request to server without auth challenge boolean isAuthRequired = response.containsHeader("WWW-Authenticate"); if (isAuthRequired) { String wwwAuthenticateHeader = response.getFirstHeader("WWW-Authenticate").getValue(); AuthenticationChallenge challenge = (AuthenticationChallenge) ChallengeParser .consume(wwwAuthenticateHeader); lastChallenge.set(challenge); response.getEntity().consumeContent(); // prepare and send second request with auth HttpRequestBase httpRequestWithAuth = createHttpRequest(request); prepareUrlConnection(request, httpRequestWithAuth, challenge); printRequest(httpRequest); response = httpclient.execute(httpRequestWithAuth); printResponse(response); } int responseCode = response.getStatusLine().getStatusCode(); if (responseCode == HttpStatus.SC_OK || responseCode == 201) { final Header etagHeader = response.getFirstHeader("ETag"); Logger.log(TAG, "etagHeader: " + etagHeader); final Header contentTypeHeader = response.getFirstHeader("Content-Type"); Logger.log(TAG, "contentTypeHeader: " + contentTypeHeader); final byte[] content = extractBody(response); Logger.log(TAG, "extracted"); Logger.log(TAG, "BODY: " + (content != null ? new String(content, DEFAULT_CHARSET) : "")); retValue = new XDMResponseImpl(content == null ? null : db.parse(new ByteArrayInputStream(content)), content, etagHeader != null ? etagHeader.getValue() : null, contentTypeHeader != null ? contentTypeHeader.getValue() : null); } else { String reasonPhrase = response.getStatusLine().getReasonPhrase(); XCAPException xcapException = new XCAPException(responseCode, reasonPhrase); if (responseCode == HttpStatus.SC_CONFLICT) { // TODO Add XCAPError } throw xcapException; } } catch (SocketTimeoutException e) { Logger.log(TAG, e.getMessage()); XCAPException xcapException = new XCAPException(408, "Request Timeout"); throw xcapException; } catch (IOException e) { Logger.log(TAG, e.getMessage()); e.printStackTrace(); } finally { if (response != null) { try { if (response.getEntity() != null) response.getEntity().consumeContent(); } catch (IOException e) { e.printStackTrace(); } } } return retValue; } private void printRequest(HttpRequestBase httpRequest) { Logger.log(TAG, "------------------------------ Request Begin ------------------------------"); Logger.log(TAG, httpRequest.getRequestLine().toString()); for (Header header : httpRequest.getAllHeaders()) { Logger.log(TAG, header.getName() + " = " + header.getValue()); } Logger.log(TAG, "------------------------------ Request End ------------------------------"); } private void printResponse(HttpResponse response) throws IOException { Logger.log(TAG, "------------------------------ Response Begin ------------------------------"); Logger.log(TAG, response.getStatusLine().toString()); for (Header header : response.getAllHeaders()) { Logger.log(TAG, header.getName() + " = " + header.getValue()); } Logger.log(TAG, "------------------------------ Response End ------------------------------"); } private byte[] extractBody(HttpResponse response) throws IOException, UnsupportedEncodingException { byte[] content = null; HttpEntity responseEntity = response.getEntity(); long contentLength = responseEntity.getContentLength(); if (contentLength > 0) { content = EntityUtils.toByteArray(responseEntity); } return content; } /* * private byte[] readAllAndClose(final InputStream inputStream, final int * possibleStreamLength) throws IOException { byte[] content; * BufferedInputStream in = new BufferedInputStream(inputStream, BUFF_SIZE); * ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream( * possibleStreamLength); byte[] dataChunk = new byte[BUFF_SIZE]; int * redBytes = 0; while ((redBytes = in.read(dataChunk)) != -1) { * byteArrayOutputStream.write(dataChunk, 0, redBytes); } in.close(); * byteArrayOutputStream.close(); content = * byteArrayOutputStream.toByteArray(); return content; } */ private HttpRequestBase createHttpRequest(final XDMRequest request) { HttpMethod httpMethod = request.getMethod(); HttpRequestBase httpRequest; switch (httpMethod) { case GET: { httpRequest = new HttpGet(request.getURI()); break; } case PUT: httpRequest = new HttpPut(request.getURI()); break; case DELETE: httpRequest = new HttpDelete(request.getURI()); break; default: throw new IllegalArgumentException("Unsupported method: " + httpMethod); } return httpRequest; } private HttpRequestBase prepareUrlConnection(XDMRequest requestDescriptor, HttpRequestBase httpRequest, AuthenticationChallenge challenge) throws IOException { /* * if (request.getHeaders().get("Authorization") == null) { * urlConnection.setRequestProperty("Authorization", DIGEST); } */ if (challenge != null) { String digest = calcAuthResponse(requestDescriptor, challenge); httpRequest.addHeader("Authorization", digest); } for (Entry<String, String> mapEntry : requestDescriptor.getHeaders().entrySet()) { httpRequest.addHeader(mapEntry.getKey(), mapEntry.getValue()); } //String headerString = SystemProperties.get("ro.product.manufacturer") + "." + // SystemProperties.get("ro.product.model") + "." + // SystemProperties.get("ro.build.display.id"); String headerString = "Test.0.1"; httpRequest.addHeader("X-3GPP-Intended-Identity", "\"" + getStackContext().getRegistrationIdentity().getUserInfo().toUri() + "\""); httpRequest.addHeader("XCAP-User-Agent", headerString); String requestBody = requestDescriptor.getBody(); if (httpRequest instanceof HttpPut) { HttpPut httpPutRequest = ((HttpPut) httpRequest); if (requestBody != null && !requestBody.equals("")) { StringEntity dataEntity = new StringEntity(requestDescriptor.getBody(), CHARSET_NAME); httpPutRequest.setEntity(dataEntity); } } return httpRequest; } // see examples at // http://potaroo.net/ietf/all-ids/draft-smith-sip-auth-examples-00.txt private String calcAuthResponse(XDMRequest request, AuthenticationChallenge challenge) { final XDMConfig xdmConfig = getStackContext().getConfig().getXDMConfig(); final String userName = xdmConfig.getAuthName(); final String realm = challenge.getRealm(); final String password = xdmConfig.getPassword(); final String nonce = challenge.getNextNonce() != null ? challenge.getNextNonce() : challenge.getNonce(); // final String uri = // "/services/org.openmobilealliance.xcap-directory/users/sip%3Amovial11%40dummy.com/directory.xml"; final String uri = "/" + removeXCAPRoot(request.getURI()); // final String clientNonce = "d776de233ae90908"; final String clientNonce = DigestUtils.md5Hex("" + System.currentTimeMillis()); final String auth = challenge.getQop() == 1 ? "auth" : "auth-int"; // final String nc = "00000005"; String nonceCount = challenge.getNonceCount(); final String nc = AuthUtil.creatNounceCounterString(nonceCount == null ? 1 : Integer.parseInt(nonceCount)); final HttpMethod method = request.getMethod(); final String body = request.getBody(); String ha1 = AuthUtil.calcHA1(userName, realm, password); String ha2 = AuthUtil.calcQopHA2(method.name(), body == null ? null : body.getBytes(), uri, challenge.getQop()); final String authResponce = AuthUtil.calculateAuthResponse(ha1, ha2, nonce, nc, clientNonce, challenge.getQop()); // $uname, $realm, $nonce, $uri, $responce, $cnonce, $qop, $nc, $cnonce; return DIGEST_TEMPLATE.replaceAll("#uname", userName).replaceAll("#realm", realm) .replaceAll("#nonce", nonce).replaceAll("#uri", uri).replaceAll("#responce", authResponce) .replaceAll("#opaque", challenge.getOpaque() != null ? challenge.getOpaque() : "") .replaceAll("#qop", auth).replaceAll("#nc", nc).replaceAll("#cnonce", clientNonce); } /* * private static String getMethod(int methodType) { String retValue = null; * switch (methodType) { case 0: retValue = "PUT"; break; case 1: retValue = * "GET"; break; case 2: retValue = "DELETE"; break; default: * Logger.log(TAG, "getMethod#unknown method type = " + methodType); break; * } return retValue; } /* <?xml version="1.0" encoding="UTF-8"?> * <resource-lists xmlns="urn:ietf:params:xml:ns:resource-lists"> <list * name="phbk"> <display-name>phbk</display-name> <gid * xmlns="voxmobili.xcap.dblink">119851</gid> <entry uri="tel:19728881041"> * <display-name>T 1041</display-name> </entry> <entry * uri="tel:14257707516"> <display-name>User 7516</display-name> </entry> * </list> </resource-lists> */ public List<DocumentBean> listDocuments(String auid) throws XCAPException { /** * 1. Urls for all auids * http://siptest.dummy.com:8080/services/org.openmobilealliance * .xcap-directory/users/sip%3Amovial11%40dummy.com/directory.xml 2. * Query for specified auid * http://siptest.dummy.com:8080/services/org * .openmobilealliance.xcap- * directory/users/sip%3Amovial11%40dummy.com * /directory.xml/~~/xcap-directory * /folder%5B@auid=%22resource-lists%22%5D Response: <folder * auid="resource-lists"> <entry uri= * "http://siptest.dummy.com:8080/services/resource-lists/users/sip%3Amovial11%40dummy.com/index" * etag="W/'437-1271417541984'" * last-modified="2010-04-16T13:32:21.000+02:00" size="437"/> </folder> */ final HashMap<String, String> headers = new HashMap<String, String>(); headers.put("Authorization", DIGEST2); String xcapURI = "http://siptest.dummy.com:8080/services/org.openmobilealliance.xcap-directory/users/sip%3Amovial11%40dummy.com/directory.xml"; if (auid != null) { xcapURI = xcapURI + "/~~/xcap-directory/folder%5B@auid=%22" + auid + "%22%5D"; } XDMRequest documentEntryRequest = new XDMRequestImpl(HttpMethod.GET, xcapURI, headers, null); // String xmlContent = documentListXML; List<DocumentBean> retValue = new ArrayList<DocumentBean>(); try { final XDMResponse xdmResponse = sendXCAPRequest(documentEntryRequest); NodeList nodeList = xdmResponse.getDoc().getElementsByTagNameNS("*", "folder"); for (int fldrIndex = 0; fldrIndex < nodeList.getLength(); fldrIndex++) { Node node = nodeList.item(fldrIndex); retValue.addAll(handleFolderNode(node)); } } catch (SAXException e) { e.printStackTrace(); } return retValue; } private List<DocumentBean> handleFolderNode(Node node) { List<DocumentBean> retValue = new ArrayList<DocumentBean>(); if (node != null) { if (!"Folder".equalsIgnoreCase(node.getNodeName())) { throw new IllegalArgumentException("Must be 'Folder' node"); } if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; NodeList nameNode = element.getElementsByTagNameNS("*", "entry"); for (int entrIndex = 0; entrIndex < nameNode.getLength(); entrIndex++) { if (nameNode.item(entrIndex).getNodeType() == Node.ELEMENT_NODE) { Element entryElement = (Element) nameNode.item(entrIndex); // "<entry // uri=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip%3Amovial11%40dummy.com/index\" // etag=\"W/'437-1271417541984'\" last-modified=\"2010-04-16T13:32:21.000+02:00\" size=\"437\"/>\n" // + String uriAttrValue = entryElement.getAttribute("uri"); String etagAttrValue = entryElement.getAttribute("etag"); String lmAttrValue = entryElement.getAttribute("last-modified"); String sizeAttrValue = entryElement.getAttribute("size"); DocumentBean documentBean = new DocumentDataBean(uriAttrValue, etagAttrValue, lmAttrValue, sizeAttrValue); retValue.add(documentBean); } } } } return retValue.size() != 0 ? retValue : Collections.<DocumentBean>emptyList(); } private URIListData handleListNode(Node listNode) { URIListDataBean retValue; if (listNode != null) { if (!LIST_NODE_NAME.equalsIgnoreCase(listNode.getLocalName())) { throw new IllegalArgumentException("Must be 'list' listNode"); } if (listNode.getNodeType() == Node.ELEMENT_NODE) { Element listElement = (Element) listNode; NodeList displayNameNode = listElement.getElementsByTagNameNS("*", "display-name"); String displayName = /* "" */null; for (int entrIndex = 0; entrIndex < displayNameNode.getLength(); entrIndex++) { if (displayNameNode.item(entrIndex).getNodeType() == Node.ELEMENT_NODE) { Element entryElement = (Element) displayNameNode.item(entrIndex); if (LIST_NODE_NAME.equalsIgnoreCase(entryElement.getParentNode().getLocalName())) { final Node firstChildNode = entryElement.getFirstChild(); if (firstChildNode != null) { displayName = firstChildNode.getNodeValue(); } break; } } } String name = listElement.getAttribute("name"); List<ListEntryData> listEntryData = new ArrayList<ListEntryData>(); // extracts single user URI { NodeList entryNode = listElement.getElementsByTagNameNS("*", "entry"); for (int entrIndex = 0; entrIndex < entryNode.getLength(); entrIndex++) { if (entryNode.item(entrIndex).getNodeType() == Node.ELEMENT_NODE) { Element entryElement = (Element) entryNode.item(entrIndex); if (LIST_NODE_NAME.equalsIgnoreCase(entryElement.getParentNode().getLocalName())) { String entryURI = entryElement.getAttribute("uri"); NodeList entryDisplayNameNode = entryElement.getElementsByTagNameNS("*", "display-name"); String entryDisplayName = null/* "" */; if (entryDisplayNameNode.getLength() > 0) { Node node = entryDisplayNameNode.item(0); final Node firstChildNode = node.getFirstChild(); if (firstChildNode != null) { entryDisplayName = firstChildNode.getNodeValue(); } } listEntryData.add( new ListEntryDataBean(ListEntryData.URI_ENTRY, entryDisplayName, entryURI)); } } } } // extracts references to an already existing URI list { NodeList externalsNode = listElement.getElementsByTagNameNS("*", "external"); for (int entrIndex = 0; entrIndex < externalsNode.getLength(); entrIndex++) { if (externalsNode.item(entrIndex).getNodeType() == Node.ELEMENT_NODE) { Element externalElement = (Element) externalsNode.item(entrIndex); if (LIST_NODE_NAME.equalsIgnoreCase(externalElement.getParentNode().getLocalName())) { String anchorURI = externalElement.getAttribute("anchor"); NodeList anchorDisplayNameNode = externalElement.getElementsByTagNameNS("*", "display-name"); String anchorDisplayName = null/* "" */; if (anchorDisplayNameNode.getLength() > 0) { Node node = anchorDisplayNameNode.item(0); final Node firstChildNode = node.getFirstChild(); if (firstChildNode != null) { anchorDisplayName = firstChildNode.getNodeValue(); } } listEntryData.add(new ListEntryDataBean(ListEntryData.URI_LIST_ENTRY, anchorDisplayName, anchorURI)); } } } } retValue = new URIListDataBean(displayName, name, listEntryData); } else { throw new IllegalArgumentException( "only " + Node.ELEMENT_NODE + " is allowed as parameter. Passed " + listNode.getNodeType()); } } else { throw new NullPointerException("listNode is null. Null is not allowed here."); } return retValue; } // public static void main(String[] args) { // // try { // URL url = new URL(URL_STR); // HttpURLConnection urlConnection = (HttpURLConnection) // url.openConnection(); // urlConnection.setRequestProperty("Authorization", DIGEST); // urlConnection.connect(); // InputStream in = (InputStream) urlConnection.getContent(); // // String ha1 = AuthUtil.calcHA1("sip:movial11@dummy.com", // "dummy.com", "movial11"); // String ha2 = AuthUtil.calcQopHA2("GET", null, // "/services/org.openmobilealliance.xcap-directory/users/sip%3Amovial11%40dummy.com/directory.xml", // (byte) 1); // final String s = AuthUtil.calculateAuthResponse(ha1, ha2, // "403f83140fbf864a9110a29258e5dea7", "00000005", "d776de233ae90908", // (byte) 1); // System.out.println("" + s); // /*InputStreamReader streamReader = new InputStreamReader(in); // BufferedReader bufferedReader = new BufferedReader(streamReader, // 10*1024); // // char [] responseBody = new char[urlConnection.getContentLength()]; // bufferedReader.read(responseBody); // // // System.out.println("" + new String(responseBody));*/ // // // //SAXReader saxReader = new SAXReader(); // // Document document = null; // // try { // // document = saxReader.read(in); // // } catch (DocumentException e) { // // e.printStackTrace(); //To change body of catch statement use File | // Settings | File Templates. // // } // // //System.out.println("" + document); // // } catch (IOException e) { // e.printStackTrace(); // } // } public <T extends XDMDocumentData> T retrieveDocument(XDMRequest xdmRequest, XDMDocumentDescriptor<T> documentDescriptor) throws XCAPException, IOException { T retValue; final XDMDocumentType type = documentDescriptor.getDocumentType(); switch (type) { case URI_LIST_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) retrieveURIListDocument(xdmRequest); } break; case PRESENCE_LIST_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) retrievePresenceListDocument(xdmRequest); } break; case PRESENCE_AUTHORIZATION_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) retrievePresenceAuthorizationDocument(xdmRequest); } break; default: { throw new UnsupportedOperationException("Operation " + type + " is not supported."); } } return retValue; } private URIListDocumentData retrieveURIListDocument(XDMRequest xdmRequest) throws IOException, XCAPException { final URIListDocumentData retValue; try { final XDMResponse xdmResponse = sendXCAPRequest(xdmRequest); final String documentSelector = removeNodeSelector(removeXCAPRoot(xdmRequest.getURI())); List<URIListData> dataList = new ArrayList<URIListData>(); final String xmlContent = xdmResponse.buildContent(); if (xmlContent != null) { dataList = parseURIListDocument(xdmResponse.getDoc()); } retValue = new URIListDocumentDataBean(xdmResponse.getEtag(), documentSelector, xmlContent, dataList); } catch (SAXException e) { e.printStackTrace(); final String errMsg = "Cann't parse xml, e = " + e.getMessage(); Logger.log(Logger.Tag.WARNING, errMsg); throw new IOException(errMsg); } catch (XCAPException e) { throw e; } catch (Exception e) { e.printStackTrace(); final String errMsg = "Cann't parse xml, e = " + e.getMessage(); Logger.log(Logger.Tag.WARNING, errMsg); throw new IOException(errMsg); } return retValue; } // TODO for test /* * source = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+ * "<resource-lists xmlns=\"urn:ietf:params:xml:ns:resource-lists\" xmlns:xd=\"urn:oma:xml:xdm:xcap-directory\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" * + "<list name=\"rcs\">"+ "<entry uri=\"sip:movial7\" />"+ * "<entry uri=\"sip:movial7@dummy.com\" />"+ * "<entry uri=\"sip:movial8@dummy.com\" />"+ * "<entry uri=\"welcome@app.on.im\">"+ * "<display-name>welcome@app.on.im</display-name>"+ "</entry>"+ "</list>"+ * "<list name=\"rcs_blockedcontacts\" />"+ * "<list name=\"rcs_revokedcontacts\" />"+ "<list name=\"oma_buddylist\">"+ * "<external anchor=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial8@dummy.com/index/~~/resource-lists/list%5b@name=%22rcs%22%5d\" />" * + "</list>"+ "<list name=\"oma_grantedcontacts\">"+ * "<external anchor=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial8@dummy.com/index/~~/resource-lists/list%5b@name=%22rcs%22%5d\" />" * + "</list>"+ "<list name=\"oma_blockedcontacts\">"+ * "<external anchor=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial8@dummy.com/index/~~/resource-lists/list%5b@name=%22rcs_revokedcontacts%22%5d\" />" * + * "<external anchor=\"http://siptest.dummy.com:8080/services/resource-lists/users/sip:movial8@dummy.com/index/~~/resource-lists/list%5b@name=%22rcs_blockedcontacts%22%5d\" />" * + "</list>"+ "</resource-lists>"; */ private List<URIListData> parseURIListDocument(final Document doc) { final List<URIListData> retValue = new ArrayList<URIListData>(); NodeList nodeList = doc.getElementsByTagNameNS("*", LIST_NODE_NAME); for (int listIndex = 0; listIndex < nodeList.getLength(); listIndex++) { Node node = nodeList.item(listIndex); retValue.add(handleListNode(node)); } return retValue; } public <T extends XDMDocumentData> T loadDocument(String documentSelector, XDMDocumentDescriptor<T> documentDescriptor, String source) throws IOException { T retValue; final XDMDocumentType type = documentDescriptor.getDocumentType(); switch (type) { case URI_LIST_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) loadURIListDocument(documentSelector, source); } break; case PRESENCE_LIST_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) loadPresenceListDocument(documentSelector, source); } break; case PRESENCE_AUTHORIZATION_DOCUMENT: { // supress inspection here, cause we know for sure the type of // ret value. // noinspection unchecked retValue = (T) loadPresenceAuthorizationDocument(documentSelector, source); } break; default: { throw new UnsupportedOperationException("Opeartion " + type + " is not supported."); } } return retValue; } private URIListDocumentData loadURIListDocument(final String documentSelector, final String source) throws IOException { final URIListDocumentData retValue; try { List<URIListData> dataList = parseURIListDocument(stringToXMLDocument(source)); retValue = new URIListDocumentDataBean(null, documentSelector, source, dataList); } catch (SAXException e) { e.printStackTrace(); final String errMsg = "Cann't parse xml, e = " + e.getMessage(); Logger.log(Logger.Tag.WARNING, errMsg); throw new IOException(errMsg); } catch (IOException e) { e.printStackTrace(); final String errMsg = "Cann't parse xml, e = " + e.getMessage(); Logger.log(Logger.Tag.WARNING, errMsg); throw new IOException(errMsg); } catch (Exception e) { e.printStackTrace(); final String errMsg = "Cann't parse xml, e = " + e.getMessage(); Logger.log(Logger.Tag.WARNING, errMsg); throw new IOException(errMsg); } return retValue; } private PresenceListDocumentData loadPresenceListDocument(final String documentSelector, final String source) throws IOException { final PresenceListDocumentData retValue; try { List<PresenceListData> dataList = parsePresenceListDocument(stringToXMLDocument(source)); retValue = new PresenceListDocumentDataBean(null, documentSelector, source, dataList); } catch (SAXException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } catch (IOException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } return retValue; } private PresenceAuthorizationDocumentData loadPresenceAuthorizationDocument(final String documentSelector, final String source) throws IOException { final PresenceAuthorizationDocumentData retValue; try { List<PresenceAuthorizationRuleData> dataList = parsePresenceAuthorizationDocument( stringToXMLDocument(source)); retValue = new PresenceAuthorizationDocumentDataBean(null, documentSelector, source, dataList); } catch (SAXException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } catch (IOException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } return retValue; } private Document stringToXMLDocument(String source) throws SAXException, IOException { return db.parse(new InputSource(new StringReader(source))); } private PresenceListDocumentData retrievePresenceListDocument(XDMRequest xdmRequest) throws XCAPException, IOException { final PresenceListDocumentData retValue; try { final XDMResponse xdmResponse = sendXCAPRequest(xdmRequest); final String documentSelector = removeNodeSelector(removeXCAPRoot(xdmRequest.getURI())); List<PresenceListData> dataList = new ArrayList<PresenceListData>(); if (xdmResponse.buildContent() != null) { dataList = parsePresenceListDocument(xdmResponse.getDoc()); } retValue = new PresenceListDocumentDataBean(xdmResponse.getEtag(), documentSelector, xdmResponse.buildContent(), dataList); } catch (SAXException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } return retValue; } private List<PresenceListData> parsePresenceListDocument(final Document doc) { final List<PresenceListData> retValue = new ArrayList<PresenceListData>(); NodeList nodeList = doc.getElementsByTagNameNS("*", XDMHelper.SERVICE_NODE_NAME); for (int listIndex = 0; listIndex < nodeList.getLength(); listIndex++) { Node node = nodeList.item(listIndex); retValue.add(XDMHelper.handleServiceNode(node)); } return retValue; } // private String testXML = "" + // "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + // " <cr:ruleset xmlns=\"urn:ietf:params:xml:ns:pres-rules\"\n" + // " xmlns:pr=\"urn:ietf:params:xml:ns:pres-rules\"\n" + // " xmlns:cr=\"urn:ietf:params:xml:ns:common-policy\">\n" + // " <cr:rule id=\"a\">\n" + // " <cr:conditions>\n" + // " <cr:identity>\n" + // " <cr:one id=\"sip:USER@example.com\"/>\n" + // " </cr:identity>\n" + // " </cr:conditions>\n" + // " <cr:actions>\n" + // " <pr:sub-handling>allow</pr:sub-handling>\n" + // " </cr:actions>\n" + // " <cr:transformations>\n" + // " <pr:provide-services>\n" + // " <pr:service-uri-scheme>sip</pr:service-uri-scheme>\n" + // " <pr:service-uri-scheme>mailto</pr:service-uri-scheme>\n" + // " </pr:provide-services>\n" + // " <pr:provide-persons>\n" + // " <pr:all-persons/>\n" + // " </pr:provide-persons>\n" + // " <pr:provide-activities>true</pr:provide-activities>\n" + // " <pr:provide-USER-input>bare</pr:provide-USER-input>\n" + // " <pr:provide-unknown-attribute\n" + // " ns=\"urn:vendor-specific:foo-namespace\"\n" + // " name=\"foo\">true</pr:provide-unknown-attribute>\n" + // " </cr:transformations>\n" + // " </cr:rule>\n" + // " </cr:ruleset>"; private PresenceAuthorizationDocumentData retrievePresenceAuthorizationDocument(XDMRequest xdmRequest) throws XCAPException, IOException { final PresenceAuthorizationDocumentData retValue; try { final XDMResponse xdmResponse = sendXCAPRequest(xdmRequest); final String documentSelector = removeNodeSelector(removeXCAPRoot(xdmRequest.getURI())); List<PresenceAuthorizationRuleData> dataList = new ArrayList<PresenceAuthorizationRuleData>(); if (xdmResponse.buildContent() != null) { dataList = parsePresenceAuthorizationDocument(xdmResponse.getDoc()); } retValue = new PresenceAuthorizationDocumentDataBean(xdmResponse.getEtag(), documentSelector, xdmResponse.buildContent(), dataList); } catch (SAXException e) { throw new IOException("Cann't parse xml, e = " + e.getMessage()); } return retValue; } private/* static */List<PresenceAuthorizationRuleData> parsePresenceAuthorizationDocument(final Document doc) { final List<PresenceAuthorizationRuleData> retValue = new ArrayList<PresenceAuthorizationRuleData>(); // javax.xml.parsers.DocumentBuilderFactory factory = // javax.xml.parsers.DocumentBuilderFactory.newInstance(); // javax.xml.parsers.DocumentBuilder db = null; // try { // db = factory.newDocumentBuilder(); // } catch (ParserConfigurationException e) { // // } NodeList nodeList = doc.getElementsByTagNameNS("*", XDMHelper.RULE_NODE_NAME); for (int listIndex = 0; listIndex < nodeList.getLength(); listIndex++) { Node node = nodeList.item(listIndex); retValue.add(XDMHelper.handlePresenceAuthorizationRuleNode(node)); } return retValue; } public static void main(String[] args) throws IMSStackException, IOException, SAXException, XCAPException, AkaException { /* final Configuration configuration = MockConfBuilderRegistry.AlternativeServer._79262948587 .build(); final DefaultStackRegistry stackRegistry = new DefaultStackRegistry( MockStackRegistryHelper.COMMON_REGISTRY); ConnectionDataProvider connDataProvider = new ConnectionDataProviderConfigVsDnsImpl( configuration, new DNSResolverDNSJavaImpl(configuration)); connDataProvider.refresh(); RepetitiousTaskManager repetitiousTaskManager = new RepetitiousTaskManager(new DefaultScheduledService()); final Router<IMSMessage> messageRouter = new MessageRouterComposite.Builder(configuration, connDataProvider).addRouter(new MessageRouterMSRP()) .addRouter(new MessageRouterSIP(configuration, connDataProvider, repetitiousTaskManager)).build(); final IMSStack<IMSMessage> imsStack = StackHelper .newIMSSipStack(new DefaultStackContext.Builder().configuration(configuration) .router(messageRouter).router(messageRouter) .environment(EnvironmentDefaultImpl.Builder.build(ConnState.CONNECTED)) .stackRegistry(stackRegistry) .akaAuthProvider(new AKAAuthProviderMockImpl()) .repetitiousTaskManager(repetitiousTaskManager) .build()); final URIListDocumentData data = ((XDMServiceImpl)imsStack.getXDMService()) .retrieveURIListDocument(new XDMRequestImpl(HttpMethod.PUT, null, new HashMap<String, String>(), "")); System.out.println("" + data); */ } private static String removeXCAPRoot(String uri) { return uri.replaceAll("^https?://.*?/", ""); } private static String removeNodeSelector(String uri) { return uri.replaceAll("/(\\s*)?[?~](\\s*)?[?~](\\s*)/?.*$", ""); } public void shutdown() { // TODO: put real code here // do not add shutdown(), the HttpClientHolder is static // httpclient.getConnectionManager().shutdown(); } }