Merge branch 'feature/SEARCH-56_externalize_solr_host_properties' into 'master'

Feature/search 56 externalize solr host properties

solr.host, solr.port, solr.baseUrl are the properties a client (eg. Alfresco) can use to talk to Solr. These are the external values, not local values e.g. they could point to a proxy.
We should allow these to be passed in via configuration.

See merge request !1
This commit is contained in:
Joel Bernstein
2016-06-13 14:34:21 +01:00
25 changed files with 2308 additions and 314 deletions
@@ -1851,7 +1851,7 @@ public class AlfrescoSolrDataModel implements QueryConstants
parser.setSearchParameters(searchParameters);
parser.setAllowLeadingWildcard(true);
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getCoreProperties();
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getProperties();
int topTermSpanRewriteLimit = Integer.parseInt(props.getProperty("alfresco.topTermSpanRewriteLimit", "1000"));
parser.setTopTermSpanRewriteLimit(topTermSpanRewriteLimit);
@@ -128,6 +128,7 @@ import org.alfresco.solr.client.SOLRAPIClient;
import org.alfresco.solr.client.SOLRAPIClient.GetTextContentResponse;
import org.alfresco.solr.client.StringPropertyValue;
import org.alfresco.solr.client.Transaction;
import org.alfresco.solr.config.ConfigUtil;
import org.alfresco.solr.content.SolrContentStore;
import org.alfresco.solr.content.SolrContentUrlBuilder;
import org.alfresco.solr.tracker.IndexHealthReport;
@@ -202,17 +203,20 @@ public class SolrInformationServer implements InformationServer
public static final String DOC_TYPE_TX = "Tx";
public static final String DOC_TYPE_ACL_TX = "AclTx";
public static final String DOC_TYPE_STATE = "State";
public static final String SOLR_PROXY_HOST = "proxy.host";
public static final String SOLR_PROXY_PORT = "proxy.port";
public static final String SOLR_PROXY_BASEURL = "proxy.baseurl";
private static final Pattern CAPTURE_SITE = Pattern.compile("^/\\{http\\://www\\.alfresco\\.org/model/application/1\\.0\\}company\\_home/\\{http\\://www\\.alfresco\\.org/model/site/1\\.0\\}sites/\\{http\\://www\\.alfresco\\.org/model/content/1\\.0}([^/]*)/.*" );
private static final Pattern CAPTURE_TAG = Pattern.compile("^/\\{http\\://www\\.alfresco\\.org/model/content/1\\.0\\}taggable/\\{http\\://www\\.alfresco\\.org/model/content/1\\.0\\}([^/]*)/\\{\\}member");
private static final Pattern CAPTURE_SHARED_FILES = Pattern.compile("^/\\{http\\://www\\.alfresco\\.org/model/application/1\\.0\\}company\\_home/\\{http\\://www\\.alfresco\\.org/model/application/1\\.0\\}shared/.*" );
private static final Pattern CAPTURE_SHARED_FILES = Pattern.compile("^/\\{http\\://www\\.alfresco\\.org/model/application/1\\.0\\}company\\_home/\\{http\\://www\\.alfresco\\.org/model/application/1\\.0\\}shared/.*" );
/* 4096 is 2 to the power of (6*2), and we do this because the precision step for the long is 6,
* and the transactions are long
*/
public static final int BATCH_FACET_TXS = 4096;
public static final int BATCH_FACET_TXS = 4096;
private AlfrescoCoreAdminHandler adminHandler;
private SolrCore core;
private SolrRequestHandler nativeRequestHandler;
@@ -298,7 +302,7 @@ public class SolrInformationServer implements InformationServer
this.solrContentStore = solrContentStore;
Properties p = core.getResourceLoader().getCoreProperties();
alfrescoVersion = p.getProperty("alfresco.version", "5.0.0");
alfrescoVersion = p.getProperty("alfresco.version", "Unknown");
transformContent = Boolean.parseBoolean(p.getProperty("alfresco.index.transformContent", "true"));
recordUnindexedNodes = Boolean.parseBoolean(p.getProperty("alfresco.recordUnindexedNodes", "true"));
lag = Integer.parseInt(p.getProperty("alfresco.lag", "1000"));
@@ -309,21 +313,17 @@ public class SolrInformationServer implements InformationServer
contentStreamLimit = Integer.parseInt(p.getProperty("alfresco.contentStreamLimit", "10000000"));
// build base URL - host and port have to come from configuration.
Properties props = AlfrescoSolrDataModel.getCommonConfig();
port = Integer.parseInt(props.getProperty("solr.port", getHttpPort("8080")));
String defaultHost;
try
{
defaultHost = InetAddress.getLocalHost().getHostName();
hostName = ConfigUtil.locateProperty(SOLR_PROXY_HOST, props.getProperty(SOLR_PROXY_HOST));
String portNumber = ConfigUtil.locateProperty(SOLR_PROXY_PORT, props.getProperty(SOLR_PROXY_PORT));
try {
port = Integer.parseInt(portNumber);
} catch (NumberFormatException e) {
log.error("Failed to find a valid solr.port number, the default value is in shared.properties");
throw e;
}
catch (UnknownHostException e)
{
defaultHost = "localhost";
}
hostName = props.getProperty("solr.host", defaultHost);
baseUrl = props.getProperty("solr.baseUrl", "/solr4");
baseUrl = ConfigUtil.locateProperty(SOLR_PROXY_BASEURL, props.getProperty(SOLR_PROXY_BASEURL));
baseUrl = (baseUrl.startsWith("/") ? "" : "/") + baseUrl + "/" + core.getName() + "/";
}
@@ -3858,39 +3858,6 @@ public class SolrInformationServer implements InformationServer
return hostName;
}
private String getHttpPort(String defaultPort)
{
try
{
MBeanServer mBeanServer = MBeanServerFactory.findMBeanServer(null).get(0);
QueryExp query = Query.and(Query.eq(Query.attr("scheme"), Query.value("http")), Query.eq(Query.attr("protocol"), Query.value("HTTP/1.1")));
Set<ObjectName> objectNames = mBeanServer.queryNames(null, query);
if (objectNames != null && objectNames.size() > 0) {
for (ObjectName objectName : objectNames) {
String name = objectName.toString();
if (name.indexOf("port=") > -1) {
String[] parts = name.split("port=");
String port = parts[1];
try {
Integer.parseInt(port);
return port;
} catch (NumberFormatException e) {
log.error("Error parsing http port:" + port);
return defaultPort;
}
}
}
}
}
catch(Throwable t)
{
log.error("Error getting https port:", t);
}
return defaultPort;
}
public void setCleanContentTxnFloor(long cleanContentTxnFloor)
{
this.cleanContentTxnFloor = cleanContentTxnFloor;
@@ -60,7 +60,7 @@ public class EnsureModelsComponent extends SearchComponent
public void prepare(ResponseBuilder rb) throws IOException
{
SolrQueryRequest req = rb.req;
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getCoreProperties();
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getProperties();
boolean isTrackingEnabled = Boolean.parseBoolean(props.getProperty("enable.alfresco.tracking", "false"));
@@ -90,7 +90,7 @@ public class EnsureModelsComponent extends SearchComponent
SolrResourceLoader loader = core.getLatestSchema().getResourceLoader();
SolrKeyResourceLoader keyResourceLoader = new SolrKeyResourceLoader(loader);
SOLRAPIClientFactory clientFactory = new SOLRAPIClientFactory();
Properties props = new CoreDescriptorDecorator(core.getCoreDescriptor()).getCoreProperties();
Properties props = new CoreDescriptorDecorator(core.getCoreDescriptor()).getProperties();
SOLRAPIClient repositoryClient = clientFactory.getSOLRAPIClient(props, keyResourceLoader,
AlfrescoSolrDataModel.getInstance().getDictionaryService(CMISStrictDictionaryService.DEFAULT),
AlfrescoSolrDataModel.getInstance().getNamespaceDAO());
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.solr.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.naming.NoInitialContextException;
/**
* Helps with configuring and setup of Alfresco and Solr.
*
* @author Gethin James
*/
public class ConfigUtil {
protected final static Logger log = LoggerFactory.getLogger(ConfigUtil.class);
private static final String JNDI_PREFIX = "java:comp/env/";
private static final String ENV_PREFIX = "SOLR_";
/**
* Finds the property based on looking up the value in one of three places (in order of preference):
* <ol>
* <li>JNDI: via java:comp/env/{propertyName/converted/to/slash}</li>
* <li>A Java system property or a Java system property prefixed with solr.</li>
* <li>OS environment variable</li>
* </ol>
*
* @return A property
*/
public static String locateProperty(String propertyName, String defaultValue)
{
String propertyValue = null;
String propertyKey = propertyName.toLowerCase();
String jndiKey = convertPropertyNameToJNDIPath(propertyKey);
String envVar = convertPropertyNameToEnvironmentParam(propertyKey);
// Try JNDI
try {
Context c = new InitialContext();
propertyValue = (String) c.lookup(jndiKey);
log.info("Using JNDI key: "+jndiKey+": "+propertyValue );
return propertyValue;
} catch (NoInitialContextException e) {
log.info("JNDI not configured (NoInitialContextEx)");
} catch (NamingException e) {
log.info("No "+jndiKey+" in JNDI");
} catch( RuntimeException ex ) {
log.warn("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
}
// Now try system property
propertyValue = System.getProperty(propertyKey);
if( propertyValue != null ) {
log.info("Using system property "+propertyKey+": " + propertyValue );
return propertyValue;
}
//try system property again with a solr. prefix
propertyValue = System.getProperty("solr."+propertyKey);
if( propertyValue != null ) {
log.info("Using system property "+"solr."+propertyKey+": " + propertyValue );
return propertyValue;
}
// Now try an environment variable
propertyValue = System.getenv(envVar);
if( propertyValue != null ) {
log.info("Using environment variable "+envVar+": " + propertyValue );
return propertyValue;
}
//if all else fails then return the default
log.info("Using default value for variable "+propertyName+": " + defaultValue );
return defaultValue;
}
/**
* Takes a property name and splits it via / instead of .
* @param propertyName
* @return the property name as a jndi path
*/
protected static String convertPropertyNameToJNDIPath(String propertyName)
{
if (propertyName == null) propertyName = "";
return JNDI_PREFIX+propertyName.replace('.','/');
}
protected static String convertPropertyNameToEnvironmentParam(String propertyName)
{
if (propertyName == null) propertyName = "";
return ENV_PREFIX+propertyName.replace('.','_').toUpperCase();
}
}
@@ -36,6 +36,7 @@ import org.alfresco.repo.content.ContentStore;
import org.alfresco.service.cmr.repository.ContentIOException;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.solr.config.ConfigUtil;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.util.BytesRef;
import org.apache.solr.common.SolrInputDocument;
@@ -62,7 +63,7 @@ public class SolrContentStore implements ContentStore
{
protected final static Logger log = LoggerFactory.getLogger(SolrContentStore.class);
static SolrContentStore solrContentStore;
private static SolrContentStore solrContentStore;
static
{
@@ -82,52 +83,17 @@ public class SolrContentStore implements ContentStore
private static SolrContentStore getSolrContentStore(String solrHome)
throws JobExecutionException
{
// TODO: Could specify the rootStr from a properties file.
return new SolrContentStore(locateContentHome(solrHome));
String normalSolrHome = SolrResourceLoader.normalizeDir(solrHome);
return new SolrContentStore(ConfigUtil.locateProperty("solr.content.dir", normalSolrHome+"ContentStore"));
}
public static String locateContentHome(String solrHome) {
String contentDir = null;
// Try JNDI
try {
Context c = new InitialContext();
contentDir = (String) c.lookup("java:comp/env/solr/content/dir");
log.info("Using JNDI solr.content.dir: " + contentDir);
} catch (NoInitialContextException e) {
log.info("JNDI not configured for solr (NoInitialContextEx)");
} catch (NamingException e) {
log.info("No solr/content/dir in JNDI");
} catch (RuntimeException ex) {
log.warn("Odd RuntimeException while testing for JNDI: "
+ ex.getMessage());
}
// Now try system property
if (contentDir == null) {
String prop = "solr.solr.content.dir";
contentDir = System.getProperty(prop);
if (contentDir != null) {
log.info("using system property " + prop + ": " + contentDir);
}
}
// if all else fails, try
if (contentDir == null) {
return solrHome + "ContentStore";
} else {
return contentDir;
}
}
public static SolrContentStore getSolrContentStore()
{
return solrContentStore;
}
// write a BytesRef as a byte array
private static JavaBinCodec.ObjectResolver resolver = new JavaBinCodec.ObjectResolver()
{
@@ -219,7 +185,7 @@ public class SolrContentStore implements ContentStore
private final String root;
public SolrContentStore(String rootStr)
private SolrContentStore(String rootStr)
{
File rootFile = new File(rootStr);
try
@@ -72,7 +72,7 @@ public class Lucene4QueryBuilderContextSolrImpl implements LuceneQueryBuilderCon
// lqp.setAllowLeadingWildcard(true);
// this.namespacePrefixResolver = namespacePrefixResolver;
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getCoreProperties();
Properties props = new CoreDescriptorDecorator(req.getCore().getCoreDescriptor()).getProperties();
int topTermSpanRewriteLimit = Integer.parseInt(props.getProperty("alfresco.topTermSpanRewriteLimit", "1000"));
lqp.setTopTermSpanRewriteLimit(topTermSpanRewriteLimit);
@@ -97,7 +97,7 @@ public class CoreWatcherJob implements Job
private void registerForCore(AlfrescoCoreAdminHandler adminHandler, CoreContainer coreContainer, SolrCore core,
String coreName, TrackerRegistry trackerRegistry) throws JobExecutionException
{
Properties props = new CoreDescriptorDecorator(core.getCoreDescriptor()).getCoreProperties();
Properties props = new CoreDescriptorDecorator(core.getCoreDescriptor()).getProperties();
boolean testcase = Boolean.parseBoolean(System.getProperty("alfresco.test", "false"));
if (Boolean.parseBoolean(props.getProperty("enable.alfresco.tracking", "false")))
{
@@ -110,9 +110,8 @@ public class CoreWatcherJob implements Job
SOLRAPIClient repositoryClient = clientFactory.getSOLRAPIClient(props, keyResourceLoader,
AlfrescoSolrDataModel.getInstance().getDictionaryService(CMISStrictDictionaryService.DEFAULT),
AlfrescoSolrDataModel.getInstance().getNamespaceDAO());
SolrContentStore solrContentStore = this.getSolrContentStore(coreContainer);
SolrInformationServer srv = new SolrInformationServer(adminHandler, core, repositoryClient,
solrContentStore);
SolrContentStore.getSolrContentStore());
adminHandler.getInformationServers().put(coreName, srv);
log.info("Starting to track " + coreName);
@@ -176,56 +175,4 @@ public class CoreWatcherJob implements Job
scheduler.schedule(commitTracker, coreName, props);
}
}
private SolrContentStore getSolrContentStore(CoreContainer coreContainer) throws JobExecutionException
{
// TODO: Could specify the rootStr from a properties file.
return new SolrContentStore(locateContentHome(coreContainer.getSolrHome()));
}
public static String locateContentHome(String solrHome)
{
String contentDir = null;
// Try JNDI
try
{
Context c = new InitialContext();
contentDir = (String) c.lookup("java:comp/env/solr/content/dir");
log.info("Using JNDI solr.content.dir: " + contentDir);
}
catch (NoInitialContextException e)
{
log.info("JNDI not configured for solr (NoInitialContextEx)");
}
catch (NamingException e)
{
log.info("No solr/content/dir in JNDI");
}
catch (RuntimeException ex)
{
log.warn("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
}
// Now try system property
if (contentDir == null)
{
String prop = "solr.solr.content.dir";
contentDir = System.getProperty(prop);
if (contentDir != null)
{
log.info("using system property " + prop + ": " + contentDir);
}
}
// if all else fails, try
if (contentDir == null)
{
return solrHome + "ContentStore";
}
else
{
return contentDir;
}
}
}
@@ -49,6 +49,8 @@ import org.alfresco.solr.InformationServer;
import org.alfresco.solr.client.AlfrescoModel;
import org.alfresco.solr.client.AlfrescoModelDiff;
import org.alfresco.solr.client.SOLRAPIClient;
import org.alfresco.solr.config.ConfigUtil;
import org.apache.solr.core.SolrResourceLoader;
import org.json.JSONException;
/**
@@ -107,7 +109,8 @@ public class ModelTracker extends AbstractTracker implements Tracker
InformationServer informationServer)
{
super(p, client, coreName, informationServer);
alfrescoModelDir = locateModelHome(solrHome);
String normalSolrHome = SolrResourceLoader.normalizeDir(solrHome);
alfrescoModelDir = new File(ConfigUtil.locateProperty("solr.model.dir", normalSolrHome+"alfrescoModels"));
log.info("Alfresco Model dir " + alfrescoModelDir);
if (!alfrescoModelDir.exists())
{
@@ -565,53 +568,6 @@ public class ModelTracker extends AbstractTracker implements Tracker
{
return model.getName().replace(":", ".") + "." + model.getChecksum(XMLBindingType.DEFAULT) + ".xml";
}
public static File locateModelHome(String solrHome)
{
String modelDir = null;
// Try JNDI
try
{
Context c = new InitialContext();
modelDir = (String) c.lookup("java:comp/env/solr/model/dir");
log.info("Using JNDI solr.model.dir: " + modelDir);
}
catch (NoInitialContextException e)
{
log.info("JNDI not configured for solr (NoInitialContextEx)");
}
catch (NamingException e)
{
log.info("No solr/model/dir in JNDI");
}
catch (RuntimeException ex)
{
log.warn("Odd RuntimeException while testing for JNDI: " + ex.getMessage());
}
// Now try system property
if (modelDir == null)
{
String prop = "solr.solr.model.dir";
modelDir = System.getProperty(prop);
if (modelDir != null)
{
log.info("using system property " + prop + ": " + modelDir);
}
}
// if all else fails, try
if (modelDir == null)
{
File answer = new File(solrHome, "alfrescoModels");
log.info("solr home defaulted to " + answer + "(could not find system property or JNDI)");
return answer;
}
else
{
return new File(modelDir);
}
}
public boolean hasModels()
{
@@ -18,22 +18,39 @@
*/
package org.apache.solr.core;
import com.google.common.collect.ImmutableList;
import org.alfresco.solr.config.ConfigUtil;
import java.util.Properties;
/**
* This class was created solely for the purpose of exposing the coreProperties of the CoreDescriptor
* This class was created solely for the purpose of exposing the coreProperties of the CoreDescriptor.
* It is now possible to substitute a sub-set of properties using the rules specified here @see ConfigUtil#locateProperty()
*
* The Substitutable Properties are defined in the substitutableProperties list.
* @author Ahmed Owian
* @author Gethin James
*/
public class CoreDescriptorDecorator {
private CoreDescriptor descriptor;
private final Properties properties = new Properties();
public static ImmutableList<String> substitutableProperties = ImmutableList.of(
"alfresco.host",
"alfresco.port",
"alfresco.baseUrl",
"alfresco.port.ssl"
);
public CoreDescriptorDecorator(CoreDescriptor descriptor)
{
this.descriptor = descriptor;
properties.putAll(descriptor.coreProperties);
substitutableProperties.forEach(prop ->
properties.put(prop, ConfigUtil.locateProperty(prop,properties.getProperty(prop)))
);
}
public Properties getCoreProperties()
public Properties getProperties()
{
return this.descriptor.coreProperties;
return this.properties;
}
}
@@ -1,5 +1,9 @@
# Shared Properties file
#Host details an external client would use to connect to Solr
proxy.host=localhost
proxy.port=8983
proxy.baseurl=/solr
# Properties treated as identifiers when indexed
@@ -1,10 +1,7 @@
#
# solrcore.properties - used in solrconfig.xml
#
# data is in ${data.dir.root}/${data.dir.store}
data.dir.root=@@ALFRESCO_SOLR4_DATA_DIR@@
data.dir.store=workspace/SpacesStore
enable.alfresco.tracking=true
#
@@ -12,6 +9,12 @@ enable.alfresco.tracking=true
#
alfresco.version=5.1
#
#These are replaced by the admin handler
#
#data.dir.root=DATA_DIR
#data.dir.store=workspace/SpacesStore
#alfresco.stores=workspace://SpacesStore
#
# Properties loaded during alfresco tracking
@@ -22,7 +25,7 @@ alfresco.port=8080
alfresco.port.ssl=8443
alfresco.baseUrl=/alfresco
alfresco.cron=0/15 * * * * ? *
alfresco.stores=workspace://SpacesStore
#alfresco.index.transformContent=false
#alfresco.ignore.datatype.1=d:content
alfresco.lag=1000
@@ -186,7 +186,7 @@ public class AlfrescoSolrTestCaseJ4 extends SolrTestCaseJ4 implements SolrTestFi
ignoreException("ignore_exception");
System.setProperty("solr.directoryFactory","solr.RAMDirectoryFactory");
System.setProperty("solr.solr.home", getFile(TEST_FILES_LOCATION).toString());
System.setProperty("solr.solr.home", testSolrHome.toAbsolutePath().toString());
System.setProperty("solr.tests.maxBufferedDocs", "1000");
System.setProperty("solr.tests.maxIndexingThreads", "10");
@@ -24,7 +24,7 @@ package org.alfresco.solr;
*/
public interface SolrTestFiles
{
public final String TEST_FILES_LOCATION = "src/test/resources/test-files";
public final String TEST_FILES_LOCATION = "target/test-classes/test-files";
public final String TEST_SOLR_COLLECTION = TEST_FILES_LOCATION + "/collection1";
public final String TEST_SOLR_CONF = TEST_SOLR_COLLECTION + "/conf/";
@@ -0,0 +1,65 @@
/*
* Copyright (C) 2005-2016 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.solr.config;
import org.junit.Test;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
/**
* Tests configuring and setup of Alfresco and Solr properties
*
* @author Gethin James
*/
public class ConfigUtilTest {
@Test
public void locateProperty() throws Exception {
assertEquals("king", ConfigUtil.locateProperty("find.me", "king"));
System.setProperty("solr.find.me", "iamfound");
assertEquals("iamfound", ConfigUtil.locateProperty("find.me", "king"));
System.clearProperty("solr.find.me");
assertEquals("king", ConfigUtil.locateProperty("find.me", "king"));
System.setProperty("find.me", "iamfoundagain");
assertEquals("iamfoundagain", ConfigUtil.locateProperty("find.me", "king"));
System.clearProperty("find.me");
}
@Test
public void convertPropertyNameToJNDIPath() throws Exception {
assertEquals("java:comp/env/gethin",ConfigUtil.convertPropertyNameToJNDIPath("gethin"));
assertEquals("java:comp/env/solr/content/dir",ConfigUtil.convertPropertyNameToJNDIPath("solr.content.dir"));
assertEquals("java:comp/env/solr/model/dir",ConfigUtil.convertPropertyNameToJNDIPath("solr.model.dir"));
assertEquals("java:comp/env/",ConfigUtil.convertPropertyNameToJNDIPath(""));
assertEquals("java:comp/env/",ConfigUtil.convertPropertyNameToJNDIPath(null));
}
@Test
public void convertPropertyNameToEnvironmentParam() throws Exception {
assertEquals("SOLR_GETHIN",ConfigUtil.convertPropertyNameToEnvironmentParam("gethin"));
assertEquals("SOLR_SOLR_CONTENT_DIR",ConfigUtil.convertPropertyNameToEnvironmentParam("solr.content.dir"));
assertEquals("SOLR_SOLR_MODEL_DIR",ConfigUtil.convertPropertyNameToEnvironmentParam("solr.model.dir"));
assertEquals("SOLR_SOLR_HOST",ConfigUtil.convertPropertyNameToEnvironmentParam("solr.host"));
}
}
@@ -18,23 +18,21 @@
*/
package org.alfresco.solr.content;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
import org.alfresco.repo.content.ContentContext;
import org.alfresco.service.cmr.repository.ContentReader;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
/**
* Tests {@link SolrContentStoreTest}
*
@@ -44,26 +42,11 @@ import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SolrContentStoreTest
{
private String rootStr;
@Before
public void setUp() throws IOException
{
System.setProperty("solr.solr.content.dir","target");
File tempFile = File.createTempFile("SolrContentStoreTest-", ".bin");
File tempFolder = tempFile.getParentFile();
rootStr = tempFolder.getAbsolutePath() + "/" + System.currentTimeMillis();
rootStr = new File(rootStr).getAbsolutePath(); // Ensure we handle separator char for this test
}
@After
public void tearDown() throws IOException
{
if (rootStr != null)
{
File rootDir = new File(rootStr);
FileUtils.deleteDirectory(rootDir);
}
File rootDir = new File(SolrContentStore.getSolrContentStore().getRootLocation());
FileUtils.deleteDirectory(rootDir);
}
/**
@@ -78,43 +61,24 @@ public class SolrContentStoreTest
@Test
public void rootLocation()
{
SolrContentStore store = new SolrContentStore(rootStr);
File rootDir = new File(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
File rootDir = new File(store.getRootLocation());
Assert.assertTrue(rootDir.exists());
Assert.assertTrue(rootDir.isDirectory());
Assert.assertEquals(rootStr, store.getRootLocation());
}
@Test
public void failedRootLocation() throws IOException
{
File rootFile = new File(rootStr);
rootFile.createNewFile();
try
{
new SolrContentStore(rootStr);
Assert.fail("Failed to handle file in root location.");
}
catch (RuntimeException e)
{
// Expected
}
rootFile.delete();
}
@Test
public void reconstruct()
{
new SolrContentStore(rootStr);
new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
store = SolrContentStore.getSolrContentStore();
}
@Test
public void getWriter()
{
SolrContentStore store = new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
ContentContext ctx = createContentContext("abc");
ContentWriter writer = store.getWriter(ctx);
String url = writer.getContentUrl();
@@ -126,12 +90,12 @@ public class SolrContentStoreTest
@Test
public void contentByString()
{
SolrContentStore store = new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
ContentContext ctx = createContentContext("abc");
ContentWriter writer = store.getWriter(ctx);
File file = new File(rootStr + "/" + writer.getContentUrl().replace("solr://", ""));
File file = new File(store.getRootLocation() + "/" + writer.getContentUrl().replace("solr://", ""));
Assert.assertFalse("File was created before anything was written", file.exists());
String content = "Quick brown fox jumps over the lazy dog.";
@@ -158,8 +122,8 @@ public class SolrContentStoreTest
@Test
public void contentByStream() throws Exception
{
SolrContentStore store = new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
ContentContext ctx = createContentContext("abc");
ContentWriter writer = store.getWriter(ctx);
@@ -180,8 +144,8 @@ public class SolrContentStoreTest
@Test
public void delete() throws Exception
{
SolrContentStore store = new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
ContentContext ctx = createContentContext("abc");
String url = ctx.getContentUrl();
ContentWriter writer = store.getWriter(ctx);
@@ -201,42 +165,15 @@ public class SolrContentStoreTest
// Delete when already gone; should just not fail
store.delete(url);
}
//
// See ACE-2896. There is actually no way of ensuring that the cached document is latest or perfect.
// /**
// * This store allows the same URL to be used but does redirection to the latest version under the covers
// */
// @Test
// public void rewrite() throws Exception
// {
// SolrContentStore store = new SolrContentStore(rootStr);
//
// ContentContext ctx = createContentContext("abc");
// ContentWriter writer1 = store.getWriter(ctx);
// ContentWriter writer2 = store.getWriter(ctx);
// assertNotEquals(
// "Different writers should use different URLs: writer1=" + writer1 + ", writer2=" + writer2,
// writer1.getContentUrl(), writer2.getContentUrl());
// assertTrue(
// "Second URL must be 'greater' than first: writer1=" + writer1 + ", writer2=" + writer2,
// writer1.getContentUrl().compareTo(writer2.getContentUrl()) < 0);
//
// writer1.putContent("Text1");
// writer2.putContent("Text2");
//
// // Now get the reader
// ContentReader reader = store.getReader(ctx.getContentUrl());
// assertEquals("Text2", reader.getContentString());
// }
/**
* A demonstration of how the store might be used.
*/
@Test
public void exampleUsage()
{
SolrContentStore store = new SolrContentStore(rootStr);
SolrContentStore store = SolrContentStore.getSolrContentStore();
String tenant = "alfresco.com";
long dbId = 12345;
String otherData = "sdfklsfdl";
@@ -69,16 +69,19 @@ public class ModelTrackerTest
@Mock
private TrackerStats trackerStats;
private static File alfrescoModelDir;
@BeforeClass
public static void setUpBeforeClass() throws Exception
{
alfrescoModelDir = new File("target/testalfrescoModels");
alfrescoModelDir.mkdir();
}
@AfterClass
public static void tearDownAfterClass() throws Exception
{
try {
File alfrescoModelDir = new File("alfrescoModels");
File[] listFiles = alfrescoModelDir.listFiles();
for (File file : listFiles)
{
@@ -103,8 +106,8 @@ public class ModelTrackerTest
when(props.getProperty("acl.shard.count", "1")).thenReturn("1");
when(props.getProperty("acl.shard.instance", "0")).thenReturn("0");
when(this.srv.getTrackerStats()).thenReturn(trackerStats);
System.setProperty("solr.model.dir", alfrescoModelDir.getAbsolutePath());
// TODO: create test folder for model sync?
this.modelTracker = new ModelTracker(null, props, repositoryClient, coreName, srv);
}
@@ -137,7 +140,6 @@ public class ModelTrackerTest
{
verify(this.srv).afterInitModels();
File alfrescoModelDir = new File("alfrescoModels");
assertTrue(alfrescoModelDir.isDirectory());
File[] modelRepresentations = alfrescoModelDir.listFiles(new FileFilter()
@@ -1,10 +1,7 @@
#
# solrcore.properties - used in solrconfig.xml
#
# data is in ${data.dir.root}/${data.dir.store}
data.dir.root=@@ALFRESCO_SOLR4_DATA_DIR@@
data.dir.store=archive/SpacesStore
enable.alfresco.tracking=true
#
@@ -12,6 +9,12 @@ enable.alfresco.tracking=true
#
alfresco.version=5.1
#
#These are replaced by the admin handler
#
#data.dir.root=DATA_DIR
#data.dir.store=workspace/SpacesStore
#alfresco.stores=workspace://SpacesStore
#
# Properties loaded during alfresco tracking
@@ -22,7 +25,7 @@ alfresco.port=8080
alfresco.port.ssl=8443
alfresco.baseUrl=/alfresco
alfresco.cron=0/15 * * * * ? *
alfresco.stores=archive://SpacesStore
#alfresco.index.transformContent=false
#alfresco.ignore.datatype.1=d:content
alfresco.lag=1000
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,17 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<bean id="cmisTypeExclusions" class="org.alfresco.opencmis.dictionary.QNameFilterImpl" init-method="initFilter">
<property name="excludedTypes">
<list>
<value>{http://www.jcp.org/jcr/1.0}*</value>
<value>{http://www.jcp.org/jcr/nt/1.0}*</value>
<value>{http://www.jcp.org/jcr/mix/1.0}*</value>
<value>{http://www.jcp.org/jcr/sv/1.0}*</value>
<value>{http://www.alfresco.org/model/wcmappmodel/1.0}*</value>
<value>{http://www.alfresco.org/model/wcmmodel/1.0}*</value>
</list>
</property>
</bean>
</beans>
@@ -0,0 +1,36 @@
# Shared Properties file
#Host details an external client would use to connect to Solr
proxy.host=localhost
proxy.port=8983
proxy.baseurl=/solr
# Properties treated as identifiers when indexed
alfresco.identifier.property.0={http://www.alfresco.org/model/content/1.0}creator
alfresco.identifier.property.1={http://www.alfresco.org/model/content/1.0}modifier
alfresco.identifier.property.2={http://www.alfresco.org/model/content/1.0}userName
alfresco.identifier.property.3={http://www.alfresco.org/model/content/1.0}authorityName
# Suggestable Propeties
alfresco.suggestable.property.0={http://www.alfresco.org/model/content/1.0}name
alfresco.suggestable.property.1={http://www.alfresco.org/model/content/1.0}title
alfresco.suggestable.property.2={http://www.alfresco.org/model/content/1.0}description
alfresco.suggestable.property.3={http://www.alfresco.org/model/content/1.0}content
# Data types that support cross locale/word splitting/token patterns if tokenised
alfresco.cross.locale.property.0={http://www.alfresco.org/model/content/1.0}name
# Data types that support cross locale/word splitting/token patterns if tokenised
alfresco.cross.locale.datatype.0={http://www.alfresco.org/model/dictionary/1.0}text
alfresco.cross.locale.datatype.1={http://www.alfresco.org/model/dictionary/1.0}content
alfresco.cross.locale.datatype.2={http://www.alfresco.org/model/dictionary/1.0}mltext
@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Context debug="0" crossContext="true">
<Environment name="solr/home" type="java.lang.String" value="@@ALFRESCO_SOLR_DIR@@" override="true"/>
</Context>
+5 -3
View File
@@ -6,7 +6,9 @@ set -eo pipefail
# set current working directory to the directory of the script
cd "$(dirname "$0")"
dockerImage="dockerreg.alfresco.com/alfresco-solr:${bamboo_planRepository_1_branch}-latest"
nicebranch=`echo "$bamboo_planRepository_1_branch" | sed 's/\//_/'`
dockerImage="dockerreg.alfresco.com/alfresco-solr:${nicebranch}-latest"
rm -rf target/alfresco-solr
rm -rf target/solr-*
@@ -25,9 +27,9 @@ fi
# running tests
docker run --rm "$dockerImage" [ -d /opt/alfresco-solr/data ] || (echo "Data dir does not exist" && exit 1)
docker run --rm "$dockerImage" [ -e /opt/alfresco-solr/solr/server/solr/conf/shared.properties ] || (echo "shared.properties does not exist" && exit 1)
docker run --rm "$dockerImage" [ -e /opt/alfresco-solr/solrhome/conf/shared.properties ] || (echo "shared.properties does not exist" && exit 1)
docker run --rm "$dockerImage" /opt/alfresco-solr/solr/bin/solr start
echo "Publishing $dockerImage..."
docker push "$dockerImage"
echo "SUCCESS"
echo "Docker SUCCESS"
+20 -2
View File
@@ -110,10 +110,28 @@
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<!-- Set the default solr home directory to solrhome -->
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>prepare-package</phase>
<configuration>
<target>
<replace token= "SOLR_SERVER_DIR/solr" value="SOLR_TIP/../solrhome" dir="target/solr-${solr.version}">
<include name="**/bin/solr"/>
</replace>
<chmod file="target/solr-${solr.version}/bin/solr" perm="755"/>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
@@ -10,11 +10,15 @@
<fileSet>
<directory>target/solr-${solr.version}</directory>
<outputDirectory>solr</outputDirectory>
<excludes>
<exclude>**/server/solr/**</exclude>
<exclude>**/example/**</exclude>
</excludes>
</fileSet>
<!-- Solr config -->
<fileSet>
<directory>target/alfresco-solr/solr/instance</directory>
<outputDirectory>solr/server/solr/</outputDirectory>
<outputDirectory>solrhome</outputDirectory>
<excludes>
<exclude>**/workspace-SpacesStore/**</exclude>
<exclude>**/archive-SpacesStore/**</exclude>