001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.portals.gems.browser;
018:
019: import java.io.IOException;
020: import java.security.AccessControlContext;
021: import java.security.AccessController;
022: import java.sql.Connection;
023: import java.sql.PreparedStatement;
024: import java.sql.ResultSet;
025: import java.sql.ResultSetMetaData;
026: import java.sql.SQLException;
027: import java.sql.Types;
028: import java.util.ArrayList;
029: import java.util.Iterator;
030: import java.util.List;
031:
032: import javax.naming.Context;
033: import javax.naming.InitialContext;
034: import javax.portlet.ActionRequest;
035: import javax.portlet.ActionResponse;
036: import javax.portlet.PortletException;
037: import javax.portlet.PortletMode;
038: import javax.portlet.PortletPreferences;
039: import javax.portlet.PortletRequest;
040: import javax.portlet.PortletSession;
041: import javax.portlet.RenderRequest;
042: import javax.portlet.RenderResponse;
043: import javax.security.auth.Subject;
044: import javax.sql.DataSource;
045:
046: import org.apache.commons.dbcp.BasicDataSource;
047: import org.apache.jetspeed.security.JSSubject;
048: import org.apache.jetspeed.sso.SSOContext;
049: import org.apache.jetspeed.sso.SSOException;
050: import org.apache.portals.bridges.util.PreferencesHelper;
051: import org.apache.portals.gems.util.StatusMessage;
052: import org.apache.portals.messaging.PortletMessaging;
053:
054: /**
055: * DatabaseBrowserPortlet
056: *
057: * @author <a href="mailto:taylor@apache.org">David Sean Taylor </a>
058: * @version $Id: DatabaseBrowserPortlet.java 516448 2007-03-09 16:25:47Z ate $
059: */
060: public class DatabaseBrowserPortlet extends BrowserPortlet implements
061: Browser {
062: /**
063: * Execute the sql statement as specified by the user or the default, and
064: * store the resultSet in a vector.
065: *
066: * @param sql
067: * The sql statement to be executed.
068: * @param data
069: * The turbine rundata context for this request.
070: */
071: public void getRows(RenderRequest request, String sql,
072: int windowSize) throws Exception {
073: List resultSetList = new ArrayList();
074: List resultSetTitleList = new ArrayList();
075: List resultSetTypeList = new ArrayList();
076:
077: Connection con = null;
078: PreparedStatement selectStmt = null;
079: ResultSet rs = null;
080:
081: PortletSession session = request.getPortletSession();
082: try {
083: String poolname = getPreference(request, POOLNAME, null);
084: if (poolname == null || poolname.length() == 0) {
085: con = getConnection(request);
086: } else {
087: con = getConnection(poolname);
088: }
089: selectStmt = con.prepareStatement(sql);
090:
091: readSqlParameters(request);
092: Iterator it = sqlParameters.iterator();
093: int ix = 0;
094: while (it.hasNext()) {
095: ix++;
096: Object object = it.next();
097: selectStmt.setObject(ix, object);
098: }
099: rs = selectStmt.executeQuery();
100: ResultSetMetaData rsmd = rs.getMetaData();
101: int columnNum = rsmd.getColumnCount();
102: /*
103: * get the user object types to be displayed and add them to the
104: * title list as well as the result set list
105: */
106: List userObjList = (List) session
107: .getAttribute(USER_OBJECTS);
108: int userObjListSize = 0;
109: if (userObjList != null) {
110: userObjListSize = userObjList.size();
111: }
112: //System.out.println("User List Size = "+ userObjListSize);
113: /*
114: * the array columnDisplayed maintains a boolean value for each
115: * column index. Only the columns that are set to true are added to
116: * the resultSetList, resultSetTitleList and resultSetTypeList.
117: */
118: boolean[] columnDisplayed = new boolean[columnNum
119: + userObjListSize];
120:
121: /*
122: * this for loop constructs the columnDisplayed array as well as
123: * adds to the resultSetTitleList and resultSetTypeList
124: */
125: for (int i = 1; i <= columnNum; i++) {
126: int type = rsmd.getColumnType(i);
127: if (!((type == Types.BLOB) || (type == Types.CLOB)
128: || (type == Types.BINARY)
129: || (type == Types.LONGVARBINARY) || (type == Types.VARBINARY))) {
130: resultSetTitleList.add(rsmd.getColumnName(i));
131: resultSetTypeList.add(String.valueOf(type));
132: columnDisplayed[i - 1] = true;
133: } else {
134: columnDisplayed[i - 1] = false;
135: }
136: }
137:
138: for (int i = columnNum; i < columnNum + userObjListSize; i++) {
139: ActionParameter usrObj = (ActionParameter) userObjList
140: .get(i - columnNum);
141: resultSetTitleList.add(usrObj.getName());
142: resultSetTypeList.add(usrObj.getType());
143: columnDisplayed[i] = true;
144: //System.out.println("User List Name = "+ usrObj.getName()+"
145: // Type = "+usrObj.getType());
146: }
147: /*
148: * this while loop adds each row to the resultSetList
149: */
150: int index = 0;
151: while (rs.next()) {
152: List row = new ArrayList(columnNum);
153:
154: for (int i = 1; i <= columnNum; i++) {
155: if (columnDisplayed[i - 1]) {
156: Object obj = rs.getObject(i);
157: if (obj == null) {
158: obj = VELOCITY_NULL_ENTRY;
159: }
160: row.add(obj);
161: }
162: }
163: for (int i = columnNum; i < columnNum + userObjListSize; i++) {
164: ActionParameter usrObj = (ActionParameter) userObjList
165: .get(i - columnNum);
166: if (columnDisplayed[i]) {
167: Class c = Class.forName(usrObj.getType());
168: row.add(c.newInstance());
169: populate(index, i, row);
170: }
171: }
172:
173: if (filter(row, request)) {
174: continue;
175: }
176:
177: resultSetList.add(row);
178: index++;
179: }
180: BrowserIterator iterator = new DatabaseBrowserIterator(
181: resultSetList, resultSetTitleList,
182: resultSetTypeList, windowSize);
183: setBrowserIterator(request, iterator);
184:
185: } catch (SQLException e) {
186: throw e;
187: } finally {
188: try {
189: if (null != selectStmt)
190: selectStmt.close();
191: if (null != rs)
192: rs.close();
193: if (null != con) //closes con also
194: {
195: closeConnection(con);
196: }
197:
198: } catch (Exception e) {
199: throw e;
200: }
201: }
202:
203: }
204:
205: /*
206: * Connection Management
207: */
208:
209: public Connection getConnection(PortletRequest request)
210: throws Exception {
211: Connection con = null;
212: try {
213: PortletPreferences prefs = request.getPreferences();
214: String dsType = prefs.getValue("DatasourceType", null);
215: if (dsType == null) {
216: throw new SQLException("No DataSource provided");
217: }
218: if (dsType.equals("jndi")) {
219: Context ctx = new InitialContext();
220: String dsName = prefs.getValue("JndiDatasource", "");
221: Context envContext = (Context) ctx
222: .lookup("java:/comp/env");
223: DataSource ds = (DataSource) envContext.lookup(dsName);
224: con = ds.getConnection();
225: } else if (dsType.equals("dbcp")) {
226: BasicDataSource ds = new BasicDataSource();
227: ds.setDriverClassName(prefs.getValue("JdbcDriver", ""));
228: ds.setUrl(prefs.getValue("JdbcConnection", ""));
229: ds.setUsername(prefs.getValue("JdbcUsername", ""));
230: ds.setPassword(prefs.getValue("JdbcPassword", ""));
231: // ds.setUrl("jdbc:mysql://j2-server/j2");
232: con = ds.getConnection();
233: } else if (dsType.equals("sso")) {
234: /*
235: * For SSO the user has to define the JDBCdriver and JdbcConnection (URL)
236: * but the credentials for the db come from the SSO storage
237: */
238: BasicDataSource ds = new BasicDataSource();
239: ds.setDriverClassName(prefs.getValue("SSOJdbcDriver",
240: ""));
241: ds.setUrl(prefs.getValue("SSOJdbcConnection", ""));
242: String ssoURL = prefs.getValue("SSOSite", "");
243:
244: // SSO API lookup
245: SSOContext credentials = null;
246: try {
247: if (sso == null)
248: throw new SSOException("SSO Not supported.");
249:
250: credentials = sso.getCredentials(getSubject(),
251: ssoURL);
252: } catch (SSOException ssoex) {
253: throw new Exception(
254: "SSO credential lookup failed. Error: "
255: + ssoex.getMessage());
256: }
257:
258: String ssoUserName = credentials
259: .getRemotePrincipalName();
260: String ssoPWD = credentials.getRemoteCredential();
261: ds.setUsername(ssoUserName);
262: ds.setPassword(ssoPWD);
263: con = ds.getConnection();
264: } else {
265: throw new SQLException("No DataSource provided");
266: }
267:
268: } catch (Exception e) {
269: throw new Exception("Failed to connect", e); // TODO: complete this
270: }
271: return con;
272: }
273:
274: public Connection getConnection(String poolName) {
275: return null;
276: }
277:
278: public void closeConnection(Connection con) {
279: try {
280: con.close();
281: } catch (SQLException e) {
282: log.error("Cant close connection", e);
283: }
284:
285: }
286:
287: public void doEdit(RenderRequest request, RenderResponse response)
288: throws PortletException, IOException {
289: response.setContentType("text/html");
290: StatusMessage msg = (StatusMessage) PortletMessaging.consume(
291: request, "DatabaseBrowserPortlet", "dbConnectTest");
292: if (msg != null) {
293: this .getContext(request).put("statusMsg", msg);
294: }
295: super .doEdit(request, response);
296: }
297:
298: public void processAction(ActionRequest request,
299: ActionResponse response) throws PortletException,
300: IOException {
301: if (request.getPortletMode() == PortletMode.EDIT) {
302: String test = request.getParameter("Test");
303: if (test != null && test.equals("Test")) {
304: try {
305: PortletPreferences prefs = request.getPreferences();
306: PreferencesHelper
307: .requestParamsToPreferences(request);
308: prefs.store();
309: getConnection(request);
310: StatusMessage msg = new StatusMessage(
311: "Connection made successfully.",
312: StatusMessage.SUCCESS);
313: PortletMessaging.publish(request,
314: "DatabaseBrowserPortlet", "dbConnectTest",
315: msg);
316: } catch (Exception e) {
317: String msg = e.toString();
318: Throwable cause = e.getCause();
319: if (cause != null) {
320: msg = msg + ", " + cause.getMessage();
321: }
322: StatusMessage sm = new StatusMessage(msg,
323: StatusMessage.ERROR);
324: PortletMessaging.publish(request,
325: "DatabaseBrowserPortlet", "dbConnectTest",
326: sm);
327: }
328: response.setPortletMode(PortletMode.EDIT);
329: return;
330: }
331: }
332: super .processAction(request, response);
333: }
334:
335: private Subject getSubject() {
336: AccessControlContext context = AccessController.getContext();
337: return JSSubject.getSubject(context);
338: }
339: }
|