Posts filed under 'Uncategorized'

Check in Java web app if user is logged in in Rails web app

I have a Rails application where users can log in and do stuff. For one of the actions a user can perform, I actually use a Java web application integrated in the Rails application. Because I don’t want a malicious user that is not logged in to the application to surf directly to the Java application, I need a system where my Java application is only accessible for users logged in to the Rails application. I used a Servlet Filter that contacts the Rails application in the background and asks if the user is logged in. Only then is the user allowed to proceed.

First I built an a controller in Rails with an action that checks if the user is logged in. In my application this is available at the url localhost:3000/session/check.

class SessionController < ApplicationController

def check

if session['user'].nil?

logged_in = false

else

logged_in = true

end

render :text => logged_in.to_s #just write true or false to the output

end

end

package be.vrt.medialab.filters;

Now I want my Java web application to first request the Rails session check and when it returns false it should redirect to the login page instead of serving the Java servlets. I used a Java servlet filter for this job. I created the filter in a separate project, here is the source code:

package be.vrt.medialab.filters;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.net.MalformedURLException;

import java.util.ResourceBundle;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletContext;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

public class RailsAuthentication implements Filter {

FilterConfig filterConfig = null;

private ResourceBundle resources;

public RailsAuthentication() {

resources = ResourceBundle.getBundle(“config”);

}

public boolean getRailsResponse(String urlString,String cookie) {

// Open a URL connection.

java.net.URL url;

try {

System.out.println(“urlString=”+urlString);

url = new java.net.URL( urlString );

final java.net.URLConnection uconn = url.openConnection( );

if ( !(uconn instanceof java.net.HttpURLConnection) )

throw new java.lang.IllegalArgumentException(

“URL protocol must be HTTP.” );

final java.net.HttpURLConnection conn =

(java.net.HttpURLConnection)uconn;

// Set up a request.

conn.setConnectTimeout( 10000 ); // 10 sec

conn.setReadTimeout( 10000 ); // 10 sec

conn.setInstanceFollowRedirects( true );

conn.setRequestProperty( “User-agent”, “spider” );

conn.setRequestProperty(“Cookie”, “_ifip_rails_session=”+cookie+“;”);

// Send the request.

conn.connect( );

BufferedReader in = new BufferedReader( new InputStreamReader((InputStream) conn.getContent( )));

String inputLine;

inputLine = in.readLine(); // Process each line.

System.out.println(“rails returned: “+inputLine);

conn.disconnect( );

if (inputLine.equals(“true”)) {

//authentication successful: user is logged in

System.out.println(“authentication successful!”);

return true;

} else {

//authentication failed: user is not logged in

System.out.println(“authentication failed!”);

return false;

}

} catch (Exception e) {

e.printStackTrace();

}

return false;

}

public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException,ServletException {

String railsCheck =resources.getString(“RailsCheck”);

String invalidUrl=resources.getString(“InvalidUrl”);

HttpServletRequest request = (HttpServletRequest) req;

Cookie[] cookies = request.getCookies();

String rails_session_id = null;

for(int i=0;i<cookies.length;i++) {

Cookie cookie = cookies[i];

if (cookie.getName().equals(“_ifip_rails_session”)) {

rails_session_id = cookie.getValue();

}

}

if (rails_session_id == null) {

//authentication fails

System.out.println(“Autentication fails, no rails session id!”);

} else {

System.out.println(“Rails session id is “+rails_session_id);

//query rails app if this session id is from a logged in user

boolean valid_user =getRailsResponse(railsCheck,rails_session_id);

if (valid_user) {

// pass the request along the filter chain

chain.doFilter(request, response);

} else {

System.out.println(“valid_user=”+valid_user+“, redirecting to /RedirectServlet”);

ServletContext context =filterConfig.getServletContext();

context.getRequestDispatcher(“/RedirectServlet”).forward(request, response);

}

}

}

public void init(FilterConfig fConfig) throwsServletException {

// TODO Auto-generated method stub

filterConfig = fConfig;

}

}


I couldn’t find how to redirect to an external URL directly from within the servlet filter, so I just forwarded to a second servlet that has the sole job of redirecting to a certain URL (the login page):


package be.vrt.medialab;

import java.io.IOException;

import java.util.ResourceBundle;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;


public class RedirectServlet extends HttpServlet {

private static final long serialVersionUID = 1L;

private ResourceBundle resources;

public RedirectServlet() {

super();

resources = ResourceBundle.getBundle(“config”);

}

protected void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {

String invalidUrl=resources.getString(“InvalidUrl”);

response.sendRedirect(invalidUrl);

}


protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException {

String invalidUrl=resources.getString(“InvalidUrl”);

response.sendRedirect(invalidUrl);

}

}

import java.io.BufferedReader;

Now the only thing we have to do is place the classes in our web application and change the web.xml as follows:

<?xml version=“1.0″ encoding=“UTF-8″?>

<web-appxmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”xmlns=“http://java.sun.com/xml/ns/javaee”xmlns:web=“http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”xsi:schemaLocation=“http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd”id=“WebApp_ID” version=“2.5″>

<display-name>IfipUploader</display-name>

<welcome-file-list>

<welcome-file>TestPage.html</welcome-file>

<welcome-file>FormUpload.html</welcome-file>

<welcome-file>index.jsp</welcome-file>

<welcome-file>default.html</welcome-file>

<welcome-file>default.htm</welcome-file>

<welcome-file>default.jsp</welcome-file>

</welcome-file-list>

<filter>

<filter-name>Rails Authentication</filter-name>

<filter-class>be.vrt.medialab.filters.RailsAuthentication</filter-class>

</filter>

<filter-mapping>

<filter-name>Rails Authentication</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

<servlet>

<servlet-name>RedirectServlet</servlet-name>

<display-name>RedirectServlet</display-name>

<description>redirects to InvalidUrl</description>

<servlet-class>be.vrt.medialab.RedirectServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>RedirectServlet</servlet-name>

<url-pattern>/RedirectServlet</url-pattern>

</servlet-mapping>

<servlet>

<description>Extension of abstract class UploadServlet</description>

<display-name>UploadServletWithQueue</display-name>

<servlet-name>UploadServletWithQueue</servlet-name>

<servlet-class>be.vrt.medialab.upload.UploadServletWithQueue</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>UploadServletWithQueue</servlet-name>

<url-pattern>/UploadServletWithQueue</url-pattern>

</servlet-mapping>

</web-app>

import java.io.IOException;

Below are two logs from the Java web application:

Logged out: (the Rails session id is from a previous session and thus invalid)

Rails session id is BAh7CToQX2NzcmZfdG9rZW4iMVUyeFJWWWVzc1hUZFNPRDR2dkFUb3lONVFaQlJrVmsxR1h0VzVaS3RmUFU9Og9zZXNzaW9uX2lkIiUyOTg2NDc2NzY0N2RlMGU1OWExMTFiOTUwMTk0Zjg2MCIQaW5pdGlhbF91cmkiDS9tYW1taWUvIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--41ae001042b16ee26966fc931d11719bc51d7b71
urlString=http://media.ibbt.be/mammie/session/check
rails returned: false
authentication failed!
valid_user=false, redirecting to /RedirectServlet

Logged in:

Rails session id is BAh7CiIJdXNlcm86CVVzZXIHOhZAYXR0cmlidXRlc19jYWNoZXsAOhBAYXR0cmlidXRlc3sdIg5qb2JfdGl0bGUiF1NpdGUgQWRtaW5pc3RyYXRvciIRb2ZmaWNlX3Bob25lMCIPdXBkYXRlZF9hdCIYMjAwOS0xMC0wOCAxMTo1OToxNiIKdGl0bGUiF3NpdGUgYWRtaW5pc3RyYXRvciIYb3JnYW5pc2F0aW9uX3JlZ2lvbjAiDXVzZXJuYW1lIgphZG1pbiIMY291bnRyeSIHQkUiGW9yZ2FuaXNhdGlvbl9hZGRyZXNzMCIHaWQiBjEiHG9yZ2FuaXNhdGlvbl9kZXBhcnRtZW50MCIWb3JnYW5pc2F0aW9uX2NpdHkwIhRhc3Npc3RhbnRfcGhvbmUwIg9maXJzdF9uYW1lIgphZG1pbiITaGFzaGVkX3Bhc3dvcmQiLWI0NzIwODY3MGU2YmU1ODdhNjE1YTcwZDMzZGRkYmVkNmNhMGNiZjAiD29mZmljZV9mYXgwIhFvcmdhbmlzYXRpb24wIg5sYXN0X25hbWUiFnRoZSBhZG1pbmlzdHJhdG9yIhBhZmZpbGlhdGlvbjAiFm9yZ2FuaXNhdGlvbl90eXBlMCIPY3JlYXRlZF9hdCIYMjAwOS0xMC0wOCAxMTo1OToxNiIKZW1haWwiHmthcmVsLmJyYWVja21hbkBnbWFpbC5jb20iEW1vYmlsZV9waG9uZTAiHW9yZ2FuaXNhdGlvbl9wb3N0YWxfY29kZTAiGW9yZ2FuaXNhdGlvbl9jb3VudHJ5MDoPc2Vzc2lvbl9pZCIlMjk4NjQ3Njc2NDdkZTBlNTlhMTExYjk1MDE5NGY4NjA6EF9jc3JmX3Rva2VuIjFVMnhSVlllc3NYVGRTT0Q0dnZBVG95TjVRWkJSa1ZrMUdYdFc1Wkt0ZlBVPSIQaW5pdGlhbF91cmkiDS9tYW1taWUvIgpmbGFzaElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewAGOgpAdXNlZHsA--9857ba6780010c041df44eabbfa5f3943ecbe218
urlString=http://media.ibbt.be/mammie/session/check
rails returned: true
authentication successful!

Add comment October 20, 2009

Jeditable JQuery plugin on Rails

The Jeditable JQuery plugin is an awesome piece of javascript code that allows the users of your webpage to just click some text and edit it in place. So instead of having an “edit” page for your data, you let the user edit directly from the “show” page.

The usage of the plugin is very easy, as explained on their homepage. You just wrap the editable text in a div with class “edit” and add the folowing piece of javascript code:

$(document).ready(function() {
$(‘.edit’).editable(‘http://www.example.com/save.php’);
});
$(document).ready(function() {

     $('.edit').editable('http://www.example.com/save.php');

 });

This will make the text clickable. When the user clicks on it, the text changes to an input field with a submit button, which saves the new data to save.php.

edit_in_place

I wanted to use the Jeditable script in my Rails application, but I ran into some difficulties along the way. After some frustrating digging around I came to the following:

I added an update_field action to my controller that allows changing a single value and returns the value of that field:

  # called after editing an item
  # PUT /items/1
  # PUT /items/1.xml
  def update_field
    @item = Item.find(params[:item][:id])
    dc_ds = params[:item][:dc_ds]
    #read and write the DC datastream...
    @dc_ds = DC_datastream.new(:id => params[:item][:id])
    puts 'params update:'
    pp params

    keys = params[:dc_datastream_solr].keys
    k = keys.first
    #params[:dc_datastream_solr].each_key do |k|
      @dc_ds.send k.to_s+'=',params[:dc_datastream_solr][k]
    #end    

    @dc_ds.save_to_fedora

    render :text => params[:dc_datastream_solr][k]
  end



In the layout of the item we set the javascript AUTH_TOKEN variable so we can correctly set the authenticity token in the requests sent to Rails by JQuery:
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>

And this is the javascript that will work on e.g. <div class=”edit_area” id=”theid” name=”thename” />

//the each is needed because we need to read id and name of each item
$('.edit_area').each(function(i) {
  $(this).editable('./update_field/<%=@item.id%>', {
    type	:	'textarea',
    name	:	$(this).attr('name'),
    id		:	$(this).attr('id'),
    cancel	:	'Cancel',
    submit	:	'OK',
    indicator:	'Saving...',
    tooltip	:	'Click to edit...',
    submitdata:	{_method: "put", "item[id]": "<%=@item.id%>",authenticity_token: AUTH_TOKEN},
    rows:		10
  });
});

I iterate explicitly over all the divs on the page with class edit_area so I can set the name and id of this editable object to the name and id attribute of the respective div’s.

The submitdata line does a few things:

submitdata:	{_method: "put", "item[id]": "<%=@item.id%>",authenticity_token: AUTH_TOKEN},

_method: "put" is Rails' way of simulating an HTTP PUT verb via an HTTP POST. 

"item[id]": "<%=@item.id%>" passes the item's id back to Rails.

authenticity_token: AUTH_TOKEN includes the authenticity token in the request that is sent. 

Add comment October 13, 2009

Webdesign: show content on top of Flash or Silverlight component

I started playing with JQuery last week and used the Boxy plugin to display a dialog window to the user while disabling all other components. In the background it uses CSS’s z-index property to accomplish this. At least.. almost all components, because as you can see in the video below the flash movie kept appearing on top of the Boxy window. In a later test I noticed the same thing happens for Silverlight components.

problem

Here is how to fix it:

Flash

Flash has a “wmode” parameter which you have to set to “opaque” for the z-index style to have an effect. For instance for the Flash JWPlayer:

<script type='text/javascript'> 

	var s1 = new SWFObject('player.swf','IFIPPlayer','400','300','9');

	s1.addParam('allowfullscreen','true');

	s1.addParam('allowscriptaccess','always');

	s1.addParam('flashvars','type=video&file=movie.flv');

	s1.addParam('wmode','opaque');

	s1.write('theplayer');

</script> 

Silverlight

Silverlight has a “windowsless” property which you have to set to ‘true’ for the z-index style to have an effect. For instance for the Silverlight JWPlayer:

<script type=”text/javascript”>
var cnt = document.getElementById(“player_http://ifip.test.ibbt.be/fedora/get/<%=@item.id%>/MAM_lowres”);
var src = ‘<%=ActionController::Base.relative_url_root%>/wmvplayer.xaml’;
var cfg = {
file:’http://ifip.test.ibbt.be/fedora/get/<%=@item.id%>/MAM_original_media’,
image:’http://ifip.test.ibbt.be/fedora/get/<%=@item.id%>/MAM_thumb’,
height:’<%=defined?(@flashplayer_height) ? @flashplayer_height : 300%>’,
width:’<%=defined?(@flashplayer_width) ? @flashplayer_width : 400%>’,
windowless:’true’
};
var ply = new jeroenwijering.Player(cnt,src,cfg);
</script>
<script type="text/javascript"> 

	var cnt = document.getElementById("theplayer");

	var src = '/wmvplayer.xaml';

	var cfg = {

		file:'movie.wmv',

		image:'thumb.jpg',

		height:'300',

		width:'400',

		windowless:'true'

	};

	var ply = new jeroenwijering.Player(cnt,src,cfg);	

</script> 

And a screenshot to prove it :-)

solved

Add comment October 6, 2009

flash 10 on Ubuntu amd_64

230  sudo apt-get remove flashplugin-nonfree flashplugin-installer
231  wget http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.22.87.linux-x86_64.so.tar.gz
232  wget http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz
233  tar xvf libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz
234  sudo mv libflashplayer.so /usr/lib/mozilla/plugins/
Flashplayer 10 is not yet supported by Adobe for amd_64 Linux architectures, but they do have an alpha relase in their labs: http://labs.adobe.com/downloads/flashplayer10.html. Here’s how to install it (Thanks to these guys, only the download url has changed. ).
sudo apt-get remove flashplugin-nonfree flashplugin-installer
wget http://download.macromedia.com/pub/labs/flashplayer10/libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz
tar xvf libflashplayer-10.0.32.18.linux-x86_64.so.tar.gz 
sudo mv libflashplayer.so /usr/lib/mozilla/plugins/

Add comment October 2, 2009

Watching DVB-T television on my Ubuntu

As mentioned in the edit of my previous post, I got my DVB-T stick working without any big problems. Nevertheless here are the steps I took to get it fully working! The DVB-T stick is a Pinacle 72e dvb-t tuner usb stick.

1. Use Kaffeine in the beginning. It is the simplest DVB-T player. Scan for channels and play, that’s it.

2. Then I followed this guide to get MythTV working. MythTV is a more advanced mediaplayer than Kaffeine. It is especially good in working with TV capture cards and everything related (timeshifting, recording, pausing, …). It can even work with several capture cards. The disadvantage is that the configuration is a bit counterintuitive.. (but with the guide in your hands you’ll be safe)

3. I got a problem with my audio-jack, when I plugged in my speakers or a headphone, nothing happened. I used these steps to solve the problem.

4. You can select MythTV to run on a second display in the setup (select screen “1″ instead of screen “0″).

5. My EPG (program guide) took the longest time to setup. The best way to go depends on the country in which you live. I live in Belgium and found the following approach to work well:

177  sudo apt-get install libc6-i386
178  sudo apt-get install lib32nss-mdns
179  mkdir ~/mc2xml
180  cd /home/karel/mc2xml/
181  wget http://mc2xml.110mb.com/?h=o9wxhzm
182  ls
183  rm index.html\?h\=o9wxhzm
184  ls
185  chmod 755 mc2xml
186  sudo ./mc2xml -c us -g 10000
187  sudo ./mc2xml -c be -g 9000 -o xmltv.xml
188  ls
189  cat xmltv.xml
190  sudo ./mc2xml -c be -g 9000 -o xmltv.xml
191  sh myth_script.sh
192  ls
193  sudo sh myth_script.sh
sudo apt-get install libc6-i386
sudo apt-get install lib32nss-mdns
mkdir ~/mc2xml
cd /home/karel/mc2xml/
–> download mc2xml from http://mc2xml.110mb.com/ and save it in the created folder
chmod 755 mc2xml
sudo ./mc2xml -c be -g 9000 -o xmltv.xml
Then I used the script from this site to convert the channel names to something more readable and fill the MythTV database. My replacements file looks like this:
I203250.750821.microsoft.com/een
I217250.750822.microsoft.com/ketnet-canvas
Make sure you change the “xml tv channel id” in MythTV backend channel editor to the same one you selected in the replacements file (e.g., “een” or “ketnet-canvas”). Now everything should work and MythTV should show the program guide:
mythtv
tvinfo
Note that MythTV even shows the channel icons, which I find really cool (even MediaCenter couldn’t do that).

2 comments September 25, 2009

Switched to Ubuntu!

My laptop was getting on my nerves again, acting slow and dodgy (even though I formatted it only a few months ago). I was feeling adventurous and decided to kick my Windows out of the hard drive and install Linux on it! Asking my friend Bert what is the best Linux distribution in his opinion, I was pointed at Ubuntu. So Ubuntu it is :-)

6109ubuntu_logo

Not a day after deciding to clean up the computer I am happily using my Ubuntu. And the cool part is I can just keep using my favourite applications:

  • Pidgin chat client is included in Ubuntu by default
  • Virtualbox has a linux version. This will also allow me to run Windows in case I get homesick ;-)
  • Dropbox for sharing my files between work and home
  • Xmind for creating mind maps and notes
  • Google Chrome (although it is not already stable, f.i. the security features don’t work yet)
  • Evernote (using Wine, a Linux app that allows you to install and run Windows applications)

I’m a bit afraid of my more exotic hardware (dvb-t stick, PIC development board, …) but haven’t tried it yet.. But very positive so far!

edit: I got my DVB-T stick working without problems :-) . It’s a Pinacle 72e stick, and it is natively supported by Ubuntu. I used Kaffeine player to first test it and it found all my channels without problems. Than I got things working in MythTV using this guide.

Add comment September 10, 2009

SuSe Yast hangs due to offline repositories

I had to install a package using Yast today, but every time I started the software management in Yast it froze, displaying ‘Downloading files’. After some digging around (I am no Linux expert), I found out Suse couldn’t find the package repositories that were configured on the machine.

I added some repositories by duplicating the files in /var/lib/zypp/db/sources and editing their URL and alias with vi. When querying zypper for the repositories they showed up immediately:

machine:/var/lib/zypp/db/sources # zypper sl

# | Enabled | Refresh | Type | Name                                     | URI

--+---------+---------+------+------------------------------------------+-----------------------------------------------------------------

1 | Yes     | Yes     | YaST | SUSE Linux Official Repo Open source     | http://download.opensuse.org/distribution/10.3/repo/oss/

2 | Yes     | Yes     | YaST | SUSE Linux Official Repo Non Open source | http://download.opensuse.org/distribution/10.3/repo/non-oss/

4 | Yes     | Yes     | YaST | SUSE LINUX 10.1                          | http://opensuse.hro.nl/opensuse/distribution/SL-10.1/inst-source
cp a727c04ccf8bec4dcfd5d093571e8abb nonopensour
When I opened the Software Management section in Yast now, it started downloading the files.

Add comment September 7, 2009

Free GPS tracker on handheld / pocket pc

I hacked my Medion GPS a few months ago so I could add other programs on the device using instructions from this site. But a simple application that I really wanted but just could not find was a GPS tracker, a program that logs your coordinates to a file. Last week I picked up my Medion again determined to find the missing application, and I found it :-)

The hacked gps with Windows CE desktop

The hacked gps with Windows CE desktop

The program gives information about the available GPS satelites

The program gives information about the available GPS satelites

The application is called NMEA Monitor CE and can be downloaded for free over here. For my Medion 95058 device (PNA150 model with Win CE 4.2) I needed the ARM H/PC Pro2.11 H/PC2000 download. Just copy the file to your device and run it over there.

Go to Option>Preferences and select your GPS’s COM port (on my Medion it is COM port 2). Then select File>save as and create a *.NME file. Now your coordinates are logged in NMEA format, so put that GPS in your backpack and go cycling for a while!

Once you come back all tired and sweaty you’ll want to check out the route you have cycled so copy the .NME file over to your pc. Now you’ll have to convert it to the *.kml format so you can view the route in Google Earth.

You can use GPSBabel, an open source program available at http://www.gpsbabel.org/download.html for this conversion.

The following screenshots show you the settings for converting the NME file to a kml file:

1

The Filter button reveals some other options (which you can ignore safely for now):

93f0a17845415e22fec495dd91b12658

Click on “let’s go” and your kml file is generated. Open the file in Google Earth and you’ll get a nice view of the track! Sidenote: The new Google Earth appears to have a cool time slider which makes it handy to view where your were at what time.

The route in Google Earth

The route in Google Earth

If you know of other handy free tools that run on a handheld pc (especially gps-related tools), let me know in the comments!

Add comment May 27, 2009

Getting started with Fedora Repository

I recently had to get started with the Fedora Repository. Because the Fedora Commons site is somewhat chaotic, and a quickstart is hard to find online, I’ll write the basic steps in getting a Fedora Repository up and running here. 

fedora_commons

What is it?

First of all, the Fedora Repository has nothing to do with the famous Linux distro (there actually was some dispute over the trademark). Fedora Repository is an open source digital repository management system, originating at the Cornell University in 1998 and open source since 2003. The current release is Fedora 3.2. 

The repository is meant to store (or link to) digital assets (images, video, audio, … anything really) and their related metadata. For example, I am using Fedora as a repository for video files. The video files are available in different formats (high resolution, low resolution flash video, …) and there is an XML file per video describing the video contents. 

This article describes the setup of the repository, the data model Fedora uses, and how to interact with the repository using Java and Ruby.

Installation

First download the latest version of Fedora from their site (go to Developers > Downloads). As mentioned before, the current release is fedora-installer-3.2.jar. When installing you can choose between the quick and the custom installation. Choose the latter, because we want to enable the REST interface. Go to the download location in your terminal and type

java -jar fedora-installer-3.2.jar

to start the installation process. The default options are ok except that you should enable the REST api. More information on the installation is available here.

Fedora comes runs inside a tomcat server. After installation you can start Fedora by going to fedora_home/tomcat/bin and typing in a command line (Linux / Mac)

sh catalina.sh run

or (Windows)

startup.bat

You should see some messages that indicate that tomcat is starting up and that Fedora is being deployed and the final message should say something like “server startup complete”. Now you can fire up your browser and surf to http://localhost:8080/fedora. If everything went well, an ugly page showing some info about Apache Axis.

The Fedora data model

A Fedora object contains several datastreams

A Fedora object contains several datastreams

The image on the right shows a Fedora object. It has a unique ID called the PID (persistent ID) and some other properties. A Fedora object also contains so-called datastreams. These contain the actual data. This data can be the essence (e.g., the video material) or the metadata about this essence (e.g., an XML file with descriptions). 

Fedora has some default datastreams (RELS-EXT, DC and AUDIT), and the user can add as many other datastreams as necessary. So what do these default datastreams contain?

  • The RELS-EXT datastream contains the relationships to other objects in the repository. This can for example contain a relationship “is part of” that states that this object is part of another object (e.g. a collection “news videos”).
  • The DC datastream contains Dublin Core metadata about the object. Dublin Core is a metadatastandard with some basic fields (like title, author etc.), so this stream is a basic description of the object’s contents.
  • The AUDIT datastream contains the history of actions performed on the object.
  • The other datastreams could contain the different versions of a video file (High resolution version, low resolution, audio channels, …). Datastreams can also contain more metadata (e.g., a NewsML XML file).

You can find more information about the datastreams in tutorial 1 on the Fedora site.

Fedora offers a number of cool features, like versioning datastreams (so you can go back to a previous version of a datastream, e.g. when someone messed up the metadata describing a videofile). It is also possible to define transformations of your datastream using webservices. If you have for example a webservice that can convert an image to grayscale, you could couple this to Fedora and it would be like your object had an extra datastream that contained the grayscale version, but actually when this datastream is called a grayscale version would be created on the fly. 

Adding your first objects

The best way to get started with Fedora is using the client administrator program that is included in the installation (fedora_home/client/bin/fedora-admin). 

This is explained in tutorial2 on the Fedora site: tutorial2, so I won’t go into detail. You really should follow this tutorial as it gives a good overview of Fedora’s possibilities. The image below shows a screenshot of the application:

The Fedora Administrator application

The Fedora Administrator application

With the application you can add new objects to Fedora. 

Connecting to Fedora with Ruby

ruby_logo

The Fedora repository exposes two types of interfaces to the outside world: a SOAP API and a REST API. The latter is the simplest and we’ll start with it to demonstrate access from within a Ruby script to Fedora. 

The guys at http://www.yourmediashelf.com/ have created two Ruby gems for communication with Fedora: RubyFedora and ActiveFedora (homepage). RubyFedora is a Ruby wrapper around the Fedora REST interface and is the gem we’ll be using in this paragraph. ActiveFedora tries to provide an ActiveRecord-like experience when using Fedora from Ruby, I haven’t tested this gem yet. 

Start by installing the RubyFedora gem:

gem install ruby-fedora

Use the following Ruby script (fill in your username, e.g., fedoraAdmin, and password in the repository url) to create a new object, save it and find it back:

#!/usr/local/bin/ruby
require 'ruby-fedora'
repository = Fedora::Repository.register('http://user:pass@localhost:8080/fedora')
test_object = Fedora::FedoraObject.new(:label => 'honolulu', :contentModel => 'Image', :state => 'A', :o wnerID => 'fedoraAdmin')
repository.save(test_object)
objects = repository.find_objects('label~Image*')
object = repository.fetch_content('demo:1')

(The last line will result in an error if a file with pid equal to demo:1 does not exist)

The following is a more elaborate example that will print some of the object’s fields and will also print some of the fields of the Dublin Core datastream:

#!/usr/local/bin/ruby
require ‘ruby-fedora’
require ‘rexml/document’
#connect to the repository
repository = Fedora::Repository.register(‘http://fedoraAdmin:test@localhost:8080/fedora’)
#create a new object
test_object = Fedora::FedoraObject.new(:label => ‘blublub’, :contentModel => ‘Video’, :state => ‘A’, :o wnerID => ‘fedoraAdmin’)
#save the object
repository.save(test_object)
#find objects with pid video* (e.g., “video:1″ / “video:2″ / … )
vids = repository.find_objects(‘pid~video*’) 
vids.each { |video|
  #print this item’s fields
  puts video.pid.to_s     + “\n******************\n”
  puts “create_date … ” + video.create_date.to_s      + “\n”
  puts “modified_date … ” + video.modified_date.to_s       + “\n”
  puts “state … ” + video.state.to_s     + “\n”
  puts “label … ” + video.label.to_s     + “\n”
  puts “owner_id … ” + video.owner_id.to_s     + “\n”
#  puts “profile … ” + video.profile.to_s     + “\n”
  
  #extract Dublin Core datastream
  xml_data = video.object_xml
  doc = REXML::Document.new(xml_data)
  root = doc.root
  dc_field = root.elements["foxml:datastream[@ID='DC']/foxml:datastreamVersion/foxml:xmlContent/oai_dc:dc”]
  puts “\n” + dc_field.elements["dc:identifier"].text + ” => ” + dc_field.elements["dc:title"].text
}
#!/usr/local/bin/ruby
require 'ruby-fedora'
require 'rexml/document'
#connect to the repository
repository = Fedora::Repository.register('http://fedoraAdmin:test@localhost:8080/fedora')
#create a new object
test_object = Fedora::FedoraObject.new(:label => 'blublub', :contentModel => 'Video', :state => 'A', :o wnerID => 'fedoraAdmin')
#save the object
repository.save(test_object)
#find objects with pid video* (e.g., "video:1" / "video:2" / ... )
vids = repository.find_objects('pid~video*') 
vids.each { |video|
  #print this item's fields
  puts video.pid.to_s     + "\n******************\n"
  puts "create_date ... " + video.create_date.to_s      + "\n"
  puts "modified_date ... " + video.modified_date.to_s       + "\n"
  puts "state ... " + video.state.to_s     + "\n"
  puts "label ... " + video.label.to_s     + "\n"
  puts "owner_id ... " + video.owner_id.to_s     + "\n"
  #puts "profile ... " + video.profile.to_s     + "\n"
  #extract Dublin Core datastream
  xml_data = video.object_xml
  doc = REXML::Document.new(xml_data)
  root = doc.root
  dc_field = root.elements["foxml:datastream[@ID='DC']/foxml:datastreamVersion/foxml:xmlContent/oai_dc:dc"]
  puts "\n" + dc_field.elements["dc:identifier"].text + " => " + dc_field.elements["dc:title"].text
}

Connecting to Fedora with Java

296946221_6ef6d4e99b

(Duke image taken from here). The Fedora installation comes with a client demo illustrating some of the things you can do with the SOAP interface. It is located at Fedora_Home\client\demo\soapclient. To create a project in Eclipse with this code, start up Eclipse and add the following libraries to your build path: fedora_home/client/fedora-client-3.1.jar and everything in fedora_home/client/lib/. Add the DemoSOAPClient.java file to your project and use the functions in it in your own code. For example, the following code will add an item to Fedora based from a FOXML file.

 

 

public static void addToFedora(String filename,long theID) {
//FEDORA REPO
DemoSOAPClient caller;
try {
	caller = new DemoSOAPClient("http", "localhost", 8080, "fedoraAdmin", "test");
	//RepositoryInfo repoinfo = caller.describeRepository();
	//delete item if it exists
	String purgeDate=null;
	try {
		purgeDate = caller.purgeObject(
			"id:"+theID, // the object pid
			"purge object", // an optional log message about the change
			 false);  // do not force changes that break ref integrity
	} catch (Exception e) {
		//System.out.println("Hack...just ignore failures since objects may not exist yet." + e.getMessage());
	}

	//add the item to Fedora
	FileInputStream inStream=null;
	String ingestPID=null;
	File ingestFile=new File(filename);
	try {
		inStream=new FileInputStream(ingestFile);
	} catch (IOException ioe) {
		System.out.println("Error on ingest file inputstream: " + ioe.getMessage());
		ioe.printStackTrace();
	}
	System.out.println(" - ingest FoXML in Fedora");
	try {
	        ingestPID = caller.ingest(inStream, fedora.common.Constants.FOXML1_1.uri, "ingest of item");
	} catch (IOException ee1) {
		System.out.println("Error during ingest: "+ee1.getMessage());
		//ee1.printStackTrace();
	}
	//System.out.println("Finished test ingest of sdef object: " + ingestPID);
} catch (Exception e1) {
	// TODO Auto-generated catch block
	e1.printStackTrace();
}
}

That’s it for this Fedora introduction!

10 comments May 24, 2009

Poor man’s virtualization (a rich experience!)

As computers are becoming more and more powerful, a mere laptop is able to virtualize complete computer systems. With technology like VMWare and Sun’s Virtualbox one can create so-called virtual machines that have an entirely different setup (hardware / operating system) than the host system. As I am finding myself using virtualization more and more, I decided to write an article about it. I won’t be giving an in depth overview of all available technologies and setup tricks, but an overview of how I am using it today. Furthermore, this article will only focus on freely available virtualization software.

A microcontroller development station (Virtualbox)

When looking for a free solution, Virtualbox is the obvious choice as it is available as open source software (GNU GPL) . Just download it from their site (it is available for a myriad of host systems: Win/Linux/Mac/Solaris) and install it to your computer.

virtualbox

I have recently formated my laptop and I am intending to keep it clean and uncluttered for a while. That’s why I decided to put all software and tools needed for my microcontroller activities in a dedicated virtual machine.

The setup:

The host system is my personal laptop I bought a year ago (core 2 duo 2GHz, 2GB RAM, Windows Vista). The guest operating system is a Windows XP machine. I chose XP because it runs faster than Vista and I didn’t need any of the Vista features. Make sure you install the Virtualbox guest tools on your guest system for optimal performance.

The bright side:

  • No polluting of my host environment by all the software needed for my PIC (that’s the microcontroller) programming, as it is contained in the virtual machine: compiler, two IDE’s (Eclipse and MPLAB), programming tools, …
  • All my projects and documentation (datasheets, user guides, …) are available in the virtual machine.
  • I can backup the virtual machine so the software setup and my projects are safe.
  • When I have to format my host environment again, I won’t have to reinstall all the microcontroller software and find my projects back. I’ll just have to reinstall Virtualbox and put the virtual machine back.
  • I only have time in my weekends for this microcontroller hobby. At the end of my weekend I just save the state of my virtual machine (I just leave all windows open) and at the beginning of the next weekend I can pick up exactly where I left off!
  • I usually work with a dual monitor setup (laptop screen + external monitor). It is possible to put the Virtual machine on one monitor and on the other monitor just work in the host operating system.
  • A shared folder allows to share files between the host and guest system.
  • My host is a Vista machine, but it could as well have been a Linux OS, thus giving a solution to hardcore Linux users wanting to program PICs (the Microchip compiler is not available on Linux).

The dark side:

  • As everything is virtualized, things tend to run a tad slower. I don’t find this annoying while developing (it doesn’t require a fast PC), but you wouldn’t want to run games in a virtual machine!
  • For the actual programming of a PIC microcontroller, I use a USB device. It is possible to forward the USB device to the virtual machine so it is recognized over there, but I found this to be rather buggy in Virtualbox (it crashed a few times). So for the actual programming I still use the host system.

Conclusion:

Virtualbox is really, really cool software. I almost can’t believe something like this is just available as open source software. It is ideal for quickly testing some new software / platform or for separating a certain environment from the rest of your system (as I did for my microcontroller environment).

A research platform (VMWare server)

At work we are constantly testing new setups and trying out new technologies. We also have some powerfull servers, but we prefer to do our tests in a vacuum environment (not influenced by other installed components we might not have thought about). That’s why we decided to put VMWare on our server and run our little test setups inside Virtual Machines.

vmware-logo

VMWare offers a lot of products, most of which are paying solutions. They do however offer a free player and a free server virtualization product: VMware Server. The player can be used to run an existing virtual machine on your desktop machine. Vmware Server is a very powerfull solution for creating / managing / running virtual machines on the server. Creating virtual machines is done in a browser application which is really handy. By installing the VMware console plugin one can remotely take over the screen of a virtual machine and run it as you would run a local virtual machine.

The setup:

The actual installation is described over here by my colleague. We installed VMware Server on a Linux host system (2 quad cores and 32GB RAM) [sidenote: I think VMWare Server can only be installed on a Linux host]. Once installed you can open up Firefox on your client computer and point it to port 8333 of your host computer. You should see a login screen. I advise you to use Firefox2 Portable because the console plugin doesn’t work too good with Firefox3. Below are some screenshots of the browser application:

Overview of the available virtual machines and used resources

Overview of the available virtual machines and details of one of them

Creating a new virtual machine

Creating a new virtual machine

Remotely taking over a virtual machine

Remotely taking over a virtual machine

More setup goodness:

I’m not going into details about the actual setup but I’ll give some pointers to what is possible:

  • Configure the dhcp to asssign static IP adresses to your virtual machines. Put an apache http server on your host machine and use proxypass / proxypassreverse / virtualhost to forward a browser to a virtual machine. I.e., we can point the client browser to a url like http://hudson.dunamis, our client host file says that hudson.dunamis is found at the IP adress of our host system so our call is forwarded to the host. The apache http server on the host system has a configuration that says that hudson.dunamis  is to be forwarded to the local IP of the virtual machine to a certain port. So the client is immediately forwarded to the virtual machine, as if it is connected to the actual network.
    [sidenote: you could also use the bridged network setup of VMware for this, but this wasn't possible in our setup]
  • In this way you can also forward your ssh access: checkout jedi.

The bright side:

  • Once set up, it becomes very easy to create new machines. By copying the vmdk (=virtual harddrive) of another machine you can skip the installation of the operating system and focus on what you really want to test.
  • The different machines can access each other via the network so complex setups are possible.
  • It is possible to copy and paste virtual machines. E.g. you can also create virtual machines locally using VMware Desktop (this is a paying solution) and copy them later to the server. You can also grab a machine from the server and play it locally using VMware player.
  • You can make a snapshot (or just copy) virtual machines so you can return to a certain state later.

The dark side:

  • Because we have to work with the NAT networking setup, it is sometimes difficult to get things running that have to communicate with machines outside the virtual domain..

Conclusion:

This is ideal for a research environment where you have to test all sorts of different setups. Creating and deleting virtual machines is really easy and succesful setups can be copied so you can always return to them.

Add comment April 24, 2009

Previous Posts


Tags

18F4455 ADC asp autoIt boot bootloader CDT com port computer problem continuous_integration dll eclipse embedded evernote flash frapps java launchy Linux m2eclipse Matlab maven microchip microcontroller network php PIC PIC18F PIC18F4455 productivity programming rails robot scope serial servo silverlight software subclipse svn tutorial ubuntu uC usb webdesign

Feeds

Top Posts

Articles to be written…

Pages

 

November 2009
M T W T F S S
« Oct    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Archives

Blogroll

Meta