/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.registry.indexing;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonException;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.indexing.indexer.Indexer;
import org.wso2.carbon.utils.CarbonUtils;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class RegistryConfigLoader {
public static final String SKIP_CACHE = "skipCache";
public static final String TRUE = "true";
private static volatile RegistryConfigLoader registryConfigLoaderInstance = new RegistryConfigLoader();
private static Log log = LogFactory.getLog(RegistryConfigLoader.class);
private boolean startIndexing;
private long startingDelayInSecs;
private long indexingFreqInSecs;
private String lastAccessTimeLocation;
private Map<String, Indexer> indexerMap = new LinkedHashMap<String, Indexer>();
private List<Pattern> exclusionList = new ArrayList<Pattern>();
private long batchSize = 50;
public int getIndexerPoolSize() {
return indexerPoolSize;
}
private int indexerPoolSize = 50;
private boolean skipIndexingCache = false;
public boolean isSkipIndexingCache() {
return skipIndexingCache;
}
public void setSkipIndexingCache(boolean skipIndexingCache) {
this.skipIndexingCache = skipIndexingCache;
}
public long getBatchSize() {
return batchSize;
}
// solr server url for initiate the solr server
private String solrServerUrl;
public String getSolrServerUrl(){
return solrServerUrl;
}
private RegistryConfigLoader() {
startIndexing = IndexingConstants.START_INDEXING_DEFAULT_VALUE;
startingDelayInSecs = IndexingConstants.STARTING_DELAY_IN_SECS_DEFAULT_VALUE;
indexingFreqInSecs = IndexingConstants.INDEXING_FREQ_IN_SECS_DEFAULT_VALUE;
lastAccessTimeLocation = IndexingConstants.LAST_ACCESS_TIME_LOCATION;
try {
FileInputStream fileInputStream = new FileInputStream(getConfigFile());
StAXOMBuilder builder = new StAXOMBuilder(
CarbonUtils.replaceSystemVariablesInXml(fileInputStream));
OMElement configElement = builder.getDocumentElement();
OMElement indexingConfig = configElement.getFirstChildWithName(
new QName("indexingConfiguration"));
if (indexingConfig != null) { //registry.xml need an <indexingConfiguration> </indexingConfiguration> entry to continue
loadIndexingConfiguration(indexingConfig);
}
} catch (FileNotFoundException e) {
// This virtually cannot happen as registry.xml is necessary to start up the registry
log.error("registry.xml has not been found", e);
} catch (RegistryException e) {
log.error(e.getMessage(),e);
} catch (XMLStreamException e) {
String msg = "error building registry.xml, check for badly formed xml";
log.error(msg, e);
} catch (CarbonException e) {
log.error("An error occurred during system variable replacement", e);
}
}
public static RegistryConfigLoader getInstance(){
return registryConfigLoaderInstance;
}
public long getIndexingFreqInSecs() {
return indexingFreqInSecs;
}
public String getLastAccessTimeLocation() {
return lastAccessTimeLocation;
}
public Map<String, Indexer> getIndexerMap() {
return indexerMap;
}
public Pattern[] getExclusionPatterns() {
return exclusionList.toArray(new Pattern[exclusionList.size()]);
}
public boolean IsStartIndexing() {
return startIndexing;
}
public long getStartingDelayInSecs() {
return startingDelayInSecs;
}
// Get registry.xml instance.
private static File getConfigFile() throws RegistryException {
String configPath = CarbonUtils.getRegistryXMLPath();
if (configPath != null) {
File registryXML = new File(configPath);
if (!registryXML.exists()) {
String msg = "Registry configuration file (registry.xml) file does " +
"not exist in the path " + configPath;
log.error(msg);
throw new RegistryException(msg);
}
return registryXML;
} else {
String msg = "Cannot find registry.xml";
log.error(msg);
throw new RegistryException(msg);
}
}
private void loadIndexingConfiguration(OMElement indexingConfig){
OMElement startIndexingConfig = indexingConfig.getFirstChildWithName(new QName("startIndexing"));
if (startIndexingConfig != null) {
try {
startIndexing = Boolean.parseBoolean(startIndexingConfig.getText());
} catch (OMException e) {
// we can use default value and continue if no OMElement found in indexingConfig
log.error("Error occurred when retrieving startIndexing, hence using the default value '" +
startIndexing + "'", e);
}
}
try {
startingDelayInSecs = Long.parseLong(indexingConfig.getFirstChildWithName(
new QName("startingDelayInSeconds")).getText());
} catch (OMException e) {
// we can use default value and continue if no OMElement found in indexingConfig
log.error("Error occurred when retriving startingDelayInSeconds, hence using the default value", e);
}
try {
indexingFreqInSecs = Long.parseLong(indexingConfig.getFirstChildWithName(
new QName("indexingFrequencyInSeconds")).getText());
} catch (OMException e) {
// we can use default value and continue if no OMElement found in indexingConfig
log.error("Error occurred when retriving indexingFrequencyInSeconds, hence using the default value", e);
}
try {
lastAccessTimeLocation = indexingConfig.getFirstChildWithName(
new QName("lastAccessTimeLocation")).getText();
} catch (OMException e) {
// we can use default value and continue if no OMElement found in indexingConfig
log.error("Error occurred when retriving lastAccessTimeLocation, hence using the default value", e);
}
try {
// Reads whether to skip cache for indexing purposes.
OMElement skipIndexingCacheEle = indexingConfig.getFirstChildWithName(
new QName(SKIP_CACHE));
if (skipIndexingCacheEle != null) {
this.setSkipIndexingCache(TRUE.equals(skipIndexingCacheEle.getText()));
}
} catch (OMException e) {
// we can use default value and continue if no OMElement found in indexingConfig
log.error("Error occurred when retrieving skipCache info, hence using the default value", e);
}
// solr server url for initiate the solr server
if(indexingConfig.getFirstChildWithName(new QName("solrServerUrl")) != null){
solrServerUrl = indexingConfig.getFirstChildWithName(new QName("solrServerUrl")).getText();
}
batchSize = Long.parseLong(indexingConfig.getFirstChildWithName(new QName("batchSize")).getText());
indexerPoolSize = Integer.parseInt(indexingConfig.getFirstChildWithName(new QName("indexerPoolSize")).getText());
Iterator exclusions = indexingConfig.getFirstChildWithName(new QName("exclusions")).
getChildrenWithName(new QName("exclusion"));
while (exclusions.hasNext()) {
OMElement indexerEl = (OMElement) exclusions.next();
String pathRegEx =
indexerEl.getAttribute(new QName("pathRegEx")).getAttributeValue();
if (pathRegEx != null) {
try {
exclusionList.add(Pattern.compile(pathRegEx));
} catch (PatternSyntaxException ignore) {
log.error("Error occured when compiling the RegEx pattern: " + pathRegEx, ignore);
}
}
}
Iterator indexers = indexingConfig.getFirstChildWithName(new QName("indexers")).
getChildrenWithName(new QName("indexer"));
String currentProfile = System.getProperty("profile", "default");
while (indexers.hasNext()) {
OMElement indexerEl = (OMElement) indexers.next();
boolean isValidConfigurationForProfile = false;
String profileStr = indexerEl.getAttributeValue(new QName("profiles"));
if (profileStr != null) {
String[] profiles = profileStr.split(",");
for (String profile : profiles) {
if (profile.trim().equals(currentProfile)) {
isValidConfigurationForProfile = true;
}
}
} else {
//when no profile is defined
isValidConfigurationForProfile = true;
}
if(isValidConfigurationForProfile){
String clazz = indexerEl.getAttribute(new QName("class")).getAttributeValue();
try {
Object indexerObj = this.getClass().getClassLoader().loadClass(clazz).newInstance();
if (!(indexerObj instanceof Indexer)) {
log.error(clazz + " has not implemented Indexer interface");
}
String mediaPattern = indexerEl.getAttribute(
new QName("mediaTypeRegEx")).getAttributeValue();
indexerMap.put(mediaPattern, (Indexer) indexerObj);
} catch (InstantiationException e) {
log.error(clazz + " cannot be instantiated.", e);
} catch (IllegalAccessException e) {
log.error(clazz + " constructor cannot be accessed", e);
} catch (ClassNotFoundException e) {
log.error(clazz + " is not found in classpath. Please check whether the class " +
"is exported in your OSGI bundle.", e);
}
}
}
}
}