Archive for Software

Selenium and the Permission denied to get property Location.href problem

SeleniumI came across a strange behaviour of Selenium and wanted to share my pain with someone really. But first couple of words of introduction. I use Selenium in my current webapp project which I am working on. The application uses quite a lot of javascript (Dojo framework mostly) which can be tested using D.O.H. framework but the Selenium is giving us the final sanity checks, acts as integration test framework and may be used by product owner in an agile environment to drive acceptance on user stories via automated acceptance tests.

Selenium is an excellent package. I really love it. Just to mention integration with various browsers, Selenium IDE, support for integration with build (Selenese ant task) and really easy way of creating and storing the tests as HTML. It is a framework which cannot be ignored by anyone working on webinterfaces.

There is previously mentioned selenese ant task which helps with integration of the Selenium tests and an ant build. You can grab the jar from the Selenium RC distribution.

However as most of the things around us it is not a perfect software. Anyone had the famous “Permission denied to get property Location.href”? Cross domain scripting issues?
In my case I figure out two reasons for above problem and I wanted to share it:

Problem 1:

Let’s look at the following selenium command:

  • open
  • http://host/some/url

Looks good, doesn’t it? So it might work, but it can as well break on another box with the “Permission denied to get property” and some other scary warnings. The solution in this case was simply to remove the host definition from url leaving just:

  • open
  • /some/url

Problem 2:

One of the pages I was testing had redirection in case of the authorization violation. So esentially after single HTTP request the browser was receiving single response with redirection and then performed another request to the URL defined in the redirection. Selenium couldn’t handle that correctly. But again, it wasn’t deterministic, it could work on one box but fail on another. Timing issues etc. Hate that. Neither of the combinations worked in consistent way: openAndWait, open + pause.

The solution in this case required change in the webapp to remove usage of the redirection (which I believe was an ugly way of dealing with the problem anyway).

Hope it will help someone with similar issues. If you know another tricks or something to avoid when using Selenium please contact me or leave a comment here.

Popularity: 65% [?]

Comments (4)

How to use Java Web21c SDK from Scala

It is an example how to use the Web21c SDK from a Scala application.

First couple of words about Scala. Scala was created in 2001 at the École Polytechnique Fédérale de Lausanne (EPFL) in Switzerland. It is platform independent, multi-paradigm language which integrates features of object-oriented and functional programming, is type-safe (but you don’t have to define redundant types of information) and extensible (good candidate for DSLs). It brings a lot of very nice syntactical sugar as well! As Scala smoothly integrates with Java and .Net worlds we can run Scala applications on JVM or .NET CLR and easily reuse existing libraries for those platforms.

One of those libraries is Web21c SDK which gives us easy way of integrating communication services and comes in couple of flavours: SDK for Java, .Net, Python and PHP. We could integrate Scala with Java or .NET SDK but for the purpose of this example we will see how easy it is to incorporate Java SDK into our Scala application.

Let’s assume we use Scala plugin for Eclipse and we created a new Scala project.

We can get the latest Web21c SDK for Java and before proceeding to next steps we have to register our application and obtain own certificate for sandbox server which is free. Then we will create two folders: lib and resources in our project and we will unzip content of the Web21C-JavaSDK-5.0.zip and copy content of the lib folder from SDK to our lib folder. Let’s copy the Web21C-JavaSDK-5.0.jar there as well. We will copy previously obtained certificate to the resources folder and we will create a properties file called security.properties where you can store name of your cert and its password:

org.apache.ws.security.crypto.provider=com.bt.security.PKCS12Crypto
org.apache.ws.security.crypto.merlin.keystore.type=pkcs12
org.apache.ws.security.crypto.merlin.keystore.password=YOUR_CERTIFICATE_PASSWORD
org.apache.ws.security.crypto.merlin.alias.password=YOUR_CERTIFICATE_PASSWORD
org.apache.ws.security.crypto.merlin.file=YOUR_CERTIFICATE.pfx

constants.provider=com.bt.sdk.common.SandboxConstants

Next from Eclipse in the project Properties/Java Build Path/Source/Add Folder… we will add resources folder to the classpath and all jars from lib folder to the Properties/Java Build Path/Libraries/Add JARs… to place them on the classpath as well. We should be good to go.

Then we will create the Scala singleton where we will use directly Java objects. For example Manager classes for one of the Web21c services, for instance One Way Messaging to create a simple sms client (src/SmsClient.scala):

import com.bt.sdk.capabilities.messaging.oneway.MessagingOneWayManager

object SmsClient {
    def main(args: Array[String]) {
        new MessagingOneWayManager().sendMessage("tel:44xxxxxxxxx", "Hello World")
    }
}

Or even simpler:

import com.bt.sdk.capabilities.messaging.oneway.MessagingOneWayManager

object SmsClient extends Application {
    new MessagingOneWayManager().sendMessage("tel:44xxxxxxxxx", "Hello World")
}

Is that close to the famous “one line of code”?

Our project’s structure should look more or less like:

+ Web21cAndScala
    L---+ src
        L--- Web21c.scala
    L---+ bin
        L--- //compiled classes
    L---+ lib
        L--- Web21C-JavaSDK-5.0.jar
        L--- //other jars from lib folder
    L---+ resources
        L--- sandbox.pfx
        L--- security.properties

We are ready to try if it works. Try Run As… Scala Application. Great if it works! If you get following error:

Exception in thread "main" Reporting Service: Unknown
com.bt.sdk.ServiceException: Unknown exception encountered: java.lang.ExceptionInInitializerError
null
    at com.bt.sdk.capabilities.messaging.oneway.MessagingOneWayManager.<init>(MessagingOneWayManager.java:26)
    at SmsClient$.main(SmsClient.scala:7)
    at SmsClient.main(SmsClient.scala)

Then it means that folks from Lausanne haven’t fixed the bug in Scala Eclipse Plugin yet. It simply doesn’t copy resources on the classpath to the output folder (bin) and the Web21c Java SDK can’t see security.properties and the certificate. For purposes of this exercise you can simply copy content of the resources folder to the bin folder. As hot fix you could also create an ant task similar to the one below. You can make the execution of one or more targets from an Ant build part of the normal build of your project:

<?xml version="1.0" encoding="UTF-8"?>
<project name="copyprops" default="default" >
    <target name="default" >
        <copy todir="${basedir}/bin">
            <fileset dir="${basedir}/src" includes="**/*.*" excludes="**/*.scala"/>
        </copy>
    </target>
</project>

I know that it is very simple demo but I hope it will be of any use for someone. Let me know if you are having any issues with the sample. And remember that Sandbox Usage is restricted.

Popularity: 65% [?]

Comments

Lookout search plugin and Outlook 2007

LookoutIf you have to use Outlook I believe you deserve better search features than the features available for you by default. Many of you know the great search plugin Lookout. However after migrating to Outlook 2007 I was unable to successfuly install and use it. Instead after restarting Outlook I got error message:

Sorry! It looks like another Outlook Plugin has installed an unofficial version of the Outlook libraries which breaks Lookout. Lookout will not be able to load. […].

But it looks like there is a way to install Lookout on Outlook 2007. After closing Outlook run from command line:

cd  %SYSTEMROOT%\assembly\GAC

rename Microsoft.Office.Interop.Outlook Microsoft.Office.Interop.Outlook.OLD

type nul > Microsoft.Office.Interop.Outlook

rename Policy.11.0.Microsoft.Office.Interop.Outlook Policy.11.0.Microsoft.Office.Interop.Outlook.OLD

After restarting Outlook everything should work. Don’t blame me if it doesn’t. But in case it doesn’t you can revert changes executing following commands:

cd  %SYSTEMROOT%\assembly\GAC

rename Policy.11.0.Microsoft.Office.Interop.Outlook.OLD Policy.11.0.Microsoft.Office.Interop.Outlook

del Microsoft.Office.Interop.Outlook

rename Microsoft.Office.Interop.Outlook.OLD Microsoft.Office.Interop.Outlook

Hope it helps!

Popularity: 75% [?]

Comments (6)

How to verify digital signatures of XML documents without WSE3

Joshua Watkins, Piotr Woloszyn

Just before Christmas Josh Watkins and me had to face the interesting task of removing the dependency on Microsoft Web Services Enhancements (WSE) 3.0 in one of the projects that we are working on currently. The task consisted of two parts: signing the soap requests and validating incoming soap responses. Thanks to Robbie’s spike for signing requests we managed to quickly finish the first task. I might blog about this as well soon. The second one is a different story. As this turned out to be a pain in the butt and we couldn’t find easily comprehensive information about verifying XML’s digital signatures on the web we decided to share our finding with wider audience and hopefully help someone who has to face the same challenge. Alors…

Josh: I would just like to add that it was a really really … really big pain in the butt.

XML digital signatures (XMLDSIG) allow you to verify that data was not altered after it was signed. Working in the Microsoft .NET 2.0 world it wouldn’t be difficult as we could use the SignedXml class as described here:

// Verify the signature of an XML file against an asymmetric

// algorithm and return the result.

public static Boolean VerifyXml(XmlDocument Doc, RSA Key)

{
    // Create a new SignedXml object and pass it
    // the XML document class.
    SignedXml signedXml = new SignedXml(Doc);    // Find the "Signature" node and create a new

    // XmlNodeList object.
    XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

    // Load the first <signature> node.
    signedXml.LoadXml((XmlElement)nodeList[0]);

    // Check the signature and return the result.
    return signedXml.CheckSignature(Key);
}

Unfortunately the signed soap responses were hashed with SHA256 algorithm defined as:

<signaturemethod algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256">

And that algorithm is unsupported:

With the 2.0 release of the CLR, there is no way to use the RSA-SHA256 signature type with SignedXml. Adding a SHA-256 CryptoServiceProivder implemenation is high on our list of items to look at in the next version, which should enable this scenario.

- Shawn Farkas, Microsoft, 09/09/2007

Josh: When we first tried using the SignedXML method we would get a malformed Reference Element error (or something like that). Which as you can imagine, isn’t really all that helpful or descriptive.

The only available option was to verify the signature manually. Before we will get to details how to do it let’s look at the XML of the SOAP response coming back to us. As we can see there is Signature element which has the children SignedInfo and SignatureValue. SignedInfo holds information about which parts of the message have been signed, with which algorithm, and the hash of the signed element. No one will be able to tamper with the content of the nodes (in this example we sign soap:Body, wsu:Timestamp, wsse:BinarySecurityToken) without being detected through varying hash values. The SignatureValue is the content of the SignedInfo node hashed and signed with the private key of sender, so we can trust the content of that node as well. The whole problem is in the step which has to be performed before hashing: Canonicalization of the XML. Getting the process right for c14n was the most time consuming part.

Now more details and some code. Let’s assume that we implement System.Web.Services.Protocols.SoapExtension and will verify the message in overriden ProcessMessage(SoapMessage message) method, stage SoapMessageStage.BeforeDeserialize. Let’s assume as well that we have the content of the soap message as string (messageContent). To verify the digital signature of an XML document:

1. Create XmlDocument using the messageContent:

XmlDocument xDoc = new XmlDocument();

xDoc.PreserveWhitespace = false;

xDoc.LoadXml(messageContent);

2. Load the server certificate from file system:

X509Certificate2 serverCertificate = new X509Certificate2(pathToServerCert);

3. Now let’s validate message signature. Move to SignatureValue node using the lovely XPathNavigator:

XPathNavigator nav = xDoc.CreateNavigator();

nav.MoveToFollowing("SignatureValue", "http://www.w3.org/2000/09/xmldsig#");

4. The signature value requires that all of the \n inserted into the value are removed before we processed it:

string signatureValue = Regex.Replace(nav.InnerXml.Trim(), @"\s", "");

5. The signature value is saved in the messages encoded in base64. Therefore to get the actual signature value we have to convert back from base64:

byte[] sigVal = Convert.FromBase64String(signatureValue);

6. The SignedInfo XML block is extracted from the greater document. Then we take out all of the namespaces used in all of the parent nodes of SignedInfo and then reinsert them into the SignedInfo block. Without this your validation will FAIL.

Josh: And our validation did indeed fail every time without this. J

XmlNode signedInfo = xDoc.GetElementsByTagName("ds:SignedInfo")[0];
Hashtable ns = RetrieveNameSpaces((XmlElement)signedInfo);
InsertNamespacesIntoElement(ns, (XmlElement)signedInfo);

where:

public static Hashtable RetrieveNameSpaces(XmlElement xEle)
{
    Hashtable foundNamespaces = new Hashtable();
    XmlNode currentNode = xEle;
    string name = null;

    while (currentNode !=null)
    {
        //add namespace for current nodes namespace if it has one.
        if (currentNode.NodeType == XmlNodeType.Element && !String.IsNullOrEmpty(currentNode.Prefix))
        {
            if (!foundNamespaces.ContainsKey("xmlns:" + currentNode.Prefix))
            {
                foundNamespaces.Add("xmlns:" + currentNode.Prefix, currentNode.NamespaceURI);
            }
        }

        //now we add namespaces for any attributes that this node may have.
        if (currentNode.Attributes !=null && currentNode.Attributes.Count>0)
        {
            for (int i=0; i< currentNode.Attributes.Count;i++)
            {
                if (currentNode.Attributes[i].Prefix.Equals("xmlns") || currentNode.Attributes[i].Name.Equals("xmlns"))
                {
                    if (!foundNamespaces.ContainsKey(currentNode.Attributes[i].Name))
                    {
                        foundNamespaces.Add(currentNode.Attributes[i].Name, currentNode.Attributes[i].Value);
                    }
                }
            }
        }
        currentNode = currentNode.ParentNode;
    }
    return foundNamespaces;
}

public static void InsertNamespacesIntoElement(Hashtable namespacesHash, XmlElement node)
{
    XPathNavigator nav = node.CreateNavigator();
    if (String.IsNullOrEmpty(nav.Prefix) && String.IsNullOrEmpty(nav.GetAttribute("xmlns","")))
    {
        nav.CreateAttribute("", "xmlns","",nav.NamespaceURI);
    }
    foreach (DictionaryEntry namespacePair in namespacesHash)
    {
        string[] attrName = ((string)namespacePair.Key).Split(':');
        if (attrName.Length > 1 && !node.HasAttribute(attrName[0]+":"+attrName[1]))
        {
             nav.CreateAttribute(attrName[0], attrName[1], "", (string)namespacePair.Value);
        }
    }
}

7. Canonicalize the signedInfo:

Stream signedInfoStream = canonicalizeNode(signedInfo);

where:

public static Stream canonicalizeNode(XmlNode node)
{
    XmlNodeReader reader = new XmlNodeReader(node);
    Stream stream = new MemoryStream();

    XmlWriter writer = new XmlTextWriter(stream, Encoding.UTF8);

    writer.WriteNode(reader, false);
    writer.Flush();

    stream.Position = 0;

    //To ensure that the XML is properly formatted we use this transform on it
    // before creating the hash of the SignedInfo block.
    XmlDsigC14NTransform transform = new XmlDsigC14NTransform();
    transform.LoadInput(stream);
    return (Stream)transform.GetOutput();
}

8. The next step is to compute the hash of the canonicalized signedInfo:

SHA1 sha1 = SHA1.Create();
byte[] hashedSignedInfo = sha1.ComputeHash(signedInfoStream);

9. The last step of the validation of the message signature is to verify the hash using a crypto service provider via the sender’s public key:

string oid = CryptoConfig.MapNameToOID("SHA1");
RSACryptoServiceProvider crypto = (RSACryptoServiceProvider)cert.PublicKey.Key;
bool isMessageSignatureValid = crypto.VerifyHash(hashedSignedInfo, oid, sigVal);

10. OK, if we got so far it means that nobody tempered with the SignedInfo node. Now we have to validate if no one tempered with content of signed elements by inspecting references and hashes in the SignedInfo. That’s the place where the SHA256 algorithm is used. First let’s load the message references from the SingedInfo node:

XmlNamespaceManager man = new XmlNamespaceManager(xDoc.NameTable);
man.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
man.AddNamespace("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
man.AddNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");

// A bit of xpath to only get the reference nodes in the security header.
XmlNodeList messageReferences = xDoc.SelectNodes("//soap:Header/wsse:Security/ds:Signature/ds:SignedInfo/ds:Reference", man);

11. For each of the references we shall perform validation (steps 12-17). First we will look up the reference listed in SignedInfo and retrieve the correspodning node from the xDoc.

XPathNavigator elementNav = xEle.CreateNavigator();
string elementID = elementNav.GetAttribute("URI", "");
//We need to remove the hash. :)
if (elementID.StartsWith("#"))
{
    elementID = elementID.Substring(1);
}

12. Now we find the node associated with the id.

XmlElement referencedNode = retrieveElementByAttribute(xDoc, "wsu" + ":Id", elementID);

where:

public static XmlElement retrieveElementByAttribute(XmlNode xDoc, string attributeName, string attributeValue)
{
    ParameterValidation.Validate("xDoc", xDoc);
    ParameterValidation.Validate("attributeName", attributeName);
    ParameterValidation.Validate("attributeValue", attributeValue);

    XmlElement foundElement = null;
    foreach (XmlNode node in xDoc)
    {
        if (node.HasChildNodes)
        {
            foundElement = retrieveElementByAttribute(node, attributeName, attributeValue);
        }
        if (foundElement == null && node.Attributes != null && node.Attributes[attributeName] != null && node.Attributes[attributeName].Value.Equals(attributeValue))
        {
            foundElement = (XmlElement)node;
            break;
        }
        if (foundElement != null)
        {
            break;
        }
    }
    return foundElement;
}

13. Then we will incorporate the namespaces from the parent node of the retrieved node

InsertNamespacesIntoElement(RetrieveNameSpaces((XmlElement)referencedNode.ParentNode), referencedNode);

14. Now we will canonicalize the node with the specified canonicalization method.

Stream canonicalizedNodeStream = canonicalizeNode(referencedNode);

15. Create the proper hash algorithm object and compute the hash of the signed node:

elementNav.MoveToFollowing("DigestMethod", "http://www.w3.org/2000/09/xmldsig#");
HashAlgorithm hashAlg = (HashAlgorithm)CryptoConfig.CreateFromName(elementNav.GetAttribute("Algorithm", ""));
byte[] hashedNode = hashAlg.ComputeHash(canonicalizedNodeStream);

16. Load the digest value and decode its value using base64 encoding:

elementNav.MoveToFollowing("DigestValue", "http://www.w3.org/2000/09/xmldsig#");
byte [] digestValue = Convert.FromBase64String(elementNav.InnerXml)

17. If the hashedNode array and the digestValue array are equal then the verification of the reference from the SignedInfo is positive! After repeating this for all the references the verification of the digital signatures of XML documents, without using WSE3 is done.

Josh: It all seems so easy now. I think the hardest part of this entire process is never really knowing if you are on the right path until you get it completely right. Hopefully this tutorial will help someone else avoid the pain and suffering that we had to endure.

Some other useful links:
Apache XML Security
An Introduction to XML Digital Signatures
Bouncy Castle

PS. REST rulez!

Popularity: 62% [?]

Comments (2)

Hibernate Shards

There are situations when you can’t put all data which you need in a single instance of a relational database. The reasons may differ. Maybe because it is too much of the data itself. Or there is a problem with network latency of a distributed architecture. Scaling? Or one of many other reasons. The answer is: horizontal partitioning. The process of splitting up your data sets that once has been called partitioning, now, it has a new name: sharding. If your data doesn’t fit on one machine you split it up into segments and each segment is called a shard. It is term used initially at Google but now spreading everywhere.

So… There is a new project Hibernate Shards which is a framework that is designed to encapsulate and minimize complexity of accessing multiple databases by adding support for horizontal partitioning on top of Hibernate Core. It was once the 20 percent project at Google but it is open-sourced now and licensed under the LGPL. If you know the Core Hibernate API you know the Shards API as its implementation hasn’t violated the Core API. Basic assumptions and paradigms for using Hibernate are still valid as Configuration, SessionFactory, and Session objects are almost exactly the same. Interfaces from Hibernate Core:

  • org.hibernate.Session
  • org.hibernate.SessionFactory
  • org.hibernate.Criteria
  • org.hibernate.Query

have shard-aware extensions:

  • org.hibernate.shards.session.ShardedSession
  • org.hibernate.shards.ShardedSessionFactory
  • org.hibernate.shards.criteria.ShardedCriteria
  • org.hibernate.shards.query.ShardedQuery

The implementations for these four interfaces serve as a sharding engine that knows how to apply an application-specific sharding logic. This logic is a set of rules how data is distributed across its shards. To specify this logic we have to implement the interfaces below:

  • org.hibernate.shards.strategy.selection.ShardSelectionStrategy
  • org.hibernate.shards.strategy.resolution.ShardResolutionStrategy
  • org.hibernate.shards.strategy.access.ShardAccessStrategy

Hibernate Shards comes with a couple of simple implementations of these interfaces. For instance for the Shard Selection Strategy we have choice of sequential (load balanced round robin) or parallel access.

To finish the topic of the sharding logic I shall mention the id generation as well. As the standard database sequences can’t be used in distributed environment we have a choice of two primary key generators:

  • ShardedUUIDGenerator - that generates a big random number
  • ShardedTableHiLoGenerator - that uses a table in one of the shards to generate the primary key. Obviously it is a single point of failure for our system.

Although project is still in its early stage and even the creators warn about possible glitches this nice wrapper for hiding all the complexity of distributing data around multiple relational databases is very much worth looking at, especially if the Hibernate is already used as the ORM tool of choice.

Popularity: 50% [?]

Comments

To test or not to test

Cruise Control LightsI believe in testing, I really do. Combined with continuous integration, daily builds and automation of all aspects of build process, those are for me mandatory elements of a software project which has got any aspiration to be a successful one. Joel thinks there are more.

I believe in unit tests as well as integration and acceptance tests. I can see value of that and I use TDD happily for last two years and unit testing without being so strict about that for much longer time. It just works for me, gives me something.

However I still have questions regarding this subject. Let’s just put up first of them:

Should we or shouldn’t we unit test private methods of a class?

There are valid reasons for both of them. From one hand if we limit ourselves to a public interface and we test our class as a black box which behaves in a certain way and we don’t care how it is implemented then the tests are easier (read cheaper) to maintain. Whenever we have to change implementation we don’t have to change tests. Neat.

But there is other side as well. What about this word unit? What about TDD? If TDD can actively help us with process of developing a single unit of code why not to use that? As we all know the first red - last green routine of writing test, making it fail, developing code, making the test pass might be painful, might take long time to switch to that way of development but and the end of the day gives code of the better quality. But now what shall we do if that single unit of code by design is a private method? Shall we change that following philosophy of design for testability? It again might lead to innocent changes like converting (Java):

private void foo() {
...
}

to:

protected void foo() {
...
}

Then we can create unit tests for that method in the same package. It was really innocent. What if we have to reach to a toolbox with dirty tools? We can’t really use the same solution for C#. Let’s first have a look at the method access modifiers for that language:

  • public indicates the method is freely accessible inside and outside of the class in which it is defined
  • internal means the method is only accessible to types defined in the same assembly
  • protected means the method is accessible in the type in which it is defined, and in derived types of that type. This is used to give derived classes access to the methods in their base class
  • protected internal means the method is accessible to types defined in the same assembly or to types in a derived assembly
  • private methods are only accessible in the class in which they are defined.

As we can see our dear friends from Microsoft have done it in even more problematic way. We have a choice of converting private methods to internal but our tests have to be placed in the same assembly as the production code or we can use the public modifier or we have to use some tricks with reflection. Not perfect, wrong or smells.

I understand that there is no universal answer for the question above. Applying common sense usually pays off but I wonder what is your opinion about testing in general with focus on testing private methods.

Popularity: 27% [?]

Comments (3)

Flickrfs - because the Flickr Uploader sux

FlickrI can recall a conversation with psd from early this year about why I think current way of uploading photos to flickr sux big time. I treat flickr as repository and backup of _all_ my photos (12525 photos at the moment, still growing) and not just as a photo blog. It means that very often I have to upload quite a lot of them in batches. The existing solutions just make me angry (how shabby is the standard Flickr Uploadr!) when I have to tag them and correctly name or create sets. I am not (yet) a mac user. Maybe there is something more user friendly, I hope.

So… Coming back to the conversation with psd I have told him that unless there is some clever integration with OS which will make the process of uploading more smooth it will be always the pain. I expected as well a bit more metadata to be populated by camera automatically. How cool would be to have GPS and geo-tag all the photos when taking them. That’s not the end. I would expect as well to be able to define some tags in a camera.

That would solve a bit problem with tags. The other problems are setting permissions, creating sets etc. For pretty long time I couldn’t find any tool which I liked. Lately after migrating all my home computers to Gutsy I found something called Flickrfs as an available package. It is a virtual filesystem which mounts a flickr account as any other data file storage. It synchronizes the flickr account with local filesystem and shows photos as images files with all metadata represented as text files.

Imagine that. You can upload photos to flickr just by using cp command, the same applies to downloading photos (even if Flickr itself makes it as hard as possible to get back of your own photos). Deleting is as easy as invoking rm. You can set permissions using standard chmod command and define sets by creating symlinks with ln.

I like the idea itself very much. The Flickrfs is created and maintained mainly by one person so there might be some small “bugletes” but I still support this project and wish it the best. Well done Manish Rai Jain!

Popularity: 28% [?]

Comments

Eclipse 3.3 leaks permgen space

EclipseSome of you who use Eclipse 3.3 with Sun JVM might notice that it crashes from time to time. Those who have many plugins certainly experienced this more often. Problem and solution for this bug is very trivial but worth mentioning: leaking permgen space. Comes back like November flu! Just to remind the permgen space is a memory for storing “data needed by the virtual machine to describe objects that do not have an equivalence at the Java language level. For example objects describing classes and methods are stored in the permanent generation“. More information about permgen can be found in an article about tuning garbage collection.

To fix the problem edit your eclipse.ini and add following lines:

-XX:PermSize=128M
-XX:MaxPermSize=256M

You might also try Eclipse 3.3.1.1 which includes a fix for the above problem.

Enjoy!

Popularity: 48% [?]

Comments (1)

Close
E-mail It