001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: ClientDetectionDefaultImpl.java,v 1.5 2008/06/25 05:41:32 qcheng Exp $ 026 * 027 */ 028 029package com.iplanet.services.cdm; 030 031import com.iplanet.am.util.AMClientDetector; 032import com.sun.identity.shared.debug.Debug; 033import java.util.Iterator; 034import javax.servlet.http.HttpServletRequest; 035 036/** 037 * The <code>ClientDetectionInterface</code> interface needs to be implemented 038 * by services and applications serving multiple clients, to determine the 039 * client from which the request has originated. This interface detects the 040 * client type from the client request. 041 * @supported.all.api 042 */ 043public class ClientDetectionDefaultImpl implements ClientDetectionInterface { 044 045 protected static Debug debug = Debug.getInstance("amClientDetection"); 046 047 protected static DefaultClientTypesManager defCTM = 048 (DefaultClientTypesManager) 049 AMClientDetector.getClientTypesManagerInstance(); 050 051 /** 052 * Creates a client detection default implementation instance. 053 */ 054 public ClientDetectionDefaultImpl() { 055 } 056 057 /** 058 * This is the method used by the interface to set the client-type. 059 * <code>ClientDetectionDefaultImpl</code> currently uses the following 060 * algorithm. 061 * 062 * <pre> 063 * if userAgent equals a known user-agent then 064 * compare userAgent length and store the longest match 065 * if clientType not found 066 * return the default clientType 067 * </pre> 068 * 069 * @param request 070 * The calling object passes in the 071 * <code>HTTPServletRequest</code>. 072 * @return The string corresponding to the client type. 073 * @throws ClientDetectionException 074 * if a default client type cannot be found 075 */ 076 077 public String getClientType(HttpServletRequest request) 078 throws ClientDetectionException { 079 080 String httpUA = request.getHeader("user-agent"); 081 String clientType = null; 082 int prevClientUALen = 0; 083 084 if (debug.messageEnabled()) { 085 debug.message("UserAgent : httpUA is : " + httpUA); 086 debug.message("Looking in UA/PartialMatch Maps"); 087 } 088 089 Client clientInstance = null; 090 if ((clientInstance = defCTM.getFromUserAgentMap(httpUA)) != null) { 091 // 092 // Perf: We wont have to iterate thro' all clients 093 // 094 clientType = clientInstance.getClientType(); 095 if (debug.messageEnabled()) { 096 debug.message("Perf: from UA Map: " + clientType); 097 } 098 return clientType; 099 } else 100 if ((clientType = defCTM.getPartiallyMatchedClient(httpUA)) != null) 101 102 { 103 if (debug.messageEnabled()) { 104 debug.message("Perf: from PartialMatch Map: " + clientType); 105 } 106 return clientType; 107 } 108 109 // Iterate through Clients, find and save the longest match 110 int i = 0; 111 Iterator knownClients = ClientsManager.getAllInstances(); 112 while (knownClients.hasNext()) { 113 clientInstance = (Client) knownClients.next(); 114 i++; 115 116 String curClientUA = clientInstance.getProperty("userAgent"); 117 if (curClientUA != null) { 118 119 if (debug.messageEnabled()) { 120 debug.message("(" + i + ") Client user-agent = " 121 + curClientUA + " :: clientType = " 122 + clientInstance.getClientType()); 123 } 124 125 if (userAgentCheck(httpUA, curClientUA)) { 126 127 // We have a match 128 String curClientType = clientInstance 129 .getProperty("clientType"); 130 131 // Check length 132 int curClientUALen = curClientUA.length(); 133 if (curClientUALen > prevClientUALen) { 134 clientType = curClientType; 135 prevClientUALen = curClientUALen; 136 137 if (debug.messageEnabled()) { 138 debug.message("Longest user-agent match client " + 139 "type = " + clientType); 140 } 141 } 142 } 143 } 144 } 145 146 // If we don't have a single match, get the default clientType 147 if (clientType == null) { 148 clientType = Client.getDefaultInstance().getProperty("clientType"); 149 150 if (debug.messageEnabled()) { 151 debug.message("Default client type = " + clientType); 152 } 153 } else { 154 // 155 // Found a partial map - add it so our Map, 156 // so our next search is faster 157 // 158 defCTM.addToPartialMatchMap(httpUA, clientType); 159 } 160 161 // If we can't get the default clientType 162 if (clientType == null) { 163 164 debug.message("Unable to obtain default client type"); 165 166 throw new ClientDetectionException(CDMBundle 167 .getString("null_clientType")); 168 } 169 170 if (debug.messageEnabled()) { 171 debug.message("Returning client type : " + clientType); 172 } 173 return clientType; 174 } 175 176 /** 177 * This method contains the algorithm used to compare the 178 * <CODE>HTTPServletRequest</CODE> 179 * user-agent versus the <CODE>Client</CODE> user-agent. 180 * 181 * @param httpUA 182 * The HTTPServletRequest user-agent 183 * @param clientUA 184 * The Client userAgent 185 * @return True or false if they match 186 */ 187 protected boolean userAgentCheck(String httpUA, String clientUA) { 188 if ((httpUA == null) || (clientUA == null)) { 189 return false; 190 } 191 192 if ((httpUA.equalsIgnoreCase(clientUA)) 193 || (httpUA.indexOf(clientUA) > -1)) { 194 return true; 195 } else { 196 return false; 197 } 198 } 199}