/** * */ package org.infoglue.deliver.util; import java.io.File; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import org.apache.log4j.Logger; import org.exolab.castor.jdo.Database; import org.exolab.castor.jdo.ObjectNotFoundException; import org.infoglue.cms.controllers.kernel.impl.simple.CastorDatabaseService; import org.infoglue.cms.controllers.kernel.impl.simple.ContentVersionController; import org.infoglue.cms.controllers.kernel.impl.simple.DigitalAssetController; import org.infoglue.cms.entities.content.ContentVersionVO; import org.infoglue.cms.entities.content.DigitalAssetVO; import org.infoglue.cms.exception.SystemException; import org.infoglue.cms.util.CmsPropertyHandler; public class AssetUpdatingThread extends Thread { private static final Logger logger = Logger.getLogger(AssetUpdatingThread.class); private String contentVersionIdString; private static AtomicInteger numberOfRunningThreads = new AtomicInteger(0); AssetUpdatingThread(String contentVersionIdString) { this.contentVersionIdString = contentVersionIdString; } @SuppressWarnings("static-access") @Override public void run() { while(numberOfRunningThreads.get() > 10) { logger.info("To many threads - let's wait: "); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } numberOfRunningThreads.incrementAndGet(); logger.info("Running thread"); Database db = null; try { db = CastorDatabaseService.getDatabase(); CacheController.beginTransaction(db); // Setup Integer contentVersionId = new Integer(contentVersionIdString); ContentVersionVO contentVersionVO = ContentVersionController.getContentVersionController().getContentVersionVOWithId(contentVersionId, db); int operationMode = Integer.parseInt(CmsPropertyHandler.getOperatingMode()); if (contentVersionVO.getStateId() < operationMode) { logger.debug("Updated version had a to low state. State: " + contentVersionVO.getStateId() + ". Operation mode: " + operationMode); } else { Integer contentId = contentVersionVO.getContentId(); Integer languageId = contentVersionVO.getLanguageId(); Set<Integer> existingAssetIds = new HashSet<Integer>(); logger.info("Starting asset on disc clean for ContentVersion. Id: " + contentId); // Get stuff from previous version ContentVersionVO previousContentVersionVO = ContentVersionController.getContentVersionController().getSecondLatestActiveContentVersionVO(contentId, languageId, false, db); if (logger.isInfoEnabled()) { logger.info("Previous content version for cache cleaning of ContentVersion: " + contentVersionId + ". ContentVersion.id:" + (previousContentVersionVO == null ? "null" : previousContentVersionVO.getContentVersionId())); } if (previousContentVersionVO != null) { List<DigitalAssetVO> previousDigitalAssets = DigitalAssetController.getController().getDigitalAssetVOList(previousContentVersionVO.getContentVersionId(), db); for (DigitalAssetVO digitalAssetVO : previousDigitalAssets) { if (logger.isDebugEnabled()) { logger.debug("Adding digital asset to previous assets. DigitalAsset.id: " + digitalAssetVO.getDigitalAssetId()); } existingAssetIds.add(digitalAssetVO.getDigitalAssetId()); } } if (logger.isInfoEnabled()) { logger.info("existingAssets: " + existingAssetIds); } // Handling assets in current version List<DigitalAssetVO> digitalAssetVOs = DigitalAssetController.getDigitalAssetVOList(contentVersionId, db); if (digitalAssetVOs.size() == 0) { logger.info("ContentVersion had no assets so we leave things as they are. ContentVersion.id: " + contentVersionIdString); } else { for (DigitalAssetVO digitalAssetVO : digitalAssetVOs) { if (logger.isDebugEnabled()) { logger.debug("Checking DigitalAsset.id: " + digitalAssetVO.getDigitalAssetId() + " for ContentVersion.id: " + contentVersionIdString); } boolean wasOldAsset = existingAssetIds.remove(digitalAssetVO.getDigitalAssetId()); if (wasOldAsset) { logger.debug("Asset still exists. AssetId: " + digitalAssetVO.getDigitalAssetId()); } // Check if we should update file on disc File currentAssetFile = DigitalAssetController.getController().getAssetFile(digitalAssetVO, contentId, languageId, db); if (currentAssetFile != null) { logger.debug("File is currently stored on disc, let's update!. File: " + currentAssetFile.getAbsolutePath()); File assetFolder = DigitalAssetController.getController().getAssetFolderFile(digitalAssetVO, contentId, languageId, db); String assetFilename = DigitalAssetController.getController().getAssetFileName(digitalAssetVO, contentId, languageId, db); DigitalAssetController.getController().dumpDigitalAsset(digitalAssetVO, assetFilename, assetFolder.getAbsolutePath(), true, db); } } } logger.info("Number of assets to remove after cache clean: " + existingAssetIds.size()); for (Integer digitalAssetId : existingAssetIds) { DigitalAssetVO digitalAssetVO = DigitalAssetController.getController().getDigitalAssetVOWithId(digitalAssetId, db); File assetFile = DigitalAssetController.getController().getAssetFile(digitalAssetVO, contentId, languageId, db); if (assetFile != null) { logger.debug("Found asset file to remove. File: " + assetFile.getAbsolutePath()); boolean success = assetFile.delete(); if (logger.isDebugEnabled() && success) { logger.debug("Successfully deleted file. File: " + assetFile.getAbsolutePath()); } } } } CacheController.commitTransaction(db); } catch (NumberFormatException nex) { CacheController.rollbackTransaction(db); logger.warn("Failed to parse integer in asset clean thread. Message: " + nex); } catch (SystemException se) { CacheController.rollbackTransaction(db); if(se.getCause() instanceof ObjectNotFoundException) { logger.info("Error when cleaning assets from disc for ContentVersion.id: " + contentVersionIdString + ". Object is probably deleted. Message: " + se.getMessage()); } else { logger.error("Error when cleaning assets from disc for ContentVersion.id: " + contentVersionIdString + ". Message: " + se.getMessage()); logger.warn("Error when cleaning assets from disc for ContentVersion.id: " + contentVersionIdString, se); } } catch (Throwable ex) { CacheController.rollbackTransaction(db); logger.error("Error when cleaning assets from disc for ContentVersion.id: " + contentVersionIdString + ". Message: " + ex.getMessage()); logger.warn("Error when cleaning assets from disc for ContentVersion.id: " + contentVersionIdString, ex); } finally { numberOfRunningThreads.decrementAndGet(); } } }