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.services.dbobj;
066:
067: import com.jcorporate.expresso.core.db.DBConnection;
068: import com.jcorporate.expresso.core.db.DBException;
069: import com.jcorporate.expresso.core.dbobj.RequestContext;
070: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
071: import com.jcorporate.expresso.core.misc.ConfigContext;
072: import com.jcorporate.expresso.core.misc.ConfigManager;
073: import com.jcorporate.expresso.core.misc.StringUtil;
074: import org.apache.log4j.Logger;
075:
076: /**
077: * <p/>
078: * SecurityDBObject.java</p>
079: * this object provides a means to control the DB context via Setup values.
080: * subclasses will ignore any context except that found in Setup.
081: * <p/>
082: * You probably will never create a subclass of SecurityDBObject yourself--it is
083: * a framework tool embedded in the Expresso security system. The idea is to provide
084: * a flexible way to redirect authentication classes to another database context.
085: * For example, consider a situation where there are two Expresso applications,
086: * and you wanted the second application to rely on the first in order to
087: * authenticate users and otherwise supply user information.
088: * The following classes extend SecurityDBObject in Expresso:
089: * <ul>
090: * <li>ControllerSecurity</li>
091: * <li>DBObjSecurity</li>
092: * <li>DefaultUserInfo</li>
093: * <li>GroupMembers</li>
094: * <li>GroupNest</li>
095: * <li>JobSecurity</li>
096: * <li>TmpUser</li>
097: * <li>UserGroup</li>
098: * <li>UserPreference</li>
099: * <li>UserPreferenceDef</li>
100: * </ul>
101: * <p>SecurityDBObject provides a means to control the DB context
102: * (for some or all of the classes listed above) via Setup values.
103: * Two Setup values are important for SecurityDBObject:
104: * SecurityDB -- Database to use for User/Group Security Info
105: * SecurityDBObjs -- Database Objects that should use the 'fixed' context found in the SecurityDB parameter
106: * <p/>
107: * If these Setup values are empty, SecurityDBObject does nothing special. However, if these 2 Setup values contain
108: * meaningful info, subclasses of SecurityDBObject may ignore any DB context supplied (e.g., they can ignore a
109: * context like 'default' that comes from the ControllerRequest). The logic is two-fold: the Setup value SecurityDB
110: * must be filled, AND the Setup value SecurityDBObjs must contain the fully-qualified class name of all objects
111: * (from the list of SecurityDBObject subclasses listed above) that will use the 'fixed' context value in Setup
112: * value SecurityDB. That's a bit tricky, so to repeat: even though all the security classes listed above are
113: * instances of SecurityDBObject, each one will use the fixed context only if that individual class is also listed
114: * in the Setup value, SecurityDBObjs.
115: * </p>
116: * <p/>
117: * This scheme is useful in at least one case: one primary Expresso application supplying User information to a
118: * secondary Expresso application.
119: * </p>
120: * <p/>
121: * LIMITATION: user info and group membership changed on the primary,
122: * UserInfo application will not trigger a cache cleaning on the secondary
123: * system. So when these memberships are changed, manually clean the cache on
124: * the secondary system via admin
125: * pages, or by restarting.</p>
126: * <p>As always, this sample may not be representative of your needs, so attempt
127: * this only with caution and a single-step debugger handy.</p>
128: *
129: * @author Michael Nash
130: */
131: public abstract class SecurityDBObject extends SecuredDBObject {
132: private static Logger log = Logger
133: .getLogger(SecurityDBObject.class);
134: public static final String SECURITY_CONTEXT = "SecurityDB";
135: public static final String SECURITY_OBJECTS = "SecurityDBObjs";
136:
137: public SecurityDBObject() throws DBException {
138: super ();
139: }
140:
141: /**
142: * Use over (String) constructor. Initializes the object in the context
143: * of the user who's uid belongs to the parameter.
144: *
145: * @param uid the Uid of the user context
146: * @throws DBException if there's an initialization problem
147: */
148: public SecurityDBObject(int uid) throws DBException {
149: super (uid);
150: }
151:
152: /**
153: * For using DBObjects within Controllers. Initializes based upon the current
154: * user and the requested db. [Of course this can be modified later]
155: *
156: * @param request - The controller request handed to you by the framework.
157: * @throws DBException if there's an error constructing the object
158: */
159: public SecurityDBObject(RequestContext request) throws DBException {
160: super (request);
161: }
162:
163: /**
164: * Override of DBObject's setDataContext() to call setDBName
165: *
166: * @param newContext the new dataContext to use
167: */
168: public void setDataContext(String newContext) {
169: try {
170: setDBName(newContext);
171: } catch (DBException e) {
172: throw new IllegalArgumentException(e.getMessage());
173: }
174: }
175:
176: /**
177: * Ignore the newContext parameter if Setup values indicate to do this.
178: * In other words, when someone tries to set a new data context, check
179: * with Setup values to see if this SecurityDBObject subclass is listed in the set
180: * of SecurityDBObjs (a list configurable as a Setup param).
181: * <p/>
182: * Warning: calls super.setDBName(),
183: * which could loop back recursively if the superclass
184: * then creates objects which get db context set.
185: *
186: * @param newContext the new dataContext to use
187: * @throws DBException upon construction error.
188: */
189: public void setDBName(String newContext) throws DBException {
190: super .setDBName(newContext);
191: overrideDataContext(newContext);
192: }
193:
194: /**
195: * when someone tries to set a new data context, check
196: * with Setup values to see if this new context should be
197: * ignored, such as when a SecurityDBObject subclass is listed in the set
198: * of SecurityDBObjs (a list configurable as a Setup param).
199: *
200: * @param newContext the new data context to use.
201: */
202: protected void overrideDataContext(String newContext) {
203: try {
204: if (newContext == null || newContext.length() == 0) {
205: newContext = DBConnection.DEFAULT_DB_CONTEXT_NAME;
206: }
207:
208: // look for setup values only if the context includes setup
209: ConfigContext config = ConfigManager.getContext(newContext);
210: if (config != null && config.hasSetupTables()) {
211: String securityDB = StringUtil.notNull(Setup.getValue(
212: newContext, SECURITY_CONTEXT));
213: String objNames = StringUtil.notNull(Setup.getValue(
214: newContext, SECURITY_OBJECTS));
215:
216: // if our object is included in list,
217: // use the Setup value for DB context instead the one passed in
218: if (objNames.indexOf(getClass().getName()) >= 0) {
219: super .setDBName(securityDB);
220: }
221: }
222: } catch (Exception ex) {
223: String errorMessage = "Problem overriding newContext name: "
224: + newContext + ": " + ex.getMessage();
225: log.error(errorMessage, ex);
226: throw new IllegalArgumentException(errorMessage);
227: }
228: }
229: }
|