001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.ext.xml.dbobj;
066:
067: import com.jcorporate.expresso.core.db.DBException;
068: import com.jcorporate.expresso.core.dbobj.DBObject;
069: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
070: import com.jcorporate.expresso.core.dbobj.ValidValue;
071: import org.apache.commons.collections.LRUMap;
072: import org.apache.oro.text.regex.MalformedPatternException;
073: import org.apache.oro.text.regex.Pattern;
074: import org.apache.oro.text.regex.PatternCompiler;
075: import org.apache.oro.text.regex.PatternMatcher;
076: import org.apache.oro.text.regex.Perl5Compiler;
077: import org.apache.oro.text.regex.Perl5Matcher;
078:
079: import java.util.Iterator;
080: import java.util.Map;
081: import java.util.Vector;
082:
083: //import com.jcorporate.expresso.ext.regexp.RE;
084: //import com.jcorporate.expresso.ext.regexp.RESyntaxException;
085:
086: /**
087: * Entries here define the other VM's (even on other servers) that are also using
088: * this database, and with whom cache synchronizations should be attempted. Note
089: * that for this to work, the db/context names on the remote servers must be the
090: * same as the db/context names here.
091: *
092: * @author Michael Nash
093: */
094: public class UserAgent extends SecuredDBObject {
095: private static final String this Class = UserAgent.class.getName()
096: + ".";
097:
098: /**
099: * Used to hold compiled regular expressions in an attempt to speed
100: * up pattern matching.
101: */
102: protected static Map regExpCache = null;
103:
104: /**
105: * Used for regular expression compilation
106: */
107: protected static PatternCompiler compiler = new Perl5Compiler();
108:
109: /**
110: * Used to match compiled patterns against strings
111: */
112: protected static PatternMatcher matcher = new Perl5Matcher();
113:
114: /**
115: * Constructor
116: */
117: public UserAgent() throws DBException {
118: super ();
119: } /* UserAgent() */
120:
121: /**
122: * Constructor that sets the 'owner' of this DBObject class.
123: *
124: * @param uid The User's uid
125: * @throws DBException upon construction error
126: */
127: public UserAgent(int uid) throws DBException {
128: super (uid);
129: } /* UserAgent(String) */
130:
131: /**
132: * Creates the object cache based upon the size of the UserAgent map.
133: *
134: * @param agentList the user agent dbobject.
135: */
136: private synchronized void createObjectCache(UserAgent agentList) {
137: try {
138: if (regExpCache == null) {
139: int numMatches = agentList.count();
140:
141: //Let's limit the size of the cache in case it's really
142: //ridiculous
143: if (numMatches > 60) {
144: numMatches = 60;
145: }
146:
147: regExpCache = new LRUMap(numMatches);
148: }
149: } catch (DBException dbe) {
150: regExpCache = new LRUMap(60);
151: }
152: }
153:
154: /**
155: * Get's the regular expression patter to match against.
156: *
157: * @param userAgentPattern the pattern of the UserAgent
158: * @return a precompiled regular expression pattern to match.
159: * @throws DBException if the mattern match is bad.
160: */
161: private synchronized Pattern getPattern(String userAgentPattern)
162: throws DBException {
163: Pattern p = (Pattern) regExpCache.get(userAgentPattern);
164:
165: if (p == null) {
166: try {
167: p = compiler.compile(userAgentPattern,
168: Perl5Compiler.READ_ONLY_MASK);
169: regExpCache.put(userAgentPattern, p);
170: } catch (MalformedPatternException mpe) {
171: throw new DBException(this Class + "getPattern(String)",
172: mpe);
173: }
174: }
175:
176: return p;
177: }
178:
179: public Vector getValues() throws DBException {
180: return getValuesDefault("UserAgent", "Descrip");
181: }
182:
183: /**
184: * Figure out which UserAgent entry this User-Agent string from the browser
185: * should match & set this db object to the appropriate object.
186: *
187: * @param userAgentString the string of the user agent to match against
188: * @return true if we get a successful match.
189: * @throws DBException upon database communication error
190: */
191: public boolean getMatch(String userAgentString) throws DBException {
192: UserAgent oneAgent = null;
193: UserAgent agentList = new UserAgent();
194: agentList.setDataContext(getDataContext());
195: createObjectCache(agentList);
196:
197: for (Iterator i = agentList.searchAndRetrieveList("MatchSeq")
198: .iterator(); i.hasNext();) {
199: oneAgent = (UserAgent) i.next();
200:
201: String uaPattern = oneAgent.getField("UAPattern");
202: Pattern compiledRegExp = getPattern(uaPattern);
203:
204: boolean result;
205: synchronized (matcher) {
206: result = matcher.matches(userAgentString,
207: compiledRegExp);
208: }
209: if (result) { //wlo: changed 'uaPattern' to 'userAgentString'
210: setField("UserAgent", oneAgent.getField("UserAgent"));
211: retrieve();
212:
213: return true;
214: }
215: }
216:
217: return false;
218: } /* getMatch(String) */
219:
220: /**
221: * Standard method to return a new UserAgent object
222: *
223: * @return DBObject A new CacheSync object
224: * @throws DBException If the new object cannot be created
225: */
226: public DBObject getThisDBObj() throws DBException {
227: return (DBObject) new UserAgent();
228: } /* getThisDBObj() */
229:
230: /**
231: * Override the method getValues to provide specific values for our
232: * multi-valued fields
233: *
234: * @param fieldName Fielname to retrieve values for
235: * @return Vector of ValidValue Value/description pairs for this field
236: * @throws DBException If the values cannot be retrieved
237: */
238: public synchronized Vector getValidValues(String fieldName)
239: throws DBException {
240: if (fieldName.equals("Protocol")) {
241: Vector myValues = new Vector(4);
242: myValues.addElement(new ValidValue("http", "HTTP"));
243: myValues.addElement(new ValidValue("jobqueue",
244: "Via Job Queue"));
245:
246: return myValues;
247: }
248:
249: return super .getValidValues(fieldName);
250: } /* getValidValues(String) */
251:
252: /**
253: * Define the table and fields for this object
254: *
255: * @throws DBException If the fields cannot be set up
256: */
257: public void setupFields() throws DBException {
258: setTargetTable("USERAGENT");
259: setDescription("User-Agent Matching");
260: setCharset("ISO-8859-1");
261: addField("UserAgent", "auto-inc", 0, false, "User Agent Id");
262: addField("MatchSeq", "int", 0, false, "Match Sequence");
263: addField("Descrip", "varchar", 80, false, "Description");
264: addField("UAPattern", "text", 0, false, "Pattern to Match");
265: addKey("UserAgent");
266: setReadOnly("UserAgent");
267: } /* setupFields() */
268:
269: public synchronized void populateDefaultValues() throws DBException {
270: UserAgent defAgent = new UserAgent();
271: defAgent.setDataContext(getDataContext());
272: defAgent.setField("UAPattern", ".*");
273:
274: if (!defAgent.find()) {
275: defAgent.setField("Descrip", "Default Agent");
276: defAgent.setField("MatchSeq", "9999");
277: defAgent.add();
278: }
279: } /* populateDefaultValues() */
280:
281: } /* UserAgent */
282:
283: /* UserAgent */
|