GeoServer – create a datastore programmatically

Martin Zeller GeoServer, java 2 Comments

Currently I am programming an upload module for GeoServer 2.1-RC2. The user should be able to upload a shape file which is automatically installed as datastore in the default workspace. For this intention I didn’t want to use the REST-API of GeoServer, I wanted to create the data store  programmatically.

The following piece of code adds a ShapeFile data store to GeoServer:

private boolean addShapeFileDataStore(String title, String description, String pathToFile)  {
		final Catalog catalog = getCatalog();
        DataStoreInfo dsInfo = catalog.getFactory().createDataStore();
        dsInfo.setName(title);
        dsInfo.setDescription(description);
        dsInfo.setEnabled(true);
        dsInfo.setType("Shapefile");
        dsInfo.getConnectionParameters().put("create spatial index", true);
        dsInfo.getConnectionParameters().put("charset", "ISO-8859-1");
        dsInfo.getConnectionParameters().put("filetype", "shapefile");
        dsInfo.getConnectionParameters().put("cache and reuse memory maps", true);
        dsInfo.getConnectionParameters().put("url", "file:" + pathToFile);
        dsInfo.getConnectionParameters().put("namespace", "http://www.torres.at/");
        try {
            catalog.add(dsInfo);
        } catch (Exception e) {
            LOGGER.log(Level.WARNING, "Error adding data store to catalog", e);
        }
        return true;
}

It’s quite simple. With this code you can add every kind of data store to GeoServer – all you need to know are the connection parameters. If you do not know the parameters of your kind of data store just create such a data store and write the connection parameters to your log file. You could use the following function:

private void LogDataStoreData(String dataStoreName) {
		final Catalog catalog = getCatalog();
        DataStoreInfo ds = catalog.getDataStoreByName(dataStoreName);
        if (ds!=null)
        {
            Map<String,Serializable> conMap = ds.getConnectionParameters();
            LOGGER.finest("Id: " + ds.getId());
            LOGGER.finest("Name: " + ds.getName());
            LOGGER.finest("Description: " + ds.getDescription());
            LOGGER.finest("Type: " + ds.getType());
            LOGGER.finest("Connection parameters:");

            for(String key : conMap.keySet())
            {
                LOGGER.finest("\t" + key + ": " + conMap.get(key));
            }
        }
}

C pointers for dummies (like me :)

Martin Zeller ANSI C Leave a Comment

Just a little piece of code in C for clearing up pointers… look at the comments in the first part!
(If you need an environment to develop in C on windows, find a solution here: environment for ansi c on windows

void change(short*, short*);

int main(void) {
	short *pointer1 = NULL;
	short *pointer2 = NULL;
	short value1 = 1111;
	short value2 = 2222;

	pointer1 = &value1;
	pointer2 = &value2;

	printf("main - VALUE1:\n");
	printf("main - value of value1: %d\n", value1); // Output the value of value1
	printf("main - value of value1: %d\n", *pointer1); // Output the value at the address
	printf("main - address of value1: %p\n", &value1); // Output the address of value1
	printf("main - address of value1: %p\n", pointer1); // Output the value of pointer1 (it's the address of value1 !)
	printf("main - address of pointer1: %p\n", &pointer1);	// Output the address(!) of the pointer(!)
	printf("\nmain - VALUE2:\n");
	printf("main - value of value2: %d\n", value2);
	printf("main - value of value2: %d\n", *pointer2);
	printf("main - address of value2: %p\n", &value2);
	printf("main - address of value2: %p\n", pointer2);
	printf("main - address of pointer2: %p\n", &pointer2);
	printf("\n*** main - starting change...\n\n");
	change(pointer1, pointer2);
	printf("\n*** main - changing done!\n\n");
	printf("main - VALUE1:\n");
	printf("main - value of value1: %d\n", value1);
	printf("main - value of value1: %d\n", *pointer1);
	printf("main - address of value1: %p\n", &value1);
	printf("main - address of value1: %p\n", pointer1);
	printf("main - address of pointer1: %p\n", &pointer1);
	printf("\nmain - VALUE2:\n");
	printf("main - value of value2: %d\n", value2);
	printf("main - value of value2: %d\n", *pointer2);
	printf("main - address of value2: %p\n", &value2);
	printf("main - address of value2: %p\n", pointer2);
	printf("main - address of pointer2: %p\n", &pointer2);

	return EXIT_SUCCESS;
}

void change(short *valuePointer1, short *valuePointer2) {
	printf("change - value of value1: %d\n", *valuePointer1);
	printf("change - address of value1: %p\n", valuePointer1);
	printf("change - value of value2: %d\n", *valuePointer2);
	printf("change - address of value2: %p\n", valuePointer2);
	printf("change - changing now...\n");
	short h;
	h = *valuePointer1;
	*valuePointer1 = *valuePointer2;
	*valuePointer2 = h;
	printf("change - changing done!\n");
	printf("change - value of value1: %d\n", *valuePointer1);
	printf("change - address of value1: %p\n", valuePointer1);
	printf("change - value of value2: %d\n", *valuePointer2);
	printf("change - address of value2: %p\n", valuePointer2);
}

gcc on windows with eclipse and mingw

Martin Zeller ANSI C 2 Comments

This information will help you:

  • if you want to develop in C with gcc on windows
  • if you want to develop in C with mingw and eclipse with CDT plugin

Forget all the tutorials for installing and configuring eclipse with mingw or cygwin – just download the Wascana Eclipse C/C++ IDE for Windows Developers
You will be surprised!

Wascana is a ready-to-use-eclipse-ide (Helios) with mingw toolchain installed and configured! OUT OF THE BOX! You don’t have to install anything else (neither mingw nor cygwin)!

** Download: Wascana

Het mysterie van Arendarvon Castle

Martin Zeller Allgemein Leave a Comment

Gute Neuigkeiten für alle niederländischen Fans des C64-Adventures ‘Das Geheimnis des Schloss Arendarvon’. Dank eines eurer Landsleute konnte (und wird auch weiterhin) die niederländische Version unserer Fanpage nun endlich richtig übersetzt. Seht:

=> Het mysterie van Arendarvon Castle

(Die deutsche Version der Fan-Seite: => Das Geheimnis des Schloss Arendarvon)

Unser Dank geht an H. Zwetsloot

The “IE7 setAttribute class” problem!

Martin Zeller Javascript Leave a Comment

This does not work with IE7:

elem.setAttribute('class',  cssClass);

Use this instead:

elem.setAttribute((document.all ? 'className' : 'class'), cssClass);

Problem: document.all exists in IE8 too, but IE8 does not work with ‘className’!
My solution in one of my projects was prototype:

Prototype.Browser.IE6 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6;
Prototype.Browser.IE7 = Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 7;
Prototype.Browser.IE8 = Prototype.Browser.IE && !Prototype.Browser.IE6 && !Prototype.Browser.IE7;

function SetCssClass(id, cssClass) {
  if (Prototype.Browser.IE6 || Prototype.Browser.IE7)
    $(id).setAttribute((document.all ? 'className' : 'class'), cssClass);
  else $(id).setAttribute('class', cssClass);
}

PS: in IE7 you can set styles to an element this way:

elem.style.setAttribute('cssText', 'border:1px solid red;',0);

SqlHelper und benutzerdefinierte Tabellentypen mit SQL Server 2008

Martin Zeller .net, sql server Leave a Comment

Arbeitest du mit SQL Server 2008, SqlHelper und benutzerdefinierten Tabellentypen und erhältst folgende Fehlermeldung?

Der eingehende Tabular Data Stream (TDS) für das 
RPC-Protokoll (Remote Procedure Call) ist nicht richtig.
Tabellenwertparameter ('@xxx'), Zeile n, Spalte n: 
Für den Datentyp xxx (benutzerdefinierter Tabellentyp) wurde ein 
Datenbankname mit einer Nicht-Null-Länge angegeben. Der Datenbankname 
ist mit einem Tabellenwertparameter nicht zulässig. Es sind nur ein 
Schemaname und ein Typname gültig.

Wichtig beim SqlHelper ist bei dieser Fehlermeldung, dass du den CommandType angibst. So wie hier:

// C#
dr = SqlHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, "MyProcedureName", sqlParams);

Die andere Fehlermeldung, mit der ich Bekanntschaft schließen durfte, war:

Es ist keine Zuordnung zwischen dem Objekttyp 
System.Collections.Generic.List`1[[Microsoft.SqlServer.Server.SqlDataRecord, System.Data, 
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 
und einem bekannten verwalteten systemeigenen Providertyp vorhanden.

Erhältst du diese Meldung, dann solltest du eventuell den SqlDbType deiner übergebenen Liste auf SqlDbType.Structured setzen. Siehe hier:

List<SqlDataRecord> datList = new List<SqlDataRecord>();
SqlMetaData[] tvp_definition = { new SqlMetaData("n", SqlDbType.BigInt) };
foreach (MyDataInfo dat in datas)
{
  SqlDataRecord rec = new SqlDataRecord(tvp_definition);
  rec.SetInt64(0, dat.SomePropertyId);
  datList.Add(rec);
}
SqlParameter[] sqlParams = new SqlParameter[1];
SqlParameter param = new SqlParameter("@MyParameter", datList);
param.Direction = ParameterDirection.Input;
param.TypeName = "long_list_tbltype"; // long_list_tbltype ist ein von mir definierter Tabellentyp
param.SqlDbType = SqlDbType.Structured; // IMPORTANT!!!
sqlParams[0] = param;

dr = SqlHelper.ExecuteReader(ConnectionString, CommandType.StoredProcedure, GetFullyQualifiedName("MyProcedureName"), sqlParams);

Ich bin auf diese Probleme gestoßen, weil ich eine generische Liste an eine Procedure übergeben wollte. Wie das geht, siehst du in diesem Artikel: Arrays and Lists in SQL Server

Pdf thumbnails / Pdf to jpg

Martin Zeller php 2 Comments

Do you want to create thumbnails for pdf files with PHP (or C#)? You can simply do this with ghostscript. Here’s the php way (it is very easy to convert this code to C#):

  1. First install ghostscript on your server. Download: http://ghostscript.com/releases/
  2. Then write your code:
$pathToPdf = "C:\....\PdfFile.pdf";
$pathToJpg = "C:\....\generatedThumbnail.jpg";

$gsCall = "\"C:\....\gs\gs8.70\bin\gswin32.exe\" -q -dBATCH -dMaxBitmap=300000000 -dNOPAUSE -dSAFER -sDEVICE=jpeg -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dFirstPage=1 -dLastPage=1 -sOutputFile={0} {1} -c quit";

$gsCall = str_replace(array('{0}', '{1}'), array($pathToJpg, $pathToPdf), $gsCall); // or use sprintf
$str = exec($gsCall, $output=array(), $returnValue);

This code will generate a jpg file with the content of the first page of the pdf file.

Ready.

Zend_Captcha, an example without Zend_Form

Martin Zeller php 2 Comments

Here is your example how to implement Zend_Captcha_Image without using Zend_Form.

In your action method:

public function indexAction()
{
//...
$captcha = new Zend_Captcha_Image();
$captcha->setImgDir(APPLICATION_PATH . '/../public/tmp/captcha/');
$captcha->setImgUrl($this->view->baseUrl('/tmp/captcha/'));
$captcha->setFont(APPLICATION_PATH . '/fonts/elephant.ttf');
$captcha->setWidth(350);
$captcha->setHeight(150);
$captcha->setWordlen(5);
$captcha->setFontSize(70);
$captcha->setLineNoiseLevel(3);
$captcha->generate();
$this->view->captcha = $captcha;   // giving captcha object to the view
//...
}

In the corresponding view render the captcha and add a hidden field with the captcha id:

<form>
<input id="captcha" type="text" name="captcha" />
<?php echo $this->captcha->render($this, null) ?>
<input type="hidden" name="cid" value="<?php echo $this->captcha->getId() ?>" >
</form>

Validating the input of the user after postback:

// ...
$capId = $_POST['cid'];
$capSession = new Zend_Session_Namespace('Zend_Form_Captcha_'.$capId);
if ($_POST['captcha']==$capSession->word)
{
  // input OK
}
else {
  // input NOK
}
// ...

Good luck!

PS: If you want to use your Zend_Captcha WITH Zend_Form, this blog post may help you: Zend_Captcha with Zend_Form