001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.search;
016    
017    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
018    import com.liferay.portal.kernel.lar.StagingIndexingDeletionThreadLocal;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.search.Document;
022    import com.liferay.portal.kernel.search.DocumentImpl;
023    import com.liferay.portal.kernel.search.Indexable;
024    import com.liferay.portal.kernel.search.IndexableType;
025    import com.liferay.portal.kernel.search.Indexer;
026    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
027    import com.liferay.portal.model.BaseModel;
028    import com.liferay.portal.model.StagedModel;
029    import com.liferay.portal.service.ServiceContext;
030    import com.liferay.portal.spring.aop.AnnotationChainableMethodAdvice;
031    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
032    import com.liferay.portlet.documentlibrary.util.DLFileEntryIndexer;
033    
034    import java.lang.annotation.Annotation;
035    import java.lang.reflect.Method;
036    
037    import org.aopalliance.intercept.MethodInvocation;
038    
039    /**
040     * @author Shuyang Zhou
041     */
042    public class IndexableAdvice
043            extends AnnotationChainableMethodAdvice<Indexable> {
044    
045            @Override
046            public void afterReturning(MethodInvocation methodInvocation, Object result)
047                    throws Throwable {
048    
049                    if (result == null) {
050                            return;
051                    }
052    
053                    Indexable indexable = findAnnotation(methodInvocation);
054    
055                    if (indexable == _nullIndexable) {
056                            return;
057                    }
058    
059                    Method method = methodInvocation.getMethod();
060    
061                    Class<?> returnType = method.getReturnType();
062    
063                    if (!BaseModel.class.isAssignableFrom(returnType)) {
064                            if (_log.isWarnEnabled()) {
065                                    _log.warn(
066                                            methodInvocation + " does not have a valid return type");
067                            }
068    
069                            return;
070                    }
071    
072                    Indexer indexer = null;
073    
074                    if (StagedModel.class.isAssignableFrom(returnType) &&
075                            ExportImportThreadLocal.isImportInProcess()) {
076    
077                            if (indexable.type() == IndexableType.DELETE) {
078                                    try {
079                                            indexer = IndexerRegistryUtil.getIndexer(
080                                                    returnType.getName());
081    
082                                            String className = indexer.getClass().getName();
083    
084                                            Document document = null;
085    
086                                            if (className.equals(DLFileEntryIndexer.class.getName())) {
087                                                    DLFileEntry dlFileEntry = (DLFileEntry)result;
088    
089                                                    document = new DocumentImpl();
090    
091                                                    document.addUID(
092                                                            DLFileEntryIndexer.PORTLET_ID,
093                                                            dlFileEntry.getFileEntryId());
094                                            }
095                                            else {
096                                                    document = indexer.getDocument(result);
097                                            }
098    
099                                            StagingIndexingDeletionThreadLocal.setDeletionKey(
100                                                    className, document.getUID());
101                                    }
102                                    catch (Exception e) {
103                                    }
104                            }
105    
106                            if (_log.isDebugEnabled()) {
107                                    _log.debug("Skipping indexing until the import is finished");
108                            }
109    
110                            return;
111                    }
112    
113                    if (indexer == null) {
114                            indexer = IndexerRegistryUtil.getIndexer(returnType.getName());
115                    }
116    
117                    if (indexer == null) {
118                            serviceBeanAopCacheManager.removeMethodInterceptor(
119                                    methodInvocation, this);
120    
121                            return;
122                    }
123    
124                    Object[] arguments = methodInvocation.getArguments();
125    
126                    for (int i = arguments.length - 1; i >= 0; i--) {
127                            if (arguments[i] instanceof ServiceContext) {
128                                    ServiceContext serviceContext = (ServiceContext)arguments[i];
129    
130                                    if (serviceContext.isIndexingEnabled()) {
131                                            break;
132                                    }
133    
134                                    return;
135                            }
136                    }
137    
138                    if (indexable.type() == IndexableType.DELETE) {
139                            indexer.delete(result);
140                    }
141                    else {
142                            indexer.reindex(result);
143                    }
144            }
145    
146            @Override
147            public Indexable getNullAnnotation() {
148                    return _nullIndexable;
149            }
150    
151            private static Log _log = LogFactoryUtil.getLog(IndexableAdvice.class);
152    
153            private static Indexable _nullIndexable =
154                    new Indexable() {
155    
156                            @Override
157                            public Class<? extends Annotation> annotationType() {
158                                    return Indexable.class;
159                            }
160    
161                            @Override
162                            public IndexableType type() {
163                                    return null;
164                            }
165    
166                    };
167    
168    }