View Javadoc

1   /*
2    * ModeShape (http://www.modeshape.org)
3    * See the COPYRIGHT.txt file distributed with this work for information
4    * regarding copyright ownership.  Some portions may be licensed
5    * to Red Hat, Inc. under one or more contributor license agreements.
6    * See the AUTHORS.txt file in the distribution for a full listing of 
7    * individual contributors.
8    *
9    * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
10   * is licensed to you under the terms of the GNU Lesser General Public License as
11   * published by the Free Software Foundation; either version 2.1 of
12   * the License, or (at your option) any later version.
13   * 
14   * ModeShape is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this software; if not, write to the Free
21   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23   */
24  package org.modeshape.search.lucene;
25  
26  import net.jcip.annotations.NotThreadSafe;
27  import org.apache.lucene.queryParser.ParseException;
28  import org.apache.lucene.search.Query;
29  import org.modeshape.common.util.Logger;
30  import org.modeshape.graph.ExecutionContext;
31  import org.modeshape.graph.Location;
32  import org.modeshape.graph.observe.Observer;
33  import org.modeshape.graph.property.DateTime;
34  import org.modeshape.graph.property.Path;
35  import org.modeshape.graph.query.QueryResults.Columns;
36  import org.modeshape.graph.query.QueryResults.Statistics;
37  import org.modeshape.graph.query.process.FullTextSearchResultColumns;
38  import org.modeshape.graph.request.CloneBranchRequest;
39  import org.modeshape.graph.request.CloneWorkspaceRequest;
40  import org.modeshape.graph.request.CopyBranchRequest;
41  import org.modeshape.graph.request.CreateNodeRequest;
42  import org.modeshape.graph.request.CreateWorkspaceRequest;
43  import org.modeshape.graph.request.DeleteBranchRequest;
44  import org.modeshape.graph.request.DestroyWorkspaceRequest;
45  import org.modeshape.graph.request.FullTextSearchRequest;
46  import org.modeshape.graph.request.GetWorkspacesRequest;
47  import org.modeshape.graph.request.LockBranchRequest;
48  import org.modeshape.graph.request.MoveBranchRequest;
49  import org.modeshape.graph.request.ReadAllChildrenRequest;
50  import org.modeshape.graph.request.ReadAllPropertiesRequest;
51  import org.modeshape.graph.request.UnlockBranchRequest;
52  import org.modeshape.graph.request.UpdatePropertiesRequest;
53  import org.modeshape.graph.request.VerifyWorkspaceRequest;
54  import org.modeshape.graph.search.AbstractSearchEngine.Workspaces;
55  import org.modeshape.graph.search.SearchEngineProcessor;
56  import org.modeshape.search.lucene.AbstractLuceneSearchEngine.AbstractLuceneProcessor;
57  
58  import java.io.FileNotFoundException;
59  import java.io.IOException;
60  import java.util.ArrayList;
61  import java.util.HashSet;
62  import java.util.List;
63  import java.util.Set;
64  
65  /**
66   * Abstract {@link SearchEngineProcessor} implementation for the {@link LuceneSearchEngine}.
67   */
68  @NotThreadSafe
69  public class LuceneSearchProcessor extends AbstractLuceneProcessor<LuceneSearchWorkspace, LuceneSearchSession> {
70  
71      protected static final Columns FULL_TEXT_RESULT_COLUMNS = new FullTextSearchResultColumns();
72      private static final Logger logger = Logger.getLogger(LuceneSearchProcessor.class);
73  
74      protected LuceneSearchProcessor( String sourceName,
75                                       ExecutionContext context,
76                                       Workspaces<LuceneSearchWorkspace> workspaces,
77                                       Observer observer,
78                                       DateTime now,
79                                       boolean readOnly ) {
80          super(sourceName, context, workspaces, observer, now, readOnly);
81      }
82  
83      /**
84       * {@inheritDoc}
85       * 
86       * @see org.modeshape.search.lucene.AbstractLuceneSearchEngine.AbstractLuceneProcessor#createSessionFor(org.modeshape.graph.search.SearchEngineWorkspace)
87       */
88      @Override
89      protected LuceneSearchSession createSessionFor( LuceneSearchWorkspace workspace ) {
90          return new LuceneSearchSession(workspace, this);
91      }
92  
93      /**
94       * {@inheritDoc}
95       * 
96       * @see org.modeshape.search.lucene.AbstractLuceneSearchEngine.AbstractLuceneProcessor#fullTextFieldName(java.lang.String)
97       */
98      @Override
99      protected String fullTextFieldName( String propertyName ) {
100         return propertyName == null ? LuceneSearchWorkspace.ContentIndex.FULL_TEXT : LuceneSearchWorkspace.FULL_TEXT_PREFIX
101                                                                                      + propertyName;
102     }
103 
104     /**
105      * {@inheritDoc}
106      * 
107      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.FullTextSearchRequest)
108      */
109     @Override
110     public void process( FullTextSearchRequest request ) {
111         LuceneSearchSession session = getSessionFor(request, request.workspace(), false);
112         if (session == null) return;
113         try {
114             List<Object[]> results = new ArrayList<Object[]>();
115             Statistics statistics = session.search(request.expression(), results, request.maxResults(), request.offset());
116             request.setResults(FULL_TEXT_RESULT_COLUMNS, results, statistics);
117         } catch (ParseException e) {
118             request.setError(e);
119         } catch (IOException e) {
120             request.setError(e);
121         }
122     }
123 
124     /**
125      * {@inheritDoc}
126      * 
127      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.VerifyWorkspaceRequest)
128      */
129     @Override
130     public void process( VerifyWorkspaceRequest request ) {
131         LuceneSearchSession session = getSessionFor(request, request.workspaceName(), true);
132         if (session == null) return;
133         request.setActualWorkspaceName(session.getWorkspaceName());
134         try {
135             request.setActualRootLocation(session.getLocationForRoot());
136         } catch (IOException e) {
137             request.setError(e);
138         }
139     }
140 
141     /**
142      * {@inheritDoc}
143      * 
144      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.GetWorkspacesRequest)
145      */
146     @Override
147     public void process( GetWorkspacesRequest request ) {
148         Set<String> names = new HashSet<String>();
149         for (LuceneSearchWorkspace workspace : workspaces.getWorkspaces()) {
150             names.add(workspace.getWorkspaceName());
151         }
152         request.setAvailableWorkspaceNames(names);
153     }
154 
155     /**
156      * {@inheritDoc}
157      * 
158      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.CreateNodeRequest)
159      */
160     @Override
161     public void process( CreateNodeRequest request ) {
162         // Get the session to the workspace ...
163         LuceneSearchSession session = getSessionFor(request, request.inWorkspace(), true);
164         if (session == null) return;
165 
166         // We make a big assumption here: the CreateNodeRequests created by the SearchEngineProcessor have the
167         // actual locations set ...
168         Location location = request.getActualLocationOfNode();
169         assert location != null;
170 
171         try {
172             session.setOrReplaceProperties(location, request.properties());
173             session.recordChange();
174         } catch (IOException e) {
175             request.setError(e);
176         }
177     }
178 
179     /**
180      * {@inheritDoc}
181      * 
182      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.UpdatePropertiesRequest)
183      */
184     @Override
185     public void process( UpdatePropertiesRequest request ) {
186         // Get the session to the workspace ...
187         LuceneSearchSession session = getSessionFor(request, request.inWorkspace(), true);
188         if (session == null) return;
189 
190         Location location = request.getActualLocationOfNode();
191         assert location != null;
192 
193         try {
194             // We make a big assumption here: the UpdatePropertiesRequest created by the SearchEngineProcessor have the
195             // actual locations set ...
196             session.setOrReplaceProperties(location, request.properties().values());
197             session.recordChange();
198         } catch (IOException e) {
199             request.setError(e);
200         }
201     }
202 
203     /**
204      * {@inheritDoc}
205      * 
206      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.DeleteBranchRequest)
207      */
208     @Override
209     public void process( DeleteBranchRequest request ) {
210         LuceneSearchSession session = getSessionFor(request, request.inWorkspace());
211         if (session == null) return;
212 
213         Path path = request.at().getPath();
214         assert !readOnly;
215         try {
216             // Create a query to find all the nodes at or below the specified path (this efficiently handles the root path) ...
217             if (logger.isTraceEnabled()) {
218                 logger.trace("index for \"{0}\" workspace: DEL '{1}' branch", request.inWorkspace(), stringFactory.create(path));
219             }
220             Query query = session.findAllNodesAtOrBelow(path);
221             // Now delete the documents from each index using this query, which we can reuse ...
222             session.getContentWriter().deleteDocuments(query);
223             session.recordChanges(100);
224         } catch (FileNotFoundException e) {
225             // There are no index files yet, so nothing to delete ...
226         } catch (IOException e) {
227             request.setError(e);
228         }
229     }
230 
231     /**
232      * {@inheritDoc}
233      * 
234      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.DestroyWorkspaceRequest)
235      */
236     @Override
237     public void process( DestroyWorkspaceRequest request ) {
238         LuceneSearchWorkspace workspace = getWorkspace(request, request.workspaceName(), false);
239         if (workspace == null) return;
240         try {
241             LuceneSearchSession session = getSessionFor(request, workspace.getWorkspaceName());
242             request.setActualRootLocation(session.getLocationForRoot());
243             workspace.destroy(getExecutionContext());
244             session.recordChanges(LuceneSearchWorkspace.CHANGES_BEFORE_OPTIMIZATION + 100);
245         } catch (IOException e) {
246             request.setError(e);
247         }
248     }
249 
250     /**
251      * {@inheritDoc}
252      * 
253      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.LockBranchRequest)
254      */
255     @Override
256     public void process( LockBranchRequest request ) {
257         request.setActualLocation(request.at());
258     }
259 
260     /**
261      * {@inheritDoc}
262      * 
263      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.UnlockBranchRequest)
264      */
265     @Override
266     public void process( UnlockBranchRequest request ) {
267         request.setActualLocation(request.at());
268     }
269 
270     /**
271      * {@inheritDoc}
272      * 
273      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.CloneBranchRequest)
274      */
275     @Override
276     public void process( CloneBranchRequest request ) {
277         super.processUnknownRequest(request);
278     }
279 
280     /**
281      * {@inheritDoc}
282      * 
283      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.CloneWorkspaceRequest)
284      */
285     @Override
286     public void process( CloneWorkspaceRequest request ) {
287         super.processUnknownRequest(request);
288     }
289 
290     /**
291      * {@inheritDoc}
292      * 
293      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.CopyBranchRequest)
294      */
295     @Override
296     public void process( CopyBranchRequest request ) {
297         super.processUnknownRequest(request);
298     }
299 
300     /**
301      * {@inheritDoc}
302      * 
303      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.CreateWorkspaceRequest)
304      */
305     @Override
306     public void process( CreateWorkspaceRequest request ) {
307         super.processUnknownRequest(request);
308     }
309 
310     /**
311      * {@inheritDoc}
312      * 
313      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.MoveBranchRequest)
314      */
315     @Override
316     public void process( MoveBranchRequest request ) {
317         super.processUnknownRequest(request);
318     }
319 
320     /**
321      * {@inheritDoc}
322      * 
323      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.ReadAllChildrenRequest)
324      */
325     @Override
326     public void process( ReadAllChildrenRequest request ) {
327         super.processUnknownRequest(request);
328     }
329 
330     /**
331      * {@inheritDoc}
332      * 
333      * @see org.modeshape.graph.request.processor.RequestProcessor#process(org.modeshape.graph.request.ReadAllPropertiesRequest)
334      */
335     @Override
336     public void process( ReadAllPropertiesRequest request ) {
337         super.processUnknownRequest(request);
338     }
339 }