This project has retired. For details please refer to its
Attic page.
InMemoryServiceFactoryImpl xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.inmemory.server;
20
21 import java.io.File;
22 import java.io.InputStream;
23 import java.math.BigInteger;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Date;
27 import java.util.LinkedHashMap;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.concurrent.Executors;
32 import java.util.concurrent.ScheduledExecutorService;
33 import java.util.concurrent.ScheduledFuture;
34 import java.util.concurrent.TimeUnit;
35
36 import javax.xml.bind.JAXBElement;
37 import javax.xml.bind.Unmarshaller;
38
39 import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
40 import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
41 import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
42 import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
43 import org.apache.chemistry.opencmis.commons.impl.Converter;
44 import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractTypeDefinition;
45 import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl;
46 import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisTypeDefinitionType;
47 import org.apache.chemistry.opencmis.commons.impl.server.AbstractServiceFactory;
48 import org.apache.chemistry.opencmis.commons.server.CallContext;
49 import org.apache.chemistry.opencmis.commons.server.CmisService;
50 import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
51 import org.apache.chemistry.opencmis.inmemory.ConfigConstants;
52 import org.apache.chemistry.opencmis.inmemory.ConfigurationSettings;
53 import org.apache.chemistry.opencmis.inmemory.storedobj.api.ObjectStore;
54 import org.apache.chemistry.opencmis.inmemory.storedobj.api.StoreManager;
55 import org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable;
56 import org.apache.chemistry.opencmis.inmemory.storedobj.impl.StoreManagerFactory;
57 import org.apache.chemistry.opencmis.inmemory.storedobj.impl.StoreManagerImpl;
58 import org.apache.chemistry.opencmis.inmemory.types.InMemoryJaxbHelper;
59 import org.apache.chemistry.opencmis.inmemory.types.TypeDefinitions;
60 import org.apache.chemistry.opencmis.server.support.CmisServiceWrapper;
61 import org.apache.chemistry.opencmis.server.support.TypeManager;
62 import org.apache.chemistry.opencmis.util.repository.ObjectGenerator;
63 import org.apache.commons.logging.Log;
64 import org.apache.commons.logging.LogFactory;
65
66 public class InMemoryServiceFactoryImpl extends AbstractServiceFactory {
67
68 private static final Log LOG = LogFactory.getLog(InMemoryServiceFactoryImpl.class.getName());
69 private static final BigInteger DEFAULT_MAX_ITEMS_OBJECTS = BigInteger.valueOf(1000);
70 private static final BigInteger DEFAULT_MAX_ITEMS_TYPES = BigInteger.valueOf(100);
71 private static final BigInteger DEFAULT_DEPTH_OBJECTS = BigInteger.valueOf(2);
72 private static final BigInteger DEFAULT_DEPTH_TYPES = BigInteger.valueOf(-1);
73 private static CallContext OVERRIDE_CTX;
74
75 private Map<String, String> inMemoryServiceParameters;
76 private ThreadLocal<CmisServiceWrapper<InMemoryService>> threadLocalService = new ThreadLocal<CmisServiceWrapper<InMemoryService>>();
77 private boolean fUseOverrideCtx = false;
78 private StoreManager storeManager;
79 private CleanManager cleanManager = null;
80
81 private File tempDir;
82 private int memoryThreshold;
83
84
85 @Override
86 public void init(Map<String, String> parameters) {
87 LOG.info("Initializing in-memory repository...");
88
89 inMemoryServiceParameters = parameters;
90 String overrideCtx = parameters.get(ConfigConstants.OVERRIDE_CALL_CONTEXT);
91 if (null != overrideCtx) {
92 fUseOverrideCtx = true;
93 }
94
95 ConfigurationSettings.init(parameters);
96
97 String repositoryClassName = (String) parameters.get(ConfigConstants.REPOSITORY_CLASS);
98 if (null == repositoryClassName) {
99 repositoryClassName = StoreManagerImpl.class.getName();
100 }
101
102 if (null == storeManager) {
103 storeManager = StoreManagerFactory.createInstance(repositoryClassName);
104 }
105
106 String tempDirStr = parameters.get(ConfigConstants.TEMP_DIR);
107 tempDir = (tempDirStr == null ? super.getTempDirectory() : new File(tempDirStr));
108
109 String memoryThresholdStr = parameters.get(ConfigConstants.MEMORY_THRESHOLD);
110 memoryThreshold = (memoryThresholdStr == null ? super.getMemoryThreshold(): Integer.parseInt(memoryThresholdStr));
111
112 Date deploymentTime = new Date();
113 String strDate = new SimpleDateFormat("EEE MMM dd hh:mm:ss a z yyyy", Locale.US).format(deploymentTime);
114
115 parameters.put(ConfigConstants.DEPLOYMENT_TIME, strDate);
116
117 initStorageManager(parameters);
118
119 fillRepositoryIfConfigured(parameters);
120
121 Long cleanInterval = ConfigurationSettings
122 .getConfigurationValueAsLong(ConfigConstants.CLEAN_REPOSITORY_INTERVAL);
123 if (null != cleanInterval && cleanInterval > 0) {
124 scheduleCleanRepositoryJob(cleanInterval);
125 }
126
127 LOG.info("...initialized in-memory repository.");
128 }
129
130 public static void setOverrideCallContext(CallContext ctx) {
131 OVERRIDE_CTX = ctx;
132 }
133
134 @Override
135 public CmisService getService(CallContext context) {
136 LOG.debug("start getService()");
137
138
139
140
141
142 if (fUseOverrideCtx && null != OVERRIDE_CTX) {
143 context = OVERRIDE_CTX;
144 }
145
146 CmisServiceWrapper<InMemoryService> wrapperService = threadLocalService.get();
147 if (wrapperService == null) {
148 wrapperService = new CmisServiceWrapper<InMemoryService>(new InMemoryService(inMemoryServiceParameters,
149 storeManager), DEFAULT_MAX_ITEMS_TYPES, DEFAULT_DEPTH_TYPES, DEFAULT_MAX_ITEMS_OBJECTS,
150 DEFAULT_DEPTH_OBJECTS);
151 threadLocalService.set(wrapperService);
152 }
153
154 wrapperService.getWrappedService().setCallContext(context);
155
156 LOG.debug("stop getService()");
157 return wrapperService.getWrappedService();
158 }
159
160 @Override
161 public File getTempDirectory() {
162 return tempDir;
163 }
164
165 @Override
166 public int getMemoryThreshold() {
167 return memoryThreshold;
168 }
169
170
171 @Override
172 public void destroy() {
173 if (null != cleanManager) {
174 cleanManager.stopCleanRepositoryJob();
175 }
176 threadLocalService = null;
177 }
178
179 public StoreManager getStoreManger() {
180 return storeManager;
181 }
182
183 private void initStorageManager(Map<String, String> parameters) {
184
185 String repositoryClassName = (String) parameters.get(ConfigConstants.REPOSITORY_CLASS);
186 if (null == repositoryClassName) {
187 repositoryClassName = StoreManagerImpl.class.getName();
188 }
189
190 if (null == storeManager) {
191 storeManager = StoreManagerFactory.createInstance(repositoryClassName);
192 }
193
194 String repositoryId = parameters.get(ConfigConstants.REPOSITORY_ID);
195
196 List<String> allAvailableRepositories = storeManager.getAllRepositoryIds();
197
198
199 for (String existingRepId : allAvailableRepositories) {
200 storeManager.initRepository(existingRepId);
201 }
202
203
204 if (null != repositoryId) {
205 if (allAvailableRepositories.contains(repositoryId)) {
206 LOG.warn("Repostory " + repositoryId + " already exists and will not be created.");
207 } else {
208 String typeCreatorClassName = parameters.get(ConfigConstants.TYPE_CREATOR_CLASS);
209 storeManager.createAndInitRepository(repositoryId, typeCreatorClassName);
210 }
211 }
212
213
214
215 String typeDefsFileName = parameters.get(ConfigConstants.TYPE_XML);
216 if (null == typeDefsFileName)
217 LOG.info("No file name for type definitions given, no types will be created.");
218 else {
219 TypeManager typeManager = storeManager.getTypeManager(repositoryId);
220 if (typeManager instanceof TypeManagerCreatable) {
221 TypeManagerCreatable tmc = (TypeManagerCreatable) typeManager;
222 importTypesFromFile(tmc, typeDefsFileName);
223 } else {
224 LOG.warn("Type Definitions are configured in XML file but type manager cannot create types. Type definitions are ignored.");
225 }
226 }
227
228 }
229
230 private void importTypesFromFile(TypeManagerCreatable tmc, String typeDefsFileName) {
231
232 InputStream is = this.getClass().getResourceAsStream("/" + typeDefsFileName);
233
234 if (null == is) {
235 LOG.warn("Resource file with type definitions " + typeDefsFileName
236 + " could not be found, no types will be created.");
237 return;
238 }
239
240 try {
241 TypeDefinition typeDef = null;
242 Unmarshaller u = InMemoryJaxbHelper.createUnmarshaller();
243 JAXBElement<TypeDefinitions> types = (JAXBElement<TypeDefinitions>) u.unmarshal(is);
244 for (CmisTypeDefinitionType td : types.getValue().getTypeDefinitions()) {
245 LOG.debug("Found type in file: " + td.getLocalName());
246 typeDef = Converter.convert(td);
247 if (typeDef.getPropertyDefinitions() == null) {
248 ((AbstractTypeDefinition) typeDef)
249 .setPropertyDefinitions(new LinkedHashMap<String, PropertyDefinition<?>>());
250 }
251 tmc.addTypeDefinition(typeDef);
252 }
253 } catch (Exception e) {
254 LOG.error("Could not load type definitions from file '" + typeDefsFileName + "': " + e);
255 }
256 }
257
258 private static List<String> readPropertiesToSetFromConfig(Map<String, String> parameters, String keyPrefix) {
259 List<String> propsToSet = new ArrayList<String>();
260 for (int i = 0;; ++i) {
261 String propertyKey = keyPrefix + Integer.toString(i);
262 String propertyToAdd = parameters.get(propertyKey);
263 if (null == propertyToAdd) {
264 break;
265 } else {
266 propsToSet.add(propertyToAdd);
267 }
268 }
269 return propsToSet;
270 }
271
272 private void fillRepositoryIfConfigured(Map<String, String> parameters) {
273
274 class DummyCallContext implements CallContext {
275
276 public String get(String key) {
277 return null;
278 }
279
280 public String getBinding() {
281 return null;
282 }
283
284 public boolean isObjectInfoRequired() {
285 return false;
286 }
287
288 public String getRepositoryId() {
289 return null;
290 }
291
292 public String getLocale() {
293 return null;
294 }
295
296 public BigInteger getOffset() {
297 return null;
298 }
299
300 public BigInteger getLength() {
301 return null;
302 }
303
304 public String getPassword() {
305 return null;
306 }
307
308 public String getUsername() {
309 return null;
310 }
311
312 public File getTempDirectory() {
313
314 return null;
315 }
316
317 public int getMemoryThreshold() {
318 return 0;
319 }
320 }
321
322
323
324 String repositoryId = parameters.get(ConfigConstants.REPOSITORY_ID);
325 String doFillRepositoryStr = parameters.get(ConfigConstants.USE_REPOSITORY_FILER);
326 String contentKindStr = parameters.get(ConfigConstants.CONTENT_KIND);
327 boolean doFillRepository = doFillRepositoryStr == null ? false : Boolean.parseBoolean(doFillRepositoryStr);
328
329 if (doFillRepository
330
331
332 ) {
333
334
335
336
337 InMemoryService svc = new InMemoryService(inMemoryServiceParameters, storeManager);
338
339 BindingsObjectFactory objectFactory = new BindingsObjectFactoryImpl();
340
341 String levelsStr = parameters.get(ConfigConstants.FILLER_DEPTH);
342 int levels = 1;
343 if (null != levelsStr) {
344 levels = Integer.parseInt(levelsStr);
345 }
346
347 String docsPerLevelStr = parameters.get(ConfigConstants.FILLER_DOCS_PER_FOLDER);
348 int docsPerLevel = 1;
349 if (null != docsPerLevelStr) {
350 docsPerLevel = Integer.parseInt(docsPerLevelStr);
351 }
352
353 String childrenPerLevelStr = parameters.get(ConfigConstants.FILLER_FOLDERS_PER_FOLDER);
354 int childrenPerLevel = 2;
355 if (null != childrenPerLevelStr) {
356 childrenPerLevel = Integer.parseInt(childrenPerLevelStr);
357 }
358
359 String documentTypeId = parameters.get(ConfigConstants.FILLER_DOCUMENT_TYPE_ID);
360 if (null == documentTypeId) {
361 documentTypeId = BaseTypeId.CMIS_DOCUMENT.value();
362 }
363
364 String folderTypeId = parameters.get(ConfigConstants.FILLER_FOLDER_TYPE_ID);
365 if (null == folderTypeId) {
366 folderTypeId = BaseTypeId.CMIS_FOLDER.value();
367 }
368
369 int contentSizeKB = 0;
370 String contentSizeKBStr = parameters.get(ConfigConstants.FILLER_CONTENT_SIZE);
371 if (null != contentSizeKBStr) {
372 contentSizeKB = Integer.parseInt(contentSizeKBStr);
373 }
374
375 ObjectGenerator.CONTENT_KIND contentKind;
376 if (null == contentKindStr)
377 contentKind = ObjectGenerator.CONTENT_KIND.LoremIpsumText;
378 else {
379 if (contentKindStr.equals("static/text"))
380 contentKind = ObjectGenerator.CONTENT_KIND.StaticText;
381 else if (contentKindStr.equals("lorem/text"))
382 contentKind = ObjectGenerator.CONTENT_KIND.LoremIpsumText;
383 else if (contentKindStr.equals("lorem/html"))
384 contentKind = ObjectGenerator.CONTENT_KIND.LoremIpsumHtml;
385 else if (contentKindStr.equals("fractal/jpeg"))
386 contentKind = ObjectGenerator.CONTENT_KIND.ImageFractalJpeg;
387 else
388 contentKind = ObjectGenerator.CONTENT_KIND.StaticText;
389 }
390
391 ObjectGenerator gen = new ObjectGenerator(objectFactory, svc, svc, svc, repositoryId, contentKind);
392
393 gen.setNumberOfDocumentsToCreatePerFolder(docsPerLevel);
394
395
396 gen.setDocumentTypeId(documentTypeId);
397
398
399 gen.setFolderTypeId(folderTypeId);
400
401
402 gen.setContentSizeInKB(contentSizeKB);
403
404
405
406
407
408
409
410 List<String> propsToSet = readPropertiesToSetFromConfig(parameters,
411 ConfigConstants.FILLER_DOCUMENT_PROPERTY);
412 if (null != propsToSet) {
413 gen.setDocumentPropertiesToGenerate(propsToSet);
414 }
415
416 propsToSet = readPropertiesToSetFromConfig(parameters, ConfigConstants.FILLER_FOLDER_PROPERTY);
417 if (null != propsToSet) {
418 gen.setFolderPropertiesToGenerate(propsToSet);
419 }
420
421
422
423
424
425 DummyCallContext ctx = new DummyCallContext();
426 svc.setCallContext(ctx);
427
428
429 RepositoryInfo rep = svc.getRepositoryInfo(repositoryId, null);
430 String rootFolderId = rep.getRootFolderId();
431
432 try {
433 gen.createFolderHierachy(levels, childrenPerLevel, rootFolderId);
434
435 gen.dumpFolder(rootFolderId, "*");
436 } catch (Exception e) {
437 LOG.error("Could not create folder hierarchy with documents. " + e);
438 e.printStackTrace();
439 }
440 }
441
442 }
443
444 class CleanManager {
445
446 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
447 ScheduledFuture<?> cleanerHandle = null;
448
449 public void startCleanRepositoryJob(long intervalInMinutes) {
450
451 final Runnable cleaner = new Runnable() {
452 public void run() {
453 LOG.info("Cleaning repository as part of a scheduled maintenance job.");
454 for (String repositoryId : storeManager.getAllRepositoryIds()) {
455 ObjectStore store = storeManager.getObjectStore(repositoryId);
456 store.clear();
457 fillRepositoryIfConfigured(ConfigurationSettings.getParameters());
458 }
459 LOG.info("Repository cleaned. Freeing memory.");
460 System.gc();
461 }
462 };
463
464 LOG.info("Repository Clean Job starting clean job, interval " + intervalInMinutes + " min");
465 cleanerHandle = scheduler.scheduleAtFixedRate(cleaner, intervalInMinutes, intervalInMinutes,
466 TimeUnit.MINUTES);
467 }
468
469 public void stopCleanRepositoryJob() {
470 LOG.info("Repository Clean Job cancelling clean job.");
471 boolean ok = cleanerHandle.cancel(true);
472 LOG.info("Repository Clean Job cancelled with result: " + ok);
473 scheduler.shutdownNow();
474 }
475 }
476
477 private void scheduleCleanRepositoryJob(long minutes) {
478 cleanManager = new CleanManager();
479 cleanManager.startCleanRepositoryJob(minutes);
480 }
481
482 }