/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. 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 com.esri.gpt.catalog.search; import com.esri.gpt.catalog.harvest.protocols.HarvestProtocolNone; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Map; import java.util.TreeMap; import java.util.UUID; import java.util.logging.Logger; import com.esri.gpt.catalog.harvest.repository.HrRecord; import com.esri.gpt.control.webharvest.protocol.Protocol; import com.esri.gpt.framework.collection.StringSet; import com.esri.gpt.framework.context.RequestContext; import com.esri.gpt.framework.jsf.FacesContextBroker; import com.esri.gpt.framework.security.principal.User; import com.esri.gpt.framework.sql.BaseDao; import com.esri.gpt.framework.sql.ConnectionBroker; import com.esri.gpt.framework.sql.ManagedConnection; import com.esri.gpt.framework.util.UuidUtil; import com.esri.gpt.framework.util.Val; import com.esri.gpt.framework.xml.DomUtil; /** * The Class GptRepository. Object that communicates with the Gpt repository for * the search classes . */ public class GptRepository extends BaseDao implements ISearchSaveRepository { // class variables ============================================================= /** Table where all the saves are inserted into **/ private static String SAVE_TABLE = "GPT_SEARCH"; /** Class logger **/ private static final Logger LOG = Logger.getLogger(GptRepository.class .getCanonicalName()); // methods ===================================================================== /** * Delete a search * * @param id * associated with the saved search * @param user * associated with the saved search * @throws SearchException */ public void delete(Object id, User user) throws SearchException { PreparedStatement pStmt = null; Connection connection = null; try { String sql = " DELETE FROM " + SAVE_TABLE + " WHERE UUID=? AND USERID=? "; connection = this.getConnection(); pStmt = connection.prepareStatement(sql); int n = 1; pStmt.setString(n++, id.toString()); pStmt.setInt(n++, user.getLocalID()); pStmt.executeUpdate(); } catch (Exception e) { throw new SearchException(e); } finally { closeStatement(pStmt); } } /** * * @param user * associated with the saved search * @return List of criterias * @throws SearchException */ public SavedSearchCriterias getSavedList(User user) throws SearchException { Connection connection = null; SavedSearchCriterias criteria = new SavedSearchCriterias(); PreparedStatement ps = null; ResultSet rs = null; try { String sql = "SELECT UUID, NAME, CRITERIA FROM " + SAVE_TABLE + " WHERE USERID = ?"; connection = this.getConnection(); ps = connection.prepareStatement(sql); ps.setInt(1, user.getLocalID()); rs = ps.executeQuery(); String name = null; String id; String sCriteria; while (rs.next()) { id = rs.getString(1); name = rs.getString(2); sCriteria = rs.getString(3); SavedSearchCriteria sCrit = new SavedSearchCriteria(id, name, this); sCrit.setCriteria(sCriteria); criteria.add(sCrit); } } catch (Exception e) { throw new SearchException(e); } finally { closeResultSet(rs); closeStatement(ps); } return criteria; } /** * Gets search criteria object * * @param id * of the search criteria * @param user * associated with the saved search * @return SearchCriteria queried * @throws SearchException */ public SearchCriteria getSearchCriteria(Object id, User user) throws SearchException { Connection connection = null; PreparedStatement ps = null; ResultSet rs = null; SearchCriteria searchCriteria = null; try { String sql = "SELECT CRITERIA FROM " + SAVE_TABLE + " WHERE USERID = ? " + "AND UUID = ?"; connection = this.getConnection(); ps = connection.prepareStatement(sql); ps.setInt(1, user.getLocalID()); ps.setString(2, id.toString()); rs = ps.executeQuery(); String criteriaXml = null; if (rs.next()) { criteriaXml = Val.chkStr(rs.getString(1)); if ("".equals(criteriaXml)) { throw new SearchException( "Empty search criteria retrived from repository."); } searchCriteria = new SearchCriteria(DomUtil.makeDomFromString( criteriaXml, false)); } } catch (Exception e) { throw new SearchException(e); } finally { closeResultSet(rs); closeStatement(ps); } return searchCriteria; } /** * Saves the criteria * * @param savedCriteria * Object with the search to be saved * @throws SearchException */ public void save(SavedSearchCriteria savedCriteria) throws SearchException { PreparedStatement pStmt = null; Connection connection = null; try { SearchCriteria criteria = savedCriteria.getSearchCriteria(); String name = criteria.getSavedSearchName(); int userId = savedCriteria.getUser().getLocalID(); String uuid = UUID.randomUUID().toString(); String sql = " INSERT INTO " + SAVE_TABLE + " (UUID, NAME, USERID, CRITERIA) " + " VALUES(?,?,?,?)"; connection = this.getConnection(); pStmt = connection.prepareStatement(sql); int n = 1; pStmt.setString(n++, uuid); pStmt.setString(n++, name); pStmt.setInt(n++, userId); pStmt.setString(n++, criteria.toDom2()); pStmt.executeUpdate(); } catch (Exception e) { throw new SearchException(e); } finally { closeStatement(pStmt); } } /** * Saves the criteria * * @param name name * @param restCriteria * Object with the search to be saved * @param user user * @throws SearchException */ public void save(String name, String restCriteria, User user) throws SearchException { PreparedStatement pStmt = null; Connection connection = null; try { String uuid = UUID.randomUUID().toString(); String sql = " INSERT INTO " + SAVE_TABLE + " (UUID, NAME, USERID, CRITERIA) " + " VALUES(?,?,?,?)"; connection = this.getConnection(); pStmt = connection.prepareStatement(sql); int n = 1; pStmt.setString(n++, uuid); pStmt.setString(n++, name); pStmt.setInt(n++, user.getLocalID()); pStmt.setString(n++, restCriteria); pStmt.executeUpdate(); } catch (Exception e) { throw new SearchException(e); } finally { closeStatement(pStmt); } } /** * Gets the connection. * * @return the connection (never null) * * @throws SearchException * the search exception * @throws SQLException * the SQL exception */ protected Connection getConnection() throws SearchException, SQLException { SearchConfig.getConfiguredInstance(); RequestContext requestContext = this.getRequestContext(); if (requestContext == null) { throw new SearchException("Could not get a request context so as " + " to make a" + " connection to the repository."); } ConnectionBroker connectionBroker = requestContext.getConnectionBroker(); if (connectionBroker == null) { throw new SearchException("Could not get a Connection Broker so as" + " to make a" + " connection to the repository."); } ManagedConnection managedConnection = connectionBroker.returnConnection(""); Connection connection = managedConnection.getJdbcConnection(); if (connection == null) { throw new SearchException("Got null connection to repository " + "for save search"); } return connection; } /** * Gets the request context * * @return RequestContext for this Request */ @Override public RequestContext getRequestContext() { if(super.getRequestContext() != null) { return super.getRequestContext(); } FacesContextBroker broker = new FacesContextBroker(); RequestContext requestContext = broker.extractRequestContext(); return requestContext; } /** * Read harvest record. Will update uuid, url, profile, protocol and name * * @param rid * repository id * @param context * the request context * * @return the hr record * * @throws SearchException * the search exception */ public HrRecord readHarvestRecord(String rid, RequestContext context) throws SearchException { StringSet ridSet = new StringSet(); ridSet.add(rid); Map<String, HrRecord> mapHrRecord = this.readHarvestRecords(ridSet, context); if(mapHrRecord.size() < 1 || mapHrRecord.get(rid) == null) { throw new SearchException("Could not get record from db with rid = " + rid); } return mapHrRecord.get(rid); } /** * Read harvest records. * * @param rids the rids * @param context the context * @return the map between rid and hrRecord (never null) * @throws SearchException the search exception * * */ public Map<String, HrRecord> readHarvestRecords(StringSet rids, RequestContext context) throws SearchException { // TODO: Sort out exception issues HrRecord record = null; PreparedStatement st = null; ManagedConnection mcon = null; ResultSet rs = null; Map<String, HrRecord> mpRidRecords = new TreeMap<String, HrRecord>(String.CASE_INSENSITIVE_ORDER); Map<String, String> idFields = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER); for (String rid : rids) { rid = Val.chkStr(rid); if (rid.length() < 1) { continue; } String field = "DOCUUID"; try { Integer.parseInt(rid); field = "ID"; } catch (NumberFormatException nfe) { if (!UuidUtil.isUuid(rid)) { rid = rid.toUpperCase(); field = "UPPER(TITLE)"; } } idFields.put(rid, field); } // Create sql to query db String table = context.getCatalogConfiguration().getResourceTableName(); String sql = "SELECT PROTOCOL_TYPE, HOST_URL, PROTOCOL, TITLE, " + "DOCUUID, ID FROM " + table + " WHERE "; int i = 0; int maxEntries = idFields.size(); for (Map.Entry<String, String> entry : idFields.entrySet()) { sql += entry.getValue() + "= ?"; if (i >= 0 && i < maxEntries - 1) { sql += " or "; } i++; } sql += " AND ((APPROVALSTATUS = 'approved') OR (APPROVALSTATUS = 'reviewed'))"; sql += " AND SEARCHABLE = 'true'"; LOG.info("DB Query " + sql); ArrayList<HrRecord> arrHrRecords = new ArrayList<HrRecord>(); try { mcon = context.getConnectionBroker().returnConnection(""); st = mcon.getJdbcConnection().prepareStatement(sql); int parNum = 1; for (Map.Entry<String, String> entry : idFields.entrySet()) { String field = entry.getValue(); String rid = entry.getKey(); if (field.equalsIgnoreCase("ID")) { st.setInt(parNum, Val.chkInt(rid, Integer.MIN_VALUE)); } else { st.setString(parNum, rid); } parNum++; } rs = st.executeQuery(); while (rs.next()) { // Assembling records for each id record = new HrRecord(); record.setHostUrl(rs.getString(2)); String protocolDef = rs.getString(3); Protocol protocol = getRequestContext().getApplicationConfiguration() .getProtocolFactories().parseProtocol(protocolDef); try { record.setProtocol(protocol); } catch (IllegalArgumentException ex) { record.setProtocol(new HarvestProtocolNone()); } record.setName(rs.getString(4)); record.setUuid(rs.getString(5)); LOG .info("Name = " + record.getName() + "protocol " + protocol.toString()); // Attempting to marshall db with ids that have been given String id = Val.chkStr(rs.getString("ID")); String idValue = Val.chkStr(idFields.get(id)); String docuuid = Val.chkStr(rs.getString("DOCUUID")); String docuuidValue = Val.chkStr(idFields.get(docuuid)); String title = Val.chkStr(rs.getString("TITLE")); String titleValue = Val.chkStr(idFields.get(title)); if(!"".equals(docuuidValue)) { mpRidRecords.put(docuuid, record); } else if (!"".equals(titleValue)) { mpRidRecords.put(title, record); } else if (!"".equals(idValue)) { mpRidRecords.put(id, record); } } } catch (Exception e) { throw new SearchException(e); // throw new SearchException("Could not get Harvest Record with UUID/ID = " // + rid + ":" + e.getMessage(), e); } finally { BaseDao.closeStatement(st); BaseDao.closeResultSet(rs); } return mpRidRecords; } }