/* * Copyright (C) 2007-2008 Esmertec AG. * Copyright (C) 2007-2008 The Android Open Source Project * * Licensed 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.android.im.imps; import android.os.Parcel; import com.android.im.engine.Address; import com.android.im.engine.ImEntity; /** * The abstract representation of an IMPS address. */ public abstract class ImpsAddress extends Address { private static final char[] SPECIALS = {'/', '@', '+'}; protected String mUser; protected String mResource; protected String mDomain; private String mFullAddress; protected ImpsAddress() { } protected ImpsAddress(String user, String resource, String domain) { // build the full address and unify the fields to lower case since imps // address is case insensitive. StringBuilder buf = new StringBuilder(ImpsConstants.ADDRESS_PREFIX); if(user != null) { buf.append(user.toLowerCase()); } if(resource != null) { buf.append('/').append(resource.toLowerCase()); } if(domain != null) { buf.append('@').append(domain.toLowerCase()); } mFullAddress = buf.toString(); mUser = user; mResource = resource; mDomain = domain; verifyAddress(); } protected ImpsAddress(String full){ this(full, true); } protected ImpsAddress(String full, boolean verify) { if (full == null || full.length() == 0) { throw new IllegalArgumentException(); } //TODO: escape reserved characters. if(!full.startsWith(ImpsConstants.ADDRESS_PREFIX)) { full = ImpsConstants.ADDRESS_PREFIX + full; } parse(full); mFullAddress = full; if (verify) { verifyAddress(); } } private void parse(String full) { mUser = parseUser(full); mResource = parseResource(full); mDomain = parseDomain(full); } private void verifyAddress() throws IllegalArgumentException { ImpsLog.log("verifyAddress:" + mUser + ", " + mResource + ", " + mDomain); if(mUser == null && mResource == null) { throw new IllegalArgumentException(); } if(mUser != null) { if(mUser.length() == 0) { throw new IllegalArgumentException("Invalid user"); } if(mUser.charAt(0) == '+') {//mobile number for(int i = 1; i < mUser.length(); i++) { if(!Character.isDigit(mUser.charAt(i))) { throw new IllegalArgumentException("Invalid user"); } } } else if(!isAlphaSequence(mUser)) { throw new IllegalArgumentException("Invalid user"); } } if(mResource != null && !isAlphaSequence(mResource)) { throw new IllegalArgumentException("Invalid resource"); } if(mDomain != null && !isAlphaSequence(mDomain)) { throw new IllegalArgumentException("Invalid domain"); } } /** * Gets the User-part of the address which refers to the identification of * the IMPS user. * * @return the User-part of the address. */ public String getUser() { return mUser; } /** * Gets the Resource-part of the address which identifies the referred * public or private resource. * * @return the Resource-part of the address. */ public String getResource() { return mResource; } /** * Gets the Domain-part of the address which identifies the IMPS server * domain. * * @return the Domain-part of the address. */ public String getDomain() { return mDomain; } /** * Gets the full string representation of the address. */ @Override public String getFullName() { return mFullAddress; } @Override public void writeToParcel(Parcel dest) { dest.writeString(mFullAddress); } @Override public void readFromParcel(Parcel source) { mFullAddress = source.readString(); parse(mFullAddress); } @Override public boolean equals(Object other) { return other instanceof ImpsAddress && mFullAddress.equalsIgnoreCase(((ImpsAddress)other).mFullAddress); } @Override public int hashCode() { return mFullAddress.toLowerCase().hashCode(); } /** * Formats the address to a PrimitiveElement which can be used as the * content of Sender or Recipient. * * @return a PrimitiveElement. */ public abstract PrimitiveElement toPrimitiveElement(); /** * Gets the entity this address object refers to. * * @param connection * @return the entity this address refers to or <code>null</code> if the * entity not found. */ abstract ImEntity getEntity(ImpsConnection connection); /** * Constructs an ImpsAddress from the Sender or Recipient element in a * primitive. * * @param elem the Sender of Recipient element. * @return the ImpsAddress object or <code>null</code> if it's not a valid * element. */ public static ImpsAddress fromPrimitiveElement(PrimitiveElement elem) { String type = elem.getTagName(); if(ImpsTags.User.equals(type)) { return new ImpsUserAddress(elem.getChildContents(ImpsTags.UserID), false); } else if(ImpsTags.Group.equals(type)) { PrimitiveElement child = elem.getFirstChild(); if(child == null) { throw new IllegalArgumentException(); } if(ImpsTags.GroupID.equals(child.getTagName())){ return new ImpsGroupAddress(child.getContents()); } else { String screeName = child.getChildContents(ImpsTags.SName); String groupId = child.getChildContents(ImpsTags.GroupID); return new ImpsGroupAddress(groupId, screeName); } } else if(ImpsTags.ContactList.equals(type)) { return new ImpsContactListAddress(elem.getContents(), false); } else { throw new IllegalArgumentException(); } } private String parseUser(String full) { int index = full.indexOf('/'); if(index == 3) { return null; } if (index == -1) { index = full.lastIndexOf('@'); } if (index == -1) { index = full.length(); } return full.substring(3, index); } private String parseResource(String full) { int beginIndex = full.indexOf('/'); if (beginIndex == -1) { return null; } int endIndex = full.lastIndexOf('@'); if (endIndex == -1 || endIndex < beginIndex) { endIndex = full.length(); } return full.substring(beginIndex + 1, endIndex); } private String parseDomain(String full) { int beginIndex = full.lastIndexOf('@'); return beginIndex == -1 ? null : full.substring(beginIndex + 1); } private boolean isAlphaSequence(String str) { for(int i = 0; i < str.length(); i++) { char ch = str.charAt(i); if(ch < 32 || ch > 126 || isSpecial(ch)) { return false; } } return true; } private boolean isSpecial(char ch) { for (char element : SPECIALS) { if(ch == element) { return true; } } return false; } }