Friday, September 20, 2013

MarkLogic - using xquery to interact via Alfresco's content repository using the REST API

Using Alfresco community edition 4.2.a, and MarkLogic 6.

It was difficult navigating Alfresco's documentation on the REST API, as there were NO examples, just specs.. and often the specs stated that they were "deprecated".  Ultimately I found this document on CMIS and interacting via http.  (NOTE:  There is a vital typo on page 25 in the cmisra namespace declaration, which causes example to fail.. just remove extraneous slash).

Anyway, I cobbled together an example that demonstrates login, ticket validation, content creation, and logout.  This works in the Query Console.. although the base64 module is my own (see prior post on base64 encoding of binary files).

xquery version "1.0-ml";
declare namespace html = "";
import module namespace json = "" at "/MarkLogic/json/json.xqy";
import module namespace base64 = "base64" at "utility/base64.xqm";

let $string := concat('{ "username":"admin", "password":"admin" }')
let $data := <data>{$string}</data>

let $login := xdmp:http-post("http:/localhost:8080/alfresco/service/api/login",
  <options xmlns="xdmp:http">
let $ticket_xml := json:transform-from-json($login[2])

let $ticket_id := data($ticket_xml//*[local-name() = 'ticket'])

let $uri := concat("http://localhost:8080/alfresco/service/api/login/ticket/",$ticket_id,"?alf_ticket=",$ticket_id)

let $check := xdmp:http-get($uri)
(: if you have a node_id, the following is example of how to retrieve content
let $content_uri := concat("http://localhost:8080/alfresco/service/cmis/i/", $node_id, "/content?alf_ticket=", $ticket_id) :)

let $filedata := base64:encode("/some/path/image.png")  (: insert your own base64 here :)

let $content_uri := concat("http://localhost:8080/alfresco/s/cmis/p/path/children", "?alf_ticket=", $ticket_id)  (: the "path" is the path after "Company Home" :)

let $atomxml :=
<entry xmlns="" 
 <summary>A sample upload</summary>
 <content type="image/png">{$filedata}</content>
 <cmis:propertyId propertyDefinitionId="cm:description"><cmis:value>This is the description property</cmis:value></cmis:propertyId>
 <cmis:propertyId propertyDefinitionId="cmis:objectTypeId"><cmis:value>cmis:content</cmis:value></cmis:propertyId>

let $upload := xdmp:http-post($content_uri,
  <options xmlns="xdmp:http">
        <data>{concat('<?xml version="1.0" encoding="utf-8"?>',xdmp:quote($atomxml))}</data>

let $logout := xdmp:http-delete($uri)

return ($check,$upload)

MarkLogic base64 encoding of a binary file using MLJAM

MarkLogic has the function xdmp:base64-encode, which unfortunately only works on xs:string's.

I needed a function to convert an arbitrary file (ie. binary) into a base64 encoded stream in order to put it into an atom+xml http post to feed Alfresco document management system.  Luckily I found MLJAM, which allows you to embed Java into xquery.  I found the needed Java snippet here, and then put it together - the code below should work in the MarkLogic Query console, just set the filename parameter accordingly.

Ultimately MarkLogic should have xdmp:base64-encode work on a binary node, then you could simply do xdmp:base64-encode(xdmp:external-binary("/some/path/image.png"))!

xquery version "1.0-ml";
import module namespace jam = "" at "/MarkLogic/jam.xqy";
let $code := <code><![CDATA[
import org.apache.commons.codec.binary.Base64;
private String encodeFileToBase64Binary(String fileName)
throws IOException {
File file = new File(fileName);
byte[] bytes = loadFile(file);
byte[] encoded = Base64.encodeBase64(bytes);
String encodedString = new String(encoded);
return encodedString;
private static byte[] loadFile(File file) throws IOException {
   InputStream is = new FileInputStream(file);
     long length = file.length();
   if (length > Integer.MAX_VALUE) {
       // File is too large
   byte[] bytes = new byte[(int)length];
   int offset = 0;
   int numRead = 0;
   while (offset < bytes.length
          && (, offset, bytes.length-offset)) >= 0) {
       offset += numRead;
   if (offset < bytes.length) {
       throw new IOException("Could not completely read file "+file.getName());
   return bytes;
    return encodeFileToBase64Binary(filename);
let $path := "http://localhost:8080/mljam/mljam"
let $connect := jam:start($path, (), ())
let $vars := jam:set("filename", "/some/path/image.png")
let $eval := jam:eval-get($code)
let $end := jam:end()
return $eval

Friday, August 2, 2013

League of Legends on 64-bit ubuntu 12.04 with Intel graphics

With the release of wine 1.6, LOL works well under linux, but was having black background issue.

Found this link:

Installed driconf and enabled S3TC texture compression support.. this solved the problem.

Tuesday, May 7, 2013

IMAP setup on BB10 (Z10)

Its soo simple now.. way to go BB.

First - "Add Account"

Click on "Advanced"

Click on "IMAP"

Enter details.  Custom ports supported..  PUSH supported for sure with Cyrus imap server.  Very nice.. no third-party app required.

Friday, April 26, 2013

Installing Ubuntu 13.04 on an ASUS X55A / X55U

Downloaded the official release of 13.04 yesterday, and tried installing on an ASUS X55A.  I wanted a dual-boot setup.  Took a little bit of effort, but got er done.. steps follow.

First thing I had to do was to disable Fast Boot and disable Secure Boot.  From inital power on, press ESC repeatedly until small blue boot menu appears, then select "Enter Setup".  Goto Boot -> Boot Configuration and disable Fast Boot. Change boot order so that DVD is 1st.  Goto Security and disable Secure Boot Control.  Press F10 to save and exit.  This allows the install media to boot (in my case a DVD).  Install went fine, selected the "Install Ubuntu alongside Windows 8" option.

After install, the system booted to grub, but when selecting Ubuntu, screen would go blank (but not off) and all HDD activity would stop.  Numlock/Capslock keys worked, so system was not hung.  Pressing Enter a few times would cause HDD light to flicker, but otherwise nothing.. Ctrl-Alt-Fn would not do anything.  Strange thing was that if I rebooted, pressed ESC to get blue boot menu, and selected the "ubuntu" option (created by installer), it would goto grub and then boot fine!

To fix this, I installed and ran boot-repair.

sudo add-apt-repository ppa:yannubuntu/boot-repair && sudo apt-get update
sudo apt-get install -y boot-repair && (sudo boot-repair &)
I just selected the "recommended" option in boot-repair.  After doing this, I had to add another boot option as per the instructions - had to add sda1/EFI/ubuntu/grubx64.efi.  Pay attention to what it tells you, as it may not be identical, depending on your partitioning.

Reboot and press ESC on boot to get blue menu, Enter Setup, goto Boot -> Add New Boot Option -> Add boot option and give it a name (i used "ubuntu13.04").  The filesystem was pre-selected for me, the path for the boot option I entered as follows:  fsx:sda1/EFI/ubuntu/grubx64.efi  - have no idea what the fsx: is about, but it was given in the help text.  Scroll down to Create, and press enter.  Press ESC to go back, and then move the newly created boot option to #1 position.  Reboot and enjoy.  Fully functional dual-boot system with Win8 and Ubuntu 13.04.

Why the Ubuntu folks don't learn from the boot-repair folks is really a mystery to me...

NOTE:  I ended up having to delete the Windows 8 boot option in the BIOS, because after booting from grub into Win8 once, it did something to bypass grub.. frikin Windows!

Thursday, March 21, 2013

Upgrading RT 3.6.4 to RT 4.0.10

Request-Tracker (RT) upgrade steps.  This is based on  Please read all related documents and don't just follow this blindly.

Moving from a gentoo linux 2.4 box, RT 3.6.4, mysql 4.0.8 to an ubuntu 12.04 server, RT 4.0.10 and mysql 5.5

Export 3.6.4 Database
On RT 3.6.4 machine as root (obviously must know the root mysql password):
mysqldump -p --opt rt3 > rt3.sql
Copy this file to the new machine.  All further steps are on new machine.

Prepare SQL for Import
You have to edit rt3.sql with vim or sed, and remove all references to "Type=Innodb" (this is default in mysql now), and search for "timestamp(" and remove the bracketed section.. (eg. "timestamp(14)" is now just "timestamp").

Create Database for Import
mysql -p
create database rt4 character set latin1;
grant all on rt4.* to rt_user identified by 'rt_pass';
NOTE: above replace rt_user and rt_pass by the user/password you wish to use for RT.  Also, it may seem counter intuitive to name database rt4, since we are importing rt3 - just remember the end target is 4.0.10.

Import 3.6.4 Database
mysql -p --default-character-set=binary rt4 < rt3.sql
Download/Configure/Install RT 4.0.10

Download RT 4.0.10 source, extract to temp dir, run .configure with needed parameters (see your 3.6.4 install), and basically follow README up to and including "make install".  This should install in /opt/rt4.  Be sure to configure and configure apache2 as needed (beyond scope of this post).

Upgrade Database
From the temp dir used above execute the following:
make upgrade-database
(From 3.6.4 to 3.7.87)
If it fails at 3.7.81, do this:
mysql -p rt4
CREATE INDEX CachedGroupMembers3 on CachedGroupMembers (MemberId, ImmediateParentId);
make upgrade-database
(From 3.7.81 to 3.7.87)
perl etc/upgrade/ rt4 rt_user rt_pass > queries.sql
(again replacing rt_user and rt_pass with user/password you wish to use for RT)
mysql -p rt4 < queries.sql
(this takes about 3 times as long as the initial import!)
mysql -p
alter database rt4 default character set utf8;
make upgrade-database
(From 3.7.87 to 4.0.9)
If it fails at 3.8.2, do this:
mysql -p rt4
drop index groupmembers1 on GroupMembers;
create unique index groupmembers1 on GroupMembers (GroupId,MemberId);
make upgrade-database
(From 3.8.3 to 4.0.9)
perl -I /opt/rt4/local/lib -I /opt/rt4/lib etc/upgrade/
(takes even longer than above query)
perl -I /opt/rt4/local/lib -I /opt/rt4/lib etc/upgrade/
perl etc/upgrade/vulnerable-passwords --fix
Now test, test, test... :)