1 17 package org.alfresco.repo.content; 18 19 import java.io.Serializable ; 20 import java.util.Collection ; 21 import java.util.HashSet ; 22 import java.util.Map ; 23 import java.util.Set ; 24 25 import org.alfresco.error.AlfrescoRuntimeException; 26 import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy; 27 import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy; 28 import org.alfresco.repo.content.filestore.FileContentStore; 29 import org.alfresco.repo.content.transform.ContentTransformer; 30 import org.alfresco.repo.content.transform.ContentTransformerRegistry; 31 import org.alfresco.repo.policy.ClassPolicyDelegate; 32 import org.alfresco.repo.policy.JavaBehaviour; 33 import org.alfresco.repo.policy.PolicyComponent; 34 import org.alfresco.service.cmr.dictionary.DataTypeDefinition; 35 import org.alfresco.service.cmr.dictionary.DictionaryService; 36 import org.alfresco.service.cmr.dictionary.InvalidTypeException; 37 import org.alfresco.service.cmr.dictionary.PropertyDefinition; 38 import org.alfresco.service.cmr.repository.ContentData; 39 import org.alfresco.service.cmr.repository.ContentIOException; 40 import org.alfresco.service.cmr.repository.ContentReader; 41 import org.alfresco.service.cmr.repository.ContentService; 42 import org.alfresco.service.cmr.repository.ContentStreamListener; 43 import org.alfresco.service.cmr.repository.ContentWriter; 44 import org.alfresco.service.cmr.repository.NoTransformerException; 45 import org.alfresco.service.cmr.repository.NodeRef; 46 import org.alfresco.service.cmr.repository.NodeService; 47 import org.alfresco.service.namespace.NamespaceService; 48 import org.alfresco.service.namespace.QName; 49 import org.alfresco.service.transaction.TransactionService; 50 import org.alfresco.util.EqualsHelper; 51 import org.alfresco.util.TempFileProvider; 52 import org.apache.commons.logging.Log; 53 import org.apache.commons.logging.LogFactory; 54 55 56 62 public class RoutingContentService implements ContentService 63 { 64 private static Log logger = LogFactory.getLog(RoutingContentService.class); 65 66 private TransactionService transactionService; 67 private DictionaryService dictionaryService; 68 private NodeService nodeService; 69 70 private ContentTransformerRegistry transformerRegistry; 71 72 private ContentStore store; 73 74 private ContentStore tempStore; 75 76 79 private PolicyComponent policyComponent; 80 81 84 ClassPolicyDelegate<ContentServicePolicies.OnContentUpdatePolicy> onContentUpdateDelegate; 85 ClassPolicyDelegate<ContentServicePolicies.OnContentReadPolicy> onContentReadDelegate; 86 87 90 public RoutingContentService() 91 { 92 this.tempStore = new FileContentStore(TempFileProvider.getTempDir().getAbsolutePath()); 93 } 94 95 public void setTransactionService(TransactionService transactionService) 96 { 97 this.transactionService = transactionService; 98 } 99 100 public void setDictionaryService(DictionaryService dictionaryService) 101 { 102 this.dictionaryService = dictionaryService; 103 } 104 105 public void setNodeService(NodeService nodeService) 106 { 107 this.nodeService = nodeService; 108 } 109 110 public void setTransformerRegistry(ContentTransformerRegistry transformerRegistry) 111 { 112 this.transformerRegistry = transformerRegistry; 113 } 114 115 public void setStore(ContentStore store) 116 { 117 this.store = store; 118 } 119 120 public void setPolicyComponent(PolicyComponent policyComponent) 121 { 122 this.policyComponent = policyComponent; 123 } 124 125 128 public void init() 129 { 130 this.policyComponent.bindClassBehaviour( 132 QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), 133 this, 134 new JavaBehaviour(this, "onUpdateProperties")); 135 136 this.onContentUpdateDelegate = this.policyComponent.registerClassPolicy(OnContentUpdatePolicy.class); 138 this.onContentReadDelegate = this.policyComponent.registerClassPolicy(OnContentReadPolicy.class); 139 } 140 141 148 public void onUpdateProperties( 149 NodeRef nodeRef, 150 Map <QName, Serializable > before, 151 Map <QName, Serializable > after) 152 { 153 boolean fire = false; 154 boolean newContent = false; 155 for (QName propertyQName : after.keySet()) 157 { 158 PropertyDefinition propertyDef = dictionaryService.getProperty(propertyQName); 160 if (propertyDef == null) 161 { 162 continue; 164 } 165 if (!propertyDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)) 166 { 167 continue; 169 } 170 171 try 172 { 173 ContentData beforeValue = (ContentData) before.get(propertyQName); 174 ContentData afterValue = (ContentData) after.get(propertyQName); 175 if (afterValue != null && afterValue.getContentUrl() == null) 176 { 177 } 179 else if (!EqualsHelper.nullSafeEquals(beforeValue, afterValue)) 180 { 181 if (logger.isDebugEnabled() == true) 183 { 184 String beforeString = ""; 185 if (beforeValue != null) 186 { 187 beforeString = beforeValue.toString(); 188 } 189 String afterString = ""; 190 if (afterValue != null) 191 { 192 afterString = afterValue.toString(); 193 } 194 logger.debug("onContentUpate: before = " + beforeString + "; after = " + afterString); 195 } 196 197 String beforeContentUrl = null; 199 if (beforeValue != null) 200 { 201 beforeContentUrl = beforeValue.getContentUrl(); 202 } 203 String afterContentUrl = null; 204 if (afterValue != null) 205 { 206 afterContentUrl = afterValue.getContentUrl(); 207 } 208 if (beforeContentUrl == null && afterContentUrl != null) 209 { 210 newContent = true; 211 } 212 213 fire = true; 216 break; 217 } 218 } 219 catch (ClassCastException e) 220 { 221 continue; 223 } 224 } 225 if (fire) 227 { 228 Set <QName> types = new HashSet <QName>(this.nodeService.getAspects(nodeRef)); 230 types.add(this.nodeService.getType(nodeRef)); 231 OnContentUpdatePolicy policy = this.onContentUpdateDelegate.get(types); 232 policy.onContentUpdate(nodeRef, newContent); 233 } 234 } 235 236 public ContentReader getReader(NodeRef nodeRef, QName propertyQName) 237 { 238 return getReader(nodeRef, propertyQName, true); 239 } 240 241 private ContentReader getReader(NodeRef nodeRef, QName propertyQName, boolean fireContentReadPolicy) 242 { 243 ContentData contentData = null; 244 Serializable propValue = nodeService.getProperty(nodeRef, propertyQName); 245 if (propValue instanceof Collection ) 246 { 247 Collection colPropValue = (Collection )propValue; 248 if (colPropValue.size() > 0) 249 { 250 propValue = (Serializable )colPropValue.iterator().next(); 251 } 252 } 253 if (propValue instanceof ContentData) 254 { 255 contentData = (ContentData)propValue; 256 } 257 258 if (contentData == null) 259 { 260 PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName); 262 if (contentPropDef != null && 263 (!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) || 264 contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY)))) 265 { 266 throw new InvalidTypeException("The node property must be of type content: \n" + 267 " node: " + nodeRef + "\n" + 268 " property name: " + propertyQName + "\n" + 269 " property type: " + ((contentPropDef == null) ? "unknown" : contentPropDef.getDataType()), 270 propertyQName); 271 } 272 } 273 274 if (contentData == null || contentData.getContentUrl() == null) 276 { 277 return null; 279 } 280 String contentUrl = contentData.getContentUrl(); 281 282 ContentReader reader = store.getReader(contentUrl); 284 285 reader.setMimetype(contentData.getMimetype()); 287 reader.setEncoding(contentData.getEncoding()); 288 289 if (reader != null && fireContentReadPolicy == true) 291 { 292 Set <QName> types = new HashSet <QName>(this.nodeService.getAspects(nodeRef)); 294 types.add(this.nodeService.getType(nodeRef)); 295 OnContentReadPolicy policy = this.onContentReadDelegate.get(types); 296 policy.onContentRead(nodeRef); 297 } 298 299 return reader; 302 } 303 304 public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update) 305 { 306 ContentReader existingContentReader = getReader(nodeRef, propertyQName, false); 308 309 311 ContentWriter writer = store.getWriter(existingContentReader, null); 314 315 Serializable contentValue = nodeService.getProperty(nodeRef, propertyQName); 317 if (contentValue != null && contentValue instanceof ContentData) 318 { 319 ContentData contentData = (ContentData)contentValue; 320 writer.setMimetype(contentData.getMimetype()); 321 writer.setEncoding(contentData.getEncoding()); 322 } 323 324 if (update) 326 { 327 WriteStreamListener listener = new WriteStreamListener(nodeService, nodeRef, propertyQName, writer); 329 writer.addListener(listener); 330 writer.setTransactionService(transactionService); 331 } 332 333 return writer; 335 } 336 337 340 public ContentWriter getTempWriter() 341 { 342 return tempStore.getWriter(null, null); 344 } 345 346 350 public void transform(ContentReader reader, ContentWriter writer) 351 throws NoTransformerException, ContentIOException 352 { 353 String sourceMimetype = reader.getMimetype(); 355 if (sourceMimetype == null) 356 { 357 throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader); 358 } 359 String targetMimetype = writer.getMimetype(); 360 if (targetMimetype == null) 361 { 362 throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); 363 } 364 ContentTransformer transformer = transformerRegistry.getTransformer(sourceMimetype, targetMimetype); 366 if (transformer == null) 367 { 368 throw new NoTransformerException(sourceMimetype, targetMimetype); 369 } 370 transformer.transform(reader, writer); 372 } 374 375 379 public boolean isTransformable(ContentReader reader, ContentWriter writer) 380 { 381 String sourceMimetype = reader.getMimetype(); 383 if (sourceMimetype == null) 384 { 385 throw new AlfrescoRuntimeException("The content reader mimetype must be set: " + reader); 386 } 387 String targetMimetype = writer.getMimetype(); 388 if (targetMimetype == null) 389 { 390 throw new AlfrescoRuntimeException("The content writer mimetype must be set: " + writer); 391 } 392 393 ContentTransformer transformer = transformerRegistry.getTransformer(sourceMimetype, targetMimetype); 395 return (transformer != null); 396 } 397 398 407 private static class WriteStreamListener implements ContentStreamListener 408 { 409 private NodeService nodeService; 410 private NodeRef nodeRef; 411 private QName propertyQName; 412 private ContentWriter writer; 413 414 public WriteStreamListener( 415 NodeService nodeService, 416 NodeRef nodeRef, 417 QName propertyQName, 418 ContentWriter writer) 419 { 420 this.nodeService = nodeService; 421 this.nodeRef = nodeRef; 422 this.propertyQName = propertyQName; 423 this.writer = writer; 424 } 425 426 public void contentStreamClosed() throws ContentIOException 427 { 428 try 429 { 430 ContentData contentData = writer.getContentData(); 432 nodeService.setProperty( 433 nodeRef, 434 propertyQName, 435 contentData); 436 if (logger.isDebugEnabled()) 438 { 439 logger.debug("Stream listener updated node: \n" + 440 " node: " + nodeRef + "\n" + 441 " property: " + propertyQName + "\n" + 442 " value: " + contentData); 443 } 444 } 445 catch (Throwable e) 446 { 447 throw new ContentIOException("Failed to set content property on stream closure: \n" + 448 " node: " + nodeRef + "\n" + 449 " property: " + propertyQName + "\n" + 450 " writer: " + writer, 451 e); 452 } 453 } 454 } 455 } 456 | Popular Tags |