001
014
015 package com.liferay.portal.search.buffer;
016
017 import com.liferay.portal.NoSuchModelException;
018 import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.search.Indexer;
022 import com.liferay.portal.kernel.search.SearchEngineUtil;
023 import com.liferay.portal.kernel.util.MethodKey;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.model.BaseModel;
026 import com.liferay.portal.model.ClassedModel;
027 import com.liferay.portal.model.ResourcedModel;
028 import com.liferay.portal.security.auth.CompanyThreadLocal;
029 import com.liferay.portal.service.PersistedModelLocalService;
030 import com.liferay.portal.service.PersistedModelLocalServiceRegistry;
031 import com.liferay.portal.util.PropsValues;
032
033 import java.lang.reflect.InvocationHandler;
034 import java.lang.reflect.Method;
035
036 import java.util.Arrays;
037 import java.util.Collection;
038
039
042 public class BufferedIndexerInvocationHandler implements InvocationHandler {
043
044 public BufferedIndexerInvocationHandler(
045 Indexer indexer,
046 PersistedModelLocalServiceRegistry persistedModelLocalServiceRegistry) {
047
048 _indexer = indexer;
049 _persistedModelLocalServiceRegistry =
050 persistedModelLocalServiceRegistry;
051 }
052
053 @Override
054 public Object invoke(Object proxy, Method method, Object[] args)
055 throws Throwable {
056
057 IndexerRequestBuffer indexerRequestBuffer = IndexerRequestBuffer.get();
058
059 if ((!Validator.equals(method.getName(), "delete") &&
060 !Validator.equals(method.getName(), "reindex")) ||
061 (args.length == 0) || (args.length > 2) ||
062 (indexerRequestBuffer == null)) {
063
064 return method.invoke(_indexer, args);
065 }
066
067 if (SearchEngineUtil.isIndexReadOnly()) {
068 if (_log.isDebugEnabled()) {
069 _log.debug(
070 "Skipping indexer request buffer because index is read " +
071 "only");
072 }
073
074 return null;
075 }
076
077 if (ExportImportThreadLocal.isImportInProcess() &&
078 Validator.equals(method.getName(), "reindex")) {
079
080 if (_log.isDebugEnabled()) {
081 _log.debug(
082 "Skipping indexer request buffer because import is in " +
083 "process");
084 }
085
086 return null;
087 }
088
089 if (CompanyThreadLocal.isDeleteInProcess()) {
090 if (_log.isDebugEnabled()) {
091 _log.debug(
092 "Skipping indexer request buffer because a company " +
093 "delete is in process");
094 }
095
096 return null;
097 }
098
099 Class<?> args0Class = args[0].getClass();
100
101 if (!(args[0] instanceof BaseModel) &&
102 !(args[0] instanceof ClassedModel) &&
103 !((args[0] instanceof Long) && (args.length == 1)) &&
104 !(args[0] instanceof long[]) &&
105 !(args0Class.isArray() ||
106 Collection.class.isAssignableFrom(args0Class)) &&
107 !((args.length == 2) && (args[0] instanceof String) &&
108 Validator.equals(args[1].getClass(), Long.class))) {
109
110 return method.invoke(_indexer, args);
111 }
112
113 if (args[0] instanceof ResourcedModel &&
114 args[0] instanceof ClassedModel &&
115 Validator.equals(method.getName(), "reindex")) {
116
117 MethodKey methodKey = new MethodKey(
118 Indexer.class, method.getName(), String.class, Long.TYPE);
119
120 ClassedModel classedModel = (ClassedModel)args[0];
121 ResourcedModel resourcedModel = (ResourcedModel)args[0];
122
123 bufferRequest(
124 methodKey, classedModel.getModelClassName(),
125 resourcedModel.getResourcePrimKey(), indexerRequestBuffer);
126 }
127 else if (args[0] instanceof ClassedModel) {
128 MethodKey methodKey = new MethodKey(
129 Indexer.class, method.getName(), Object.class);
130
131 bufferRequest(methodKey, args[0], indexerRequestBuffer);
132 }
133 else if (args.length == 2) {
134 MethodKey methodKey = new MethodKey(
135 Indexer.class, method.getName(), String.class, Long.TYPE);
136
137 String className = (String)args[0];
138 Long classPK = (Long)args[1];
139
140 PersistedModelLocalService persistedModelLocalService =
141 _persistedModelLocalServiceRegistry.
142 getPersistedModelLocalService(className);
143
144 try {
145 Object obj = persistedModelLocalService.getPersistedModel(
146 classPK);
147
148 if (obj instanceof ResourcedModel) {
149 ResourcedModel resourcedModel = (ResourcedModel)obj;
150
151 classPK = resourcedModel.getResourcePrimKey();
152 }
153 }
154 catch (Exception e) {
155 if (_log.isDebugEnabled()) {
156 _log.debug(
157 "Unable to get resource primary key for class " +
158 className + " with primary key " + classPK);
159
160 if (!(e instanceof NoSuchModelException)) {
161 _log.debug(e, e);
162 }
163 }
164 }
165
166 bufferRequest(methodKey, className, classPK, indexerRequestBuffer);
167 }
168 else if (args[0] instanceof Long) {
169 MethodKey methodKey = new MethodKey(
170 Indexer.class, method.getName(), String.class, Long.TYPE);
171
172 String className = _indexer.getClassNames()[0];
173 Long classPK = (Long)args[0];
174
175 bufferRequest(methodKey, className, classPK, indexerRequestBuffer);
176 }
177 else if (args[0] instanceof long[]) {
178 MethodKey methodKey = new MethodKey(
179 Indexer.class, method.getName(), String.class, Long.TYPE);
180
181 long[] primaryKeyArray = (long[])args[0];
182
183 for (int i = 0; i<primaryKeyArray.length; i++) {
184 String className = _indexer.getClassNames()[0];
185 Long classPK = (Long)primaryKeyArray[i];
186
187 bufferRequest(
188 methodKey, className, classPK, indexerRequestBuffer);
189 }
190 }
191 else {
192 MethodKey methodKey = new MethodKey(
193 Indexer.class, method.getName(), Object.class);
194
195 Collection<Object> objects;
196
197 try {
198 if (args0Class.isArray()) {
199 objects = Arrays.asList((Object[])args[0]);
200 }
201 else {
202 objects = (Collection<Object>)args[0];
203 }
204
205 for (Object object : objects) {
206 if (!(object instanceof ClassedModel)) {
207 objects = null;
208
209 break;
210 }
211 }
212 }
213 catch (Exception e) {
214 if (_log.isDebugEnabled()) {
215 if (_log.isDebugEnabled()) {
216 _log.debug(
217 "Unexpected error buffering indexing request", e);
218 }
219 }
220
221 objects = null;
222 }
223
224 if (objects == null) {
225 return method.invoke(_indexer, args);
226 }
227
228 for (Object object : objects) {
229 bufferRequest(methodKey, object, indexerRequestBuffer);
230 }
231 }
232
233 return null;
234 }
235
236 protected void bufferRequest(
237 MethodKey methodKey, Object object,
238 IndexerRequestBuffer indexerRequestBuffer)
239 throws Exception {
240
241 BaseModel<?> baseModel = (BaseModel<?>)object;
242
243 ClassedModel classedModel = (ClassedModel)baseModel.clone();
244
245 IndexerRequest indexerRequest = new IndexerRequest(
246 methodKey.getMethod(), classedModel, _indexer);
247
248 doBufferRequest(indexerRequest, indexerRequestBuffer);
249 }
250
251 protected void bufferRequest(
252 MethodKey methodKey, String className, Long classPK,
253 IndexerRequestBuffer indexerRequestBuffer)
254 throws Exception {
255
256 IndexerRequest indexerRequest = new IndexerRequest(
257 methodKey.getMethod(), _indexer, className, classPK);
258
259 doBufferRequest(indexerRequest, indexerRequestBuffer);
260 }
261
262 protected void doBufferRequest(
263 IndexerRequest indexerRequest,
264 IndexerRequestBuffer indexerRequestBuffer)
265 throws Exception {
266
267 if (BufferOverflowThreadLocal.isOverflowMode()) {
268 indexerRequest.execute();
269
270 return;
271 }
272
273 indexerRequestBuffer.add(indexerRequest);
274
275 if (indexerRequestBuffer.size() >
276 PropsValues.INDEX_REQUEST_BUFFER_MAX_SIZE) {
277
278 IndexerRequestBufferUtil.bufferOverflowed(
279 indexerRequestBuffer,
280 PropsValues.INDEX_REQUEST_BUFFER_MAX_SIZE);
281 }
282 }
283
284 private static Log _log = LogFactoryUtil.getLog(
285 BufferedIndexerInvocationHandler.class);
286
287 private final Indexer _indexer;
288 private final PersistedModelLocalServiceRegistry
289 _persistedModelLocalServiceRegistry;
290
291 }