001: /***************************************************************
002: * This file is part of the [fleXive](R) project.
003: *
004: * Copyright (c) 1999-2008
005: * UCS - unique computing solutions gmbh (http://www.ucs.at)
006: * All rights reserved
007: *
008: * The [fleXive](R) project is free software; you can redistribute
009: * it and/or modify it under the terms of the GNU General Public
010: * License as published by the Free Software Foundation;
011: * either version 2 of the License, or (at your option) any
012: * later version.
013: *
014: * The GNU General Public License can be found at
015: * http://www.gnu.org/copyleft/gpl.html.
016: * A copy is found in the textfile GPL.txt and important notices to the
017: * license from the author are found in LICENSE.txt distributed with
018: * these libraries.
019: *
020: * This library is distributed in the hope that it will be useful,
021: * but WITHOUT ANY WARRANTY; without even the implied warranty of
022: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
023: * GNU General Public License for more details.
024: *
025: * For further information about UCS - unique computing solutions gmbh,
026: * please see the company website: http://www.ucs.at
027: *
028: * For further information about [fleXive](R), please see the
029: * project website: http://www.flexive.org
030: *
031: *
032: * This copyright notice MUST APPEAR in all copies of the file!
033: ***************************************************************/package com.flexive.ejb.beans.search;
034:
035: import com.flexive.core.Database;
036: import com.flexive.core.DatabaseConst;
037: import com.flexive.core.search.SqlSearch;
038: import com.flexive.shared.EJBLookup;
039: import com.flexive.shared.FxContext;
040: import com.flexive.shared.configuration.Parameter;
041: import com.flexive.shared.configuration.ParameterDataBean;
042: import com.flexive.shared.configuration.ParameterPathBean;
043: import com.flexive.shared.configuration.SystemParameters;
044: import com.flexive.shared.configuration.parameters.ObjectParameter;
045: import com.flexive.shared.exceptions.*;
046: import com.flexive.shared.interfaces.*;
047: import com.flexive.shared.search.*;
048: import com.flexive.shared.search.query.QueryRootNode;
049: import org.apache.commons.logging.Log;
050: import org.apache.commons.logging.LogFactory;
051:
052: import javax.annotation.Resource;
053: import javax.ejb.EJB;
054: import javax.ejb.Stateless;
055: import javax.ejb.TransactionAttribute;
056: import javax.ejb.TransactionAttributeType;
057: import java.sql.Connection;
058: import java.sql.ResultSet;
059: import java.sql.Statement;
060: import java.sql.Timestamp;
061: import java.util.Collection;
062:
063: @javax.ejb.TransactionManagement(javax.ejb.TransactionManagementType.CONTAINER)
064: @Stateless(name="SearchEngine")
065: public class SearchEngineBean implements SearchEngine,
066: SearchEngineLocal {
067: private static final Log LOG = LogFactory
068: .getLog(SearchEngineBean.class);
069: private static final String DEFAULT_QUERY_NAME = SearchEngineBean.class
070: + ".DEFAULTQUERY";
071:
072: @Resource
073: javax.ejb.SessionContext ctx;
074: @EJB
075: ResultPreferencesEngineLocal resultPreferences;
076: @EJB
077: private SequencerEngine seq;
078: @EJB
079: private BriefcaseEngine briefcase;
080: @EJB
081: private ConfigurationEngineLocal configuration;
082: @EJB
083: private TreeEngine treeEngine;
084:
085: /**
086: * {@inheritDoc}
087: */
088: @TransactionAttribute(TransactionAttributeType.REQUIRED)
089: public FxResultSet search(String query, final int startIndex,
090: final Integer fetchRows, FxSQLSearchParams params)
091: throws FxApplicationException {
092: return search(query, startIndex, fetchRows, params,
093: AdminResultLocations.DEFAULT, ResultViewType.LIST);
094: }
095:
096: /**
097: * {@inheritDoc}
098: */
099: @TransactionAttribute(TransactionAttributeType.REQUIRED)
100: public FxResultSet search(String query, int startIndex,
101: Integer fetchRows, FxSQLSearchParams params,
102: ResultLocation location, ResultViewType viewType)
103: throws FxApplicationException {
104: try {
105: if (params == null) {
106: params = new FxSQLSearchParams();
107: }
108: return new SqlSearch(seq, briefcase, treeEngine, query,
109: startIndex, fetchRows, params, resultPreferences,
110: location, viewType).executeQuery();
111: } catch (FxSqlSearchException exc) {
112: ctx.setRollbackOnly();
113: throw exc;
114: }
115: }
116:
117: /**
118: * {@inheritDoc}
119: */
120: @TransactionAttribute(TransactionAttributeType.REQUIRED)
121: public long getLastContentChange(boolean live) {
122: Connection con = null;
123: Statement stmt = null;
124: try {
125: con = Database.getDbConnection();
126: String contentFilter = live ? " where ISLIVE_VER=true "
127: : "";
128: String sSql = "select max(modified_at) from\n"
129: + "(select\n"
130: + "(select max(modified_at) from "
131: + DatabaseConst.TBL_CONTENT
132: + contentFilter
133: + ") modified_at\n"
134: + (live ? "\nunion\n(select max(modified_at) from "
135: + DatabaseConst.TBL_TREE + "_LIVE)\n" : "")
136: + "\nunion\n(select max(modified_at) from "
137: + DatabaseConst.TBL_TREE + ")\n" + ") changes";
138: stmt = con.createStatement();
139: ResultSet rs = stmt.executeQuery(sSql);
140: rs.next();
141: return rs.getLong(1);
142: } catch (Exception e) {
143: throw new FxLoadException(LOG, e,
144: "ex.sqlSearch.lastContentChange", e)
145: .asRuntimeException();
146: } finally {
147: Database.closeObjects(this .getClass(), con, stmt);
148: }
149: }
150:
151: /**
152: * {@inheritDoc}
153: */
154: @TransactionAttribute(TransactionAttributeType.REQUIRED)
155: public QueryRootNode load(ResultLocation location, String name)
156: throws FxApplicationException {
157: return configuration.get(getConfigurationParameter(location),
158: name);
159: }
160:
161: /**
162: * {@inheritDoc}
163: */
164: @TransactionAttribute(TransactionAttributeType.REQUIRED)
165: public QueryRootNode loadDefault(ResultLocation location)
166: throws FxApplicationException {
167: try {
168: return load(location, DEFAULT_QUERY_NAME);
169: } catch (FxNotFoundException e) {
170: return new QueryRootNode(QueryRootNode.Type.CONTENTSEARCH,
171: location);
172: } catch (FxApplicationException e) {
173: LOG.error(e.getMessage(), e);
174: throw e;
175: }
176: }
177:
178: /**
179: * {@inheritDoc}
180: */
181: @TransactionAttribute(TransactionAttributeType.REQUIRED)
182: public Collection<String> loadNames(ResultLocation location)
183: throws FxApplicationException {
184: return configuration
185: .getKeys(getConfigurationParameter(location));
186: }
187:
188: /**
189: * {@inheritDoc}
190: */
191: @TransactionAttribute(TransactionAttributeType.REQUIRED)
192: public void save(QueryRootNode query) throws FxApplicationException {
193: save(configuration, query, query.getName());
194: }
195:
196: /**
197: * {@inheritDoc}
198: */
199: @TransactionAttribute(TransactionAttributeType.REQUIRED)
200: public void saveDefault(QueryRootNode query)
201: throws FxApplicationException {
202: save(configuration, query, DEFAULT_QUERY_NAME);
203: }
204:
205: /**
206: * {@inheritDoc}
207: */
208: @TransactionAttribute(TransactionAttributeType.REQUIRED)
209: public void saveSystemDefault(QueryRootNode query)
210: throws FxApplicationException {
211: if (!FxContext.get().getTicket().isGlobalSupervisor()) {
212: throw new FxNoAccessException(LOG,
213: "ex.searchQuery.systemDefault.noAccess");
214: }
215: save(EJBLookup.getDivisionConfigurationEngine(), query,
216: DEFAULT_QUERY_NAME);
217: }
218:
219: /**
220: * {@inheritDoc}
221: */
222: @TransactionAttribute(TransactionAttributeType.REQUIRED)
223: public void remove(ResultLocation location, String name)
224: throws FxApplicationException {
225: configuration.remove(getConfigurationParameter(location), name);
226: }
227:
228: private void save(GenericConfigurationEngine configuration,
229: QueryRootNode query, String key) throws FxUpdateException {
230: try {
231: configuration.put(getConfigurationParameter(query
232: .getLocation()), key, query);
233: } catch (Exception e) {
234: throw new FxUpdateException(LOG, "ex.searchQuery.toXml", e,
235: e.getMessage());
236: }
237: }
238:
239: /**
240: * Return the appropriate string parameter for the given query type.
241: *
242: * @param location the result location
243: * @return the appropriate string parameter for the given query type.
244: */
245: private ObjectParameter<QueryRootNode> getConfigurationParameter(
246: ResultLocation location) {
247: final Parameter<QueryRootNode> parameter = SystemParameters.USER_QUERIES_CONTENT;
248: // append the location name to the parameter path
249: final ParameterPathBean locationPath = new ParameterPathBean(
250: parameter.getPath().getValue() + "/"
251: + location.getName(), parameter.getScope());
252: return new ObjectParameter<QueryRootNode>(
253: new ParameterDataBean<QueryRootNode>(locationPath, null),
254: QueryRootNode.class, false);
255: }
256:
257: }
|