Java tutorial
/** * Copyright (C) 2011 - 2013 Alfresco Business Reporting project * * This file is part of the Alfresco Business Reporting project. * * Licensed under the GNU LGPL, Version 3.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.gnu.org/licenses/lgpl.html * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.alfresco.reporting.processor; import java.io.IOException; import java.io.Serializable; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; import org.alfresco.repo.dictionary.DictionaryNamespaceComponent; import org.alfresco.repo.site.SiteModel; import org.alfresco.repo.version.Version2Model; import org.alfresco.reporting.Constants; import org.alfresco.reporting.ReportLine; import org.alfresco.reporting.ReportingHelper; import org.alfresco.reporting.ReportingModel; import org.alfresco.reporting.db.DatabaseHelperBean; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentReader; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.repository.Path.ChildAssocElement; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.ResultSetRow; import org.alfresco.service.cmr.search.SearchParameters; import org.alfresco.service.cmr.search.SearchService; import org.alfresco.service.cmr.version.VersionHistory; import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.namespace.NamespacePrefixResolver; import org.alfresco.service.namespace.QName; import org.alfresco.service.cmr.version.Version; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.Sort; /** * This class accepts an Alfresco object (document or folder), strips out all * properties and associations, and will return a Map of they key-value pairs. * * @author tpeelen * */ public class NodeRefBasedPropertyProcessor extends PropertyProcessor { /** * an object containing the noderef as key, and the parent of the version * series as value */ // private Properties versionnodes; private VersionService versionService; private ContentService contentService; private String vendor = ""; private String COLUMN_SIZE = ""; private static Log logger = LogFactory.getLog(NodeRefBasedPropertyProcessor.class); public ContentService getContentService() { return contentService; } public void setContentService(ContentService contentService) { this.contentService = contentService; } /** * * @param versionNodes * @param dbhb * @param reportingHelper * @param serviceRegistry * @throws Exception */ public NodeRefBasedPropertyProcessor(Properties versionNodes, DatabaseHelperBean dbhb, ReportingHelper reportingHelper, ServiceRegistry serviceRegistry) throws Exception { setNodeService(serviceRegistry.getNodeService()); setDictionaryService(serviceRegistry.getDictionaryService()); setFileFolderService(serviceRegistry.getFileFolderService()); setContentService(serviceRegistry.getContentService()); setSearchService(serviceRegistry.getSearchService()); setReportingHelper(reportingHelper); setDbhb(dbhb); // this.versionnodes = versionNodes; this.versionService = serviceRegistry.getVersionService(); super.versionService = serviceRegistry.getVersionService(); setClassToColumnType(reportingHelper.getClassToColumnType()); setReplacementDataTypes(reportingHelper.getReplacementDataType()); setGlobalProperties(reportingHelper.getGlobalProperties()); setNamespaces(reportingHelper.getNameSpaces()); setBlacklist(reportingHelper.getBlacklist()); vendor = reportingHelper.getDatabaseProvider(); if (Constants.VENDOR_ORACLE.equals(vendor)) { this.COLUMN_SIZE = Constants.COLUMN_SIZE_ORACLE; } else { this.COLUMN_SIZE = Constants.COLUMN_SIZE; } if (logger.isDebugEnabled() && false) { logger.debug("##this.dataDictionary =" + this.dataDictionary); logger.debug("##this.replacementDataTypes =" + this.replacementDataTypes); // logger.debug("##this.getGlobalProperties() =" + // this.getGlobalProperties()); logger.debug("##this.namespaces =" + this.namespaces); // logger.debug("##this.versionnodes =" + getVersionNodes()); } } /** * Gien the current noderef, retrieve the value of the Site name (will be * stored as a column by default) * * @param currentRef * @return cm:name of the Site, or "" if no site found */ private String getSiteName(NodeRef currentRef) { // logger.debug("Enter getSiteName"); String siteName = ""; if (currentRef != null) { NodeRef rootNode = getNodeService().getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE); NodeRef siteRef = null; boolean siteTypeFound = getNodeService().getType(currentRef).equals(SiteModel.TYPE_SITE); if (siteTypeFound) { siteRef = currentRef; } while (!currentRef.equals(rootNode) && (!siteTypeFound)) { // logger.debug("getTypeForNode: voor loopRef="+currentRef); currentRef = getNodeService().getPrimaryParent(currentRef).getParentRef(); // logger.debug("getTypeForNode: na loopRef="+currentRef); siteTypeFound = getNodeService().getType(currentRef).equals(SiteModel.TYPE_SITE); if (siteTypeFound) { siteRef = currentRef; // logger.debug("getTypeForNode: Found QName node!"); } } if (siteRef != null) { siteName = (String) getNodeService().getProperty(siteRef, ContentModel.PROP_NAME); } } // end if nodeRef!=null return siteName; } /** * @param path * @return display path */ private String toDisplayPath(Path path) { // logger.debug("Enter toDisplayPath"); StringBuffer displayPath = new StringBuffer(); if (path.size() == 1) { displayPath.append("/"); } else { for (int i = 1; i < path.size(); i++) { Path.Element element = path.get(i); if (element instanceof ChildAssocElement) { ChildAssociationRef assocRef = ((ChildAssocElement) element).getRef(); NodeRef node = assocRef.getChildRef(); displayPath.append("/"); displayPath.append(getNodeService().getProperty(node, ContentModel.PROP_NAME)); } } } return displayPath.toString(); } /** * Given the ScriptNode, get all available associations (parent/child & * target/source) Create a column to store the noderef if there are any of * these associations * * @throws Exception * */ private Properties processAssociationDefinitions(Properties definition, NodeRef nodeRef) throws Exception { // logger.debug("Enter processAssociationDefinitions"); // Child References try { List<ChildAssociationRef> childCars = getNodeService().getChildAssocs(nodeRef); if (childCars.size() > 0) { String type = getClassToColumnType().getProperty("noderefs", "-"); if (getReplacementDataType().containsKey("child_noderef")) { type = getReplacementDataType().getProperty("child_noderef", "-").trim(); } definition.setProperty("child_noderef", type); } } catch (Exception e) { logger.error("processAssociationDefinitions: child_noderef ERROR! " + e.getMessage()); e.printStackTrace(); } try { // Parent References ChildAssociationRef parentCar = getNodeService().getPrimaryParent(nodeRef); if (parentCar != null) { String type = getClassToColumnType().getProperty("noderef", "-"); if (getReplacementDataType().containsKey("parent_noderef")) { type = getReplacementDataType().getProperty("parent_noderef", "-").trim(); } definition.setProperty("parent_noderef", type); } } catch (Exception e) { logger.error("processAssociationDefinitions: parent_noderef ERROR!"); e.printStackTrace(); } try { Collection<QName> assocTypes = getDictionaryService().getAllAssociations(); String blockNameSpaces = globalProperties.getProperty(Constants.property_blockNameSpaces, ""); String[] startValues = blockNameSpaces.split(","); for (QName type : assocTypes) { String key = ""; String shortName = replaceNameSpaces(type.toString()); boolean stop = nodeRef.toString().startsWith("versionStore") || nodeRef.toString().startsWith("archive"); for (String startValue : startValues) { stop = shortName.startsWith(startValue.trim()); if (stop) break; } // trx,act,blg_,wca,wcm,ver,fm_,emailserver,sys_,cm_member,cm_subcategories,cm_subscribedBy,cm_attachments, // cm_preference,cm_translations,cm_replaces,cm_ml,cm_references,cm_failed,cm_references,cm_avatar,rn_,usr_ /* * if (stop || shortName.startsWith("trx") || * shortName.startsWith("act") || shortName.startsWith("blg_") * || shortName.startsWith("wca") || shortName.startsWith("wcm") * || shortName.startsWith("ver") || shortName.startsWith("fm_") * || shortName.startsWith("emailserver_") || * shortName.startsWith("sys_") || * shortName.startsWith("cm_member") || * shortName.startsWith("cm_subcategories") || * shortName.startsWith("cm_subscribedBy") || * shortName.startsWith("cm_attachments") || * shortName.startsWith("cm_translations") || * shortName.startsWith("cm_preference") || * shortName.startsWith("cm_replaces") || * shortName.startsWith("cm_ml") || * shortName.startsWith("cm_failed") || * shortName.startsWith("cm_references") || * shortName.startsWith("cm_avatar") || * shortName.startsWith("rn_") || /* * shortName.startsWith("imap_") || shortName.startsWith("usr_") * ){} else { */ if (!stop) { try { // logger.debug("ASSOCIATIONS: processing " + shortName // + " for " + shortName); List<AssociationRef> targetRefs = getNodeService().getTargetAssocs(nodeRef, type); if (targetRefs.size() > 0) { // logger.debug("Found a Target association! " + // type.toString()); key = type.toString(); // logger.debug("Target: key1="+key); key = replaceNameSpaces(key); // logger.debug("Target: key2="+key); if (!getBlacklist().toLowerCase().contains("," + key.toLowerCase() + ",") && !type.equals("-")) { // logger.debug("Target: Still in the game! // key="+key); String sType = getClassToColumnType().getProperty("noderefs", "-"); if (getReplacementDataType().containsKey(key)) { sType = getReplacementDataType().getProperty(key, "-").trim(); } if (logger.isDebugEnabled()) logger.debug("Target: Setting " + key + "=" + sType); definition.setProperty(key, sType); // extensionPoint: Include username, or name // property of target } } } catch (Exception e) { logger.error("processAssociationDefinitions: Target_Association ERROR! key=" + key); // e.printStackTrace(); } try { List<AssociationRef> sourceRefs = getNodeService().getSourceAssocs(nodeRef, type); if (sourceRefs.size() > 0) { logger.debug("Found a Source association! " + type.toString()); key = type.toString(); key = replaceNameSpaces(key); if (!getBlacklist().toLowerCase().contains("," + key.toLowerCase() + ",") && !type.equals("-")) { String sType = getClassToColumnType().getProperty("noderefs", "-"); if (getReplacementDataType().containsKey(key)) { sType = getReplacementDataType().getProperty(key, "-").trim(); } definition.setProperty(key, sType); // extensionPoint: Include username, or name // property of source } } } catch (UnsupportedOperationException uoe) { // silent drop. On purpose. Because this is most likely // an operation against some // version store implementation of the nodeservice... we // don't bother... } catch (Exception e) { logger.warn("processAssociationDefinitions: Source_Association ERROR! key=" + key); logger.warn(" Messg: " + e.getMessage()); logger.warn(" Cause: " + e.getCause()); logger.warn(" Error: " + e.toString()); // e.printStackTrace(); } } // end exclude trx_orphan } // end for } catch (Exception e) { logger.warn("processAssociationDefinitions: source-target ERROR!"); e.printStackTrace(); } return definition; } // *************** Values ********************* /** * * @param rl * @param sn * @return * @throws Exception */ private ReportLine processAssociationValues(ReportLine rl, NodeRef nodeRef) throws Exception { // Child References try { List<ChildAssociationRef> childCars = getNodeService().getChildAssocs(nodeRef); long maxChildCount = Math.min(childCars.size(), Integer .parseInt(getGlobalProperties().getProperty(Constants.property_treshold_child_assocs, "20"))); long numberOfChildCars = childCars.size(); if ((numberOfChildCars > 0) && (numberOfChildCars <= maxChildCount)) { String value = ""; for (ChildAssociationRef car : childCars) { if (value.length() > 0) value += ","; value += car.getChildRef(); } rl.setLine("child_noderef", getClassToColumnType().getProperty("noderefs", "-"), value, getReplacementDataType()); } } catch (Exception e) { logger.warn("Error in processing processAssociationValues"); e.printStackTrace(); } // Parent References try { ChildAssociationRef parentCar = getNodeService().getPrimaryParent(nodeRef); if (parentCar != null) { String value = parentCar.getParentRef().toString(); rl.setLine("parent_noderef", getClassToColumnType().getProperty("noderef", "-"), value, getReplacementDataType()); } } catch (Exception e) { logger.warn("Exception in getting primary Parent noderef: " + e.getMessage()); } // Other associations Collection<QName> assocTypes = getDictionaryService().getAllAssociations(); for (QName type : assocTypes) { String shortName = replaceNameSpaces(type.toString()); // logger.debug("ASSOCIATIONS: processing " + shortName + " for " + // sn.getTypeShort()); if (shortName.startsWith("trx") || shortName.startsWith("act") || shortName.startsWith("wca")) { // nothing. Dont like these namespaces, that's all. } else { try { List<AssociationRef> targetRefs = getNodeService().getTargetAssocs(nodeRef, type); long maxChildCount = Math.min(targetRefs.size(), Integer.parseInt(getGlobalProperties() .getProperty(Constants.property_treshold_soucetarget_assocs, "20"))); long numberOfChildCars = targetRefs.size(); if ((numberOfChildCars > 0) && (numberOfChildCars <= maxChildCount)) { String key = type.toString(); key = replaceNameSpaces(key); if (!getBlacklist().toLowerCase().contains("," + key.toLowerCase() + ",") && !type.equals("-")) { if ((targetRefs != null) && targetRefs.size() > 0) { String valueRef = ""; for (AssociationRef ar : targetRefs) { if (valueRef.length() > 0) valueRef += ","; valueRef += ar.getTargetRef().toString(); } rl.setLine(key, getClassToColumnType().getProperty("noderefs", "-"), valueRef, getReplacementDataType()); } } // end if blacklist // extensionPoint: Include username, or name // property of target } } catch (Exception e) { } try { List<AssociationRef> sourceRefs = getNodeService().getSourceAssocs(nodeRef, type); long maxChildCount = Math.min(sourceRefs.size(), Integer.parseInt(getGlobalProperties() .getProperty(Constants.property_treshold_soucetarget_assocs, "20"))); long numberOfChildCars = sourceRefs.size(); if ((numberOfChildCars > 0) && (numberOfChildCars <= maxChildCount)) { String key = type.toString(); key = replaceNameSpaces(key); if (!getBlacklist().toLowerCase().contains("," + key.toLowerCase() + ",") && !type.equals("-")) { if ((sourceRefs != null) && sourceRefs.size() > 0) { String value = ""; for (AssociationRef ar : sourceRefs) { if (value.length() > 0) value += ","; value += ar.getSourceRef().toString(); } rl.setLine(key, getClassToColumnType().getProperty("noderefs", "-"), value, getReplacementDataType()); } // extensionPoint: Include username, or name // property of source } // end if blacklist } } catch (Exception e) { } } // it is not a trx_ } // end or return rl; } @Override protected ReportLine processNodeToMap(String identifier, String table, ReportLine rl) { table = dbhb.fixTableColumnName(table); if (logger.isDebugEnabled()) logger.debug("processNodeToMap, identifier=" + identifier); NodeRef masterRef = null; NodeRef nodeRef = new NodeRef(identifier.split(",")[0]); if (identifier.contains(",")) { masterRef = new NodeRef(identifier.split(",")[1]); } // NodeRef nodeRef=new NodeRef(identifier); if (logger.isDebugEnabled()) logger.debug("Enter processNodeToMap nodeRef=" + nodeRef); try { // logger.debug("processNodeToMap: processing values"); rl = processPropertyValues(rl, nodeRef); } catch (Exception e) { // logger.error("processprocessNodeToMap: That is weird, // processPropertyValues crashed! " + nodeRef); e.printStackTrace(); } try { rl = processAssociationValues(rl, nodeRef); } catch (Exception e) { // logger.error("processNodeToMap: That is weird, // processAssociationValues crashed! " + nodeRef); e.printStackTrace(); } try { rl.setLine(Constants.COLUMN_NODEREF, getClassToColumnType().getProperty("noderef"), nodeRef.toString(), getReplacementDataType()); } catch (Exception e) { // logger.error("processNodeToMap: That is weird, // rl.setLine(noderef) crashed! " + nodeRef); e.printStackTrace(); } try { String typeString = nodeService.getType(nodeRef).getLocalName(); // .getPrefixedQName(resolver);// // apparently for native documents (cm:content) the type == null. // Code below should fix if (typeString == null) { typeString = nodeService.getType(nodeRef).toString(); typeString = typeString.substring(typeString.lastIndexOf(":")); } rl.setLine(Constants.COLUMN_OBJECT_TYPE, getClassToColumnType().getProperty(Constants.COLUMN_OBJECT_TYPE, ""), typeString, getReplacementDataType()); } catch (Exception e) { // it does not have a type (??). Bad luck. Don't crash // (versionStore?!) logger.debug("EXCPTION1: // it does not have a Type. Bad luck. Don't crash (versionStore?!)"); e.printStackTrace(); } String aspectString = ""; try { Set<QName> aspectsSet = nodeService.getAspects(nodeRef); Iterator<QName> aspectIterator = aspectsSet.iterator(); while (aspectIterator.hasNext()) { QName aspect = aspectIterator.next(); if (aspectString.length() > 0) { aspectString += ","; } aspectString += aspect.getLocalName(); // getPrefixedQName(resolver);// // getLocalName(); } // end while rl.setLine(Constants.COLUMN_ASPECTS, getClassToColumnType().getProperty(Constants.COLUMN_ASPECTS, ""), aspectString, getReplacementDataType()); } catch (Exception e) { // it does not have aspects. Bad luck. Don't crash (versionStore?!) // logger.debug("EXCPTION1: // it does not have Aspects. Bad luck. // Don't crash (versionStore?!)"); e.printStackTrace(); } Path path; String displayPath = ""; try { path = getNodeService().getPath(nodeRef); displayPath = toDisplayPath(path); rl.setLine(Constants.COLUMN_PATH, getClassToColumnType().getProperty(Constants.COLUMN_PATH), displayPath, getReplacementDataType()); } catch (Exception e) { // it does not have a path. Bad luck. Don't crash (versionStore?!) // logger.debug("EXCPTION1: // it is not in a site. Bad luck. Don't // crash (versionStore?!)"); e.printStackTrace(); } String site = ""; try { site = getSiteName(nodeRef); rl.setLine(Constants.COLUMN_SITE, getClassToColumnType().getProperty(Constants.COLUMN_SITE), site, getReplacementDataType()); } catch (Exception e) { // it is not in a site. Bad luck. Don't crash } QName myType = getNodeService().getType(nodeRef); if (getDictionaryService().isSubClass(myType, ContentModel.TYPE_FOLDER)) { NodeRef origNodeRef = null; try { if (nodeRef.toString().startsWith(StoreRef.PROTOCOL_ARCHIVE)) { ChildAssociationRef car = (ChildAssociationRef) nodeService.getProperty(nodeRef, QName.createQName("http://www.alfresco.org/model/system/1.0", "archivedOriginalParentAssoc")); logger.debug("ORIGIN: child:" + car.getChildRef() + " parent: " + car.getParentRef()); origNodeRef = car.getChildRef(); } } catch (Exception e) { logger.fatal("Exception getting orig_noderef" + e.getStackTrace()); } if (origNodeRef != null) { // it is an archived thingy if (logger.isDebugEnabled()) logger.debug("Setting Ref from archive to orig_noderef!!!"); rl.setLine(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef"), origNodeRef.toString(), getReplacementDataType()); } else { if (logger.isDebugEnabled()) logger.debug("Setting currentRef to orig_noderef!!!"); rl.setLine(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef"), nodeRef.toString(), getReplacementDataType()); } } if (getDictionaryService().isSubClass(myType, ContentModel.TYPE_CONTENT) || (getDictionaryService().getType(myType)).toString() .equalsIgnoreCase(ContentModel.TYPE_CONTENT.toString())) { long size = 0; String sizeString = "0"; try { size = getFileFolderService().getFileInfo(nodeRef).getContentData().getSize(); if (size == 0) { sizeString = "0"; } else { sizeString = Long.toString(size); } // get the COLUMN_SIZE prop, being "size" for MySQL, but // "docsize" for Oracle rl.setLine(COLUMN_SIZE, getClassToColumnType().getProperty(COLUMN_SIZE), sizeString, getReplacementDataType()); } catch (Exception e) { logger.info("processNodeToMap: Huh, no size?"); sizeString = "0"; } boolean versioned = false; try { versioned = getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE); rl.setLine("versioned", getClassToColumnType().getProperty("boolean"), String.valueOf(versioned), getReplacementDataType()); } catch (Exception e) { logger.info("processNodeToMap: Huh, no versioned info?"); e.printStackTrace(); } try { String mimetype = getFileFolderService().getFileInfo(nodeRef).getContentData().getMimetype(); if (mimetype == null) mimetype = "NULL"; rl.setLine(Constants.COLUMN_MIMETYPE, getClassToColumnType().getProperty(Constants.COLUMN_MIMETYPE), mimetype, getReplacementDataType()); } catch (Exception e) { logger.info("processNodeToMap: Huh, no mimetype?"); } NodeRef origNodeRef = null; try { if (nodeRef.toString().startsWith(StoreRef.PROTOCOL_ARCHIVE)) { ChildAssociationRef car = (ChildAssociationRef) nodeService.getProperty(nodeRef, QName.createQName("http://www.alfresco.org/model/system/1.0", "archivedOriginalParentAssoc")); logger.debug("ORIGIN: child:" + car.getChildRef() + " parent: " + car.getParentRef()); origNodeRef = car.getChildRef(); } } catch (Exception e) { logger.warn("Exception getting orig_noderef" + e.getStackTrace()); } try { if (nodeRef.toString().startsWith("version")) { // replace all archive-space references in the orig_noderef // into the workspace one. if (logger.isDebugEnabled()) { logger.debug("Setting nodeRef to orig_noderef - VERSION!!!"); logger.debug("Master says: " + masterRef.toString()); } rl.setLine(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef"), masterRef.toString(), getReplacementDataType()); } else { if (origNodeRef != null) { // it is an archived thingy if (logger.isDebugEnabled()) logger.debug("Setting Ref from archive to orig_noderef!!!"); rl.setLine(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef"), origNodeRef.toString(), getReplacementDataType()); } else { if (logger.isDebugEnabled()) logger.debug("Setting currentRef to orig_noderef!!!"); rl.setLine(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef"), nodeRef.toString(), getReplacementDataType()); } } } catch (Exception e) { // don't crash... (versionStore?!) // logger.debug("EXCPTION: don't crash... (versionStore?!)"); } } // end if else { if (logger.isDebugEnabled()) logger.debug(myType.toString() + " is no content subclass!"); } return rl; } public Properties processQueueDefinition(String table) { table = dbhb.fixTableColumnName(table); // logger.debug("Enter processQueueDefinition"); Properties definition = new Properties(); // set of propname-proptype int queuesize = queue.size(); for (int q = 0; q < queue.size(); q++) { // logger.debug("Queue contains: " + queue.get(q).toString()); // remind, a queue entry can contain versionRef,nodeRef values NodeRef nodeRef = new NodeRef(queue.get(q).toString().split(",")[0]); try { String name = (String) getNodeService().getProperty(nodeRef, ContentModel.PROP_NAME); if (logger.isDebugEnabled()) logger.debug("processQueueDefinition: " + q + "/" + queuesize + ": " + name); // Process Properties definition = processPropertyDefinitions(definition, nodeRef); // logger.debug("processQueueDefinition: Done processing // Properties"); // logger.debug("processQueueDefinition: Returned from // processPropertyDefinitions"); // if it is a versioned noderef, add the original noderef too // if ((getVersionNodes()!=null) && // getVersionNodes().containsKey(nodeRef.toString())){ definition.setProperty(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef", "-")); // } } catch (Exception e) { logger.warn("processQueueDefinition: ERROR: versionNodes.containsKey or before " + e.getMessage()); e.printStackTrace(); } // logger.debug("processQueueDefinition: try/catch survived"); try { // Process 'manual' properties definition.setProperty(Constants.COLUMN_ORIG_NODEREF, getClassToColumnType().getProperty("noderef", "-")); definition.setProperty(Constants.COLUMN_SITE, getClassToColumnType().getProperty("site", "-")); definition.setProperty(Constants.COLUMN_PATH, getClassToColumnType().getProperty("path", "-")); definition.setProperty(Constants.COLUMN_NODEREF, getClassToColumnType().getProperty(Constants.COLUMN_NODEREF, "-")); definition.setProperty(Constants.COLUMN_OBJECT_TYPE, getClassToColumnType().getProperty(Constants.COLUMN_OBJECT_TYPE, "-")); definition.setProperty(Constants.COLUMN_ASPECTS, getClassToColumnType().getProperty(Constants.COLUMN_ASPECTS, "-")); // logger.debug("processQueueDefinition: custom props // survived"); QName myType = getNodeService().getType(nodeRef); if (logger.isDebugEnabled()) logger.debug("processQueueDefinition: qname=" + myType); if (getDictionaryService().isSubClass(myType, ContentModel.TYPE_CONTENT) || (getDictionaryService().getType(myType)).toString() .equalsIgnoreCase(ContentModel.TYPE_CONTENT.toString())) { if (logger.isDebugEnabled()) logger.debug("processQueueDefinition: YEAH! We are a subtype of Content! " + ContentModel.TYPE_CONTENT); definition.setProperty(Constants.COLUMN_MIMETYPE, getClassToColumnType().getProperty(Constants.COLUMN_MIMETYPE, "-")); definition.setProperty(COLUMN_SIZE, getClassToColumnType().getProperty(COLUMN_SIZE, "-")); // and some stuff default reporting is dependent on definition.setProperty("cm_workingCopyLlink", getClassToColumnType().getProperty("noderef", "-")); definition.setProperty("cm_lockOwner", getClassToColumnType().getProperty("noderef", "-")); definition.setProperty("cm_lockType", getClassToColumnType().getProperty("noderef", "-")); definition.setProperty("cm_expiryDate", getClassToColumnType().getProperty("datetime", "-")); definition.setProperty("sys_archivedDate", getClassToColumnType().getProperty("datetime", "-")); definition.setProperty("sys_archivedBy", getClassToColumnType().getProperty("noderef", "-")); definition.setProperty("sys_archivedOriginalOwner", getClassToColumnType().getProperty("noderef", "-")); definition.setProperty("versioned", getClassToColumnType().getProperty("noderef", "-")); } else { logger.debug("processQueueDefinition: NOOOOO! We are NOT a subtype of Content!"); } if (getDictionaryService().isSubClass(myType, ContentModel.TYPE_PERSON)) { definition.setProperty("enabled", getClassToColumnType().getProperty("boolean", "-")); } // QName objectType = getNodeService().getType(nodeRef); if ((getNodeService().hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE))) { // (getDictionaryService().isSubClass(objectType, // ContentModel.TYPE_CONTENT))){ String type = getClassToColumnType().getProperty("text", "-"); if (getReplacementDataType().containsKey("cm_versionLabel")) { type = getReplacementDataType().getProperty("cm_versionLabel", "-").trim(); } definition.setProperty("cm_versionLabel", type); type = getClassToColumnType().getProperty("text", "-"); if (getReplacementDataType().containsKey("cm_versionType")) { type = getReplacementDataType().getProperty("cm_versionType", "-").trim(); } definition.setProperty("cm_versionType", type); } } catch (Exception e) { logger.info("unexpeted error in node " + nodeRef.toString()); logger.info("unexpeted error in node " + e.getMessage()); } // logger.debug("processQueueDefinition: content specific props // survived"); // Process Associations try { definition = processAssociationDefinitions(definition, nodeRef); } catch (Exception e) { logger.warn("Error getting assoc definitions" + e.getMessage()); e.printStackTrace(); } } // end for sn:queue // logger.debug("Exit processQueueDefinition"); return definition; } public void processQueueValues(String table) throws Exception { if (logger.isDebugEnabled()) logger.debug("Enter processQueueValues table=" + table); // Statement stmt = null; // Properties tableDesc = dbhb.getTableDescription(stmt, table); if (logger.isDebugEnabled()) logger.debug( "************ Found " + queue.size() + " entries in " + table + " **************** " + method); ReportLine rl = new ReportLine(table, getSimpleDateFormat(), reportingHelper); // Create the processing object once... long now_before = (new Date()).getTime(); int queuesize = queue.size(); for (int q = 0; q < queue.size(); q++) { String identifier = queue.get(q).toString(); try { NodeRef nodeRef = new NodeRef(identifier.split(",")[0]); if (logger.isDebugEnabled()) { String name = (String) getNodeService().getProperty(nodeRef, ContentModel.PROP_NAME); logger.debug("processQueueValues: " + q + "/" + queuesize + ": " + name); } // run each queue entry through the processing object rl = processNodeToMap(identifier, table, rl); int numberOfRows = 0; if (logger.isDebugEnabled()) logger.debug("Current method=" + this.method); try { // SINGLE_INSTANCE, // logger.debug(method + " ##### " + rl.size()); if ((rl.size() > 0) /* * && * (rl.getValue("sys_node_uuid").length( * )>5) */) { // logger.debug("method="+method+" && row exists?"); if (this.method.equals(Constants.INSERT_ONLY)) { // if (logger.isDebugEnabled()) logger.debug("Going // INSERT_ONLY"); numberOfRows = dbhb.insertIntoTable(rl); // logger.debug(numberOfRows+ " rows inserted"); } // ------------------------------------------------------------- if (this.method.equals(Constants.SINGLE_INSTANCE)) { // if (logger.isDebugEnabled()) logger.debug("Going // SINGLE_INSTANCE"); if (dbhb.rowExists(rl)) { numberOfRows = dbhb.updateIntoTable(rl); // logger.debug(numberOfRows+ " rows updated"); } else { numberOfRows = dbhb.insertIntoTable(rl); // logger.debug(numberOfRows+ " rows inserted"); } } // ------------------------------------------------------------- if (this.method.equals(Constants.UPDATE_VERSIONED)) { if (logger.isDebugEnabled()) logger.debug("Going UPDATE_VERSIONED"); try { if (dbhb.rowExists(rl)) { numberOfRows = dbhb.updateVersionedIntoTable(rl); // numberOfRows = dbhb.insertIntoTable(rl); if (logger.isDebugEnabled()) logger.debug(numberOfRows + " rows updated"); } else { if (logger.isDebugEnabled()) { logger.debug("No rows exist"); logger.debug("## Set " + rl.getInsertListOfKeys()); logger.debug("## Values " + rl.getInsertListOfValues()); } numberOfRows = dbhb.insertIntoTable(rl); if (logger.isDebugEnabled()) logger.debug(numberOfRows + " rows inserted"); } } catch (org.springframework.dao.RecoverableDataAccessException rdae) { throw new AlfrescoRuntimeException("processQueueValues1: " + rdae.getMessage()); } catch (Exception ee) { ee.printStackTrace(); logger.fatal("processQueueValues Exception1: " + ee.getMessage()); } } } // end if rl.size>0 } catch (org.springframework.dao.RecoverableDataAccessException rdae) { throw new AlfrescoRuntimeException("processQueueValues2: " + rdae.getMessage()); } catch (Exception e) { logger.fatal("processQueueValues Exception2: " + e.getStackTrace()); e.printStackTrace(); } finally { rl.reset(); } } catch (Exception e) { logger.info("Bad node detected; ignoring... " + identifier); } } // end for scriptnode in queue long now_after = (new Date()).getTime(); if (logger.isInfoEnabled()) { logger.info("processQueueValues summary: " + queuesize + " rows in " + (now_after - now_before) + "ms = " + (now_after - now_before) / queuesize + "ms per row"); } if (logger.isDebugEnabled()) logger.debug("Exit processQueueValues"); } public void addToQueue(Object nodeRef, Properties versionThingy) { addToQueue(nodeRef); // now what } public void addToQueue(final Object nodeRef, final NodeRef masterRef) { addToQueue(nodeRef.toString() + "," + masterRef.toString()); // now what } public boolean stillContinueHarvesting(long loopcount) { return stillContinueHarvesting(loopcount, 1); } public boolean stillContinueHarvesting(long loopcount, int resultSize) { boolean returnBoolean = true; if (getMaxLoopCount() != 0) { returnBoolean = (loopcount <= getMaxLoopCount()); } try { returnBoolean = returnBoolean && (resultSize > 0); } catch (Exception e) { // leave it, if resultSize==null, return true too } return returnBoolean; } /** * Harvests 1) objects 2) closed tasks after date x */ public void havestNodes(final NodeRef harvestDefinition) { /* * for each store:stores for each table:tables while continue search * continue = search.size>0 for each result:resultset if isVersioned * addAllOlderVersionsToQueue(result) addToQueue(result) processQueue() * // end while continue // end for each table // end for each store */ logger.info("harvest run start..."); ; try { final ArrayList<StoreRef> storeList = getStoreRefList(); final Properties queries = getTableQueries(harvestDefinition); final String language = reportingHelper.getSearchLanguage(harvestDefinition); // Make sure there is a connection dbhb.openReportingConnection(); Enumeration<Object> keys = queries.keys(); String fullQuery; // is the actual query appending orderby // node-dbid, and lastmodifued clause // Cycle all Lucene queries while (keys.hasMoreElements()) { String tableName = (String) keys.nextElement(); String query = (String) queries.get(tableName); tableName = dbhb.fixTableColumnName(tableName); if (logger.isDebugEnabled()) logger.debug("harvest: preparing table =" + tableName); // get a clean iterator to cycle all stores Iterator<StoreRef> storeIterator = storeList.iterator(); Date lastModified = null; boolean archiveAllowed = false; // prevent having two threads doing the same if (!dbhb.tableIsRunning(tableName)) { String nowFormattedDate = getNowAsFormattedString(); String timestamp = ""; // old school all-in-one harvesting if (!getBatchTimestampEnabled()) { dbhb.setLastTimestampStatusRunning(tableName); timestamp = dbhb.getLastTimestamp(tableName); } // else, see 5 lines below dbhb.createEmptyTables(tableName); int maxItems = getMaxLoopSize(); while (storeIterator.hasNext()) { StoreRef storeRef = storeIterator.next(); // mew insight, limit the number of loops, treat // mechanism with more care if (getBatchTimestampEnabled()) { dbhb.setLastTimestampStatusRunning( tableName + "_" + storeRef.getProtocol().substring(0, 1)); timestamp = dbhb .getLastTimestamp(tableName + "_" + storeRef.getProtocol().substring(0, 1)); } if (logger.isDebugEnabled()) logger.debug("harvest: StoreRef=" + storeRef.getProtocol() + ", archiveAllowed=" + archiveAllowed); // (re)set some essential process markers. // These are local to the run-per-storeRef long startDbId = 0; // the original database id of // the noderef long loopcount = 0; // count the number of // harvesting loops. Should be // <=2 for initial harvesting // agaist factory repo boolean letsContinue = true; // break if we process the archive before the // workspace is done... if (storeRef.getProtocol().equals(StoreRef.PROTOCOL_ARCHIVE) && !archiveAllowed) { letsContinue = false; } if (logger.isDebugEnabled()) logger.debug("harvest: before while, letsContinue=" + letsContinue); while (letsContinue) { loopcount++; // hasEverRun is needed to determine if an // update of lastModifiedTimestamp has occured // ever in a batch, or never. boolean hasEverRun = false; if (logger.isInfoEnabled()) { logger.info("++ Loop number: " + loopcount + ", tablename: " + tableName + ", archive: " + archiveAllowed); } if (getBatchTimestampEnabled()) { // default = // true nowFormattedDate = getNowAsFormattedString(); } fullQuery = query + queryClauseTimestamp(language, timestamp, storeRef.getProtocol()) + queryClauseOrderBy(language, startDbId, storeRef.getProtocol()); if (logger.isDebugEnabled()) { logger.debug("harvest: StoreProtocol = " + storeRef.getProtocol() + ", archive: " + archiveAllowed + "\nfullQuery = " + fullQuery); } SearchParameters sp = new SearchParameters(); sp.setLanguage(language); sp.addStore(storeRef); sp.setQuery(fullQuery); // sp.addSort(getOrderBy(language), true); if (maxItems > 0) { sp.setMaxItems(maxItems); } if (logger.isDebugEnabled()) { logger.debug("Searchparameter query: " + sp.getQuery()); } ResultSet results = getSearchService().query(sp); if (logger.isDebugEnabled()) logger.debug("harvest: prepare flipping: archiveAllowed=" + archiveAllowed + ", length=" + results.length()); // allow harvesting the archive if the workspace // has been done! // workspace is done if there are no more search // results if (results.length() == 0 && !archiveAllowed) { if (logger.isDebugEnabled()) logger.debug("harvest: flipping to archiveAllowed=true"); archiveAllowed = true; } letsContinue = stillContinueHarvesting(loopcount, results.length()); logger.debug("harvest: loopcount= " + loopcount + "\n" + "harvest: resultsize = " + results.length() + "\n" + "harvest: letsContinue = " + letsContinue + "\n" + "harvest: archiveAllow = " + archiveAllowed + "\n" + "harvest: tablename = " + tableName); SimpleDateFormat sdf = getSimpleDateFormat(); if (letsContinue) { Iterator<ResultSetRow> resultsIterator = results.iterator(); while (resultsIterator.hasNext()) { try { // be tolerant for non-existing // nodes... happens to hurt // leaving status=Running NodeRef result = resultsIterator.next().getNodeRef(); logger.debug("harvest noderef " + result); if (!storeRef.getProtocol().equalsIgnoreCase("archive")) { if (getNodeService().hasAspect(result, ContentModel.ASPECT_VERSIONABLE) // versionService.isVersioned(result) && versionService.getVersionHistory(result).getAllVersions() .size() > 1) { VersionHistory vh = versionService.getVersionHistory(result); Iterator<Version> vhi = vh.getAllVersions().iterator(); String latestVersionLabel = (String) nodeService.getProperty( vh.getHeadVersion().getVersionedNodeRef(), ContentModel.PROP_VERSION_LABEL); // Date latestDate = // (Date)nodeService.getProperty(result, // ContentModel.PROP_MODIFIED); while (vhi.hasNext()) { Version version = vhi.next(); String currentVersionLabel = version.getVersionLabel(); // Date versionDate = // version.getFrozenModifiedDate(); // logger.debug("comparing: // " + // currentVersionLabel + // "/" + // latestVersionLabel // );//+ " and " + // sdf.format(versionDate) // +"/"+ // sdf.format(latestDate)); if (!currentVersionLabel.equals(latestVersionLabel)) { if (logger.isInfoEnabled()) logger.info( "harvest: Adding Version " + currentVersionLabel + " " + version.getFrozenStateNodeRef() + " - " + result.toString()); // version.getVersionedNodeRef()); addToQueue(version.getFrozenStateNodeRef(), result); } else { if (logger.isDebugEnabled()) logger.info("Ignoring version " + currentVersionLabel); } // end ifelse } // end while } // id if // hasAspect(versionable) } // end exclude Archive // all versions should be post-fixed // with their head version workspace // ref if (!result.toString().startsWith("version")) { if (logger.isDebugEnabled()) logger.debug("harvest: " + " adding NodeRef " + result); addToQueue(result); } } catch (Exception e) { // ignore, we need to buffer for // non-existing nodes... logger.info("NodeRef appears broken: " + e.getMessage()); logger.info(" " + e.getStackTrace()); } } // end resultsIterator try { // process the current queue Properties props = processQueueDefinition(tableName); if (logger.isDebugEnabled()) logger.debug("harvest: queueDef done, setting tableDefinition"); setTableDefinition(tableName, props); if (logger.isDebugEnabled()) logger.debug("harvest: tableDef done. Processing queue Values"); processQueueValues(tableName); // prep the queue for the next run resetQueue(); if (results.length() > 0) { // prepare the dbid for the next run startDbId = Long.parseLong(String.valueOf(getNodeService().getProperty( results.getNodeRef(results.length() - 1), ContentModel.PROP_NODE_DBID))); lastModified = (Date) getNodeService().getProperty( results.getNodeRef(results.length() - 1), ContentModel.PROP_MODIFIED); if (logger.isDebugEnabled()) { logger.debug("harvest: StoreProtocol = " + storeRef.getProtocol()); logger.debug("harvest: New start DBID=" + startDbId); logger.debug("harvest: New lastModified=" + lastModified); } } } catch (Exception e) { logger.info("harvest: something wrong with the noderef, skipping"); } if ((results.length() > 0) && getBatchTimestampEnabled() && (lastModified != null)) { if (logger.isDebugEnabled()) logger.debug("Setting Batch-based timestamp: " + getDateAsFormattedString(lastModified)); dbhb.setLastTimestamp(tableName + "_" + storeRef.getProtocol().substring(0, 1), getDateAsFormattedString(lastModified)); hasEverRun = true; } } // end if(letsContinue) if ((!letsContinue) && (results.length() == 0)) { // register lastruntimestamp anyway if (hasEverRun) { dbhb.setAllStatusesDoneForTable(); } else { dbhb.setLastTimestampAndStatusDone( tableName + "_" + storeRef.getProtocol().substring(0, 1), nowFormattedDate); } } letsContinue = stillContinueHarvesting(loopcount, results.length()); } // end while letsContinue } // end storeProtocol if (getBatchTimestampEnabled()) { // dbhb.setLastTimestamp(tableName, // getDateAsFormattedString(lastModified)); if (lastModified != null) { if (logger.isDebugEnabled()) logger.debug("Setting Batch-based status to done"); dbhb.setAllStatusesDoneForTable(); } } else { if (logger.isDebugEnabled()) logger.debug("Setting end-last-run-based timestamp"); dbhb.setLastTimestampAndStatusDone(tableName, nowFormattedDate); } // startDbId=0; } // end if tableIsRunning else { if (logger.isDebugEnabled()) logger.debug("harvest: table is running; leaving..."); } } // end while keys } catch (Exception e) { // e.printStackTrace(); logger.info("Fatality: " + e); } finally { // make sure we gently close the connection dbhb.closeReportingConnection(); } logger.info("harvest run done..."); } private ArrayList<StoreRef> getStoreRefList() { String[] stores = reportingHelper.getGlobalProperties().getProperty(Constants.property_storelist, "") .split(","); ArrayList<StoreRef> storeRefArray = new ArrayList<StoreRef>(); for (String store : stores) { logger.debug("Adding store: " + store); StoreRef s = new StoreRef(store); storeRefArray.add(s); } return storeRefArray; } // Helper methods to build the queue and process the queue public String queryClauseTimestamp(final String language, final String timestamp, String protocol) { String dateQuery = " "; final String myTimestamp = timestamp.replaceAll(" ", "T"); if (SearchService.LANGUAGE_LUCENE.equalsIgnoreCase(language)) { if (protocol.equalsIgnoreCase(StoreRef.PROTOCOL_WORKSPACE)) { dateQuery += "AND @cm\\:modified:[" + myTimestamp + " TO NOW]"; } if (protocol.equalsIgnoreCase(StoreRef.PROTOCOL_ARCHIVE)) { dateQuery += "AND @sys\\:archivedDate:[" + myTimestamp + " TO NOW]"; } } if (SearchService.LANGUAGE_CMIS_ALFRESCO.equalsIgnoreCase(language)) { if (protocol.equalsIgnoreCase(StoreRef.PROTOCOL_WORKSPACE)) { // dateQuery += "AND @cm\\:modified:[" + myTimestamp + " TO // NOW]"; // TODO } if (protocol.equalsIgnoreCase(StoreRef.PROTOCOL_ARCHIVE)) { // dateQuery += "AND @sys\\:archivedDate:[" + myTimestamp + " TO // NOW]"; // TODO } } return dateQuery; } public String queryClauseOrderBy(final String language, final long dbid, final String protocol) { String orderBy = " "; if (SearchService.LANGUAGE_LUCENE.equalsIgnoreCase(language)) { if ((dbid > 0) // && (protocol.equalsIgnoreCase("workspace")) ) { orderBy += "AND @sys\\:node-dbid:[" + (dbid + 1) + " TO MAX]"; } } if (SearchService.LANGUAGE_CMIS_ALFRESCO.equalsIgnoreCase(language)) { // TODO } return orderBy; } public String getOrderBy(final String language) { String orderBy = " "; if (SearchService.LANGUAGE_LUCENE.equalsIgnoreCase(language)) { orderBy += ContentModel.PROP_NODE_DBID.toPrefixString();// "@sys\\:node-dbid"; // orderBy += "sys:node-dbid"; orderBy = QueryParser.escape(orderBy); } if (SearchService.LANGUAGE_CMIS_ALFRESCO.equalsIgnoreCase(language)) { // TODO } return orderBy; } // public String queryClauseGetStartAtDbid(String language, long startDbId){ // return ""; // } private Properties getTableQueries(final NodeRef nodeRef) { Properties p = new Properties(); if (logger.isDebugEnabled()) { logger.debug("getTableQueries, nodeRef=" + nodeRef); } try { ContentService cs = getContentService(); ContentReader contentReader = cs.getReader(nodeRef, ContentModel.PROP_CONTENT); p.load(contentReader.getContentInputStream()); } catch (ContentIOException e) { logger.error(e.getMessage()); // e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); logger.error(e.getMessage()); } return p; } }