jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mreut...@apache.org
Subject svn commit: r606180 - in /jackrabbit/trunk/jackrabbit-core/src: main/java/org/apache/jackrabbit/core/query/lucene/ test/java/org/apache/jackrabbit/core/query/ test/repository/workspaces/default/
Date Fri, 21 Dec 2007 12:50:29 GMT
Author: mreutegg
Date: Fri Dec 21 04:50:28 2007
New Revision: 606180

URL: http://svn.apache.org/viewvc?rev=606180&view=rev
Log:
JCR-1278: Add configuration path to SynonymProvider

Added:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java
  (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java
  (with props)
    jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties
  (with props)
Modified:
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
    jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SynonymProvider.java
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
    jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/workspace.xml

Added: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java?rev=606180&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java
Fri Dec 21 04:50:28 2007
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.jackrabbit.core.query.lucene;
+
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Iterator;
+
+/**
+ * Implements a synonym provider based on a properties file. Each line in the
+ * properties file is treated as a synonym definition. Example:
+ * <pre>
+ * A=B
+ * B=C
+ * </pre>
+ * This synonym provider will return B as a synonym for A and vice versa. The
+ * same applies to B and C. However A is not considered a synonym for C, nor
+ * C a synonym for A.
+ */
+public class PropertiesSynonymProvider implements SynonymProvider {
+
+    /**
+     * The logger instance for this class.
+     */
+    private static final Logger log = LoggerFactory.getLogger(PropertiesSynonymProvider.class);
+
+    /**
+     * An empty string array. Returned when no synonym is found.
+     */
+    private static final String[] EMPTY_ARRAY = new String[0];
+
+    /**
+     * Check at most every 10 seconds for configuration updates.
+     */
+    private static final long CHECK_INTERVAL = 10 * 1000;
+
+    /**
+     * The file system resource that contains the configuration.
+     */
+    private FileSystemResource config;
+
+    /**
+     * Timestamp when the configuration was checked last.
+     */
+    private long lastCheck;
+
+    /**
+     * Timestamp when the configuration was last modified.
+     */
+    private long configLastModified;
+
+    /**
+     * Contains the synonym mapping. Map&lt;String, String[]>
+     */
+    private Map synonyms = new HashMap();
+
+    /**
+     * {@inheritDoc}
+     */
+    public synchronized void initialize(FileSystemResource fsr)
+            throws IOException {
+        if (fsr == null) {
+            throw new IOException("PropertiesSynonymProvider requires a path configuration");
+        }
+        try {
+            config = fsr;
+            synonyms = getSynonyms(config);
+            configLastModified = config.lastModified();
+            lastCheck = System.currentTimeMillis();
+        } catch (FileSystemException e) {
+            IOException ex = new IOException();
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public String[] getSynonyms(String term) {
+        checkConfigUpdated();
+        term = term.toLowerCase();
+        String[] syns;
+        synchronized (this) {
+            syns = (String[]) synonyms.get(term);
+        }
+        if (syns == null) {
+            syns = EMPTY_ARRAY;
+        }
+        return syns;
+    }
+
+    //---------------------------------< internal >-----------------------------
+
+    /**
+     * Checks if the synonym properties file has been updated and this provider
+     * should reload the synonyms. This method performs the actual check at most
+     * every {@link #CHECK_INTERVAL}. If reloading fails an error is logged and
+     * this provider will retry after {@link #CHECK_INTERVAL}.
+     */
+    private synchronized void checkConfigUpdated() {
+        if (lastCheck + CHECK_INTERVAL > System.currentTimeMillis()) {
+            return;
+        }
+        // check last modified
+        try {
+            if (configLastModified != config.lastModified()) {
+                synonyms = getSynonyms(config);
+                configLastModified = config.lastModified();
+                log.info("Reloaded synonyms from {}", config.getPath());
+            }
+        } catch (Exception e) {
+            log.error("Exception while reading synonyms", e);
+        }
+        // update lastCheck timestamp, even if error occured (retry later)
+        lastCheck = System.currentTimeMillis();
+    }
+
+    /**
+     * Reads the synonym properties file and returns the contents as a synonym
+     * Map.
+     *
+     * @param config the synonym properties file.
+     * @return a Map containing the synonyms.
+     * @throws IOException if an error occurs while reading from the file system
+     *                     resource.
+     */
+    private static Map getSynonyms(FileSystemResource config) throws IOException {
+        try {
+            Map synonyms = new HashMap();
+            Properties props = new Properties();
+            props.load(config.getInputStream());
+            for (Iterator it = props.entrySet().iterator(); it.hasNext(); ) {
+                Map.Entry e = (Map.Entry) it.next();
+                String key = (String) e.getKey();
+                String value = (String) e.getValue();
+                addSynonym(key, value, synonyms);
+                addSynonym(value, key, synonyms);
+            }
+            return synonyms;
+        } catch (FileSystemException e) {
+            IOException ex = new IOException();
+            ex.initCause(e);
+            throw ex;
+        }
+    }
+
+    /**
+     * Adds a synonym definition to the map.
+     *
+     * @param term     the term
+     * @param synonym  synonym for <code>term</code>.
+     * @param synonyms the Map containing the synonyms.
+     */
+    private static void addSynonym(String term, String synonym, Map synonyms) {
+        term = term.toLowerCase();
+        String[] syns = (String[]) synonyms.get(term);
+        if (syns == null) {
+            syns = new String[]{synonym};
+        } else {
+            String[] tmp = new String[syns.length + 1];
+            System.arraycopy(syns, 0, tmp, 0, syns.length);
+            tmp[syns.length] = synonym;
+            syns = tmp;
+        }
+        synonyms.put(term, syns);
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/PropertiesSynonymProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java?rev=606180&r1=606179&r2=606180&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
Fri Dec 21 04:50:28 2007
@@ -20,6 +20,10 @@
 import org.apache.jackrabbit.core.SessionImpl;
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeIdIterator;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+import org.apache.jackrabbit.core.fs.FileSystemException;
+import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
 import org.apache.jackrabbit.core.query.AbstractQueryHandler;
 import org.apache.jackrabbit.core.query.DefaultQueryNodeFactory;
 import org.apache.jackrabbit.core.query.ExecutableQuery;
@@ -326,6 +330,17 @@
     private SynonymProvider synProvider;
 
     /**
+     * The configuration path for the synonym provider.
+     */
+    private String synonymProviderConfigPath;
+
+    /**
+     * The FileSystem for the synonym if the query handler context does not
+     * provide one.
+     */
+    private FileSystem synonymProviderConfigFs;
+
+    /**
      * Indicates the index format version which is relevant to a <b>query</b>.
This
      * value may be different from what {@link MultiIndex#getIndexFormatVersion()}
      * returns because queries may be executed on two physical indexes with
@@ -598,6 +613,13 @@
      * to this handler.
      */
     public void close() {
+        if (synonymProviderConfigFs != null) {
+            try {
+                synonymProviderConfigFs.close();
+            } catch (FileSystemException e) {
+                log.warn("Exception while closing FileSystem", e);
+            }
+        }
         // shutdown extractor
         if (extractor instanceof PooledTextExtractor) {
             ((PooledTextExtractor) extractor).shutdown();
@@ -897,6 +919,7 @@
         if (synonymProviderClass != null) {
             try {
                 sp = (SynonymProvider) synonymProviderClass.newInstance();
+                sp.initialize(createSynonymProviderConfigResource());
             } catch (Exception e) {
                 log.warn("Exception initializing synonym provider: " +
                         synonymProviderClass, e);
@@ -906,6 +929,52 @@
     }
 
     /**
+     * Creates a file system resource to the synonym provider configuration.
+     *
+     * @return a file system resource or <code>null</code> if no path was
+     *         configured.
+     * @throws FileSystemException if an exception occurs accessing the file
+     *                             system.
+     */
+    protected FileSystemResource createSynonymProviderConfigResource()
+            throws FileSystemException {
+        if (synonymProviderConfigPath != null) {
+            FileSystemResource fsr;
+            // simple sanity check
+            if (synonymProviderConfigPath.endsWith(FileSystem.SEPARATOR)) {
+                throw new FileSystemException(
+                        "Invalid synonymProviderConfigPath: " +
+                        synonymProviderConfigPath);
+            }
+            FileSystem fs = getContext().getFileSystem();
+            if (fs == null) {
+                fs = new LocalFileSystem();
+                int lastSeparator = synonymProviderConfigPath.lastIndexOf(
+                        FileSystem.SEPARATOR_CHAR);
+                if (lastSeparator != -1) {
+                    File root = new File(path,
+                            synonymProviderConfigPath.substring(0, lastSeparator));
+                    ((LocalFileSystem) fs).setRoot(root);
+                    fs.init();
+                    fsr = new FileSystemResource(fs,
+                            synonymProviderConfigPath.substring(lastSeparator + 1));
+                } else {
+                    ((LocalFileSystem) fs).setPath(path);
+                    fs.init();
+                    fsr = new FileSystemResource(fs, synonymProviderConfigPath);
+                }
+                synonymProviderConfigFs = fs;
+            } else {
+                fsr = new FileSystemResource(fs, synonymProviderConfigPath);
+            }
+            return fsr;
+        } else {
+            // path not configured
+            return null;
+        }
+    }
+
+    /**
      * Creates a spell checker for this query handler.
      *
      * @return the spell checker or <code>null</code> if none is configured or
@@ -1683,6 +1752,23 @@
      */
     public boolean getEnableConsistencyCheck() {
         return consistencyCheckEnabled;
+    }
+
+    /**
+     * Sets the configuration path for the synonym provider.
+     *
+     * @param path the configuration path for the synonym provider.
+     */
+    public void setSynonymProviderConfigPath(String path) {
+        synonymProviderConfigPath = path;
+    }
+
+    /**
+     * @return the configuration path for the synonym provider. If none is set
+     *         this method returns <code>null</code>.
+     */
+    public String getSynonymProviderConfigPath() {
+        return synonymProviderConfigPath;
     }
 
     //----------------------------< internal >----------------------------------

Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SynonymProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SynonymProvider.java?rev=606180&r1=606179&r2=606180&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SynonymProvider.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SynonymProvider.java
Fri Dec 21 04:50:28 2007
@@ -16,11 +16,28 @@
  */
 package org.apache.jackrabbit.core.query.lucene;
 
+import org.apache.jackrabbit.core.fs.FileSystemResource;
+
+import java.io.IOException;
+
 /**
  * <code>SynonymProvider</code> defines an interface for a component that
  * returns synonyms for a given term.
  */
 public interface SynonymProvider {
+
+    /**
+     * Initializes the synonym provider and passes the file system resource to
+     * the synonym provider configuration defined by the configuration value of
+     * the <code>synonymProviderConfigPath</code> parameter. The resource may
be
+     * <code>null</code> if the configuration parameter is not set.
+     *
+     * @param fsr the file system resource to the synonym provider
+     *            configuration.
+     * @throws IOException if an error occurs while initializing the synonym
+     *                     provider.
+     */
+    public void initialize(FileSystemResource fsr) throws IOException;
 
     /**
      * Returns an array of terms that are considered synonyms for the given

Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java?rev=606180&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java
Fri Dec 21 04:50:28 2007
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF 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 org.apache.jackrabbit.core.query;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Node;
+
+/**
+ * <code>SynonymProviderTest</code> contains test cases for the
+ * <code>PropertiesSynonymProvider</code> class.
+ * This test assumes that the following synonyms are defined:
+ * <ul>
+ * <li>quick &lt;-> fast</li>
+ * <li>sluggish &lt;-> lazy</li>
+ * <li>ASF &lt;-> Apache Software Foundation</li>
+ * </ul>
+ */
+public class SynonymProviderTest extends AbstractQueryTest {
+
+    public void testSynonyms() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1);
+        n.setProperty(propertyName1, "The quick brown fox jumps over the lazy dog.");
+        testRootNode.save();
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~fast')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~Fast')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~quick')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~sluggish')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~sluGGish')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~lazy')]", new Node[]{n});
+        // check term which is not in the synonym provider
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~brown')]", new Node[]{n});
+    }
+
+    public void testPhrase() throws RepositoryException {
+        Node n = testRootNode.addNode(nodeName1);
+        n.setProperty(propertyName1, "Licensed to the Apache Software Foundation ...");
+        testRootNode.save();
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~ASF')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., '~asf')]", new Node[]{n});
+        executeXPathQuery(testPath + "//*[jcr:contains(., 'asf')]", new Node[]{});
+    }
+
+    public void disabled_testReload() throws RepositoryException, InterruptedException {
+        for (int i = 0; i < 60; i++) {
+            Thread.sleep(1 * 1000);
+            executeXPathQuery(testPath + "//*[jcr:contains(., '~asf')]", new Node[]{});
+        }
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/SynonymProviderTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java?rev=606180&r1=606179&r2=606180&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/TestAll.java
Fri Dec 21 04:50:28 2007
@@ -50,6 +50,7 @@
         suite.addTestSuite(QueryResultTest.class);
         suite.addTestSuite(FnNameQueryTest.class);
         suite.addTestSuite(PathQueryNodeTest.class);
+        suite.addTestSuite(SynonymProviderTest.class);
 
         // exclude long running tests per default
         //suite.addTestSuite(MassiveRangeTest.class);

Added: jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties?rev=606180&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties
(added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties
Fri Dec 21 04:50:28 2007
@@ -0,0 +1,4 @@
+# this is a synonym definition file for PropertiesSynonymProvider
+ASF=Apache Software Foundation
+quick=fast
+sluggish=lazy
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/synonyms.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/workspace.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/workspace.xml?rev=606180&r1=606179&r2=606180&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/workspace.xml
(original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/repository/workspaces/default/workspace.xml
Fri Dec 21 04:50:28 2007
@@ -36,6 +36,8 @@
   -->
   <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
     <param name="path" value="${wsp.home}/index" />
+    <param name="synonymProviderClass" value="org.apache.jackrabbit.core.query.lucene.PropertiesSynonymProvider"/>
+    <param name="synonymProviderConfigPath" value="../synonyms.properties"/>
   </SearchIndex>
 </Workspace>
 



Mime
View raw message