001: /*
002: * ====================================================================
003: * JAFFA - Java Application Framework For All
004: *
005: * Copyright (C) 2002 JAFFA Development Group
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: * Redistribution and use of this software and associated documentation ("Software"),
022: * with or without modification, are permitted provided that the following conditions are met:
023: * 1. Redistributions of source code must retain copyright statements and notices.
024: * Redistributions must also contain a copy of this document.
025: * 2. Redistributions in binary form must reproduce the above copyright notice,
026: * this list of conditions and the following disclaimer in the documentation
027: * and/or other materials provided with the distribution.
028: * 3. The name "JAFFA" must not be used to endorse or promote products derived from
029: * this Software without prior written permission. For written permission,
030: * please contact mail to: jaffagroup@yahoo.com.
031: * 4. Products derived from this Software may not be called "JAFFA" nor may "JAFFA"
032: * appear in their names without prior written permission.
033: * 5. Due credit should be given to the JAFFA Project (http://jaffa.sourceforge.net).
034: *
035: * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
036: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
037: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
038: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
039: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
040: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
041: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
042: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
043: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
044: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
045: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
046: * SUCH DAMAGE.
047: * ====================================================================
048: */
049: package org.jaffa.security;
050:
051: import org.apache.log4j.Logger;
052: import java.sql.CallableStatement;
053: import java.sql.Connection;
054: import java.sql.SQLException;
055: import java.lang.String;
056: import java.security.Principal;
057: import java.util.Iterator;
058: import java.util.ArrayList;
059: import java.util.Set;
060: import java.util.List;
061: import java.util.WeakHashMap;
062: import oracle.sql.ArrayDescriptor;
063: import oracle.sql.ARRAY;
064:
065: //
066: import java.sql.*;
067: import org.apache.commons.dbcp.DelegatingConnection;
068: import java.io.*;
069: import org.jaffa.util.StringHelper;
070:
071: //
072: import org.jaffa.persistence.engines.jdbcengine.security.IJdbcSecurityPlugin;
073: import org.jaffa.exceptions.UOWSecurityException;
074: import org.jaffa.security.SecurityManager;
075: import org.jaffa.security.SecurityContext;
076:
077: /**
078: * JDBCSecurityPlugin.java
079: *
080: * @author maheshd
081: * @version 1.1
082: */
083: public class JDBCSecurityPlugin implements IJdbcSecurityPlugin {
084:
085: private static final Logger log = Logger
086: .getLogger(JDBCSecurityPlugin.class);
087:
088: /** This holds previously calculated values for the role list per user.
089: * It is possible for the JVM Garbage Collecter to empty this if needed
090: */
091: private static WeakHashMap cache = new WeakHashMap();
092:
093: /** Creates new JDBCSecurityPlugin */
094: public JDBCSecurityPlugin() {
095: }
096:
097: private void executeStoredProcedure(Connection connection,
098: String userid) throws java.sql.SQLException {
099: CallableStatement cs = null;
100: try {
101: if (log.isDebugEnabled())
102: log
103: .debug("Calling the Stored Procedure to Set the Context");
104: // Call a procedure with no parameters
105: cs = connection
106: .prepareCall("{call jaffa_sec.set_userid(?,?)}");
107: cs.setString(1, userid);
108:
109: // When using the dbcp DataSource, a wrapper connection is created. Extract the actual oracle connection from the wrapper.
110: if (connection instanceof DelegatingConnection)
111: connection = ((DelegatingConnection) connection)
112: .getInnermostDelegate();
113: ArrayDescriptor desc = ArrayDescriptor.createDescriptor(
114: "ROLE", connection);
115: ARRAY newArray = new ARRAY(desc, connection, getUserRoles(
116: userid).toArray());
117: cs.setArray(2, newArray);
118: // Execute the stored procedure
119: cs.execute();
120:
121: } catch (SQLException e) {
122: String str = "Error in executing the the Stored Procedure to Set the Context";
123: log.error(str, e);
124: throw new UOWSecurityException(str, e);
125: } finally {
126: if (cs != null)
127: cs.close();
128: }
129: }
130:
131: public void newConnection(Connection connection)
132: throws java.sql.SQLException {
133:
134: if (log.isDebugEnabled())
135: log.debug("Getting the Security Context");
136:
137: SecurityContext current = SecurityManager.getCurrentContext();
138: if (current != null) {
139: if (log.isDebugEnabled())
140: log.debug("Getting the Principal");
141: Principal p = current.getPrincipal();
142: if (p != null) {
143: String userid = p.getName();
144: if (userid != null) {
145: try {
146: if (connection != null) {
147: executeStoredProcedure(connection, userid);
148: }
149: } catch (SQLException e) {
150: String str = "Error in executing the newConnection trigger of the JdbcSecurityPlugin";
151: log.error(str, e);
152: throw new UOWSecurityException(str, e);
153: }
154: }
155: }
156: }
157: }
158:
159: public void freeConnection(Connection connection)
160: throws java.sql.SQLException {
161: CallableStatement cs = null;
162: try {
163: if (log.isDebugEnabled())
164: log.debug("Clearing the Security Context");
165: // Call a procedure with no parameters
166: cs = connection.prepareCall("{call jaffa_sec.clearctx}");
167: // Execute the stored procedure
168: cs.execute();
169:
170: } catch (SQLException e) {
171: String str = "Error in executing the the Stored Procedure for Clearing the Context";
172: log.error(str, e);
173: throw new UOWSecurityException(str, e);
174: } finally {
175: if (cs != null)
176: cs.close();
177: }
178: }
179:
180: /** Get the roles for this user. If we can find a cached list use that, else use
181: * the current security context to check them
182: */
183: private List getUserRoles(String userid) {
184: List l = (List) cache.get(userid);
185: if (l != null)
186: return l;
187: // Figure out access and cache it.
188: ArrayList al = new ArrayList();
189: Set rl = PolicyManager.getRoleSet();
190: if (rl != null) {
191: // Get thread context
192: SecurityContext ctx = SecurityManager.getCurrentContext();
193: if (ctx != null) {
194: // Check access to each role
195: if (log.isDebugEnabled())
196: log.debug("Checking the Access to Each Role");
197: for (Iterator it = rl.iterator(); it.hasNext();) {
198: String role = (String) it.next();
199: // If user has added add to the array
200: if (ctx.inRole(role)) {
201: if (al == null)
202: al = new ArrayList();
203: al.add(role);
204:
205: }
206: }
207: }
208: }
209: // Cache array and return value.
210: cache.put(userid, al);
211: return al;
212: }
213:
214: /** Flush the cached list of security roles
215: */
216: public static void clearCache() {
217: cache = new WeakHashMap();
218: }
219: }
|