Seekity.com – Search Engine based on web usage behavior

Seekity.com - Results for java

Seekity.com - Results for java

Back in 2010 I created a prototype of a search engine based on web usage behavior. Back then I was heading a SEO-Driven startup and got so annoyed with search engine optimization, that I thought about ways to classify the web that cannot be optimized.

Firstly a search engine like this should not rely on backlinks. That will always lead to search engine optimization! More money … more SEO aktivity … more backlinks … better ranking … regardless of the quality of the content.

Well, let the people decide what websites are good. If a lot of people visit a website repeatedly and spend time on the website, it must have valuable content to that user.

Collecting this information a ranking can be constructed in which each user can cast one vote for a search query. Let’s say I work with Java Data Objects (JDO) and visit many pages about this topic. A search about “JDO” can take my usage data to construct my personal ranking. My personal ranking can then be merged with everybody else’s personal ranking, and the best websites on the topic come at the top of the search results page.

To make this more awesome you could personalize the search results to my taste. Maybe I am one of a few programmers that has a lot of experience with JDO. If there are very many beginners out there, beginners webpages would show on top of the search engine result page. However, if only the usage date of like-minded users, e.g., other programmers that have experience with JDO, is used for constructing my result page, then very valueable results would show.

This approach almost cannot be optimized, every user can only have one ranking for a search. To trick this algorithm you would need to create lots of artificial users. A user must have a minimum diversity in his/her usage behavior in order to be considered for contributing to the ranking. Creating users like this difficult and such users can easily be excluded.

Personalized results cannot be optimized at all. However creating personalized results in real time with large data sets is a challenging task.

I put all these ideas into www.seekity.com. This is a beta project. It runs completely in Google’s App Enginge, because I wanted to test developing with Google Web Toolkit.

Together with my buddies at 1xINTERNET we plan on rebuilding it based on Drupal / Solr with a shiny interface and all the Drupal-goodness.

Let me know what you think about this :-)

Javascript goodies: Get parameter from url – Round number with dot and comma

Here is some useful javascript stuff

Get parameter from url:

function getURLParam(strParamName){
var strReturn = “”;
var strHref = window.location.href;
if ( strHref.indexOf(“?”) > -1 ){
var strQueryString = strHref.substr(strHref.indexOf(“?”)).toLowerCase();
var aQueryString = strQueryString.split(“&”);
for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
if (aQueryString[iParam].indexOf(strParamName + “=”) > -1 ){
var aParam = aQueryString[iParam].split(“=”);
strReturn = aParam[1];
break;
}
}
}
return strReturn;
}

Round values to two digits with comma or dot as separater:

//Round with . as decimal separator
function kaufm_dot(x) {
var k = (Math.round(x * 100) / 100).toString();
k += (k.indexOf(‘.’) == -1)? ‘.00′ : ’00′;
return k.substring(0, k.indexOf(‘.’) + 3);
}
//Round with , as decimal separator
function kaufm_comma(x) {
var k = (Math.round(x * 100) / 100).toString();
k += (k.indexOf(‘.’) == -1)? ‘.00′ : ’00′;
var p = k.indexOf(‘.’);
return k.substring(0, p) + ‘,’ + k.substring(p+1, p+3);
}

Drupal Block Internet Explorer Update Warning XP Security Certificate Warning

Background:

  1. To optimize for IE6 is a pain in the !$”§$  - Therefore we want to display a warning message when a user visits one of our Drupal pages with Internet Explorer 6.
  2. We have multiple Drupal sites running on the same machine with the same IP address. Some of sites use HTTPS certificates. In order to use different certificates SNI is uses to differentiate between the certificates (see http://en.wikipedia.org/wiki/Server_Name_Indication). However, under Windows XP no version of Internet Explorer is capable of SNI. Users accessing secured pages from Windows XP get sent a wrong certificate – Therefore we want to display a warning for that.

Solution:

I created a block, that checks for XP with any version of Internet Explorer and if found displays a warning message. The same block also displays a warning message  when IE6 is found – that would get displayed on later Windows Versions that still run IE6 – I don’t know if that is a use case, but it is still nice to have.

It looks like this:

Here is the block (input type php):

<?php

//User Agent String
$ua = $_SERVER["HTTP_USER_AGENT"];

//Test for XP with IE
$xp = false;
if(strpos($ua, ‘Windows NT 5.’) || strpos($ua, ‘Windows XP’)) {
$xp = strpos($ua, ‘MSIE’) ? true : false;
}

//Test for IE6
$ie6 = strpos($ua, ‘MSIE 6.’) ? true : false;

//Disable potential caching of this page
if($xp || $ie6) {
$GLOBALS['conf']['cache'] = FALSE;
}

//Testing
//print “<p>$ua</p>”;
//$ie6 = true;
//$xp = true;
?><?php if($xp): ?>
<div id=”security-warning”>
<div id=”security-warning-close”>
<a class=”close” href=”#” onclick=”javascript:document.getElementById(&quot;security-warning&quot;).style.display=&quot;none&quot;; return false;”>x</a></div>
<table id=”security-warning-table”>
<tbody>
<tr>
<td id=”warning-icon” rowspan=”2″>
<img alt=”Warning!” src=”/sites/awo-rtk.de/files/icons/warning1.png” style=”width: 48px; height: 48px;” /></td>
<td class=”warning-message-bar” id=”warning-message” rowspan=”2″>
<b>Ihr Browser ist unsicher!</b>
<p>&nbsp;</p>
<p>Auf dieser Seite werden Sicherheitsstandards eingesetzt, die von Windows XP nicht unterst&uuml;tzt werden. Bitte verwenden Sie einen anderen Browser.</p>
</td>
<td class=”browser-link-icon”>
<a href=”http://www.firefox.com” target=”_blank”><img alt=”Firefox” src=”/sites/awo-rtk.de/files/icons/firefox.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
<td class=”browser-link-icon”>
<a href=”http://www.apple.com/safari/download/” target=”_blank”> <img alt=”Safari” src=”/sites/awo-rtk.de/files/icons/safari.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
<td class=”browser-link-icon”>
<a href=”http://www.google.com/chrome” target=”_blank”> <img alt=”Get Google Chrome” src=”/sites/awo-rtk.de/files/icons/chrome.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
</tr>
<tr>
<td class=”browser-link-text”>
Firefox</td>
<td class=”browser-link-text”>
Safari</td>
<td class=”browser-link-text”>
Chrome</td>
</tr>
</tbody>
</table>
</div>
<?php elseif($ie6): ?><div id=”security-warning”>
<div id=”security-warning-close”>
<a class=”close” href=”#” onclick=”javascript:document.getElementById(&quot;security-warning&quot;).style.display=&quot;none&quot;; return false;”>x</a></div>
<table id=”security-warning-table”>
<tbody>
<tr>
<td id=”warning-icon” rowspan=”2″>
<img alt=”Warning!” src=”/sites/awo-rtk.de/files/icons/warning1.png” style=”width: 48px; height: 48px;” /></td>
<td class=”warning-message-bar” id=”warning-message” rowspan=”2″>
<b>Ihr Browser ist veraltet!</b>
<p>Auf dieser Seite werden moderne Sicherheitsstandards und Darstellungsformen eingesetzt, die Ihr Browser nicht unterst&uuml;tzt. Bitte verwenden Sie einen anderen Browser.</p>
</td>
<td class=”browser-link-icon”>
<a href=”http://www.firefox.com” target=”_blank”><img alt=”Firefox” src=”/sites/awo-rtk.de/files/icons/firefox.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
<td class=”browser-link-icon”>
<a href=”http://www.microsoft.com/windows/internet-explorer/” target=”_blank”> <img alt=”Internet Explorer” src=”/sites/awo-rtk.de/files/icons/ie.png” style=”width: 48px; height: 48px;” /></a></td>
<td class=”browser-link-icon”>
<a href=”http://www.apple.com/safari/download/” target=”_blank”> <img alt=”Safari” src=”/sites/awo-rtk.de/files/icons/safari.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
<td class=”browser-link-icon”>
<a href=”http://www.google.com/chrome” target=”_blank”> <img alt=”Get Google Chrome” src=”/sites/awo-rtk.de/files/icons/chrome.png” style=”border-style: none; width: 48px; height: 48px;” /></a></td>
</tr>
<tr>
<td class=”browser-link-text”>
Firefox</td>
<td class=”browser-link-text”>
IE 8+</td>
<td class=”browser-link-text”>
Safari</td>
<td class=”browser-link-text”>
Chrome</td>
</tr>
</tbody>
</table>
</div>
<?php endif; ?>

Here is the CSS:

#security-warning {
border: 3px solid #EEE;
padding: 10px;
margin: 10px;
position: relative;
}
#security-warning-close {
position: absolute;
right: 5px;
top: 0px;
}
#security-warning-close a {
color: #999;
text-decoration: none;
}
#security-warning-table td {
padding: 5px 10px;
vertical-align: top;
}
#security-warning-table img {
padding-top: 20px;
}
.browser-link-icon {
}
.browser-link-text {
}
.browser-link-icon,
.browser-link-text {
text-align: center;
}
.warning-message-bar {
border-right: 1px solid #EEE;
}

Icons:

You can find the icons at http://www.iconfinder.com/

Drupal module node_limit – limit per user in role

Tonight I wrote an extension to Drupal’s node_limit module, allowing administrators to apply a Node Limit to all users that have a certain role. With this extension the administrator only selects the role. The limit gets applied for all users that have the configured role individually.

Node_limit was easy to extend thanks to the well-written and understanable code by Edouard Cunibil. Thanks for the good work.

If this extension is useful to you, download it here (.zip) or here (.tar.gz) and please leave a comment.

Programmatically upload form with text field and file field to server using PHP stream_context_create

OK, this turned out to be a tricky one.

For some reason I wanted to programmatically post data to a server. I wanted to do the equivalent to posting this form from a web-browser:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Upload</title>
</head>
<body>
<form action="http://localhost/upload" method="post" enctype="multipart/form-data">
 <input type="file" name="files[upload]" size="40">
 <input type="text" name="info" value="some text">
 <input type="submit" name="op" value="Upload">
</form>
</body>
</html>

Well, I thought this must be easy using PHP. Right? It’s one of the oldest programming languages for web applications out there, right? Well, it turned out to be somewhat tricky.

I read up on some posts, for examples the comments on http://php.net/manual/de/function.stream-context-create.php or in this blog: http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/

These posts explain howto use stream_context_create() resource to send data to a server.

However, there was always essential information missing, for example how to actually create the data to post. After a little bit of scratching my head and testing this is what worked for me.

<?php
//Target url
$url = "http://localhost/upload";
//Boundary definition
$boundary = "---------------------".substr(md5(rand(0,32000)), 0, 10);
//Post data
$data = "";
//Fields
$data .= "--$boundary\n";
$data .= "Content-Disposition: form-data; name=\"name\"\n\nsome text\n";
$data .= "--$boundary\n";
$data .= "Content-Disposition: form-data; name=\"op\"\n\nUpload\n";
$data .= "--$boundary\n";
//Files
$fileContents = file_get_contents('test.zip');
$data .= "Content-Disposition: form-data; name=\"files[upload]\"; filename=\"test.zip\"\n";
$data .= "Content-Type: application/zip\n";
$data .= "Content-Transfer-Encoding: binary\n\n";
$data .= $fileContents."\n";
$data .= "--$boundary\n";
//Header
$optional_headers = header('Content-Type: multipart/form-data; boundary='.$boundary);
//Construct params
$params = array('http' => array(
 'method' => 'POST',
 'header' => 'Content-Type: multipart/form-data; boundary='.$boundary,
 'content' => $data
));
//Create context
$ctx = stream_context_create($params);
//Post data to url
$fp = @fopen($url, 'rb', false, $ctx);
if (!$fp) {
 echo "Error posting to $url: " . $php_errormsg;
 exit(1);
}
//Read response
$response = @stream_get_contents($fp);
if ($response === false) {
 throw new Exception("Problem reading data from $url, $php_errormsg");
 exit(1);
}
//Display response (with a little bit of formatting)
$response = strip_tags($response);
$response = preg_replace('/\s+\n/', "\n", $response);
$response = preg_replace('/\n\s+/', "\n", $response);
$response = preg_replace("'[ ]+'", ' ', $response);
echo $response;
echo "Done";
?>

This PHP programm can be executed on the command line with PHP (CLI). If it is saved as test_upload.php it can be executed with php test_upload.php.

Please note that I use $php_errormsg. This gives access to previous errors. To have access to this variable, it must be turned on in php.ini (track_errors = On). I have also turned on display of error messages (display_errors = On).

Obviously there must be a file named test.zip in the same directory als test_upload.php for this programm to work. If you want to post anything else than a zip file, don’t forget to change the content-type. If you wanted to post a jpeg you would set it to Content-Type: image/jpeg.

I hope this helpy someone.

Cheers,

Christoph

PS: You can also a PHP extension called cURL (http://php.net/manual/de/book.curl.php), it should also work, I didn’t try it.

PHP-5.2 and PHP-5.3 for Drupal applications under Apache on Ubuntu 10.04 LTS

Why do this?

For running legacy Drupal applications it can be necessary to have different version of PHP on your system. Drupal5 runs on PHP-5.2, Drupal6 and later versions run on PHP-5.3, more about this here: http://drupal.org/requirements.

In a situation like this you might want the PHP-5.2 application (e.g., Drupal5) and the PHP-5.3 application (e.g., Drupal6) to be served from the same Apache. One way of doing it is using mod_php5 to serve PHP-5.3 applications and run PHP-5.2 applications over fast-cgi. Under Ubuntu 10.04 this can be achieved by installing PHP-5.3 from the repository and manually compiling and installing PHP-5.2.

I was facing this problem and this post is a write-up what I did to get it running in a step-by-step tutorial with all necessary resources and configurations.

There are two excellent blog posts, about how this can be done. The earlier is from Dave Parrish, a bit later came Brett with a nice tutorial. However, in spite of these excellent posts I encountered some pitfalls and discovered some caveats.

Setup Apache with mod_php5 (PHP-5.3)

Under Ubuntu it is really easy to set up apache with php. You simply install the necessary packages from the repository. The php version shipped with Ubuntu 10.04 is PHP-5.3. In my test environment I have the following installed:

sudo apt-get install apache2
sudo apt-get install php5 php5-dev libapache2-mod-php5

Checking localhost by directing the browser to http://localhost shows apache’s index.html saying It works!

To test if php works create a php file with f.x.

echo "<?php phpinfo(); ?>" | sudo tee /var/www/testphp.php

Testing php by directing the browser to http://localhost/testphp.php shows the php version information for PHP-5.3 from mod_php5.

To set up Drupal6 you can also install from the repositories by running

sudo apt-get install mysql-server
sudo apt-get install drupal6

With this setup Drupal6 applications can painlessly be run. However for production you might want to set up Drupal differently, here is some guidance: http://drupal.org/node/251019.

Install and test PHP-5.2

To install PHP-5.2 download the latest version from http://php.net/downloads.php to some local directory. Change into the directory and unpack php and change into the resulting directory

gunzip php-5.2.17.tar.gz
tar -xf php-5.2.17.tar
cd php-5.2.17/

Install the build tools to manually compile PHP-5.2.

sudo apt-get install libxml2-dev libmysqlclient-dev libcurl4-gnutls-dev libpng12-dev libjpeg62-dev

Then configure and install PHP-5-2 to /opt/php5.2

./configure --prefix=/opt/php5.2 --with-config-file-path=/opt/php5.2 --with-mysqli --with-mysql --with-curl --with-gd --with-jpeg-dir --enable-cli --enable-fastcgi --enable-discard-path --enable-force-cgi-redirect
make
sudo make install

Now you have PHP-5.2 installed in /opt/php5.2

You can test if PHP-5.2 works by having the testphp.php interpreted by the cgi binary

/opt/php5.2/bin/php /var/www/testphp.php

Set up Apache for FastCGI

Next thing to do is to set up apache to run PHP-5.2 over FastCGI

sudo apt-get install libapache2-mod-fastcgi

Make sure all neccesary modules are enabled in apache

sudo a2enmod cgi
sudo a2enmod fastcgi
sudo a2enmod actions
sudo /etc/init.d/apache2 restart

It is smart  to use a shell script that executes PHP-5.2 for you, in order to configure FastCGI and make a php.ini available. To do this create a file name php52-cgi and place it in Apaches cgi-bin directory /usr/lib/cgi-bin/ with the following content

#!/bin/sh
PHPRC="/opt/php5.2/"
export PHPRC
PHP_FCGI_CHILDREN=4
export PHP_FCGI_CHILDREN
PHP_FCGI_MAX_REQUESTS=5000
export PHP_FCGI_MAX_REQUESTS
exec /opt/php5.2/bin/php-cgi

The first parameter tells PHP-5.2 where to look for a php.ini, the second pre-fork threads with the FastCGI process manager, the third limits the requests. The last line executes php. More about this can be found at http://www.fastcgi.com/drupal/node/5?q=node/10.

Make sure the file is executable

sudo chmod +x /usr/lib/cgi-bin/php52-cgi

Please note that there is no php.ini in /opt/php5.2/. You have to manually copy and rename the php.ini that was shipped with PHP-5.2. It is located at in the php folder you unzipped at php-5.2.17/php.ini-recommended.

You can test if the script works by executing

/usr/lib/cgi-bin/php52-cgi < /var/www/testphp.php

To set up Apache create a Include file named php52.conf at /etc/apache2/ that can be used in any virtual host, which needs to use PHP-5.2. Write the following content in the /etc/apache2/php52.conf

#include for virtual hosts that need to run php-5.2
<FilesMatch "\.php">
   SetHandler application/x-httpd-php5
</FilesMatch>
ScriptAlias /php52-cgi /usr/lib/cgi-bin/php52-cgi
Action application/x-httpd-php5 /php52-cgi
AddHandler application/x-httpd-php5 .php

The FilesMatch forces the handler to execute files with the suffix .php. This must be set, because if mod_php with PHP-5.3 is installed, the module interprets the php file and not the cgi script. The ScriptAlias sets the path to the cgi script. The AddHandler registers a new handler. The Action activates the cgi script for the files passed from the handler. You can read up on this under http://httpd.apache.org/docs/2.2/mod/mod_actions.html, http://httpd.apache.org/docs/2.2/mod/mod_mime.html#addhandler, and http://httpd.apache.org/docs/2.2/mod/core.html#sethandler.

See if it works

For testing you can runa PHP-5.3 application and a PHP-5.2 application in two different virtual hosts. Create a new entry in /etc/hosts with the line

127.0.0.1	php52.localhost php53.localhost

Now when you ping php52.localhost or php53.localhost you should receive packages from your local apache on the ip-address 127.0.0.1.

Now we create two virtual host files in /etc/apache2/sites-available, one named php52 and php53. In the php52 we add the Include file created earlier.

php52:

<VirtualHost *:80>ServerAdmin webmaster@localhostServerName php52.localhostDocumentRoot /var/www#Include php5.2Include php52.conf
ErrorLog /var/log/apache2/error.log# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.LogLevel debugCustomLog /var/log/apache2/access.log combined </VirtualHost>

php53:

<VirtualHost *:80>ServerAdmin webmaster@localhostServerName php53.localhostDocumentRoot /var/wwwErrorLog /var/log/apache2/error.log# Possible values include: debug, info, notice, warn, error, crit, alert, emerg.LogLevel debugCustomLog /var/log/apache2/access.log combined </VirtualHost>

Enable the new virtual hosts and restart apache

cd /etc/apache2/sites-enabled
sudo ln -s ../sites-available/php52 php52
sudo ln -s ../sites-available/php52 php52
sudo /etc/init.d/apache2 restart

When you now direct your browser to http://php52.localhost/testphp.php you should see the output of PHP-5.2, when you direct your browser to http://php53.localhost/testphp.php you see the output of PHP-5.3.

So for any virtual host that requires PHP-5.2 you simply need to add the include /etc/apache2/php52.conf.

Have fun.

Qype – Free vs. Premium – HOWTO

Nachdem ich gestern das Angebot von 1xINTERNET bei Qype eingetragen habe, wurde ich heute von einem Mitarbeiter von Qype angerufen, der mir eine Premiummitgliedschaft verkaufen wollte.

Beim Gespräch habe ich erfahren, dass 1xINTERNET in der Suche nicht berücksichtigt wird, weil Verschlagwortung u.s.w. exklusv Premiummitgliedern vorbehalten ist. Auf Qype kann mein Eintrag über zwei Wege erreicht werden.

  1. Der Nutzer gibt den Firmennamen in die Suche ein, aber dann kennt er das Unternehmen ja sowiso schon, und sucht nicht auf Qype danach.
  2. Der Nutzer navigiert durch die Branchen, also z.B. Klick auf Frankfurt -> Klick auf Dienstleistungen -> Klick auf Computerdienste …, das macht sowiso keiner.

Fazit: User auf Qype werden meinen Firmeneintrag niemals finden.

Hier der Trick: Jetzt kann man natürlich schlau sein und den Firmennamen ein wenig mit passenden Keywords aufpeppen. Der Firmenname wird nämlich durchsucht.

Ich hätte statt

  • 1xINTERNET
  • 1xINTERNET – Homepage, Website, Web-Design für Unternehmen

als Firmenname wählen sollen.

Naja, vielleicht hilft dieser Trick jemandem.

Günstige Homepage mit Domain, Emailadressen und Hosting

1xINTERNET - Professionelle Internetseiten für Unternehmen - Erstellung und Hosting Meine Frau und ich haben gemeinsam mit Partnern Anfang des Jahres 1xINTERNET gegründet. Die Idee ist durch das “Do-it-yourself” Homepageangebot von 1und1 entstanden. Das Problem bei einer “Do-it-yourself” Homepage ist, dass ein unfahrener Ersteller sehr lange braucht, und dass die resultierende Homepage in vielen Fällen unprofessionell aussieht.

Also haben wir uns gedacht, wenn wir das für Kunden erstellen, geht es schneller und das Ergebnis ist viel besser. Natürlich bieten wir auch das komplette Paket mit Emails und Hosting an.

Die Erstellung einer Homepage kostet einmalig 799,- € (vgl. Preise). Die kosten für das Hosting betragen 9,- € pro Monat. Das ist zwar genau derselbe Preis wie bei anderen Hostern. Support gibts bei uns ab 20,- € pro Stunde auch zu einem fairen Preis. Das ist wichtig, damit Kunden die Inhalte ihrer Internetseiten überarbeiten können. Beim Hosting sind die Domain, E-Mail-Postfächer und 5 GB Webspace ebenfalls inkludiert.

Damit bietet 1xINTERNET alles aus einer Hand. Mehr Infos auf ww.1xinternet.de.

Nautilus – resize and rotate images

I’m storing many photos on my computer and sometimes I just want to quickly resize an image and send it in email or upload it to a website. Ubuntu doesn’t come with a easy-to-use image software and therefore I installed GIMP to do all my image editing.

It takes a lot of time and effort to open each image in GIMP only to resize it. Therefore I decided to look for another solution. Of course it would be best if this could be done directly in Nautilus. It didn’t take me long to find an article about exactly this problem and with it a solution.

You have to install the nautilus-image-converter package:

sudo aptitude install nautilus-image-converter

Then you need to restart nautilus:

killall nautilus

Now when you right-click on the image, you see two new items: “Resize Images…” and “Rotate Images…”

This works perfectly on my Nokia Booklet 3G with Ubuntu 10.04 Netbook edition

Have fun with it

Howto Solr Ubuntu 10.04 Lucid Tomcat6

I had some difficulties finding good howtos for setting up Solr on my system. There are some covering the topic, but none of them worked for me. The best I found was by Paul Bramsher published here, but this was for older versions of Ubuntu and Solr. There is also a wiki for setting up Solr hosted on apache.org, but I did not find that very herlpful. In the end I got it working and here is what I did.

I am using Ubuntu 10.04 Lucid and use the standard installation of Tomcat6 with sun-java6-jdk, both installed via apt-get.

All installations were done as root user.

First step is to download and extract Solr:

mkdir ~/solr
cd ~/solr
wget http://apache.thelorne.com/lucene/solr/1.4.1/apache-solr-1.4.1.tgz
gunzip apache-solr-1.4.1.tgz
tar -xf apache-solr-1.4.1.tgz

Now create a directory structure for multiple Solr instances. That way you can have one instance for development and one for production:

mkdir /var/lib/tomcat6/data
mkdir /var/lib/tomcat6/data/solr
mkdir /var/lib/tomcat6/data/solr/dev
mkdir /var/lib/tomcat6/data/solr/dev/conf
mkdir /var/lib/tomcat6/data/solr/dev/data
mkdir /var/lib/tomcat6/data/solr/prod
mkdir /var/lib/tomcat6/data/solr/prod/conf
mkdir /var/lib/tomcat6/data/solr/prod/data

Move the war file from the downloaded Solr to the new location:

cp /home/breidert/solr/apache-solr-1.4.1/dist/apache-solr-1.4.1.war /var/lib/tomcat6/data/solr/solr.war

Create config files for two instances. They will automatically get read by tomcat6, when the server is restarted:

echo “<Context docBase=\”/var/lib/tomcat6/data/solr/solr.war\” debug=\”0\” crossContext=\”true\”> <Environment name=\”solr/home\” type=\”java.lang.String\” value=\”/var/lib/tomcat6/data/solr/dev\” override=\”true\” /> </Context>” > /etc/tomcat6/Catalina/localhost/solrdev.xml
echo "<Context docBase="/var/lib/tomcat6/data/solr/solr.war" debug="0" crossContext="true">
  <Environment name="solr/home" type="java.lang.String" value="/var/lib/tomcat6/data/solr/prod" override="true" />
</Context>" > /etc/tomcat6/Catalina/localhost/solrprod.xml

Copy the sample applications for the two instances from the downloades Solr to the new locations:

cp -R /home/breidert/solr/apache-solr-1.4.1/example/solr/conf/* /var/lib/tomcat6/data/solr/dev/conf/
cp -R /home/breidert/solr/apache-solr-1.4.1/example/solr/conf/* /var/lib/tomcat6/data/solr/prod/conf/

Now the solrconfig.xml file needs to be adapted for tomcat6. For both instances there needs to be specified a dataDir. In the example files copied above this is set to <dataDir>${solr.data.dir:./solr/data}</dataDir> and must be changed to <dataDir>${solr.data.dir:/var/lib/tomcat6/data/solr/dev/data}</dataDir> for dev and to <dataDir>${solr.data.dir:/var/lib/tomcat6/data/solr/prod/data}</dataDir> for prod:

cp /var/lib/tomcat6/data/solr/dev/conf/solrconfig.xml /var/lib/tomcat6/data/solr/dev/conf/solrconfig.xml.bak
sed 's/.\/solr\/data/\/var\/lib\/tomcat6\/data\/solr\/dev\/data/g' /var/lib/tomcat6/data/solr/dev/conf/solrconfig.xml.bak >/var/lib/tomcat6/data/solr/dev/conf/solrconfig.xml

cp /var/lib/tomcat6/data/solr/prod/conf/solrconfig.xml /var/lib/tomcat6/data/solr/prod/conf/solrconfig.xml.bak
sed 's/.\/solr\/data/\/var\/lib\/tomcat6\/data\/solr\/prod\/data/g' /var/lib/tomcat6/data/solr/prod/conf/solrconfig.xml.bak >/var/lib/tomcat6/data/solr/prod/conf/solrconfig.xml

Make tomcat6 the owner of the new directories and file:.

chown -R tomcat6:tomcat6 /var/lib/tomcat6/data

That’s it. After restarting tomcat6 you find the two instances under http://<yourhost_and_port>/solrdev and http://<yourhost_and_port>/solrprod

Easy AdSense by Unreal