| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.myfaces.trinidadinternal.agent; |
| |
| import java.util.Collections; |
| import java.util.Map; |
| |
| import javax.faces.context.FacesContext; |
| |
| import org.apache.myfaces.trinidad.context.Agent; |
| import org.apache.myfaces.trinidad.logging.TrinidadLogger; |
| |
| import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlConstants; |
| |
| /** |
| * Trinidad implementation of AgentFactory. |
| */ |
| public class AgentFactoryImpl implements AgentFactory |
| { |
| |
| |
| public Agent createAgent(Map<String, String> headerMap) |
| { |
| // this method primarily exists for use during testing |
| |
| AgentImpl agent = new AgentImpl(); |
| _populateAgentImpl(null, headerMap,agent); |
| return agent; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public Agent createAgent(FacesContext facesContext) |
| { |
| AgentImpl agent = new AgentImpl(); |
| |
| // Get the RequestHeaderMap to help populate the agent |
| Map<String, String> headerMap; |
| if (facesContext != null) |
| { |
| headerMap = facesContext.getExternalContext().getRequestHeaderMap(); |
| } |
| else |
| { |
| headerMap = Collections.emptyMap(); |
| } |
| |
| //TODO: Add declarative and extensible means for populating AgentImpl object |
| // the RequestHeaderMap helps populate the agent |
| _populateAgentImpl(facesContext, headerMap, agent); |
| |
| return agent; |
| } |
| |
| // The headerMap is the RequestHeaderMap from the externalContext. It is |
| // consulted to correctly populate the agent |
| private void _populateAgentImpl( |
| FacesContext facesContext, |
| Map<String, String> headerMap, |
| AgentImpl agent) |
| { |
| |
| String userAgent = headerMap.get("User-Agent"); |
| String isEmail = null; |
| if (facesContext != null) |
| isEmail = facesContext.getExternalContext().getRequestParameterMap(). |
| get(_EMAIL_PARAM); |
| |
| if ("true".equals(isEmail)) |
| { |
| _populateEmailAgentImpl(agent); |
| return; |
| } |
| |
| if ((userAgent != null) && userAgent.startsWith("PTG")) |
| { |
| _populateIaswAgentImpl(userAgent, |
| headerMap.get(_IASW_DEVICE_HINT_PARAM),agent); |
| return; |
| } |
| |
| String accept = headerMap.get("Accept"); |
| |
| // See if the agent wants WML - if so, we're talking WAP. |
| if ((accept != null) && |
| accept.regionMatches(true, 0, "vnd.wap.wml", 0, 11)) |
| { |
| _populateWAPAgentImpl(agent); |
| return; |
| } |
| |
| if (userAgent == null) |
| { |
| _populateUnknownAgentImpl(null, agent); |
| return; |
| } |
| |
| //the useragent string for telnet and PDA design time will start with |
| //OracleJDevMobile because in each of these cases we know we have an |
| //exact match in the device repository for the agent name. This is |
| //because the jdev design time and ITS runtime have access to the same |
| //device repository as the Trinidad runtime |
| //The PDA DT useragent string will be: OracleJDevMobile/PDA/[agentName] |
| //The telnet DT and RT useragent string will be: |
| //OracleJDevMobile/ITS/[agentName] |
| if (userAgent.startsWith("OracleJDevMobile")) |
| { |
| _populateJDevMobileAgentImpl(userAgent,agent); |
| return; |
| } |
| if (userAgent.startsWith("OracleITS")) |
| { |
| _populateTelnetAgentImpl(userAgent,agent); |
| return; |
| } |
| if (userAgent.startsWith("Pixo-Browser")) |
| { |
| _populatePixoAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| if (userAgent.startsWith("ICE Browser")) |
| { |
| _populateIceAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| // Web Pro |
| //userAgent = "Mozilla/4.76 (compatible; MSIE 6.0; U; Windows 95; PalmSource; PalmOS; WebPro; Tungsten Proxyless 1.1 320x320x16)"; |
| if ( (userAgent.indexOf( "WebPro") != -1 && |
| userAgent.indexOf("Palm")!= -1)|| |
| userAgent.indexOf("Blazer/3.") != -1) |
| { |
| _populatePalmWebBrowserProAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| /* //Commenting - Confirm this pattern fornBlazer before uncommenting |
| //and remove the Blazer 3.0 check in the previous if |
| if (((userAgent.indexOf("Blazer/4.") != -1) || |
| (userAgent.indexOf("Blazer 3.") != -1)) && |
| ((userAgent.indexOf("Palm") != -1))) |
| { |
| return _getPalmBlazerAgentEntry(userAgent); |
| } |
| */ |
| |
| //PPC 02 |
| //userAgent = "Mozilla/2.0 (compatible; MSIE 3.02; Windows CE; PPC; 240x320)"; |
| // PPC 03 |
| //userAgent = "Mozilla/4.0 (compatible; MSIE 4.01; Windows CE; PPC; 240x320)"; |
| if (userAgent.indexOf("Windows CE") != -1) |
| { |
| // for PocketPC and Windows Mobile, try to grab the header UA-pixels to |
| // determine width/height |
| String uaPixels = headerMap.get("UA-pixels"); |
| _populatePocketPCAgentImpl(userAgent,uaPixels,agent); |
| return; |
| } |
| |
| // This needs to be before check for mozilla! |
| if ((userAgent.indexOf("PalmOS") != -1) || |
| (userAgent.indexOf("Blazer") != -1) || |
| (userAgent.indexOf("Xiino") != -1)) |
| { |
| _populatePalmAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| if ((userAgent.indexOf("AppleWebKit") != -1) || |
| (userAgent.indexOf("Safari") != -1)) |
| { |
| _populateSafariAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| if(userAgent.startsWith("BlackBerry")) |
| { |
| _populateBlackberryAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| if (userAgent.indexOf("Opera") > -1) |
| { |
| _populateOperaAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| // Generic Mobile Browser Detection |
| // The user agent signature varies depending on the |
| // device manufacturer and carrier. Use case insensitive |
| // string matching. |
| // Some of the browsers listed below support higher capabilities |
| // than basic HTML browser capabilities. However, those browsers |
| // are treated as basic HTML browser here for maximam compatibility |
| // and performance. |
| // We do not support WAP1.X browsers (WML). |
| |
| String userAgentLowercase = userAgent.toLowerCase(); |
| |
| if ((userAgentLowercase.indexOf("wap1.") < 0) && |
| (userAgentLowercase.indexOf("wap2.") > -1 || |
| userAgentLowercase.indexOf("up.browser") > -1 || |
| userAgentLowercase.indexOf("nokia") > -1 || |
| userAgentLowercase.startsWith("mot-") || |
| userAgentLowercase.indexOf("symbian") > -1 || |
| userAgentLowercase.indexOf("sonyeri") > -1 || |
| userAgentLowercase.indexOf("netfront/") > -1 || |
| userAgentLowercase.startsWith("samsang-") || |
| userAgentLowercase.startsWith("lg-") || |
| userAgentLowercase.indexOf("obigo") > -1|| |
| userAgentLowercase.indexOf("vodafone") > -1 || |
| userAgentLowercase.indexOf("kddi") > -1 || |
| userAgentLowercase.indexOf("openwave") > -1)) |
| { |
| _populateGenericPDAAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| // Gecko and Mozilla tests should be placed following more specific |
| // uiser-agent test. |
| if (userAgent.indexOf("Gecko/") != -1) |
| { |
| _populateGeckoAgentImpl(userAgent,agent); |
| return; |
| } |
| // must check for gecko before checking for mozilla: |
| else if (userAgent.startsWith("Mozilla")) |
| { |
| _populateMozillaAgentImpl(userAgent,agent); |
| return; |
| } |
| |
| _populateUnknownAgentImpl(userAgent, agent); |
| } |
| |
| |
| private void _populateGenericPDAAgentImpl(String userAgent, AgentImpl agent) |
| { |
| // Generic PDA browser |
| agent.setType(Agent.TYPE_PDA); |
| agent.setAgent(Agent.AGENT_GENERICPDA); |
| agent.setAgentVersion("1"); // Version does not matter |
| agent.setPlatform(Agent.PLATFORM_GENERICPDA); |
| } |
| |
| private void _populateUnknownAgentImpl(String userAgent, AgentImpl agent) |
| { |
| // Log warning message that we are setting the agent entry to unknown attributes |
| _LOG.warning("UNKNOWN_AGENT_ATTRIBUTES_CREATE_WITH_UNKNOWN", userAgent); |
| agent.setAgentEntryToNULL(); |
| } |
| |
| //populates the agent entry for DT access for either Telnet or PDA |
| //for jdev mobile there are two user agent strings possible: |
| //1. OracleJDevMobile_PDA(DeviceName:[name of device]) |
| //2. OracleJDevMobile_ITS(DeviceName:[name of device]) |
| private void _populateJDevMobileAgentImpl(String agent,AgentImpl agentObj) |
| { |
| //the form of JDEVMobile user agent string will be: |
| //OracleJDevMobile_[PDA or ITS]/[version](DeviceName:[device name];[capability1]:[capability 1 value];...) |
| |
| boolean returnUnknownAgentObj = false; |
| int itsIndex = agent.indexOf("ITS"); |
| int pdaIndex = agent.indexOf("PDA"); |
| int versionStartIndex = -1; |
| if (itsIndex > -1) |
| { |
| agentObj.setType(Agent.TYPE_TELNET); |
| versionStartIndex = "OracleJDevMobile_ITS".length()+1; |
| } |
| else if (pdaIndex > -1) |
| { |
| |
| agentObj.setType(Agent.TYPE_PDA); |
| versionStartIndex = "OracleJDevMobile_PDA".length()+1; |
| } |
| else |
| { |
| returnUnknownAgentObj = true; |
| } |
| //Now find the name of the device |
| if (!returnUnknownAgentObj){ |
| int versionEndIndex = agent.indexOf("("); |
| String version = agent.substring(versionStartIndex,versionEndIndex); |
| agentObj.setAgentVersion(version); |
| //parse agentName |
| int agentNameStartIndex = agent.indexOf(":",versionEndIndex) +1; |
| //find end of agentName (ie. when we see a semicolon |
| int agentNameEndIndex = agentNameStartIndex; |
| for (;agent.charAt(agentNameEndIndex)!=';' && |
| agent.charAt(agentNameEndIndex) !=')'; |
| agentNameEndIndex++); |
| String agentName = agent.substring(agentNameStartIndex,agentNameEndIndex); |
| agentObj.setAgent(agentName); |
| if (agent.charAt(agentNameEndIndex) == ')') |
| return; |
| //now parse remaining request specific capabilities |
| int capabilityNameStartIndex; |
| int capabilityNameEndIndex; |
| int capabilityValueStartIndex; |
| int capabilityValueEndIndex = agentNameEndIndex; |
| while(agent.charAt(capabilityValueEndIndex)!= ')') |
| { |
| capabilityNameStartIndex = capabilityValueEndIndex + 1; |
| capabilityNameEndIndex = agent.indexOf(":",capabilityNameStartIndex); |
| String capabilityName = agent.substring(capabilityNameStartIndex,capabilityNameEndIndex); |
| capabilityValueStartIndex = capabilityNameEndIndex +1; |
| capabilityValueEndIndex = agent.indexOf(";",capabilityValueStartIndex); |
| if (capabilityValueEndIndex == -1) |
| { |
| capabilityValueEndIndex = agent.indexOf(")",capabilityValueEndIndex); |
| } |
| String capabilityValue = agent.substring(capabilityValueStartIndex,capabilityValueEndIndex); |
| agentObj.__addRequestCapability(CapabilityKey.getCapabilityKey(capabilityName,true),capabilityValue); |
| } |
| } |
| if (returnUnknownAgentObj) |
| { |
| _populateUnknownAgentImpl(agent, agentObj); |
| } |
| } |
| |
| private void _populateTelnetAgentImpl(String agent,AgentImpl agentObj) |
| { |
| //the form of an ITS user agent will be |
| //OracleITS/[version](DeviceName:[device name];[capability1]:[capability 1 value];...) |
| agentObj.setType(Agent.TYPE_TELNET); |
| int versionStartIndex = "OracleITS".length() +1; |
| int versionEndIndex = agent.indexOf("("); |
| String version = agent.substring(versionStartIndex,versionEndIndex); |
| agentObj.setAgentVersion(version); |
| //parse agentName |
| int agentNameStartIndex = agent.indexOf(":",versionEndIndex) +1; |
| //find end of agentName (ie. when we see a semicolon |
| int agentNameEndIndex = agentNameStartIndex; |
| for (;agent.charAt(agentNameEndIndex)!=';' && |
| agent.charAt(agentNameEndIndex) !=')'; |
| agentNameEndIndex++); |
| String agentName = agent.substring(agentNameStartIndex,agentNameEndIndex); |
| agentObj.setAgent(agentName); |
| if (agent.charAt(agentNameEndIndex) == ')') |
| return; |
| //now parse remaining request specific capabilities |
| int capabilityNameStartIndex; |
| int capabilityNameEndIndex; |
| int capabilityValueStartIndex; |
| int capabilityValueEndIndex = agentNameEndIndex; |
| while(agent.charAt(capabilityValueEndIndex)!= ')') |
| { |
| capabilityNameStartIndex = capabilityValueEndIndex + 1; |
| capabilityNameEndIndex = agent.indexOf(":",capabilityNameStartIndex); |
| String capabilityName = agent.substring(capabilityNameStartIndex,capabilityNameEndIndex); |
| capabilityValueStartIndex = capabilityNameEndIndex +1; |
| capabilityValueEndIndex = agent.indexOf(";",capabilityValueStartIndex); |
| if (capabilityValueEndIndex == -1) |
| { |
| capabilityValueEndIndex = agent.indexOf(")",capabilityValueEndIndex); |
| } |
| String capabilityValue = agent.substring(capabilityValueStartIndex,capabilityValueEndIndex); |
| agentObj.__addRequestCapability(CapabilityKey.getCapabilityKey(capabilityName,true),capabilityValue); |
| } |
| } |
| |
| /** |
| * populates data from a PocketPC IE request |
| */ |
| private void _populatePocketPCAgentImpl(String agent,String uaPixels,AgentImpl agentObj) |
| { |
| int start = agent.indexOf("MSIE"); |
| String version = null; |
| |
| if (start > -1) |
| { |
| version = _getVersion(agent, start + "MSIE".length()); |
| } |
| agentObj.setType(Agent.TYPE_PDA); |
| agentObj.setAgent(Agent.AGENT_IE); |
| agentObj.setAgentVersion(version); |
| agentObj.setPlatform(Agent.PLATFORM_PPC); |
| |
| boolean narrowScreenDevice = false; |
| |
| if(uaPixels != null && uaPixels.length() > 0) |
| { |
| // UA-pixels is defined as <width>x<height> |
| // UA-pixels was proposed here |
| // http://www.watersprings.org/pub/id/draft-mutz-http-attributes-00.txt |
| // and it is used by Pocket IE and IE Mobile; see |
| // http://blogs.msdn.com/iemobile/archive/2006/08/03/Detecting_IE_Mobile.aspx |
| Integer width = null; |
| Integer height = null; |
| |
| String[] parts = uaPixels.split("x"); |
| if(parts.length == 2) |
| { |
| try |
| { |
| width = new Integer(parts[0]); |
| height = new Integer(parts[1]); |
| } |
| catch(NumberFormatException ex) |
| { |
| _LOG.fine(ex); |
| } |
| } |
| |
| if(width != null && height != null) |
| { |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_WIDTH,width); |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_HEIGHT,height); |
| |
| if (width.intValue() < XhtmlConstants.NARROW_SCREEN_PDA_MAX_WIDTH) |
| { |
| narrowScreenDevice = true; |
| } |
| } |
| else |
| { |
| _LOG.fine("When creating the Agent, the UA-pixels value \"{0}\" could not be parsed.", uaPixels); |
| } |
| } |
| else |
| { |
| narrowScreenDevice = true; |
| } |
| |
| if (narrowScreenDevice) |
| { |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_NARROW_SCREEN, |
| Boolean.TRUE); |
| } |
| else |
| { |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_NARROW_SCREEN, |
| Boolean.FALSE); |
| } |
| } |
| |
| /** |
| * populates data from a Blackberry browser request |
| */ |
| private void _populateBlackberryAgentImpl(String agent,AgentImpl agentObj) |
| { |
| // the User-Agent string for the BlackBerry Browser starts with |
| // BlackBerry<model>/<version> where <model> is the BlackBerry |
| // model, e.g. for the BlackBerry browser 4.1.0 on |
| // the BlackBerry 8700 device, the User-Agent string begins with |
| // BlackBerry8700/4.1.0 |
| |
| int start = agent.indexOf("BlackBerry"); |
| |
| String version = null; |
| String makeModel = null; |
| |
| if (start > -1) |
| { |
| // find the first /, which occurs before the version number |
| int slashLoc = agent.indexOf('/',start); |
| if(slashLoc > -1) |
| { |
| // see the note above about how the User-Agent starts with |
| // BlackBerry<model>/<version>; this returns the |
| // BlackBerry<model> (e.g. BlackBerry8700), which we will |
| // use as the Agent hardwareMakeModel |
| makeModel = agent.substring(start,slashLoc); |
| |
| // _getVersion assumes the location of the slash is passed in, |
| // and starts looking for the version at the NEXT character |
| version = _getVersion(agent, slashLoc); |
| } |
| } |
| |
| // note that the agent and platform are both BLACKBERRY |
| // this is because it is the BlackBerry Browser running on the |
| // BlackBerry device |
| agentObj.setType(Agent.TYPE_PDA); |
| agentObj.setAgent(Agent.AGENT_BLACKBERRY); |
| agentObj.setAgentVersion(version); |
| agentObj.setPlatform(Agent.PLATFORM_BLACKBERRY); |
| agentObj.setMakeModel(makeModel); |
| // Most of BlackBerry devices' widths are more than 240px, so |
| // don't consider BlackBerry as a narrow-screen PDA. |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_NARROW_SCREEN, |
| Boolean.FALSE); |
| } |
| |
| /** |
| * returns the data for the Palm Web Pro browser request |
| */ |
| private void _populatePalmWebBrowserProAgentImpl(String agent,AgentImpl agentObj) |
| { |
| agentObj.setType(Agent.TYPE_PDA); |
| agentObj.setAgent(TrinidadAgent.AGENT_WEBPRO); |
| |
| int start = agent.indexOf("WebPro/"); |
| |
| if (start > -1) |
| { |
| agentObj.setAgentVersion(_getVersion(agent, start + 6)); |
| } |
| |
| agentObj.setPlatform(Agent.PLATFORM_PALM); |
| |
| } |
| |
| /** |
| * returns the data for the Palm blazer browser request |
| */ |
| /* //comment for now |
| private AgentEntry _getPalmBlazerAgentEntry(String agent) |
| { |
| AgentEntry entry = new AgentEntry(); |
| entry._type = TYPE_PDA; |
| entry._agent = AdfFacesAgent.AGENT_BLAZER; |
| |
| //balzer 3 has "Blazer 3..." and 4.0 has Blazer 4/.... |
| int start = agent.indexOf("Blazer"); |
| |
| if (start > -1) |
| { |
| entry._agentVersion = _getVersion(agent, start + 6); |
| } |
| |
| entry._platform = Agent.PLATFORM_PALM; |
| |
| return entry; |
| } |
| */ |
| |
| /** |
| * returns the AgentEntry for ias wireless |
| */ |
| private void _populateIaswAgentImpl(String agent, String wirelessType,AgentImpl agentObj) |
| { |
| // map device hint to agent type |
| if (wirelessType == null) |
| { |
| _populateUnknownAgentImpl(agent, agentObj); |
| return; |
| } |
| |
| String version = _getVersion(agent, agent.indexOf('/')); |
| agentObj.setType(Agent.TYPE_PHONE); |
| agentObj.setAgent(TrinidadAgent.AGENT_PTG); |
| agentObj.setAgentVersion(version); |
| } |
| |
| /** |
| * returns the AgentEntry for the Palm |
| */ |
| private void _populatePalmAgentImpl(String userAgent,AgentImpl agentObj) |
| { |
| agentObj.setType(Agent.TYPE_PDA); |
| |
| if (userAgent.indexOf("Blazer") != -1) |
| agentObj.setAgent(TrinidadAgent.AGENT_BLAZER); |
| else if (userAgent.indexOf("Xiino") != -1) |
| agentObj.setAgent(TrinidadAgent.AGENT_XIINO); |
| |
| agentObj.setPlatform(Agent.PLATFORM_PALM); |
| |
| } |
| |
| /** |
| * returns the AgentEntry for the Ice brwoser |
| */ |
| private void _populateIceAgentImpl(String agent,AgentImpl agentObj) |
| { |
| int slashIndex = agent.indexOf('/'); |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| agentObj.setAgent(TrinidadAgent.AGENT_ICE_BROWSER); |
| agentObj.setAgentVersion(_getVersion(agent, slashIndex)); |
| agentObj.setPlatform(_getJavaOS(agent, slashIndex)); |
| } |
| |
| /** |
| * returns the AgentEntry for the Pixo Microbrowser |
| */ |
| private void _populatePixoAgentImpl(String agent,AgentImpl agentObj) |
| { |
| agentObj.setType(Agent.TYPE_PHONE); |
| agentObj.setAgent(TrinidadAgent.AGENT_PIXO); |
| agentObj.setAgentVersion(_getVersion(agent, agent.indexOf('/'))); |
| } |
| |
| /** |
| * Returns an AgentEntry for a WML client. |
| */ |
| private void _populateWAPAgentImpl(AgentImpl agentObj) |
| { |
| //TODO: Add generic wmlbrowser when wml browsers are supported |
| // Generic WML support |
| agentObj.setType(Agent.TYPE_PHONE); |
| } |
| |
| /** |
| * Returns an AgentEntry for the browsers that use the Gecko Layout Engine. |
| */ |
| private void _populateGeckoAgentImpl(String agent,AgentImpl agentObj) |
| { |
| //Identifying an Gecko Based agent as Gecko (and not Mozilla, Netscape, Firefox) |
| //could be an issue |
| //E.g User-Agent String |
| //Mozilla/5.0 (Windows; U; Win 9x 4.90; en-US; rv:1.0.1) Gecko/20020823 Netscape/7.0 |
| //For Gecko based agents |
| // - Gecko uses Date string as a version number |
| // - Mozilla uses the revision number as the version number rv:x.x.x |
| // - Each vendor has a version number (like firefox/1.0, Netscape/7.0) |
| // Mozilla revision : Gecko Version |
| // 1.0.1 : 20020826 |
| // 1.1 : 20020826 |
| // 1.2.1 : 20021130 |
| |
| //Currently (in UIX 2.2 base agent Impl) |
| // - All Gecko Based agents are identified as Gecko |
| // - But PPR capability is determined is based on the Mozilla version number (rv:x.x.x) |
| // - For Major version , for Gecko, always "1" is returned |
| //so stricly speaking all capabilities are not based on the layout engine. |
| |
| //New Impl. |
| // - Still using Gecko as the identifier for all gecko based agents |
| // - Still returning date string as version number of Gecko. But this can get messy to use |
| // by the applications. The version number could change everyday and may not be the same for |
| // different platforms. (An alternate option is to return version number of Mozilla |
| // that would be equivalent to current browser for Gecko-based browsers) |
| // - But assumes PPR Support in all Gecko versions. |
| |
| //Change 2008-05-13: |
| // We need the rv to support @agent versioning in CSS as the date makes no sense, |
| // so look for the rv:, not the Gecko build date |
| |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| agentObj.setAgent(Agent.AGENT_GECKO); |
| |
| int start = agent.indexOf("rv:"); |
| if (start >= 0) |
| { |
| agentObj.setAgentVersion(_getVersion(agent, start + 2)); |
| } |
| else |
| { |
| int geckoIndex = agent.indexOf("Gecko/"); |
| agentObj.setAgentVersion(agent.substring(geckoIndex+6, // skip over 'Gecko/' |
| geckoIndex+14)); // always 8 chars length |
| } |
| |
| int paren = agent.indexOf('('); |
| |
| if (paren >= 0) |
| { |
| // try to determine the OS |
| if (agent.indexOf("Win", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_WINDOWS); |
| } |
| else if (agent.indexOf("Mac", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_MACOS); |
| } |
| else if (agent.indexOf("Linux", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_LINUX); |
| } |
| else if (agent.indexOf("Sun", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_SOLARIS); |
| } |
| } |
| } |
| |
| /** |
| * Returns an AgentEntry for the Opera browser. |
| */ |
| |
| private void _populateOperaAgentImpl(String agent,AgentImpl agentObj) |
| { |
| int start = agent.indexOf("Opera Mini"); |
| if (start > -1) |
| { |
| // Opera Mini supports JavaScript. However, generic PDA capability |
| // will be assigned to maximize the compatibility until fully certified. |
| start = agent.indexOf('/', start); |
| String version = _getVersion(agent, start); |
| agentObj.setAgentVersion(version); |
| agentObj.setType(Agent.TYPE_PDA); |
| agentObj.setAgent(Agent.AGENT_GENERICPDA); |
| agentObj.setPlatform(Agent.PLATFORM_GENERICPDA); |
| } |
| // For performance reasons, consider Opera Mobile as a generic PDA-browser |
| // so just return. It will be handle by _populateGenricPDAImpl(). |
| else if (agent.indexOf("MOT-") != -1 || agent.indexOf("Nokia") != -1) |
| { |
| return; |
| } |
| else |
| { |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| agentObj.setAgent(Agent.AGENT_GECKO); |
| |
| int operaIndex = agent.indexOf("Opera/"); |
| int firstSpace = agent.indexOf(" "); |
| if (operaIndex >= 0 && firstSpace >=0 ) |
| { |
| agentObj.setAgentVersion(agent.substring(operaIndex + 6,firstSpace)); |
| } |
| |
| int paren = agent.indexOf('('); |
| |
| if (paren >= 0) |
| { |
| // try to determine the OS |
| if (agent.indexOf("Win", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_WINDOWS); |
| } |
| else if (agent.indexOf("Mac", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_MACOS); |
| } |
| else if (agent.indexOf("Linux", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_LINUX); |
| } |
| else if (agent.indexOf("Sun", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_SOLARIS); |
| } |
| } |
| } |
| } |
| |
| /** |
| * returns the AgentEntry for Safari |
| */ |
| private void _populateSafariAgentImpl(String agent, AgentImpl agentObj) |
| { |
| int start = agent.indexOf("AppleWebKit"); |
| |
| if (start < 0) |
| { |
| start = agent.indexOf("Safari"); |
| } |
| |
| if (start >= 0) |
| { |
| start = agent.indexOf('/', start); |
| } |
| |
| if (agent.indexOf("iPhone") > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_IPHONE); |
| } |
| else if (agent.indexOf("iPod") > 0) |
| { |
| // At the moment, the iPod touch version of this browser matches iPhone's |
| agentObj.setPlatform(Agent.PLATFORM_IPHONE); |
| } |
| else if (agent.indexOf("Win") > 0) |
| { |
| // At the moment, this includes Safari and Google Chrome |
| agentObj.setPlatform(Agent.PLATFORM_WINDOWS); |
| } |
| else if (agent.indexOf("Linux") > 0) |
| { |
| // At the moment, this includes Android |
| agentObj.setPlatform(Agent.PLATFORM_LINUX); |
| } |
| else if (agent.indexOf("Mac") > 0) |
| { |
| // At the moment, this includes Safari |
| agentObj.setPlatform(Agent.PLATFORM_MACOS); |
| } |
| |
| String version = _getVersion(agent, start); |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| if ((agent.indexOf("Symbian") > -1) || (agent.indexOf("Nokia") > -1)) |
| { |
| agentObj.setAgent(Agent.AGENT_NOKIA_S60); |
| agentObj.setPlatform(Agent.AGENT_NOKIA_S60); |
| } |
| else |
| { |
| agentObj.setAgent(Agent.AGENT_WEBKIT); |
| } |
| agentObj.setAgentVersion(version); |
| } |
| |
| /** |
| * Returns an AgentEntry for the "Mozilla" family of browsers - which |
| * most at least pretend to be. |
| */ |
| private void _populateMozillaAgentImpl(String agent,AgentImpl agentObj) |
| { |
| int paren = agent.indexOf('('); |
| agentObj.setType(Agent.TYPE_DESKTOP); //Is this default realli okay??? These days Mobile agents also use Mozilla/xx.xx |
| |
| // No section to qualify the agent; assume Mozilla/Netscape |
| if (paren == -1) |
| { |
| agentObj.setAgent(TrinidadAgent.AGENT_NETSCAPE); |
| agentObj.setAgentVersion(_getVersion(agent, agent.indexOf('/'))); |
| } |
| else |
| { |
| paren = paren + 1; |
| |
| boolean isJDevVE = agent.indexOf("JDeveloper", paren) > 0; |
| boolean isJDevJSVE = agent.indexOf("JDeveloper JS", paren) > 0; |
| |
| if (agent.indexOf("Konqueror", paren) >= 0) |
| { |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| agentObj.setAgent(Agent.AGENT_KONQUEROR); |
| agentObj.setAgentVersion(_getVersion(agent, agent.lastIndexOf('/'))); |
| } |
| else if (agent.startsWith("compatible", paren)) |
| { |
| int ieIndex = agent.indexOf("MSIE", paren); |
| |
| if (ieIndex < 0) |
| { |
| // check for Palm |
| int palmIndex = agent.indexOf("Elaine", paren); |
| |
| if (palmIndex > 0) |
| { |
| agentObj.setType(Agent.TYPE_PDA); |
| agentObj.setAgent(TrinidadAgent.AGENT_ELAINE); |
| agentObj.setAgentVersion(_getVersion(agent, palmIndex)); |
| agentObj.setPlatform(Agent.PLATFORM_PALM); |
| } |
| } |
| else |
| { |
| agentObj.setAgent(Agent.AGENT_IE); |
| agentObj.setAgentVersion(_getVersion(agent, ieIndex + 4)); |
| } |
| } |
| else |
| { |
| agentObj.setAgent(TrinidadAgent.AGENT_NETSCAPE); |
| agentObj.setAgentVersion(_getVersion(agent, agent.indexOf('/'))); |
| } |
| |
| // try to determine the OS, if unknown |
| if (agentObj.getPlatformName() == null || |
| agentObj.getPlatformName().equals(Agent.PLATFORM_UNKNOWN)) |
| { |
| // Hack: treat the JDeveloper agent as Windows, |
| // so that we assume IE 6.0 Windows capabilities |
| if ((agent.indexOf("Win", paren) > 0) || isJDevVE) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_WINDOWS); |
| } |
| else if (agent.indexOf("Mac", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_MACOS); |
| } |
| else if (agent.indexOf("Linux", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_LINUX); |
| } |
| else if (agent.indexOf("Sun", paren) > 0) |
| { |
| agentObj.setPlatform(Agent.PLATFORM_SOLARIS); |
| } |
| } |
| |
| if (isJDevVE) |
| { |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_IS_JDEV_VE, |
| Boolean.TRUE); |
| if (isJDevJSVE) |
| { |
| agentObj.__addRequestCapability(TrinidadAgent.CAP_IS_JDEV_JAVASCRIPT_VE, |
| Boolean.TRUE); |
| } |
| |
| } |
| } |
| } |
| |
| /** |
| * Returns an AgentEntry for the email agents like Outlook 2007 and |
| * Thunderbird |
| */ |
| private void _populateEmailAgentImpl(AgentImpl agentObj) |
| { |
| |
| agentObj.setType(Agent.TYPE_DESKTOP); |
| |
| agentObj.setAgent(Agent.AGENT_EMAIL); |
| agentObj.setAgentVersion("0.0"); |
| agentObj.setPlatform(Agent.AGENT_UNKNOWN); |
| agentObj.setPlatformVersion(Agent.PLATFORM_VERSION_UNKNOWN); |
| agentObj.setMakeModel(Agent.MAKE_MODEL_UNKNOWN); |
| |
| } |
| |
| |
| /** |
| * Returns the version contained within a string starting |
| * at a certain location. The version will contain only numeric |
| * parts separated by dots (.). |
| * @param base the string to pull the version from |
| * @param start the index of the character BEFORE the version |
| * @return the version string |
| */ |
| private String _getVersion(String base, int start) |
| { |
| // start should be the character BEFORE the version portion |
| // (typically a slash character after the agent name) |
| |
| if (start < 0) |
| { |
| return null; |
| } |
| |
| int end = base.length(); |
| start = start + 1; |
| |
| for (int i = start; i < end; i++) |
| { |
| // Find the last non-numeric character; that'll |
| // mark the end of the version |
| char ch = base.charAt(i); |
| |
| if ((ch != '.') && ((ch < '0') || (ch > '9'))) |
| { |
| return base.substring(start, i); |
| } |
| } |
| |
| return base.substring(start); |
| } |
| |
| /** |
| * Parse the OS string returned from java.System. |
| * <p/> |
| * Currently, only checks for Windows |
| */ |
| private String _getJavaOS(String base, int start) |
| { |
| if (start < 0) |
| { |
| return null; |
| } |
| |
| // check for Windows |
| if (base.regionMatches(start, "Windows", 0, base.length() - start)) |
| { |
| return Agent.PLATFORM_WINDOWS; |
| } |
| |
| return null; |
| } |
| static private final String _EMAIL_PARAM = |
| "org.apache.myfaces.trinidad.agent.email"; |
| static final private String _IASW_DEVICE_HINT_PARAM = "X-Oracle-Device.Class"; |
| static final private TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(AgentFactoryImpl.class); |
| |
| } |