/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.sip;
import java.io.UnsupportedEncodingException;
import javax.servlet.sip.ServletParseException;
import javax.servlet.sip.SipURI;
import javax.servlet.sip.TelURL;
import javax.servlet.sip.URI;
/**
* This is is a utility for accessing common parts in URI subclasses, that are
* not specified in the URI interface.
*/
public class UriUtil {
private static boolean ignoreUserParameter =
Boolean.getBoolean("org.glassfish.sip.ignoreUserParameter");
public static class UriUtilException extends Exception {
private static final long serialVersionUID = 1L;
/**
* @param message
* @param cause
*/
public UriUtilException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* Sets the specified parameter of the URI in the request to the specified
* value.
*
* @param uri
* the URI
* @param name
* parameter name
* @param value
* parameter value
*/
public static void setParameter(URI uri, String name, String value) {
if (uri instanceof SipURI) {
SipURI sipUri = (SipURI) uri;
sipUri.setParameter(name, value);
} else {
TelURLImpl telUrl = (TelURLImpl) uri;
telUrl.setParameter(name, value);
}
}
/**
* Remove the specified parameter of the URI in the request.
*
* @param uri
* the URI
* @param name
* the parameter name
* @return the value of the removed parameter (or null if parameter does not
* exist)
*/
public static String removeParameter(URI uri, String name) {
if (uri instanceof SipURI) {
SipURI sipUri = (SipURI) uri;
String value = sipUri.getParameter(name);
sipUri.removeParameter(name);
return value;
} else {
TelURLImpl telUrl = (TelURLImpl) uri;
String value = telUrl.getParameter(name);
telUrl.removeParameter(name);
return value;
}
}
/**
* Gets the value of the specified parameter of the URI in the request.
*
* @param uri
* the URI
* @param name
* parameter name
*/
public static String getParameter(URI uri, String name) {
if (uri instanceof SipURI) {
SipURI sipUri = (SipURI) uri;
return sipUri.getParameter(name);
} else {
TelURLImpl telUrl = (TelURLImpl) uri;
return telUrl.getParameter(name);
}
}
/**
* Sets the specified parameter but encodes first using {@link SipURIEncoder#encodeParameter(String)}
* @param uri
* @param name
* @param value
*/
public static void setAndEncodeParameter(URI uri, String name, String value) {
String encoded = null;
if (value != null) {
encoded = new SipURIEncoder().encodeParameter(value);
}
setParameter(uri, name, encoded);
}
/**
* Gets, but first decodes (using {@link SipURIDecoder#decodeParameter(String)}) the specified parameter.
* @param uri
* @param name
* @return the decoded parameter
* @throws UnsupportedEncodingException in case value was not possible to decode
*/
public static String getAndDecodeParameter(URI uri, String name) throws UnsupportedEncodingException {
String encoded = getParameter(uri, name);
if (encoded == null) return null;
return new SipURIDecoder().decode(encoded);
}
/**
* Cleans out visual separators but keep '+' if there is any.
* For example, "+46-8-123456" would be changed to "+468123456".
* @param phoneNumber the phone number to clean-up
* @return the resulting phone number.
*/
public static String cleanupPhonenumber(String phoneNumber) {
if (phoneNumber == null) return null;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < phoneNumber.length(); i++) {
char ch = phoneNumber.charAt(i);
if (Character.isDigit(ch) || (ch == '+')) {
sb.append(ch);
}
}
return sb.toString();
}
/**
* Adjusts the phone number (if existing) in the URI. See {@link #cleanupPhonenumber(String)}.
* @param uri the URI to cleanup
* @return the cleansed URI
*/
public static URI cleanupPossibleTelephoneNumberURI(URI uri) {
if (uri == null) return null;
if (!isTelephoneNumber(uri)) return uri;
if (uri.isSipURI()) {
// Since we are modifying the uri we need a copy
SipURI tmpUri = (SipURI) uri.clone();
TelURL telUrl;
try {
telUrl = convertToTelURL(tmpUri);
if (telUrl.isGlobal()) {
telUrl.setPhoneNumber("+" + com.ericsson.ssa.sip.UriUtil.cleanupPhonenumber(telUrl.getPhoneNumber()));
} else {
telUrl.setPhoneNumber(com.ericsson.ssa.sip.UriUtil.cleanupPhonenumber(telUrl.getPhoneNumber()), telUrl.getPhoneContext());
}
tmpUri.setUser(getAsSipUriUser(telUrl));
} catch (UriUtilException e) {
// This was not a phone number. Silently ignore
}
return tmpUri;
} else {
// Since we are modifying the uri we need a copy
TelURLImpl tmpUri = (TelURLImpl) uri.clone();
if (tmpUri.isGlobal()) {
tmpUri.setPhoneNumber("+" + com.ericsson.ssa.sip.UriUtil.cleanupPhonenumber(tmpUri.getPhoneNumber()));
} else {
tmpUri.setPhoneNumber(com.ericsson.ssa.sip.UriUtil.cleanupPhonenumber(tmpUri.getPhoneNumber()), tmpUri.getPhoneContext());
}
return tmpUri;
}
}
/**
* Converts the SIP URI containing a Tel-URL in the user part (user=phone) to a Tel-URL.
* @param sipuri the SIP-URI to convert
* @return the created Tel-URL
* @throws UriUtilException thrown if the SIP-URI does not contain a user=phone
*/
public static TelURL convertToTelURL(SipURI sipuri) throws UriUtilException {
String userParam = sipuri.getParameter("user");
if ((userParam == null) || (userParam.equals("phone") == false)) {
throw new UriUtilException("Missing parameter user=phone", null);
}
String user = sipuri.getUser();
return createTelUrl(user);
}
/**
* Create a Tel-URL from the specified user string (typically extracted from a SIP-URI with user=phone)
* @param user the user string
* @return the created Tel-URL
* @throws UriUtilException
*/
public static TelURL createTelUrl(String user) throws UriUtilException {
StringBuilder userTelUrl = new StringBuilder();
userTelUrl.append(SipFactoryImpl.TEL_URI_PROTOCOL);
userTelUrl.append(':');
userTelUrl.append(user);
try {
return (TelURL) SipFactoryImpl.getInstance().createURI(userTelUrl.toString());
} catch (ServletParseException e) {
throw new UriUtilException("Exception when creating TelURL", e);
}
}
/**
* Gets the Tel-URL as a string that can be set directly as the user part on a SIP-URI.
* @param telUrl the Tel-URL
* @return the Tel-URL as a string that can be set directly as the user part on a SIP-URI
*/
public static String getAsSipUriUser(TelURL telUrl) {
assert telUrl instanceof TelURLImpl;
TelURLImpl telUrlImpl = (TelURLImpl) telUrl;
return telUrlImpl.getAsSipUriUser();
}
/**
* Checks if this is a telephone number (either a Tel-URL or a SIP-URI with user=phone).
* @param uri the URI to check
* @return true if it is a telephone number; otherwise false
*/
public static boolean isTelephoneNumber(URI uri) {
if (uri != null) {
if (uri.isSipURI() && !ignoreUserParameter) {
String userParam = ((SipURI) uri).getParameter("user");
return (userParam != null) && userParam.equals("phone");
} else {
return isTelUrl(uri);
}
}
return false;
}
/**
* Checks if the URI is a Tel-URI
* @param uri the URI to check
* @return true if it is a Tel-URL; otherwise false
*/
public static boolean isTelUrl(URI uri) {
return SipFactoryImpl.TEL_URI_PROTOCOL.equals(uri.getScheme());
}
}