org.kimios.kernel.index.IndexManager.java Source code

Java tutorial

Introduction

Here is the source code for org.kimios.kernel.index.IndexManager.java

Source

/*
 * Kimios - Document Management System Software
 * Copyright (C) 2012-2013  DevLib'
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.kimios.kernel.index;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Vector;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.kimios.exceptions.ConfigException;
import org.kimios.kernel.configuration.Config;
import org.kimios.kernel.dms.DMEntity;
import org.kimios.kernel.dms.DMEntityType;
import org.kimios.kernel.dms.Document;
import org.kimios.kernel.dms.DocumentVersion;
import org.kimios.kernel.dms.FactoryInstantiator;
import org.kimios.kernel.dms.MetaType;
import org.kimios.kernel.dms.MetaValue;
import org.kimios.kernel.exception.DataSourceException;
import org.kimios.kernel.exception.IndexException;
import org.kimios.kernel.hibernate.HFactory;
import org.kimios.kernel.security.DMEntityACL;
import org.kimios.utils.configuration.ConfigurationManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Deprecated
public class IndexManager implements LuceneIndexManager {
    private static Logger log = LoggerFactory.getLogger(IndexManager.class);

    private static IndexManager instance = null;

    private IndexWriter indexModifier;

    private Directory indexDirectory;

    private Thread reindexThread = null;

    private int reindexProgression = -1;

    private IndexManager() throws ConfigException, IndexException {
        try {
            File lock = new File(ConfigurationManager.getValue(Config.DEFAULT_INDEX_PATH) + "/write.lock");
            if (lock.exists()) {
                lock.delete();
            }

            File indexDir = new File(ConfigurationManager.getValue(Config.DEFAULT_INDEX_PATH));
            boolean create = indexDir.exists();
            this.indexDirectory = FSDirectory.open(indexDir);
            indexModifier = new IndexWriter(this.indexDirectory, IndexHelper.getAnalyzer(), !create,
                    MaxFieldLength.UNLIMITED);

            /*
            *
            *  Enable lucene debug
            *
            */
            if (log.isDebugEnabled()) {
                indexModifier.setInfoStream(System.out);
            }
        } catch (IOException io) {
            throw new IndexException(io, io.getMessage());
        }
    }

    public static synchronized IndexManager getInstance() throws ConfigException, IndexException {
        if (instance == null) {
            instance = new IndexManager();
        }
        return instance;
    }

    public void reindex(String path) throws DataSourceException, ConfigException, IndexException {
        final String finalPath = path;
        if (this.reindexThread == null || !this.reindexThread.isAlive()) {
            this.reindexThread = new Thread(new Runnable() {
                public void run() {
                    try {
                        reindexProgression = 0;
                        int indexed = 0;
                        close();

                        /*
                        *  Init Auto commit hibernate Session
                        *
                        */
                        HFactory.setAutoCommit(true);
                        File indexDir = new File(ConfigurationManager.getValue(Config.DEFAULT_INDEX_PATH));
                        deleteDirectory(indexDir);
                        Directory d = FSDirectory.open(indexDir);
                        indexModifier = new IndexWriter(d, IndexHelper.getAnalyzer(), MaxFieldLength.UNLIMITED);
                        indexModifier.setMaxBufferedDocs(100);
                        indexModifier.setRAMBufferSizeMB(32);
                        List<DMEntity> entities = FactoryInstantiator.getInstance().getDmEntityFactory()
                                .getEntitiesByPathAndType(finalPath, DMEntityType.DOCUMENT);
                        int total = entities.size();
                        log.debug("Entities to index: " + total);
                        for (int i = 0; i < entities.size(); i++) {
                            try {
                                if (entities.get(i).getClass().equals(Document.class)) {
                                    log.info(reindexProgression + "% - Indexing " + entities.get(i).getPath());
                                    indexDocument((Document) entities.get(i));
                                    indexed++;
                                }
                                reindexProgression = (int) Math.round((double) indexed / (double) total * 100);
                            } catch (Throwable ex) {
                                log.error("Exception on " + entities.get(i).getPath() + " during reindex", ex);
                            }
                        }
                        reindexProgression = -1;
                    } catch (Exception ex) {
                        log.error("Exception during reindex! Process stopped", ex);
                    }
                }
            });
            this.reindexThread.setName("ReindexThread");
            this.reindexThread.start();
        } else {
            throw new IndexException(null, "A reindex process is already running.");
        }
    }

    public int getReindexProgression() {
        return this.reindexProgression;
    }

    public boolean deleteDirectory(File path) {
        if (path.exists()) {
            File[] files = path.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    deleteDirectory(files[i]);
                } else {
                    files[i].delete();
                }
            }
        }
        return (path.delete());
    }

    public void deleteDocument(Document document) throws IndexException {
        try {
            this.indexModifier.deleteDocuments(new DocumentUidClause(document.getUid()).getLuceneQuery());
            commit();
            log.debug("Commited deletion of document " + document.getUid());
        } catch (IOException e) {
            throw new IndexException(e,
                    "An exception occured while deleting document " + document.getUid() + " : " + e.getMessage());
        }
    }

    public void indexDocument(DMEntity documentEntity) throws IndexException, DataSourceException, ConfigException {
        try {
            Document document = (Document) documentEntity;
            this.deleteDocument(document);
            org.apache.lucene.document.Document doc = new org.apache.lucene.document.Document();
            doc.add(IndexHelper.getUnanalyzedField("DocumentUid", document.getUid()));
            doc.add(IndexHelper.getUnanalyzedField("DocumentName", document.getName().toLowerCase()));
            doc.add(IndexHelper.getAnalyzedField("DocumentNameAnalysed", document.getName()));
            if (document.getExtension() != null) {
                doc.add(IndexHelper.getUnanalyzedField("DocumentExtension", document.getExtension().toLowerCase()));
            }
            doc.add(IndexHelper.getUnanalyzedField("DocumentOwner",
                    document.getOwner() + "@" + document.getOwnerSource()));
            doc.add(IndexHelper.getUnanalyzedField("DocumentParent", document.getFolder().getPath() + "/"));
            DocumentVersion version = FactoryInstantiator.getInstance().getDocumentVersionFactory()
                    .getLastDocumentVersion(document);

            //standard datas
            doc.add(IndexHelper.getUnanalyzedField("DocumentCreationDate", document.getCreationDate()));
            doc.add(IndexHelper.getUnanalyzedField("DocumentUpdateDate", document.getUpdateDate()));
            doc.add(IndexHelper.getUnanalyzedField("DocumentVersionUpdateDate", version.getModificationDate()));

            if (version.getDocumentType() != null) {
                doc.add(IndexHelper.getUnanalyzedField("DocumentTypeUid", version.getDocumentType().getUid()));
                List<MetaValue> values = FactoryInstantiator.getInstance().getMetaValueFactory()
                        .getMetaValues(version);
                for (MetaValue value : values) {
                    switch (value.getMeta().getMetaType()) {
                    case MetaType.STRING:
                        doc.add(IndexHelper.getUnanalyzedField("MetaData" + value.getMetaUid(),
                                ((String) value.getValue()).toLowerCase()));
                        break;
                    default:
                        doc.add(IndexHelper.getUnanalyzedField("MetaData" + value.getMetaUid(), value.getValue()));
                        break;
                    }
                }
            }
            for (String attribute : document.getAttributes().keySet()) {
                doc.add(IndexHelper.getUnanalyzedField("Attribute_" + attribute.toUpperCase(),
                        document.getAttributes().get(attribute).getValue()));
            }
            Object body = null;
            try {
                IndexFilter filter = FiltersMapper.getInstance().getFiltersFor(document.getExtension());
                if (filter != null) {
                    body = filter.getBody(version.getInputStream());
                }
            } catch (Throwable ex) {
                log.debug("Error while getting body", ex);
            }
            if (body == null) {
                body = IndexHelper.EMPTY_STRING;
            }
            if (body instanceof String) {
                doc.add(IndexHelper.getAnalyzedNotStoredField("DocumentBody", (String) body));
            } else {
                doc.add(IndexHelper.getAnalyzedNotStoredFromReaderField("DocumentBody", (Reader) body));
            }

            List<DMEntityACL> acls = org.kimios.kernel.security.FactoryInstantiator.getInstance()
                    .getDMEntitySecurityFactory().getDMEntityACL(document);
            for (int i = 0; i < acls.size(); i++) {
                doc.add(IndexHelper.getUnanalyzedField("DocumentACL", acls.get(i).getRuleHash()));
            }
            this.indexModifier.addDocument(doc);
            commit();
        } catch (IOException io) {
            throw new IndexException(io, "An exception occured while indexing document " + documentEntity.getUid()
                    + " : " + io.getMessage());
        }
    }

    public void close() throws IndexException {
        try {
            commit();
            indexModifier.close();
        } catch (IOException io) {
            throw new IndexException(io, io.getMessage());
        }
    }

    /*
    * TODO: Review collector (create one collector for unique result...
    */

    public List<Integer> executeQuery(Query query) throws IndexException {
        IndexReader reader = this.getIndexReader();
        IndexSearcher searcher = new IndexSearcher(reader);
        try {
            final List<Integer> list = new Vector<Integer>();
            TopDocs topDoc = searcher.search(query, Integer.MAX_VALUE);
            for (ScoreDoc dc : topDoc.scoreDocs) {
                list.add(dc.doc);
            }
            return list;
        } catch (IOException io) {
            throw new IndexException(io, io.getMessage());
        } finally {

            try {
                if (searcher != null) {
                    searcher.close();
                }

                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                throw new IndexException(e, e.getMessage());
            }
        }
    }

    public void updateAcls(long docUid, List<DMEntityACL> acls) throws IndexException {
        IndexReader reader = null;
        try {
            reader = IndexReader.open(this.indexDirectory);
            log.trace("Updating ACL for document #" + docUid);
            Query q = new DocumentUidClause(docUid).getLuceneQuery();
            List<Integer> list = this.executeQuery(q);
            if (list.size() > 0) {
                org.apache.lucene.document.Document d = reader.document(list.get(0));
                this.indexModifier.deleteDocuments(q);
                d.removeFields("DocumentACL");

                for (int j = 0; j < acls.size(); j++) {
                    d.add(IndexHelper.getUnanalyzedField("DocumentACL", acls.get(j).getRuleHash()));
                }

                this.indexModifier.addDocument(d);
            }
        } catch (Exception e) {
            throw new IndexException(e, e.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                throw new IndexException(e, e.getMessage());
            }
        }
    }

    public void commit() throws IndexException {
        try {
            this.indexModifier.expungeDeletes(true);
            this.indexModifier.commit();
        } catch (Exception e) {
            throw new IndexException(e, e.getMessage());
        }
    }

    public void deletePath(String path) throws IndexException {
        IndexReader reader = null;
        try {

            log.debug("Path delete: " + path);
            if (path.endsWith("/")) {
                path = path.substring(0, path.lastIndexOf("/"));
            }
            reader = IndexReader.open(this.indexDirectory);
            Query q = new DocumentParentClause(path).getLuceneQuery();
            this.indexModifier.deleteDocuments(q);
            reader.close();
            commit();
        } catch (Exception ex) {
            throw new IndexException(ex, ex.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                throw new IndexException(e, "Error while closing reader");
            }
        }
    }

    public void updatePath(String oldPath, String newPath) throws IndexException {
        IndexReader reader = null;
        try {
            if (oldPath.endsWith("/")) {
                oldPath = oldPath.substring(0, oldPath.lastIndexOf("/"));
            }
            if (!newPath.endsWith("/")) {
                newPath += "/";
            }
            reader = IndexReader.open(this.indexDirectory);
            Query q = new DocumentParentClause(oldPath).getLuceneQuery();
            List<Integer> list = this.executeQuery(q);
            Vector<org.apache.lucene.document.Document> docs = new Vector<org.apache.lucene.document.Document>();
            for (int i = 0; i < list.size(); i++) {
                docs.add(reader.document(list.get(i)));
            }
            this.indexModifier.deleteDocuments(q);
            for (int i = 0; i < docs.size(); i++) {
                String path = docs.get(i).get("DocumentParent");
                path = newPath + path.substring(oldPath.length() + 1);
                docs.get(i).removeField("DocumentParent");
                docs.get(i).add(IndexHelper.getUnanalyzedField("DocumentParent", path));
                this.indexModifier.addDocument(docs.get(i));
            }
            reader.close();
            commit();
        } catch (Exception ex) {
            throw new IndexException(ex, ex.getMessage());
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                throw new IndexException(e, "Error while closing reader");
            }
        }
    }

    public IndexReader getIndexReader() throws IndexException {
        try {
            return IndexReader.open(this.indexDirectory);
        } catch (IOException io) {
            throw new IndexException(io, io.getMessage());
        }
    }
}