diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/AclReport.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/AclReport.java index 510f93fb8..37ef5b536 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/AclReport.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/AclReport.java @@ -1,92 +1,92 @@ -package org.alfresco.solr; - -/** - * @author Andy - * - */ -public class AclReport -{ - - private Long aclId; - - private boolean existsInDb; - - private Long indexAclDoc; - - private Long indexAclTx; - private Long indexedAclDocCount; - - /** - * @return the aclId - */ - public Long getAclId() - { - return aclId; - } - - /** - * @param aclId the aclId to set - */ - public void setAclId(Long aclId) - { - this.aclId = aclId; - } - - /** - * @return the existsInDb - */ - public boolean isExistsInDb() - { - return existsInDb; - } - - /** - * @param existsInDb the existsInDb to set - */ - public void setExistsInDb(boolean existsInDb) - { - this.existsInDb = existsInDb; - } - - /** - * @return the indexAclDoc - */ - public Long getIndexAclDoc() - { - return indexAclDoc; - } - - /** - * @param indexAclDoc the indexAclDoc to set - */ - public void setIndexAclDoc(Long indexAclDoc) - { - this.indexAclDoc = indexAclDoc; - } - - /** - * @return the indexAclTx - */ - public Long getIndexAclTx() - { - return indexAclTx; - } - - /** - * @param indexAclTx the indexAclTx to set - */ - public void setIndexAclTx(Long indexAclTx) - { - this.indexAclTx = indexAclTx; - } - - public Long getIndexedAclDocCount() - { - return indexedAclDocCount; - } - - public void setIndexedAclDocCount(Long indexedAclDocCount) - { - this.indexedAclDocCount = indexedAclDocCount; - } -} +package org.alfresco.solr; + +/** + * @author Andy + * + */ +public class AclReport +{ + + private Long aclId; + + private boolean existsInDb; + + private Long indexAclDoc; + + private Long indexAclTx; + private Long indexedAclDocCount; + + /** + * @return the aclId + */ + public Long getAclId() + { + return aclId; + } + + /** + * @param aclId the aclId to set + */ + public void setAclId(Long aclId) + { + this.aclId = aclId; + } + + /** + * @return the existsInDb + */ + public boolean isExistsInDb() + { + return existsInDb; + } + + /** + * @param existsInDb the existsInDb to set + */ + public void setExistsInDb(boolean existsInDb) + { + this.existsInDb = existsInDb; + } + + /** + * @return the indexAclDoc + */ + public Long getIndexAclDoc() + { + return indexAclDoc; + } + + /** + * @param indexAclDoc the indexAclDoc to set + */ + public void setIndexAclDoc(Long indexAclDoc) + { + this.indexAclDoc = indexAclDoc; + } + + /** + * @return the indexAclTx + */ + public Long getIndexAclTx() + { + return indexAclTx; + } + + /** + * @param indexAclTx the indexAclTx to set + */ + public void setIndexAclTx(Long indexAclTx) + { + this.indexAclTx = indexAclTx; + } + + public Long getIndexedAclDocCount() + { + return indexedAclDocCount; + } + + public void setIndexedAclDocCount(Long indexedAclDocCount) + { + this.indexedAclDocCount = indexedAclDocCount; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/BoundedDeque.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/BoundedDeque.java index eebe53eb8..c52f9ee05 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/BoundedDeque.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/BoundedDeque.java @@ -1,61 +1,61 @@ - -package org.alfresco.solr; - -import java.util.Iterator; -import java.util.concurrent.LinkedBlockingDeque; - -public class BoundedDeque implements Iterable -{ - private LinkedBlockingDeque deque; - - private int max = 10; - - public BoundedDeque(int max) - { - this.max = max; - setDeque(new LinkedBlockingDeque()); - } - - /** - * @return int - */ - public int size() - { - return getDeque().size(); - } - - public void add(T add) - { - while (getDeque().size() > (max - 1)) - { - getDeque().removeLast(); - } - getDeque().addFirst(add); - } - - public T getLast() - { - return getDeque().getFirst(); - } - - /* - * (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - @Override - public Iterator iterator() - { - return getDeque().iterator(); - } - - public LinkedBlockingDeque getDeque() - { - return deque; - } - - public void setDeque(LinkedBlockingDeque deque) - { - this.deque = deque; - } - + +package org.alfresco.solr; + +import java.util.Iterator; +import java.util.concurrent.LinkedBlockingDeque; + +public class BoundedDeque implements Iterable +{ + private LinkedBlockingDeque deque; + + private int max = 10; + + public BoundedDeque(int max) + { + this.max = max; + setDeque(new LinkedBlockingDeque()); + } + + /** + * @return int + */ + public int size() + { + return getDeque().size(); + } + + public void add(T add) + { + while (getDeque().size() > (max - 1)) + { + getDeque().removeLast(); + } + getDeque().addFirst(add); + } + + public T getLast() + { + return getDeque().getFirst(); + } + + /* + * (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + @Override + public Iterator iterator() + { + return getDeque().iterator(); + } + + public LinkedBlockingDeque getDeque() + { + return deque; + } + + public void setDeque(LinkedBlockingDeque deque) + { + this.deque = deque; + } + } \ No newline at end of file diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/IndexTrackingShutdownException.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/IndexTrackingShutdownException.java index 0184b3f9a..062a6e589 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/IndexTrackingShutdownException.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/IndexTrackingShutdownException.java @@ -1,11 +1,11 @@ -package org.alfresco.solr; - -public class IndexTrackingShutdownException extends RuntimeException -{ - - /** - * - */ - private static final long serialVersionUID = -1294455847013444397L; - -} +package org.alfresco.solr; + +public class IndexTrackingShutdownException extends RuntimeException +{ + + /** + * + */ + private static final long serialVersionUID = -1294455847013444397L; + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/InformationServerCollectionProvider.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/InformationServerCollectionProvider.java index 14c35900b..bde7fc64b 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/InformationServerCollectionProvider.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/InformationServerCollectionProvider.java @@ -1,11 +1,11 @@ -package org.alfresco.solr; - -import org.alfresco.solr.adapters.IOpenBitSet; -import org.alfresco.solr.adapters.ISimpleOrderedMap; - -public interface InformationServerCollectionProvider -{ - IOpenBitSet getOpenBitSetInstance(); - - ISimpleOrderedMap getSimpleOrderedMapInstance(); -} +package org.alfresco.solr; + +import org.alfresco.solr.adapters.IOpenBitSet; +import org.alfresco.solr.adapters.ISimpleOrderedMap; + +public interface InformationServerCollectionProvider +{ + IOpenBitSet getOpenBitSetInstance(); + + ISimpleOrderedMap getSimpleOrderedMapInstance(); +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/NodeReport.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/NodeReport.java index 0d2dc9742..0e7cf0b70 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/NodeReport.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/NodeReport.java @@ -1,152 +1,152 @@ -package org.alfresco.solr; - -import org.alfresco.solr.client.Node.SolrApiNodeStatus; - -/** - * @author Andy - */ -public class NodeReport -{ - private Long dbid; - - private Long dbTx; - - private SolrApiNodeStatus dbNodeStatus; - - private Long indexLeafDoc; - - private Long indexAuxDoc; - - private Long indexLeafTx; - - private Long indexAuxTx; - private Long indexedNodeDocCount; - - - /** - * @return the dbid - */ - public Long getDbid() - { - return dbid; - } - - /** - * @param dbid - * the dbid to set - */ - public void setDbid(Long dbid) - { - this.dbid = dbid; - } - - /** - * @return the dbTx - */ - public Long getDbTx() - { - return dbTx; - } - - /** - * @param dbTx - * the dbTx to set - */ - public void setDbTx(Long dbTx) - { - this.dbTx = dbTx; - } - - /** - * @return the dbNodeStatus - */ - public SolrApiNodeStatus getDbNodeStatus() - { - return dbNodeStatus; - } - - /** - * @param dbNodeStatus - * the dbNodeStatus to set - */ - public void setDbNodeStatus(SolrApiNodeStatus dbNodeStatus) - { - this.dbNodeStatus = dbNodeStatus; - } - - /** - * @return the indexLeafDoc - */ - public Long getIndexLeafDoc() - { - return indexLeafDoc; - } - - /** - * @param indexLeafDoc - * the indexLeafDoc to set - */ - public void setIndexLeafDoc(Long indexLeafDoc) - { - this.indexLeafDoc = indexLeafDoc; - } - - /** - * @return the indexAuxDoc - */ - public Long getIndexAuxDoc() - { - return indexAuxDoc; - } - - /** - * @param indexAuxDoc - * the indexAuxDoc to set - */ - public void setIndexAuxDoc(Long indexAuxDoc) - { - this.indexAuxDoc = indexAuxDoc; - } - - /** - * @return the indexLeafTx - */ - public Long getIndexLeafTx() - { - return indexLeafTx; - } - - /** - * @param indexLeafTx the indexLeafTx to set - */ - public void setIndexLeafTx(Long indexLeafTx) - { - this.indexLeafTx = indexLeafTx; - } - - /** - * @return the indexAuxTx - */ - public Long getIndexAuxTx() - { - return indexAuxTx; - } - - /** - * @param indexAuxTx the indexAuxTx to set - */ - public void setIndexAuxTx(Long indexAuxTx) - { - this.indexAuxTx = indexAuxTx; - } - - public Long getIndexedNodeDocCount() - { - return indexedNodeDocCount; - } - - public void setIndexedNodeDocCount(Long indexedNodeDocCount) - { - this.indexedNodeDocCount = indexedNodeDocCount; - } -} +package org.alfresco.solr; + +import org.alfresco.solr.client.Node.SolrApiNodeStatus; + +/** + * @author Andy + */ +public class NodeReport +{ + private Long dbid; + + private Long dbTx; + + private SolrApiNodeStatus dbNodeStatus; + + private Long indexLeafDoc; + + private Long indexAuxDoc; + + private Long indexLeafTx; + + private Long indexAuxTx; + private Long indexedNodeDocCount; + + + /** + * @return the dbid + */ + public Long getDbid() + { + return dbid; + } + + /** + * @param dbid + * the dbid to set + */ + public void setDbid(Long dbid) + { + this.dbid = dbid; + } + + /** + * @return the dbTx + */ + public Long getDbTx() + { + return dbTx; + } + + /** + * @param dbTx + * the dbTx to set + */ + public void setDbTx(Long dbTx) + { + this.dbTx = dbTx; + } + + /** + * @return the dbNodeStatus + */ + public SolrApiNodeStatus getDbNodeStatus() + { + return dbNodeStatus; + } + + /** + * @param dbNodeStatus + * the dbNodeStatus to set + */ + public void setDbNodeStatus(SolrApiNodeStatus dbNodeStatus) + { + this.dbNodeStatus = dbNodeStatus; + } + + /** + * @return the indexLeafDoc + */ + public Long getIndexLeafDoc() + { + return indexLeafDoc; + } + + /** + * @param indexLeafDoc + * the indexLeafDoc to set + */ + public void setIndexLeafDoc(Long indexLeafDoc) + { + this.indexLeafDoc = indexLeafDoc; + } + + /** + * @return the indexAuxDoc + */ + public Long getIndexAuxDoc() + { + return indexAuxDoc; + } + + /** + * @param indexAuxDoc + * the indexAuxDoc to set + */ + public void setIndexAuxDoc(Long indexAuxDoc) + { + this.indexAuxDoc = indexAuxDoc; + } + + /** + * @return the indexLeafTx + */ + public Long getIndexLeafTx() + { + return indexLeafTx; + } + + /** + * @param indexLeafTx the indexLeafTx to set + */ + public void setIndexLeafTx(Long indexLeafTx) + { + this.indexLeafTx = indexLeafTx; + } + + /** + * @return the indexAuxTx + */ + public Long getIndexAuxTx() + { + return indexAuxTx; + } + + /** + * @param indexAuxTx the indexAuxTx to set + */ + public void setIndexAuxTx(Long indexAuxTx) + { + this.indexAuxTx = indexAuxTx; + } + + public Long getIndexedNodeDocCount() + { + return indexedNodeDocCount; + } + + public void setIndexedNodeDocCount(Long indexedNodeDocCount) + { + this.indexedNodeDocCount = indexedNodeDocCount; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/TrackerState.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/TrackerState.java index 4e4f7ae8c..84511ebe0 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/TrackerState.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/TrackerState.java @@ -1,276 +1,276 @@ - -package org.alfresco.solr; - -/** - * This class was moved from org.alfresco.solr.tracker.CoreTracker - * The data in this class is relevant for a particular Solr index. - */ -public class TrackerState -{ - private volatile long lastChangeSetIdOnServer; - - private volatile long lastChangeSetCommitTimeOnServer; - - private volatile long lastIndexedChangeSetId; - - private volatile long lastIndexedTxCommitTime = 0; - - private volatile long lastIndexedTxId = 0; - - private volatile long lastIndexedChangeSetCommitTime = 0; - - private volatile long lastTxCommitTimeOnServer = 0; - - private volatile long lastTxIdOnServer = 0; - - private volatile long lastIndexedTxIdBeforeHoles = -1; - - private volatile long lastIndexedChangeSetIdBeforeHoles = -1; - - private volatile boolean running = false; - - private volatile boolean checkedFirstTransactionTime = false; - private volatile boolean checkedFirstAclTransactionTime = false; - private volatile boolean checkedLastAclTransactionTime = false; - private volatile boolean checkedLastTransactionTime = false; - - private volatile boolean check = false; - - private long timeToStopIndexing; - - private long lastGoodChangeSetCommitTimeInIndex; - - private long lastGoodTxCommitTimeInIndex; - - private long timeBeforeWhichThereCanBeNoHoles; - - public long getLastChangeSetIdOnServer() - { - return lastChangeSetIdOnServer; - } - - public void setLastChangeSetIdOnServer(long lastChangeSetIdOnServer) - { - this.lastChangeSetIdOnServer = lastChangeSetIdOnServer; - } - - public long getLastChangeSetCommitTimeOnServer() - { - return lastChangeSetCommitTimeOnServer; - } - - public void setLastChangeSetCommitTimeOnServer(long lastChangeSetCommitTimeOnServer) - { - this.lastChangeSetCommitTimeOnServer = lastChangeSetCommitTimeOnServer; - } - - public long getLastIndexedChangeSetId() - { - return lastIndexedChangeSetId; - } - - public void setLastIndexedChangeSetId(long lastIndexedChangeSetId) - { - this.lastIndexedChangeSetId = lastIndexedChangeSetId; - } - - public long getLastIndexedTxCommitTime() - { - return lastIndexedTxCommitTime; - } - - public void setLastIndexedTxCommitTime(long lastIndexedTxCommitTime) - { - this.lastIndexedTxCommitTime = lastIndexedTxCommitTime; - } - - public long getLastIndexedTxId() - { - return lastIndexedTxId; - } - - public void setLastIndexedTxId(long lastIndexedTxId) - { - this.lastIndexedTxId = lastIndexedTxId; - } - - public long getLastIndexedChangeSetCommitTime() - { - return lastIndexedChangeSetCommitTime; - } - - public void setLastIndexedChangeSetCommitTime(long lastIndexedChangeSetCommitTime) - { - this.lastIndexedChangeSetCommitTime = lastIndexedChangeSetCommitTime; - } - - public long getLastTxCommitTimeOnServer() - { - return lastTxCommitTimeOnServer; - } - - public void setLastTxCommitTimeOnServer(long lastTxCommitTimeOnServer) - { - this.lastTxCommitTimeOnServer = lastTxCommitTimeOnServer; - } - - public long getLastTxIdOnServer() - { - return lastTxIdOnServer; - } - - public void setLastTxIdOnServer(long lastTxIdOnServer) - { - this.lastTxIdOnServer = lastTxIdOnServer; - } - - public long getLastIndexedTxIdBeforeHoles() - { - return lastIndexedTxIdBeforeHoles; - } - - public void setLastIndexedTxIdBeforeHoles(long lastIndexedTxIdBeforeHoles) - { - this.lastIndexedTxIdBeforeHoles = lastIndexedTxIdBeforeHoles; - } - - public long getLastIndexedChangeSetIdBeforeHoles() - { - return lastIndexedChangeSetIdBeforeHoles; - } - - public void setLastIndexedChangeSetIdBeforeHoles(long lastIndexedChangeSetIdBeforeHoles) - { - this.lastIndexedChangeSetIdBeforeHoles = lastIndexedChangeSetIdBeforeHoles; - } - - public boolean isRunning() - { - return running; - } - - public void setRunning(boolean running) - { - this.running = running; - } - - public boolean isCheckedFirstTransactionTime() - { - return checkedFirstTransactionTime; - } - - public void setCheckedFirstTransactionTime(boolean checkedFirstTransactionTime) - { - this.checkedFirstTransactionTime = checkedFirstTransactionTime; - } - - public boolean isCheck() - { - return check; - } - - public void setCheck(boolean check) - { - this.check = check; - } - - public long getTimeToStopIndexing() - { - return timeToStopIndexing; - } - - public void setTimeToStopIndexing(long timeToStopIndexing) - { - this.timeToStopIndexing = timeToStopIndexing; - } - - public long getLastGoodChangeSetCommitTimeInIndex() - { - return lastGoodChangeSetCommitTimeInIndex; - } - - public void setLastGoodChangeSetCommitTimeInIndex(long lastGoodChangeSetCommitTimeInIndex) - { - this.lastGoodChangeSetCommitTimeInIndex = lastGoodChangeSetCommitTimeInIndex; - } - - public long getLastGoodTxCommitTimeInIndex() - { - return lastGoodTxCommitTimeInIndex; - } - - public void setLastGoodTxCommitTimeInIndex(long lastGoodTxCommitTimeInIndex) - { - this.lastGoodTxCommitTimeInIndex = lastGoodTxCommitTimeInIndex; - } - - public long getTimeBeforeWhichThereCanBeNoHoles() - { - return timeBeforeWhichThereCanBeNoHoles; - } - - public void setTimeBeforeWhichThereCanBeNoHoles(long timeBeforeWhichThereCanBeNoHoles) - { - this.timeBeforeWhichThereCanBeNoHoles = timeBeforeWhichThereCanBeNoHoles; - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - return "TrackerState [lastChangeSetIdOnServer=" + lastChangeSetIdOnServer - + ", lastChangeSetCommitTimeOnServer=" + lastChangeSetCommitTimeOnServer - + ", lastIndexedChangeSetId=" + lastIndexedChangeSetId - + ", lastIndexedTxCommitTime=" + lastIndexedTxCommitTime - + ", lastIndexedTxId=" + lastIndexedTxId - + ", lastIndexedChangeSetCommitTime=" + lastIndexedChangeSetCommitTime - + ", lastTxCommitTimeOnServer=" + lastTxCommitTimeOnServer - + ", lastTxIdOnServer=" + lastTxIdOnServer - + ", lastIndexedTxIdBeforeHoles=" + lastIndexedTxIdBeforeHoles - + ", lastIndexedChangeSetIdBeforeHoles=" + lastIndexedChangeSetIdBeforeHoles - + ", running=" + running - + ", checkedFirstTransactionTime=" + checkedFirstTransactionTime - + ", checkedFirstAclTransactionTime=" + this.checkedFirstAclTransactionTime - + ", checkedLastTransactionTime=" + this.checkedLastTransactionTime - + ", checkedLastAclTransactionTime=" + this.checkedLastAclTransactionTime - + ", check=" + check - + ", timeToStopIndexing=" + timeToStopIndexing - + ", lastGoodChangeSetCommitTimeInIndex=" + lastGoodChangeSetCommitTimeInIndex - + ", lastGoodTxCommitTimeInIndex=" + lastGoodTxCommitTimeInIndex - + ", timeBeforeWhichThereCanBeNoHoles=" + timeBeforeWhichThereCanBeNoHoles + "]"; - } - - public boolean isCheckedFirstAclTransactionTime() - { - return checkedFirstAclTransactionTime; - } - - public void setCheckedFirstAclTransactionTime(boolean checkedFirstAclTransactionTime) - { - this.checkedFirstAclTransactionTime = checkedFirstAclTransactionTime; - } - - public boolean isCheckedLastTransactionTime() - { - return checkedLastTransactionTime; - } - - public void setCheckedLastTransactionTime(boolean checkedLastTransactionTime) - { - this.checkedLastTransactionTime = checkedLastTransactionTime; - } - - public boolean isCheckedLastAclTransactionTime() - { - return checkedLastAclTransactionTime; - } - - public void setCheckedLastAclTransactionTime(boolean checkedLastAclTransactionTime) - { - this.checkedLastAclTransactionTime = checkedLastAclTransactionTime; - } - -} + +package org.alfresco.solr; + +/** + * This class was moved from org.alfresco.solr.tracker.CoreTracker + * The data in this class is relevant for a particular Solr index. + */ +public class TrackerState +{ + private volatile long lastChangeSetIdOnServer; + + private volatile long lastChangeSetCommitTimeOnServer; + + private volatile long lastIndexedChangeSetId; + + private volatile long lastIndexedTxCommitTime = 0; + + private volatile long lastIndexedTxId = 0; + + private volatile long lastIndexedChangeSetCommitTime = 0; + + private volatile long lastTxCommitTimeOnServer = 0; + + private volatile long lastTxIdOnServer = 0; + + private volatile long lastIndexedTxIdBeforeHoles = -1; + + private volatile long lastIndexedChangeSetIdBeforeHoles = -1; + + private volatile boolean running = false; + + private volatile boolean checkedFirstTransactionTime = false; + private volatile boolean checkedFirstAclTransactionTime = false; + private volatile boolean checkedLastAclTransactionTime = false; + private volatile boolean checkedLastTransactionTime = false; + + private volatile boolean check = false; + + private long timeToStopIndexing; + + private long lastGoodChangeSetCommitTimeInIndex; + + private long lastGoodTxCommitTimeInIndex; + + private long timeBeforeWhichThereCanBeNoHoles; + + public long getLastChangeSetIdOnServer() + { + return lastChangeSetIdOnServer; + } + + public void setLastChangeSetIdOnServer(long lastChangeSetIdOnServer) + { + this.lastChangeSetIdOnServer = lastChangeSetIdOnServer; + } + + public long getLastChangeSetCommitTimeOnServer() + { + return lastChangeSetCommitTimeOnServer; + } + + public void setLastChangeSetCommitTimeOnServer(long lastChangeSetCommitTimeOnServer) + { + this.lastChangeSetCommitTimeOnServer = lastChangeSetCommitTimeOnServer; + } + + public long getLastIndexedChangeSetId() + { + return lastIndexedChangeSetId; + } + + public void setLastIndexedChangeSetId(long lastIndexedChangeSetId) + { + this.lastIndexedChangeSetId = lastIndexedChangeSetId; + } + + public long getLastIndexedTxCommitTime() + { + return lastIndexedTxCommitTime; + } + + public void setLastIndexedTxCommitTime(long lastIndexedTxCommitTime) + { + this.lastIndexedTxCommitTime = lastIndexedTxCommitTime; + } + + public long getLastIndexedTxId() + { + return lastIndexedTxId; + } + + public void setLastIndexedTxId(long lastIndexedTxId) + { + this.lastIndexedTxId = lastIndexedTxId; + } + + public long getLastIndexedChangeSetCommitTime() + { + return lastIndexedChangeSetCommitTime; + } + + public void setLastIndexedChangeSetCommitTime(long lastIndexedChangeSetCommitTime) + { + this.lastIndexedChangeSetCommitTime = lastIndexedChangeSetCommitTime; + } + + public long getLastTxCommitTimeOnServer() + { + return lastTxCommitTimeOnServer; + } + + public void setLastTxCommitTimeOnServer(long lastTxCommitTimeOnServer) + { + this.lastTxCommitTimeOnServer = lastTxCommitTimeOnServer; + } + + public long getLastTxIdOnServer() + { + return lastTxIdOnServer; + } + + public void setLastTxIdOnServer(long lastTxIdOnServer) + { + this.lastTxIdOnServer = lastTxIdOnServer; + } + + public long getLastIndexedTxIdBeforeHoles() + { + return lastIndexedTxIdBeforeHoles; + } + + public void setLastIndexedTxIdBeforeHoles(long lastIndexedTxIdBeforeHoles) + { + this.lastIndexedTxIdBeforeHoles = lastIndexedTxIdBeforeHoles; + } + + public long getLastIndexedChangeSetIdBeforeHoles() + { + return lastIndexedChangeSetIdBeforeHoles; + } + + public void setLastIndexedChangeSetIdBeforeHoles(long lastIndexedChangeSetIdBeforeHoles) + { + this.lastIndexedChangeSetIdBeforeHoles = lastIndexedChangeSetIdBeforeHoles; + } + + public boolean isRunning() + { + return running; + } + + public void setRunning(boolean running) + { + this.running = running; + } + + public boolean isCheckedFirstTransactionTime() + { + return checkedFirstTransactionTime; + } + + public void setCheckedFirstTransactionTime(boolean checkedFirstTransactionTime) + { + this.checkedFirstTransactionTime = checkedFirstTransactionTime; + } + + public boolean isCheck() + { + return check; + } + + public void setCheck(boolean check) + { + this.check = check; + } + + public long getTimeToStopIndexing() + { + return timeToStopIndexing; + } + + public void setTimeToStopIndexing(long timeToStopIndexing) + { + this.timeToStopIndexing = timeToStopIndexing; + } + + public long getLastGoodChangeSetCommitTimeInIndex() + { + return lastGoodChangeSetCommitTimeInIndex; + } + + public void setLastGoodChangeSetCommitTimeInIndex(long lastGoodChangeSetCommitTimeInIndex) + { + this.lastGoodChangeSetCommitTimeInIndex = lastGoodChangeSetCommitTimeInIndex; + } + + public long getLastGoodTxCommitTimeInIndex() + { + return lastGoodTxCommitTimeInIndex; + } + + public void setLastGoodTxCommitTimeInIndex(long lastGoodTxCommitTimeInIndex) + { + this.lastGoodTxCommitTimeInIndex = lastGoodTxCommitTimeInIndex; + } + + public long getTimeBeforeWhichThereCanBeNoHoles() + { + return timeBeforeWhichThereCanBeNoHoles; + } + + public void setTimeBeforeWhichThereCanBeNoHoles(long timeBeforeWhichThereCanBeNoHoles) + { + this.timeBeforeWhichThereCanBeNoHoles = timeBeforeWhichThereCanBeNoHoles; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "TrackerState [lastChangeSetIdOnServer=" + lastChangeSetIdOnServer + + ", lastChangeSetCommitTimeOnServer=" + lastChangeSetCommitTimeOnServer + + ", lastIndexedChangeSetId=" + lastIndexedChangeSetId + + ", lastIndexedTxCommitTime=" + lastIndexedTxCommitTime + + ", lastIndexedTxId=" + lastIndexedTxId + + ", lastIndexedChangeSetCommitTime=" + lastIndexedChangeSetCommitTime + + ", lastTxCommitTimeOnServer=" + lastTxCommitTimeOnServer + + ", lastTxIdOnServer=" + lastTxIdOnServer + + ", lastIndexedTxIdBeforeHoles=" + lastIndexedTxIdBeforeHoles + + ", lastIndexedChangeSetIdBeforeHoles=" + lastIndexedChangeSetIdBeforeHoles + + ", running=" + running + + ", checkedFirstTransactionTime=" + checkedFirstTransactionTime + + ", checkedFirstAclTransactionTime=" + this.checkedFirstAclTransactionTime + + ", checkedLastTransactionTime=" + this.checkedLastTransactionTime + + ", checkedLastAclTransactionTime=" + this.checkedLastAclTransactionTime + + ", check=" + check + + ", timeToStopIndexing=" + timeToStopIndexing + + ", lastGoodChangeSetCommitTimeInIndex=" + lastGoodChangeSetCommitTimeInIndex + + ", lastGoodTxCommitTimeInIndex=" + lastGoodTxCommitTimeInIndex + + ", timeBeforeWhichThereCanBeNoHoles=" + timeBeforeWhichThereCanBeNoHoles + "]"; + } + + public boolean isCheckedFirstAclTransactionTime() + { + return checkedFirstAclTransactionTime; + } + + public void setCheckedFirstAclTransactionTime(boolean checkedFirstAclTransactionTime) + { + this.checkedFirstAclTransactionTime = checkedFirstAclTransactionTime; + } + + public boolean isCheckedLastTransactionTime() + { + return checkedLastTransactionTime; + } + + public void setCheckedLastTransactionTime(boolean checkedLastTransactionTime) + { + this.checkedLastTransactionTime = checkedLastTransactionTime; + } + + public boolean isCheckedLastAclTransactionTime() + { + return checkedLastAclTransactionTime; + } + + public void setCheckedLastAclTransactionTime(boolean checkedLastAclTransactionTime) + { + this.checkedLastAclTransactionTime = checkedLastAclTransactionTime; + } + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/IOpenBitSet.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/IOpenBitSet.java index 30a34985d..24956ece0 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/IOpenBitSet.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/IOpenBitSet.java @@ -1,22 +1,22 @@ - -package org.alfresco.solr.adapters; - -/** - * The reason we have this interface is so that lucene-free dependent classes can be dependent on IOpenBitSet instead of the - * lucene-version-specific OpenBitSet. - * @author Ahmed Owian - */ -public interface IOpenBitSet -{ - - void set(long txid); - - void or(IOpenBitSet duplicatedTxInIndex); - - long nextSetBit(long l); - - long cardinality(); - - boolean get(long i); - + +package org.alfresco.solr.adapters; + +/** + * The reason we have this interface is so that lucene-free dependent classes can be dependent on IOpenBitSet instead of the + * lucene-version-specific OpenBitSet. + * @author Ahmed Owian + */ +public interface IOpenBitSet +{ + + void set(long txid); + + void or(IOpenBitSet duplicatedTxInIndex); + + long nextSetBit(long l); + + long cardinality(); + + boolean get(long i); + } \ No newline at end of file diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/ISimpleOrderedMap.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/ISimpleOrderedMap.java index 16aec3c77..caf51cc83 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/ISimpleOrderedMap.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/adapters/ISimpleOrderedMap.java @@ -1,14 +1,14 @@ -package org.alfresco.solr.adapters; - - -/** - * The reason we have this interface is so that lucene-free dependent classes can be dependent on ISimpleOrderedMap instead of the - * lucene-version-specific SimpleOrderedMap. - * @author Ahmed Owian - */ -public interface ISimpleOrderedMap -{ - - void add(String name, T val); - -} +package org.alfresco.solr.adapters; + + +/** + * The reason we have this interface is so that lucene-free dependent classes can be dependent on ISimpleOrderedMap instead of the + * lucene-version-specific SimpleOrderedMap. + * @author Ahmed Owian + */ +public interface ISimpleOrderedMap +{ + + void add(String name, T val); + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AclChangeSets.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AclChangeSets.java index 0ffc6efe0..1b979e3b8 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AclChangeSets.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AclChangeSets.java @@ -1,39 +1,39 @@ -package org.alfresco.solr.client; - -import java.util.List; - -/** - * @author Andy - * - */ -public class AclChangeSets -{ - private List aclChangeSets; - - private Long maxChangeSetCommitTime; - - private Long maxChangeSetId; - - AclChangeSets(List aclChangeSets, Long maxChangeSetCommitTime, Long maxChangeSetId) - { - this.aclChangeSets = aclChangeSets; - this.maxChangeSetCommitTime = maxChangeSetCommitTime; - this.maxChangeSetId = maxChangeSetId; - } - - public List getAclChangeSets() - { - return aclChangeSets; - } - - public Long getMaxChangeSetCommitTime() - { - return maxChangeSetCommitTime; - } - - public Long getMaxChangeSetId() - { - return maxChangeSetId; - } - -} +package org.alfresco.solr.client; + +import java.util.List; + +/** + * @author Andy + * + */ +public class AclChangeSets +{ + private List aclChangeSets; + + private Long maxChangeSetCommitTime; + + private Long maxChangeSetId; + + AclChangeSets(List aclChangeSets, Long maxChangeSetCommitTime, Long maxChangeSetId) + { + this.aclChangeSets = aclChangeSets; + this.maxChangeSetCommitTime = maxChangeSetCommitTime; + this.maxChangeSetId = maxChangeSetId; + } + + public List getAclChangeSets() + { + return aclChangeSets; + } + + public Long getMaxChangeSetCommitTime() + { + return maxChangeSetCommitTime; + } + + public Long getMaxChangeSetId() + { + return maxChangeSetId; + } + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModel.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModel.java index 956642bff..c8126e70a 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModel.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModel.java @@ -1,55 +1,55 @@ -package org.alfresco.solr.client; - -import org.alfresco.repo.dictionary.M2Model; - -/** - * Represents an alfresco model and checksum. - * - * @since 4.0 - */ -public class AlfrescoModel -{ - private M2Model model; - private Long checksum; - - public AlfrescoModel(M2Model model, Long checksum) - { - this.model = model; - this.checksum = checksum; - } - - public M2Model getModel() - { - return model; - } - - public Long getChecksum() - { - return checksum; - } - - public boolean equals(Object other) - { - if (this == other) - { - return true; - } - - if(!(other instanceof AlfrescoModel)) - { - return false; - } - - AlfrescoModel model = (AlfrescoModel)other; - return (this.model.getName().equals(model.getModel().getName()) && - checksum.equals(model.getChecksum())); - } - - public int hashcode() - { - int result = 17; - result = 31 * result + model.hashCode(); - result = 31 * result + Long.valueOf(checksum).hashCode(); - return result; - } -} +package org.alfresco.solr.client; + +import org.alfresco.repo.dictionary.M2Model; + +/** + * Represents an alfresco model and checksum. + * + * @since 4.0 + */ +public class AlfrescoModel +{ + private M2Model model; + private Long checksum; + + public AlfrescoModel(M2Model model, Long checksum) + { + this.model = model; + this.checksum = checksum; + } + + public M2Model getModel() + { + return model; + } + + public Long getChecksum() + { + return checksum; + } + + public boolean equals(Object other) + { + if (this == other) + { + return true; + } + + if(!(other instanceof AlfrescoModel)) + { + return false; + } + + AlfrescoModel model = (AlfrescoModel)other; + return (this.model.getName().equals(model.getModel().getName()) && + checksum.equals(model.getChecksum())); + } + + public int hashcode() + { + int result = 17; + result = 31 * result + model.hashCode(); + result = 31 * result + Long.valueOf(checksum).hashCode(); + return result; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModelDiff.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModelDiff.java index 735543dbe..b18e634c1 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModelDiff.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/AlfrescoModelDiff.java @@ -1,78 +1,78 @@ -package org.alfresco.solr.client; - -import org.alfresco.service.namespace.QName; - -/** - * Represents a diff between the set of current repository Alfresco models and the set maintained in SOLR. - * The diff can represent a new, changed or removed Alfresco model. For a new model the newChecksum is - * populated; for a changed model both checksums are populated; for a removed model neither checksum is populated. - * - * @since 4.0 - */ -public class AlfrescoModelDiff -{ - public static enum TYPE - { - NEW, CHANGED, REMOVED; - }; - - private QName modelName; - private TYPE type; - private Long oldChecksum; - private Long newChecksum; - - public AlfrescoModelDiff(QName modelName, TYPE type, Long oldChecksum, Long newChecksum) - { - super(); - this.modelName = modelName; - this.type = type; - this.oldChecksum = oldChecksum; - this.newChecksum = newChecksum; - } - - public QName getModelName() - { - return modelName; - } - - public TYPE getType() - { - return type; - } - - public Long getOldChecksum() - { - return oldChecksum; - } - - public Long getNewChecksum() - { - return newChecksum; - } - - public boolean equals(Object other) - { - if(this == other) - { - return true; - } - if(!(other instanceof AlfrescoModelDiff)) - { - return false; - } - AlfrescoModelDiff diff = (AlfrescoModelDiff)other; - return(diff.getModelName().equals(getModelName()) && - diff.getType().equals(getType()) && - diff.getOldChecksum().equals(getOldChecksum()) && - diff.getNewChecksum().equals(getNewChecksum())); - } - - public int hashcode() - { - int result = 17; - result = 31 * result + getModelName().hashCode(); - result = 31 * result + getType().hashCode(); - result = 31 * result + (int)(getOldChecksum().longValue() ^ (getOldChecksum().longValue() >>> 32)); - return result; - } -} +package org.alfresco.solr.client; + +import org.alfresco.service.namespace.QName; + +/** + * Represents a diff between the set of current repository Alfresco models and the set maintained in SOLR. + * The diff can represent a new, changed or removed Alfresco model. For a new model the newChecksum is + * populated; for a changed model both checksums are populated; for a removed model neither checksum is populated. + * + * @since 4.0 + */ +public class AlfrescoModelDiff +{ + public static enum TYPE + { + NEW, CHANGED, REMOVED; + }; + + private QName modelName; + private TYPE type; + private Long oldChecksum; + private Long newChecksum; + + public AlfrescoModelDiff(QName modelName, TYPE type, Long oldChecksum, Long newChecksum) + { + super(); + this.modelName = modelName; + this.type = type; + this.oldChecksum = oldChecksum; + this.newChecksum = newChecksum; + } + + public QName getModelName() + { + return modelName; + } + + public TYPE getType() + { + return type; + } + + public Long getOldChecksum() + { + return oldChecksum; + } + + public Long getNewChecksum() + { + return newChecksum; + } + + public boolean equals(Object other) + { + if(this == other) + { + return true; + } + if(!(other instanceof AlfrescoModelDiff)) + { + return false; + } + AlfrescoModelDiff diff = (AlfrescoModelDiff)other; + return(diff.getModelName().equals(getModelName()) && + diff.getType().equals(getType()) && + diff.getOldChecksum().equals(getOldChecksum()) && + diff.getNewChecksum().equals(getNewChecksum())); + } + + public int hashcode() + { + int result = 17; + result = 31 * result + getModelName().hashCode(); + result = 31 * result + getType().hashCode(); + result = 31 * result + (int)(getOldChecksum().longValue() ^ (getOldChecksum().longValue() >>> 32)); + return result; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/ContentPropertyValue.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/ContentPropertyValue.java index f18b362db..46b3ff1ca 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/ContentPropertyValue.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/ContentPropertyValue.java @@ -1,59 +1,59 @@ -package org.alfresco.solr.client; - -import java.util.Locale; - -/** - * Represents a content property value, including locale, length, content id, encoding, mime type - * - * @since 4.0 - */ -public class ContentPropertyValue extends PropertyValue -{ - private Locale locale; - private long length; - private String encoding; - private String mimetype; - private Long id; - - public ContentPropertyValue(Locale locale, long length, String encoding, String mimetype, Long id) - { - super(); - this.locale = locale; - this.length = length; - this.encoding = encoding; - this.mimetype = mimetype; - this.id = id; - } - - public String getEncoding() - { - return encoding; - } - - public String getMimetype() - { - return mimetype; - } - - public Locale getLocale() - { - return locale; - } - - public long getLength() - { - return length; - } - - public Long getId() - { - return id; - } - - @Override - public String toString() - { - return "ContentPropertyValue [locale=" + locale + ", length=" + length + ", encoding=" - + encoding + ", mimetype=" + mimetype + ", id="+id+"]"; - } -} +package org.alfresco.solr.client; + +import java.util.Locale; + +/** + * Represents a content property value, including locale, length, content id, encoding, mime type + * + * @since 4.0 + */ +public class ContentPropertyValue extends PropertyValue +{ + private Locale locale; + private long length; + private String encoding; + private String mimetype; + private Long id; + + public ContentPropertyValue(Locale locale, long length, String encoding, String mimetype, Long id) + { + super(); + this.locale = locale; + this.length = length; + this.encoding = encoding; + this.mimetype = mimetype; + this.id = id; + } + + public String getEncoding() + { + return encoding; + } + + public String getMimetype() + { + return mimetype; + } + + public Locale getLocale() + { + return locale; + } + + public long getLength() + { + return length; + } + + public Long getId() + { + return id; + } + + @Override + public String toString() + { + return "ContentPropertyValue [locale=" + locale + ", length=" + length + ", encoding=" + + encoding + ", mimetype=" + mimetype + ", id="+id+"]"; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/GetNodesParameters.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/GetNodesParameters.java index 8bbfbee79..789e84b57 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/GetNodesParameters.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/GetNodesParameters.java @@ -1,122 +1,122 @@ -package org.alfresco.solr.client; - -import java.util.List; -import java.util.Set; - -import org.alfresco.service.namespace.QName; - -/** - * Query parameters for fetching nodes. - * - * @since 4.0 - */ -public class GetNodesParameters -{ - private List transactionIds; - private Long fromNodeId; - private Long toNodeId; - - private String storeProtocol; - private String storeIdentifier; - - private Set includeNodeTypes; - private Set excludeNodeTypes; - - private Set includeAspects; - private Set excludeAspects; - - public boolean getStoreFilter() - { - return (storeProtocol != null || storeIdentifier != null); - } - - public void setStoreProtocol(String storeProtocol) - { - this.storeProtocol = storeProtocol; - } - - public String getStoreProtocol() - { - return storeProtocol; - } - - public void setStoreIdentifier(String storeIdentifier) - { - this.storeIdentifier = storeIdentifier; - } - - public String getStoreIdentifier() - { - return storeIdentifier; - } - - public void setTransactionIds(List txnIds) - { - this.transactionIds = txnIds; - } - - public List getTransactionIds() - { - return transactionIds; - } - - public Long getFromNodeId() - { - return fromNodeId; - } - - public void setFromNodeId(Long fromNodeId) - { - this.fromNodeId = fromNodeId; - } - - public Long getToNodeId() - { - return toNodeId; - } - - public void setToNodeId(Long toNodeId) - { - this.toNodeId = toNodeId; - } - - public Set getIncludeNodeTypes() - { - return includeNodeTypes; - } - - public Set getExcludeNodeTypes() - { - return excludeNodeTypes; - } - - public Set getIncludeAspects() - { - return includeAspects; - } - - public Set getExcludeAspects() - { - return excludeAspects; - } - - public void setIncludeNodeTypes(Set includeNodeTypes) - { - this.includeNodeTypes = includeNodeTypes; - } - - public void setExcludeNodeTypes(Set excludeNodeTypes) - { - this.excludeNodeTypes = excludeNodeTypes; - } - - public void setIncludeAspects(Set includeAspects) - { - this.includeAspects = includeAspects; - } - - public void setExcludeAspects(Set excludeAspects) - { - this.excludeAspects = excludeAspects; - } -} +package org.alfresco.solr.client; + +import java.util.List; +import java.util.Set; + +import org.alfresco.service.namespace.QName; + +/** + * Query parameters for fetching nodes. + * + * @since 4.0 + */ +public class GetNodesParameters +{ + private List transactionIds; + private Long fromNodeId; + private Long toNodeId; + + private String storeProtocol; + private String storeIdentifier; + + private Set includeNodeTypes; + private Set excludeNodeTypes; + + private Set includeAspects; + private Set excludeAspects; + + public boolean getStoreFilter() + { + return (storeProtocol != null || storeIdentifier != null); + } + + public void setStoreProtocol(String storeProtocol) + { + this.storeProtocol = storeProtocol; + } + + public String getStoreProtocol() + { + return storeProtocol; + } + + public void setStoreIdentifier(String storeIdentifier) + { + this.storeIdentifier = storeIdentifier; + } + + public String getStoreIdentifier() + { + return storeIdentifier; + } + + public void setTransactionIds(List txnIds) + { + this.transactionIds = txnIds; + } + + public List getTransactionIds() + { + return transactionIds; + } + + public Long getFromNodeId() + { + return fromNodeId; + } + + public void setFromNodeId(Long fromNodeId) + { + this.fromNodeId = fromNodeId; + } + + public Long getToNodeId() + { + return toNodeId; + } + + public void setToNodeId(Long toNodeId) + { + this.toNodeId = toNodeId; + } + + public Set getIncludeNodeTypes() + { + return includeNodeTypes; + } + + public Set getExcludeNodeTypes() + { + return excludeNodeTypes; + } + + public Set getIncludeAspects() + { + return includeAspects; + } + + public Set getExcludeAspects() + { + return excludeAspects; + } + + public void setIncludeNodeTypes(Set includeNodeTypes) + { + this.includeNodeTypes = includeNodeTypes; + } + + public void setExcludeNodeTypes(Set excludeNodeTypes) + { + this.excludeNodeTypes = excludeNodeTypes; + } + + public void setIncludeAspects(Set includeAspects) + { + this.includeAspects = includeAspects; + } + + public void setExcludeAspects(Set excludeAspects) + { + this.excludeAspects = excludeAspects; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MLTextPropertyValue.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MLTextPropertyValue.java index ae76530f5..142b49a20 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MLTextPropertyValue.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MLTextPropertyValue.java @@ -1,54 +1,54 @@ -package org.alfresco.solr.client; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -/** - * Represents a multi-lingual property value, comprising a map from locale to string value - * - * @since 4.0 - */ -public class MLTextPropertyValue extends PropertyValue -{ - private Map values; - - public MLTextPropertyValue() - { - super(); - values = new HashMap(10); - } - - public MLTextPropertyValue(Map values) - { - super(); - this.values = values; - } - - public void addValue(Locale locale, String value) - { - values.put(locale, value); - } - - public Map getValues() - { - return values; - } - - public Set getLocales() - { - return values.keySet(); - } - - public String getValue(Locale locale) - { - return values.get(locale); - } - - @Override - public String toString() - { - return "MLTextPropertyValue [values=" + values + "]"; - } -} +package org.alfresco.solr.client; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +/** + * Represents a multi-lingual property value, comprising a map from locale to string value + * + * @since 4.0 + */ +public class MLTextPropertyValue extends PropertyValue +{ + private Map values; + + public MLTextPropertyValue() + { + super(); + values = new HashMap(10); + } + + public MLTextPropertyValue(Map values) + { + super(); + this.values = values; + } + + public void addValue(Locale locale, String value) + { + values.put(locale, value); + } + + public Map getValues() + { + return values; + } + + public Set getLocales() + { + return values.keySet(); + } + + public String getValue(Locale locale) + { + return values.get(locale); + } + + @Override + public String toString() + { + return "MLTextPropertyValue [values=" + values + "]"; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MultiPropertyValue.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MultiPropertyValue.java index 1a841340c..a2388367f 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MultiPropertyValue.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/MultiPropertyValue.java @@ -1,42 +1,42 @@ -package org.alfresco.solr.client; - -import java.util.ArrayList; -import java.util.List; - -/** - * Represents a multi property value, comprising a list of other property values - * - * @since 4.0 - */ -public class MultiPropertyValue extends PropertyValue -{ - private List values; - - public MultiPropertyValue() - { - super(); - this.values = new ArrayList(10); - } - - public MultiPropertyValue(List values) - { - super(); - this.values = values; - } - - public void addValue(PropertyValue value) - { - values.add(value); - } - - public List getValues() - { - return values; - } - - @Override - public String toString() - { - return "MultiPropertyValue [values=" + values + "]"; - } -} +package org.alfresco.solr.client; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a multi property value, comprising a list of other property values + * + * @since 4.0 + */ +public class MultiPropertyValue extends PropertyValue +{ + private List values; + + public MultiPropertyValue() + { + super(); + this.values = new ArrayList(10); + } + + public MultiPropertyValue(List values) + { + super(); + this.values = values; + } + + public void addValue(PropertyValue value) + { + values.add(value); + } + + public List getValues() + { + return values; + } + + @Override + public String toString() + { + return "MultiPropertyValue [values=" + values + "]"; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Node.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Node.java index 677d4f005..c3ffd4ca2 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Node.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Node.java @@ -1,86 +1,86 @@ -package org.alfresco.solr.client; - -public class Node -{ - public static enum SolrApiNodeStatus - { - UPDATED, DELETED, UNKNOWN, NON_SHARD_DELETED, NON_SHARD_UPDATED; - }; - - private long id; - private String nodeRef; - private long txnId; - private SolrApiNodeStatus status; - private String tenant; - private long aclId; - - public long getId() - { - return id; - } - public void setId(long id) - { - this.id = id; - } - public String getNodeRef() - { - return nodeRef; - } - public void setNodeRef(String nodeRef) - { - this.nodeRef = nodeRef; - } - public long getTxnId() - { - return txnId; - } - public void setTxnId(long txnId) - { - this.txnId = txnId; - } - public SolrApiNodeStatus getStatus() - { - return status; - } - public void setStatus(SolrApiNodeStatus status) - { - this.status = status; - } - /** - * @return the tenant - */ - public String getTenant() - { - return tenant; - } - /** - * @param tenant the tenant to set - */ - public void setTenant(String tenant) - { - this.tenant = tenant; - } - /** - * @return the aclId - */ - public long getAclId() - { - return aclId; - } - /** - * @param aclId the aclId to set - */ - public void setAclId(long aclId) - { - this.aclId = aclId; - } - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - return "Node [id=" + id + ", nodeRef=" + nodeRef + ", txnId=" + txnId + ", status=" + status + ", tenant=" + tenant + ", aclId=" + aclId + "]"; - } - -} +package org.alfresco.solr.client; + +public class Node +{ + public static enum SolrApiNodeStatus + { + UPDATED, DELETED, UNKNOWN, NON_SHARD_DELETED, NON_SHARD_UPDATED; + }; + + private long id; + private String nodeRef; + private long txnId; + private SolrApiNodeStatus status; + private String tenant; + private long aclId; + + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public String getNodeRef() + { + return nodeRef; + } + public void setNodeRef(String nodeRef) + { + this.nodeRef = nodeRef; + } + public long getTxnId() + { + return txnId; + } + public void setTxnId(long txnId) + { + this.txnId = txnId; + } + public SolrApiNodeStatus getStatus() + { + return status; + } + public void setStatus(SolrApiNodeStatus status) + { + this.status = status; + } + /** + * @return the tenant + */ + public String getTenant() + { + return tenant; + } + /** + * @param tenant the tenant to set + */ + public void setTenant(String tenant) + { + this.tenant = tenant; + } + /** + * @return the aclId + */ + public long getAclId() + { + return aclId; + } + /** + * @param aclId the aclId to set + */ + public void setAclId(long aclId) + { + this.aclId = aclId; + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "Node [id=" + id + ", nodeRef=" + nodeRef + ", txnId=" + txnId + ", status=" + status + ", tenant=" + tenant + ", aclId=" + aclId + "]"; + } + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaData.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaData.java index 947d5de03..4e08de8e6 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaData.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaData.java @@ -1,181 +1,181 @@ -package org.alfresco.solr.client; - -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.Pair; - -/** - * SOLR-side representation of node metadata information. - * - * @since 4.0 - */ -public class NodeMetaData -{ - private long id; - private NodeRef nodeRef; - private QName type; - private long aclId; - private Map properties; - private Set aspects; - private List> paths; - private List> namePaths; - private long parentAssocsCrc; - private List parentAssocs; - private List childAssocs; - private List childIds; - private String owner; - private long txnId; - private Set ancestors; - private String tenantDomain; - - public long getId() - { - return id; - } - public void setId(long id) - { - this.id = id; - } - public NodeRef getNodeRef() - { - return nodeRef; - } - public void setNodeRef(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - } - public QName getType() - { - return type; - } - public void setType(QName type) - { - this.type = type; - } - public long getAclId() - { - return aclId; - } - public void setAclId(long aclId) - { - this.aclId = aclId; - } - - /** - * A property value is either null or a subclass of PropertyValue - */ - public Map getProperties() - { - return properties; - } - public void setProperties(Map properties) - { - this.properties = properties; - } - public Set getAspects() - { - return aspects; - } - public void setAspects(Set aspects) - { - this.aspects = aspects; - } - public List> getPaths() - { - return paths; - } - public void setPaths(List> paths) - { - this.paths = paths; - } - - public List> getNamePaths() - { - return namePaths; - } - - public void setNamePaths(List> namePaths) - { - this.namePaths = namePaths; - } - public void setParentAssocsCrc(long parentAssocsCrc) - { - this.parentAssocsCrc = parentAssocsCrc; - } - public long getParentAssocsCrc() - { - return parentAssocsCrc; - } - public void setParentAssocs(List parentAssocs) - { - this.parentAssocs = parentAssocs; - } - public List getParentAssocs() - { - return parentAssocs; - } - public void setChildAssocs(List childAssocs) - { - this.childAssocs = childAssocs; - } - public List getChildAssocs() - { - return childAssocs; - } - public List getChildIds() - { - return childIds; - } - public void setChildIds(List childIds) - { - this.childIds = childIds; - } - - public String getOwner() - { - return owner; - } - public void setOwner(String owner) - { - this.owner = owner; - } - - public long getTxnId() - { - return txnId; - } - public void setTxnId(long txnId) - { - this.txnId = txnId; - } - public Set getAncestors() - { - return ancestors; - } - public void setAncestors(Set ancestors) - { - this.ancestors = ancestors; - } - public String getTenantDomain() - { - return tenantDomain; - } - public void setTenantDomain(String tenantDomain) - { - this.tenantDomain = tenantDomain; - } - - @Override - public String toString() - { - return "NodeMetaData [id=" - + id + ", nodeRef=" + nodeRef + ", type=" + type + ", aclId=" + aclId + ", properties=" + properties + ", aspects=" + aspects + ", paths=" + paths - + ", parentAssocsCrc=" + parentAssocsCrc + ", parentAssocs=" + parentAssocs + ", childAssocs=" + childAssocs + ", childIds=" + childIds + ", owner=" + owner - + ", txnId=" + txnId + ", ancestors=" + ancestors + ", tenantDomain=" + tenantDomain + "]"; - } -} +package org.alfresco.solr.client; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.Pair; + +/** + * SOLR-side representation of node metadata information. + * + * @since 4.0 + */ +public class NodeMetaData +{ + private long id; + private NodeRef nodeRef; + private QName type; + private long aclId; + private Map properties; + private Set aspects; + private List> paths; + private List> namePaths; + private long parentAssocsCrc; + private List parentAssocs; + private List childAssocs; + private List childIds; + private String owner; + private long txnId; + private Set ancestors; + private String tenantDomain; + + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public NodeRef getNodeRef() + { + return nodeRef; + } + public void setNodeRef(NodeRef nodeRef) + { + this.nodeRef = nodeRef; + } + public QName getType() + { + return type; + } + public void setType(QName type) + { + this.type = type; + } + public long getAclId() + { + return aclId; + } + public void setAclId(long aclId) + { + this.aclId = aclId; + } + + /** + * A property value is either null or a subclass of PropertyValue + */ + public Map getProperties() + { + return properties; + } + public void setProperties(Map properties) + { + this.properties = properties; + } + public Set getAspects() + { + return aspects; + } + public void setAspects(Set aspects) + { + this.aspects = aspects; + } + public List> getPaths() + { + return paths; + } + public void setPaths(List> paths) + { + this.paths = paths; + } + + public List> getNamePaths() + { + return namePaths; + } + + public void setNamePaths(List> namePaths) + { + this.namePaths = namePaths; + } + public void setParentAssocsCrc(long parentAssocsCrc) + { + this.parentAssocsCrc = parentAssocsCrc; + } + public long getParentAssocsCrc() + { + return parentAssocsCrc; + } + public void setParentAssocs(List parentAssocs) + { + this.parentAssocs = parentAssocs; + } + public List getParentAssocs() + { + return parentAssocs; + } + public void setChildAssocs(List childAssocs) + { + this.childAssocs = childAssocs; + } + public List getChildAssocs() + { + return childAssocs; + } + public List getChildIds() + { + return childIds; + } + public void setChildIds(List childIds) + { + this.childIds = childIds; + } + + public String getOwner() + { + return owner; + } + public void setOwner(String owner) + { + this.owner = owner; + } + + public long getTxnId() + { + return txnId; + } + public void setTxnId(long txnId) + { + this.txnId = txnId; + } + public Set getAncestors() + { + return ancestors; + } + public void setAncestors(Set ancestors) + { + this.ancestors = ancestors; + } + public String getTenantDomain() + { + return tenantDomain; + } + public void setTenantDomain(String tenantDomain) + { + this.tenantDomain = tenantDomain; + } + + @Override + public String toString() + { + return "NodeMetaData [id=" + + id + ", nodeRef=" + nodeRef + ", type=" + type + ", aclId=" + aclId + ", properties=" + properties + ", aspects=" + aspects + ", paths=" + paths + + ", parentAssocsCrc=" + parentAssocsCrc + ", parentAssocs=" + parentAssocs + ", childAssocs=" + childAssocs + ", childIds=" + childIds + ", owner=" + owner + + ", txnId=" + txnId + ", ancestors=" + ancestors + ", tenantDomain=" + tenantDomain + "]"; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaDataParameters.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaDataParameters.java index ab45aaa07..aff4072b7 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaDataParameters.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/NodeMetaDataParameters.java @@ -1,215 +1,215 @@ -package org.alfresco.solr.client; - -import java.util.List; - -/** - * Stores node meta data query parameters for use in SOLR remote api calls - * - * @since 4.0 - */ -public class NodeMetaDataParameters -{ - private List transactionIds; - private Long fromTxnId; - private Long toTxnId; - - // default is 'all' results - private int maxResults = 0; - - private Long fromNodeId; - private Long toNodeId; - private List nodeIds; - - private boolean includeAclId = true; - private boolean includeAspects = true; - private boolean includeNodeRef = true; - private boolean includeOwner = true; - private boolean includeProperties = true; - private boolean includePaths = true; - private boolean includeType = true; - private boolean includeChildAssociations = true; - private boolean includeParentAssociations = true; - private boolean includeChildIds = true; - private boolean includeTxnId = true; - - public boolean isIncludeAclId() - { - return includeAclId; - } - - public void setIncludeAclId(boolean includeAclId) - { - this.includeAclId = includeAclId; - } - - public boolean isIncludeAspects() - { - return includeAspects; - } - - public void setIncludeAspects(boolean includeAspects) - { - this.includeAspects = includeAspects; - } - - public boolean isIncludeNodeRef() - { - return includeNodeRef; - } - - public void setIncludeNodeRef(boolean includeNodeRef) - { - this.includeNodeRef = includeNodeRef; - } - - public boolean isIncludeOwner() - { - return includeOwner; - } - - public void setIncludeOwner(boolean includeOwner) - { - this.includeOwner = includeOwner; - } - - public boolean isIncludeProperties() - { - return includeProperties; - } - - public void setIncludeProperties(boolean includeProperties) - { - this.includeProperties = includeProperties; - } - - public boolean isIncludePaths() - { - return includePaths; - } - - public void setIncludePaths(boolean includePaths) - { - this.includePaths = includePaths; - } - - public boolean isIncludeType() - { - return includeType; - } - - public void setIncludeType(boolean includeType) - { - this.includeType = includeType; - } - - public boolean isIncludeChildAssociations() - { - return includeChildAssociations; - } - - public void setIncludeChildAssociations(boolean includeChildAssociations) - { - this.includeChildAssociations = includeChildAssociations; - } - - public boolean isIncludeParentAssociations() - { - return includeParentAssociations; - } - - public void setIncludeParentAssociations(boolean includeParentAssociations) - { - this.includeParentAssociations = includeParentAssociations; - } - - public int getMaxResults() - { - return maxResults; - } - - public void setMaxResults(int maxResults) - { - this.maxResults = maxResults; - } - - public List getNodeIds() - { - return nodeIds; - } - - public void setNodeIds(List nodeIds) - { - this.nodeIds = nodeIds; - } - - public void setTransactionIds(List txnIds) - { - this.transactionIds = txnIds; - } - - public List getTransactionIds() - { - return transactionIds; - } - - public Long getFromTxnId() - { - return fromTxnId; - } - - public void setFromTxnId(Long fromTxnId) - { - this.fromTxnId = fromTxnId; - } - - public Long getToTxnId() - { - return toTxnId; - } - - public void setToTxnId(Long toTxnId) - { - this.toTxnId = toTxnId; - } - - public Long getFromNodeId() - { - return fromNodeId; - } - - public void setFromNodeId(Long fromNodeId) - { - this.fromNodeId = fromNodeId; - } - - public Long getToNodeId() - { - return toNodeId; - } - - public void setToNodeId(Long toNodeId) - { - this.toNodeId = toNodeId; - } - - public boolean isIncludeChildIds() - { - return includeChildIds; - } - - public void setIncludeChildIds(boolean includeChildIds) - { - this.includeChildIds = includeChildIds; - } - - public boolean isIncludeTxnId() - { - return includeTxnId; - } - - public void setIncludeTxnId(boolean includeTxnId) - { - this.includeTxnId = includeTxnId; - } - -} +package org.alfresco.solr.client; + +import java.util.List; + +/** + * Stores node meta data query parameters for use in SOLR remote api calls + * + * @since 4.0 + */ +public class NodeMetaDataParameters +{ + private List transactionIds; + private Long fromTxnId; + private Long toTxnId; + + // default is 'all' results + private int maxResults = 0; + + private Long fromNodeId; + private Long toNodeId; + private List nodeIds; + + private boolean includeAclId = true; + private boolean includeAspects = true; + private boolean includeNodeRef = true; + private boolean includeOwner = true; + private boolean includeProperties = true; + private boolean includePaths = true; + private boolean includeType = true; + private boolean includeChildAssociations = true; + private boolean includeParentAssociations = true; + private boolean includeChildIds = true; + private boolean includeTxnId = true; + + public boolean isIncludeAclId() + { + return includeAclId; + } + + public void setIncludeAclId(boolean includeAclId) + { + this.includeAclId = includeAclId; + } + + public boolean isIncludeAspects() + { + return includeAspects; + } + + public void setIncludeAspects(boolean includeAspects) + { + this.includeAspects = includeAspects; + } + + public boolean isIncludeNodeRef() + { + return includeNodeRef; + } + + public void setIncludeNodeRef(boolean includeNodeRef) + { + this.includeNodeRef = includeNodeRef; + } + + public boolean isIncludeOwner() + { + return includeOwner; + } + + public void setIncludeOwner(boolean includeOwner) + { + this.includeOwner = includeOwner; + } + + public boolean isIncludeProperties() + { + return includeProperties; + } + + public void setIncludeProperties(boolean includeProperties) + { + this.includeProperties = includeProperties; + } + + public boolean isIncludePaths() + { + return includePaths; + } + + public void setIncludePaths(boolean includePaths) + { + this.includePaths = includePaths; + } + + public boolean isIncludeType() + { + return includeType; + } + + public void setIncludeType(boolean includeType) + { + this.includeType = includeType; + } + + public boolean isIncludeChildAssociations() + { + return includeChildAssociations; + } + + public void setIncludeChildAssociations(boolean includeChildAssociations) + { + this.includeChildAssociations = includeChildAssociations; + } + + public boolean isIncludeParentAssociations() + { + return includeParentAssociations; + } + + public void setIncludeParentAssociations(boolean includeParentAssociations) + { + this.includeParentAssociations = includeParentAssociations; + } + + public int getMaxResults() + { + return maxResults; + } + + public void setMaxResults(int maxResults) + { + this.maxResults = maxResults; + } + + public List getNodeIds() + { + return nodeIds; + } + + public void setNodeIds(List nodeIds) + { + this.nodeIds = nodeIds; + } + + public void setTransactionIds(List txnIds) + { + this.transactionIds = txnIds; + } + + public List getTransactionIds() + { + return transactionIds; + } + + public Long getFromTxnId() + { + return fromTxnId; + } + + public void setFromTxnId(Long fromTxnId) + { + this.fromTxnId = fromTxnId; + } + + public Long getToTxnId() + { + return toTxnId; + } + + public void setToTxnId(Long toTxnId) + { + this.toTxnId = toTxnId; + } + + public Long getFromNodeId() + { + return fromNodeId; + } + + public void setFromNodeId(Long fromNodeId) + { + this.fromNodeId = fromNodeId; + } + + public Long getToNodeId() + { + return toNodeId; + } + + public void setToNodeId(Long toNodeId) + { + this.toNodeId = toNodeId; + } + + public boolean isIncludeChildIds() + { + return includeChildIds; + } + + public void setIncludeChildIds(boolean includeChildIds) + { + this.includeChildIds = includeChildIds; + } + + public boolean isIncludeTxnId() + { + return includeTxnId; + } + + public void setIncludeTxnId(boolean includeTxnId) + { + this.includeTxnId = includeTxnId; + } + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/PropertyValue.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/PropertyValue.java index 1dcf369fd..7379a981c 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/PropertyValue.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/PropertyValue.java @@ -1,11 +1,11 @@ -package org.alfresco.solr.client; - -/** - * Base class for property values returned to SOLR for indexing. - * - * @since 4.0 - */ -public abstract class PropertyValue -{ - -} +package org.alfresco.solr.client; + +/** + * Base class for property values returned to SOLR for indexing. + * + * @since 4.0 + */ +public abstract class PropertyValue +{ + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClient.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClient.java index b4645e285..89a46c21a 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClient.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClient.java @@ -1,1516 +1,1516 @@ -package org.alfresco.solr.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.httpclient.AlfrescoHttpClient; -import org.alfresco.httpclient.AuthenticationException; -import org.alfresco.httpclient.GetRequest; -import org.alfresco.httpclient.PostRequest; -import org.alfresco.httpclient.Response; -import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.NamespaceDAO; -import org.alfresco.repo.index.shard.ShardState; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.service.cmr.dictionary.DataTypeDefinition; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.service.cmr.dictionary.PropertyDefinition; -import org.alfresco.service.cmr.repository.AssociationRef; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.MLText; -import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.repository.Path; -import org.alfresco.service.cmr.repository.Path.AttributeElement; -import org.alfresco.service.cmr.repository.Path.ChildAssocElement; -import org.alfresco.service.cmr.repository.StoreRef; -import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; -import org.alfresco.service.cmr.repository.datatype.TypeConversionException; -import org.alfresco.service.cmr.repository.datatype.TypeConverter; -import org.alfresco.service.cmr.repository.datatype.TypeConverter.Converter; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.ISO8601DateFormat; -import org.alfresco.util.Pair; -import org.apache.commons.codec.EncoderException; -import org.apache.commons.codec.net.URLCodec; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.util.DateUtil; -import org.codehaus.jackson.JsonFactory; -import org.codehaus.jackson.JsonParser; -import org.codehaus.jackson.JsonToken; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.extensions.surf.util.URLEncoder; - -// TODO error handling, including dealing with a repository that is not responsive (ConnectException in sendRemoteRequest) -// TODO get text content transform status handling -/** - * Http client to handle SOLR-Alfresco remote calls. - * - * @since 4.0 - */ -public class SOLRAPIClient -{ - protected final static Logger log = LoggerFactory.getLogger(SOLRAPIClient.class); - private static final String GET_ACL_CHANGESETS_URL = "api/solr/aclchangesets"; - private static final String GET_ACLS = "api/solr/acls"; - private static final String GET_ACLS_READERS = "api/solr/aclsReaders"; - private static final String GET_TRANSACTIONS_URL = "api/solr/transactions"; - private static final String GET_METADATA_URL = "api/solr/metadata"; - private static final String GET_NODES_URL = "api/solr/nodes"; - private static final String GET_CONTENT = "api/solr/textContent"; - private static final String GET_MODEL = "api/solr/model"; - private static final String GET_MODELS_DIFF = "api/solr/modelsdiff"; - - private static final String CHECKSUM_HEADER = "XAlfresco-modelChecksum"; - - private AlfrescoHttpClient repositoryHttpClient; - private SOLRDeserializer deserializer; - private DictionaryService dictionaryService; - private JsonFactory jsonFactory; - private NamespaceDAO namespaceDAO; - - public SOLRAPIClient(AlfrescoHttpClient repositoryHttpClient, - DictionaryService dictionaryService, - NamespaceDAO namespaceDAO) - { - this.repositoryHttpClient = repositoryHttpClient; - this.dictionaryService = dictionaryService; - this.namespaceDAO = namespaceDAO; - this.deserializer = new SOLRDeserializer(namespaceDAO); - this.jsonFactory = new JsonFactory(); - } - - /** - * Get the ACL ChangeSets - * - * @param fromCommitTime the lowest commit time (optional) - * @param minAclChangeSetId the lowest ChangeSet ID (optional) - * @param maxResults the maximum number of results (a reasonable value only) - * @return the ACL ChangeSets in order of commit time and ID - */ - public AclChangeSets getAclChangeSets(Long fromCommitTime, Long minAclChangeSetId, Long toCommitTime, Long maxAclChangeSetId, int maxResults) - throws AuthenticationException, IOException, JSONException - { - StringBuilder url = new StringBuilder(GET_ACL_CHANGESETS_URL); - StringBuilder args = new StringBuilder(); - if (fromCommitTime != null) - { - args.append("?").append("fromTime").append("=").append(fromCommitTime); - } - if (minAclChangeSetId != null) - { - args.append(args.length() == 0 ? "?" : "&").append("fromId").append("=").append(minAclChangeSetId); - } - if (toCommitTime != null) - { - args.append(args.length() == 0 ? "?" : "&").append("toTime").append("=").append(toCommitTime); - } - if (maxAclChangeSetId != null) - { - args.append(args.length() == 0 ? "?" : "&").append("toId").append("=").append(maxAclChangeSetId); - } - if (maxResults != 0 && maxResults != Integer.MAX_VALUE) - { - args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); - } - url.append(args); - - GetRequest req = new GetRequest(url.toString()); - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - - if (response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if (log.isDebugEnabled()) - { - log.debug(json.toString(3)); - } - - JSONArray aclChangeSetsJSON = json.getJSONArray("aclChangeSets"); - List aclChangeSets = new ArrayList(aclChangeSetsJSON.length()); - for (int i = 0; i < aclChangeSetsJSON.length(); i++) - { - JSONObject aclChangeSetJSON = aclChangeSetsJSON.getJSONObject(i); - long aclChangeSetId = aclChangeSetJSON.getLong("id"); - long commitTimeMs = aclChangeSetJSON.getLong("commitTimeMs"); - int aclCount = aclChangeSetJSON.getInt("aclCount"); - AclChangeSet aclChangeSet = new AclChangeSet(aclChangeSetId, commitTimeMs, aclCount); - aclChangeSets.add(aclChangeSet); - } - - - Long maxChangeSetCommitTime = null; - if(json.has("maxChangeSetCommitTime")) - { - maxChangeSetCommitTime = json.getLong("maxChangeSetCommitTime"); - } - - Long maxChangeSetIdOnServer = null; - if(json.has("maxChangeSetId")) - { - maxChangeSetIdOnServer = json.getLong("maxChangeSetId"); - } - - // Done - return new AclChangeSets(aclChangeSets, maxChangeSetCommitTime, maxChangeSetIdOnServer); - } - - /** - * Get the ACLs associated with a given list of ACL ChangeSets. The ACLs may be truncated for - * the last ACL ChangeSet in the return values - the ACL count from the - * {@link #getAclChangeSets(Long, Long, Long, Long, int) ACL ChangeSets}. - * - * @param aclChangeSets the ACL ChangeSets to include - * @param minAclId the lowest ACL ID (may be null) - * @param maxResults the maximum number of results to retrieve - * @return the ACLs (includes ChangeSet ID) - */ - public List getAcls(List aclChangeSets, Long minAclId, int maxResults) throws AuthenticationException, IOException, JSONException - { - StringBuilder url = new StringBuilder(GET_ACLS); - StringBuilder args = new StringBuilder(); - if (minAclId != null) - { - args.append("?").append("fromId").append("=").append(minAclId); - } - - if(maxResults >= 0) - { - args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); - } - - url.append(args); - - JSONObject jsonReq = new JSONObject(); - JSONArray aclChangeSetIdsJSON = new JSONArray(); - List aclChangeSetIds = new ArrayList(); - for (AclChangeSet aclChangeSet : aclChangeSets) - { - Long aclChangeSetId = aclChangeSet.getId(); - aclChangeSetIdsJSON.put(aclChangeSetId); - aclChangeSetIds.add(aclChangeSetId); - } - jsonReq.put("aclChangeSetIds", aclChangeSetIdsJSON); - - PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json"); - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - - if (response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if (log.isDebugEnabled()) - { - log.debug(json.toString(3)); - } - - JSONArray aclsJSON = json.getJSONArray("acls"); - List acls = new ArrayList(aclsJSON.length()); - for (int i = 0; i < aclsJSON.length(); i++) - { - JSONObject aclJSON = aclsJSON.getJSONObject(i); - long aclChangeSetId = aclJSON.getLong("aclChangeSetId"); - long aclId = aclJSON.getLong("id"); - Acl acl = new Acl(aclChangeSetId, aclId); - acls.add(acl); - } - // Done - return acls; - } - - /** - * Get the ACL readers for a given list of ACLs - * - * @param acls the ACLs - * @return the readers for the ACLs - */ - public List getAclReaders(List acls) throws AuthenticationException, IOException, JSONException - { - StringBuilder url = new StringBuilder(GET_ACLS_READERS); - - JSONObject jsonReq = new JSONObject(); - JSONArray aclIdsJSON = new JSONArray(); - List aclIds = new ArrayList(); - for (Acl acl : acls) - { - Long aclId = acl.getId(); - aclIdsJSON.put(aclId); - aclIds.add(aclId); - } - jsonReq.put("aclIds", aclIdsJSON); - - PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json"); - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - - if (response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException(GET_ACLS_READERS + " return status:" + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if (log.isDebugEnabled()) - { - log.debug(json.toString(3)); - } - - JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders"); - List aclsReaders = new ArrayList(aclsReadersJSON.length()); - for (int i = 0; i < aclsReadersJSON.length(); i++) - { - JSONObject aclReadersJSON = aclsReadersJSON.getJSONObject(i); - long aclId = aclReadersJSON.getLong("aclId"); - JSONArray readersJSON = aclReadersJSON.getJSONArray("readers"); - List readers = authorityListFromJSON(readersJSON); - JSONArray deniedJSON = aclReadersJSON.getJSONArray("denied"); - List denied = authorityListFromJSON(deniedJSON); - long aclChangeSetId = aclReadersJSON.getLong("aclChangeSetId"); - - String tenantDomain = aclReadersJSON.getString("tenantDomain"); - if (tenantDomain == null) - { - tenantDomain = TenantService.DEFAULT_DOMAIN; - } - - AclReaders aclReaders = new AclReaders(aclId, readers, denied, aclChangeSetId, tenantDomain); - aclsReaders.add(aclReaders); - } - // Done - return aclsReaders; - } - - /** - * Convert a JSON array of authorities to a simple Java List<String> - * - * @param jsonArray JSONArray - * @return List<String> - * @throws JSONException - */ - private List authorityListFromJSON(JSONArray jsonArray) throws JSONException - { - List authorities = new ArrayList(jsonArray.length()); - for (int j = 0; j < jsonArray.length(); j++) - { - String authority = jsonArray.getString(j); - authorities.add(authority); - } - return authorities; - } - - public Transactions getTransactions(Long fromCommitTime, Long minTxnId, Long toCommitTime, Long maxTxnId, int maxResults) throws AuthenticationException, IOException, JSONException - { - try - { - return getTransactions(fromCommitTime, minTxnId, toCommitTime, maxTxnId, maxResults, null); - } - catch (EncoderException e) - { - // Can not happen .... - throw new IOException(e); - } - } - - public Transactions getTransactions(Long fromCommitTime, Long minTxnId, Long toCommitTime, Long maxTxnId, int maxResults, ShardState shardState) throws AuthenticationException, IOException, JSONException, EncoderException - { - URLCodec encoder = new URLCodec(); - - StringBuilder url = new StringBuilder(GET_TRANSACTIONS_URL); - StringBuilder args = new StringBuilder(); - if (fromCommitTime != null) - { - args.append("?").append("fromCommitTime").append("=").append(fromCommitTime); - } - if (minTxnId != null) - { - args.append(args.length() == 0 ? "?" : "&").append("minTxnId").append("=").append(minTxnId); - } - if (toCommitTime != null) - { - args.append(args.length() == 0 ? "?" : "&").append("toCommitTime").append("=").append(toCommitTime); - } - if (maxTxnId != null) - { - args.append(args.length() == 0 ? "?" : "&").append("maxTxnId").append("=").append(maxTxnId); - } - if (maxResults != 0 && maxResults != Integer.MAX_VALUE) - { - args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); - } - if(shardState != null) - { - args.append(args.length() == 0 ? "?" : "&"); - args.append(encoder.encode("baseUrl")).append("=").append(encoder.encode(shardState.getShardInstance().getBaseUrl())); - args.append("&").append(encoder.encode("hostName")).append("=").append(encoder.encode(shardState.getShardInstance().getHostName())); - args.append("&").append(encoder.encode("template")).append("=").append(encoder.encode(shardState.getShardInstance().getShard().getFloc().getTemplate())); - - for(String key : shardState.getShardInstance().getShard().getFloc().getPropertyBag().keySet()) - { - String value = shardState.getShardInstance().getShard().getFloc().getPropertyBag().get(key); - if(value != null) - { - args.append("&").append(encoder.encode("floc.property."+key)).append("=").append(encoder.encode(value)); - } - } - - for(String key : shardState.getPropertyBag().keySet()) - { - String value = shardState.getPropertyBag().get(key); - if(value != null) - { - args.append("&").append(encoder.encode("state.property."+key)).append("=").append(encoder.encode(value)); - } - } - - args.append("&").append(encoder.encode("instance")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getInstance())); - args.append("&").append(encoder.encode("numberOfShards")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getFloc().getNumberOfShards())); - args.append("&").append(encoder.encode("port")).append("=").append(encoder.encode("" + shardState.getShardInstance().getPort())); - args.append("&").append(encoder.encode("stores")).append("="); - for(StoreRef store : shardState.getShardInstance().getShard().getFloc().getStoreRefs()) - { - if(args.charAt(args.length()-1) != '=') - { - args.append(encoder.encode(",")); - } - args.append(encoder.encode(store.toString())); - } - args.append("&").append(encoder.encode("isMaster")).append("=").append(encoder.encode("" + shardState.isMaster())); - args.append("&").append(encoder.encode("hasContent")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getFloc().hasContent())); - args.append("&").append(encoder.encode("shardMethod")).append("=").append(encoder.encode(shardState.getShardInstance().getShard().getFloc().getShardMethod().toString())); - - args.append("&").append(encoder.encode("lastUpdated")).append("=").append(encoder.encode("" + shardState.getLastUpdated())); - args.append("&").append(encoder.encode("lastIndexedChangeSetCommitTime")).append("=").append(encoder.encode("" + shardState.getLastIndexedChangeSetCommitTime())); - args.append("&").append(encoder.encode("lastIndexedChangeSetId")).append("=").append(encoder.encode("" + shardState.getLastIndexedChangeSetId())); - args.append("&").append(encoder.encode("lastIndexedTxCommitTime")).append("=").append(encoder.encode("" + shardState.getLastIndexedTxCommitTime())); - args.append("&").append(encoder.encode("lastIndexedTxId")).append("=").append(encoder.encode("" + shardState.getLastIndexedTxId())); - - } - - url.append(args); - - GetRequest req = new GetRequest(url.toString()); - Response response = null; - List transactions = new ArrayList(); - Long maxTxnCommitTime = null; - Long maxTxnIdOnServer = null; - try - { - response = repositoryHttpClient.sendRequest(req); - if(response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException("GetTransactions return status is " + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - JsonParser parser = jsonFactory.createJsonParser(reader); - - JsonToken token = parser.nextValue(); - while (token != null) - { - if ("transactions".equals(parser.getCurrentName())) - { - token = parser.nextToken(); //START_ARRAY - while (token == JsonToken.START_OBJECT) - { - token = parser.nextValue(); - long id = parser.getLongValue(); - - token = parser.nextValue(); - long commitTime = parser.getLongValue(); - - token = parser.nextValue(); - long updates = parser.getLongValue(); - - token = parser.nextValue(); - long deletes = parser.getLongValue(); - - Transaction txn = new Transaction(); - txn.setCommitTimeMs(commitTime); - txn.setDeletes(deletes); - txn.setId(id); - txn.setUpdates(updates); - - transactions.add(txn); - - token = parser.nextToken(); //END_OBJECT - token = parser.nextToken(); // START_OBJECT or END_ARRAY; - } - } - else if ("maxTxnCommitTime".equals(parser.getCurrentName())) - { - maxTxnCommitTime = parser.getLongValue(); - } - else if ("maxTxnId".equals(parser.getCurrentName())) - { - maxTxnIdOnServer = parser.getLongValue(); - } - token = parser.nextValue(); - } - parser.close(); - reader.close(); - - } - finally - { - if(response != null) - { - response.release(); - } - } - - return new Transactions(transactions, maxTxnCommitTime, maxTxnIdOnServer); - } - - public List getNodes(GetNodesParameters parameters, int maxResults) throws AuthenticationException, IOException, JSONException - { - StringBuilder url = new StringBuilder(GET_NODES_URL); - - JSONObject body = new JSONObject(); - - if(parameters.getTransactionIds() != null) - { - JSONArray jsonTxnIds = new JSONArray(); - for(Long txnId : parameters.getTransactionIds()) - { - jsonTxnIds.put(txnId); - } - body.put("txnIds", jsonTxnIds); - } - - if(parameters.getFromNodeId() != null) - { - body.put("fromNodeId", parameters.getFromNodeId()); - } - if(parameters.getToNodeId() != null) - { - body.put("toNodeId", parameters.getToNodeId()); - } - if(parameters.getExcludeAspects() != null) - { - JSONArray jsonExcludeAspects = new JSONArray(); - for(QName excludeAspect : parameters.getExcludeAspects()) - { - jsonExcludeAspects.put(excludeAspect.toString()); - } - body.put("excludeAspects", jsonExcludeAspects); - } - if(parameters.getIncludeAspects() != null) - { - JSONArray jsonIncludeAspects = new JSONArray(); - for(QName includeAspect : parameters.getIncludeAspects()) - { - jsonIncludeAspects.put(includeAspect.toString()); - } - body.put("includeAspects", jsonIncludeAspects); - } - - if(parameters.getStoreProtocol() != null) - { - body.put("storeProtocol", parameters.getStoreProtocol()); - } - - if(parameters.getStoreIdentifier() != null) - { - body.put("storeIdentifier", parameters.getStoreIdentifier()); - } - - body.put("maxResults", maxResults); - - PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); - - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - if(response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException("GetNodes return status is " + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if(log.isDebugEnabled()) - { - log.debug(json.toString()); - } - - JSONArray jsonNodes = json.getJSONArray("nodes"); - List nodes = new ArrayList(jsonNodes.length()); - for(int i = 0; i < jsonNodes.length(); i++) - { - JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i); - Node nodeInfo = new Node(); - if(jsonNodeInfo.has("id")) - { - nodeInfo.setId(jsonNodeInfo.getLong("id")); - } - - if(jsonNodeInfo.has("nodeRef")) - { - nodeInfo.setNodeRef(jsonNodeInfo.getString("nodeRef")); - } - - if(jsonNodeInfo.has("txnId")) - { - nodeInfo.setTxnId(jsonNodeInfo.getLong("txnId")); - } - - if(jsonNodeInfo.has("aclId")) - { - nodeInfo.setAclId(jsonNodeInfo.getLong("aclId")); - } - - if(jsonNodeInfo.has("tenant")) - { - nodeInfo.setTenant(jsonNodeInfo.getString("tenant")); - } - - if(jsonNodeInfo.has("status")) - { - Node.SolrApiNodeStatus status; - String statusStr = jsonNodeInfo.getString("status"); - if(statusStr.equals("u")) - { - status = Node.SolrApiNodeStatus.UPDATED; - } - else if(statusStr.equals("d")) - { - status = Node.SolrApiNodeStatus.DELETED; - } - else - { - status = Node.SolrApiNodeStatus.UNKNOWN; - } - nodeInfo.setStatus(status); - } - - nodes.add(nodeInfo); - } - - return nodes; - } - - private PropertyValue getSinglePropertyValue(DataTypeDefinition dataType, Object value) throws JSONException - { - PropertyValue ret = null; - QName dataTypeName = dataType.getName(); - - if(value == null || value == JSONObject.NULL) - { - ret = null; - } - else if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) - { - JSONArray a = (JSONArray)value; - Map mlValues = new HashMap(a.length()); - - for(int k = 0; k < a.length(); k++) - { - JSONObject pair = a.getJSONObject(k); - Locale locale = deserializer.deserializeValue(Locale.class, pair.getString("locale")); - String mlValue = pair.has("value") ? pair.getString("value") : null; - mlValues.put(locale, mlValue); - } - - ret = new MLTextPropertyValue(mlValues); - } - else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) - { - JSONObject o = (JSONObject)value; - - String localeStr = o.has("locale") ? o.getString("locale") : null; - Locale locale = (o.has("locale") ? deserializer.deserializeValue(Locale.class, localeStr) : null); - - Long size = o.has("size") ? o.getLong("size") : null; - - String encoding = o.has("encoding") ? o.getString("encoding") : null; - String mimetype = o.has("mimetype") ? o.getString("mimetype") : null; - - Long id = o.has("contentId") ? o.getLong("contentId") : null; - - ret = new ContentPropertyValue(locale, size, encoding, mimetype, id); - } - else - { - ret = new StringPropertyValue((String)value); - } - - return ret; - } - - private PropertyValue getPropertyValue(PropertyDefinition propertyDef, Object value) throws JSONException - { - PropertyValue ret = null; - - if(value == null || value == JSONObject.NULL) - { - ret = null; - } - else if(propertyDef == null) - { - // assume a string - ret = new StringPropertyValue((String)value); - } - else - { - DataTypeDefinition dataType = propertyDef.getDataType(); - - boolean isMulti = propertyDef.isMultiValued(); - if(isMulti) - { - if(!(value instanceof JSONArray)) - { - throw new IllegalArgumentException("Expected json array, got " + value.getClass().getName()); - } - - MultiPropertyValue multi = new MultiPropertyValue(); - JSONArray array = (JSONArray)value; - for(int j = 0; j < array.length(); j++) - { - multi.addValue(getSinglePropertyValue(dataType, array.get(j))); - } - - ret = multi; - } - else - { - ret = getSinglePropertyValue(dataType, value); - } - } - - return ret; - } - - public List getNodesMetaData(NodeMetaDataParameters params, int maxResults) throws AuthenticationException, IOException, JSONException - { - List nodeIds = params.getNodeIds(); - - StringBuilder url = new StringBuilder(GET_METADATA_URL); - - JSONObject body = new JSONObject(); - if(nodeIds != null && nodeIds.size() > 0) - { - JSONArray jsonNodeIds = new JSONArray(); - for(Long nodeId : nodeIds) - { - jsonNodeIds.put(nodeId); - } - body.put("nodeIds", jsonNodeIds); - - } - if(params.getFromNodeId() != null) - { - body.put("fromNodeId", params.getFromNodeId()); - } - if(params.getToNodeId() != null) - { - body.put("toNodeId", params.getToNodeId()); - } - - // only need to set in cases where we don't want them in the response - // because they default to true - if(!params.isIncludeAclId()) - { - body.put("includeAclId", params.isIncludeAclId()); - } - if(!params.isIncludeAspects()) - { - body.put("includeAspects", params.isIncludeAspects()); - } - if(!params.isIncludeProperties()) - { - body.put("includeProperties", params.isIncludeProperties()); - } - if(!params.isIncludeChildAssociations()) - { - body.put("includeChildAssociations", params.isIncludeChildAssociations()); - } - if(!params.isIncludeParentAssociations()) - { - body.put("includeParentAssociations", params.isIncludeParentAssociations()); - } - if(!params.isIncludeChildIds()) - { - body.put("includeChildIds", params.isIncludeChildIds()); - } - if(!params.isIncludePaths()) - { - body.put("includePaths", params.isIncludePaths()); - } - if(!params.isIncludeOwner()) - { - body.put("includeOwner", params.isIncludeOwner()); - } - if(!params.isIncludeNodeRef()) - { - body.put("includeNodeRef", params.isIncludeNodeRef()); - } - if(!params.isIncludeTxnId()) - { - body.put("includeTxnId", params.isIncludeTxnId()); - } - - body.put("maxResults", maxResults); - - PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - if(response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException("GetNodeMetaData return status is " + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if (log.isDebugEnabled()) - { - log.debug(json.toString(3)); - } - - JSONArray jsonNodes = json.getJSONArray("nodes"); - - List nodes = new ArrayList(jsonNodes.length()); - for(int i = 0; i < jsonNodes.length(); i++) - { - JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i); - NodeMetaData metaData = new NodeMetaData(); - - if(jsonNodeInfo.has("id")) - { - metaData.setId(jsonNodeInfo.getLong("id")); - } - - if(jsonNodeInfo.has("tenantDomain")) - { - metaData.setTenantDomain(jsonNodeInfo.getString("tenantDomain")); - } - - if(jsonNodeInfo.has("txnId")) - { - metaData.setTxnId(jsonNodeInfo.getLong("txnId")); - } - - if(jsonNodeInfo.has("aclId")) - { - metaData.setAclId(jsonNodeInfo.getLong("aclId")); - } - - if(jsonNodeInfo.has("nodeRef")) - { - metaData.setNodeRef(new NodeRef(jsonNodeInfo.getString("nodeRef"))); - } - - if(jsonNodeInfo.has("type")) - { - metaData.setType(deserializer.deserializeValue(QName.class, jsonNodeInfo.getString("type"))); - } - - if(jsonNodeInfo.has("aspects")) - { - JSONArray jsonAspects = jsonNodeInfo.getJSONArray("aspects"); - Set aspects = new HashSet(jsonAspects.length()); - for(int j = 0; j < jsonAspects.length(); j++) - { - String jsonAspect = (String)jsonAspects.get(j); - aspects.add(deserializer.deserializeValue(QName.class, jsonAspect)); - } - metaData.setAspects(aspects); - } - - if(jsonNodeInfo.has("paths")) - { - JSONArray jsonPaths = jsonNodeInfo.getJSONArray("paths"); - List> paths = new ArrayList>(jsonPaths.length()); - for(int j = 0; j < jsonPaths.length(); j++) - { - JSONObject path = new JSONObject(jsonPaths.getString(j)); - String pathValue = path.getString("path"); - QName qname = path.has("qname") ? deserializer.deserializeValue(QName.class, path.getString("qname")) : null; - paths.add(new Pair(pathValue, qname)); - } - metaData.setPaths(paths); - } - - if(jsonNodeInfo.has("namePaths")) - { - JSONArray jsonNamePaths = jsonNodeInfo.getJSONArray("namePaths"); - List> namePaths = new ArrayList>(jsonNamePaths.length()); - for(int j = 0; j < jsonNamePaths.length(); j++) - { - JSONObject jsonNamePath = jsonNamePaths.getJSONObject(j); - JSONArray jsonNameElements = jsonNamePath.getJSONArray("namePath"); - List namePath = new ArrayList(jsonNameElements.length()); - for(int k = 0; k < jsonNameElements.length(); k++) - { - String namePathElement = jsonNameElements.getString(k); - namePath.add(namePathElement); - } - namePaths.add(namePath); - } - metaData.setNamePaths(namePaths); - } - - if(jsonNodeInfo.has("ancestors")) - { - JSONArray jsonAncestors = jsonNodeInfo.getJSONArray("ancestors"); - HashSet ancestors = new HashSet(jsonAncestors.length()); - for(int j = 0; j < jsonAncestors.length(); j++) - { - String ancestorNodeRefString = jsonAncestors.getString(j); - NodeRef ancestorNodeRef = new NodeRef(ancestorNodeRefString); - ancestors.add(ancestorNodeRef); - } - metaData.setAncestors(ancestors); - } - - if(jsonNodeInfo.has("properties")) - { - JSONObject jsonProperties = jsonNodeInfo.getJSONObject("properties"); - Map properties = new HashMap(jsonProperties.length()); - @SuppressWarnings("rawtypes") - Iterator propKeysIterator = jsonProperties.keys(); - while(propKeysIterator.hasNext()) - { - String propName = (String)propKeysIterator.next(); - QName propQName = deserializer.deserializeValue(QName.class, propName); - Object propValueObj = jsonProperties.opt(propName); - - // check the expected property type to determine how to process the value - PropertyDefinition propertyDef = dictionaryService.getProperty(propQName); -// if(propertyDef == null) -// { -// // TODO which exception here? -// throw new IllegalArgumentException("Could not find property definition for property " + propName); -// } - - properties.put(propQName, getPropertyValue(propertyDef, propValueObj)); - } - metaData.setProperties(properties); - } - - if(jsonNodeInfo.has("parentAssocsCrc")) - { - metaData.setParentAssocsCrc(jsonNodeInfo.getLong("parentAssocsCrc")); - } - - if(jsonNodeInfo.has("parentAssocs")) - { - JSONArray jsonParentAssocs = jsonNodeInfo.getJSONArray("parentAssocs"); - List assocs = new ArrayList(jsonParentAssocs.length()); - for(int j = 0; j < jsonParentAssocs.length(); j++) - { - String childAssocRefStr = jsonParentAssocs.getString(j); - ChildAssociationRef childAssociationRef = new ChildAssociationRef(childAssocRefStr); - assocs.add(childAssociationRef); - } - metaData.setParentAssocs(assocs); - } - - if(jsonNodeInfo.has("childAssocs")) - { - JSONArray jsonParentAssocs = jsonNodeInfo.getJSONArray("childAssocs"); - List assocs = new ArrayList(jsonParentAssocs.length()); - for(int j = 0; j < jsonParentAssocs.length(); j++) - { - String childAssocRefStr = jsonParentAssocs.getString(j); - ChildAssociationRef childAssociationRef = new ChildAssociationRef(childAssocRefStr); - assocs.add(childAssociationRef); - } - metaData.setChildAssocs(assocs); - } - - if(jsonNodeInfo.has("childIds")) - { - JSONArray jsonChildIds = jsonNodeInfo.getJSONArray("childIds"); - List childIds = new ArrayList(jsonChildIds.length()); - for(int j = 0; j < jsonChildIds.length(); j++) - { - Long childId = jsonChildIds.getLong(j); - childIds.add(childId); - } - metaData.setChildIds(childIds); - } - - if(jsonNodeInfo.has("owner")) - { - metaData.setOwner(jsonNodeInfo.getString("owner")); - } - - nodes.add(metaData); - } - - return nodes; - } - - public GetTextContentResponse getTextContent(Long nodeId, QName propertyQName, Long modifiedSince) throws AuthenticationException, IOException - { - StringBuilder url = new StringBuilder(128); - url.append(GET_CONTENT); - - StringBuilder args = new StringBuilder(128); - if(nodeId != null) - { - args.append("?"); - args.append("nodeId"); - args.append("="); - args.append(nodeId); - } - else - { - throw new NullPointerException("getTextContent(): nodeId cannot be null."); - } - if(propertyQName != null) - { - if(args.length() == 0) - { - args.append("?"); - } - else - { - args.append("&"); - } - args.append("propertyQName"); - args.append("="); - args.append(URLEncoder.encode(propertyQName.toString())); - } - - url.append(args); - - GetRequest req = new GetRequest(url.toString()); - - if(modifiedSince != null) - { - Map headers = new HashMap(1, 1.0f); - headers.put("If-Modified-Since", String.valueOf(DateUtil.formatDate(new Date(modifiedSince)))); - req.setHeaders(headers); - } - - Response response = repositoryHttpClient.sendRequest(req); - - if(response.getStatus() != Status.STATUS_NOT_MODIFIED && response.getStatus() != Status.STATUS_NO_CONTENT && response.getStatus() != Status.STATUS_OK) - { - throw new AlfrescoRuntimeException("GetTextContentResponse return status is " + response.getStatus()); - } - - return new GetTextContentResponse(response); - } - - public AlfrescoModel getModel(QName modelName) throws AuthenticationException, IOException, JSONException - { - // If the model is new to the SOLR side the prefix will be unknown so we can not generate prefixes for the request! - // Always use the full QName with explicit URI - StringBuilder url = new StringBuilder(GET_MODEL); - - URLCodec encoder = new URLCodec(); - // must send the long name as we may not have the prefix registered - url.append("?modelQName=").append(encoder.encode(modelName.toString(), "UTF-8")); - - GetRequest req = new GetRequest(url.toString()); - - Response response = null; - try - { - response = repositoryHttpClient.sendRequest(req); - if(response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException("GetModel return status is " + response.getStatus()); - } - - return new AlfrescoModel(M2Model.createModel(response.getContentAsStream()), - Long.valueOf(response.getHeader(CHECKSUM_HEADER))); - } - finally - { - if(response != null) - { - response.release(); - } - } - } - - public List getModelsDiff(List currentModels) throws AuthenticationException, IOException, JSONException - { - StringBuilder url = new StringBuilder(GET_MODELS_DIFF); - - JSONObject body = new JSONObject(); - JSONArray jsonModels = new JSONArray(); - for(AlfrescoModel model : currentModels) - { - JSONObject jsonModel = new JSONObject(); - QName modelQName = QName.createQName( model.getModel().getName(), namespaceDAO); - jsonModel.put("name", modelQName.toString()); - jsonModel.put("checksum", model.getChecksum()); - jsonModels.put(jsonModel); - } - body.put("models", jsonModels); - - PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); - Response response = null; - JSONObject json = null; - try - { - response = repositoryHttpClient.sendRequest(req); - if(response.getStatus() != HttpStatus.SC_OK) - { - throw new AlfrescoRuntimeException("GetModelsDiff return status is " + response.getStatus()); - } - - Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); - json = new JSONObject(new JSONTokener(reader)); - } - finally - { - if(response != null) - { - response.release(); - } - } - - if(log.isDebugEnabled()) - { - log.debug(json.toString()); - } - JSONArray jsonDiffs = json.getJSONArray("diffs"); - if(jsonDiffs == null) - { - throw new AlfrescoRuntimeException("GetModelsDiff badly formatted response"); - } - - List diffs = new ArrayList(jsonDiffs.length()); - for(int i = 0; i < jsonDiffs.length(); i++) - { - JSONObject jsonDiff = jsonDiffs.getJSONObject(i); - diffs.add(new AlfrescoModelDiff( - QName.createQName(jsonDiff.getString("name")), - AlfrescoModelDiff.TYPE.valueOf(jsonDiff.getString("type")), - (jsonDiff.isNull("oldChecksum") ? null : jsonDiff.getLong("oldChecksum")), - (jsonDiff.isNull("newChecksum") ? null : jsonDiff.getLong("newChecksum")))); - } - - return diffs; - } - - /* - * type conversions from serialized JSON values to SOLR-consumable objects - */ - @SuppressWarnings("rawtypes") - private class SOLRTypeConverter - { - /** - * Default Type Converter - */ - private TypeConverter instance = new TypeConverter(); - private NamespaceDAO namespaceDAO; - - @SuppressWarnings("unchecked") - SOLRTypeConverter(NamespaceDAO namespaceDAO) - { - this.namespaceDAO = namespaceDAO; - - // add all default converters to this converter - // TODO find a better way of doing this - Map, Map, Converter>> converters = DefaultTypeConverter.INSTANCE.getConverters(); - for(Class source : converters.keySet()) - { - Map, Converter> converters1 = converters.get(source); - for(Class dest : converters1.keySet()) - { - Converter converter = converters1.get(dest); - instance.addConverter(source, dest, converter); - } - } - - // dates - instance.addConverter(String.class, Date.class, new TypeConverter.Converter() - { - public Date convert(String source) - { - try - { - Date date = ISO8601DateFormat.parse(source); - return date; - } - catch (Exception e) - { - throw new TypeConversionException("Failed to convert date " + source + " to string", e); - } - } - }); - - // node refs - instance.addConverter(String.class, NodeRef.class, new TypeConverter.Converter() - { - public NodeRef convert(String source) - { - return new NodeRef(source); - } - }); - - // paths - instance.addConverter(String.class, AttributeElement.class, new TypeConverter.Converter() - { - public AttributeElement convert(String source) - { - return new Path.AttributeElement(source); - } - }); - - instance.addConverter(String.class, ChildAssocElement.class, new TypeConverter.Converter() - { - public ChildAssocElement convert(String source) - { - return new Path.ChildAssocElement(instance.convert(ChildAssociationRef.class, source)); - } - }); - - instance.addConverter(String.class, Path.DescendentOrSelfElement.class, new TypeConverter.Converter() - { - public Path.DescendentOrSelfElement convert(String source) - { - return new Path.DescendentOrSelfElement(); - } - }); - - instance.addConverter(String.class, Path.ParentElement.class, new TypeConverter.Converter() - { - public Path.ParentElement convert(String source) - { - return new Path.ParentElement(); - } - }); - - instance.addConverter(String.class, Path.SelfElement.class, new TypeConverter.Converter() - { - public Path.SelfElement convert(String source) - { - return new Path.SelfElement(); - } - }); - - // associations - instance.addConverter(String.class, ChildAssociationRef.class, new TypeConverter.Converter() - { - public ChildAssociationRef convert(String source) - { - return new ChildAssociationRef(source); - } - }); - - instance.addConverter(String.class, AssociationRef.class, new TypeConverter.Converter() - { - public AssociationRef convert(String source) - { - return new AssociationRef(source); - } - }); - - // qnames - instance.addConverter(String.class, QName.class, new TypeConverter.Converter() - { - public QName convert(String source) - { - return QName.resolveToQName(SOLRTypeConverter.this.namespaceDAO, source); - } - }); - - instance.addConverter(String.class, MLText.class, new TypeConverter.Converter() - { - public MLText convert(String source) - { - return new MLText(source); - } - }); - } - - public final T convert(Class c, Object value) - { - return instance.convert(c, value); - } - } - - /* - * Deserializes JSON values from the remote API into objects consumable by SOLR - */ - private class SOLRDeserializer - { - private SOLRTypeConverter typeConverter; - - public SOLRDeserializer(NamespaceDAO namespaceDAO) - { - typeConverter = new SOLRTypeConverter(namespaceDAO); - } - - public T deserializeValue(Class targetClass, Object value) throws JSONException - { - return typeConverter.convert(targetClass, value); - } - } - - private static class SOLRResponse - { - protected Response response; - - public SOLRResponse(Response response) - { - super(); - this.response = response; - } - - public Response getResponse() - { - return response; - } - } - - public static class GetTransactionsResponse extends SOLRResponse - { - private List txns; - - public GetTransactionsResponse(Response response, List txns) - { - super(response); - this.txns = txns; - } - - public List getTransaction() - { - return txns; - } - } - - public static class GetNodesResponse extends SOLRResponse - { - private List nodes; - - public GetNodesResponse(Response response, List nodes) - { - super(response); - this.nodes = nodes; - } - - public List getNodes() - { - return nodes; - } - } - - public static class GetNodesMetaDataResponse extends SOLRResponse - { - private List nodes; - - public GetNodesMetaDataResponse(Response response, List nodes) - { - super(response); - this.nodes = nodes; - } - - public List getNodes() - { - return nodes; - } - } - - public static enum SolrApiContentStatus - { - NOT_MODIFIED, OK, NO_TRANSFORM, NO_CONTENT, UNKNOWN, TRANSFORM_FAILED, GENERAL_FAILURE; - - public static SolrApiContentStatus getStatus(String statusStr) - { - if(statusStr.equals("ok")) - { - return OK; - } - else if(statusStr.equals("transformFailed")) - { - return TRANSFORM_FAILED; - } - else if(statusStr.equals("noTransform")) - { - return NO_TRANSFORM; - } - else if(statusStr.equals("noContent")) - { - return NO_CONTENT; - } - else - { - return UNKNOWN; - } - } - } - - // TODO register a stream close listener that release the response when the response has been read - public static class GetTextContentResponse extends SOLRResponse - { - private InputStream content; - private SolrApiContentStatus status; - private String transformException; - private String transformStatusStr; - private Long transformDuration; - - public GetTextContentResponse(Response response) throws IOException - { - super(response); - - this.content = response.getContentAsStream(); - this.transformStatusStr = response.getHeader("X-Alfresco-transformStatus"); - this.transformException = response.getHeader("X-Alfresco-transformException"); - String tmp = response.getHeader("X-Alfresco-transformDuration"); - this.transformDuration = (tmp != null ? Long.valueOf(tmp) : null); - setStatus(); - } - - public InputStream getContent() - { - return content; - } - - public SolrApiContentStatus getStatus() - { - return status; - } - - private void setStatus() - { - int status = response.getStatus(); - if(status == HttpStatus.SC_NOT_MODIFIED) - { - this.status = SolrApiContentStatus.NOT_MODIFIED; - } - else if(status == HttpStatus.SC_INTERNAL_SERVER_ERROR) - { - this.status = SolrApiContentStatus.GENERAL_FAILURE; - } - else if(status == HttpStatus.SC_OK) - { - this.status = SolrApiContentStatus.OK; - } - else if(status == HttpStatus.SC_NO_CONTENT) - { - if(transformStatusStr == null) - { - this.status = SolrApiContentStatus.UNKNOWN; - } - else - { - if(transformStatusStr.equals("noTransform")) - { - this.status = SolrApiContentStatus.NO_TRANSFORM; - } - else if(transformStatusStr.equals("transformFailed")) - { - this.status = SolrApiContentStatus.TRANSFORM_FAILED; - } - else - { - this.status = SolrApiContentStatus.UNKNOWN; - } - } - } - } - - public String getTransformException() - { - return transformException; - } - - public void release() - { - response.release(); - } - - public Long getTransformDuration() - { - return transformDuration; - } - } - - public void close() - { - repositoryHttpClient.close(); - } -} +package org.alfresco.solr.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.httpclient.AlfrescoHttpClient; +import org.alfresco.httpclient.AuthenticationException; +import org.alfresco.httpclient.GetRequest; +import org.alfresco.httpclient.PostRequest; +import org.alfresco.httpclient.Response; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.repo.dictionary.NamespaceDAO; +import org.alfresco.repo.index.shard.ShardState; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.service.cmr.dictionary.PropertyDefinition; +import org.alfresco.service.cmr.repository.AssociationRef; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.MLText; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.Path; +import org.alfresco.service.cmr.repository.Path.AttributeElement; +import org.alfresco.service.cmr.repository.Path.ChildAssocElement; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConversionException; +import org.alfresco.service.cmr.repository.datatype.TypeConverter; +import org.alfresco.service.cmr.repository.datatype.TypeConverter.Converter; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.ISO8601DateFormat; +import org.alfresco.util.Pair; +import org.apache.commons.codec.EncoderException; +import org.apache.commons.codec.net.URLCodec; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.util.DateUtil; +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.extensions.surf.util.URLEncoder; + +// TODO error handling, including dealing with a repository that is not responsive (ConnectException in sendRemoteRequest) +// TODO get text content transform status handling +/** + * Http client to handle SOLR-Alfresco remote calls. + * + * @since 4.0 + */ +public class SOLRAPIClient +{ + protected final static Logger log = LoggerFactory.getLogger(SOLRAPIClient.class); + private static final String GET_ACL_CHANGESETS_URL = "api/solr/aclchangesets"; + private static final String GET_ACLS = "api/solr/acls"; + private static final String GET_ACLS_READERS = "api/solr/aclsReaders"; + private static final String GET_TRANSACTIONS_URL = "api/solr/transactions"; + private static final String GET_METADATA_URL = "api/solr/metadata"; + private static final String GET_NODES_URL = "api/solr/nodes"; + private static final String GET_CONTENT = "api/solr/textContent"; + private static final String GET_MODEL = "api/solr/model"; + private static final String GET_MODELS_DIFF = "api/solr/modelsdiff"; + + private static final String CHECKSUM_HEADER = "XAlfresco-modelChecksum"; + + private AlfrescoHttpClient repositoryHttpClient; + private SOLRDeserializer deserializer; + private DictionaryService dictionaryService; + private JsonFactory jsonFactory; + private NamespaceDAO namespaceDAO; + + public SOLRAPIClient(AlfrescoHttpClient repositoryHttpClient, + DictionaryService dictionaryService, + NamespaceDAO namespaceDAO) + { + this.repositoryHttpClient = repositoryHttpClient; + this.dictionaryService = dictionaryService; + this.namespaceDAO = namespaceDAO; + this.deserializer = new SOLRDeserializer(namespaceDAO); + this.jsonFactory = new JsonFactory(); + } + + /** + * Get the ACL ChangeSets + * + * @param fromCommitTime the lowest commit time (optional) + * @param minAclChangeSetId the lowest ChangeSet ID (optional) + * @param maxResults the maximum number of results (a reasonable value only) + * @return the ACL ChangeSets in order of commit time and ID + */ + public AclChangeSets getAclChangeSets(Long fromCommitTime, Long minAclChangeSetId, Long toCommitTime, Long maxAclChangeSetId, int maxResults) + throws AuthenticationException, IOException, JSONException + { + StringBuilder url = new StringBuilder(GET_ACL_CHANGESETS_URL); + StringBuilder args = new StringBuilder(); + if (fromCommitTime != null) + { + args.append("?").append("fromTime").append("=").append(fromCommitTime); + } + if (minAclChangeSetId != null) + { + args.append(args.length() == 0 ? "?" : "&").append("fromId").append("=").append(minAclChangeSetId); + } + if (toCommitTime != null) + { + args.append(args.length() == 0 ? "?" : "&").append("toTime").append("=").append(toCommitTime); + } + if (maxAclChangeSetId != null) + { + args.append(args.length() == 0 ? "?" : "&").append("toId").append("=").append(maxAclChangeSetId); + } + if (maxResults != 0 && maxResults != Integer.MAX_VALUE) + { + args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); + } + url.append(args); + + GetRequest req = new GetRequest(url.toString()); + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + + if (response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if (log.isDebugEnabled()) + { + log.debug(json.toString(3)); + } + + JSONArray aclChangeSetsJSON = json.getJSONArray("aclChangeSets"); + List aclChangeSets = new ArrayList(aclChangeSetsJSON.length()); + for (int i = 0; i < aclChangeSetsJSON.length(); i++) + { + JSONObject aclChangeSetJSON = aclChangeSetsJSON.getJSONObject(i); + long aclChangeSetId = aclChangeSetJSON.getLong("id"); + long commitTimeMs = aclChangeSetJSON.getLong("commitTimeMs"); + int aclCount = aclChangeSetJSON.getInt("aclCount"); + AclChangeSet aclChangeSet = new AclChangeSet(aclChangeSetId, commitTimeMs, aclCount); + aclChangeSets.add(aclChangeSet); + } + + + Long maxChangeSetCommitTime = null; + if(json.has("maxChangeSetCommitTime")) + { + maxChangeSetCommitTime = json.getLong("maxChangeSetCommitTime"); + } + + Long maxChangeSetIdOnServer = null; + if(json.has("maxChangeSetId")) + { + maxChangeSetIdOnServer = json.getLong("maxChangeSetId"); + } + + // Done + return new AclChangeSets(aclChangeSets, maxChangeSetCommitTime, maxChangeSetIdOnServer); + } + + /** + * Get the ACLs associated with a given list of ACL ChangeSets. The ACLs may be truncated for + * the last ACL ChangeSet in the return values - the ACL count from the + * {@link #getAclChangeSets(Long, Long, Long, Long, int) ACL ChangeSets}. + * + * @param aclChangeSets the ACL ChangeSets to include + * @param minAclId the lowest ACL ID (may be null) + * @param maxResults the maximum number of results to retrieve + * @return the ACLs (includes ChangeSet ID) + */ + public List getAcls(List aclChangeSets, Long minAclId, int maxResults) throws AuthenticationException, IOException, JSONException + { + StringBuilder url = new StringBuilder(GET_ACLS); + StringBuilder args = new StringBuilder(); + if (minAclId != null) + { + args.append("?").append("fromId").append("=").append(minAclId); + } + + if(maxResults >= 0) + { + args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); + } + + url.append(args); + + JSONObject jsonReq = new JSONObject(); + JSONArray aclChangeSetIdsJSON = new JSONArray(); + List aclChangeSetIds = new ArrayList(); + for (AclChangeSet aclChangeSet : aclChangeSets) + { + Long aclChangeSetId = aclChangeSet.getId(); + aclChangeSetIdsJSON.put(aclChangeSetId); + aclChangeSetIds.add(aclChangeSetId); + } + jsonReq.put("aclChangeSetIds", aclChangeSetIdsJSON); + + PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json"); + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + + if (response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException(GET_ACL_CHANGESETS_URL + " return status:" + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if (log.isDebugEnabled()) + { + log.debug(json.toString(3)); + } + + JSONArray aclsJSON = json.getJSONArray("acls"); + List acls = new ArrayList(aclsJSON.length()); + for (int i = 0; i < aclsJSON.length(); i++) + { + JSONObject aclJSON = aclsJSON.getJSONObject(i); + long aclChangeSetId = aclJSON.getLong("aclChangeSetId"); + long aclId = aclJSON.getLong("id"); + Acl acl = new Acl(aclChangeSetId, aclId); + acls.add(acl); + } + // Done + return acls; + } + + /** + * Get the ACL readers for a given list of ACLs + * + * @param acls the ACLs + * @return the readers for the ACLs + */ + public List getAclReaders(List acls) throws AuthenticationException, IOException, JSONException + { + StringBuilder url = new StringBuilder(GET_ACLS_READERS); + + JSONObject jsonReq = new JSONObject(); + JSONArray aclIdsJSON = new JSONArray(); + List aclIds = new ArrayList(); + for (Acl acl : acls) + { + Long aclId = acl.getId(); + aclIdsJSON.put(aclId); + aclIds.add(aclId); + } + jsonReq.put("aclIds", aclIdsJSON); + + PostRequest req = new PostRequest(url.toString(), jsonReq.toString(), "application/json"); + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + + if (response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException(GET_ACLS_READERS + " return status:" + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if (log.isDebugEnabled()) + { + log.debug(json.toString(3)); + } + + JSONArray aclsReadersJSON = json.getJSONArray("aclsReaders"); + List aclsReaders = new ArrayList(aclsReadersJSON.length()); + for (int i = 0; i < aclsReadersJSON.length(); i++) + { + JSONObject aclReadersJSON = aclsReadersJSON.getJSONObject(i); + long aclId = aclReadersJSON.getLong("aclId"); + JSONArray readersJSON = aclReadersJSON.getJSONArray("readers"); + List readers = authorityListFromJSON(readersJSON); + JSONArray deniedJSON = aclReadersJSON.getJSONArray("denied"); + List denied = authorityListFromJSON(deniedJSON); + long aclChangeSetId = aclReadersJSON.getLong("aclChangeSetId"); + + String tenantDomain = aclReadersJSON.getString("tenantDomain"); + if (tenantDomain == null) + { + tenantDomain = TenantService.DEFAULT_DOMAIN; + } + + AclReaders aclReaders = new AclReaders(aclId, readers, denied, aclChangeSetId, tenantDomain); + aclsReaders.add(aclReaders); + } + // Done + return aclsReaders; + } + + /** + * Convert a JSON array of authorities to a simple Java List<String> + * + * @param jsonArray JSONArray + * @return List<String> + * @throws JSONException + */ + private List authorityListFromJSON(JSONArray jsonArray) throws JSONException + { + List authorities = new ArrayList(jsonArray.length()); + for (int j = 0; j < jsonArray.length(); j++) + { + String authority = jsonArray.getString(j); + authorities.add(authority); + } + return authorities; + } + + public Transactions getTransactions(Long fromCommitTime, Long minTxnId, Long toCommitTime, Long maxTxnId, int maxResults) throws AuthenticationException, IOException, JSONException + { + try + { + return getTransactions(fromCommitTime, minTxnId, toCommitTime, maxTxnId, maxResults, null); + } + catch (EncoderException e) + { + // Can not happen .... + throw new IOException(e); + } + } + + public Transactions getTransactions(Long fromCommitTime, Long minTxnId, Long toCommitTime, Long maxTxnId, int maxResults, ShardState shardState) throws AuthenticationException, IOException, JSONException, EncoderException + { + URLCodec encoder = new URLCodec(); + + StringBuilder url = new StringBuilder(GET_TRANSACTIONS_URL); + StringBuilder args = new StringBuilder(); + if (fromCommitTime != null) + { + args.append("?").append("fromCommitTime").append("=").append(fromCommitTime); + } + if (minTxnId != null) + { + args.append(args.length() == 0 ? "?" : "&").append("minTxnId").append("=").append(minTxnId); + } + if (toCommitTime != null) + { + args.append(args.length() == 0 ? "?" : "&").append("toCommitTime").append("=").append(toCommitTime); + } + if (maxTxnId != null) + { + args.append(args.length() == 0 ? "?" : "&").append("maxTxnId").append("=").append(maxTxnId); + } + if (maxResults != 0 && maxResults != Integer.MAX_VALUE) + { + args.append(args.length() == 0 ? "?" : "&").append("maxResults").append("=").append(maxResults); + } + if(shardState != null) + { + args.append(args.length() == 0 ? "?" : "&"); + args.append(encoder.encode("baseUrl")).append("=").append(encoder.encode(shardState.getShardInstance().getBaseUrl())); + args.append("&").append(encoder.encode("hostName")).append("=").append(encoder.encode(shardState.getShardInstance().getHostName())); + args.append("&").append(encoder.encode("template")).append("=").append(encoder.encode(shardState.getShardInstance().getShard().getFloc().getTemplate())); + + for(String key : shardState.getShardInstance().getShard().getFloc().getPropertyBag().keySet()) + { + String value = shardState.getShardInstance().getShard().getFloc().getPropertyBag().get(key); + if(value != null) + { + args.append("&").append(encoder.encode("floc.property."+key)).append("=").append(encoder.encode(value)); + } + } + + for(String key : shardState.getPropertyBag().keySet()) + { + String value = shardState.getPropertyBag().get(key); + if(value != null) + { + args.append("&").append(encoder.encode("state.property."+key)).append("=").append(encoder.encode(value)); + } + } + + args.append("&").append(encoder.encode("instance")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getInstance())); + args.append("&").append(encoder.encode("numberOfShards")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getFloc().getNumberOfShards())); + args.append("&").append(encoder.encode("port")).append("=").append(encoder.encode("" + shardState.getShardInstance().getPort())); + args.append("&").append(encoder.encode("stores")).append("="); + for(StoreRef store : shardState.getShardInstance().getShard().getFloc().getStoreRefs()) + { + if(args.charAt(args.length()-1) != '=') + { + args.append(encoder.encode(",")); + } + args.append(encoder.encode(store.toString())); + } + args.append("&").append(encoder.encode("isMaster")).append("=").append(encoder.encode("" + shardState.isMaster())); + args.append("&").append(encoder.encode("hasContent")).append("=").append(encoder.encode("" + shardState.getShardInstance().getShard().getFloc().hasContent())); + args.append("&").append(encoder.encode("shardMethod")).append("=").append(encoder.encode(shardState.getShardInstance().getShard().getFloc().getShardMethod().toString())); + + args.append("&").append(encoder.encode("lastUpdated")).append("=").append(encoder.encode("" + shardState.getLastUpdated())); + args.append("&").append(encoder.encode("lastIndexedChangeSetCommitTime")).append("=").append(encoder.encode("" + shardState.getLastIndexedChangeSetCommitTime())); + args.append("&").append(encoder.encode("lastIndexedChangeSetId")).append("=").append(encoder.encode("" + shardState.getLastIndexedChangeSetId())); + args.append("&").append(encoder.encode("lastIndexedTxCommitTime")).append("=").append(encoder.encode("" + shardState.getLastIndexedTxCommitTime())); + args.append("&").append(encoder.encode("lastIndexedTxId")).append("=").append(encoder.encode("" + shardState.getLastIndexedTxId())); + + } + + url.append(args); + + GetRequest req = new GetRequest(url.toString()); + Response response = null; + List transactions = new ArrayList(); + Long maxTxnCommitTime = null; + Long maxTxnIdOnServer = null; + try + { + response = repositoryHttpClient.sendRequest(req); + if(response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException("GetTransactions return status is " + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + JsonParser parser = jsonFactory.createJsonParser(reader); + + JsonToken token = parser.nextValue(); + while (token != null) + { + if ("transactions".equals(parser.getCurrentName())) + { + token = parser.nextToken(); //START_ARRAY + while (token == JsonToken.START_OBJECT) + { + token = parser.nextValue(); + long id = parser.getLongValue(); + + token = parser.nextValue(); + long commitTime = parser.getLongValue(); + + token = parser.nextValue(); + long updates = parser.getLongValue(); + + token = parser.nextValue(); + long deletes = parser.getLongValue(); + + Transaction txn = new Transaction(); + txn.setCommitTimeMs(commitTime); + txn.setDeletes(deletes); + txn.setId(id); + txn.setUpdates(updates); + + transactions.add(txn); + + token = parser.nextToken(); //END_OBJECT + token = parser.nextToken(); // START_OBJECT or END_ARRAY; + } + } + else if ("maxTxnCommitTime".equals(parser.getCurrentName())) + { + maxTxnCommitTime = parser.getLongValue(); + } + else if ("maxTxnId".equals(parser.getCurrentName())) + { + maxTxnIdOnServer = parser.getLongValue(); + } + token = parser.nextValue(); + } + parser.close(); + reader.close(); + + } + finally + { + if(response != null) + { + response.release(); + } + } + + return new Transactions(transactions, maxTxnCommitTime, maxTxnIdOnServer); + } + + public List getNodes(GetNodesParameters parameters, int maxResults) throws AuthenticationException, IOException, JSONException + { + StringBuilder url = new StringBuilder(GET_NODES_URL); + + JSONObject body = new JSONObject(); + + if(parameters.getTransactionIds() != null) + { + JSONArray jsonTxnIds = new JSONArray(); + for(Long txnId : parameters.getTransactionIds()) + { + jsonTxnIds.put(txnId); + } + body.put("txnIds", jsonTxnIds); + } + + if(parameters.getFromNodeId() != null) + { + body.put("fromNodeId", parameters.getFromNodeId()); + } + if(parameters.getToNodeId() != null) + { + body.put("toNodeId", parameters.getToNodeId()); + } + if(parameters.getExcludeAspects() != null) + { + JSONArray jsonExcludeAspects = new JSONArray(); + for(QName excludeAspect : parameters.getExcludeAspects()) + { + jsonExcludeAspects.put(excludeAspect.toString()); + } + body.put("excludeAspects", jsonExcludeAspects); + } + if(parameters.getIncludeAspects() != null) + { + JSONArray jsonIncludeAspects = new JSONArray(); + for(QName includeAspect : parameters.getIncludeAspects()) + { + jsonIncludeAspects.put(includeAspect.toString()); + } + body.put("includeAspects", jsonIncludeAspects); + } + + if(parameters.getStoreProtocol() != null) + { + body.put("storeProtocol", parameters.getStoreProtocol()); + } + + if(parameters.getStoreIdentifier() != null) + { + body.put("storeIdentifier", parameters.getStoreIdentifier()); + } + + body.put("maxResults", maxResults); + + PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); + + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + if(response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException("GetNodes return status is " + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if(log.isDebugEnabled()) + { + log.debug(json.toString()); + } + + JSONArray jsonNodes = json.getJSONArray("nodes"); + List nodes = new ArrayList(jsonNodes.length()); + for(int i = 0; i < jsonNodes.length(); i++) + { + JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i); + Node nodeInfo = new Node(); + if(jsonNodeInfo.has("id")) + { + nodeInfo.setId(jsonNodeInfo.getLong("id")); + } + + if(jsonNodeInfo.has("nodeRef")) + { + nodeInfo.setNodeRef(jsonNodeInfo.getString("nodeRef")); + } + + if(jsonNodeInfo.has("txnId")) + { + nodeInfo.setTxnId(jsonNodeInfo.getLong("txnId")); + } + + if(jsonNodeInfo.has("aclId")) + { + nodeInfo.setAclId(jsonNodeInfo.getLong("aclId")); + } + + if(jsonNodeInfo.has("tenant")) + { + nodeInfo.setTenant(jsonNodeInfo.getString("tenant")); + } + + if(jsonNodeInfo.has("status")) + { + Node.SolrApiNodeStatus status; + String statusStr = jsonNodeInfo.getString("status"); + if(statusStr.equals("u")) + { + status = Node.SolrApiNodeStatus.UPDATED; + } + else if(statusStr.equals("d")) + { + status = Node.SolrApiNodeStatus.DELETED; + } + else + { + status = Node.SolrApiNodeStatus.UNKNOWN; + } + nodeInfo.setStatus(status); + } + + nodes.add(nodeInfo); + } + + return nodes; + } + + private PropertyValue getSinglePropertyValue(DataTypeDefinition dataType, Object value) throws JSONException + { + PropertyValue ret = null; + QName dataTypeName = dataType.getName(); + + if(value == null || value == JSONObject.NULL) + { + ret = null; + } + else if(dataTypeName.equals(DataTypeDefinition.MLTEXT)) + { + JSONArray a = (JSONArray)value; + Map mlValues = new HashMap(a.length()); + + for(int k = 0; k < a.length(); k++) + { + JSONObject pair = a.getJSONObject(k); + Locale locale = deserializer.deserializeValue(Locale.class, pair.getString("locale")); + String mlValue = pair.has("value") ? pair.getString("value") : null; + mlValues.put(locale, mlValue); + } + + ret = new MLTextPropertyValue(mlValues); + } + else if(dataTypeName.equals(DataTypeDefinition.CONTENT)) + { + JSONObject o = (JSONObject)value; + + String localeStr = o.has("locale") ? o.getString("locale") : null; + Locale locale = (o.has("locale") ? deserializer.deserializeValue(Locale.class, localeStr) : null); + + Long size = o.has("size") ? o.getLong("size") : null; + + String encoding = o.has("encoding") ? o.getString("encoding") : null; + String mimetype = o.has("mimetype") ? o.getString("mimetype") : null; + + Long id = o.has("contentId") ? o.getLong("contentId") : null; + + ret = new ContentPropertyValue(locale, size, encoding, mimetype, id); + } + else + { + ret = new StringPropertyValue((String)value); + } + + return ret; + } + + private PropertyValue getPropertyValue(PropertyDefinition propertyDef, Object value) throws JSONException + { + PropertyValue ret = null; + + if(value == null || value == JSONObject.NULL) + { + ret = null; + } + else if(propertyDef == null) + { + // assume a string + ret = new StringPropertyValue((String)value); + } + else + { + DataTypeDefinition dataType = propertyDef.getDataType(); + + boolean isMulti = propertyDef.isMultiValued(); + if(isMulti) + { + if(!(value instanceof JSONArray)) + { + throw new IllegalArgumentException("Expected json array, got " + value.getClass().getName()); + } + + MultiPropertyValue multi = new MultiPropertyValue(); + JSONArray array = (JSONArray)value; + for(int j = 0; j < array.length(); j++) + { + multi.addValue(getSinglePropertyValue(dataType, array.get(j))); + } + + ret = multi; + } + else + { + ret = getSinglePropertyValue(dataType, value); + } + } + + return ret; + } + + public List getNodesMetaData(NodeMetaDataParameters params, int maxResults) throws AuthenticationException, IOException, JSONException + { + List nodeIds = params.getNodeIds(); + + StringBuilder url = new StringBuilder(GET_METADATA_URL); + + JSONObject body = new JSONObject(); + if(nodeIds != null && nodeIds.size() > 0) + { + JSONArray jsonNodeIds = new JSONArray(); + for(Long nodeId : nodeIds) + { + jsonNodeIds.put(nodeId); + } + body.put("nodeIds", jsonNodeIds); + + } + if(params.getFromNodeId() != null) + { + body.put("fromNodeId", params.getFromNodeId()); + } + if(params.getToNodeId() != null) + { + body.put("toNodeId", params.getToNodeId()); + } + + // only need to set in cases where we don't want them in the response + // because they default to true + if(!params.isIncludeAclId()) + { + body.put("includeAclId", params.isIncludeAclId()); + } + if(!params.isIncludeAspects()) + { + body.put("includeAspects", params.isIncludeAspects()); + } + if(!params.isIncludeProperties()) + { + body.put("includeProperties", params.isIncludeProperties()); + } + if(!params.isIncludeChildAssociations()) + { + body.put("includeChildAssociations", params.isIncludeChildAssociations()); + } + if(!params.isIncludeParentAssociations()) + { + body.put("includeParentAssociations", params.isIncludeParentAssociations()); + } + if(!params.isIncludeChildIds()) + { + body.put("includeChildIds", params.isIncludeChildIds()); + } + if(!params.isIncludePaths()) + { + body.put("includePaths", params.isIncludePaths()); + } + if(!params.isIncludeOwner()) + { + body.put("includeOwner", params.isIncludeOwner()); + } + if(!params.isIncludeNodeRef()) + { + body.put("includeNodeRef", params.isIncludeNodeRef()); + } + if(!params.isIncludeTxnId()) + { + body.put("includeTxnId", params.isIncludeTxnId()); + } + + body.put("maxResults", maxResults); + + PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + if(response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException("GetNodeMetaData return status is " + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if (log.isDebugEnabled()) + { + log.debug(json.toString(3)); + } + + JSONArray jsonNodes = json.getJSONArray("nodes"); + + List nodes = new ArrayList(jsonNodes.length()); + for(int i = 0; i < jsonNodes.length(); i++) + { + JSONObject jsonNodeInfo = jsonNodes.getJSONObject(i); + NodeMetaData metaData = new NodeMetaData(); + + if(jsonNodeInfo.has("id")) + { + metaData.setId(jsonNodeInfo.getLong("id")); + } + + if(jsonNodeInfo.has("tenantDomain")) + { + metaData.setTenantDomain(jsonNodeInfo.getString("tenantDomain")); + } + + if(jsonNodeInfo.has("txnId")) + { + metaData.setTxnId(jsonNodeInfo.getLong("txnId")); + } + + if(jsonNodeInfo.has("aclId")) + { + metaData.setAclId(jsonNodeInfo.getLong("aclId")); + } + + if(jsonNodeInfo.has("nodeRef")) + { + metaData.setNodeRef(new NodeRef(jsonNodeInfo.getString("nodeRef"))); + } + + if(jsonNodeInfo.has("type")) + { + metaData.setType(deserializer.deserializeValue(QName.class, jsonNodeInfo.getString("type"))); + } + + if(jsonNodeInfo.has("aspects")) + { + JSONArray jsonAspects = jsonNodeInfo.getJSONArray("aspects"); + Set aspects = new HashSet(jsonAspects.length()); + for(int j = 0; j < jsonAspects.length(); j++) + { + String jsonAspect = (String)jsonAspects.get(j); + aspects.add(deserializer.deserializeValue(QName.class, jsonAspect)); + } + metaData.setAspects(aspects); + } + + if(jsonNodeInfo.has("paths")) + { + JSONArray jsonPaths = jsonNodeInfo.getJSONArray("paths"); + List> paths = new ArrayList>(jsonPaths.length()); + for(int j = 0; j < jsonPaths.length(); j++) + { + JSONObject path = new JSONObject(jsonPaths.getString(j)); + String pathValue = path.getString("path"); + QName qname = path.has("qname") ? deserializer.deserializeValue(QName.class, path.getString("qname")) : null; + paths.add(new Pair(pathValue, qname)); + } + metaData.setPaths(paths); + } + + if(jsonNodeInfo.has("namePaths")) + { + JSONArray jsonNamePaths = jsonNodeInfo.getJSONArray("namePaths"); + List> namePaths = new ArrayList>(jsonNamePaths.length()); + for(int j = 0; j < jsonNamePaths.length(); j++) + { + JSONObject jsonNamePath = jsonNamePaths.getJSONObject(j); + JSONArray jsonNameElements = jsonNamePath.getJSONArray("namePath"); + List namePath = new ArrayList(jsonNameElements.length()); + for(int k = 0; k < jsonNameElements.length(); k++) + { + String namePathElement = jsonNameElements.getString(k); + namePath.add(namePathElement); + } + namePaths.add(namePath); + } + metaData.setNamePaths(namePaths); + } + + if(jsonNodeInfo.has("ancestors")) + { + JSONArray jsonAncestors = jsonNodeInfo.getJSONArray("ancestors"); + HashSet ancestors = new HashSet(jsonAncestors.length()); + for(int j = 0; j < jsonAncestors.length(); j++) + { + String ancestorNodeRefString = jsonAncestors.getString(j); + NodeRef ancestorNodeRef = new NodeRef(ancestorNodeRefString); + ancestors.add(ancestorNodeRef); + } + metaData.setAncestors(ancestors); + } + + if(jsonNodeInfo.has("properties")) + { + JSONObject jsonProperties = jsonNodeInfo.getJSONObject("properties"); + Map properties = new HashMap(jsonProperties.length()); + @SuppressWarnings("rawtypes") + Iterator propKeysIterator = jsonProperties.keys(); + while(propKeysIterator.hasNext()) + { + String propName = (String)propKeysIterator.next(); + QName propQName = deserializer.deserializeValue(QName.class, propName); + Object propValueObj = jsonProperties.opt(propName); + + // check the expected property type to determine how to process the value + PropertyDefinition propertyDef = dictionaryService.getProperty(propQName); +// if(propertyDef == null) +// { +// // TODO which exception here? +// throw new IllegalArgumentException("Could not find property definition for property " + propName); +// } + + properties.put(propQName, getPropertyValue(propertyDef, propValueObj)); + } + metaData.setProperties(properties); + } + + if(jsonNodeInfo.has("parentAssocsCrc")) + { + metaData.setParentAssocsCrc(jsonNodeInfo.getLong("parentAssocsCrc")); + } + + if(jsonNodeInfo.has("parentAssocs")) + { + JSONArray jsonParentAssocs = jsonNodeInfo.getJSONArray("parentAssocs"); + List assocs = new ArrayList(jsonParentAssocs.length()); + for(int j = 0; j < jsonParentAssocs.length(); j++) + { + String childAssocRefStr = jsonParentAssocs.getString(j); + ChildAssociationRef childAssociationRef = new ChildAssociationRef(childAssocRefStr); + assocs.add(childAssociationRef); + } + metaData.setParentAssocs(assocs); + } + + if(jsonNodeInfo.has("childAssocs")) + { + JSONArray jsonParentAssocs = jsonNodeInfo.getJSONArray("childAssocs"); + List assocs = new ArrayList(jsonParentAssocs.length()); + for(int j = 0; j < jsonParentAssocs.length(); j++) + { + String childAssocRefStr = jsonParentAssocs.getString(j); + ChildAssociationRef childAssociationRef = new ChildAssociationRef(childAssocRefStr); + assocs.add(childAssociationRef); + } + metaData.setChildAssocs(assocs); + } + + if(jsonNodeInfo.has("childIds")) + { + JSONArray jsonChildIds = jsonNodeInfo.getJSONArray("childIds"); + List childIds = new ArrayList(jsonChildIds.length()); + for(int j = 0; j < jsonChildIds.length(); j++) + { + Long childId = jsonChildIds.getLong(j); + childIds.add(childId); + } + metaData.setChildIds(childIds); + } + + if(jsonNodeInfo.has("owner")) + { + metaData.setOwner(jsonNodeInfo.getString("owner")); + } + + nodes.add(metaData); + } + + return nodes; + } + + public GetTextContentResponse getTextContent(Long nodeId, QName propertyQName, Long modifiedSince) throws AuthenticationException, IOException + { + StringBuilder url = new StringBuilder(128); + url.append(GET_CONTENT); + + StringBuilder args = new StringBuilder(128); + if(nodeId != null) + { + args.append("?"); + args.append("nodeId"); + args.append("="); + args.append(nodeId); + } + else + { + throw new NullPointerException("getTextContent(): nodeId cannot be null."); + } + if(propertyQName != null) + { + if(args.length() == 0) + { + args.append("?"); + } + else + { + args.append("&"); + } + args.append("propertyQName"); + args.append("="); + args.append(URLEncoder.encode(propertyQName.toString())); + } + + url.append(args); + + GetRequest req = new GetRequest(url.toString()); + + if(modifiedSince != null) + { + Map headers = new HashMap(1, 1.0f); + headers.put("If-Modified-Since", String.valueOf(DateUtil.formatDate(new Date(modifiedSince)))); + req.setHeaders(headers); + } + + Response response = repositoryHttpClient.sendRequest(req); + + if(response.getStatus() != Status.STATUS_NOT_MODIFIED && response.getStatus() != Status.STATUS_NO_CONTENT && response.getStatus() != Status.STATUS_OK) + { + throw new AlfrescoRuntimeException("GetTextContentResponse return status is " + response.getStatus()); + } + + return new GetTextContentResponse(response); + } + + public AlfrescoModel getModel(QName modelName) throws AuthenticationException, IOException, JSONException + { + // If the model is new to the SOLR side the prefix will be unknown so we can not generate prefixes for the request! + // Always use the full QName with explicit URI + StringBuilder url = new StringBuilder(GET_MODEL); + + URLCodec encoder = new URLCodec(); + // must send the long name as we may not have the prefix registered + url.append("?modelQName=").append(encoder.encode(modelName.toString(), "UTF-8")); + + GetRequest req = new GetRequest(url.toString()); + + Response response = null; + try + { + response = repositoryHttpClient.sendRequest(req); + if(response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException("GetModel return status is " + response.getStatus()); + } + + return new AlfrescoModel(M2Model.createModel(response.getContentAsStream()), + Long.valueOf(response.getHeader(CHECKSUM_HEADER))); + } + finally + { + if(response != null) + { + response.release(); + } + } + } + + public List getModelsDiff(List currentModels) throws AuthenticationException, IOException, JSONException + { + StringBuilder url = new StringBuilder(GET_MODELS_DIFF); + + JSONObject body = new JSONObject(); + JSONArray jsonModels = new JSONArray(); + for(AlfrescoModel model : currentModels) + { + JSONObject jsonModel = new JSONObject(); + QName modelQName = QName.createQName( model.getModel().getName(), namespaceDAO); + jsonModel.put("name", modelQName.toString()); + jsonModel.put("checksum", model.getChecksum()); + jsonModels.put(jsonModel); + } + body.put("models", jsonModels); + + PostRequest req = new PostRequest(url.toString(), body.toString(), "application/json"); + Response response = null; + JSONObject json = null; + try + { + response = repositoryHttpClient.sendRequest(req); + if(response.getStatus() != HttpStatus.SC_OK) + { + throw new AlfrescoRuntimeException("GetModelsDiff return status is " + response.getStatus()); + } + + Reader reader = new BufferedReader(new InputStreamReader(response.getContentAsStream(), "UTF-8")); + json = new JSONObject(new JSONTokener(reader)); + } + finally + { + if(response != null) + { + response.release(); + } + } + + if(log.isDebugEnabled()) + { + log.debug(json.toString()); + } + JSONArray jsonDiffs = json.getJSONArray("diffs"); + if(jsonDiffs == null) + { + throw new AlfrescoRuntimeException("GetModelsDiff badly formatted response"); + } + + List diffs = new ArrayList(jsonDiffs.length()); + for(int i = 0; i < jsonDiffs.length(); i++) + { + JSONObject jsonDiff = jsonDiffs.getJSONObject(i); + diffs.add(new AlfrescoModelDiff( + QName.createQName(jsonDiff.getString("name")), + AlfrescoModelDiff.TYPE.valueOf(jsonDiff.getString("type")), + (jsonDiff.isNull("oldChecksum") ? null : jsonDiff.getLong("oldChecksum")), + (jsonDiff.isNull("newChecksum") ? null : jsonDiff.getLong("newChecksum")))); + } + + return diffs; + } + + /* + * type conversions from serialized JSON values to SOLR-consumable objects + */ + @SuppressWarnings("rawtypes") + private class SOLRTypeConverter + { + /** + * Default Type Converter + */ + private TypeConverter instance = new TypeConverter(); + private NamespaceDAO namespaceDAO; + + @SuppressWarnings("unchecked") + SOLRTypeConverter(NamespaceDAO namespaceDAO) + { + this.namespaceDAO = namespaceDAO; + + // add all default converters to this converter + // TODO find a better way of doing this + Map, Map, Converter>> converters = DefaultTypeConverter.INSTANCE.getConverters(); + for(Class source : converters.keySet()) + { + Map, Converter> converters1 = converters.get(source); + for(Class dest : converters1.keySet()) + { + Converter converter = converters1.get(dest); + instance.addConverter(source, dest, converter); + } + } + + // dates + instance.addConverter(String.class, Date.class, new TypeConverter.Converter() + { + public Date convert(String source) + { + try + { + Date date = ISO8601DateFormat.parse(source); + return date; + } + catch (Exception e) + { + throw new TypeConversionException("Failed to convert date " + source + " to string", e); + } + } + }); + + // node refs + instance.addConverter(String.class, NodeRef.class, new TypeConverter.Converter() + { + public NodeRef convert(String source) + { + return new NodeRef(source); + } + }); + + // paths + instance.addConverter(String.class, AttributeElement.class, new TypeConverter.Converter() + { + public AttributeElement convert(String source) + { + return new Path.AttributeElement(source); + } + }); + + instance.addConverter(String.class, ChildAssocElement.class, new TypeConverter.Converter() + { + public ChildAssocElement convert(String source) + { + return new Path.ChildAssocElement(instance.convert(ChildAssociationRef.class, source)); + } + }); + + instance.addConverter(String.class, Path.DescendentOrSelfElement.class, new TypeConverter.Converter() + { + public Path.DescendentOrSelfElement convert(String source) + { + return new Path.DescendentOrSelfElement(); + } + }); + + instance.addConverter(String.class, Path.ParentElement.class, new TypeConverter.Converter() + { + public Path.ParentElement convert(String source) + { + return new Path.ParentElement(); + } + }); + + instance.addConverter(String.class, Path.SelfElement.class, new TypeConverter.Converter() + { + public Path.SelfElement convert(String source) + { + return new Path.SelfElement(); + } + }); + + // associations + instance.addConverter(String.class, ChildAssociationRef.class, new TypeConverter.Converter() + { + public ChildAssociationRef convert(String source) + { + return new ChildAssociationRef(source); + } + }); + + instance.addConverter(String.class, AssociationRef.class, new TypeConverter.Converter() + { + public AssociationRef convert(String source) + { + return new AssociationRef(source); + } + }); + + // qnames + instance.addConverter(String.class, QName.class, new TypeConverter.Converter() + { + public QName convert(String source) + { + return QName.resolveToQName(SOLRTypeConverter.this.namespaceDAO, source); + } + }); + + instance.addConverter(String.class, MLText.class, new TypeConverter.Converter() + { + public MLText convert(String source) + { + return new MLText(source); + } + }); + } + + public final T convert(Class c, Object value) + { + return instance.convert(c, value); + } + } + + /* + * Deserializes JSON values from the remote API into objects consumable by SOLR + */ + private class SOLRDeserializer + { + private SOLRTypeConverter typeConverter; + + public SOLRDeserializer(NamespaceDAO namespaceDAO) + { + typeConverter = new SOLRTypeConverter(namespaceDAO); + } + + public T deserializeValue(Class targetClass, Object value) throws JSONException + { + return typeConverter.convert(targetClass, value); + } + } + + private static class SOLRResponse + { + protected Response response; + + public SOLRResponse(Response response) + { + super(); + this.response = response; + } + + public Response getResponse() + { + return response; + } + } + + public static class GetTransactionsResponse extends SOLRResponse + { + private List txns; + + public GetTransactionsResponse(Response response, List txns) + { + super(response); + this.txns = txns; + } + + public List getTransaction() + { + return txns; + } + } + + public static class GetNodesResponse extends SOLRResponse + { + private List nodes; + + public GetNodesResponse(Response response, List nodes) + { + super(response); + this.nodes = nodes; + } + + public List getNodes() + { + return nodes; + } + } + + public static class GetNodesMetaDataResponse extends SOLRResponse + { + private List nodes; + + public GetNodesMetaDataResponse(Response response, List nodes) + { + super(response); + this.nodes = nodes; + } + + public List getNodes() + { + return nodes; + } + } + + public static enum SolrApiContentStatus + { + NOT_MODIFIED, OK, NO_TRANSFORM, NO_CONTENT, UNKNOWN, TRANSFORM_FAILED, GENERAL_FAILURE; + + public static SolrApiContentStatus getStatus(String statusStr) + { + if(statusStr.equals("ok")) + { + return OK; + } + else if(statusStr.equals("transformFailed")) + { + return TRANSFORM_FAILED; + } + else if(statusStr.equals("noTransform")) + { + return NO_TRANSFORM; + } + else if(statusStr.equals("noContent")) + { + return NO_CONTENT; + } + else + { + return UNKNOWN; + } + } + } + + // TODO register a stream close listener that release the response when the response has been read + public static class GetTextContentResponse extends SOLRResponse + { + private InputStream content; + private SolrApiContentStatus status; + private String transformException; + private String transformStatusStr; + private Long transformDuration; + + public GetTextContentResponse(Response response) throws IOException + { + super(response); + + this.content = response.getContentAsStream(); + this.transformStatusStr = response.getHeader("X-Alfresco-transformStatus"); + this.transformException = response.getHeader("X-Alfresco-transformException"); + String tmp = response.getHeader("X-Alfresco-transformDuration"); + this.transformDuration = (tmp != null ? Long.valueOf(tmp) : null); + setStatus(); + } + + public InputStream getContent() + { + return content; + } + + public SolrApiContentStatus getStatus() + { + return status; + } + + private void setStatus() + { + int status = response.getStatus(); + if(status == HttpStatus.SC_NOT_MODIFIED) + { + this.status = SolrApiContentStatus.NOT_MODIFIED; + } + else if(status == HttpStatus.SC_INTERNAL_SERVER_ERROR) + { + this.status = SolrApiContentStatus.GENERAL_FAILURE; + } + else if(status == HttpStatus.SC_OK) + { + this.status = SolrApiContentStatus.OK; + } + else if(status == HttpStatus.SC_NO_CONTENT) + { + if(transformStatusStr == null) + { + this.status = SolrApiContentStatus.UNKNOWN; + } + else + { + if(transformStatusStr.equals("noTransform")) + { + this.status = SolrApiContentStatus.NO_TRANSFORM; + } + else if(transformStatusStr.equals("transformFailed")) + { + this.status = SolrApiContentStatus.TRANSFORM_FAILED; + } + else + { + this.status = SolrApiContentStatus.UNKNOWN; + } + } + } + } + + public String getTransformException() + { + return transformException; + } + + public void release() + { + response.release(); + } + + public Long getTransformDuration() + { + return transformDuration; + } + } + + public void close() + { + repositoryHttpClient.close(); + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClientFactory.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClientFactory.java index 286e6b957..25082e1a6 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClientFactory.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/SOLRAPIClientFactory.java @@ -1,163 +1,163 @@ - -package org.alfresco.solr.client; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import org.alfresco.encryption.KeyResourceLoader; -import org.alfresco.encryption.KeyStoreParameters; -import org.alfresco.encryption.ssl.SSLEncryptionParameters; -import org.alfresco.httpclient.AlfrescoHttpClient; -import org.alfresco.httpclient.HttpClientFactory; -import org.alfresco.httpclient.HttpClientFactory.SecureCommsType; -import org.alfresco.repo.dictionary.NamespaceDAO; -import org.alfresco.service.cmr.dictionary.DictionaryService; - -/** - * This factory encapsulates the creation of a SOLRAPIClient and the management of that resource. - * - * @author Ahmed Owian - */ -public class SOLRAPIClientFactory -{ - /* - * Pool of cached client resources keyed on alfresco instances - */ - private static Map clientsPerAlfresco = new HashMap<>(); - - // encryption related parameters - private String secureCommsType; // "none", "https" - private String keyStoreType; - private String keyStoreProvider; - private String passwordFileLocation; - private String keyStoreLocation; - - // ssl - private String sslKeyStoreType; - private String sslKeyStoreProvider; - private String sslKeyStoreLocation; - private String sslKeyStorePasswordFileLocation; - private String sslTrustStoreType; - private String sslTrustStoreProvider; - private String sslTrustStoreLocation; - private String sslTrustStorePasswordFileLocation; - private String alfrescoHost; - private int alfrescoPort; - private int alfrescoPortSSL; - private String baseUrl; - - // http client - private int maxTotalConnections = 40; - private int maxHostConnections = 40; - private int socketTimeout = 120000; - - /** - * Gets the client resource from the pool. - * - * @param alfrescoHost String - * @param alfrescoPort int - * @param alfrescoPortSSL int - * @return SOLRAPIClient - */ - private SOLRAPIClient getCachedClient(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL) - { - String key = constructKey(alfrescoHost, alfrescoPort, alfrescoPortSSL); - return clientsPerAlfresco.get(key); - } - - /** - * Constructs a key to identify a unique alfresco instance to which the client will connect. - * - * @param alfrescoHost String - * @param alfrescoPort int - * @param alfrescoPortSSL int - * @return the key to get a client - */ - private String constructKey(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL) - { - return alfrescoHost + alfrescoPort + alfrescoPortSSL; - } - - /** - * Sets the client in the resource pool. - * - * @param alfrescoHost String - * @param alfrescoPort int - * @param alfrescoPortSSL int - * @param client SOLRAPIClient - */ - private void setCachedClient(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL, SOLRAPIClient client) - { - String key = constructKey(alfrescoHost, alfrescoPort, alfrescoPortSSL); - clientsPerAlfresco.put(key, client); - } - - /** - * Creates the SOLRAPIClient or gets it from a pool - * - * @param props solrcore.properties in the /conf directory - * @param keyResourceLoader reads encryption key resources - * @param dictionaryService represents the Repository Data Dictionary - * @param namespaceDAO allows retrieving and creating Namespace definitions - * @return an instance of SOLRAPIClient - */ - public SOLRAPIClient getSOLRAPIClient(Properties props, KeyResourceLoader keyResourceLoader, - DictionaryService dictionaryService, NamespaceDAO namespaceDAO) - { - alfrescoHost = props.getProperty("alfresco.host", "localhost"); - alfrescoPort = Integer.parseInt(props.getProperty("alfresco.port", "8080")); - alfrescoPortSSL = Integer.parseInt(props.getProperty("alfresco.port.ssl", "8443")); - - SOLRAPIClient client = getCachedClient(alfrescoHost, alfrescoPort, alfrescoPortSSL); - if (client == null) - { - baseUrl = props.getProperty("alfresco.baseUrl", "/alfresco"); - keyStoreType = props.getProperty("alfresco.encryption.keystore.type", "JCEKS"); - keyStoreProvider = props.getProperty("alfresco.encryption.keystore.provider"); - passwordFileLocation = props.getProperty("alfresco.encryption.keystore.passwordFileLocation"); - keyStoreLocation = props.getProperty("alfresco.encryption.keystore.location"); - sslKeyStoreType = props.getProperty("alfresco.encryption.ssl.keystore.type", "JCEKS"); - sslKeyStoreProvider = props.getProperty("alfresco.encryption.ssl.keystore.provider", ""); - sslKeyStoreLocation = props.getProperty("alfresco.encryption.ssl.keystore.location", - "ssl.repo.client.keystore"); - sslKeyStorePasswordFileLocation = props.getProperty( - "alfresco.encryption.ssl.keystore.passwordFileLocation", "ssl-keystore-passwords.properties"); - sslTrustStoreType = props.getProperty("alfresco.encryption.ssl.truststore.type", "JCEKS"); - sslTrustStoreProvider = props.getProperty("alfresco.encryption.ssl.truststore.provider", ""); - sslTrustStoreLocation = props.getProperty("alfresco.encryption.ssl.truststore.location", - "ssl.repo.client.truststore"); - sslTrustStorePasswordFileLocation = props.getProperty( - "alfresco.encryption.ssl.truststore.passwordFileLocation", - "ssl-truststore-passwords.properties"); - secureCommsType = props.getProperty("alfresco.secureComms", "none"); - maxTotalConnections = Integer.parseInt(props.getProperty("alfresco.maxTotalConnections", "40")); - maxHostConnections = Integer.parseInt(props.getProperty("alfresco.maxHostConnections", "40")); - socketTimeout = Integer.parseInt(props.getProperty("alfresco.socketTimeout", "60000")); - - client = new SOLRAPIClient(getRepoClient(keyResourceLoader), dictionaryService, namespaceDAO); - setCachedClient(alfrescoHost, alfrescoPort, alfrescoPortSSL, client); - } - - return client; - } - - protected AlfrescoHttpClient getRepoClient(KeyResourceLoader keyResourceLoader) - { - // TODO i18n - KeyStoreParameters keyStoreParameters = new KeyStoreParameters("SSL Key Store", sslKeyStoreType, - sslKeyStoreProvider, sslKeyStorePasswordFileLocation, sslKeyStoreLocation); - KeyStoreParameters trustStoreParameters = new KeyStoreParameters("SSL Trust Store", sslTrustStoreType, - sslTrustStoreProvider, sslTrustStorePasswordFileLocation, sslTrustStoreLocation); - SSLEncryptionParameters sslEncryptionParameters = new SSLEncryptionParameters(keyStoreParameters, - trustStoreParameters); - - HttpClientFactory httpClientFactory = new HttpClientFactory(SecureCommsType.getType(secureCommsType), - sslEncryptionParameters, keyResourceLoader, null, null, alfrescoHost, alfrescoPort, - alfrescoPortSSL, maxTotalConnections, maxHostConnections, socketTimeout); - // TODO need to make port configurable depending on secure comms, or just make redirects work - AlfrescoHttpClient repoClient = httpClientFactory.getRepoClient(alfrescoHost, alfrescoPortSSL); - repoClient.setBaseUrl(baseUrl); - return repoClient; - } -} + +package org.alfresco.solr.client; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.alfresco.encryption.KeyResourceLoader; +import org.alfresco.encryption.KeyStoreParameters; +import org.alfresco.encryption.ssl.SSLEncryptionParameters; +import org.alfresco.httpclient.AlfrescoHttpClient; +import org.alfresco.httpclient.HttpClientFactory; +import org.alfresco.httpclient.HttpClientFactory.SecureCommsType; +import org.alfresco.repo.dictionary.NamespaceDAO; +import org.alfresco.service.cmr.dictionary.DictionaryService; + +/** + * This factory encapsulates the creation of a SOLRAPIClient and the management of that resource. + * + * @author Ahmed Owian + */ +public class SOLRAPIClientFactory +{ + /* + * Pool of cached client resources keyed on alfresco instances + */ + private static Map clientsPerAlfresco = new HashMap<>(); + + // encryption related parameters + private String secureCommsType; // "none", "https" + private String keyStoreType; + private String keyStoreProvider; + private String passwordFileLocation; + private String keyStoreLocation; + + // ssl + private String sslKeyStoreType; + private String sslKeyStoreProvider; + private String sslKeyStoreLocation; + private String sslKeyStorePasswordFileLocation; + private String sslTrustStoreType; + private String sslTrustStoreProvider; + private String sslTrustStoreLocation; + private String sslTrustStorePasswordFileLocation; + private String alfrescoHost; + private int alfrescoPort; + private int alfrescoPortSSL; + private String baseUrl; + + // http client + private int maxTotalConnections = 40; + private int maxHostConnections = 40; + private int socketTimeout = 120000; + + /** + * Gets the client resource from the pool. + * + * @param alfrescoHost String + * @param alfrescoPort int + * @param alfrescoPortSSL int + * @return SOLRAPIClient + */ + private SOLRAPIClient getCachedClient(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL) + { + String key = constructKey(alfrescoHost, alfrescoPort, alfrescoPortSSL); + return clientsPerAlfresco.get(key); + } + + /** + * Constructs a key to identify a unique alfresco instance to which the client will connect. + * + * @param alfrescoHost String + * @param alfrescoPort int + * @param alfrescoPortSSL int + * @return the key to get a client + */ + private String constructKey(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL) + { + return alfrescoHost + alfrescoPort + alfrescoPortSSL; + } + + /** + * Sets the client in the resource pool. + * + * @param alfrescoHost String + * @param alfrescoPort int + * @param alfrescoPortSSL int + * @param client SOLRAPIClient + */ + private void setCachedClient(String alfrescoHost, int alfrescoPort, int alfrescoPortSSL, SOLRAPIClient client) + { + String key = constructKey(alfrescoHost, alfrescoPort, alfrescoPortSSL); + clientsPerAlfresco.put(key, client); + } + + /** + * Creates the SOLRAPIClient or gets it from a pool + * + * @param props solrcore.properties in the /conf directory + * @param keyResourceLoader reads encryption key resources + * @param dictionaryService represents the Repository Data Dictionary + * @param namespaceDAO allows retrieving and creating Namespace definitions + * @return an instance of SOLRAPIClient + */ + public SOLRAPIClient getSOLRAPIClient(Properties props, KeyResourceLoader keyResourceLoader, + DictionaryService dictionaryService, NamespaceDAO namespaceDAO) + { + alfrescoHost = props.getProperty("alfresco.host", "localhost"); + alfrescoPort = Integer.parseInt(props.getProperty("alfresco.port", "8080")); + alfrescoPortSSL = Integer.parseInt(props.getProperty("alfresco.port.ssl", "8443")); + + SOLRAPIClient client = getCachedClient(alfrescoHost, alfrescoPort, alfrescoPortSSL); + if (client == null) + { + baseUrl = props.getProperty("alfresco.baseUrl", "/alfresco"); + keyStoreType = props.getProperty("alfresco.encryption.keystore.type", "JCEKS"); + keyStoreProvider = props.getProperty("alfresco.encryption.keystore.provider"); + passwordFileLocation = props.getProperty("alfresco.encryption.keystore.passwordFileLocation"); + keyStoreLocation = props.getProperty("alfresco.encryption.keystore.location"); + sslKeyStoreType = props.getProperty("alfresco.encryption.ssl.keystore.type", "JCEKS"); + sslKeyStoreProvider = props.getProperty("alfresco.encryption.ssl.keystore.provider", ""); + sslKeyStoreLocation = props.getProperty("alfresco.encryption.ssl.keystore.location", + "ssl.repo.client.keystore"); + sslKeyStorePasswordFileLocation = props.getProperty( + "alfresco.encryption.ssl.keystore.passwordFileLocation", "ssl-keystore-passwords.properties"); + sslTrustStoreType = props.getProperty("alfresco.encryption.ssl.truststore.type", "JCEKS"); + sslTrustStoreProvider = props.getProperty("alfresco.encryption.ssl.truststore.provider", ""); + sslTrustStoreLocation = props.getProperty("alfresco.encryption.ssl.truststore.location", + "ssl.repo.client.truststore"); + sslTrustStorePasswordFileLocation = props.getProperty( + "alfresco.encryption.ssl.truststore.passwordFileLocation", + "ssl-truststore-passwords.properties"); + secureCommsType = props.getProperty("alfresco.secureComms", "none"); + maxTotalConnections = Integer.parseInt(props.getProperty("alfresco.maxTotalConnections", "40")); + maxHostConnections = Integer.parseInt(props.getProperty("alfresco.maxHostConnections", "40")); + socketTimeout = Integer.parseInt(props.getProperty("alfresco.socketTimeout", "60000")); + + client = new SOLRAPIClient(getRepoClient(keyResourceLoader), dictionaryService, namespaceDAO); + setCachedClient(alfrescoHost, alfrescoPort, alfrescoPortSSL, client); + } + + return client; + } + + protected AlfrescoHttpClient getRepoClient(KeyResourceLoader keyResourceLoader) + { + // TODO i18n + KeyStoreParameters keyStoreParameters = new KeyStoreParameters("SSL Key Store", sslKeyStoreType, + sslKeyStoreProvider, sslKeyStorePasswordFileLocation, sslKeyStoreLocation); + KeyStoreParameters trustStoreParameters = new KeyStoreParameters("SSL Trust Store", sslTrustStoreType, + sslTrustStoreProvider, sslTrustStorePasswordFileLocation, sslTrustStoreLocation); + SSLEncryptionParameters sslEncryptionParameters = new SSLEncryptionParameters(keyStoreParameters, + trustStoreParameters); + + HttpClientFactory httpClientFactory = new HttpClientFactory(SecureCommsType.getType(secureCommsType), + sslEncryptionParameters, keyResourceLoader, null, null, alfrescoHost, alfrescoPort, + alfrescoPortSSL, maxTotalConnections, maxHostConnections, socketTimeout); + // TODO need to make port configurable depending on secure comms, or just make redirects work + AlfrescoHttpClient repoClient = httpClientFactory.getRepoClient(alfrescoHost, alfrescoPortSSL); + repoClient.setBaseUrl(baseUrl); + return repoClient; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Status.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Status.java index 841e03618..c0b9a25af 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Status.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Status.java @@ -1,190 +1,190 @@ -package org.alfresco.solr.client; - -import javax.servlet.http.HttpServletResponse; - -import org.springframework.extensions.surf.util.I18NUtil; - -/** - * Status code constants for SOLR. - * - * @since 4.0 - */ -public class Status -{ - /* Status code constants */ - public static final int STATUS_CONTINUE = HttpServletResponse.SC_CONTINUE; - public static final int STATUS_SWITCHING_PROTOCOLS = HttpServletResponse.SC_SWITCHING_PROTOCOLS; - public static final int STATUS_OK = HttpServletResponse.SC_OK; - public static final int STATUS_CREATED = HttpServletResponse.SC_CREATED; - public static final int STATUS_ACCEPTED = HttpServletResponse.SC_ACCEPTED; - public static final int STATUS_NON_AUTHORITATIVE_INFORMATION = HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION; - public static final int STATUS_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT; - public static final int STATUS_RESET_CONTENT = HttpServletResponse.SC_RESET_CONTENT; - public static final int STATUS_PARTIAL_CONTENT = HttpServletResponse.SC_PARTIAL_CONTENT; - public static final int STATUS_MULTIPLE_CHOICES = HttpServletResponse.SC_MULTIPLE_CHOICES; - public static final int STATUS_MOVED_PERMANENTLY = HttpServletResponse.SC_MOVED_PERMANENTLY; - public static final int STATUS_MOVED_TEMPORARILY = HttpServletResponse.SC_MOVED_TEMPORARILY; - public static final int STATUS_FOUND = HttpServletResponse.SC_FOUND; - public static final int STATUS_SEE_OTHER = HttpServletResponse.SC_SEE_OTHER; - public static final int STATUS_NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED; - public static final int STATUS_USE_PROXY = HttpServletResponse.SC_USE_PROXY; - public static final int STATUS_TEMPORARY_REDIRECT = HttpServletResponse.SC_TEMPORARY_REDIRECT; - public static final int STATUS_BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST; - public static final int STATUS_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED; - public static final int STATUS_PAYMENT_REQUIRED = HttpServletResponse.SC_PAYMENT_REQUIRED; - public static final int STATUS_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN; - public static final int STATUS_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND; - public static final int STATUS_METHOD_NOT_ALLOWED = HttpServletResponse.SC_METHOD_NOT_ALLOWED; - public static final int STATUS_NOT_ACCEPTABLE = HttpServletResponse.SC_NOT_ACCEPTABLE; - public static final int STATUS_PROXY_AUTHENTICATION_REQUIRED = HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED; - public static final int STATUS_REQUEST_TIMEOUT = HttpServletResponse.SC_REQUEST_TIMEOUT; - public static final int STATUS_CONFLICT = HttpServletResponse.SC_CONFLICT; - public static final int STATUS_GONE = HttpServletResponse.SC_GONE; - public static final int STATUS_LENGTH_REQUIRED = HttpServletResponse.SC_LENGTH_REQUIRED; - public static final int STATUS_PRECONDITION_FAILED = HttpServletResponse.SC_PRECONDITION_FAILED; - public static final int STATUS_REQUEST_ENTITY_TOO_LARGE = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; - public static final int STATUS_REQUEST_URI_TOO_LONG = HttpServletResponse.SC_REQUEST_URI_TOO_LONG; - public static final int STATUS_UNSUPPORTED_MEDIA_TYPE = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; - public static final int STATUS_REQUESTED_RANGE_NOT_SATISFIABLE = HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE; - public static final int STATUS_EXPECTATION_FAILED = HttpServletResponse.SC_EXPECTATION_FAILED; - public static final int STATUS_INTERNAL_SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; - public static final int STATUS_NOT_IMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED; - public static final int STATUS_BAD_GATEWAY = HttpServletResponse.SC_BAD_GATEWAY; - public static final int STATUS_SERVICE_UNAVAILABLE = HttpServletResponse.SC_SERVICE_UNAVAILABLE; - public static final int STATUS_GATEWAY_TIMEOUT = HttpServletResponse.SC_GATEWAY_TIMEOUT; - public static final int STATUS_HTTP_VERSION_NOT_SUPPORTED = HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED; - - - private Throwable exception = null; - private String location = ""; - private int code = HttpServletResponse.SC_OK; - private String message = ""; - private boolean redirect = false; - - /** - * Helper method to set the code and message. - *

- * Redirect is set to true. - * - * @param code code - * @param message message - */ - public void setCode(int code, String message) - { - this.code = code; - this.message = message; - this.redirect = true; - } - - /** - * @param exception Throwable - */ - public void setException(Throwable exception) - { - this.exception = exception; - } - - /** - * @return exception - */ - public Throwable getException() - { - return exception; - } - - /** - * @param message String - */ - public void setMessage(String message) - { - this.message = message; - } - - /** - * @return message - */ - public String getMessage() - { - return message; - } - - /** - * @param redirect redirect to status code response - */ - public void setRedirect(boolean redirect) - { - this.redirect = redirect; - } - - /** - * @return redirect to status code response - */ - public boolean getRedirect() - { - return redirect; - } - - /** - * @see javax.servlet.http.HTTPServletResponse - * - * @param code status code - */ - public void setCode(int code) - { - this.code = code; - } - - /** - * @return status code - */ - public int getCode() - { - return code; - } - - /** - * Gets the short name of the status code - * - * @return status code name - */ - public String getCodeName() - { - String codeName = I18NUtil.getMessage("webscript.code." + code + ".name"); - return codeName == null ? "" : codeName; - } - - /** - * @see javax.servlet.http.HTTPServletResponse - * - * @param location location response-header - */ - public void setLocation(String location) - { - this.location = location; - } - - /** - * @return location - */ - public String getLocation() - { - return location; - } - - /** - * Gets the description of the status code - * - * @return status code description - */ - public String getCodeDescription() - { - String codeDescription = I18NUtil.getMessage("webscript.code." + code + ".description"); - return codeDescription == null ? "" : codeDescription; - } - - @Override - public String toString() - { - return Integer.toString(code); - } -} +package org.alfresco.solr.client; + +import javax.servlet.http.HttpServletResponse; + +import org.springframework.extensions.surf.util.I18NUtil; + +/** + * Status code constants for SOLR. + * + * @since 4.0 + */ +public class Status +{ + /* Status code constants */ + public static final int STATUS_CONTINUE = HttpServletResponse.SC_CONTINUE; + public static final int STATUS_SWITCHING_PROTOCOLS = HttpServletResponse.SC_SWITCHING_PROTOCOLS; + public static final int STATUS_OK = HttpServletResponse.SC_OK; + public static final int STATUS_CREATED = HttpServletResponse.SC_CREATED; + public static final int STATUS_ACCEPTED = HttpServletResponse.SC_ACCEPTED; + public static final int STATUS_NON_AUTHORITATIVE_INFORMATION = HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION; + public static final int STATUS_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT; + public static final int STATUS_RESET_CONTENT = HttpServletResponse.SC_RESET_CONTENT; + public static final int STATUS_PARTIAL_CONTENT = HttpServletResponse.SC_PARTIAL_CONTENT; + public static final int STATUS_MULTIPLE_CHOICES = HttpServletResponse.SC_MULTIPLE_CHOICES; + public static final int STATUS_MOVED_PERMANENTLY = HttpServletResponse.SC_MOVED_PERMANENTLY; + public static final int STATUS_MOVED_TEMPORARILY = HttpServletResponse.SC_MOVED_TEMPORARILY; + public static final int STATUS_FOUND = HttpServletResponse.SC_FOUND; + public static final int STATUS_SEE_OTHER = HttpServletResponse.SC_SEE_OTHER; + public static final int STATUS_NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED; + public static final int STATUS_USE_PROXY = HttpServletResponse.SC_USE_PROXY; + public static final int STATUS_TEMPORARY_REDIRECT = HttpServletResponse.SC_TEMPORARY_REDIRECT; + public static final int STATUS_BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST; + public static final int STATUS_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED; + public static final int STATUS_PAYMENT_REQUIRED = HttpServletResponse.SC_PAYMENT_REQUIRED; + public static final int STATUS_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN; + public static final int STATUS_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND; + public static final int STATUS_METHOD_NOT_ALLOWED = HttpServletResponse.SC_METHOD_NOT_ALLOWED; + public static final int STATUS_NOT_ACCEPTABLE = HttpServletResponse.SC_NOT_ACCEPTABLE; + public static final int STATUS_PROXY_AUTHENTICATION_REQUIRED = HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED; + public static final int STATUS_REQUEST_TIMEOUT = HttpServletResponse.SC_REQUEST_TIMEOUT; + public static final int STATUS_CONFLICT = HttpServletResponse.SC_CONFLICT; + public static final int STATUS_GONE = HttpServletResponse.SC_GONE; + public static final int STATUS_LENGTH_REQUIRED = HttpServletResponse.SC_LENGTH_REQUIRED; + public static final int STATUS_PRECONDITION_FAILED = HttpServletResponse.SC_PRECONDITION_FAILED; + public static final int STATUS_REQUEST_ENTITY_TOO_LARGE = HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE; + public static final int STATUS_REQUEST_URI_TOO_LONG = HttpServletResponse.SC_REQUEST_URI_TOO_LONG; + public static final int STATUS_UNSUPPORTED_MEDIA_TYPE = HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; + public static final int STATUS_REQUESTED_RANGE_NOT_SATISFIABLE = HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE; + public static final int STATUS_EXPECTATION_FAILED = HttpServletResponse.SC_EXPECTATION_FAILED; + public static final int STATUS_INTERNAL_SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR; + public static final int STATUS_NOT_IMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED; + public static final int STATUS_BAD_GATEWAY = HttpServletResponse.SC_BAD_GATEWAY; + public static final int STATUS_SERVICE_UNAVAILABLE = HttpServletResponse.SC_SERVICE_UNAVAILABLE; + public static final int STATUS_GATEWAY_TIMEOUT = HttpServletResponse.SC_GATEWAY_TIMEOUT; + public static final int STATUS_HTTP_VERSION_NOT_SUPPORTED = HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED; + + + private Throwable exception = null; + private String location = ""; + private int code = HttpServletResponse.SC_OK; + private String message = ""; + private boolean redirect = false; + + /** + * Helper method to set the code and message. + *

+ * Redirect is set to true. + * + * @param code code + * @param message message + */ + public void setCode(int code, String message) + { + this.code = code; + this.message = message; + this.redirect = true; + } + + /** + * @param exception Throwable + */ + public void setException(Throwable exception) + { + this.exception = exception; + } + + /** + * @return exception + */ + public Throwable getException() + { + return exception; + } + + /** + * @param message String + */ + public void setMessage(String message) + { + this.message = message; + } + + /** + * @return message + */ + public String getMessage() + { + return message; + } + + /** + * @param redirect redirect to status code response + */ + public void setRedirect(boolean redirect) + { + this.redirect = redirect; + } + + /** + * @return redirect to status code response + */ + public boolean getRedirect() + { + return redirect; + } + + /** + * @see javax.servlet.http.HTTPServletResponse + * + * @param code status code + */ + public void setCode(int code) + { + this.code = code; + } + + /** + * @return status code + */ + public int getCode() + { + return code; + } + + /** + * Gets the short name of the status code + * + * @return status code name + */ + public String getCodeName() + { + String codeName = I18NUtil.getMessage("webscript.code." + code + ".name"); + return codeName == null ? "" : codeName; + } + + /** + * @see javax.servlet.http.HTTPServletResponse + * + * @param location location response-header + */ + public void setLocation(String location) + { + this.location = location; + } + + /** + * @return location + */ + public String getLocation() + { + return location; + } + + /** + * Gets the description of the status code + * + * @return status code description + */ + public String getCodeDescription() + { + String codeDescription = I18NUtil.getMessage("webscript.code." + code + ".description"); + return codeDescription == null ? "" : codeDescription; + } + + @Override + public String toString() + { + return Integer.toString(code); + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/StringPropertyValue.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/StringPropertyValue.java index 081950b2e..c3d20ad58 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/StringPropertyValue.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/StringPropertyValue.java @@ -1,28 +1,28 @@ -package org.alfresco.solr.client; - -/** - * Represents a property value as a string - * - * @since 4.0 - */ -public class StringPropertyValue extends PropertyValue -{ - private String value; - - public StringPropertyValue(String value) - { - super(); - this.value = value; - } - - public String getValue() - { - return value; - } - - @Override - public String toString() - { - return "StringPropertyValue [value=" + value + "]"; - } -} +package org.alfresco.solr.client; + +/** + * Represents a property value as a string + * + * @since 4.0 + */ +public class StringPropertyValue extends PropertyValue +{ + private String value; + + public StringPropertyValue(String value) + { + super(); + this.value = value; + } + + public String getValue() + { + return value; + } + + @Override + public String toString() + { + return "StringPropertyValue [value=" + value + "]"; + } +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transaction.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transaction.java index 487f12d96..59eb2233f 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transaction.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transaction.java @@ -1,86 +1,86 @@ -package org.alfresco.solr.client; - -/** - * SOLR-side representation of transaction information. - * - * @since 4.0 - */ -public class Transaction -{ - private long id; - private long commitTimeMs; - private long updates; - private long deletes; - - public long getId() - { - return id; - } - public void setId(long id) - { - this.id = id; - } - public long getCommitTimeMs() - { - return commitTimeMs; - } - public void setCommitTimeMs(long commitTimeMs) - { - this.commitTimeMs = commitTimeMs; - } - public long getUpdates() - { - return updates; - } - public void setUpdates(long updates) - { - this.updates = updates; - } - public long getDeletes() - { - return deletes; - } - public void setDeletes(long deletes) - { - this.deletes = deletes; - } - @Override - public String toString() - { - return "Transaction [id=" + id + ", commitTimeMs=" + commitTimeMs + ", updates=" + updates + ", deletes=" - + deletes + "]"; - } - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + (int) (commitTimeMs ^ (commitTimeMs >>> 32)); - result = prime * result + (int) (deletes ^ (deletes >>> 32)); - result = prime * result + (int) (id ^ (id >>> 32)); - result = prime * result + (int) (updates ^ (updates >>> 32)); - return result; - } - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Transaction other = (Transaction) obj; - if (commitTimeMs != other.commitTimeMs) - return false; - if (deletes != other.deletes) - return false; - if (id != other.id) - return false; - if (updates != other.updates) - return false; - return true; - } - - -} +package org.alfresco.solr.client; + +/** + * SOLR-side representation of transaction information. + * + * @since 4.0 + */ +public class Transaction +{ + private long id; + private long commitTimeMs; + private long updates; + private long deletes; + + public long getId() + { + return id; + } + public void setId(long id) + { + this.id = id; + } + public long getCommitTimeMs() + { + return commitTimeMs; + } + public void setCommitTimeMs(long commitTimeMs) + { + this.commitTimeMs = commitTimeMs; + } + public long getUpdates() + { + return updates; + } + public void setUpdates(long updates) + { + this.updates = updates; + } + public long getDeletes() + { + return deletes; + } + public void setDeletes(long deletes) + { + this.deletes = deletes; + } + @Override + public String toString() + { + return "Transaction [id=" + id + ", commitTimeMs=" + commitTimeMs + ", updates=" + updates + ", deletes=" + + deletes + "]"; + } + @Override + public int hashCode() + { + final int prime = 31; + int result = 1; + result = prime * result + (int) (commitTimeMs ^ (commitTimeMs >>> 32)); + result = prime * result + (int) (deletes ^ (deletes >>> 32)); + result = prime * result + (int) (id ^ (id >>> 32)); + result = prime * result + (int) (updates ^ (updates >>> 32)); + return result; + } + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Transaction other = (Transaction) obj; + if (commitTimeMs != other.commitTimeMs) + return false; + if (deletes != other.deletes) + return false; + if (id != other.id) + return false; + if (updates != other.updates) + return false; + return true; + } + + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transactions.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transactions.java index 2f5db918b..09e1a7f2f 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transactions.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/client/Transactions.java @@ -1,39 +1,39 @@ -package org.alfresco.solr.client; - -import java.util.List; - -/** - * @author Andy - * - */ -public class Transactions -{ - private List transactions; - - private Long maxTxnCommitTime; - - private Long maxTxnId; - - Transactions(List transactions, Long maxTxnCommitTime, Long maxTxnId) - { - this.transactions = transactions; - this.maxTxnCommitTime = maxTxnCommitTime; - this.maxTxnId = maxTxnId; - } - - public List getTransactions() - { - return transactions; - } - - public Long getMaxTxnCommitTime() - { - return maxTxnCommitTime; - } - - public Long getMaxTxnId() - { - return maxTxnId; - } - -} +package org.alfresco.solr.client; + +import java.util.List; + +/** + * @author Andy + * + */ +public class Transactions +{ + private List transactions; + + private Long maxTxnCommitTime; + + private Long maxTxnId; + + Transactions(List transactions, Long maxTxnCommitTime, Long maxTxnId) + { + this.transactions = transactions; + this.maxTxnCommitTime = maxTxnCommitTime; + this.maxTxnId = maxTxnId; + } + + public List getTransactions() + { + return transactions; + } + + public Long getMaxTxnCommitTime() + { + return maxTxnCommitTime; + } + + public Long getMaxTxnId() + { + return maxTxnId; + } + +} diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/IndexHealthReport.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/IndexHealthReport.java index cbdfd174c..2edcdb085 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/IndexHealthReport.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/IndexHealthReport.java @@ -1,409 +1,409 @@ -package org.alfresco.solr.tracker; - -import org.alfresco.solr.InformationServerCollectionProvider; -import org.alfresco.solr.adapters.IOpenBitSet; - - -public class IndexHealthReport -{ - long dbTransactionCount; - - IOpenBitSet missingTxFromIndex; - - IOpenBitSet duplicatedTxInIndex; - - IOpenBitSet txInIndexButNotInDb; - - IOpenBitSet duplicatedLeafInIndex; - - IOpenBitSet duplicatedAuxInIndex; - - long transactionDocsInIndex; - - long uniqueTransactionDocsInIndex; - - long uniqueAclTransactionDocsInIndex; - - long aclTransactionDocsInIndex; - - long leafDocCountInIndex; - - long auxDocCountInIndex; - - long lastIndexedCommitTime; - - long lastIndexedIdBeforeHoles; - - long dbAclTransactionCount; - - IOpenBitSet missingAclTxFromIndex; - - IOpenBitSet duplicatedAclTxInIndex; - - IOpenBitSet aclTxInIndexButNotInDb; - - IOpenBitSet duplicatedErrorInIndex; - - IOpenBitSet duplicatedUnindexedInIndex; - - long errorDocCountInIndex; - - long unindexedDocCountInIndex; - - public IndexHealthReport(InformationServerCollectionProvider srv) - { - this.missingTxFromIndex = srv.getOpenBitSetInstance(); - this.duplicatedTxInIndex = srv.getOpenBitSetInstance(); - this.txInIndexButNotInDb = srv.getOpenBitSetInstance(); - this.duplicatedLeafInIndex = srv.getOpenBitSetInstance(); - this.duplicatedAuxInIndex = srv.getOpenBitSetInstance(); - - this.missingAclTxFromIndex = srv.getOpenBitSetInstance(); - this.duplicatedAclTxInIndex = srv.getOpenBitSetInstance(); - this.aclTxInIndexButNotInDb = srv.getOpenBitSetInstance(); - this.duplicatedErrorInIndex = srv.getOpenBitSetInstance(); - this.duplicatedUnindexedInIndex = srv.getOpenBitSetInstance(); - } - - /** - * @return the transactionDocsInIndex - */ - public long getTransactionDocsInIndex() - { - return transactionDocsInIndex; - } - - public long getAclTransactionDocsInIndex() - { - return aclTransactionDocsInIndex; - } - - /** - * @param leafDocCountInIndex long - */ - public void setLeafDocCountInIndex(long leafDocCountInIndex) - { - this.leafDocCountInIndex = leafDocCountInIndex; - } - - /** - * @return the leafDocCountInIndex - */ - public long getLeafDocCountInIndex() - { - return leafDocCountInIndex; - } - - /** - * @param auxDocCountInIndex long - */ - public void setAuxDocCountInIndex(long auxDocCountInIndex) - { - this.auxDocCountInIndex = auxDocCountInIndex; - } - - /** - * @return the leafDocCountInIndex - */ - public long getAuxDocCountInIndex() - { - return auxDocCountInIndex; - } - - /** - * @param txid long - */ - public void setDuplicatedLeafInIndex(long txid) - { - duplicatedLeafInIndex.set(txid); - - } - - /** - * @return the duplicatedLeafInIndex - */ - public IOpenBitSet getDuplicatedLeafInIndex() - { - return duplicatedLeafInIndex; - } - - /** - * @param txid long - */ - public void setDuplicatedAuxInIndex(long txid) - { - duplicatedAuxInIndex.set(txid); - - } - - /** - * @return the duplicatedLeafInIndex - */ - public IOpenBitSet getDuplicatedAuxInIndex() - { - return duplicatedAuxInIndex; - } - - /** - * @param transactionDocsInIndex - * the transactionDocsInIndex to set - */ - public void setTransactionDocsInIndex(long transactionDocsInIndex) - { - this.transactionDocsInIndex = transactionDocsInIndex; - } - - /** - * @param aclTransactionDocsInIndex - * the transactionDocsInIndex to set - */ - public void setAclTransactionDocsInIndex(long aclTransactionDocsInIndex) - { - this.aclTransactionDocsInIndex = aclTransactionDocsInIndex; - } - - /** - * @return the missingFromIndex - */ - public IOpenBitSet getMissingTxFromIndex() - { - return missingTxFromIndex; - } - - /** - * @return the missingFromIndex - */ - public IOpenBitSet getMissingAclTxFromIndex() - { - return missingAclTxFromIndex; - } - - /** - * @return the duplicatedInIndex - */ - public IOpenBitSet getDuplicatedTxInIndex() - { - return duplicatedTxInIndex; - } - - /** - * @return the duplicatedInIndex - */ - public IOpenBitSet getDuplicatedAclTxInIndex() - { - return duplicatedAclTxInIndex; - } - - /** - * @return the inIndexButNotInDb - */ - public IOpenBitSet getTxInIndexButNotInDb() - { - return txInIndexButNotInDb; - } - - /** - * @return the inIndexButNotInDb - */ - public IOpenBitSet getAclTxInIndexButNotInDb() - { - return aclTxInIndexButNotInDb; - } - - /** - * @return the dbTransactionCount - */ - public long getDbTransactionCount() - { - return dbTransactionCount; - } - - /** - * @param dbTransactionCount - * the dbTransactionCount to set - */ - public void setDbTransactionCount(long dbTransactionCount) - { - this.dbTransactionCount = dbTransactionCount; - } - - public void setMissingTxFromIndex(long txid) - { - missingTxFromIndex.set(txid); - } - - public void setMissingAclTxFromIndex(long txid) - { - missingAclTxFromIndex.set(txid); - } - - public void setDuplicatedTxInIndex(long txid) - { - duplicatedTxInIndex.set(txid); - } - - public void setDuplicatedAclTxInIndex(long txid) - { - duplicatedAclTxInIndex.set(txid); - } - - public void setTxInIndexButNotInDb(long txid) - { - txInIndexButNotInDb.set(txid); - } - - public void setAclTxInIndexButNotInDb(long txid) - { - aclTxInIndexButNotInDb.set(txid); - } - - /** - * @param lastIndexedCommitTime - * the lastIndexCommitTime to set - */ - public void setLastIndexedCommitTime(long lastIndexedCommitTime) - { - this.lastIndexedCommitTime = lastIndexedCommitTime; - } - - /** - * @return the lastIndexedIdBeforeHoles - */ - public long getLastIndexedIdBeforeHoles() - { - return lastIndexedIdBeforeHoles; - } - - /** - * @param lastIndexedIdBeforeHoles - * the lastIndexedIdBeforeHoles to set - */ - public void setLastIndexedIdBeforeHoles(long lastIndexedIdBeforeHoles) - { - this.lastIndexedIdBeforeHoles = lastIndexedIdBeforeHoles; - } - - /** - * @param dbAclTransactionCount long - */ - public void setDbAclTransactionCount(long dbAclTransactionCount) - { - this.dbAclTransactionCount = dbAclTransactionCount; - } - - /** - * @return the dbAclTransactionCount - */ - public long getDbAclTransactionCount() - { - return dbAclTransactionCount; - } - - /** - * @return the uniqueTransactionDocsInIndex - */ - public long getUniqueTransactionDocsInIndex() - { - return uniqueTransactionDocsInIndex; - } - - /** - * @param uniqueTransactionDocsInIndex the uniqueTransactionDocsInIndex to set - */ - public void setUniqueTransactionDocsInIndex(long uniqueTransactionDocsInIndex) - { - this.uniqueTransactionDocsInIndex = uniqueTransactionDocsInIndex; - } - - /** - * @return the uniqueAclTransactionDocsInIndex - */ - public long getUniqueAclTransactionDocsInIndex() - { - return uniqueAclTransactionDocsInIndex; - } - - /** - * @param uniqueAclTransactionDocsInIndex the uniqueAclTransactionDocsInIndex to set - */ - public void setUniqueAclTransactionDocsInIndex(long uniqueAclTransactionDocsInIndex) - { - this.uniqueAclTransactionDocsInIndex = uniqueAclTransactionDocsInIndex; - } - - /** - * @return the lastIndexedCommitTime - */ - public long getLastIndexedCommitTime() - { - return lastIndexedCommitTime; - } - - /** - * @param unindexedDocCountInIndex long - */ - public void setUnindexedDocCountInIndex(long unindexedDocCountInIndex) - { - this.unindexedDocCountInIndex = unindexedDocCountInIndex; - } - - /** - * @param dbId long - */ - public void setDuplicatedUnindexedInIndex(long dbId) - { - duplicatedUnindexedInIndex.set(dbId); - } - - /** - * @param errorDocCountInIndex long - */ - public void setErrorDocCountInIndex(long errorDocCountInIndex) - { - this.errorDocCountInIndex = errorDocCountInIndex; - } - - /** - * @param dbId long - */ - public void setDuplicatedErrorInIndex(long dbId) - { - duplicatedErrorInIndex.set(dbId); - - } - - /** - * @return the duplicatedErrorInIndex - */ - public IOpenBitSet getDuplicatedErrorInIndex() - { - return duplicatedErrorInIndex; - } - - /** - * @return the duplicatedUnindexedInIndex - */ - public IOpenBitSet getDuplicatedUnindexedInIndex() - { - return duplicatedUnindexedInIndex; - } - - /** - * @return the errorDocCountInIndex - */ - public long getErrorDocCountInIndex() - { - return errorDocCountInIndex; - } - - /** - * @return the unindexedDocCountInIndex - */ - public long getUnindexedDocCountInIndex() - { - return unindexedDocCountInIndex; - } - - - +package org.alfresco.solr.tracker; + +import org.alfresco.solr.InformationServerCollectionProvider; +import org.alfresco.solr.adapters.IOpenBitSet; + + +public class IndexHealthReport +{ + long dbTransactionCount; + + IOpenBitSet missingTxFromIndex; + + IOpenBitSet duplicatedTxInIndex; + + IOpenBitSet txInIndexButNotInDb; + + IOpenBitSet duplicatedLeafInIndex; + + IOpenBitSet duplicatedAuxInIndex; + + long transactionDocsInIndex; + + long uniqueTransactionDocsInIndex; + + long uniqueAclTransactionDocsInIndex; + + long aclTransactionDocsInIndex; + + long leafDocCountInIndex; + + long auxDocCountInIndex; + + long lastIndexedCommitTime; + + long lastIndexedIdBeforeHoles; + + long dbAclTransactionCount; + + IOpenBitSet missingAclTxFromIndex; + + IOpenBitSet duplicatedAclTxInIndex; + + IOpenBitSet aclTxInIndexButNotInDb; + + IOpenBitSet duplicatedErrorInIndex; + + IOpenBitSet duplicatedUnindexedInIndex; + + long errorDocCountInIndex; + + long unindexedDocCountInIndex; + + public IndexHealthReport(InformationServerCollectionProvider srv) + { + this.missingTxFromIndex = srv.getOpenBitSetInstance(); + this.duplicatedTxInIndex = srv.getOpenBitSetInstance(); + this.txInIndexButNotInDb = srv.getOpenBitSetInstance(); + this.duplicatedLeafInIndex = srv.getOpenBitSetInstance(); + this.duplicatedAuxInIndex = srv.getOpenBitSetInstance(); + + this.missingAclTxFromIndex = srv.getOpenBitSetInstance(); + this.duplicatedAclTxInIndex = srv.getOpenBitSetInstance(); + this.aclTxInIndexButNotInDb = srv.getOpenBitSetInstance(); + this.duplicatedErrorInIndex = srv.getOpenBitSetInstance(); + this.duplicatedUnindexedInIndex = srv.getOpenBitSetInstance(); + } + + /** + * @return the transactionDocsInIndex + */ + public long getTransactionDocsInIndex() + { + return transactionDocsInIndex; + } + + public long getAclTransactionDocsInIndex() + { + return aclTransactionDocsInIndex; + } + + /** + * @param leafDocCountInIndex long + */ + public void setLeafDocCountInIndex(long leafDocCountInIndex) + { + this.leafDocCountInIndex = leafDocCountInIndex; + } + + /** + * @return the leafDocCountInIndex + */ + public long getLeafDocCountInIndex() + { + return leafDocCountInIndex; + } + + /** + * @param auxDocCountInIndex long + */ + public void setAuxDocCountInIndex(long auxDocCountInIndex) + { + this.auxDocCountInIndex = auxDocCountInIndex; + } + + /** + * @return the leafDocCountInIndex + */ + public long getAuxDocCountInIndex() + { + return auxDocCountInIndex; + } + + /** + * @param txid long + */ + public void setDuplicatedLeafInIndex(long txid) + { + duplicatedLeafInIndex.set(txid); + + } + + /** + * @return the duplicatedLeafInIndex + */ + public IOpenBitSet getDuplicatedLeafInIndex() + { + return duplicatedLeafInIndex; + } + + /** + * @param txid long + */ + public void setDuplicatedAuxInIndex(long txid) + { + duplicatedAuxInIndex.set(txid); + + } + + /** + * @return the duplicatedLeafInIndex + */ + public IOpenBitSet getDuplicatedAuxInIndex() + { + return duplicatedAuxInIndex; + } + + /** + * @param transactionDocsInIndex + * the transactionDocsInIndex to set + */ + public void setTransactionDocsInIndex(long transactionDocsInIndex) + { + this.transactionDocsInIndex = transactionDocsInIndex; + } + + /** + * @param aclTransactionDocsInIndex + * the transactionDocsInIndex to set + */ + public void setAclTransactionDocsInIndex(long aclTransactionDocsInIndex) + { + this.aclTransactionDocsInIndex = aclTransactionDocsInIndex; + } + + /** + * @return the missingFromIndex + */ + public IOpenBitSet getMissingTxFromIndex() + { + return missingTxFromIndex; + } + + /** + * @return the missingFromIndex + */ + public IOpenBitSet getMissingAclTxFromIndex() + { + return missingAclTxFromIndex; + } + + /** + * @return the duplicatedInIndex + */ + public IOpenBitSet getDuplicatedTxInIndex() + { + return duplicatedTxInIndex; + } + + /** + * @return the duplicatedInIndex + */ + public IOpenBitSet getDuplicatedAclTxInIndex() + { + return duplicatedAclTxInIndex; + } + + /** + * @return the inIndexButNotInDb + */ + public IOpenBitSet getTxInIndexButNotInDb() + { + return txInIndexButNotInDb; + } + + /** + * @return the inIndexButNotInDb + */ + public IOpenBitSet getAclTxInIndexButNotInDb() + { + return aclTxInIndexButNotInDb; + } + + /** + * @return the dbTransactionCount + */ + public long getDbTransactionCount() + { + return dbTransactionCount; + } + + /** + * @param dbTransactionCount + * the dbTransactionCount to set + */ + public void setDbTransactionCount(long dbTransactionCount) + { + this.dbTransactionCount = dbTransactionCount; + } + + public void setMissingTxFromIndex(long txid) + { + missingTxFromIndex.set(txid); + } + + public void setMissingAclTxFromIndex(long txid) + { + missingAclTxFromIndex.set(txid); + } + + public void setDuplicatedTxInIndex(long txid) + { + duplicatedTxInIndex.set(txid); + } + + public void setDuplicatedAclTxInIndex(long txid) + { + duplicatedAclTxInIndex.set(txid); + } + + public void setTxInIndexButNotInDb(long txid) + { + txInIndexButNotInDb.set(txid); + } + + public void setAclTxInIndexButNotInDb(long txid) + { + aclTxInIndexButNotInDb.set(txid); + } + + /** + * @param lastIndexedCommitTime + * the lastIndexCommitTime to set + */ + public void setLastIndexedCommitTime(long lastIndexedCommitTime) + { + this.lastIndexedCommitTime = lastIndexedCommitTime; + } + + /** + * @return the lastIndexedIdBeforeHoles + */ + public long getLastIndexedIdBeforeHoles() + { + return lastIndexedIdBeforeHoles; + } + + /** + * @param lastIndexedIdBeforeHoles + * the lastIndexedIdBeforeHoles to set + */ + public void setLastIndexedIdBeforeHoles(long lastIndexedIdBeforeHoles) + { + this.lastIndexedIdBeforeHoles = lastIndexedIdBeforeHoles; + } + + /** + * @param dbAclTransactionCount long + */ + public void setDbAclTransactionCount(long dbAclTransactionCount) + { + this.dbAclTransactionCount = dbAclTransactionCount; + } + + /** + * @return the dbAclTransactionCount + */ + public long getDbAclTransactionCount() + { + return dbAclTransactionCount; + } + + /** + * @return the uniqueTransactionDocsInIndex + */ + public long getUniqueTransactionDocsInIndex() + { + return uniqueTransactionDocsInIndex; + } + + /** + * @param uniqueTransactionDocsInIndex the uniqueTransactionDocsInIndex to set + */ + public void setUniqueTransactionDocsInIndex(long uniqueTransactionDocsInIndex) + { + this.uniqueTransactionDocsInIndex = uniqueTransactionDocsInIndex; + } + + /** + * @return the uniqueAclTransactionDocsInIndex + */ + public long getUniqueAclTransactionDocsInIndex() + { + return uniqueAclTransactionDocsInIndex; + } + + /** + * @param uniqueAclTransactionDocsInIndex the uniqueAclTransactionDocsInIndex to set + */ + public void setUniqueAclTransactionDocsInIndex(long uniqueAclTransactionDocsInIndex) + { + this.uniqueAclTransactionDocsInIndex = uniqueAclTransactionDocsInIndex; + } + + /** + * @return the lastIndexedCommitTime + */ + public long getLastIndexedCommitTime() + { + return lastIndexedCommitTime; + } + + /** + * @param unindexedDocCountInIndex long + */ + public void setUnindexedDocCountInIndex(long unindexedDocCountInIndex) + { + this.unindexedDocCountInIndex = unindexedDocCountInIndex; + } + + /** + * @param dbId long + */ + public void setDuplicatedUnindexedInIndex(long dbId) + { + duplicatedUnindexedInIndex.set(dbId); + } + + /** + * @param errorDocCountInIndex long + */ + public void setErrorDocCountInIndex(long errorDocCountInIndex) + { + this.errorDocCountInIndex = errorDocCountInIndex; + } + + /** + * @param dbId long + */ + public void setDuplicatedErrorInIndex(long dbId) + { + duplicatedErrorInIndex.set(dbId); + + } + + /** + * @return the duplicatedErrorInIndex + */ + public IOpenBitSet getDuplicatedErrorInIndex() + { + return duplicatedErrorInIndex; + } + + /** + * @return the duplicatedUnindexedInIndex + */ + public IOpenBitSet getDuplicatedUnindexedInIndex() + { + return duplicatedUnindexedInIndex; + } + + /** + * @return the errorDocCountInIndex + */ + public long getErrorDocCountInIndex() + { + return errorDocCountInIndex; + } + + /** + * @return the unindexedDocCountInIndex + */ + public long getUnindexedDocCountInIndex() + { + return unindexedDocCountInIndex; + } + + + } \ No newline at end of file diff --git a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/TrackerStats.java b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/TrackerStats.java index ac723cc43..a3c488437 100644 --- a/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/TrackerStats.java +++ b/search-services/alfresco-solrclient-lib/source/java/org/alfresco/solr/tracker/TrackerStats.java @@ -1,961 +1,961 @@ -package org.alfresco.solr.tracker; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -import org.alfresco.solr.InformationServerCollectionProvider; -import org.alfresco.solr.adapters.ISimpleOrderedMap; -import org.alfresco.util.Pair; - -/** - * @author Andy - */ -public class TrackerStats -{ - public static final int TIME_SCALE = 1000000; - - ConcurrentHashMap modelTimes = new ConcurrentHashMap(); - - ConcurrentHashMap aclTimes = new ConcurrentHashMap(); - - ConcurrentHashMap changeSetAcls = new ConcurrentHashMap(); - - ConcurrentHashMap txDocs = new ConcurrentHashMap(); - - ConcurrentHashMap docTransformationTimes = new ConcurrentHashMap(); - - ConcurrentHashMap nodeTimes = new ConcurrentHashMap(); - - ConcurrentHashMap elapsedNodeTimes = new ConcurrentHashMap(); - - ConcurrentHashMap elapsedAclTimes = new ConcurrentHashMap(); - - ConcurrentHashMap elapsedContentTimes = new ConcurrentHashMap(); - - private InformationServerCollectionProvider infoSrv; - - public TrackerStats(InformationServerCollectionProvider server) - { - infoSrv = server; - } - - /** - * @return the modelTimes - */ - public SimpleStats getModelTimes() - { - return aggregateResults(modelTimes); - } - - /** - * @param all ConcurrentHashMap - * @return SimpleStats - */ - private SimpleStats aggregateResults(ConcurrentHashMap all) - { - SimpleStats answer = null; - - for (String key : all.keySet()) - { - IncrementalStats next = all.get(key); - IncrementalStats stats = next.copy(); - if (answer == null) - { - answer = new SimpleStats(stats.scale, this.infoSrv); - answer .start = stats.start; - answer.moments[0] = stats.moments[0]; - answer.moments[1] = stats.moments[1]; - answer.moments[2] = stats.moments[2]; - answer.max = stats.max; - answer.min = stats.min; - answer.copies.put(key, stats); - } - else - { - SimpleStats newAnswer = new SimpleStats(answer.scale, this.infoSrv); - - newAnswer.moments[0] = answer.moments[0] + stats.moments[0]; - - newAnswer.moments[1] = answer.moments[1] * answer.moments[0] + stats.moments[1] * stats.moments[0]; - newAnswer.moments[1] /= answer.moments[0] + stats.moments[0]; - - newAnswer.moments[2] = answer.moments[2] * answer.moments[0]; - newAnswer.moments[2] += (answer.moments[1] - newAnswer.moments[1]) * (answer.moments[1] - newAnswer.moments[1]) * answer.moments[0]; - newAnswer.moments[2] += stats.moments[2] * stats.moments[0]; - newAnswer.moments[2] += (stats.moments[1] - newAnswer.moments[1]) * (stats.moments[1] - newAnswer.moments[1]) * stats.moments[0]; - newAnswer.moments[2] /= answer.moments[0] + stats.moments[0]; - - newAnswer.min = (stats.min < answer.min) ? stats.min : answer.min; - newAnswer.max = (stats.max > answer.max) ? stats.max : answer.max; - - newAnswer.start = (stats.start.compareTo(answer.start) < 1) ? stats.start : answer.start; - - newAnswer.copies.putAll(answer.copies); - newAnswer.copies.put(key, stats); - - answer = newAnswer; - } - - } - - if (answer == null) - { - answer = new SimpleStats(1, this.infoSrv); - } - - return answer; - } - - /** - * @return the aclTxTimes - */ - public SimpleStats getAclTimes() - { - return aggregateResults(aclTimes); - } - - public SimpleStats getChangeSetAcls() - { - return aggregateResults(changeSetAcls); - } - - public SimpleStats getNodeTimes() - { - return aggregateResults(nodeTimes); - } - - /** - * @return the txDocs - */ - public SimpleStats getTxDocs() - { - return aggregateResults(txDocs); - } - - /** - * @return the docTransformationTimes - */ - public SimpleStats getDocTransformationTimes() - { - return aggregateResults(docTransformationTimes); - } - - public double getMeanModelSyncTime() - { - return aggregateResults(modelTimes).getMean(); - } - - public double getMeanNodeIndexTime() - { - return aggregateResults(nodeTimes).getMean(); - } - - public double getMeanNodeElapsedIndexTime() - { - return aggregateResults(elapsedNodeTimes).getMean(); - } - - public double getMeanAclElapsedIndexTime() - { - return aggregateResults(elapsedAclTimes).getMean(); - } - - public double getMeanContentElapsedIndexTime() - { - return aggregateResults(elapsedContentTimes).getMean(); - } - - public double getNodeIndexingThreadCount() - { - return nodeTimes.size(); - } - - public double getMeanAclIndexTime() - { - return aggregateResults(nodeTimes).getMean(); - } - - public double getMeanDocsPerTx() - { - return aggregateResults(txDocs).getMean(); - } - - public double getMeanAclsPerChangeSet() - { - return aggregateResults(changeSetAcls).getMean(); - } - - public static class SimpleStats - { - HashMap copies = new HashMap(); - private InformationServerCollectionProvider server; - int scale; - - SimpleStats(int scale, InformationServerCollectionProvider server) - { - this.scale = scale; - this.server = server; - } - - double[] moments = new double[3]; - - double min = 0D; - - double max = 0D; - - Date start = null; - - synchronized long getN() - { - return (long) moments[0]; - } - - synchronized double getMin() - { - return min; - } - - synchronized double getMax() - { - return max; - } - - synchronized double getMean() - { - return moments[1]; - } - - synchronized double getVarience() - { - if (moments[0] > 1) - { - return moments[2] * moments[0] / (moments[0] - 1); - } - else - { - return Double.NaN; - } - } - - synchronized double getStandardDeviation() - { - return Math.sqrt(getVarience()); - } - - public synchronized ISimpleOrderedMap getNamedList(boolean incdludeDetail, boolean includeHist, boolean includeValues) - { - ISimpleOrderedMap map = this.server.getSimpleOrderedMapInstance(); - map.add("Start", start); - map.add("N", getN()); - map.add("Min", getMin()); - map.add("Max", getMax()); - map.add("Mean", getMean()); - map.add("Varience", getVarience()); - map.add("StdDev", getStandardDeviation()); - if (incdludeDetail) - { - for (String key : copies.keySet()) - { - IncrementalStats value = copies.get(key); - map.add(key, value.getNamedList(includeHist, includeValues)); - } - } - - return map; - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - return "SimpleStats [" - + "\n getN()=" + getN() + ",\n getMin()=" + getMin() + ",\n getMax()=" + getMax() + ",\n getMean()=" - + getMean() + ",\n getVarience()=" + getVarience() + ",\n getStandardDeviation()=" + getStandardDeviation() + ",\n copies=" - + copies + ",\n]"; - } - - } - - public static class Bucket - { - IncrementalStats incrementalStats; - - public double leftBoundary; - - public double rightBoundary; - - public double countLeft; - - public double countRight; - - Bucket(IncrementalStats incrementalStats, double leftBoundary, double rightBoundary) - { - this(incrementalStats, leftBoundary, rightBoundary, 0D, 0D); - } - - Bucket(IncrementalStats incrementalStats, double leftBoundary, double rightBoundary, double countLeft, double countRight) - { - this.incrementalStats = incrementalStats; - this.leftBoundary = leftBoundary; - this.rightBoundary = rightBoundary; - this.countLeft = countLeft; - this.countRight = countRight; - } - - public void add(double x) - { - if ((x - leftBoundary) < (rightBoundary - x)) - { - countLeft++; - } - else - { - countRight++; - } - } - - public double mergeError(Bucket o) - { - double f_m = (this.countLeft + this.countRight + o.countLeft + o.countRight) / 4.0d; - double t1 = this.countLeft - f_m; - double t2 = this.countRight - f_m; - double o1 = o.countLeft - f_m; - double o2 = o.countRight - f_m; - - return (t1 * t1) + (t2 * t2) + (o1 * o1) + (o2 * o2); - } - - public double error() - { - double f_m = (this.countLeft + this.countRight) / 2.0d; - double t1 = this.countLeft - f_m; - double t2 = this.countRight - f_m; - return (t1 * t1) + (t2 * t2); - - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - double mark = (leftBoundary + rightBoundary) / 2.0D; - double width = rightBoundary - leftBoundary; - return "Bucket [(" - + leftBoundary + " TO " + mark + " = " + countLeft / incrementalStats.getN() / width + ") : (" + mark + " TO " + rightBoundary + " = " + countRight - / incrementalStats.getN() / width + "]"; - } - - } - - public static class IncrementalStats - { - Date start = new Date(); - - int scale; - - int buckets; - - double[] moments = new double[5]; - - double min = 0D; - - double max = 0D; - - List values; - - List hist; - - InformationServerCollectionProvider server; - - public IncrementalStats(int scale, int buckets, InformationServerCollectionProvider infoSrv) - { - this.scale = scale; - this.buckets = buckets; - values = new ArrayList(buckets); - hist = new ArrayList(buckets + 1); - this.server = infoSrv; - } - - /** - * @return ISimpleOrderedMap - */ - public ISimpleOrderedMap getNamedList(boolean includeHist, boolean includeValues) - { - ISimpleOrderedMap map = this.server.getSimpleOrderedMapInstance(); - map.add("Start", start); - map.add("N", getN()); - map.add("Min", getMin()); - map.add("Max", getMax()); - map.add("Mean", getMean()); - map.add("Varience", getVarience()); - map.add("StdDev", getStandardDeviation()); - map.add("Skew", getSkew()); - map.add("Kurtosis", getKurtosis()); - - if (includeHist) - { - int i = 0; - ISimpleOrderedMap buckets = this.server.getSimpleOrderedMapInstance(); - for (Bucket b : hist) - { - double mark = (b.leftBoundary + b.rightBoundary) / 2.0D; - double width = b.rightBoundary - b.leftBoundary; - - // SimpleOrderedMap bucket = new SimpleOrderedMap(); - // bucket.add("Lower", b.leftBoundary); - // bucket.add("Upper", mark); - // bucket.add("ProbabilityDensity", b.countLeft/b.incrementalStats.getN()/width); - buckets.add("" + i++, (b.leftBoundary + mark) / 2.0D + "," + b.countLeft / b.incrementalStats.getN() / width); - - // bucket = new SimpleOrderedMap(); - // bucket.add("Lower", mark); - // bucket.add("Upper", b.rightBoundary); - // bucket.add("ProbabilityDensity", b.countRight/b.incrementalStats.getN()/width); - buckets.add("" + i++, (mark + b.rightBoundary) / 2.0D + "," + b.countRight / b.incrementalStats.getN() / width); - } - map.add("Buckets", buckets); - } - - if (includeValues) - { - int i = 0; - ISimpleOrderedMap valuesMap = this.server.getSimpleOrderedMapInstance(); - for (Double value : values) - { - valuesMap.add("" + i++, value); - } - map.add("Values", valuesMap); - } - - return map; - } - - public synchronized void reset() - { - moments = new double[5]; - - min = 0D; - - max = 0D; - - values = new ArrayList(buckets); - - hist = new ArrayList(buckets + 1); - - start = new Date(); - } - - public synchronized void add(double xUnscaled) - { - double x = xUnscaled / scale; - if ((moments[0] == 0) || (x > max)) - { - max = x; - } - if ((moments[0] == 0L) || (x < min)) - { - min = x; - } - double n = moments[0]; - double nPlus1 = n + 1; - double n2 = n * n; - double d = (moments[1] - x) / nPlus1; - double d2 = d * d; - double d3 = d2 * d; - double n_nPlus1 = n / nPlus1; - - moments[4] += 4 * d * moments[3] + 6 * d2 * moments[2] + (1 + n * n2) * d2 * d2; - moments[4] *= n_nPlus1; - - moments[3] += 3 * d * moments[2] + (1 - n2) * d3; - moments[3] *= n_nPlus1; - - moments[2] += (1 + n) * d2; - moments[2] *= n_nPlus1; - - moments[1] -= d; - - moments[0] = nPlus1; - - if (buckets > 1) - { - if (moments[0] < buckets) - { - values.add(Double.valueOf(x)); - } - else if (moments[0] == buckets) - { - values.add(Double.valueOf(x)); - buildInitialBuckets(); - } - else - { - values.set((int) moments[0] % buckets, x); - if (x < hist.get(0).leftBoundary) - { - double delta = (hist.get(0).leftBoundary - x) / 3.0; - Bucket b = new Bucket(this, x - delta, hist.get(0).leftBoundary); - hist.add(0, b); - b.add(x); - Pair bestToMerge = findBestToMerge(); - if (hist.size() > buckets) - { - merge(bestToMerge.getFirst()); - } - } - else if (x >= hist.get(hist.size() - 1).rightBoundary) - { - double delta = (x - hist.get(hist.size() - 1).rightBoundary) / 3.0; - Bucket b = new Bucket(this, hist.get(hist.size() - 1).rightBoundary, x + delta); - hist.add(b); - b.add(x); - Pair bestToMerge = findBestToMerge(); - if (hist.size() > buckets) - { - merge(bestToMerge.getFirst()); - } - } - else - { - // find existing - for (Bucket b : hist) - { - if ((b.leftBoundary <= x) && (x < b.rightBoundary)) - { - b.add(x); - break; - } - - } - Pair bestToMerge = findBestToMerge(); - Pair bestToSplit = findBestToSplit(); - - if (bestToMerge.getSecond() - bestToSplit.getSecond() < 0) - { - if(hist.size() < buckets) - { - split(bestToSplit.getFirst()); - } - else - { - merge(bestToMerge.getFirst()); - split(bestToMerge.getFirst() < bestToSplit.getFirst() ? bestToSplit.getFirst() - 1 : bestToSplit.getFirst()); - } - } - } - } - } - } - - /** - * - */ - private void buildInitialBuckets() - { - // generate initial bucket list - Collections.sort(values); - FOUND: for (int i = 0; i < values.size(); i++) - { - for (Bucket b : hist) - { - if ((b.leftBoundary <= values.get(i)) && (values.get(i) < b.rightBoundary)) - { - b.add(values.get(i)); - continue FOUND; - } - - } - if (i < values.size() - 1) - { - double start = values.get(i); - double end = start + 1.0D; - - END: for (int j = i + 1; j < values.size(); j++) - { - if (values.get(j) > start) - { - end = values.get(j); - break END; - } - } - - Bucket b = new Bucket(this, start, end); - b.add(values.get(i)); - hist.add(b); - } - else - { - double first = values.get(0); - double last = values.get(values.size() - 1); - double width = 1.0D; - if (values.size() > 1) - { - width = (last - first) / (values.size() - 1); - } - Bucket b = new Bucket(this, last, last + width); - b.add(values.get(i)); - hist.add(b); - } - } - } - - void merge(int position) - { - Bucket lower = hist.get(position); - Bucket upper = hist.get(position + 1); - Bucket merged = new Bucket(this, lower.leftBoundary, upper.rightBoundary, lower.countLeft + lower.countRight, upper.countLeft + upper.countRight); - hist.remove(position); - hist.set(position, merged); - - } - - void split(int position) - { - Bucket toSplit = hist.get(position); - double mark = (toSplit.leftBoundary + toSplit.rightBoundary) / 2.0D; - Bucket lower = new Bucket(this, toSplit.leftBoundary, mark, toSplit.countLeft / 2.0D, toSplit.countLeft / 2.0D); - Bucket upper = new Bucket(this, mark, toSplit.rightBoundary, toSplit.countRight / 2.0D, toSplit.countRight / 2.0D); - hist.set(position, upper); - hist.add(position, lower); - } - - Pair findBestToMerge() - { - double minMergeError = Double.MAX_VALUE; - int bucket = 0; - for (int i = 0; i < hist.size() - 1; i++) - { - double mergeError = hist.get(i).mergeError(hist.get(i + 1)); - if (mergeError < minMergeError) - { - minMergeError = mergeError; - bucket = i; - } - } - return new Pair(bucket, minMergeError); - } - - Pair findBestToSplit() - { - double maxError = Double.MIN_VALUE; - int bucket = 0; - for (int i = 0; i < hist.size(); i++) - { - double error = hist.get(i).error(); - if (error > maxError) - { - maxError = error; - bucket = i; - } - } - return new Pair(bucket, maxError); - } - - public synchronized long getN() - { - return (long) moments[0]; - } - - public synchronized double getMin() - { - return min; - } - - public synchronized double getMax() - { - return max; - } - - public synchronized double getMean() - { - return moments[1]; - } - - public synchronized double getVarience() - { - if (moments[0] > 1) - { - return moments[2] * moments[0] / (moments[0] - 1); - } - else - { - return Double.NaN; - } - } - - public synchronized double getStandardDeviation() - { - return Math.sqrt(getVarience()); - } - - public synchronized double getSkew() - { - if (moments[0] > 2) - { - double v = getVarience(); - return moments[3] * moments[0] * moments[0] / (Math.sqrt(v) * v * (moments[0] - 1) * (moments[0] - 2)); - } - else - { - return Double.NaN; - } - } - - public synchronized double getKurtosis() - { - if (moments[0] > 3) - { - double div = (moments[0] - 2) * (moments[0] - 3); - double nMinus1 = moments[0] - 1; - double v = getVarience(); - double z = ((moments[4] * moments[0] * moments[0] * (moments[0] + 1)) / (v * v * nMinus1)); - z -= 3 * nMinus1 * nMinus1; - z /= div; - return z; - } - else - { - return Double.NaN; - } - } - - public synchronized List getHistogram() - { - if(hist.size() == 0) - { - buildInitialBuckets(); - } - return hist; - } - - - - synchronized IncrementalStats copy() - { - IncrementalStats copy = new IncrementalStats(this.scale, this.buckets, this.server); - copy.start = this.start; - copy.max = this.max; - copy.min = this.min; - copy.moments[0] = this.moments[0]; - copy.moments[1] = this.moments[1]; - copy.moments[2] = this.moments[2]; - copy.moments[3] = this.moments[3]; - copy.moments[4] = this.moments[4]; - for (Double x : this.values) - { - copy.values.add(x); - } - for (Bucket b : this.hist) - { - copy.hist.add(new Bucket(copy, b.leftBoundary, b.rightBoundary, b.countLeft, b.countRight)); - } - return copy; - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - return "IncrementalStats [getN()=" - + getN() + ", getMin()=" + getMin() + ", getMax()=" + getMax() + ", getMean()=" + getMean() + ", getVarience()=" + getVarience() + ", getStandardDeviation()=" - + getStandardDeviation() + ", getSkew()=" + getSkew() + ", getKurtosis()=" + getKurtosis() + ", values=" + values + ", hist=" + hist + "]"; - } - - } - - /** - * @param time long - */ - public void addModelTime(long time) - { - IncrementalStats stats = modelTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - modelTimes.put(Thread.currentThread().getName(), stats); - } - stats.add(time); - } - - /** - * @param time long - */ - public void addAclTime(long time) - { - IncrementalStats stats = aclTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - aclTimes.put(Thread.currentThread().getName(), stats); - } - stats.add(time); - } - - /** - * @param time long - */ - public void addNodeTime(long time) - { - IncrementalStats stats = nodeTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - nodeTimes.put(Thread.currentThread().getName(), stats); - } - stats.add(time); - } - - /** - * @param docCount int - * @param time long - */ - public void addElapsedNodeTime(int docCount, long time) - { - if(docCount < 1) - { - return; - } - IncrementalStats stats = elapsedNodeTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - elapsedNodeTimes.put(Thread.currentThread().getName(), stats); - } - long meanTime = time / docCount; - for(int i = 0; i < docCount; i++) - { - stats.add(meanTime); - } - - } - - /** - * @param docCount int - * @param time long - */ - public void addElapsedAclTime(int docCount, long time) - { - if(docCount < 1) - { - return; - } - IncrementalStats stats = elapsedAclTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - elapsedAclTimes.put(Thread.currentThread().getName(), stats); - } - long meanTime = time / docCount; - for(int i = 0; i < docCount; i++) - { - stats.add(meanTime); - } - - } - - /** - * @param docCount int - * @param time long - */ - public void addElapsedContentTime(int docCount, long time) - { - if(docCount < 1) - { - return; - } - IncrementalStats stats = elapsedContentTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - elapsedContentTimes.put(Thread.currentThread().getName(), stats); - } - long meanTime = time / docCount; - for(int i = 0; i < docCount; i++) - { - stats.add(meanTime); - } - - } - - /** - * @param size int - */ - public void addTxDocs(int size) - { - IncrementalStats stats = txDocs.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(1, 50, this.infoSrv); - txDocs.put(Thread.currentThread().getName(), stats); - } - stats.add(size); - } - - /** - * @param size int - */ - public void addChangeSetAcls(int size) - { - IncrementalStats stats = changeSetAcls.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(1, 50, this.infoSrv); - changeSetAcls.put(Thread.currentThread().getName(), stats); - } - stats.add(size); - } - - /** - * @param time long - */ - public void addDocTransformationTime(long time) - { - IncrementalStats stats = docTransformationTimes.get(Thread.currentThread().getName()); - if (stats == null) - { - stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); - docTransformationTimes.put(Thread.currentThread().getName(), stats); - } - stats.add(time); - } - - /* - * (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() - { - return "TrackerStats [modelTimes=" - + modelTimes + ", aclTimes=" + aclTimes + ", changeSetAcls=" + changeSetAcls + ", txDocs=" + txDocs + ", docTransformationTimes=" + docTransformationTimes - + ", nodeTimes=" + nodeTimes + "]"; - } - - /** - * - */ - public void reset() - { - modelTimes.clear(); - aclTimes.clear(); - changeSetAcls.clear(); - txDocs.clear(); - docTransformationTimes.clear(); - nodeTimes.clear(); - } - - -} +package org.alfresco.solr.tracker; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import org.alfresco.solr.InformationServerCollectionProvider; +import org.alfresco.solr.adapters.ISimpleOrderedMap; +import org.alfresco.util.Pair; + +/** + * @author Andy + */ +public class TrackerStats +{ + public static final int TIME_SCALE = 1000000; + + ConcurrentHashMap modelTimes = new ConcurrentHashMap(); + + ConcurrentHashMap aclTimes = new ConcurrentHashMap(); + + ConcurrentHashMap changeSetAcls = new ConcurrentHashMap(); + + ConcurrentHashMap txDocs = new ConcurrentHashMap(); + + ConcurrentHashMap docTransformationTimes = new ConcurrentHashMap(); + + ConcurrentHashMap nodeTimes = new ConcurrentHashMap(); + + ConcurrentHashMap elapsedNodeTimes = new ConcurrentHashMap(); + + ConcurrentHashMap elapsedAclTimes = new ConcurrentHashMap(); + + ConcurrentHashMap elapsedContentTimes = new ConcurrentHashMap(); + + private InformationServerCollectionProvider infoSrv; + + public TrackerStats(InformationServerCollectionProvider server) + { + infoSrv = server; + } + + /** + * @return the modelTimes + */ + public SimpleStats getModelTimes() + { + return aggregateResults(modelTimes); + } + + /** + * @param all ConcurrentHashMap + * @return SimpleStats + */ + private SimpleStats aggregateResults(ConcurrentHashMap all) + { + SimpleStats answer = null; + + for (String key : all.keySet()) + { + IncrementalStats next = all.get(key); + IncrementalStats stats = next.copy(); + if (answer == null) + { + answer = new SimpleStats(stats.scale, this.infoSrv); + answer .start = stats.start; + answer.moments[0] = stats.moments[0]; + answer.moments[1] = stats.moments[1]; + answer.moments[2] = stats.moments[2]; + answer.max = stats.max; + answer.min = stats.min; + answer.copies.put(key, stats); + } + else + { + SimpleStats newAnswer = new SimpleStats(answer.scale, this.infoSrv); + + newAnswer.moments[0] = answer.moments[0] + stats.moments[0]; + + newAnswer.moments[1] = answer.moments[1] * answer.moments[0] + stats.moments[1] * stats.moments[0]; + newAnswer.moments[1] /= answer.moments[0] + stats.moments[0]; + + newAnswer.moments[2] = answer.moments[2] * answer.moments[0]; + newAnswer.moments[2] += (answer.moments[1] - newAnswer.moments[1]) * (answer.moments[1] - newAnswer.moments[1]) * answer.moments[0]; + newAnswer.moments[2] += stats.moments[2] * stats.moments[0]; + newAnswer.moments[2] += (stats.moments[1] - newAnswer.moments[1]) * (stats.moments[1] - newAnswer.moments[1]) * stats.moments[0]; + newAnswer.moments[2] /= answer.moments[0] + stats.moments[0]; + + newAnswer.min = (stats.min < answer.min) ? stats.min : answer.min; + newAnswer.max = (stats.max > answer.max) ? stats.max : answer.max; + + newAnswer.start = (stats.start.compareTo(answer.start) < 1) ? stats.start : answer.start; + + newAnswer.copies.putAll(answer.copies); + newAnswer.copies.put(key, stats); + + answer = newAnswer; + } + + } + + if (answer == null) + { + answer = new SimpleStats(1, this.infoSrv); + } + + return answer; + } + + /** + * @return the aclTxTimes + */ + public SimpleStats getAclTimes() + { + return aggregateResults(aclTimes); + } + + public SimpleStats getChangeSetAcls() + { + return aggregateResults(changeSetAcls); + } + + public SimpleStats getNodeTimes() + { + return aggregateResults(nodeTimes); + } + + /** + * @return the txDocs + */ + public SimpleStats getTxDocs() + { + return aggregateResults(txDocs); + } + + /** + * @return the docTransformationTimes + */ + public SimpleStats getDocTransformationTimes() + { + return aggregateResults(docTransformationTimes); + } + + public double getMeanModelSyncTime() + { + return aggregateResults(modelTimes).getMean(); + } + + public double getMeanNodeIndexTime() + { + return aggregateResults(nodeTimes).getMean(); + } + + public double getMeanNodeElapsedIndexTime() + { + return aggregateResults(elapsedNodeTimes).getMean(); + } + + public double getMeanAclElapsedIndexTime() + { + return aggregateResults(elapsedAclTimes).getMean(); + } + + public double getMeanContentElapsedIndexTime() + { + return aggregateResults(elapsedContentTimes).getMean(); + } + + public double getNodeIndexingThreadCount() + { + return nodeTimes.size(); + } + + public double getMeanAclIndexTime() + { + return aggregateResults(nodeTimes).getMean(); + } + + public double getMeanDocsPerTx() + { + return aggregateResults(txDocs).getMean(); + } + + public double getMeanAclsPerChangeSet() + { + return aggregateResults(changeSetAcls).getMean(); + } + + public static class SimpleStats + { + HashMap copies = new HashMap(); + private InformationServerCollectionProvider server; + int scale; + + SimpleStats(int scale, InformationServerCollectionProvider server) + { + this.scale = scale; + this.server = server; + } + + double[] moments = new double[3]; + + double min = 0D; + + double max = 0D; + + Date start = null; + + synchronized long getN() + { + return (long) moments[0]; + } + + synchronized double getMin() + { + return min; + } + + synchronized double getMax() + { + return max; + } + + synchronized double getMean() + { + return moments[1]; + } + + synchronized double getVarience() + { + if (moments[0] > 1) + { + return moments[2] * moments[0] / (moments[0] - 1); + } + else + { + return Double.NaN; + } + } + + synchronized double getStandardDeviation() + { + return Math.sqrt(getVarience()); + } + + public synchronized ISimpleOrderedMap getNamedList(boolean incdludeDetail, boolean includeHist, boolean includeValues) + { + ISimpleOrderedMap map = this.server.getSimpleOrderedMapInstance(); + map.add("Start", start); + map.add("N", getN()); + map.add("Min", getMin()); + map.add("Max", getMax()); + map.add("Mean", getMean()); + map.add("Varience", getVarience()); + map.add("StdDev", getStandardDeviation()); + if (incdludeDetail) + { + for (String key : copies.keySet()) + { + IncrementalStats value = copies.get(key); + map.add(key, value.getNamedList(includeHist, includeValues)); + } + } + + return map; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "SimpleStats [" + + "\n getN()=" + getN() + ",\n getMin()=" + getMin() + ",\n getMax()=" + getMax() + ",\n getMean()=" + + getMean() + ",\n getVarience()=" + getVarience() + ",\n getStandardDeviation()=" + getStandardDeviation() + ",\n copies=" + + copies + ",\n]"; + } + + } + + public static class Bucket + { + IncrementalStats incrementalStats; + + public double leftBoundary; + + public double rightBoundary; + + public double countLeft; + + public double countRight; + + Bucket(IncrementalStats incrementalStats, double leftBoundary, double rightBoundary) + { + this(incrementalStats, leftBoundary, rightBoundary, 0D, 0D); + } + + Bucket(IncrementalStats incrementalStats, double leftBoundary, double rightBoundary, double countLeft, double countRight) + { + this.incrementalStats = incrementalStats; + this.leftBoundary = leftBoundary; + this.rightBoundary = rightBoundary; + this.countLeft = countLeft; + this.countRight = countRight; + } + + public void add(double x) + { + if ((x - leftBoundary) < (rightBoundary - x)) + { + countLeft++; + } + else + { + countRight++; + } + } + + public double mergeError(Bucket o) + { + double f_m = (this.countLeft + this.countRight + o.countLeft + o.countRight) / 4.0d; + double t1 = this.countLeft - f_m; + double t2 = this.countRight - f_m; + double o1 = o.countLeft - f_m; + double o2 = o.countRight - f_m; + + return (t1 * t1) + (t2 * t2) + (o1 * o1) + (o2 * o2); + } + + public double error() + { + double f_m = (this.countLeft + this.countRight) / 2.0d; + double t1 = this.countLeft - f_m; + double t2 = this.countRight - f_m; + return (t1 * t1) + (t2 * t2); + + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + double mark = (leftBoundary + rightBoundary) / 2.0D; + double width = rightBoundary - leftBoundary; + return "Bucket [(" + + leftBoundary + " TO " + mark + " = " + countLeft / incrementalStats.getN() / width + ") : (" + mark + " TO " + rightBoundary + " = " + countRight + / incrementalStats.getN() / width + "]"; + } + + } + + public static class IncrementalStats + { + Date start = new Date(); + + int scale; + + int buckets; + + double[] moments = new double[5]; + + double min = 0D; + + double max = 0D; + + List values; + + List hist; + + InformationServerCollectionProvider server; + + public IncrementalStats(int scale, int buckets, InformationServerCollectionProvider infoSrv) + { + this.scale = scale; + this.buckets = buckets; + values = new ArrayList(buckets); + hist = new ArrayList(buckets + 1); + this.server = infoSrv; + } + + /** + * @return ISimpleOrderedMap + */ + public ISimpleOrderedMap getNamedList(boolean includeHist, boolean includeValues) + { + ISimpleOrderedMap map = this.server.getSimpleOrderedMapInstance(); + map.add("Start", start); + map.add("N", getN()); + map.add("Min", getMin()); + map.add("Max", getMax()); + map.add("Mean", getMean()); + map.add("Varience", getVarience()); + map.add("StdDev", getStandardDeviation()); + map.add("Skew", getSkew()); + map.add("Kurtosis", getKurtosis()); + + if (includeHist) + { + int i = 0; + ISimpleOrderedMap buckets = this.server.getSimpleOrderedMapInstance(); + for (Bucket b : hist) + { + double mark = (b.leftBoundary + b.rightBoundary) / 2.0D; + double width = b.rightBoundary - b.leftBoundary; + + // SimpleOrderedMap bucket = new SimpleOrderedMap(); + // bucket.add("Lower", b.leftBoundary); + // bucket.add("Upper", mark); + // bucket.add("ProbabilityDensity", b.countLeft/b.incrementalStats.getN()/width); + buckets.add("" + i++, (b.leftBoundary + mark) / 2.0D + "," + b.countLeft / b.incrementalStats.getN() / width); + + // bucket = new SimpleOrderedMap(); + // bucket.add("Lower", mark); + // bucket.add("Upper", b.rightBoundary); + // bucket.add("ProbabilityDensity", b.countRight/b.incrementalStats.getN()/width); + buckets.add("" + i++, (mark + b.rightBoundary) / 2.0D + "," + b.countRight / b.incrementalStats.getN() / width); + } + map.add("Buckets", buckets); + } + + if (includeValues) + { + int i = 0; + ISimpleOrderedMap valuesMap = this.server.getSimpleOrderedMapInstance(); + for (Double value : values) + { + valuesMap.add("" + i++, value); + } + map.add("Values", valuesMap); + } + + return map; + } + + public synchronized void reset() + { + moments = new double[5]; + + min = 0D; + + max = 0D; + + values = new ArrayList(buckets); + + hist = new ArrayList(buckets + 1); + + start = new Date(); + } + + public synchronized void add(double xUnscaled) + { + double x = xUnscaled / scale; + if ((moments[0] == 0) || (x > max)) + { + max = x; + } + if ((moments[0] == 0L) || (x < min)) + { + min = x; + } + double n = moments[0]; + double nPlus1 = n + 1; + double n2 = n * n; + double d = (moments[1] - x) / nPlus1; + double d2 = d * d; + double d3 = d2 * d; + double n_nPlus1 = n / nPlus1; + + moments[4] += 4 * d * moments[3] + 6 * d2 * moments[2] + (1 + n * n2) * d2 * d2; + moments[4] *= n_nPlus1; + + moments[3] += 3 * d * moments[2] + (1 - n2) * d3; + moments[3] *= n_nPlus1; + + moments[2] += (1 + n) * d2; + moments[2] *= n_nPlus1; + + moments[1] -= d; + + moments[0] = nPlus1; + + if (buckets > 1) + { + if (moments[0] < buckets) + { + values.add(Double.valueOf(x)); + } + else if (moments[0] == buckets) + { + values.add(Double.valueOf(x)); + buildInitialBuckets(); + } + else + { + values.set((int) moments[0] % buckets, x); + if (x < hist.get(0).leftBoundary) + { + double delta = (hist.get(0).leftBoundary - x) / 3.0; + Bucket b = new Bucket(this, x - delta, hist.get(0).leftBoundary); + hist.add(0, b); + b.add(x); + Pair bestToMerge = findBestToMerge(); + if (hist.size() > buckets) + { + merge(bestToMerge.getFirst()); + } + } + else if (x >= hist.get(hist.size() - 1).rightBoundary) + { + double delta = (x - hist.get(hist.size() - 1).rightBoundary) / 3.0; + Bucket b = new Bucket(this, hist.get(hist.size() - 1).rightBoundary, x + delta); + hist.add(b); + b.add(x); + Pair bestToMerge = findBestToMerge(); + if (hist.size() > buckets) + { + merge(bestToMerge.getFirst()); + } + } + else + { + // find existing + for (Bucket b : hist) + { + if ((b.leftBoundary <= x) && (x < b.rightBoundary)) + { + b.add(x); + break; + } + + } + Pair bestToMerge = findBestToMerge(); + Pair bestToSplit = findBestToSplit(); + + if (bestToMerge.getSecond() - bestToSplit.getSecond() < 0) + { + if(hist.size() < buckets) + { + split(bestToSplit.getFirst()); + } + else + { + merge(bestToMerge.getFirst()); + split(bestToMerge.getFirst() < bestToSplit.getFirst() ? bestToSplit.getFirst() - 1 : bestToSplit.getFirst()); + } + } + } + } + } + } + + /** + * + */ + private void buildInitialBuckets() + { + // generate initial bucket list + Collections.sort(values); + FOUND: for (int i = 0; i < values.size(); i++) + { + for (Bucket b : hist) + { + if ((b.leftBoundary <= values.get(i)) && (values.get(i) < b.rightBoundary)) + { + b.add(values.get(i)); + continue FOUND; + } + + } + if (i < values.size() - 1) + { + double start = values.get(i); + double end = start + 1.0D; + + END: for (int j = i + 1; j < values.size(); j++) + { + if (values.get(j) > start) + { + end = values.get(j); + break END; + } + } + + Bucket b = new Bucket(this, start, end); + b.add(values.get(i)); + hist.add(b); + } + else + { + double first = values.get(0); + double last = values.get(values.size() - 1); + double width = 1.0D; + if (values.size() > 1) + { + width = (last - first) / (values.size() - 1); + } + Bucket b = new Bucket(this, last, last + width); + b.add(values.get(i)); + hist.add(b); + } + } + } + + void merge(int position) + { + Bucket lower = hist.get(position); + Bucket upper = hist.get(position + 1); + Bucket merged = new Bucket(this, lower.leftBoundary, upper.rightBoundary, lower.countLeft + lower.countRight, upper.countLeft + upper.countRight); + hist.remove(position); + hist.set(position, merged); + + } + + void split(int position) + { + Bucket toSplit = hist.get(position); + double mark = (toSplit.leftBoundary + toSplit.rightBoundary) / 2.0D; + Bucket lower = new Bucket(this, toSplit.leftBoundary, mark, toSplit.countLeft / 2.0D, toSplit.countLeft / 2.0D); + Bucket upper = new Bucket(this, mark, toSplit.rightBoundary, toSplit.countRight / 2.0D, toSplit.countRight / 2.0D); + hist.set(position, upper); + hist.add(position, lower); + } + + Pair findBestToMerge() + { + double minMergeError = Double.MAX_VALUE; + int bucket = 0; + for (int i = 0; i < hist.size() - 1; i++) + { + double mergeError = hist.get(i).mergeError(hist.get(i + 1)); + if (mergeError < minMergeError) + { + minMergeError = mergeError; + bucket = i; + } + } + return new Pair(bucket, minMergeError); + } + + Pair findBestToSplit() + { + double maxError = Double.MIN_VALUE; + int bucket = 0; + for (int i = 0; i < hist.size(); i++) + { + double error = hist.get(i).error(); + if (error > maxError) + { + maxError = error; + bucket = i; + } + } + return new Pair(bucket, maxError); + } + + public synchronized long getN() + { + return (long) moments[0]; + } + + public synchronized double getMin() + { + return min; + } + + public synchronized double getMax() + { + return max; + } + + public synchronized double getMean() + { + return moments[1]; + } + + public synchronized double getVarience() + { + if (moments[0] > 1) + { + return moments[2] * moments[0] / (moments[0] - 1); + } + else + { + return Double.NaN; + } + } + + public synchronized double getStandardDeviation() + { + return Math.sqrt(getVarience()); + } + + public synchronized double getSkew() + { + if (moments[0] > 2) + { + double v = getVarience(); + return moments[3] * moments[0] * moments[0] / (Math.sqrt(v) * v * (moments[0] - 1) * (moments[0] - 2)); + } + else + { + return Double.NaN; + } + } + + public synchronized double getKurtosis() + { + if (moments[0] > 3) + { + double div = (moments[0] - 2) * (moments[0] - 3); + double nMinus1 = moments[0] - 1; + double v = getVarience(); + double z = ((moments[4] * moments[0] * moments[0] * (moments[0] + 1)) / (v * v * nMinus1)); + z -= 3 * nMinus1 * nMinus1; + z /= div; + return z; + } + else + { + return Double.NaN; + } + } + + public synchronized List getHistogram() + { + if(hist.size() == 0) + { + buildInitialBuckets(); + } + return hist; + } + + + + synchronized IncrementalStats copy() + { + IncrementalStats copy = new IncrementalStats(this.scale, this.buckets, this.server); + copy.start = this.start; + copy.max = this.max; + copy.min = this.min; + copy.moments[0] = this.moments[0]; + copy.moments[1] = this.moments[1]; + copy.moments[2] = this.moments[2]; + copy.moments[3] = this.moments[3]; + copy.moments[4] = this.moments[4]; + for (Double x : this.values) + { + copy.values.add(x); + } + for (Bucket b : this.hist) + { + copy.hist.add(new Bucket(copy, b.leftBoundary, b.rightBoundary, b.countLeft, b.countRight)); + } + return copy; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "IncrementalStats [getN()=" + + getN() + ", getMin()=" + getMin() + ", getMax()=" + getMax() + ", getMean()=" + getMean() + ", getVarience()=" + getVarience() + ", getStandardDeviation()=" + + getStandardDeviation() + ", getSkew()=" + getSkew() + ", getKurtosis()=" + getKurtosis() + ", values=" + values + ", hist=" + hist + "]"; + } + + } + + /** + * @param time long + */ + public void addModelTime(long time) + { + IncrementalStats stats = modelTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + modelTimes.put(Thread.currentThread().getName(), stats); + } + stats.add(time); + } + + /** + * @param time long + */ + public void addAclTime(long time) + { + IncrementalStats stats = aclTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + aclTimes.put(Thread.currentThread().getName(), stats); + } + stats.add(time); + } + + /** + * @param time long + */ + public void addNodeTime(long time) + { + IncrementalStats stats = nodeTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + nodeTimes.put(Thread.currentThread().getName(), stats); + } + stats.add(time); + } + + /** + * @param docCount int + * @param time long + */ + public void addElapsedNodeTime(int docCount, long time) + { + if(docCount < 1) + { + return; + } + IncrementalStats stats = elapsedNodeTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + elapsedNodeTimes.put(Thread.currentThread().getName(), stats); + } + long meanTime = time / docCount; + for(int i = 0; i < docCount; i++) + { + stats.add(meanTime); + } + + } + + /** + * @param docCount int + * @param time long + */ + public void addElapsedAclTime(int docCount, long time) + { + if(docCount < 1) + { + return; + } + IncrementalStats stats = elapsedAclTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + elapsedAclTimes.put(Thread.currentThread().getName(), stats); + } + long meanTime = time / docCount; + for(int i = 0; i < docCount; i++) + { + stats.add(meanTime); + } + + } + + /** + * @param docCount int + * @param time long + */ + public void addElapsedContentTime(int docCount, long time) + { + if(docCount < 1) + { + return; + } + IncrementalStats stats = elapsedContentTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + elapsedContentTimes.put(Thread.currentThread().getName(), stats); + } + long meanTime = time / docCount; + for(int i = 0; i < docCount; i++) + { + stats.add(meanTime); + } + + } + + /** + * @param size int + */ + public void addTxDocs(int size) + { + IncrementalStats stats = txDocs.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(1, 50, this.infoSrv); + txDocs.put(Thread.currentThread().getName(), stats); + } + stats.add(size); + } + + /** + * @param size int + */ + public void addChangeSetAcls(int size) + { + IncrementalStats stats = changeSetAcls.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(1, 50, this.infoSrv); + changeSetAcls.put(Thread.currentThread().getName(), stats); + } + stats.add(size); + } + + /** + * @param time long + */ + public void addDocTransformationTime(long time) + { + IncrementalStats stats = docTransformationTimes.get(Thread.currentThread().getName()); + if (stats == null) + { + stats = new IncrementalStats(TIME_SCALE, 50, this.infoSrv); + docTransformationTimes.put(Thread.currentThread().getName(), stats); + } + stats.add(time); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() + { + return "TrackerStats [modelTimes=" + + modelTimes + ", aclTimes=" + aclTimes + ", changeSetAcls=" + changeSetAcls + ", txDocs=" + txDocs + ", docTransformationTimes=" + docTransformationTimes + + ", nodeTimes=" + nodeTimes + "]"; + } + + /** + * + */ + public void reset() + { + modelTimes.clear(); + aclTimes.clear(); + changeSetAcls.clear(); + txDocs.clear(); + docTransformationTimes.clear(); + nodeTimes.clear(); + } + + +} diff --git a/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientFactoryTest.java b/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientFactoryTest.java index 4b2f62f8d..b21f4d82e 100644 --- a/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientFactoryTest.java +++ b/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientFactoryTest.java @@ -1,80 +1,80 @@ - -package org.alfresco.solr.client; - -import static org.mockito.Mockito.*; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; - -import java.util.Properties; - -import org.alfresco.encryption.KeyResourceLoader; -import org.alfresco.repo.dictionary.NamespaceDAO; -import org.alfresco.service.cmr.dictionary.DictionaryService; -import org.alfresco.solr.client.SOLRAPIClient; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.runners.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class SOLRAPIClientFactoryTest -{ - @Mock - private Properties props; - @Mock - private KeyResourceLoader keyResourceLoader; - @Mock - private DictionaryService dictionaryService; - @Mock - private NamespaceDAO namespaceDAO; - private SOLRAPIClientFactory factory; - - @Before - public void setUp() throws Exception - { - when(props.getProperty(eq("alfresco.host"), anyString())).thenReturn("localhost"); - when(props.getProperty(eq("alfresco.port"), anyString())).thenReturn("8080"); - when(props.getProperty(eq("alfresco.port.ssl"), anyString())).thenReturn("8443"); - when(props.getProperty(eq("alfresco.maxTotalConnections"), anyString())).thenReturn("40"); - when(props.getProperty(eq("alfresco.maxHostConnections"), anyString())).thenReturn("40"); - when(props.getProperty(eq("alfresco.socketTimeout"), anyString())).thenReturn("0"); - when(props.getProperty(eq("alfresco.secureComms"), anyString())).thenReturn("none"); - when(props.getProperty(eq("alfresco.encryption.ssl.keystore.location"), anyString())) - .thenReturn("ssl.repo.client.keystore"); - when(props.getProperty(eq("alfresco.encryption.ssl.truststore.location"), anyString())) - .thenReturn("ssl.repo.client.truststore"); - - this.factory = new SOLRAPIClientFactory(); - } - - @Test - public void getsSameSOLRAPIClientForSameAlfresco() - { - SOLRAPIClient solrapiClient = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, - namespaceDAO); - assertNotNull(solrapiClient); - - SOLRAPIClient solrapiClient2 = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, - namespaceDAO); - assertNotNull(solrapiClient2); - - assertSame(solrapiClient, solrapiClient2); - } - - @Test - public void getsDifferentSOLRAPIClientForDifferentAlfresco() - { - SOLRAPIClient solrapiClient = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, - namespaceDAO); - assertNotNull(solrapiClient); - - when(props.getProperty("alfresco.port.ssl", "8443")).thenReturn("8444"); - SOLRAPIClient solrapiClient2 = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, - namespaceDAO); - assertNotNull(solrapiClient2); - - assertNotSame(solrapiClient, solrapiClient2); - } -} + +package org.alfresco.solr.client; + +import static org.mockito.Mockito.*; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +import java.util.Properties; + +import org.alfresco.encryption.KeyResourceLoader; +import org.alfresco.repo.dictionary.NamespaceDAO; +import org.alfresco.service.cmr.dictionary.DictionaryService; +import org.alfresco.solr.client.SOLRAPIClient; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SOLRAPIClientFactoryTest +{ + @Mock + private Properties props; + @Mock + private KeyResourceLoader keyResourceLoader; + @Mock + private DictionaryService dictionaryService; + @Mock + private NamespaceDAO namespaceDAO; + private SOLRAPIClientFactory factory; + + @Before + public void setUp() throws Exception + { + when(props.getProperty(eq("alfresco.host"), anyString())).thenReturn("localhost"); + when(props.getProperty(eq("alfresco.port"), anyString())).thenReturn("8080"); + when(props.getProperty(eq("alfresco.port.ssl"), anyString())).thenReturn("8443"); + when(props.getProperty(eq("alfresco.maxTotalConnections"), anyString())).thenReturn("40"); + when(props.getProperty(eq("alfresco.maxHostConnections"), anyString())).thenReturn("40"); + when(props.getProperty(eq("alfresco.socketTimeout"), anyString())).thenReturn("0"); + when(props.getProperty(eq("alfresco.secureComms"), anyString())).thenReturn("none"); + when(props.getProperty(eq("alfresco.encryption.ssl.keystore.location"), anyString())) + .thenReturn("ssl.repo.client.keystore"); + when(props.getProperty(eq("alfresco.encryption.ssl.truststore.location"), anyString())) + .thenReturn("ssl.repo.client.truststore"); + + this.factory = new SOLRAPIClientFactory(); + } + + @Test + public void getsSameSOLRAPIClientForSameAlfresco() + { + SOLRAPIClient solrapiClient = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, + namespaceDAO); + assertNotNull(solrapiClient); + + SOLRAPIClient solrapiClient2 = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, + namespaceDAO); + assertNotNull(solrapiClient2); + + assertSame(solrapiClient, solrapiClient2); + } + + @Test + public void getsDifferentSOLRAPIClientForDifferentAlfresco() + { + SOLRAPIClient solrapiClient = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, + namespaceDAO); + assertNotNull(solrapiClient); + + when(props.getProperty("alfresco.port.ssl", "8443")).thenReturn("8444"); + SOLRAPIClient solrapiClient2 = factory.getSOLRAPIClient(props, keyResourceLoader, dictionaryService, + namespaceDAO); + assertNotNull(solrapiClient2); + + assertNotSame(solrapiClient, solrapiClient2); + } +} diff --git a/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientTest.java b/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientTest.java index 7da98ee86..aac736dbe 100644 --- a/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientTest.java +++ b/search-services/alfresco-solrclient-lib/source/test-java/org/alfresco/solr/client/SOLRAPIClientTest.java @@ -1,660 +1,660 @@ -package org.alfresco.solr.client; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.security.AlgorithmParameters; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import junit.framework.TestCase; - -import org.alfresco.encryption.DefaultEncryptionUtils; -import org.alfresco.encryption.KeyProvider; -import org.alfresco.encryption.KeyResourceLoader; -import org.alfresco.encryption.KeyStoreParameters; -import org.alfresco.encryption.MACUtils.MACInput; -import org.alfresco.encryption.ssl.SSLEncryptionParameters; -import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.httpclient.AlfrescoHttpClient; -import org.alfresco.httpclient.AuthenticationException; -import org.alfresco.httpclient.HttpClientFactory; -import org.alfresco.httpclient.HttpClientFactory.SecureCommsType; -import org.alfresco.httpclient.MD5EncryptionParameters; -import org.alfresco.opencmis.dictionary.CMISDictionaryRegistry; -import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService; -import org.alfresco.opencmis.mapping.CMISMapping; -import org.alfresco.opencmis.mapping.RuntimePropertyLuceneBuilderMapping; -import org.alfresco.repo.cache.MemoryCache; -import org.alfresco.repo.dictionary.DictionaryComponent; -import org.alfresco.repo.dictionary.DictionaryDAOImpl; -import org.alfresco.repo.dictionary.CompiledModelsCache; -import org.alfresco.repo.dictionary.DictionaryNamespaceComponent; -import org.alfresco.repo.dictionary.DictionaryRegistry; -import org.alfresco.repo.dictionary.M2Model; -import org.alfresco.repo.dictionary.M2Namespace; -import org.alfresco.repo.dictionary.NamespaceDAO; -import org.alfresco.repo.i18n.StaticMessageLookup; -import org.alfresco.repo.tenant.SingleTServiceImpl; -import org.alfresco.repo.tenant.TenantService; -import org.alfresco.service.namespace.QName; -import org.alfresco.util.DynamicallySizedThreadPoolExecutor; -import org.alfresco.util.Pair; -import org.alfresco.util.TraceableThreadFactory; -import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; -import org.apache.chemistry.opencmis.commons.enums.CmisVersion; -import org.apache.commons.httpclient.HttpMethod; -import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONException; - -/** - * Tests {@link SOLRAPIClient} Note: need to make sure that source/solr/instance is on the run classpath. Note: doesn't - * currently work, need to change to use SSL. - * - * @since 4.0 - */ -public class SOLRAPIClientTest extends TestCase -{ - private static Log logger = LogFactory.getLog(SOLRAPIClientTest.class); - - // private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml"; - - private SOLRAPIClient client; - - private SOLRAPIClient invalidKeyClient; - - private SOLRAPIClient tamperWithClient; - - private TenantService tenantService; - - private NamespaceDAO namespaceDAO; - - private DictionaryDAOImpl dictionaryDAO; - - private DictionaryComponent dictionaryComponent; - - private CMISStrictDictionaryService cmisDictionaryService; - - - // private M2Model testModel; - - private void loadModel(Map modelMap, HashSet loadedModels, M2Model model) - { - String modelName = model.getName(); - if (loadedModels.contains(modelName) == false) - { - for (M2Namespace importNamespace : model.getImports()) - { - M2Model importedModel = modelMap.get(importNamespace.getUri()); - if (importedModel != null) - { - - // Ensure that the imported model is loaded first - loadModel(modelMap, loadedModels, importedModel); - } - } - - dictionaryDAO.putModelIgnoringConstraints(model); - loadedModels.add(modelName); - } - } - - @Override - public void setUp() throws Exception - { - if(client == null) - { - tenantService = new SingleTServiceImpl(); - - dictionaryDAO = new DictionaryDAOImpl(); - namespaceDAO = dictionaryDAO; - dictionaryDAO.setTenantService(tenantService); - - CompiledModelsCache compiledModelsCache = new CompiledModelsCache(); - compiledModelsCache.setDictionaryDAO(dictionaryDAO); - compiledModelsCache.setTenantService(tenantService); - compiledModelsCache.setRegistry(new DefaultAsynchronouslyRefreshedCacheRegistry()); - TraceableThreadFactory threadFactory = new TraceableThreadFactory(); - threadFactory.setThreadDaemon(true); - threadFactory.setThreadPriority(Thread.NORM_PRIORITY); - - ThreadPoolExecutor threadPoolExecutor = new DynamicallySizedThreadPoolExecutor(20, 20, 90, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory, - new ThreadPoolExecutor.CallerRunsPolicy()); - compiledModelsCache.setThreadPoolExecutor(threadPoolExecutor); - dictionaryDAO.setDictionaryRegistryCache(compiledModelsCache); - // TODO: use config .... - dictionaryDAO.setDefaultAnalyserResourceBundleName("alfresco/model/dataTypeAnalyzers"); - dictionaryDAO.setResourceClassLoader(getResourceClassLoader()); - dictionaryDAO.init(); - - dictionaryComponent = new DictionaryComponent(); - dictionaryComponent.setDictionaryDAO(dictionaryDAO); - dictionaryComponent.setMessageLookup(new StaticMessageLookup()); - - // cmis dictionary - CMISMapping cmisMapping = new CMISMapping(); - cmisMapping.setCmisVersion(CmisVersion.CMIS_1_0); - DictionaryNamespaceComponent namespaceService = new DictionaryNamespaceComponent(); - namespaceService.setNamespaceDAO(namespaceDAO); - cmisMapping.setNamespaceService(namespaceService); - cmisMapping.setDictionaryService(dictionaryComponent); - cmisMapping.afterPropertiesSet(); - - cmisDictionaryService = new CMISStrictDictionaryService(); - cmisDictionaryService.setCmisMapping(cmisMapping); - cmisDictionaryService.setDictionaryService(dictionaryComponent); - cmisDictionaryService.setDictionaryDAO(dictionaryDAO); - cmisDictionaryService.setSingletonCache(new MemoryCache()); - cmisDictionaryService.setTenantService(tenantService); - cmisDictionaryService.init(); - - RuntimePropertyLuceneBuilderMapping luceneBuilderMapping = new RuntimePropertyLuceneBuilderMapping(); - luceneBuilderMapping.setDictionaryService(dictionaryComponent); - luceneBuilderMapping.setCmisDictionaryService(cmisDictionaryService); - cmisDictionaryService.setPropertyLuceneBuilderMapping(luceneBuilderMapping); - - luceneBuilderMapping.afterPropertiesSet(); - - // Load the key store from the classpath - ClasspathKeyResourceLoader keyResourceLoader = new ClasspathKeyResourceLoader(); - client = new SOLRAPIClient(getRepoClient(keyResourceLoader), dictionaryComponent, dictionaryDAO); - trackModels(); - } - } - - private void trackModels() throws AuthenticationException, IOException, JSONException - { - - List modelDiffs = client.getModelsDiff(Collections. emptyList()); - HashMap modelMap = new HashMap(); - - for (AlfrescoModelDiff modelDiff : modelDiffs) - { - switch (modelDiff.getType()) - { - case CHANGED: - AlfrescoModel changedModel = client.getModel(modelDiff.getModelName()); - for (M2Namespace namespace : changedModel.getModel().getNamespaces()) - { - modelMap.put(namespace.getUri(), changedModel.getModel()); - } - break; - case NEW: - AlfrescoModel newModel = client.getModel(modelDiff.getModelName()); - for (M2Namespace namespace : newModel.getModel().getNamespaces()) - { - modelMap.put(namespace.getUri(), newModel.getModel()); - } - break; - case REMOVED: - // At the moment we do not unload models - I can see no side effects .... - // However search is used to check for references to indexed properties or types - // This will be partially broken anyway due to eventual consistency - // A model should only be unloaded if there are no data dependencies - // Should have been on the de-lucene list. - break; - } - } - - HashSet loadedModels = new HashSet(); - for (M2Model model : modelMap.values()) - { - loadModel(modelMap, loadedModels, model); - } - if (modelDiffs.size() > 0) - { - afterInitModels(); - } - - } - - public void afterInitModels() - { - cmisDictionaryService.afterDictionaryInit(); - } - - - protected AlfrescoHttpClient getRepoClient(ClasspathKeyResourceLoader keyResourceLoader) - { - // TODO i18n - KeyStoreParameters keyStoreParameters = new KeyStoreParameters("SSL Key Store", "JCEKS", null, "ssl-keystore-passwords.properties", "ssl.repo.client.keystore"); - KeyStoreParameters trustStoreParameters = new KeyStoreParameters("SSL Trust Store", "JCEKS", null, "ssl-truststore-passwords.properties", "ssl.repo.client.truststore"); - - SSLEncryptionParameters sslEncryptionParameters = new SSLEncryptionParameters(keyStoreParameters, trustStoreParameters); - - //MD5HttpClientFactory httpClientFactory = new MD5HttpClientFactory(); -// HttpClientFactory httpClientFactory = new HttpClientFactory(SecureComm); -// -// invalidKeyEncryptionService = new EncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); -// AlfrescoHttpClient repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, invalidKeyEncryptionService); -// //SecureHttpClient repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, invalidKeyEncryptionService); -// invalidKeyClient = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); -// -// keyStoreParameters.setLocation("org/alfresco/solr/client/.keystore"); -// tamperWithEncryptionService = new TamperWithEncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); -// repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, tamperWithEncryptionService); -//// repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, tamperWithEncryptionService); -// tamperWithClient = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); -// -// encryptionParameters.setMessageTimeout(30*1000); -// keyStoreParameters.setLocation("workspace-SpacesStore/conf/.keystore"); -// EncryptionService encryptionService = new EncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); -// repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, encryptionService); - //repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, encryptionService); -// client = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); - - HttpClientFactory httpClientFactory = new HttpClientFactory(SecureCommsType.getType("https"), sslEncryptionParameters, keyResourceLoader, null, null, "localhost", 8080, - 8443, 40, 40, 0); - // TODO need to make port configurable depending on secure comms, or just make redirects - // work - AlfrescoHttpClient repoClient = httpClientFactory.getRepoClient("localhost", 8443); - return repoClient; - } - - public ClassLoader getResourceClassLoader() - { - - File f = new File("woof", "alfrescoResources"); - if (f.canRead() && f.isDirectory()) - { - - URL[] urls = new URL[1]; - - try - { - URL url = f.toURI().normalize().toURL(); - urls[0] = url; - } - catch (MalformedURLException e) - { - throw new AlfrescoRuntimeException("Failed to add resources to classpath ", e); - } - - return URLClassLoader.newInstance(urls, this.getClass().getClassLoader()); - } - else - { - return this.getClass().getClassLoader(); - } - } - - private class ClasspathKeyResourceLoader implements KeyResourceLoader - { - @Override - public InputStream getKeyStore(String location) throws FileNotFoundException - { - return getClass().getClassLoader().getResourceAsStream(location); - } - - @Override - public Properties loadKeyMetaData(String location) throws IOException - { - Properties p = new Properties(); - p.load(getClass().getClassLoader().getResourceAsStream(location)); - return p; - } - } - - /** - * Full testing of ChangeSets, ACLs and Readers - */ - public void testGetAcls() throws Exception - { - AclChangeSets aclChangeSets = null; - - aclChangeSets = client.getAclChangeSets(null, null, null, null, 50); - assertTrue("Too many results", aclChangeSets.getAclChangeSets().size() <= 50); - if (aclChangeSets.getAclChangeSets().size() < 2) - { - return; // Not enough data - } - AclChangeSet aclChangeSetCheck = null; - AclChangeSet aclChangeSet0 = aclChangeSets.getAclChangeSets().get(0); - AclChangeSet aclChangeSet1 = aclChangeSets.getAclChangeSets().get(1); - long id0 = aclChangeSet0.getId(); - long commitTimeMs0 = aclChangeSet0.getCommitTimeMs(); - // Now query for the next ID - Long nextId = id0 + 1; - aclChangeSets = client.getAclChangeSets(commitTimeMs0, nextId, null, null, 1); - assertEquals(1, aclChangeSets.getAclChangeSets().size()); - aclChangeSetCheck = aclChangeSets.getAclChangeSets().get(0); - assertEquals(aclChangeSet1, aclChangeSetCheck); - - Map aclChangeSetsById = new HashMap(); - for (AclChangeSet aclChangeSet : aclChangeSets.getAclChangeSets()) - { - aclChangeSetsById.put(aclChangeSet.getId(), aclChangeSet); - } - - Set aclIdUniqueCheck = new HashSet(1000); - // Now do a large walk-through of the ACLs - Long minAclChangeSetId = null; - Long fromCommitTimeMs = null; - for (int i = 0; i < 100; i++) - { - aclChangeSets = client.getAclChangeSets(fromCommitTimeMs, minAclChangeSetId, null, null, 10); - if (aclChangeSets.getAclChangeSets().size() == 0) - { - break; - } - // Now repeat for the ACLs, keeping track of the last ChangeSet - Long nextAclId = null; - while (true) - { - List acls = client.getAcls(aclChangeSets.getAclChangeSets(), nextAclId, 512); - if (acls.size() == 0) - { - break; // Run out of ACLs - } - Set aclIds = new HashSet(1000); - for (Acl acl : acls) - { - long aclId = acl.getId(); - aclIds.add(aclId); - if (!aclIdUniqueCheck.add(aclId)) - { - // ignore duplicates for lazy/eager shared acl creation - //fail("ACL already processed: " + aclId); - } - // Check that we are ascending - if (nextAclId != null) - { - assertTrue("ACL IDs must be ascending: " + aclId, nextAclId.longValue() <= aclId); - } - nextAclId = aclId + 1; - } - // Now get the readers for these ACLs - List aclsReaders = client.getAclReaders(acls); - // Check that the ACL ids are all covered - for (AclReaders aclReaders : aclsReaders) - { - Long aclId = aclReaders.getId(); - aclIds.remove(aclId); - } - assertTrue("Some ACL IDs were not covered: " + aclIds, aclIds.size() == 0); - } - // March in time - AclChangeSet lastAclChangeSet = aclChangeSets.getAclChangeSets().get(aclChangeSets.getAclChangeSets().size() - 1); - fromCommitTimeMs = lastAclChangeSet.getCommitTimeMs(); - minAclChangeSetId = lastAclChangeSet.getId() + 1; - } - } - - public void testGetTransactions() throws Exception - { - // get transactions starting from txn id 1298288417234l - Transactions transactions = client.getTransactions(1298288417234l, null, null, null, 5); - - // get transactions starting from transaction 426 - transactions = client.getTransactions(null, Long.valueOf(1), null, null, 5); - List transactionIds = new ArrayList(transactions.getTransactions().size()); - for (Transaction info : transactions.getTransactions()) - { - logger.debug(info); - transactionIds.add(Long.valueOf(info.getId())); - } - - // get the first 3 nodes in those transactions - GetNodesParameters params = new GetNodesParameters(); - params.setTransactionIds(transactionIds); - List nodes = client.getNodes(params, 5); - for (Node info : nodes) - { - logger.debug(info); - } - - // get the next 3 nodes in those transactions i.e. starting from the last node id (inclusive) - params = new GetNodesParameters(); - params.setTransactionIds(transactionIds); - params.setFromNodeId(nodes.get(nodes.size() - 1).getId()); - nodes = client.getNodes(params, 3); - List nodeIds = new ArrayList(nodes.size()); - for (Node info : nodes) - { - logger.debug(info); - nodeIds.add(info.getId()); - } - - NodeMetaDataParameters metaParams = new NodeMetaDataParameters(); - metaParams.setNodeIds(nodeIds); - List metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - } - - public void testMetaData() throws AuthenticationException, IOException, JSONException - { - NodeMetaDataParameters metaParams = new NodeMetaDataParameters(); - List nodeIds = new ArrayList(1); - nodeIds.add(1l); - metaParams.setNodeIds(nodeIds); - List metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(9l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(19l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - - // individual tag/category - // TODO check why the category path has a null QName - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(49437l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - - // content with tags - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(49431l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - MultiPropertyValue multi = (MultiPropertyValue) info.getProperties().get(QName.createQName("{http://www.alfresco.org/model/content/1.0}taggable")); - if(multi != null) - { - for (PropertyValue propValue : multi.getValues()) - { - logger.debug("multi property values = " + propValue); - } - } - } - - // content with null property values for author - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(117630l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - - // content with accented characters in title properties - metaParams = new NodeMetaDataParameters(); - nodeIds = new ArrayList(1); - nodeIds.add(117678l); - metaParams.setNodeIds(nodeIds); - metadata = client.getNodesMetaData(metaParams, 3); - for (NodeMetaData info : metadata) - { - logger.debug(info); - } - } - - public void testGetModel() throws AuthenticationException, IOException, JSONException - { - AlfrescoModel alfModel = client.getModel(QName.createQName("http://www.alfresco.org/model/content/1.0", "contentmodel")); - M2Model model = alfModel.getModel(); - assertNotNull(model); - assertEquals("Returned model has incorrect name", "cm:contentmodel", model.getName()); - assertNotNull(alfModel.getChecksum()); - } - - public void testGetModelDiffs() throws AuthenticationException, IOException, JSONException - { - List diffs = client.getModelsDiff(Collections. emptyList()); - assertTrue(diffs.size() > 0); - } - -// public void testMAC() throws IOException, JSONException -// { -// // dodyClient has a secret key that is not the same as the repository's. This -// // should fail with a 401 -// try -// { -// Transactions transactions = invalidKeyClient.getTransactions(1298288417234l, null, null, null, 5); -// } -// catch (AuthenticationException e) -// { -// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); -// } -// -// try -// { -// tamperWithEncryptionService.setOverrideTimestamp(true); -// Transactions transactions = tamperWithClient.getTransactions(1298288417234l, null, null, null, 5); -// } -// catch (AuthenticationException e) -// { -// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); -// } -// finally -// { -// tamperWithEncryptionService.setOverrideTimestamp(false); -// } -// -// try -// { -// tamperWithEncryptionService.setOverrideMAC(true); -// Transactions transactions = tamperWithClient.getTransactions(1298288417234l, null, null, null, 5); -// } -// catch (AuthenticationException e) -// { -// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); -// } -// finally -// { -// tamperWithEncryptionService.setOverrideMAC(false); -// } -// } - - private void outputTextContent(SOLRAPIClient.GetTextContentResponse response) throws IOException - { - InputStream in = response.getContent(); - if (in != null) - { - logger.debug("Text content:"); - - BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); - String line = null; - while ((line = reader.readLine()) != null) - { - logger.debug(line); - } - } - } - - /** - * Overrides request encryption to create dodgy MAC and timestamp on requests - */ - private static class TestEncryptionUtils extends DefaultEncryptionUtils - { - private boolean overrideMAC = false; - - private boolean overrideTimestamp = false; - - public void setOverrideMAC(boolean overrideMAC) - { - this.overrideMAC = overrideMAC; - } - - public void setOverrideTimestamp(boolean overrideTimestamp) - { - this.overrideTimestamp = overrideTimestamp; - } - - @Override - public void setRequestAuthentication(HttpMethod method, byte[] message) throws IOException - { - if (method instanceof PostMethod) - { - // encrypt body - Pair encrypted = encryptor.encrypt(KeyProvider.ALIAS_SOLR, null, message); - setRequestAlgorithmParameters(method, encrypted.getSecond()); - - ((PostMethod) method).setRequestEntity(new ByteArrayRequestEntity(encrypted.getFirst(), "application/octet-stream")); - } - - long requestTimestamp = System.currentTimeMillis(); - - // add MAC header - byte[] mac = macUtils.generateMAC(KeyProvider.ALIAS_SOLR, new MACInput(message, requestTimestamp, getLocalIPAddress())); - - if (logger.isDebugEnabled()) - { - logger.debug("Setting MAC " + mac + " on HTTP request " + method.getPath()); - logger.debug("Setting timestamp " + requestTimestamp + " on HTTP request " + method.getPath()); - } - - if (overrideMAC) - { - mac[0] += (byte) 1; - } - setRequestMac(method, mac); - - if (overrideTimestamp) - { - requestTimestamp += 60000; - } - // prevent replays - setRequestTimestamp(method, requestTimestamp); - } - } -} +package org.alfresco.solr.client; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.security.AlgorithmParameters; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +import junit.framework.TestCase; + +import org.alfresco.encryption.DefaultEncryptionUtils; +import org.alfresco.encryption.KeyProvider; +import org.alfresco.encryption.KeyResourceLoader; +import org.alfresco.encryption.KeyStoreParameters; +import org.alfresco.encryption.MACUtils.MACInput; +import org.alfresco.encryption.ssl.SSLEncryptionParameters; +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.httpclient.AlfrescoHttpClient; +import org.alfresco.httpclient.AuthenticationException; +import org.alfresco.httpclient.HttpClientFactory; +import org.alfresco.httpclient.HttpClientFactory.SecureCommsType; +import org.alfresco.httpclient.MD5EncryptionParameters; +import org.alfresco.opencmis.dictionary.CMISDictionaryRegistry; +import org.alfresco.opencmis.dictionary.CMISStrictDictionaryService; +import org.alfresco.opencmis.mapping.CMISMapping; +import org.alfresco.opencmis.mapping.RuntimePropertyLuceneBuilderMapping; +import org.alfresco.repo.cache.MemoryCache; +import org.alfresco.repo.dictionary.DictionaryComponent; +import org.alfresco.repo.dictionary.DictionaryDAOImpl; +import org.alfresco.repo.dictionary.CompiledModelsCache; +import org.alfresco.repo.dictionary.DictionaryNamespaceComponent; +import org.alfresco.repo.dictionary.DictionaryRegistry; +import org.alfresco.repo.dictionary.M2Model; +import org.alfresco.repo.dictionary.M2Namespace; +import org.alfresco.repo.dictionary.NamespaceDAO; +import org.alfresco.repo.i18n.StaticMessageLookup; +import org.alfresco.repo.tenant.SingleTServiceImpl; +import org.alfresco.repo.tenant.TenantService; +import org.alfresco.service.namespace.QName; +import org.alfresco.util.DynamicallySizedThreadPoolExecutor; +import org.alfresco.util.Pair; +import org.alfresco.util.TraceableThreadFactory; +import org.alfresco.util.cache.DefaultAsynchronouslyRefreshedCacheRegistry; +import org.apache.chemistry.opencmis.commons.enums.CmisVersion; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; + +/** + * Tests {@link SOLRAPIClient} Note: need to make sure that source/solr/instance is on the run classpath. Note: doesn't + * currently work, need to change to use SSL. + * + * @since 4.0 + */ +public class SOLRAPIClientTest extends TestCase +{ + private static Log logger = LogFactory.getLog(SOLRAPIClientTest.class); + + // private static final String TEST_MODEL = "org/alfresco/repo/dictionary/dictionarydaotest_model.xml"; + + private SOLRAPIClient client; + + private SOLRAPIClient invalidKeyClient; + + private SOLRAPIClient tamperWithClient; + + private TenantService tenantService; + + private NamespaceDAO namespaceDAO; + + private DictionaryDAOImpl dictionaryDAO; + + private DictionaryComponent dictionaryComponent; + + private CMISStrictDictionaryService cmisDictionaryService; + + + // private M2Model testModel; + + private void loadModel(Map modelMap, HashSet loadedModels, M2Model model) + { + String modelName = model.getName(); + if (loadedModels.contains(modelName) == false) + { + for (M2Namespace importNamespace : model.getImports()) + { + M2Model importedModel = modelMap.get(importNamespace.getUri()); + if (importedModel != null) + { + + // Ensure that the imported model is loaded first + loadModel(modelMap, loadedModels, importedModel); + } + } + + dictionaryDAO.putModelIgnoringConstraints(model); + loadedModels.add(modelName); + } + } + + @Override + public void setUp() throws Exception + { + if(client == null) + { + tenantService = new SingleTServiceImpl(); + + dictionaryDAO = new DictionaryDAOImpl(); + namespaceDAO = dictionaryDAO; + dictionaryDAO.setTenantService(tenantService); + + CompiledModelsCache compiledModelsCache = new CompiledModelsCache(); + compiledModelsCache.setDictionaryDAO(dictionaryDAO); + compiledModelsCache.setTenantService(tenantService); + compiledModelsCache.setRegistry(new DefaultAsynchronouslyRefreshedCacheRegistry()); + TraceableThreadFactory threadFactory = new TraceableThreadFactory(); + threadFactory.setThreadDaemon(true); + threadFactory.setThreadPriority(Thread.NORM_PRIORITY); + + ThreadPoolExecutor threadPoolExecutor = new DynamicallySizedThreadPoolExecutor(20, 20, 90, TimeUnit.SECONDS, new LinkedBlockingQueue(), threadFactory, + new ThreadPoolExecutor.CallerRunsPolicy()); + compiledModelsCache.setThreadPoolExecutor(threadPoolExecutor); + dictionaryDAO.setDictionaryRegistryCache(compiledModelsCache); + // TODO: use config .... + dictionaryDAO.setDefaultAnalyserResourceBundleName("alfresco/model/dataTypeAnalyzers"); + dictionaryDAO.setResourceClassLoader(getResourceClassLoader()); + dictionaryDAO.init(); + + dictionaryComponent = new DictionaryComponent(); + dictionaryComponent.setDictionaryDAO(dictionaryDAO); + dictionaryComponent.setMessageLookup(new StaticMessageLookup()); + + // cmis dictionary + CMISMapping cmisMapping = new CMISMapping(); + cmisMapping.setCmisVersion(CmisVersion.CMIS_1_0); + DictionaryNamespaceComponent namespaceService = new DictionaryNamespaceComponent(); + namespaceService.setNamespaceDAO(namespaceDAO); + cmisMapping.setNamespaceService(namespaceService); + cmisMapping.setDictionaryService(dictionaryComponent); + cmisMapping.afterPropertiesSet(); + + cmisDictionaryService = new CMISStrictDictionaryService(); + cmisDictionaryService.setCmisMapping(cmisMapping); + cmisDictionaryService.setDictionaryService(dictionaryComponent); + cmisDictionaryService.setDictionaryDAO(dictionaryDAO); + cmisDictionaryService.setSingletonCache(new MemoryCache()); + cmisDictionaryService.setTenantService(tenantService); + cmisDictionaryService.init(); + + RuntimePropertyLuceneBuilderMapping luceneBuilderMapping = new RuntimePropertyLuceneBuilderMapping(); + luceneBuilderMapping.setDictionaryService(dictionaryComponent); + luceneBuilderMapping.setCmisDictionaryService(cmisDictionaryService); + cmisDictionaryService.setPropertyLuceneBuilderMapping(luceneBuilderMapping); + + luceneBuilderMapping.afterPropertiesSet(); + + // Load the key store from the classpath + ClasspathKeyResourceLoader keyResourceLoader = new ClasspathKeyResourceLoader(); + client = new SOLRAPIClient(getRepoClient(keyResourceLoader), dictionaryComponent, dictionaryDAO); + trackModels(); + } + } + + private void trackModels() throws AuthenticationException, IOException, JSONException + { + + List modelDiffs = client.getModelsDiff(Collections. emptyList()); + HashMap modelMap = new HashMap(); + + for (AlfrescoModelDiff modelDiff : modelDiffs) + { + switch (modelDiff.getType()) + { + case CHANGED: + AlfrescoModel changedModel = client.getModel(modelDiff.getModelName()); + for (M2Namespace namespace : changedModel.getModel().getNamespaces()) + { + modelMap.put(namespace.getUri(), changedModel.getModel()); + } + break; + case NEW: + AlfrescoModel newModel = client.getModel(modelDiff.getModelName()); + for (M2Namespace namespace : newModel.getModel().getNamespaces()) + { + modelMap.put(namespace.getUri(), newModel.getModel()); + } + break; + case REMOVED: + // At the moment we do not unload models - I can see no side effects .... + // However search is used to check for references to indexed properties or types + // This will be partially broken anyway due to eventual consistency + // A model should only be unloaded if there are no data dependencies + // Should have been on the de-lucene list. + break; + } + } + + HashSet loadedModels = new HashSet(); + for (M2Model model : modelMap.values()) + { + loadModel(modelMap, loadedModels, model); + } + if (modelDiffs.size() > 0) + { + afterInitModels(); + } + + } + + public void afterInitModels() + { + cmisDictionaryService.afterDictionaryInit(); + } + + + protected AlfrescoHttpClient getRepoClient(ClasspathKeyResourceLoader keyResourceLoader) + { + // TODO i18n + KeyStoreParameters keyStoreParameters = new KeyStoreParameters("SSL Key Store", "JCEKS", null, "ssl-keystore-passwords.properties", "ssl.repo.client.keystore"); + KeyStoreParameters trustStoreParameters = new KeyStoreParameters("SSL Trust Store", "JCEKS", null, "ssl-truststore-passwords.properties", "ssl.repo.client.truststore"); + + SSLEncryptionParameters sslEncryptionParameters = new SSLEncryptionParameters(keyStoreParameters, trustStoreParameters); + + //MD5HttpClientFactory httpClientFactory = new MD5HttpClientFactory(); +// HttpClientFactory httpClientFactory = new HttpClientFactory(SecureComm); +// +// invalidKeyEncryptionService = new EncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); +// AlfrescoHttpClient repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, invalidKeyEncryptionService); +// //SecureHttpClient repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, invalidKeyEncryptionService); +// invalidKeyClient = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); +// +// keyStoreParameters.setLocation("org/alfresco/solr/client/.keystore"); +// tamperWithEncryptionService = new TamperWithEncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); +// repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, tamperWithEncryptionService); +//// repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, tamperWithEncryptionService); +// tamperWithClient = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); +// +// encryptionParameters.setMessageTimeout(30*1000); +// keyStoreParameters.setLocation("workspace-SpacesStore/conf/.keystore"); +// EncryptionService encryptionService = new EncryptionService("127.0.0.1", 8080, keyResourceLoader, keyStoreParameters, encryptionParameters); +// repoClient = httpClientFactory.getAlfrescoHttpClient("127.0.0.1", 8080, encryptionService); + //repoClient = new SecureHttpClient(httpClientFactory, "127.0.0.1", 8080, encryptionService); +// client = new SOLRAPIClient(repoClient, model.getDictionaryService(), namespaceDAO); + + HttpClientFactory httpClientFactory = new HttpClientFactory(SecureCommsType.getType("https"), sslEncryptionParameters, keyResourceLoader, null, null, "localhost", 8080, + 8443, 40, 40, 0); + // TODO need to make port configurable depending on secure comms, or just make redirects + // work + AlfrescoHttpClient repoClient = httpClientFactory.getRepoClient("localhost", 8443); + return repoClient; + } + + public ClassLoader getResourceClassLoader() + { + + File f = new File("woof", "alfrescoResources"); + if (f.canRead() && f.isDirectory()) + { + + URL[] urls = new URL[1]; + + try + { + URL url = f.toURI().normalize().toURL(); + urls[0] = url; + } + catch (MalformedURLException e) + { + throw new AlfrescoRuntimeException("Failed to add resources to classpath ", e); + } + + return URLClassLoader.newInstance(urls, this.getClass().getClassLoader()); + } + else + { + return this.getClass().getClassLoader(); + } + } + + private class ClasspathKeyResourceLoader implements KeyResourceLoader + { + @Override + public InputStream getKeyStore(String location) throws FileNotFoundException + { + return getClass().getClassLoader().getResourceAsStream(location); + } + + @Override + public Properties loadKeyMetaData(String location) throws IOException + { + Properties p = new Properties(); + p.load(getClass().getClassLoader().getResourceAsStream(location)); + return p; + } + } + + /** + * Full testing of ChangeSets, ACLs and Readers + */ + public void testGetAcls() throws Exception + { + AclChangeSets aclChangeSets = null; + + aclChangeSets = client.getAclChangeSets(null, null, null, null, 50); + assertTrue("Too many results", aclChangeSets.getAclChangeSets().size() <= 50); + if (aclChangeSets.getAclChangeSets().size() < 2) + { + return; // Not enough data + } + AclChangeSet aclChangeSetCheck = null; + AclChangeSet aclChangeSet0 = aclChangeSets.getAclChangeSets().get(0); + AclChangeSet aclChangeSet1 = aclChangeSets.getAclChangeSets().get(1); + long id0 = aclChangeSet0.getId(); + long commitTimeMs0 = aclChangeSet0.getCommitTimeMs(); + // Now query for the next ID + Long nextId = id0 + 1; + aclChangeSets = client.getAclChangeSets(commitTimeMs0, nextId, null, null, 1); + assertEquals(1, aclChangeSets.getAclChangeSets().size()); + aclChangeSetCheck = aclChangeSets.getAclChangeSets().get(0); + assertEquals(aclChangeSet1, aclChangeSetCheck); + + Map aclChangeSetsById = new HashMap(); + for (AclChangeSet aclChangeSet : aclChangeSets.getAclChangeSets()) + { + aclChangeSetsById.put(aclChangeSet.getId(), aclChangeSet); + } + + Set aclIdUniqueCheck = new HashSet(1000); + // Now do a large walk-through of the ACLs + Long minAclChangeSetId = null; + Long fromCommitTimeMs = null; + for (int i = 0; i < 100; i++) + { + aclChangeSets = client.getAclChangeSets(fromCommitTimeMs, minAclChangeSetId, null, null, 10); + if (aclChangeSets.getAclChangeSets().size() == 0) + { + break; + } + // Now repeat for the ACLs, keeping track of the last ChangeSet + Long nextAclId = null; + while (true) + { + List acls = client.getAcls(aclChangeSets.getAclChangeSets(), nextAclId, 512); + if (acls.size() == 0) + { + break; // Run out of ACLs + } + Set aclIds = new HashSet(1000); + for (Acl acl : acls) + { + long aclId = acl.getId(); + aclIds.add(aclId); + if (!aclIdUniqueCheck.add(aclId)) + { + // ignore duplicates for lazy/eager shared acl creation + //fail("ACL already processed: " + aclId); + } + // Check that we are ascending + if (nextAclId != null) + { + assertTrue("ACL IDs must be ascending: " + aclId, nextAclId.longValue() <= aclId); + } + nextAclId = aclId + 1; + } + // Now get the readers for these ACLs + List aclsReaders = client.getAclReaders(acls); + // Check that the ACL ids are all covered + for (AclReaders aclReaders : aclsReaders) + { + Long aclId = aclReaders.getId(); + aclIds.remove(aclId); + } + assertTrue("Some ACL IDs were not covered: " + aclIds, aclIds.size() == 0); + } + // March in time + AclChangeSet lastAclChangeSet = aclChangeSets.getAclChangeSets().get(aclChangeSets.getAclChangeSets().size() - 1); + fromCommitTimeMs = lastAclChangeSet.getCommitTimeMs(); + minAclChangeSetId = lastAclChangeSet.getId() + 1; + } + } + + public void testGetTransactions() throws Exception + { + // get transactions starting from txn id 1298288417234l + Transactions transactions = client.getTransactions(1298288417234l, null, null, null, 5); + + // get transactions starting from transaction 426 + transactions = client.getTransactions(null, Long.valueOf(1), null, null, 5); + List transactionIds = new ArrayList(transactions.getTransactions().size()); + for (Transaction info : transactions.getTransactions()) + { + logger.debug(info); + transactionIds.add(Long.valueOf(info.getId())); + } + + // get the first 3 nodes in those transactions + GetNodesParameters params = new GetNodesParameters(); + params.setTransactionIds(transactionIds); + List nodes = client.getNodes(params, 5); + for (Node info : nodes) + { + logger.debug(info); + } + + // get the next 3 nodes in those transactions i.e. starting from the last node id (inclusive) + params = new GetNodesParameters(); + params.setTransactionIds(transactionIds); + params.setFromNodeId(nodes.get(nodes.size() - 1).getId()); + nodes = client.getNodes(params, 3); + List nodeIds = new ArrayList(nodes.size()); + for (Node info : nodes) + { + logger.debug(info); + nodeIds.add(info.getId()); + } + + NodeMetaDataParameters metaParams = new NodeMetaDataParameters(); + metaParams.setNodeIds(nodeIds); + List metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + } + + public void testMetaData() throws AuthenticationException, IOException, JSONException + { + NodeMetaDataParameters metaParams = new NodeMetaDataParameters(); + List nodeIds = new ArrayList(1); + nodeIds.add(1l); + metaParams.setNodeIds(nodeIds); + List metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(9l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(19l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + + // individual tag/category + // TODO check why the category path has a null QName + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(49437l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + + // content with tags + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(49431l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + MultiPropertyValue multi = (MultiPropertyValue) info.getProperties().get(QName.createQName("{http://www.alfresco.org/model/content/1.0}taggable")); + if(multi != null) + { + for (PropertyValue propValue : multi.getValues()) + { + logger.debug("multi property values = " + propValue); + } + } + } + + // content with null property values for author + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(117630l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + + // content with accented characters in title properties + metaParams = new NodeMetaDataParameters(); + nodeIds = new ArrayList(1); + nodeIds.add(117678l); + metaParams.setNodeIds(nodeIds); + metadata = client.getNodesMetaData(metaParams, 3); + for (NodeMetaData info : metadata) + { + logger.debug(info); + } + } + + public void testGetModel() throws AuthenticationException, IOException, JSONException + { + AlfrescoModel alfModel = client.getModel(QName.createQName("http://www.alfresco.org/model/content/1.0", "contentmodel")); + M2Model model = alfModel.getModel(); + assertNotNull(model); + assertEquals("Returned model has incorrect name", "cm:contentmodel", model.getName()); + assertNotNull(alfModel.getChecksum()); + } + + public void testGetModelDiffs() throws AuthenticationException, IOException, JSONException + { + List diffs = client.getModelsDiff(Collections. emptyList()); + assertTrue(diffs.size() > 0); + } + +// public void testMAC() throws IOException, JSONException +// { +// // dodyClient has a secret key that is not the same as the repository's. This +// // should fail with a 401 +// try +// { +// Transactions transactions = invalidKeyClient.getTransactions(1298288417234l, null, null, null, 5); +// } +// catch (AuthenticationException e) +// { +// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); +// } +// +// try +// { +// tamperWithEncryptionService.setOverrideTimestamp(true); +// Transactions transactions = tamperWithClient.getTransactions(1298288417234l, null, null, null, 5); +// } +// catch (AuthenticationException e) +// { +// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); +// } +// finally +// { +// tamperWithEncryptionService.setOverrideTimestamp(false); +// } +// +// try +// { +// tamperWithEncryptionService.setOverrideMAC(true); +// Transactions transactions = tamperWithClient.getTransactions(1298288417234l, null, null, null, 5); +// } +// catch (AuthenticationException e) +// { +// assertEquals("Should have caught unathorised request", e.getMethod().getStatusCode(), HttpStatus.SC_UNAUTHORIZED); +// } +// finally +// { +// tamperWithEncryptionService.setOverrideMAC(false); +// } +// } + + private void outputTextContent(SOLRAPIClient.GetTextContentResponse response) throws IOException + { + InputStream in = response.getContent(); + if (in != null) + { + logger.debug("Text content:"); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); + String line = null; + while ((line = reader.readLine()) != null) + { + logger.debug(line); + } + } + } + + /** + * Overrides request encryption to create dodgy MAC and timestamp on requests + */ + private static class TestEncryptionUtils extends DefaultEncryptionUtils + { + private boolean overrideMAC = false; + + private boolean overrideTimestamp = false; + + public void setOverrideMAC(boolean overrideMAC) + { + this.overrideMAC = overrideMAC; + } + + public void setOverrideTimestamp(boolean overrideTimestamp) + { + this.overrideTimestamp = overrideTimestamp; + } + + @Override + public void setRequestAuthentication(HttpMethod method, byte[] message) throws IOException + { + if (method instanceof PostMethod) + { + // encrypt body + Pair encrypted = encryptor.encrypt(KeyProvider.ALIAS_SOLR, null, message); + setRequestAlgorithmParameters(method, encrypted.getSecond()); + + ((PostMethod) method).setRequestEntity(new ByteArrayRequestEntity(encrypted.getFirst(), "application/octet-stream")); + } + + long requestTimestamp = System.currentTimeMillis(); + + // add MAC header + byte[] mac = macUtils.generateMAC(KeyProvider.ALIAS_SOLR, new MACInput(message, requestTimestamp, getLocalIPAddress())); + + if (logger.isDebugEnabled()) + { + logger.debug("Setting MAC " + mac + " on HTTP request " + method.getPath()); + logger.debug("Setting timestamp " + requestTimestamp + " on HTTP request " + method.getPath()); + } + + if (overrideMAC) + { + mac[0] += (byte) 1; + } + setRequestMac(method, mac); + + if (overrideTimestamp) + { + requestTimestamp += 60000; + } + // prevent replays + setRequestTimestamp(method, requestTimestamp); + } + } +}